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