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