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