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