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