1: /*
   2:  * Copyright (c) 1985, 1989 Regents of the University of California.
   3:  * All rights reserved.
   4:  *
   5:  * Redistribution and use in source and binary forms are permitted
   6:  * provided that the above copyright notice and this paragraph are
   7:  * duplicated in all such forms and that any documentation,
   8:  * advertising materials, and other materials related to such
   9:  * distribution and use acknowledge that the software was developed
  10:  * by the University of California, Berkeley.  The name of the
  11:  * University may not be used to endorse or promote products derived
  12:  * from this software without specific prior written permission.
  13:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16:  */
  17: 
  18: #if !defined(lint) && defined(DOSCCS)
  19: static char sccsid[] = "@(#)cmds.c	5.18.1 (2.11BSD) 1997/10/2";
  20: #endif
  21: 
  22: /*
  23:  * FTP User Program -- Command Routines.
  24:  */
  25: #include <sys/param.h>
  26: #include <sys/wait.h>
  27: #include <sys/stat.h>
  28: #include <sys/socket.h>
  29: 
  30: #include <arpa/ftp.h>
  31: 
  32: #include <signal.h>
  33: #include <stdio.h>
  34: #include <errno.h>
  35: #include <netdb.h>
  36: #include <ctype.h>
  37: #include <time.h>
  38: #include <string.h>
  39: #include <stdlib.h>
  40: #include <unistd.h>
  41: #include <netinet/in.h>
  42: 
  43: #include "ftp_var.h"
  44: #include "pathnames.h"
  45: 
  46: extern  char *globerr;
  47: extern  char **glob();
  48: extern  char *home;
  49: extern  char *remglob();
  50: extern  int allbinary;
  51: extern off_t restart_point;
  52: extern char reply_string[];
  53: 
  54: char *mname;
  55: jmp_buf jabort;
  56: char *dotrans(), *domap();
  57: 
  58: /*
  59:  * Connect to peer server and
  60:  * auto-login, if possible.
  61:  */
  62: setpeer(argc, argv)
  63:     int argc;
  64:     char *argv[];
  65: {
  66:     char *host, *hookup();
  67:     int port;
  68: 
  69:     if (connected) {
  70:         printf("Already connected to %s, use close first.\n",
  71:             hostname);
  72:         code = -1;
  73:         return;
  74:     }
  75:     if (argc < 2) {
  76:         (void) strcat(line, " ");
  77:         printf("(to) ");
  78:         (void) gets(&line[strlen(line)]);
  79:         makeargv();
  80:         argc = margc;
  81:         argv = margv;
  82:     }
  83:     if (argc > 3) {
  84:         printf("usage: %s host-name [port]\n", argv[0]);
  85:         code = -1;
  86:         return;
  87:     }
  88:     port = sp->s_port;
  89:     if (argc > 2) {
  90:         port = atoi(argv[2]);
  91:         if (port <= 0) {
  92:             printf("%s: bad port number-- %s\n", argv[1], argv[2]);
  93:             printf ("usage: %s host-name [port]\n", argv[0]);
  94:             code = -1;
  95:             return;
  96:         }
  97:         port = htons(port);
  98:     }
  99:     host = hookup(argv[1], port);
 100:     if (host) {
 101:         int overbose;
 102: 
 103:         connected = 1;
 104:         if (autologin)
 105:             (void) login(argv[1]);
 106: 
 107: #if defined(unix) && NBBY == 8
 108: /*
 109:  * this ifdef is to keep someone form "porting" this to an incompatible
 110:  * system and not checking this out. This way they have to think about it.
 111:  */
 112:         overbose = verbose;
 113:         if (debug == 0)
 114:             verbose = -1;
 115:         allbinary = 0;
 116:         if (command("SYST") == COMPLETE && overbose) {
 117:             register char *cp, c;
 118:             cp = index(reply_string+4, ' ');
 119:             if (cp == NULL)
 120:                 cp = index(reply_string+4, '\r');
 121:             if (cp) {
 122:                 if (cp[-1] == '.')
 123:                     cp--;
 124:                 c = *cp;
 125:                 *cp = '\0';
 126:             }
 127: 
 128:             printf("Remote system type is %s.\n",
 129:                 reply_string+4);
 130:             if (cp)
 131:                 *cp = c;
 132:         }
 133:         if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) {
 134:             setbinary();
 135:             /* allbinary = 1; this violates the RFC */
 136:             if (overbose)
 137:                 printf("Using %s mode to transfer files.\n",
 138:                 typename);
 139:         } else if (overbose &&
 140:             !strncmp(reply_string, "215 TOPS20", 10)) {
 141:             printf(
 142: "Remember to set tenex mode when transfering binary files from this machine.\n");
 143:         }
 144:         verbose = overbose;
 145: #endif /* unix */
 146:     }
 147: }
 148: 
 149: struct  types {
 150:     char    *t_name;
 151:     char    *t_mode;
 152:     int t_type;
 153:     char    *t_arg;
 154: } types[] = {
 155:     { "ascii",  "A",    TYPE_A, 0 },
 156:     { "binary", "I",    TYPE_I, 0 },
 157:     { "image",  "I",    TYPE_I, 0 },
 158:     { "ebcdic", "E",    TYPE_E, 0 },
 159:     { "tenex",  "L",    TYPE_L, bytename },
 160:     0
 161: };
 162: 
 163: /*
 164:  * Set transfer type.
 165:  */
 166: settype(argc, argv)
 167:     char *argv[];
 168: {
 169:     register struct types *p;
 170:     int comret;
 171: 
 172:     if (argc > 2) {
 173:         char *sep;
 174: 
 175:         printf("usage: %s [", argv[0]);
 176:         sep = " ";
 177:         for (p = types; p->t_name; p++) {
 178:             printf("%s%s", sep, p->t_name);
 179:             if (*sep == ' ')
 180:                 sep = " | ";
 181:         }
 182:         printf(" ]\n");
 183:         code = -1;
 184:         return;
 185:     }
 186:     if (argc < 2) {
 187:         printf("Using %s mode to transfer files.\n", typename);
 188:         code = 0;
 189:         return;
 190:     }
 191:     for (p = types; p->t_name; p++)
 192:         if (strcmp(argv[1], p->t_name) == 0)
 193:             break;
 194:     if (p->t_name == 0) {
 195:         printf("%s: unknown mode\n", argv[1]);
 196:         code = -1;
 197:         return;
 198:     }
 199:     if ((p->t_arg != NULL) && (*(p->t_arg) != '\0'))
 200:         comret = command ("TYPE %s %s", p->t_mode, p->t_arg);
 201:     else
 202:         comret = command("TYPE %s", p->t_mode);
 203:     if (comret == COMPLETE) {
 204:         (void) strcpy(typename, p->t_name);
 205:         type = p->t_type;
 206:     }
 207: }
 208: 
 209: char *stype[] = {
 210:     "type",
 211:     "",
 212:     0
 213: };
 214: 
 215: /*
 216:  * Set binary transfer type.
 217:  */
 218: /*VARARGS*/
 219: setbinary()
 220: {
 221:     stype[1] = "binary";
 222:     settype(2, stype);
 223: }
 224: 
 225: /*
 226:  * Set ascii transfer type.
 227:  */
 228: /*VARARGS*/
 229: setascii()
 230: {
 231:     stype[1] = "ascii";
 232:     settype(2, stype);
 233: }
 234: 
 235: /*
 236:  * Set tenex transfer type.
 237:  */
 238: /*VARARGS*/
 239: settenex()
 240: {
 241:     stype[1] = "tenex";
 242:     settype(2, stype);
 243: }
 244: 
 245: /*
 246:  * Set ebcdic transfer type.
 247:  */
 248: /*VARARGS*/
 249: setebcdic()
 250: {
 251:     stype[1] = "ebcdic";
 252:     settype(2, stype);
 253: }
 254: 
 255: /*
 256:  * Set file transfer mode.
 257:  */
 258: /*ARGSUSED*/
 259: setmode(argc, argv)
 260:     char *argv[];
 261: {
 262: 
 263:     printf("We only support %s mode, sorry.\n", modename);
 264:     code = -1;
 265: }
 266: 
 267: /*
 268:  * Set file transfer format.
 269:  */
 270: /*ARGSUSED*/
 271: setform(argc, argv)
 272:     char *argv[];
 273: {
 274: 
 275:     printf("We only support %s format, sorry.\n", formname);
 276:     code = -1;
 277: }
 278: 
 279: /*
 280:  * Set file transfer structure.
 281:  */
 282: /*ARGSUSED*/
 283: setstruct(argc, argv)
 284:     char *argv[];
 285: {
 286: 
 287:     printf("We only support %s structure, sorry.\n", structname);
 288:     code = -1;
 289: }
 290: 
 291: /*
 292:  * Send a single file.
 293:  */
 294: put(argc, argv)
 295:     int argc;
 296:     char *argv[];
 297: {
 298:     char *cmd;
 299:     int loc = 0;
 300:     char *oldargv1, *oldargv2;
 301: 
 302:     if (argc == 2) {
 303:         argc++;
 304:         argv[2] = argv[1];
 305:         loc++;
 306:     }
 307:     if (argc < 2) {
 308:         (void) strcat(line, " ");
 309:         printf("(local-file) ");
 310:         (void) gets(&line[strlen(line)]);
 311:         makeargv();
 312:         argc = margc;
 313:         argv = margv;
 314:     }
 315:     if (argc < 2) {
 316: usage:
 317:         printf("usage:%s local-file remote-file\n", argv[0]);
 318:         code = -1;
 319:         return;
 320:     }
 321:     if (argc < 3) {
 322:         (void) strcat(line, " ");
 323:         printf("(remote-file) ");
 324:         (void) gets(&line[strlen(line)]);
 325:         makeargv();
 326:         argc = margc;
 327:         argv = margv;
 328:     }
 329:     if (argc < 3)
 330:         goto usage;
 331:     oldargv1 = argv[1];
 332:     oldargv2 = argv[2];
 333:     if (!globulize(&argv[1])) {
 334:         code = -1;
 335:         return;
 336:     }
 337:     /*
 338: 	 * If "globulize" modifies argv[1], and argv[2] is a copy of
 339: 	 * the old argv[1], make it a copy of the new argv[1].
 340: 	 */
 341:     if (argv[1] != oldargv1 && argv[2] == oldargv1) {
 342:         argv[2] = argv[1];
 343:     }
 344:     cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR");
 345:     if (loc && ntflag) {
 346:         argv[2] = dotrans(argv[2]);
 347:     }
 348:     if (loc && mapflag) {
 349:         argv[2] = domap(argv[2]);
 350:     }
 351:     sendrequest(cmd, argv[1], argv[2],
 352:         argv[1] != oldargv1 || argv[2] != oldargv2);
 353: }
 354: 
 355: /*
 356:  * Send multiple files.
 357:  */
 358: mput(argc, argv)
 359:     char *argv[];
 360: {
 361:     register int i;
 362:     int ointer, (*oldintr)(), mabort();
 363:     extern jmp_buf jabort;
 364:     char *tp;
 365: 
 366:     if (argc < 2) {
 367:         (void) strcat(line, " ");
 368:         printf("(local-files) ");
 369:         (void) gets(&line[strlen(line)]);
 370:         makeargv();
 371:         argc = margc;
 372:         argv = margv;
 373:     }
 374:     if (argc < 2) {
 375:         printf("usage:%s local-files\n", argv[0]);
 376:         code = -1;
 377:         return;
 378:     }
 379:     mname = argv[0];
 380:     mflag = 1;
 381:     oldintr = signal(SIGINT, mabort);
 382:     (void) setjmp(jabort);
 383:     if (proxy) {
 384:         char *cp, *tp2, tmpbuf[MAXPATHLEN];
 385: 
 386:         while ((cp = remglob(argv,0)) != NULL) {
 387:             if (*cp == 0) {
 388:                 mflag = 0;
 389:                 continue;
 390:             }
 391:             if (mflag && confirm(argv[0], cp)) {
 392:                 tp = cp;
 393:                 if (mcase) {
 394:                     while (*tp && !islower(*tp)) {
 395:                         tp++;
 396:                     }
 397:                     if (!*tp) {
 398:                         tp = cp;
 399:                         tp2 = tmpbuf;
 400:                         while ((*tp2 = *tp) != NULL) {
 401:                              if (isupper(*tp2)) {
 402:                                 *tp2 = 'a' + *tp2 - 'A';
 403:                              }
 404:                              tp++;
 405:                              tp2++;
 406:                         }
 407:                     }
 408:                     tp = tmpbuf;
 409:                 }
 410:                 if (ntflag) {
 411:                     tp = dotrans(tp);
 412:                 }
 413:                 if (mapflag) {
 414:                     tp = domap(tp);
 415:                 }
 416:                 sendrequest((sunique) ? "STOU" : "STOR",
 417:                     cp, tp, cp != tp || !interactive);
 418:                 if (!mflag && fromatty) {
 419:                     ointer = interactive;
 420:                     interactive = 1;
 421:                     if (confirm("Continue with","mput")) {
 422:                         mflag++;
 423:                     }
 424:                     interactive = ointer;
 425:                 }
 426:             }
 427:         }
 428:         (void) signal(SIGINT, oldintr);
 429:         mflag = 0;
 430:         return;
 431:     }
 432:     for (i = 1; i < argc; i++) {
 433:         register char **cpp, **gargs;
 434: 
 435:         if (!doglob) {
 436:             if (mflag && confirm(argv[0], argv[i])) {
 437:                 tp = (ntflag) ? dotrans(argv[i]) : argv[i];
 438:                 tp = (mapflag) ? domap(tp) : tp;
 439:                 sendrequest((sunique) ? "STOU" : "STOR",
 440:                     argv[i], tp, tp != argv[i] || !interactive);
 441:                 if (!mflag && fromatty) {
 442:                     ointer = interactive;
 443:                     interactive = 1;
 444:                     if (confirm("Continue with","mput")) {
 445:                         mflag++;
 446:                     }
 447:                     interactive = ointer;
 448:                 }
 449:             }
 450:             continue;
 451:         }
 452:         gargs = glob(argv[i]);
 453:         if (globerr != NULL) {
 454:             printf("%s\n", globerr);
 455:             if (gargs) {
 456:                 blkfree(gargs);
 457:                 free(gargs);
 458:             }
 459:             continue;
 460:         }
 461:         for (cpp = gargs; cpp && *cpp != NULL; cpp++) {
 462:             if (mflag && confirm(argv[0], *cpp)) {
 463:                 tp = (ntflag) ? dotrans(*cpp) : *cpp;
 464:                 tp = (mapflag) ? domap(tp) : tp;
 465:                 sendrequest((sunique) ? "STOU" : "STOR",
 466:                     *cpp, tp, *cpp != tp || !interactive);
 467:                 if (!mflag && fromatty) {
 468:                     ointer = interactive;
 469:                     interactive = 1;
 470:                     if (confirm("Continue with","mput")) {
 471:                         mflag++;
 472:                     }
 473:                     interactive = ointer;
 474:                 }
 475:             }
 476:         }
 477:         if (gargs != NULL) {
 478:             blkfree(gargs);
 479:             free(gargs);
 480:         }
 481:     }
 482:     (void) signal(SIGINT, oldintr);
 483:     mflag = 0;
 484: }
 485: 
 486: reget(argc, argv)
 487:     char *argv[];
 488: {
 489:     (void) getit(argc, argv, 1, "r+w");
 490: }
 491: 
 492: get(argc, argv)
 493:     char *argv[];
 494: {
 495:     (void) getit(argc, argv, 0, restart_point ? "r+w" : "w" );
 496: }
 497: 
 498: /*
 499:  * Receive one file.
 500:  */
 501: getit(argc, argv, restartit, mode)
 502:     char *argv[];
 503:     char *mode;
 504: {
 505:     int loc = 0;
 506:     char *oldargv1, *oldargv2;
 507: 
 508:     if (argc == 2) {
 509:         argc++;
 510:         argv[2] = argv[1];
 511:         loc++;
 512:     }
 513:     if (argc < 2) {
 514:         (void) strcat(line, " ");
 515:         printf("(remote-file) ");
 516:         (void) gets(&line[strlen(line)]);
 517:         makeargv();
 518:         argc = margc;
 519:         argv = margv;
 520:     }
 521:     if (argc < 2) {
 522: usage:
 523:         printf("usage: %s remote-file [ local-file ]\n", argv[0]);
 524:         code = -1;
 525:         return (0);
 526:     }
 527:     if (argc < 3) {
 528:         (void) strcat(line, " ");
 529:         printf("(local-file) ");
 530:         (void) gets(&line[strlen(line)]);
 531:         makeargv();
 532:         argc = margc;
 533:         argv = margv;
 534:     }
 535:     if (argc < 3)
 536:         goto usage;
 537:     oldargv1 = argv[1];
 538:     oldargv2 = argv[2];
 539:     if (!globulize(&argv[2])) {
 540:         code = -1;
 541:         return (0);
 542:     }
 543:     if (loc && mcase) {
 544:         char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN];
 545: 
 546:         while (*tp && !islower(*tp)) {
 547:             tp++;
 548:         }
 549:         if (!*tp) {
 550:             tp = argv[2];
 551:             tp2 = tmpbuf;
 552:             while ((*tp2 = *tp) != NULL) {
 553:                 if (isupper(*tp2)) {
 554:                     *tp2 = 'a' + *tp2 - 'A';
 555:                 }
 556:                 tp++;
 557:                 tp2++;
 558:             }
 559:             argv[2] = tmpbuf;
 560:         }
 561:     }
 562:     if (loc && ntflag)
 563:         argv[2] = dotrans(argv[2]);
 564:     if (loc && mapflag)
 565:         argv[2] = domap(argv[2]);
 566:     if (restartit) {
 567:         struct stat stbuf;
 568:         int ret;
 569: 
 570:         ret = stat(argv[2], &stbuf);
 571:         if (restartit == 1) {
 572:             if (ret < 0) {
 573:                 perror(argv[2]);
 574:                 return (0);
 575:             }
 576:             restart_point = stbuf.st_size;
 577:         } else {
 578:             if (ret == 0) {
 579:                 int overbose;
 580: 
 581:                 overbose = verbose;
 582:                 if (debug == 0)
 583:                     verbose = -1;
 584:                 if (command("MDTM %s", argv[1]) == COMPLETE) {
 585:                     int yy, mo, day, hour, min, sec;
 586:                     struct tm *tm;
 587:                     verbose = overbose;
 588:                     sscanf(reply_string,
 589:                         "%*s %04d%02d%02d%02d%02d%02d",
 590:                         &yy, &mo, &day, &hour, &min, &sec);
 591:                     tm = gmtime(&stbuf.st_mtime);
 592:                     tm->tm_mon++;
 593:                     if (tm->tm_year > yy%100)
 594:                         return (1);
 595:                     else if (tm->tm_year == yy%100) {
 596:                         if (tm->tm_mon > mo)
 597:                             return (1);
 598:                     } else if (tm->tm_mon == mo) {
 599:                         if (tm->tm_mday > day)
 600:                             return (1);
 601:                     } else if (tm->tm_mday == day) {
 602:                         if (tm->tm_hour > hour)
 603:                             return (1);
 604:                     } else if (tm->tm_hour == hour) {
 605:                         if (tm->tm_min > min)
 606:                             return (1);
 607:                     } else if (tm->tm_min == min) {
 608:                         if (tm->tm_sec > sec)
 609:                             return (1);
 610:                     }
 611:                 } else {
 612:                     fputs(reply_string, stdout);
 613:                     verbose = overbose;
 614:                     return (0);
 615:                 }
 616:             }
 617:         }
 618:     }
 619: 
 620:     recvrequest("RETR", argv[2], argv[1], mode,
 621:         argv[1] != oldargv1 || argv[2] != oldargv2);
 622:     restart_point = 0;
 623:     return (0);
 624: }
 625: 
 626: mabort()
 627: {
 628:     int ointer;
 629:     extern jmp_buf jabort;
 630: 
 631:     printf("\n");
 632:     (void) fflush(stdout);
 633:     if (mflag && fromatty) {
 634:         ointer = interactive;
 635:         interactive = 1;
 636:         if (confirm("Continue with", mname)) {
 637:             interactive = ointer;
 638:             longjmp(jabort,0);
 639:         }
 640:         interactive = ointer;
 641:     }
 642:     mflag = 0;
 643:     longjmp(jabort,0);
 644: }
 645: 
 646: /*
 647:  * Get multiple files.
 648:  */
 649: mget(argc, argv)
 650:     char *argv[];
 651: {
 652:     char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN];
 653:     int ointer, (*oldintr)(), mabort();
 654:     extern jmp_buf jabort;
 655: 
 656:     if (argc < 2) {
 657:         (void) strcat(line, " ");
 658:         printf("(remote-files) ");
 659:         (void) gets(&line[strlen(line)]);
 660:         makeargv();
 661:         argc = margc;
 662:         argv = margv;
 663:     }
 664:     if (argc < 2) {
 665:         printf("usage:%s remote-files\n", argv[0]);
 666:         code = -1;
 667:         return;
 668:     }
 669:     mname = argv[0];
 670:     mflag = 1;
 671:     oldintr = signal(SIGINT,mabort);
 672:     (void) setjmp(jabort);
 673:     while ((cp = remglob(argv,proxy)) != NULL) {
 674:         if (*cp == '\0') {
 675:             mflag = 0;
 676:             continue;
 677:         }
 678:         if (mflag && confirm(argv[0], cp)) {
 679:             tp = cp;
 680:             if (mcase) {
 681:                 while (*tp && !islower(*tp)) {
 682:                     tp++;
 683:                 }
 684:                 if (!*tp) {
 685:                     tp = cp;
 686:                     tp2 = tmpbuf;
 687:                     while ((*tp2 = *tp) != NULL) {
 688:                         if (isupper(*tp2)) {
 689:                             *tp2 = 'a' + *tp2 - 'A';
 690:                         }
 691:                         tp++;
 692:                         tp2++;
 693:                     }
 694:                 }
 695:                 tp = tmpbuf;
 696:             }
 697:             if (ntflag) {
 698:                 tp = dotrans(tp);
 699:             }
 700:             if (mapflag) {
 701:                 tp = domap(tp);
 702:             }
 703:             recvrequest("RETR", tp, cp, "w",
 704:                 tp != cp || !interactive);
 705:             if (!mflag && fromatty) {
 706:                 ointer = interactive;
 707:                 interactive = 1;
 708:                 if (confirm("Continue with","mget")) {
 709:                     mflag++;
 710:                 }
 711:                 interactive = ointer;
 712:             }
 713:         }
 714:     }
 715:     (void) signal(SIGINT,oldintr);
 716:     mflag = 0;
 717: }
 718: 
 719: char *
 720: remglob(argv,doswitch)
 721:     char *argv[];
 722:     int doswitch;
 723: {
 724:     char temp[16];
 725:     static char buf[MAXPATHLEN];
 726:     static FILE *ftemp = NULL;
 727:     static char **args;
 728:     int oldverbose, oldhash;
 729:     char *cp, *mode;
 730: 
 731:     if (!mflag) {
 732:         if (!doglob) {
 733:             args = NULL;
 734:         }
 735:         else {
 736:             if (ftemp) {
 737:                 (void) fclose(ftemp);
 738:                 ftemp = NULL;
 739:             }
 740:         }
 741:         return(NULL);
 742:     }
 743:     if (!doglob) {
 744:         if (args == NULL)
 745:             args = argv;
 746:         if ((cp = *++args) == NULL)
 747:             args = NULL;
 748:         return (cp);
 749:     }
 750:     if (ftemp == NULL) {
 751:         (void) strcpy(temp, _PATH_TMP);
 752:         (void) mktemp(temp);
 753:         oldverbose = verbose, verbose = 0;
 754:         oldhash = hash, hash = 0;
 755:         if (doswitch) {
 756:             pswitch(!proxy);
 757:         }
 758:         for (mode = "w"; *++argv != NULL; mode = "a")
 759:             recvrequest ("NLST", temp, *argv, mode, 0);
 760:         if (doswitch) {
 761:             pswitch(!proxy);
 762:         }
 763:         verbose = oldverbose; hash = oldhash;
 764:         ftemp = fopen(temp, "r");
 765:         (void) unlink(temp);
 766:         if (ftemp == NULL) {
 767:             printf("can't find list of remote files, oops\n");
 768:             return (NULL);
 769:         }
 770:     }
 771:     if (fgets(buf, sizeof (buf), ftemp) == NULL) {
 772:         (void) fclose(ftemp), ftemp = NULL;
 773:         return (NULL);
 774:     }
 775:     if ((cp = index(buf, '\n')) != NULL)
 776:         *cp = '\0';
 777:     return (buf);
 778: }
 779: 
 780: char *
 781: onoff(bool)
 782:     int bool;
 783: {
 784: 
 785:     return (bool ? "on" : "off");
 786: }
 787: 
 788: /*
 789:  * Show status.
 790:  */
 791: /*ARGSUSED*/
 792: status(argc, argv)
 793:     char *argv[];
 794: {
 795:     int i;
 796: 
 797:     if (connected)
 798:         printf("Connected to %s.\n", hostname);
 799:     else
 800:         printf("Not connected.\n");
 801:     if (!proxy) {
 802:         pswitch(1);
 803:         if (connected) {
 804:             printf("Connected for proxy commands to %s.\n", hostname);
 805:         }
 806:         else {
 807:             printf("No proxy connection.\n");
 808:         }
 809:         pswitch(0);
 810:     }
 811:     printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n",
 812:         modename, typename, formname, structname);
 813:     printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n",
 814:         onoff(verbose), onoff(bell), onoff(interactive),
 815:         onoff(doglob));
 816:     printf("Store unique: %s; Receive unique: %s\n", onoff(sunique),
 817:         onoff(runique));
 818:     printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag));
 819:     if (ntflag) {
 820:         printf("Ntrans: (in) %s (out) %s\n", ntin,ntout);
 821:     }
 822:     else {
 823:         printf("Ntrans: off\n");
 824:     }
 825:     if (mapflag) {
 826:         printf("Nmap: (in) %s (out) %s\n", mapin, mapout);
 827:     }
 828:     else {
 829:         printf("Nmap: off\n");
 830:     }
 831:     printf("Hash mark printing: %s; Use of PORT cmds: %s\n",
 832:         onoff(hash), onoff(sendport));
 833:     if (macnum > 0) {
 834:         printf("Macros:\n");
 835:         for (i=0; i<macnum; i++) {
 836:             printf("\t%s\n",macros[i].mac_name);
 837:         }
 838:     }
 839:     code = 0;
 840: }
 841: 
 842: /*
 843:  * Set beep on cmd completed mode.
 844:  */
 845: /*VARARGS*/
 846: setbell()
 847: {
 848: 
 849:     bell = !bell;
 850:     printf("Bell mode %s.\n", onoff(bell));
 851:     code = bell;
 852: }
 853: 
 854: /*
 855:  * Turn on packet tracing.
 856:  */
 857: /*VARARGS*/
 858: settrace()
 859: {
 860: 
 861:     trace = !trace;
 862:     printf("Packet tracing %s.\n", onoff(trace));
 863:     code = trace;
 864: }
 865: 
 866: /*
 867:  * Toggle hash mark printing during transfers.
 868:  */
 869: /*VARARGS*/
 870: sethash()
 871: {
 872: 
 873:     hash = !hash;
 874:     printf("Hash mark printing %s", onoff(hash));
 875:     code = hash;
 876:     if (hash)
 877:         printf(" (%d bytes/hash mark)", 1024);
 878:     printf(".\n");
 879: }
 880: 
 881: /*
 882:  * Turn on printing of server echo's.
 883:  */
 884: /*VARARGS*/
 885: setverbose()
 886: {
 887: 
 888:     verbose = !verbose;
 889:     printf("Verbose mode %s.\n", onoff(verbose));
 890:     code = verbose;
 891: }
 892: 
 893: /*
 894:  * Toggle PORT cmd use before each data connection.
 895:  */
 896: /*VARARGS*/
 897: setport()
 898: {
 899: 
 900:     sendport = !sendport;
 901:     printf("Use of PORT cmds %s.\n", onoff(sendport));
 902:     code = sendport;
 903: }
 904: 
 905: /*
 906:  * Turn on interactive prompting
 907:  * during mget, mput, and mdelete.
 908:  */
 909: /*VARARGS*/
 910: setprompt()
 911: {
 912: 
 913:     interactive = !interactive;
 914:     printf("Interactive mode %s.\n", onoff(interactive));
 915:     code = interactive;
 916: }
 917: 
 918: /*
 919:  * Toggle metacharacter interpretation
 920:  * on local file names.
 921:  */
 922: /*VARARGS*/
 923: setglob()
 924: {
 925: 
 926:     doglob = !doglob;
 927:     printf("Globbing %s.\n", onoff(doglob));
 928:     code = doglob;
 929: }
 930: 
 931: /*
 932:  * Set debugging mode on/off and/or
 933:  * set level of debugging.
 934:  */
 935: /*VARARGS*/
 936: setdebug(argc, argv)
 937:     char *argv[];
 938: {
 939:     int val;
 940: 
 941:     if (argc > 1) {
 942:         val = atoi(argv[1]);
 943:         if (val < 0) {
 944:             printf("%s: bad debugging value.\n", argv[1]);
 945:             code = -1;
 946:             return;
 947:         }
 948:     } else
 949:         val = !debug;
 950:     debug = val;
 951:     if (debug)
 952:         options |= SO_DEBUG;
 953:     else
 954:         options &= ~SO_DEBUG;
 955:     printf("Debugging %s (debug=%d).\n", onoff(debug), debug);
 956:     code = debug > 0;
 957: }
 958: 
 959: /*
 960:  * Set current working directory
 961:  * on remote machine.
 962:  */
 963: cd(argc, argv)
 964:     char *argv[];
 965: {
 966: 
 967:     if (argc < 2) {
 968:         (void) strcat(line, " ");
 969:         printf("(remote-directory) ");
 970:         (void) gets(&line[strlen(line)]);
 971:         makeargv();
 972:         argc = margc;
 973:         argv = margv;
 974:     }
 975:     if (argc < 2) {
 976:         printf("usage:%s remote-directory\n", argv[0]);
 977:         code = -1;
 978:         return;
 979:     }
 980:     if (command("CWD %s", argv[1]) == ERROR && code == 500) {
 981:         if (verbose)
 982:             printf("CWD command not recognized, trying XCWD\n");
 983:         (void) command("XCWD %s", argv[1]);
 984:     }
 985: }
 986: 
 987: /*
 988:  * Set current working directory
 989:  * on local machine.
 990:  */
 991: lcd(argc, argv)
 992:     char *argv[];
 993: {
 994:     char buf[MAXPATHLEN];
 995: 
 996:     if (argc < 2)
 997:         argc++, argv[1] = home;
 998:     if (argc != 2) {
 999:         printf("usage:%s local-directory\n", argv[0]);
1000:         code = -1;
1001:         return;
1002:     }
1003:     if (!globulize(&argv[1])) {
1004:         code = -1;
1005:         return;
1006:     }
1007:     if (chdir(argv[1]) < 0) {
1008:         perror(argv[1]);
1009:         code = -1;
1010:         return;
1011:     }
1012:     printf("Local directory now %s\n", getwd(buf));
1013:     code = 0;
1014: }
1015: 
1016: /*
1017:  * Delete a single file.
1018:  */
1019: delete(argc, argv)
1020:     char *argv[];
1021: {
1022: 
1023:     if (argc < 2) {
1024:         (void) strcat(line, " ");
1025:         printf("(remote-file) ");
1026:         (void) gets(&line[strlen(line)]);
1027:         makeargv();
1028:         argc = margc;
1029:         argv = margv;
1030:     }
1031:     if (argc < 2) {
1032:         printf("usage:%s remote-file\n", argv[0]);
1033:         code = -1;
1034:         return;
1035:     }
1036:     (void) command("DELE %s", argv[1]);
1037: }
1038: 
1039: /*
1040:  * Delete multiple files.
1041:  */
1042: mdelete(argc, argv)
1043:     char *argv[];
1044: {
1045:     char *cp;
1046:     int ointer, (*oldintr)(), mabort();
1047:     extern jmp_buf jabort;
1048: 
1049:     if (argc < 2) {
1050:         (void) strcat(line, " ");
1051:         printf("(remote-files) ");
1052:         (void) gets(&line[strlen(line)]);
1053:         makeargv();
1054:         argc = margc;
1055:         argv = margv;
1056:     }
1057:     if (argc < 2) {
1058:         printf("usage:%s remote-files\n", argv[0]);
1059:         code = -1;
1060:         return;
1061:     }
1062:     mname = argv[0];
1063:     mflag = 1;
1064:     oldintr = signal(SIGINT, mabort);
1065:     (void) setjmp(jabort);
1066:     while ((cp = remglob(argv,0)) != NULL) {
1067:         if (*cp == '\0') {
1068:             mflag = 0;
1069:             continue;
1070:         }
1071:         if (mflag && confirm(argv[0], cp)) {
1072:             (void) command("DELE %s", cp);
1073:             if (!mflag && fromatty) {
1074:                 ointer = interactive;
1075:                 interactive = 1;
1076:                 if (confirm("Continue with", "mdelete")) {
1077:                     mflag++;
1078:                 }
1079:                 interactive = ointer;
1080:             }
1081:         }
1082:     }
1083:     (void) signal(SIGINT, oldintr);
1084:     mflag = 0;
1085: }
1086: 
1087: /*
1088:  * Rename a remote file.
1089:  */
1090: renamefile(argc, argv)
1091:     char *argv[];
1092: {
1093: 
1094:     if (argc < 2) {
1095:         (void) strcat(line, " ");
1096:         printf("(from-name) ");
1097:         (void) gets(&line[strlen(line)]);
1098:         makeargv();
1099:         argc = margc;
1100:         argv = margv;
1101:     }
1102:     if (argc < 2) {
1103: usage:
1104:         printf("%s from-name to-name\n", argv[0]);
1105:         code = -1;
1106:         return;
1107:     }
1108:     if (argc < 3) {
1109:         (void) strcat(line, " ");
1110:         printf("(to-name) ");
1111:         (void) gets(&line[strlen(line)]);
1112:         makeargv();
1113:         argc = margc;
1114:         argv = margv;
1115:     }
1116:     if (argc < 3)
1117:         goto usage;
1118:     if (command("RNFR %s", argv[1]) == CONTINUE)
1119:         (void) command("RNTO %s", argv[2]);
1120: }
1121: 
1122: /*
1123:  * Get a directory listing
1124:  * of remote files.
1125:  */
1126: ls(argc, argv)
1127:     char *argv[];
1128: {
1129:     char *cmd;
1130: 
1131:     if (argc < 2)
1132:         argc++, argv[1] = NULL;
1133:     if (argc < 3)
1134:         argc++, argv[2] = "-";
1135:     if (argc > 3) {
1136:         printf("usage: %s remote-directory local-file\n", argv[0]);
1137:         code = -1;
1138:         return;
1139:     }
1140:     cmd = argv[0][0] == 'n' ? "NLST" : "LIST";
1141:     if (strcmp(argv[2], "-") && !globulize(&argv[2])) {
1142:         code = -1;
1143:         return;
1144:     }
1145:     if (strcmp(argv[2], "-") && *argv[2] != '|')
1146:         if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) {
1147:             code = -1;
1148:             return;
1149:     }
1150:     recvrequest(cmd, argv[2], argv[1], "w", 0);
1151: }
1152: 
1153: /*
1154:  * Get a directory listing
1155:  * of multiple remote files.
1156:  */
1157: mls(argc, argv)
1158:     char *argv[];
1159: {
1160:     char *cmd, mode[1], *dest;
1161:     int ointer, i, (*oldintr)(), mabort();
1162:     extern jmp_buf jabort;
1163: 
1164:     if (argc < 2) {
1165:         (void) strcat(line, " ");
1166:         printf("(remote-files) ");
1167:         (void) gets(&line[strlen(line)]);
1168:         makeargv();
1169:         argc = margc;
1170:         argv = margv;
1171:     }
1172:     if (argc < 3) {
1173:         (void) strcat(line, " ");
1174:         printf("(local-file) ");
1175:         (void) gets(&line[strlen(line)]);
1176:         makeargv();
1177:         argc = margc;
1178:         argv = margv;
1179:     }
1180:     if (argc < 3) {
1181:         printf("usage:%s remote-files local-file\n", argv[0]);
1182:         code = -1;
1183:         return;
1184:     }
1185:     dest = argv[argc - 1];
1186:     argv[argc - 1] = NULL;
1187:     if (strcmp(dest, "-") && *dest != '|')
1188:         if (!globulize(&dest) || !confirm("output to local-file:", dest)) {
1189:             code = -1;
1190:             return;
1191:     }
1192:     cmd = argv[0][1] == 'l' ? "NLST" : "LIST";
1193:     mname = argv[0];
1194:     mflag = 1;
1195:     oldintr = signal(SIGINT, mabort);
1196:     (void) setjmp(jabort);
1197:     for (i = 1; mflag && i < argc-1; ++i) {
1198:         *mode = (i == 1) ? 'w' : 'a';
1199:         recvrequest(cmd, dest, argv[i], mode, 0);
1200:         if (!mflag && fromatty) {
1201:             ointer = interactive;
1202:             interactive = 1;
1203:             if (confirm("Continue with", argv[0])) {
1204:                 mflag ++;
1205:             }
1206:             interactive = ointer;
1207:         }
1208:     }
1209:     (void) signal(SIGINT, oldintr);
1210:     mflag = 0;
1211: }
1212: 
1213: /*
1214:  * Do a shell escape
1215:  */
1216: /*ARGSUSED*/
1217: shell(argc, argv)
1218:     char *argv[];
1219: {
1220:     int pid, (*old1)(), (*old2)();
1221:     char shellnam[40], *shell, *namep;
1222:     union wait status;
1223: 
1224:     old1 = signal (SIGINT, SIG_IGN);
1225:     old2 = signal (SIGQUIT, SIG_IGN);
1226:     if ((pid = fork()) == 0) {
1227:         for (pid = 3; pid < 20; pid++)
1228:             (void) close(pid);
1229:         (void) signal(SIGINT, SIG_DFL);
1230:         (void) signal(SIGQUIT, SIG_DFL);
1231:         shell = getenv("SHELL");
1232:         if (shell == NULL)
1233:             shell = _PATH_BSHELL;
1234:         namep = rindex(shell,'/');
1235:         if (namep == NULL)
1236:             namep = shell;
1237:         (void) strcpy(shellnam,"-");
1238:         (void) strcat(shellnam, ++namep);
1239:         if (strcmp(namep, "sh") != 0)
1240:             shellnam[0] = '+';
1241:         if (debug) {
1242:             printf ("%s\n", shell);
1243:             (void) fflush (stdout);
1244:         }
1245:         if (argc > 1) {
1246:             execl(shell,shellnam,"-c",altarg,(char *)0);
1247:         }
1248:         else {
1249:             execl(shell,shellnam,(char *)0);
1250:         }
1251:         perror(shell);
1252:         code = -1;
1253:         exit(1);
1254:         }
1255:     if (pid > 0)
1256:         while (wait(&status) != pid)
1257:             ;
1258:     (void) signal(SIGINT, old1);
1259:     (void) signal(SIGQUIT, old2);
1260:     if (pid == -1) {
1261:         perror("Try again later");
1262:         code = -1;
1263:     }
1264:     else {
1265:         code = 0;
1266:     }
1267:     return (0);
1268: }
1269: 
1270: /*
1271:  * Send new user information (re-login)
1272:  */
1273: user(argc, argv)
1274:     int argc;
1275:     char **argv;
1276: {
1277:     char acct[80];
1278:     int n, aflag = 0;
1279: 
1280:     if (argc < 2) {
1281:         (void) strcat(line, " ");
1282:         printf("(username) ");
1283:         (void) gets(&line[strlen(line)]);
1284:         makeargv();
1285:         argc = margc;
1286:         argv = margv;
1287:     }
1288:     if (argc > 4) {
1289:         printf("usage: %s username [password] [account]\n", argv[0]);
1290:         code = -1;
1291:         return (0);
1292:     }
1293:     n = command("USER %s", argv[1]);
1294:     if (n == CONTINUE) {
1295:         if (argc < 3 )
1296:             argv[2] = getpass("Password: "), argc++;
1297:         n = command("PASS %s", argv[2]);
1298:     }
1299:     if (n == CONTINUE) {
1300:         if (argc < 4) {
1301:             printf("Account: "); (void) fflush(stdout);
1302:             (void) fgets(acct, sizeof(acct) - 1, stdin);
1303:             acct[strlen(acct) - 1] = '\0';
1304:             argv[3] = acct; argc++;
1305:         }
1306:         n = command("ACCT %s", argv[3]);
1307:         aflag++;
1308:     }
1309:     if (n != COMPLETE) {
1310:         fprintf(stdout, "Login failed.\n");
1311:         return (0);
1312:     }
1313:     if (!aflag && argc == 4) {
1314:         (void) command("ACCT %s", argv[3]);
1315:     }
1316:     return (1);
1317: }
1318: 
1319: /*
1320:  * Print working directory.
1321:  */
1322: /*VARARGS*/
1323: pwd()
1324: {
1325:     int oldverbose = verbose;
1326: 
1327:     /*
1328: 	 * If we aren't verbose, this doesn't do anything!
1329: 	 */
1330:     verbose = 1;
1331:     if (command("PWD") == ERROR && code == 500) {
1332:         printf("PWD command not recognized, trying XPWD\n");
1333:         (void) command("XPWD");
1334:     }
1335:     verbose = oldverbose;
1336: }
1337: 
1338: /*
1339:  * Make a directory.
1340:  */
1341: makedir(argc, argv)
1342:     char *argv[];
1343: {
1344: 
1345:     if (argc < 2) {
1346:         (void) strcat(line, " ");
1347:         printf("(directory-name) ");
1348:         (void) gets(&line[strlen(line)]);
1349:         makeargv();
1350:         argc = margc;
1351:         argv = margv;
1352:     }
1353:     if (argc < 2) {
1354:         printf("usage: %s directory-name\n", argv[0]);
1355:         code = -1;
1356:         return;
1357:     }
1358:     if (command("MKD %s", argv[1]) == ERROR && code == 500) {
1359:         if (verbose)
1360:             printf("MKD command not recognized, trying XMKD\n");
1361:         (void) command("XMKD %s", argv[1]);
1362:     }
1363: }
1364: 
1365: /*
1366:  * Remove a directory.
1367:  */
1368: removedir(argc, argv)
1369:     char *argv[];
1370: {
1371: 
1372:     if (argc < 2) {
1373:         (void) strcat(line, " ");
1374:         printf("(directory-name) ");
1375:         (void) gets(&line[strlen(line)]);
1376:         makeargv();
1377:         argc = margc;
1378:         argv = margv;
1379:     }
1380:     if (argc < 2) {
1381:         printf("usage: %s directory-name\n", argv[0]);
1382:         code = -1;
1383:         return;
1384:     }
1385:     if (command("RMD %s", argv[1]) == ERROR && code == 500) {
1386:         if (verbose)
1387:             printf("RMD command not recognized, trying XRMD\n");
1388:         (void) command("XRMD %s", argv[1]);
1389:     }
1390: }
1391: 
1392: /*
1393:  * Send a line, verbatim, to the remote machine.
1394:  */
1395: quote(argc, argv)
1396:     char *argv[];
1397: {
1398:     int i;
1399:     char buf[BUFSIZ];
1400: 
1401:     if (argc < 2) {
1402:         (void) strcat(line, " ");
1403:         printf("(command line to send) ");
1404:         (void) gets(&line[strlen(line)]);
1405:         makeargv();
1406:         argc = margc;
1407:         argv = margv;
1408:     }
1409:     if (argc < 2) {
1410:         printf("usage: %s line-to-send\n", argv[0]);
1411:         code = -1;
1412:         return;
1413:     }
1414:     (void) strcpy(buf, argv[1]);
1415:     for (i = 2; i < argc; i++) {
1416:         (void) strcat(buf, " ");
1417:         (void) strcat(buf, argv[i]);
1418:     }
1419:     if (command(buf) == PRELIM) {
1420:         while (getreply(0) == PRELIM);
1421:     }
1422: }
1423: 
1424: /*
1425:  * Send a SITE command to the remote machine.  The line
1426:  * is sent almost verbatim to the remote machine, the
1427:  * first argument is changed to SITE.
1428:  */
1429: 
1430: site(argc, argv)
1431:     char *argv[];
1432: {
1433:     int i;
1434:     char buf[BUFSIZ];
1435: 
1436:     if (argc < 2) {
1437:         (void) strcat(line, " ");
1438:         printf("(arguments to SITE command) ");
1439:         (void) gets(&line[strlen(line)]);
1440:         makeargv();
1441:         argc = margc;
1442:         argv = margv;
1443:     }
1444:     if (argc < 2) {
1445:         printf("usage: %s line-to-send\n", argv[0]);
1446:         code = -1;
1447:         return;
1448:     }
1449:     (void) strcpy(buf, "SITE ");
1450:     (void) strcat(buf, argv[1]);
1451:     for (i = 2; i < argc; i++) {
1452:         (void) strcat(buf, " ");
1453:         (void) strcat(buf, argv[i]);
1454:     }
1455:     if (command(buf) == PRELIM) {
1456:         while (getreply(0) == PRELIM);
1457:     }
1458: }
1459: 
1460: do_chmod(argc, argv)
1461:     char *argv[];
1462: {
1463:     if (argc == 2) {
1464:         printf("usage: %s mode file-name\n", argv[0]);
1465:         code = -1;
1466:         return;
1467:     }
1468:     if (argc < 3) {
1469:         (void) strcat(line, " ");
1470:         printf("(mode and file-name) ");
1471:         (void) gets(&line[strlen(line)]);
1472:         makeargv();
1473:         argc = margc;
1474:         argv = margv;
1475:     }
1476:     if (argc != 3) {
1477:         printf("usage: %s mode file-name\n", argv[0]);
1478:         code = -1;
1479:         return;
1480:     }
1481:     (void)command("SITE CHMOD %s %s", argv[1], argv[2]);
1482: }
1483: 
1484: do_umask(argc, argv)
1485:     char *argv[];
1486: {
1487:     int oldverbose = verbose;
1488: 
1489:     verbose = 1;
1490:     (void) command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]);
1491:     verbose = oldverbose;
1492: }
1493: 
1494: idle(argc, argv)
1495:     char *argv[];
1496: {
1497:     int oldverbose = verbose;
1498: 
1499:     verbose = 1;
1500:     (void) command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]);
1501:     verbose = oldverbose;
1502: }
1503: 
1504: /*
1505:  * Ask the other side for help.
1506:  */
1507: rmthelp(argc, argv)
1508:     char *argv[];
1509: {
1510:     int oldverbose = verbose;
1511: 
1512:     verbose = 1;
1513:     (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
1514:     verbose = oldverbose;
1515: }
1516: 
1517: /*
1518:  * Terminate session and exit.
1519:  */
1520: /*VARARGS*/
1521: quit()
1522: {
1523: 
1524:     if (connected)
1525:         disconnect();
1526:     pswitch(1);
1527:     if (connected) {
1528:         disconnect();
1529:     }
1530:     exit(0);
1531: }
1532: 
1533: /*
1534:  * Terminate session, but don't exit.
1535:  */
1536: disconnect()
1537: {
1538:     extern FILE *cout;
1539:     extern int data;
1540: 
1541:     if (!connected)
1542:         return;
1543:     (void) command("QUIT");
1544:     if (cout) {
1545:         (void) fclose(cout);
1546:     }
1547:     cout = NULL;
1548:     connected = 0;
1549:     data = -1;
1550:     if (!proxy) {
1551:         macnum = 0;
1552:     }
1553: }
1554: 
1555: confirm(cmd, file)
1556:     char *cmd, *file;
1557: {
1558:     char line[BUFSIZ];
1559: 
1560:     if (!interactive)
1561:         return (1);
1562:     printf("%s %s? ", cmd, file);
1563:     (void) fflush(stdout);
1564:     (void) gets(line);
1565:     return (*line != 'n' && *line != 'N');
1566: }
1567: 
1568: fatal(msg)
1569:     char *msg;
1570: {
1571: 
1572:     fprintf(stderr, "ftp: %s\n", msg);
1573:     exit(1);
1574: }
1575: 
1576: /*
1577:  * Glob a local file name specification with
1578:  * the expectation of a single return value.
1579:  * Can't control multiple values being expanded
1580:  * from the expression, we return only the first.
1581:  */
1582: globulize(cpp)
1583:     char **cpp;
1584: {
1585:     char **globbed;
1586: 
1587:     if (!doglob)
1588:         return (1);
1589:     globbed = glob(*cpp);
1590:     if (globerr != NULL) {
1591:         printf("%s: %s\n", *cpp, globerr);
1592:         if (globbed) {
1593:             blkfree(globbed);
1594:             free(globbed);
1595:         }
1596:         return (0);
1597:     }
1598:     if (globbed) {
1599:         *cpp = *globbed++;
1600:         /* don't waste too much memory */
1601:         if (*globbed) {
1602:             blkfree(globbed);
1603:             free(globbed);
1604:         }
1605:     }
1606:     return (1);
1607: }
1608: 
1609: account(argc,argv)
1610:     int argc;
1611:     char **argv;
1612: {
1613:     char acct[50], *ap;
1614: 
1615:     if (argc > 1) {
1616:         ++argv;
1617:         --argc;
1618:         (void) strncpy(acct,*argv,49);
1619:         acct[49] = '\0';
1620:         while (argc > 1) {
1621:             --argc;
1622:             ++argv;
1623:             (void) strncat(acct,*argv, 49-strlen(acct));
1624:         }
1625:         ap = acct;
1626:     }
1627:     else {
1628:         ap = getpass("Account:");
1629:     }
1630:     (void) command("ACCT %s", ap);
1631: }
1632: 
1633: jmp_buf abortprox;
1634: 
1635: proxabort()
1636: {
1637:     extern int proxy;
1638: 
1639:     if (!proxy) {
1640:         pswitch(1);
1641:     }
1642:     if (connected) {
1643:         proxflag = 1;
1644:     }
1645:     else {
1646:         proxflag = 0;
1647:     }
1648:     pswitch(0);
1649:     longjmp(abortprox,1);
1650: }
1651: 
1652: doproxy(argc,argv)
1653:     int argc;
1654:     char *argv[];
1655: {
1656:     int (*oldintr)(), proxabort();
1657:     register struct cmd *c;
1658:     struct cmd *getcmd();
1659:     extern struct cmd cmdtab[];
1660:     extern jmp_buf abortprox;
1661: 
1662:     if (argc < 2) {
1663:         (void) strcat(line, " ");
1664:         printf("(command) ");
1665:         (void) gets(&line[strlen(line)]);
1666:         makeargv();
1667:         argc = margc;
1668:         argv = margv;
1669:     }
1670:     if (argc < 2) {
1671:         printf("usage:%s command\n", argv[0]);
1672:         code = -1;
1673:         return;
1674:     }
1675:     c = getcmd(argv[1]);
1676:     if (c == (struct cmd *) -1) {
1677:         printf("?Ambiguous command\n");
1678:         (void) fflush(stdout);
1679:         code = -1;
1680:         return;
1681:     }
1682:     if (c == 0) {
1683:         printf("?Invalid command\n");
1684:         (void) fflush(stdout);
1685:         code = -1;
1686:         return;
1687:     }
1688:     if (!c->c_proxy) {
1689:         printf("?Invalid proxy command\n");
1690:         (void) fflush(stdout);
1691:         code = -1;
1692:         return;
1693:     }
1694:     if (setjmp(abortprox)) {
1695:         code = -1;
1696:         return;
1697:     }
1698:     oldintr = signal(SIGINT, proxabort);
1699:     pswitch(1);
1700:     if (c->c_conn && !connected) {
1701:         printf("Not connected\n");
1702:         (void) fflush(stdout);
1703:         pswitch(0);
1704:         (void) signal(SIGINT, oldintr);
1705:         code = -1;
1706:         return;
1707:     }
1708:     (*c->c_handler)(argc-1, argv+1);
1709:     if (connected) {
1710:         proxflag = 1;
1711:     }
1712:     else {
1713:         proxflag = 0;
1714:     }
1715:     pswitch(0);
1716:     (void) signal(SIGINT, oldintr);
1717: }
1718: 
1719: setcase()
1720: {
1721:     mcase = !mcase;
1722:     printf("Case mapping %s.\n", onoff(mcase));
1723:     code = mcase;
1724: }
1725: 
1726: setcr()
1727: {
1728:     crflag = !crflag;
1729:     printf("Carriage Return stripping %s.\n", onoff(crflag));
1730:     code = crflag;
1731: }
1732: 
1733: setntrans(argc,argv)
1734:     int argc;
1735:     char *argv[];
1736: {
1737:     if (argc == 1) {
1738:         ntflag = 0;
1739:         printf("Ntrans off.\n");
1740:         code = ntflag;
1741:         return;
1742:     }
1743:     ntflag++;
1744:     code = ntflag;
1745:     (void) strncpy(ntin, argv[1], 16);
1746:     ntin[16] = '\0';
1747:     if (argc == 2) {
1748:         ntout[0] = '\0';
1749:         return;
1750:     }
1751:     (void) strncpy(ntout, argv[2], 16);
1752:     ntout[16] = '\0';
1753: }
1754: 
1755: char *
1756: dotrans(name)
1757:     char *name;
1758: {
1759:     static char new[MAXPATHLEN];
1760:     char *cp1, *cp2 = new;
1761:     register int i, ostop, found;
1762: 
1763:     for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++);
1764:     for (cp1 = name; *cp1; cp1++) {
1765:         found = 0;
1766:         for (i = 0; *(ntin + i) && i < 16; i++) {
1767:             if (*cp1 == *(ntin + i)) {
1768:                 found++;
1769:                 if (i < ostop) {
1770:                     *cp2++ = *(ntout + i);
1771:                 }
1772:                 break;
1773:             }
1774:         }
1775:         if (!found) {
1776:             *cp2++ = *cp1;
1777:         }
1778:     }
1779:     *cp2 = '\0';
1780:     return(new);
1781: }
1782: 
1783: setnmap(argc, argv)
1784:     int argc;
1785:     char *argv[];
1786: {
1787:     char *cp;
1788: 
1789:     if (argc == 1) {
1790:         mapflag = 0;
1791:         printf("Nmap off.\n");
1792:         code = mapflag;
1793:         return;
1794:     }
1795:     if (argc < 3) {
1796:         (void) strcat(line, " ");
1797:         printf("(mapout) ");
1798:         (void) gets(&line[strlen(line)]);
1799:         makeargv();
1800:         argc = margc;
1801:         argv = margv;
1802:     }
1803:     if (argc < 3) {
1804:         printf("Usage: %s [mapin mapout]\n",argv[0]);
1805:         code = -1;
1806:         return;
1807:     }
1808:     mapflag = 1;
1809:     code = 1;
1810:     cp = index(altarg, ' ');
1811:     if (proxy) {
1812:         while(*++cp == ' ');
1813:         altarg = cp;
1814:         cp = index(altarg, ' ');
1815:     }
1816:     *cp = '\0';
1817:     (void) strncpy(mapin, altarg, MAXPATHLEN - 1);
1818:     while (*++cp == ' ');
1819:     (void) strncpy(mapout, cp, MAXPATHLEN - 1);
1820: }
1821: 
1822: char *
1823: domap(name)
1824:     char *name;
1825: {
1826:     static char new[MAXPATHLEN];
1827:     register char *cp1 = name, *cp2 = mapin;
1828:     char *tp[9], *te[9];
1829:     int i, toks[9], toknum = 0, match = 1;
1830: 
1831:     for (i=0; i < 9; ++i) {
1832:         toks[i] = 0;
1833:     }
1834:     while (match && *cp1 && *cp2) {
1835:         switch (*cp2) {
1836:             case '\\':
1837:                 if (*++cp2 != *cp1) {
1838:                     match = 0;
1839:                 }
1840:                 break;
1841:             case '$':
1842:                 if (*(cp2+1) >= '1' && (*cp2+1) <= '9') {
1843:                     if (*cp1 != *(++cp2+1)) {
1844:                         toks[toknum = *cp2 - '1']++;
1845:                         tp[toknum] = cp1;
1846:                         while (*++cp1 && *(cp2+1)
1847:                             != *cp1);
1848:                         te[toknum] = cp1;
1849:                     }
1850:                     cp2++;
1851:                     break;
1852:                 }
1853:                 /* FALLTHROUGH */
1854:             default:
1855:                 if (*cp2 != *cp1) {
1856:                     match = 0;
1857:                 }
1858:                 break;
1859:         }
1860:         if (match && *cp1) {
1861:             cp1++;
1862:         }
1863:         if (match && *cp2) {
1864:             cp2++;
1865:         }
1866:     }
1867:     if (!match && *cp1) /* last token mismatch */
1868:     {
1869:         toks[toknum] = 0;
1870:     }
1871:     cp1 = new;
1872:     *cp1 = '\0';
1873:     cp2 = mapout;
1874:     while (*cp2) {
1875:         match = 0;
1876:         switch (*cp2) {
1877:             case '\\':
1878:                 if (*(cp2 + 1)) {
1879:                     *cp1++ = *++cp2;
1880:                 }
1881:                 break;
1882:             case '[':
1883: LOOP:
1884:                 if (*++cp2 == '$' && isdigit(*(cp2+1))) {
1885:                     if (*++cp2 == '0') {
1886:                         char *cp3 = name;
1887: 
1888:                         while (*cp3) {
1889:                             *cp1++ = *cp3++;
1890:                         }
1891:                         match = 1;
1892:                     }
1893:                     else if (toks[toknum = *cp2 - '1']) {
1894:                         char *cp3 = tp[toknum];
1895: 
1896:                         while (cp3 != te[toknum]) {
1897:                             *cp1++ = *cp3++;
1898:                         }
1899:                         match = 1;
1900:                     }
1901:                 }
1902:                 else {
1903:                     while (*cp2 && *cp2 != ',' &&
1904:                         *cp2 != ']') {
1905:                         if (*cp2 == '\\') {
1906:                             cp2++;
1907:                         }
1908:                         else if (*cp2 == '$' &&
1909:                                 isdigit(*(cp2+1))) {
1910:                             if (*++cp2 == '0') {
1911:                                char *cp3 = name;
1912: 
1913:                                while (*cp3) {
1914:                                 *cp1++ = *cp3++;
1915:                                }
1916:                             }
1917:                             else if (toks[toknum =
1918:                                 *cp2 - '1']) {
1919:                                char *cp3=tp[toknum];
1920: 
1921:                                while (cp3 !=
1922:                                   te[toknum]) {
1923:                                 *cp1++ = *cp3++;
1924:                                }
1925:                             }
1926:                         }
1927:                         else if (*cp2) {
1928:                             *cp1++ = *cp2++;
1929:                         }
1930:                     }
1931:                     if (!*cp2) {
1932:                         printf("nmap: unbalanced brackets\n");
1933:                         return(name);
1934:                     }
1935:                     match = 1;
1936:                     cp2--;
1937:                 }
1938:                 if (match) {
1939:                     while (*++cp2 && *cp2 != ']') {
1940:                           if (*cp2 == '\\' && *(cp2 + 1)) {
1941:                             cp2++;
1942:                           }
1943:                     }
1944:                     if (!*cp2) {
1945:                         printf("nmap: unbalanced brackets\n");
1946:                         return(name);
1947:                     }
1948:                     break;
1949:                 }
1950:                 switch (*++cp2) {
1951:                     case ',':
1952:                         goto LOOP;
1953:                     case ']':
1954:                         break;
1955:                     default:
1956:                         cp2--;
1957:                         goto LOOP;
1958:                 }
1959:                 break;
1960:             case '$':
1961:                 if (isdigit(*(cp2 + 1))) {
1962:                     if (*++cp2 == '0') {
1963:                         char *cp3 = name;
1964: 
1965:                         while (*cp3) {
1966:                             *cp1++ = *cp3++;
1967:                         }
1968:                     }
1969:                     else if (toks[toknum = *cp2 - '1']) {
1970:                         char *cp3 = tp[toknum];
1971: 
1972:                         while (cp3 != te[toknum]) {
1973:                             *cp1++ = *cp3++;
1974:                         }
1975:                     }
1976:                     break;
1977:                 }
1978:                 /* intentional drop through */
1979:             default:
1980:                 *cp1++ = *cp2;
1981:                 break;
1982:         }
1983:         cp2++;
1984:     }
1985:     *cp1 = '\0';
1986:     if (!*new) {
1987:         return(name);
1988:     }
1989:     return(new);
1990: }
1991: 
1992: setsunique()
1993: {
1994:     sunique = !sunique;
1995:     printf("Store unique %s.\n", onoff(sunique));
1996:     code = sunique;
1997: }
1998: 
1999: setrunique()
2000: {
2001:     runique = !runique;
2002:     printf("Receive unique %s.\n", onoff(runique));
2003:     code = runique;
2004: }
2005: 
2006: /* change directory to perent directory */
2007: cdup()
2008: {
2009:     if (command("CDUP") == ERROR && code == 500) {
2010:         if (verbose)
2011:             printf("CDUP command not recognized, trying XCUP\n");
2012:         (void) command("XCUP");
2013:     }
2014: }
2015: 
2016: /* restart transfer at specific point */
2017: restart(argc, argv)
2018:     int argc;
2019:     char *argv[];
2020: {
2021:     extern long atol();
2022:     if (argc != 2)
2023:         printf("restart: offset not specified\n");
2024:     else {
2025:         restart_point = atol(argv[1]);
2026:         printf("restarting at %ld. %s\n", restart_point,
2027:             "execute get, put or append to initiate transfer");
2028:     }
2029: }
2030: 
2031: /* show remote system type */
2032: syst()
2033: {
2034:     (void) command("SYST");
2035: }
2036: 
2037: macdef(argc, argv)
2038:     int argc;
2039:     char *argv[];
2040: {
2041:     char *tmp;
2042:     int c;
2043: 
2044:     if (macnum == 16) {
2045:         printf("Limit of 16 macros have already been defined\n");
2046:         code = -1;
2047:         return;
2048:     }
2049:     if (argc < 2) {
2050:         (void) strcat(line, " ");
2051:         printf("(macro name) ");
2052:         (void) gets(&line[strlen(line)]);
2053:         makeargv();
2054:         argc = margc;
2055:         argv = margv;
2056:     }
2057:     if (argc != 2) {
2058:         printf("Usage: %s macro_name\n",argv[0]);
2059:         code = -1;
2060:         return;
2061:     }
2062:     if (interactive) {
2063:         printf("Enter macro line by line, terminating it with a null line\n");
2064:     }
2065:     (void) strncpy(macros[macnum].mac_name, argv[1], 8);
2066:     if (macnum == 0) {
2067:         macros[macnum].mac_start = macbuf;
2068:     }
2069:     else {
2070:         macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
2071:     }
2072:     tmp = macros[macnum].mac_start;
2073:     while (tmp != macbuf+4096) {
2074:         if ((c = getchar()) == EOF) {
2075:             printf("macdef:end of file encountered\n");
2076:             code = -1;
2077:             return;
2078:         }
2079:         if ((*tmp = c) == '\n') {
2080:             if (tmp == macros[macnum].mac_start) {
2081:                 macros[macnum++].mac_end = tmp;
2082:                 code = 0;
2083:                 return;
2084:             }
2085:             if (*(tmp-1) == '\0') {
2086:                 macros[macnum++].mac_end = tmp - 1;
2087:                 code = 0;
2088:                 return;
2089:             }
2090:             *tmp = '\0';
2091:         }
2092:         tmp++;
2093:     }
2094:     while (1) {
2095:         while ((c = getchar()) != '\n' && c != EOF)
2096:             /* LOOP */;
2097:         if (c == EOF || getchar() == '\n') {
2098:             printf("Macro not defined - 4k buffer exceeded\n");
2099:             code = -1;
2100:             return;
2101:         }
2102:     }
2103: }
2104: 
2105: /*
2106:  * get size of file on remote machine
2107:  */
2108: sizecmd(argc, argv)
2109:     char *argv[];
2110: {
2111: 
2112:     if (argc < 2) {
2113:         (void) strcat(line, " ");
2114:         printf("(filename) ");
2115:         (void) gets(&line[strlen(line)]);
2116:         makeargv();
2117:         argc = margc;
2118:         argv = margv;
2119:     }
2120:     if (argc < 2) {
2121:         printf("usage:%s filename\n", argv[0]);
2122:         code = -1;
2123:         return;
2124:     }
2125:     (void) command("SIZE %s", argv[1]);
2126: }
2127: 
2128: /*
2129:  * get last modification time of file on remote machine
2130:  */
2131: modtime(argc, argv)
2132:     char *argv[];
2133: {
2134:     int overbose;
2135: 
2136:     if (argc < 2) {
2137:         (void) strcat(line, " ");
2138:         printf("(filename) ");
2139:         (void) gets(&line[strlen(line)]);
2140:         makeargv();
2141:         argc = margc;
2142:         argv = margv;
2143:     }
2144:     if (argc < 2) {
2145:         printf("usage:%s filename\n", argv[0]);
2146:         code = -1;
2147:         return;
2148:     }
2149:     overbose = verbose;
2150:     if (debug == 0)
2151:         verbose = -1;
2152:     if (command("MDTM %s", argv[1]) == COMPLETE) {
2153:         int yy, mo, day, hour, min, sec;
2154:         sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo,
2155:             &day, &hour, &min, &sec);
2156:         /* might want to print this in local time */
2157:         printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1],
2158:             mo, day, yy, hour, min, sec);
2159:     } else
2160:         fputs(reply_string, stdout);
2161:     verbose = overbose;
2162: }
2163: 
2164: /*
2165:  * show status on reomte machine
2166:  */
2167: rmtstatus(argc, argv)
2168:     char *argv[];
2169: {
2170:     (void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]);
2171: }
2172: 
2173: /*
2174:  * get file if modtime is more recent than current file
2175:  */
2176: newer(argc, argv)
2177:     char *argv[];
2178: {
2179:     if (getit(argc, argv, -1, "w"))
2180:         printf("Local file \"%s\" is newer than remote file \"%s\"\n",
2181:             argv[1], argv[2]);
2182: }

