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 #ifndef lint 19 static char sccsid[] = "@(#)cmds.c 5.15 (Berkeley) 03/21/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)", 1024); 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 if (command("CWD %s", argv[1]) == ERROR && code == 500) { 963 if (verbose) 964 printf("CWD command not recognized, trying XCWD\n"); 965 (void) command("XCWD %s", argv[1]); 966 } 967 } 968 969 /* 970 * Set current working directory 971 * on local machine. 972 */ 973 lcd(argc, argv) 974 char *argv[]; 975 { 976 char buf[MAXPATHLEN]; 977 978 if (argc < 2) 979 argc++, argv[1] = home; 980 if (argc != 2) { 981 printf("usage:%s local-directory\n", argv[0]); 982 code = -1; 983 return; 984 } 985 if (!globulize(&argv[1])) { 986 code = -1; 987 return; 988 } 989 if (chdir(argv[1]) < 0) { 990 perror(argv[1]); 991 code = -1; 992 return; 993 } 994 printf("Local directory now %s\n", getwd(buf)); 995 code = 0; 996 } 997 998 /* 999 * Delete a single file. 1000 */ 1001 delete(argc, argv) 1002 char *argv[]; 1003 { 1004 1005 if (argc < 2) { 1006 (void) strcat(line, " "); 1007 printf("(remote-file) "); 1008 (void) gets(&line[strlen(line)]); 1009 makeargv(); 1010 argc = margc; 1011 argv = margv; 1012 } 1013 if (argc < 2) { 1014 printf("usage:%s remote-file\n", argv[0]); 1015 code = -1; 1016 return; 1017 } 1018 (void) command("DELE %s", argv[1]); 1019 } 1020 1021 /* 1022 * Delete multiple files. 1023 */ 1024 mdelete(argc, argv) 1025 char *argv[]; 1026 { 1027 char *cp; 1028 int ointer, (*oldintr)(), mabort(); 1029 extern jmp_buf jabort; 1030 1031 if (argc < 2) { 1032 (void) strcat(line, " "); 1033 printf("(remote-files) "); 1034 (void) gets(&line[strlen(line)]); 1035 makeargv(); 1036 argc = margc; 1037 argv = margv; 1038 } 1039 if (argc < 2) { 1040 printf("usage:%s remote-files\n", argv[0]); 1041 code = -1; 1042 return; 1043 } 1044 mname = argv[0]; 1045 mflag = 1; 1046 oldintr = signal(SIGINT, mabort); 1047 (void) setjmp(jabort); 1048 while ((cp = remglob(argv,0)) != NULL) { 1049 if (*cp == '\0') { 1050 mflag = 0; 1051 continue; 1052 } 1053 if (mflag && confirm(argv[0], cp)) { 1054 (void) command("DELE %s", cp); 1055 if (!mflag && fromatty) { 1056 ointer = interactive; 1057 interactive = 1; 1058 if (confirm("Continue with", "mdelete")) { 1059 mflag++; 1060 } 1061 interactive = ointer; 1062 } 1063 } 1064 } 1065 (void) signal(SIGINT, oldintr); 1066 mflag = 0; 1067 } 1068 1069 /* 1070 * Rename a remote file. 1071 */ 1072 renamefile(argc, argv) 1073 char *argv[]; 1074 { 1075 1076 if (argc < 2) { 1077 (void) strcat(line, " "); 1078 printf("(from-name) "); 1079 (void) gets(&line[strlen(line)]); 1080 makeargv(); 1081 argc = margc; 1082 argv = margv; 1083 } 1084 if (argc < 2) { 1085 usage: 1086 printf("%s from-name to-name\n", argv[0]); 1087 code = -1; 1088 return; 1089 } 1090 if (argc < 3) { 1091 (void) strcat(line, " "); 1092 printf("(to-name) "); 1093 (void) gets(&line[strlen(line)]); 1094 makeargv(); 1095 argc = margc; 1096 argv = margv; 1097 } 1098 if (argc < 3) 1099 goto usage; 1100 if (command("RNFR %s", argv[1]) == CONTINUE) 1101 (void) command("RNTO %s", argv[2]); 1102 } 1103 1104 /* 1105 * Get a directory listing 1106 * of remote files. 1107 */ 1108 ls(argc, argv) 1109 char *argv[]; 1110 { 1111 char *cmd; 1112 1113 if (argc < 2) 1114 argc++, argv[1] = NULL; 1115 if (argc < 3) 1116 argc++, argv[2] = "-"; 1117 if (argc > 3) { 1118 printf("usage: %s remote-directory local-file\n", argv[0]); 1119 code = -1; 1120 return; 1121 } 1122 cmd = argv[0][0] == 'n' ? "NLST" : "LIST"; 1123 if (strcmp(argv[2], "-") && !globulize(&argv[2])) { 1124 code = -1; 1125 return; 1126 } 1127 if (strcmp(argv[2], "-") && *argv[2] != '|') 1128 if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) { 1129 code = -1; 1130 return; 1131 } 1132 recvrequest(cmd, argv[2], argv[1], "w"); 1133 } 1134 1135 /* 1136 * Get a directory listing 1137 * of multiple remote files. 1138 */ 1139 mls(argc, argv) 1140 char *argv[]; 1141 { 1142 char *cmd, mode[1], *dest; 1143 int ointer, i, (*oldintr)(), mabort(); 1144 extern jmp_buf jabort; 1145 1146 if (argc < 2) { 1147 (void) strcat(line, " "); 1148 printf("(remote-files) "); 1149 (void) gets(&line[strlen(line)]); 1150 makeargv(); 1151 argc = margc; 1152 argv = margv; 1153 } 1154 if (argc < 3) { 1155 (void) strcat(line, " "); 1156 printf("(local-file) "); 1157 (void) gets(&line[strlen(line)]); 1158 makeargv(); 1159 argc = margc; 1160 argv = margv; 1161 } 1162 if (argc < 3) { 1163 printf("usage:%s remote-files local-file\n", argv[0]); 1164 code = -1; 1165 return; 1166 } 1167 dest = argv[argc - 1]; 1168 argv[argc - 1] = NULL; 1169 if (strcmp(dest, "-") && *dest != '|') 1170 if (!globulize(&dest) || !confirm("output to local-file:", dest)) { 1171 code = -1; 1172 return; 1173 } 1174 cmd = argv[0][1] == 'l' ? "NLST" : "LIST"; 1175 mname = argv[0]; 1176 mflag = 1; 1177 oldintr = signal(SIGINT, mabort); 1178 (void) setjmp(jabort); 1179 for (i = 1; mflag && i < argc-1; ++i) { 1180 *mode = (i == 1) ? 'w' : 'a'; 1181 recvrequest(cmd, dest, argv[i], mode); 1182 if (!mflag && fromatty) { 1183 ointer = interactive; 1184 interactive = 1; 1185 if (confirm("Continue with", argv[0])) { 1186 mflag ++; 1187 } 1188 interactive = ointer; 1189 } 1190 } 1191 (void) signal(SIGINT, oldintr); 1192 mflag = 0; 1193 } 1194 1195 /* 1196 * Do a shell escape 1197 */ 1198 /*ARGSUSED*/ 1199 shell(argc, argv) 1200 char *argv[]; 1201 { 1202 int pid, (*old1)(), (*old2)(); 1203 char shellnam[40], *shell, *namep; 1204 union wait status; 1205 1206 old1 = signal (SIGINT, SIG_IGN); 1207 old2 = signal (SIGQUIT, SIG_IGN); 1208 if ((pid = fork()) == 0) { 1209 for (pid = 3; pid < 20; pid++) 1210 (void) close(pid); 1211 (void) signal(SIGINT, SIG_DFL); 1212 (void) signal(SIGQUIT, SIG_DFL); 1213 shell = getenv("SHELL"); 1214 if (shell == NULL) 1215 shell = "/bin/sh"; 1216 namep = rindex(shell,'/'); 1217 if (namep == NULL) 1218 namep = shell; 1219 (void) strcpy(shellnam,"-"); 1220 (void) strcat(shellnam, ++namep); 1221 if (strcmp(namep, "sh") != 0) 1222 shellnam[0] = '+'; 1223 if (debug) { 1224 printf ("%s\n", shell); 1225 (void) fflush (stdout); 1226 } 1227 if (argc > 1) { 1228 execl(shell,shellnam,"-c",altarg,(char *)0); 1229 } 1230 else { 1231 execl(shell,shellnam,(char *)0); 1232 } 1233 perror(shell); 1234 code = -1; 1235 exit(1); 1236 } 1237 if (pid > 0) 1238 while (wait(&status) != pid) 1239 ; 1240 (void) signal(SIGINT, old1); 1241 (void) signal(SIGQUIT, old2); 1242 if (pid == -1) { 1243 perror("Try again later"); 1244 code = -1; 1245 } 1246 else { 1247 code = 0; 1248 } 1249 return (0); 1250 } 1251 1252 /* 1253 * Send new user information (re-login) 1254 */ 1255 user(argc, argv) 1256 int argc; 1257 char **argv; 1258 { 1259 char acct[80], *getpass(); 1260 int n, aflag = 0; 1261 1262 if (argc < 2) { 1263 (void) strcat(line, " "); 1264 printf("(username) "); 1265 (void) gets(&line[strlen(line)]); 1266 makeargv(); 1267 argc = margc; 1268 argv = margv; 1269 } 1270 if (argc > 4) { 1271 printf("usage: %s username [password] [account]\n", argv[0]); 1272 code = -1; 1273 return (0); 1274 } 1275 n = command("USER %s", argv[1]); 1276 if (n == CONTINUE) { 1277 if (argc < 3 ) 1278 argv[2] = getpass("Password: "), argc++; 1279 n = command("PASS %s", argv[2]); 1280 } 1281 if (n == CONTINUE) { 1282 if (argc < 4) { 1283 printf("Account: "); (void) fflush(stdout); 1284 (void) fgets(acct, sizeof(acct) - 1, stdin); 1285 acct[strlen(acct) - 1] = '\0'; 1286 argv[3] = acct; argc++; 1287 } 1288 n = command("ACCT %s", argv[3]); 1289 aflag++; 1290 } 1291 if (n != COMPLETE) { 1292 fprintf(stdout, "Login failed.\n"); 1293 return (0); 1294 } 1295 if (!aflag && argc == 4) { 1296 (void) command("ACCT %s", argv[3]); 1297 } 1298 return (1); 1299 } 1300 1301 /* 1302 * Print working directory. 1303 */ 1304 /*VARARGS*/ 1305 pwd() 1306 { 1307 int oldverbose = verbose; 1308 1309 /* 1310 * If we aren't verbose, this doesn't do anything! 1311 */ 1312 verbose = 1; 1313 if (command("PWD") == ERROR && code == 500) { 1314 printf("PWD command not recognized, trying XPWD\n"); 1315 (void) command("XPWD"); 1316 } 1317 verbose = oldverbose; 1318 } 1319 1320 /* 1321 * Make a directory. 1322 */ 1323 makedir(argc, argv) 1324 char *argv[]; 1325 { 1326 1327 if (argc < 2) { 1328 (void) strcat(line, " "); 1329 printf("(directory-name) "); 1330 (void) gets(&line[strlen(line)]); 1331 makeargv(); 1332 argc = margc; 1333 argv = margv; 1334 } 1335 if (argc < 2) { 1336 printf("usage: %s directory-name\n", argv[0]); 1337 code = -1; 1338 return; 1339 } 1340 if (command("MKD %s", argv[1]) == ERROR && code == 500) { 1341 if (verbose) 1342 printf("MKD command not recognized, trying XMKD\n"); 1343 (void) command("XMKD %s", argv[1]); 1344 } 1345 } 1346 1347 /* 1348 * Remove a directory. 1349 */ 1350 removedir(argc, argv) 1351 char *argv[]; 1352 { 1353 1354 if (argc < 2) { 1355 (void) strcat(line, " "); 1356 printf("(directory-name) "); 1357 (void) gets(&line[strlen(line)]); 1358 makeargv(); 1359 argc = margc; 1360 argv = margv; 1361 } 1362 if (argc < 2) { 1363 printf("usage: %s directory-name\n", argv[0]); 1364 code = -1; 1365 return; 1366 } 1367 if (command("RMD %s", argv[1]) == ERROR && code == 500) { 1368 if (verbose) 1369 printf("RMD command not recognized, trying XRMD\n"); 1370 (void) command("XRMD %s", argv[1]); 1371 } 1372 } 1373 1374 /* 1375 * Send a line, verbatim, to the remote machine. 1376 */ 1377 quote(argc, argv) 1378 char *argv[]; 1379 { 1380 int i; 1381 char buf[BUFSIZ]; 1382 1383 if (argc < 2) { 1384 (void) strcat(line, " "); 1385 printf("(command line to send) "); 1386 (void) gets(&line[strlen(line)]); 1387 makeargv(); 1388 argc = margc; 1389 argv = margv; 1390 } 1391 if (argc < 2) { 1392 printf("usage: %s line-to-send\n", argv[0]); 1393 code = -1; 1394 return; 1395 } 1396 (void) strcpy(buf, argv[1]); 1397 for (i = 2; i < argc; i++) { 1398 (void) strcat(buf, " "); 1399 (void) strcat(buf, argv[i]); 1400 } 1401 if (command(buf) == PRELIM) { 1402 while (getreply(0) == PRELIM); 1403 } 1404 } 1405 1406 /* 1407 * Send a SITE command to the remote machine. The line 1408 * is sent almost verbatim to the remote machine, the 1409 * first argument is changed to SITE. 1410 */ 1411 1412 site(argc, argv) 1413 char *argv[]; 1414 { 1415 int i; 1416 char buf[BUFSIZ]; 1417 1418 if (argc < 2) { 1419 (void) strcat(line, " "); 1420 printf("(arguments to SITE command) "); 1421 (void) gets(&line[strlen(line)]); 1422 makeargv(); 1423 argc = margc; 1424 argv = margv; 1425 } 1426 if (argc < 2) { 1427 printf("usage: %s line-to-send\n", argv[0]); 1428 code = -1; 1429 return; 1430 } 1431 (void) strcpy(buf, "SITE "); 1432 (void) strcat(buf, argv[1]); 1433 for (i = 2; i < argc; i++) { 1434 (void) strcat(buf, " "); 1435 (void) strcat(buf, argv[i]); 1436 } 1437 if (command(buf) == PRELIM) { 1438 while (getreply(0) == PRELIM); 1439 } 1440 } 1441 1442 do_chmod(argc, argv) 1443 char *argv[]; 1444 { 1445 if (argc == 2) { 1446 printf("usage: %s mode file-name\n", argv[0]); 1447 code = -1; 1448 return; 1449 } 1450 if (argc < 3) { 1451 (void) strcat(line, " "); 1452 printf("(mode and file-name) "); 1453 (void) gets(&line[strlen(line)]); 1454 makeargv(); 1455 argc = margc; 1456 argv = margv; 1457 } 1458 if (argc != 3) { 1459 printf("usage: %s mode file-name\n", argv[0]); 1460 code = -1; 1461 return; 1462 } 1463 (void)command("SITE CHMOD %s %s", argv[1], argv[2]); 1464 } 1465 1466 do_umask(argc, argv) 1467 char *argv[]; 1468 { 1469 int oldverbose = verbose; 1470 1471 verbose = 1; 1472 (void) command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]); 1473 verbose = oldverbose; 1474 } 1475 1476 idle(argc, argv) 1477 char *argv[]; 1478 { 1479 int oldverbose = verbose; 1480 1481 verbose = 1; 1482 (void) command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]); 1483 verbose = oldverbose; 1484 } 1485 1486 /* 1487 * Ask the other side for help. 1488 */ 1489 rmthelp(argc, argv) 1490 char *argv[]; 1491 { 1492 int oldverbose = verbose; 1493 1494 verbose = 1; 1495 (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]); 1496 verbose = oldverbose; 1497 } 1498 1499 /* 1500 * Terminate session and exit. 1501 */ 1502 /*VARARGS*/ 1503 quit() 1504 { 1505 1506 if (connected) 1507 disconnect(); 1508 pswitch(1); 1509 if (connected) { 1510 disconnect(); 1511 } 1512 exit(0); 1513 } 1514 1515 /* 1516 * Terminate session, but don't exit. 1517 */ 1518 disconnect() 1519 { 1520 extern FILE *cout; 1521 extern int data; 1522 1523 if (!connected) 1524 return; 1525 (void) command("QUIT"); 1526 if (cout) { 1527 (void) fclose(cout); 1528 } 1529 cout = NULL; 1530 connected = 0; 1531 data = -1; 1532 if (!proxy) { 1533 macnum = 0; 1534 } 1535 } 1536 1537 confirm(cmd, file) 1538 char *cmd, *file; 1539 { 1540 char line[BUFSIZ]; 1541 1542 if (!interactive) 1543 return (1); 1544 printf("%s %s? ", cmd, file); 1545 (void) fflush(stdout); 1546 (void) gets(line); 1547 return (*line != 'n' && *line != 'N'); 1548 } 1549 1550 fatal(msg) 1551 char *msg; 1552 { 1553 1554 fprintf(stderr, "ftp: %s\n", msg); 1555 exit(1); 1556 } 1557 1558 /* 1559 * Glob a local file name specification with 1560 * the expectation of a single return value. 1561 * Can't control multiple values being expanded 1562 * from the expression, we return only the first. 1563 */ 1564 globulize(cpp) 1565 char **cpp; 1566 { 1567 char **globbed; 1568 1569 if (!doglob) 1570 return (1); 1571 globbed = glob(*cpp); 1572 if (globerr != NULL) { 1573 printf("%s: %s\n", *cpp, globerr); 1574 if (globbed) { 1575 blkfree(globbed); 1576 free(globbed); 1577 } 1578 return (0); 1579 } 1580 if (globbed) { 1581 *cpp = *globbed++; 1582 /* don't waste too much memory */ 1583 if (*globbed) { 1584 blkfree(globbed); 1585 free(globbed); 1586 } 1587 } 1588 return (1); 1589 } 1590 1591 account(argc,argv) 1592 int argc; 1593 char **argv; 1594 { 1595 char acct[50], *getpass(), *ap; 1596 1597 if (argc > 1) { 1598 ++argv; 1599 --argc; 1600 (void) strncpy(acct,*argv,49); 1601 acct[49] = '\0'; 1602 while (argc > 1) { 1603 --argc; 1604 ++argv; 1605 (void) strncat(acct,*argv, 49-strlen(acct)); 1606 } 1607 ap = acct; 1608 } 1609 else { 1610 ap = getpass("Account:"); 1611 } 1612 (void) command("ACCT %s", ap); 1613 } 1614 1615 jmp_buf abortprox; 1616 1617 proxabort() 1618 { 1619 extern int proxy; 1620 1621 if (!proxy) { 1622 pswitch(1); 1623 } 1624 if (connected) { 1625 proxflag = 1; 1626 } 1627 else { 1628 proxflag = 0; 1629 } 1630 pswitch(0); 1631 longjmp(abortprox,1); 1632 } 1633 1634 doproxy(argc,argv) 1635 int argc; 1636 char *argv[]; 1637 { 1638 int (*oldintr)(), proxabort(); 1639 register struct cmd *c; 1640 struct cmd *getcmd(); 1641 extern struct cmd cmdtab[]; 1642 extern jmp_buf abortprox; 1643 1644 if (argc < 2) { 1645 (void) strcat(line, " "); 1646 printf("(command) "); 1647 (void) gets(&line[strlen(line)]); 1648 makeargv(); 1649 argc = margc; 1650 argv = margv; 1651 } 1652 if (argc < 2) { 1653 printf("usage:%s command\n", argv[0]); 1654 code = -1; 1655 return; 1656 } 1657 c = getcmd(argv[1]); 1658 if (c == (struct cmd *) -1) { 1659 printf("?Ambiguous command\n"); 1660 (void) fflush(stdout); 1661 code = -1; 1662 return; 1663 } 1664 if (c == 0) { 1665 printf("?Invalid command\n"); 1666 (void) fflush(stdout); 1667 code = -1; 1668 return; 1669 } 1670 if (!c->c_proxy) { 1671 printf("?Invalid proxy command\n"); 1672 (void) fflush(stdout); 1673 code = -1; 1674 return; 1675 } 1676 if (setjmp(abortprox)) { 1677 code = -1; 1678 return; 1679 } 1680 oldintr = signal(SIGINT, proxabort); 1681 pswitch(1); 1682 if (c->c_conn && !connected) { 1683 printf("Not connected\n"); 1684 (void) fflush(stdout); 1685 pswitch(0); 1686 (void) signal(SIGINT, oldintr); 1687 code = -1; 1688 return; 1689 } 1690 (*c->c_handler)(argc-1, argv+1); 1691 if (connected) { 1692 proxflag = 1; 1693 } 1694 else { 1695 proxflag = 0; 1696 } 1697 pswitch(0); 1698 (void) signal(SIGINT, oldintr); 1699 } 1700 1701 setcase() 1702 { 1703 mcase = !mcase; 1704 printf("Case mapping %s.\n", onoff(mcase)); 1705 code = mcase; 1706 } 1707 1708 setcr() 1709 { 1710 crflag = !crflag; 1711 printf("Carriage Return stripping %s.\n", onoff(crflag)); 1712 code = crflag; 1713 } 1714 1715 setntrans(argc,argv) 1716 int argc; 1717 char *argv[]; 1718 { 1719 if (argc == 1) { 1720 ntflag = 0; 1721 printf("Ntrans off.\n"); 1722 code = ntflag; 1723 return; 1724 } 1725 ntflag++; 1726 code = ntflag; 1727 (void) strncpy(ntin, argv[1], 16); 1728 ntin[16] = '\0'; 1729 if (argc == 2) { 1730 ntout[0] = '\0'; 1731 return; 1732 } 1733 (void) strncpy(ntout, argv[2], 16); 1734 ntout[16] = '\0'; 1735 } 1736 1737 char * 1738 dotrans(name) 1739 char *name; 1740 { 1741 static char new[MAXPATHLEN]; 1742 char *cp1, *cp2 = new; 1743 register int i, ostop, found; 1744 1745 for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++); 1746 for (cp1 = name; *cp1; cp1++) { 1747 found = 0; 1748 for (i = 0; *(ntin + i) && i < 16; i++) { 1749 if (*cp1 == *(ntin + i)) { 1750 found++; 1751 if (i < ostop) { 1752 *cp2++ = *(ntout + i); 1753 } 1754 break; 1755 } 1756 } 1757 if (!found) { 1758 *cp2++ = *cp1; 1759 } 1760 } 1761 *cp2 = '\0'; 1762 return(new); 1763 } 1764 1765 setnmap(argc, argv) 1766 int argc; 1767 char *argv[]; 1768 { 1769 char *cp; 1770 1771 if (argc == 1) { 1772 mapflag = 0; 1773 printf("Nmap off.\n"); 1774 code = mapflag; 1775 return; 1776 } 1777 if (argc < 3) { 1778 (void) strcat(line, " "); 1779 printf("(mapout) "); 1780 (void) gets(&line[strlen(line)]); 1781 makeargv(); 1782 argc = margc; 1783 argv = margv; 1784 } 1785 if (argc < 3) { 1786 printf("Usage: %s [mapin mapout]\n",argv[0]); 1787 code = -1; 1788 return; 1789 } 1790 mapflag = 1; 1791 code = 1; 1792 cp = index(altarg, ' '); 1793 if (proxy) { 1794 while(*++cp == ' '); 1795 altarg = cp; 1796 cp = index(altarg, ' '); 1797 } 1798 *cp = '\0'; 1799 (void) strncpy(mapin, altarg, MAXPATHLEN - 1); 1800 while (*++cp == ' '); 1801 (void) strncpy(mapout, cp, MAXPATHLEN - 1); 1802 } 1803 1804 char * 1805 domap(name) 1806 char *name; 1807 { 1808 static char new[MAXPATHLEN]; 1809 register char *cp1 = name, *cp2 = mapin; 1810 char *tp[9], *te[9]; 1811 int i, toks[9], toknum = 0, match = 1; 1812 1813 for (i=0; i < 9; ++i) { 1814 toks[i] = 0; 1815 } 1816 while (match && *cp1 && *cp2) { 1817 switch (*cp2) { 1818 case '\\': 1819 if (*++cp2 != *cp1) { 1820 match = 0; 1821 } 1822 break; 1823 case '$': 1824 if (*(cp2+1) >= '1' && (*cp2+1) <= '9') { 1825 if (*cp1 != *(++cp2+1)) { 1826 toks[toknum = *cp2 - '1']++; 1827 tp[toknum] = cp1; 1828 while (*++cp1 && *(cp2+1) 1829 != *cp1); 1830 te[toknum] = cp1; 1831 } 1832 cp2++; 1833 break; 1834 } 1835 /* FALLTHROUGH */ 1836 default: 1837 if (*cp2 != *cp1) { 1838 match = 0; 1839 } 1840 break; 1841 } 1842 if (match && *cp1) { 1843 cp1++; 1844 } 1845 if (match && *cp2) { 1846 cp2++; 1847 } 1848 } 1849 if (!match && *cp1) /* last token mismatch */ 1850 { 1851 toks[toknum] = 0; 1852 } 1853 cp1 = new; 1854 *cp1 = '\0'; 1855 cp2 = mapout; 1856 while (*cp2) { 1857 match = 0; 1858 switch (*cp2) { 1859 case '\\': 1860 if (*(cp2 + 1)) { 1861 *cp1++ = *++cp2; 1862 } 1863 break; 1864 case '[': 1865 LOOP: 1866 if (*++cp2 == '$' && isdigit(*(cp2+1))) { 1867 if (*++cp2 == '0') { 1868 char *cp3 = name; 1869 1870 while (*cp3) { 1871 *cp1++ = *cp3++; 1872 } 1873 match = 1; 1874 } 1875 else if (toks[toknum = *cp2 - '1']) { 1876 char *cp3 = tp[toknum]; 1877 1878 while (cp3 != te[toknum]) { 1879 *cp1++ = *cp3++; 1880 } 1881 match = 1; 1882 } 1883 } 1884 else { 1885 while (*cp2 && *cp2 != ',' && 1886 *cp2 != ']') { 1887 if (*cp2 == '\\') { 1888 cp2++; 1889 } 1890 else if (*cp2 == '$' && 1891 isdigit(*(cp2+1))) { 1892 if (*++cp2 == '0') { 1893 char *cp3 = name; 1894 1895 while (*cp3) { 1896 *cp1++ = *cp3++; 1897 } 1898 } 1899 else if (toks[toknum = 1900 *cp2 - '1']) { 1901 char *cp3=tp[toknum]; 1902 1903 while (cp3 != 1904 te[toknum]) { 1905 *cp1++ = *cp3++; 1906 } 1907 } 1908 } 1909 else if (*cp2) { 1910 *cp1++ = *cp2++; 1911 } 1912 } 1913 if (!*cp2) { 1914 printf("nmap: unbalanced brackets\n"); 1915 return(name); 1916 } 1917 match = 1; 1918 cp2--; 1919 } 1920 if (match) { 1921 while (*++cp2 && *cp2 != ']') { 1922 if (*cp2 == '\\' && *(cp2 + 1)) { 1923 cp2++; 1924 } 1925 } 1926 if (!*cp2) { 1927 printf("nmap: unbalanced brackets\n"); 1928 return(name); 1929 } 1930 break; 1931 } 1932 switch (*++cp2) { 1933 case ',': 1934 goto LOOP; 1935 case ']': 1936 break; 1937 default: 1938 cp2--; 1939 goto LOOP; 1940 } 1941 break; 1942 case '$': 1943 if (isdigit(*(cp2 + 1))) { 1944 if (*++cp2 == '0') { 1945 char *cp3 = name; 1946 1947 while (*cp3) { 1948 *cp1++ = *cp3++; 1949 } 1950 } 1951 else if (toks[toknum = *cp2 - '1']) { 1952 char *cp3 = tp[toknum]; 1953 1954 while (cp3 != te[toknum]) { 1955 *cp1++ = *cp3++; 1956 } 1957 } 1958 break; 1959 } 1960 /* intentional drop through */ 1961 default: 1962 *cp1++ = *cp2; 1963 break; 1964 } 1965 cp2++; 1966 } 1967 *cp1 = '\0'; 1968 if (!*new) { 1969 return(name); 1970 } 1971 return(new); 1972 } 1973 1974 setsunique() 1975 { 1976 sunique = !sunique; 1977 printf("Store unique %s.\n", onoff(sunique)); 1978 code = sunique; 1979 } 1980 1981 setrunique() 1982 { 1983 runique = !runique; 1984 printf("Receive unique %s.\n", onoff(runique)); 1985 code = runique; 1986 } 1987 1988 /* change directory to perent directory */ 1989 cdup() 1990 { 1991 if (command("CDUP") == ERROR && code == 500) { 1992 if (verbose) 1993 printf("CDUP command not recognized, trying XCUP\n"); 1994 (void) command("XCUP"); 1995 } 1996 } 1997 1998 /* restart transfer at specific point */ 1999 restart(argc, argv) 2000 int argc; 2001 char *argv[]; 2002 { 2003 extern long atol(); 2004 if (argc != 2) 2005 printf("restart: offset not specified\n"); 2006 else { 2007 restart_point = atol(argv[1]); 2008 printf("restarting at %ld. %s\n", restart_point, 2009 "execute get, put or append to initiate transfer"); 2010 } 2011 } 2012 2013 /* show remote system type */ 2014 syst() 2015 { 2016 (void) command("SYST"); 2017 } 2018 2019 macdef(argc, argv) 2020 int argc; 2021 char *argv[]; 2022 { 2023 char *tmp; 2024 int c; 2025 2026 if (macnum == 16) { 2027 printf("Limit of 16 macros have already been defined\n"); 2028 code = -1; 2029 return; 2030 } 2031 if (argc < 2) { 2032 (void) strcat(line, " "); 2033 printf("(macro name) "); 2034 (void) gets(&line[strlen(line)]); 2035 makeargv(); 2036 argc = margc; 2037 argv = margv; 2038 } 2039 if (argc != 2) { 2040 printf("Usage: %s macro_name\n",argv[0]); 2041 code = -1; 2042 return; 2043 } 2044 if (interactive) { 2045 printf("Enter macro line by line, terminating it with a null line\n"); 2046 } 2047 (void) strncpy(macros[macnum].mac_name, argv[1], 8); 2048 if (macnum == 0) { 2049 macros[macnum].mac_start = macbuf; 2050 } 2051 else { 2052 macros[macnum].mac_start = macros[macnum - 1].mac_end + 1; 2053 } 2054 tmp = macros[macnum].mac_start; 2055 while (tmp != macbuf+4096) { 2056 if ((c = getchar()) == EOF) { 2057 printf("macdef:end of file encountered\n"); 2058 code = -1; 2059 return; 2060 } 2061 if ((*tmp = c) == '\n') { 2062 if (tmp == macros[macnum].mac_start) { 2063 macros[macnum++].mac_end = tmp; 2064 code = 0; 2065 return; 2066 } 2067 if (*(tmp-1) == '\0') { 2068 macros[macnum++].mac_end = tmp - 1; 2069 code = 0; 2070 return; 2071 } 2072 *tmp = '\0'; 2073 } 2074 tmp++; 2075 } 2076 while (1) { 2077 while ((c = getchar()) != '\n' && c != EOF) 2078 /* LOOP */; 2079 if (c == EOF || getchar() == '\n') { 2080 printf("Macro not defined - 4k buffer exceeded\n"); 2081 code = -1; 2082 return; 2083 } 2084 } 2085 } 2086 2087 /* 2088 * get size of file on remote machine 2089 */ 2090 sizecmd(argc, argv) 2091 char *argv[]; 2092 { 2093 2094 if (argc < 2) { 2095 (void) strcat(line, " "); 2096 printf("(filename) "); 2097 (void) gets(&line[strlen(line)]); 2098 makeargv(); 2099 argc = margc; 2100 argv = margv; 2101 } 2102 if (argc < 2) { 2103 printf("usage:%s filename\n", argv[0]); 2104 code = -1; 2105 return; 2106 } 2107 (void) command("SIZE %s", argv[1]); 2108 } 2109 2110 /* 2111 * get last modification time of file on remote machine 2112 */ 2113 modtime(argc, argv) 2114 char *argv[]; 2115 { 2116 int overbose; 2117 2118 if (argc < 2) { 2119 (void) strcat(line, " "); 2120 printf("(filename) "); 2121 (void) gets(&line[strlen(line)]); 2122 makeargv(); 2123 argc = margc; 2124 argv = margv; 2125 } 2126 if (argc < 2) { 2127 printf("usage:%s filename\n", argv[0]); 2128 code = -1; 2129 return; 2130 } 2131 overbose = verbose; 2132 if (debug == 0) 2133 verbose = -1; 2134 if (command("MDTM %s", argv[1]) == COMPLETE) { 2135 int yy, mo, day, hour, min, sec; 2136 sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo, 2137 &day, &hour, &min, &sec); 2138 /* might want to print this in local time */ 2139 printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1], 2140 mo, day, yy, hour, min, sec); 2141 } else 2142 fputs(reply_string, stdout); 2143 verbose = overbose; 2144 } 2145 2146 /* 2147 * show status on reomte machine 2148 */ 2149 rmtstatus(argc, argv) 2150 char *argv[]; 2151 { 2152 (void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]); 2153 } 2154 2155 /* 2156 * get file if modtime is more recent than current file 2157 */ 2158 newer(argc, argv) 2159 char *argv[]; 2160 { 2161 if (getit(argc, argv, -1, "w")) 2162 printf("Local file \"%s\" is newer than remote file \"%s\"\n", 2163 argv[1], argv[2]); 2164 } 2165