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: }