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