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