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