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