Defined functions

account defined in line 1609; used 2 times
cd defined in line 963; used 2 times
cdup defined in line 2007; used 2 times
confirm defined in line 1555; used 14 times
delete defined in line 1019; used 2 times
disconnect defined in line 1536; used 5 times
do_chmod defined in line 1460; used 2 times
do_umask defined in line 1484; used 2 times
domap defined in line 1822; used 7 times
doproxy defined in line 1652; used 2 times
dotrans defined in line 1755; used 7 times
fatal defined in line 1568; used 2 times
get defined in line 492; used 3 times
getit defined in line 501; used 3 times
globulize defined in line 1582; used 6 times
idle defined in line 1494; used 2 times
lcd defined in line 991; used 2 times
ls defined in line 1126; used 4 times
mabort defined in line 626; used 8 times
macdef defined in line 2037; used 2 times
makedir defined in line 1341; used 2 times
mdelete defined in line 1042; used 2 times
mget defined in line 649; used 2 times
mls defined in line 1157; used 3 times
modtime defined in line 2131; used 2 times
mput defined in line 358; used 2 times
newer defined in line 2176; used 2 times
onoff defined in line 780; used 22 times
proxabort defined in line 1635; used 2 times
put defined in line 294; used 4 times
pwd defined in line 1323; used 2 times
quit defined in line 1521; used 4 times
quote defined in line 1395; used 2 times
reget defined in line 486; used 2 times
remglob defined in line 719; used 5 times
removedir defined in line 1368; used 2 times
renamefile defined in line 1090; used 2 times
restart defined in line 2017; used 2 times
rmthelp defined in line 1507; used 2 times
rmtstatus defined in line 2167; used 2 times
setascii defined in line 229; used 10 times
setbell defined in line 846; used 2 times
setbinary defined in line 219; used 15 times
setcase defined in line 1719; used 2 times
setcr defined in line 1726; used 2 times
setdebug defined in line 936; used 2 times
setebcdic defined in line 249; used 11 times
setform defined in line 271; used 2 times
setglob defined in line 923; used 2 times
sethash defined in line 870; used 2 times
setmode defined in line 259; used 2 times
setnmap defined in line 1783; used 2 times
setntrans defined in line 1733; used 2 times
setpeer defined in line 62; used 3 times
setport defined in line 897; used 2 times
setprompt defined in line 910; used 2 times
setrunique defined in line 1999; used 2 times
setstruct defined in line 283; used 2 times
setsunique defined in line 1992; used 2 times
settenex defined in line 239; used 13 times
settrace defined in line 858; used 2 times
settype defined in line 166; used 6 times
setverbose defined in line 885; used 2 times
shell defined in line 1217; used 12 times
site defined in line 1430; used 2 times
sizecmd defined in line 2108; used 2 times
status defined in line 792; used 4 times
syst defined in line 2032; used 2 times
user defined in line 1273; used 2 times

Defined variables

abortprox defined in line 1633; used 3 times
jabort defined in line 55; used 11 times
mname defined in line 54; used 5 times
sccsid defined in line 19; never used
stype defined in line 209; used 8 times
types defined in line 154; used 2 times

Defined struct's

types defined in line 149; used 2 times
  • in line 169(2)
Last modified: 1997-10-03
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 13056
Valid CSS Valid XHTML 1.0 Strict