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