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