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