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