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