|
|
1.1 root 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.8 (Berkeley) 6/29/88";
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: continue;
399: }
400: for (cpp = gargs; cpp && *cpp != NULL; cpp++) {
401: if (mflag && confirm(argv[0], *cpp)) {
402: tp = (ntflag) ? dotrans(*cpp) : *cpp;
403: tp = (mapflag) ? domap(tp) : tp;
404: sendrequest((sunique) ? "STOU" : "STOR",
405: *cpp, tp);
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: if (gargs != NULL)
417: blkfree(gargs);
418: }
419: (void) signal(SIGINT, oldintr);
420: mflag = 0;
421: }
422:
423: /*
424: * Receive one file.
425: */
426: get(argc, argv)
427: char *argv[];
428: {
429: int loc = 0;
430:
431: if (argc == 2) {
432: argc++;
433: argv[2] = argv[1];
434: loc++;
435: }
436: if (argc < 2) {
437: (void) strcat(line, " ");
438: printf("(remote-file) ");
439: (void) gets(&line[strlen(line)]);
440: makeargv();
441: argc = margc;
442: argv = margv;
443: }
444: if (argc < 2) {
445: usage:
446: printf("usage: %s remote-file [ local-file ]\n", argv[0]);
447: code = -1;
448: return;
449: }
450: if (argc < 3) {
451: (void) strcat(line, " ");
452: printf("(local-file) ");
453: (void) gets(&line[strlen(line)]);
454: makeargv();
455: argc = margc;
456: argv = margv;
457: }
458: if (argc < 3)
459: goto usage;
460: if (!globulize(&argv[2])) {
461: code = -1;
462: return;
463: }
464: if (loc && mcase) {
465: char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN];
466:
467: while (*tp && !islower(*tp)) {
468: tp++;
469: }
470: if (!*tp) {
471: tp = argv[2];
472: tp2 = tmpbuf;
473: while ((*tp2 = *tp) != NULL) {
474: if (isupper(*tp2)) {
475: *tp2 = 'a' + *tp2 - 'A';
476: }
477: tp++;
478: tp2++;
479: }
480: argv[2] = tmpbuf;
481: }
482: }
483: if (loc && ntflag) {
484: argv[2] = dotrans(argv[2]);
485: }
486: if (loc && mapflag) {
487: argv[2] = domap(argv[2]);
488: }
489: recvrequest("RETR", argv[2], argv[1], "w");
490: }
491:
492: mabort()
493: {
494: int ointer;
495: extern jmp_buf jabort;
496:
497: printf("\n");
498: (void) fflush(stdout);
499: if (mflag && fromatty) {
500: ointer = interactive;
501: interactive = 1;
502: if (confirm("Continue with", mname)) {
503: interactive = ointer;
504: longjmp(jabort,0);
505: }
506: interactive = ointer;
507: }
508: mflag = 0;
509: longjmp(jabort,0);
510: }
511:
512: /*
513: * Get multiple files.
514: */
515: mget(argc, argv)
516: char *argv[];
517: {
518: char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN];
519: int ointer, (*oldintr)(), mabort();
520: extern jmp_buf jabort;
521:
522: if (argc < 2) {
523: (void) strcat(line, " ");
524: printf("(remote-files) ");
525: (void) gets(&line[strlen(line)]);
526: makeargv();
527: argc = margc;
528: argv = margv;
529: }
530: if (argc < 2) {
531: printf("usage:%s remote-files\n", argv[0]);
532: code = -1;
533: return;
534: }
535: mname = argv[0];
536: mflag = 1;
537: oldintr = signal(SIGINT,mabort);
538: (void) setjmp(jabort);
539: while ((cp = remglob(argv,proxy)) != NULL) {
540: if (*cp == '\0') {
541: mflag = 0;
542: continue;
543: }
544: if (mflag && confirm(argv[0], cp)) {
545: tp = cp;
546: if (mcase) {
547: while (*tp && !islower(*tp)) {
548: tp++;
549: }
550: if (!*tp) {
551: tp = cp;
552: tp2 = tmpbuf;
553: while ((*tp2 = *tp) != NULL) {
554: if (isupper(*tp2)) {
555: *tp2 = 'a' + *tp2 - 'A';
556: }
557: tp++;
558: tp2++;
559: }
560: }
561: tp = tmpbuf;
562: }
563: if (ntflag) {
564: tp = dotrans(tp);
565: }
566: if (mapflag) {
567: tp = domap(tp);
568: }
569: recvrequest("RETR", tp, cp, "w");
570: if (!mflag && fromatty) {
571: ointer = interactive;
572: interactive = 1;
573: if (confirm("Continue with","mget")) {
574: mflag++;
575: }
576: interactive = ointer;
577: }
578: }
579: }
580: (void) signal(SIGINT,oldintr);
581: mflag = 0;
582: }
583:
584: char *
585: remglob(argv,doswitch)
586: char *argv[];
587: int doswitch;
588: {
589: char temp[16];
590: static char buf[MAXPATHLEN];
591: static FILE *ftemp = NULL;
592: static char **args;
593: int oldverbose, oldhash;
594: char *cp, *mode;
595:
596: if (!mflag) {
597: if (!doglob) {
598: args = NULL;
599: }
600: else {
601: if (ftemp) {
602: (void) fclose(ftemp);
603: ftemp = NULL;
604: }
605: }
606: return(NULL);
607: }
608: if (!doglob) {
609: if (args == NULL)
610: args = argv;
611: if ((cp = *++args) == NULL)
612: args = NULL;
613: return (cp);
614: }
615: if (ftemp == NULL) {
616: (void) strcpy(temp, "/tmp/ftpXXXXXX");
617: (void) mktemp(temp);
618: oldverbose = verbose, verbose = 0;
619: oldhash = hash, hash = 0;
620: if (doswitch) {
621: pswitch(!proxy);
622: }
623: for (mode = "w"; *++argv != NULL; mode = "a")
624: recvrequest ("NLST", temp, *argv, mode);
625: if (doswitch) {
626: pswitch(!proxy);
627: }
628: verbose = oldverbose; hash = oldhash;
629: ftemp = fopen(temp, "r");
630: (void) unlink(temp);
631: if (ftemp == NULL) {
632: printf("can't find list of remote files, oops\n");
633: return (NULL);
634: }
635: }
636: if (fgets(buf, sizeof (buf), ftemp) == NULL) {
637: (void) fclose(ftemp), ftemp = NULL;
638: return (NULL);
639: }
640: if ((cp = index(buf, '\n')) != NULL)
641: *cp = '\0';
642: return (buf);
643: }
644:
645: char *
646: onoff(bool)
647: int bool;
648: {
649:
650: return (bool ? "on" : "off");
651: }
652:
653: /*
654: * Show status.
655: */
656: /*ARGSUSED*/
657: status(argc, argv)
658: char *argv[];
659: {
660: int i;
661:
662: if (connected)
663: printf("Connected to %s.\n", hostname);
664: else
665: printf("Not connected.\n");
666: if (!proxy) {
667: pswitch(1);
668: if (connected) {
669: printf("Connected for proxy commands to %s.\n", hostname);
670: }
671: else {
672: printf("No proxy connection.\n");
673: }
674: pswitch(0);
675: }
676: printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n",
677: modename, typename, formname, structname);
678: printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n",
679: onoff(verbose), onoff(bell), onoff(interactive),
680: onoff(doglob));
681: printf("Store unique: %s; Receive unique: %s\n", onoff(sunique),
682: onoff(runique));
683: printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag));
684: if (ntflag) {
685: printf("Ntrans: (in) %s (out) %s\n", ntin,ntout);
686: }
687: else {
688: printf("Ntrans: off\n");
689: }
690: if (mapflag) {
691: printf("Nmap: (in) %s (out) %s\n", mapin, mapout);
692: }
693: else {
694: printf("Nmap: off\n");
695: }
696: printf("Hash mark printing: %s; Use of PORT cmds: %s\n",
697: onoff(hash), onoff(sendport));
698: if (macnum > 0) {
699: printf("Macros:\n");
700: for (i=0; i<macnum; i++) {
701: printf("\t%s\n",macros[i].mac_name);
702: }
703: }
704: code = 0;
705: }
706:
707: /*
708: * Set beep on cmd completed mode.
709: */
710: /*VARARGS*/
711: setbell()
712: {
713:
714: bell = !bell;
715: printf("Bell mode %s.\n", onoff(bell));
716: code = bell;
717: }
718:
719: /*
720: * Turn on packet tracing.
721: */
722: /*VARARGS*/
723: settrace()
724: {
725:
726: trace = !trace;
727: printf("Packet tracing %s.\n", onoff(trace));
728: code = trace;
729: }
730:
731: /*
732: * Toggle hash mark printing during transfers.
733: */
734: /*VARARGS*/
735: sethash()
736: {
737:
738: hash = !hash;
739: printf("Hash mark printing %s", onoff(hash));
740: code = hash;
741: if (hash)
742: printf(" (%d bytes/hash mark)", BUFSIZ);
743: printf(".\n");
744: }
745:
746: /*
747: * Turn on printing of server echo's.
748: */
749: /*VARARGS*/
750: setverbose()
751: {
752:
753: verbose = !verbose;
754: printf("Verbose mode %s.\n", onoff(verbose));
755: code = verbose;
756: }
757:
758: /*
759: * Toggle PORT cmd use before each data connection.
760: */
761: /*VARARGS*/
762: setport()
763: {
764:
765: sendport = !sendport;
766: printf("Use of PORT cmds %s.\n", onoff(sendport));
767: code = sendport;
768: }
769:
770: /*
771: * Turn on interactive prompting
772: * during mget, mput, and mdelete.
773: */
774: /*VARARGS*/
775: setprompt()
776: {
777:
778: interactive = !interactive;
779: printf("Interactive mode %s.\n", onoff(interactive));
780: code = interactive;
781: }
782:
783: /*
784: * Toggle metacharacter interpretation
785: * on local file names.
786: */
787: /*VARARGS*/
788: setglob()
789: {
790:
791: doglob = !doglob;
792: printf("Globbing %s.\n", onoff(doglob));
793: code = doglob;
794: }
795:
796: /*
797: * Set debugging mode on/off and/or
798: * set level of debugging.
799: */
800: /*VARARGS*/
801: setdebug(argc, argv)
802: char *argv[];
803: {
804: int val;
805:
806: if (argc > 1) {
807: val = atoi(argv[1]);
808: if (val < 0) {
809: printf("%s: bad debugging value.\n", argv[1]);
810: code = -1;
811: return;
812: }
813: } else
814: val = !debug;
815: debug = val;
816: if (debug)
817: options |= SO_DEBUG;
818: else
819: options &= ~SO_DEBUG;
820: printf("Debugging %s (debug=%d).\n", onoff(debug), debug);
821: code = debug > 0;
822: }
823:
824: /*
825: * Set current working directory
826: * on remote machine.
827: */
828: cd(argc, argv)
829: char *argv[];
830: {
831:
832: if (argc < 2) {
833: (void) strcat(line, " ");
834: printf("(remote-directory) ");
835: (void) gets(&line[strlen(line)]);
836: makeargv();
837: argc = margc;
838: argv = margv;
839: }
840: if (argc < 2) {
841: printf("usage:%s remote-directory\n", argv[0]);
842: code = -1;
843: return;
844: }
845: (void) command("CWD %s", argv[1]);
846: }
847:
848: /*
849: * Set current working directory
850: * on local machine.
851: */
852: lcd(argc, argv)
853: char *argv[];
854: {
855: char buf[MAXPATHLEN];
856:
857: if (argc < 2)
858: argc++, argv[1] = home;
859: if (argc != 2) {
860: printf("usage:%s local-directory\n", argv[0]);
861: code = -1;
862: return;
863: }
864: if (!globulize(&argv[1])) {
865: code = -1;
866: return;
867: }
868: if (chdir(argv[1]) < 0) {
869: perror(argv[1]);
870: code = -1;
871: return;
872: }
873: printf("Local directory now %s\n", getwd(buf));
874: code = 0;
875: }
876:
877: /*
878: * Delete a single file.
879: */
880: delete(argc, argv)
881: char *argv[];
882: {
883:
884: if (argc < 2) {
885: (void) strcat(line, " ");
886: printf("(remote-file) ");
887: (void) gets(&line[strlen(line)]);
888: makeargv();
889: argc = margc;
890: argv = margv;
891: }
892: if (argc < 2) {
893: printf("usage:%s remote-file\n", argv[0]);
894: code = -1;
895: return;
896: }
897: (void) command("DELE %s", argv[1]);
898: }
899:
900: /*
901: * Delete multiple files.
902: */
903: mdelete(argc, argv)
904: char *argv[];
905: {
906: char *cp;
907: int ointer, (*oldintr)(), mabort();
908: extern jmp_buf jabort;
909:
910: if (argc < 2) {
911: (void) strcat(line, " ");
912: printf("(remote-files) ");
913: (void) gets(&line[strlen(line)]);
914: makeargv();
915: argc = margc;
916: argv = margv;
917: }
918: if (argc < 2) {
919: printf("usage:%s remote-files\n", argv[0]);
920: code = -1;
921: return;
922: }
923: mname = argv[0];
924: mflag = 1;
925: oldintr = signal(SIGINT, mabort);
926: (void) setjmp(jabort);
927: while ((cp = remglob(argv,0)) != NULL) {
928: if (*cp == '\0') {
929: mflag = 0;
930: continue;
931: }
932: if (mflag && confirm(argv[0], cp)) {
933: (void) command("DELE %s", cp);
934: if (!mflag && fromatty) {
935: ointer = interactive;
936: interactive = 1;
937: if (confirm("Continue with", "mdelete")) {
938: mflag++;
939: }
940: interactive = ointer;
941: }
942: }
943: }
944: (void) signal(SIGINT, oldintr);
945: mflag = 0;
946: }
947:
948: /*
949: * Rename a remote file.
950: */
951: renamefile(argc, argv)
952: char *argv[];
953: {
954:
955: if (argc < 2) {
956: (void) strcat(line, " ");
957: printf("(from-name) ");
958: (void) gets(&line[strlen(line)]);
959: makeargv();
960: argc = margc;
961: argv = margv;
962: }
963: if (argc < 2) {
964: usage:
965: printf("%s from-name to-name\n", argv[0]);
966: code = -1;
967: return;
968: }
969: if (argc < 3) {
970: (void) strcat(line, " ");
971: printf("(to-name) ");
972: (void) gets(&line[strlen(line)]);
973: makeargv();
974: argc = margc;
975: argv = margv;
976: }
977: if (argc < 3)
978: goto usage;
979: if (command("RNFR %s", argv[1]) == CONTINUE)
980: (void) command("RNTO %s", argv[2]);
981: }
982:
983: /*
984: * Get a directory listing
985: * of remote files.
986: */
987: ls(argc, argv)
988: char *argv[];
989: {
990: char *cmd;
991:
992: if (argc < 2)
993: argc++, argv[1] = NULL;
994: if (argc < 3)
995: argc++, argv[2] = "-";
996: if (argc > 3) {
997: printf("usage: %s remote-directory local-file\n", argv[0]);
998: code = -1;
999: return;
1000: }
1001: cmd = argv[0][0] == 'l' ? "NLST" : "LIST";
1002: if (strcmp(argv[2], "-") && !globulize(&argv[2])) {
1003: code = -1;
1004: return;
1005: }
1006: if (strcmp(argv[2], "-") && *argv[2] != '|')
1007: if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) {
1008: code = -1;
1009: return;
1010: }
1011: recvrequest(cmd, argv[2], argv[1], "w");
1012: }
1013:
1014: /*
1015: * Get a directory listing
1016: * of multiple remote files.
1017: */
1018: mls(argc, argv)
1019: char *argv[];
1020: {
1021: char *cmd, mode[1], *dest;
1022: int ointer, i, (*oldintr)(), mabort();
1023: extern jmp_buf jabort;
1024:
1025: if (argc < 2) {
1026: (void) strcat(line, " ");
1027: printf("(remote-files) ");
1028: (void) gets(&line[strlen(line)]);
1029: makeargv();
1030: argc = margc;
1031: argv = margv;
1032: }
1033: if (argc < 3) {
1034: (void) strcat(line, " ");
1035: printf("(local-file) ");
1036: (void) gets(&line[strlen(line)]);
1037: makeargv();
1038: argc = margc;
1039: argv = margv;
1040: }
1041: if (argc < 3) {
1042: printf("usage:%s remote-files local-file\n", argv[0]);
1043: code = -1;
1044: return;
1045: }
1046: dest = argv[argc - 1];
1047: argv[argc - 1] = NULL;
1048: if (strcmp(dest, "-") && *dest != '|')
1049: if (!globulize(&dest) || !confirm("output to local-file:", dest)) {
1050: code = -1;
1051: return;
1052: }
1053: cmd = argv[0][1] == 'l' ? "NLST" : "LIST";
1054: mname = argv[0];
1055: mflag = 1;
1056: oldintr = signal(SIGINT, mabort);
1057: (void) setjmp(jabort);
1058: for (i = 1; mflag && i < argc-1; ++i) {
1059: *mode = (i == 1) ? 'w' : 'a';
1060: recvrequest(cmd, dest, argv[i], mode);
1061: if (!mflag && fromatty) {
1062: ointer = interactive;
1063: interactive = 1;
1064: if (confirm("Continue with", argv[0])) {
1065: mflag ++;
1066: }
1067: interactive = ointer;
1068: }
1069: }
1070: (void) signal(SIGINT, oldintr);
1071: mflag = 0;
1072: }
1073:
1074: /*
1075: * Do a shell escape
1076: */
1077: /*ARGSUSED*/
1078: shell(argc, argv)
1079: char *argv[];
1080: {
1081: int pid, (*old1)(), (*old2)();
1082: char shellnam[40], *shell, *namep;
1083: union wait status;
1084:
1085: old1 = signal (SIGINT, SIG_IGN);
1086: old2 = signal (SIGQUIT, SIG_IGN);
1087: if ((pid = fork()) == 0) {
1088: for (pid = 3; pid < 20; pid++)
1089: (void) close(pid);
1090: (void) signal(SIGINT, SIG_DFL);
1091: (void) signal(SIGQUIT, SIG_DFL);
1092: shell = getenv("SHELL");
1093: if (shell == NULL)
1094: shell = "/bin/sh";
1095: namep = rindex(shell,'/');
1096: if (namep == NULL)
1097: namep = shell;
1098: (void) strcpy(shellnam,"-");
1099: (void) strcat(shellnam, ++namep);
1100: if (strcmp(namep, "sh") != 0)
1101: shellnam[0] = '+';
1102: if (debug) {
1103: printf ("%s\n", shell);
1104: (void) fflush (stdout);
1105: }
1106: if (argc > 1) {
1107: execl(shell,shellnam,"-c",altarg,(char *)0);
1108: }
1109: else {
1110: execl(shell,shellnam,(char *)0);
1111: }
1112: perror(shell);
1113: code = -1;
1114: exit(1);
1115: }
1116: if (pid > 0)
1117: while (wait(&status) != pid)
1118: ;
1119: (void) signal(SIGINT, old1);
1120: (void) signal(SIGQUIT, old2);
1121: if (pid == -1) {
1122: perror("Try again later");
1123: code = -1;
1124: }
1125: else {
1126: code = 0;
1127: }
1128: return (0);
1129: }
1130:
1131: /*
1132: * Send new user information (re-login)
1133: */
1134: user(argc, argv)
1135: int argc;
1136: char **argv;
1137: {
1138: char acct[80], *mygetpass();
1139: int n, aflag = 0;
1140:
1141: if (argc < 2) {
1142: (void) strcat(line, " ");
1143: printf("(username) ");
1144: (void) gets(&line[strlen(line)]);
1145: makeargv();
1146: argc = margc;
1147: argv = margv;
1148: }
1149: if (argc > 4) {
1150: printf("usage: %s username [password] [account]\n", argv[0]);
1151: code = -1;
1152: return (0);
1153: }
1154: n = command("USER %s", argv[1]);
1155: if (n == CONTINUE) {
1156: if (argc < 3 )
1157: argv[2] = mygetpass("Password: "), argc++;
1158: n = command("PASS %s", argv[2]);
1159: }
1160: if (n == CONTINUE) {
1161: if (argc < 4) {
1162: printf("Account: "); (void) fflush(stdout);
1163: (void) fgets(acct, sizeof(acct) - 1, stdin);
1164: acct[strlen(acct) - 1] = '\0';
1165: argv[3] = acct; argc++;
1166: }
1167: n = command("ACCT %s", argv[3]);
1168: aflag++;
1169: }
1170: if (n != COMPLETE) {
1171: fprintf(stdout, "Login failed.\n");
1172: return (0);
1173: }
1174: if (!aflag && argc == 4) {
1175: (void) command("ACCT %s", argv[3]);
1176: }
1177: return (1);
1178: }
1179:
1180: /*
1181: * Print working directory.
1182: */
1183: /*VARARGS*/
1184: pwd()
1185: {
1186:
1187: (void) command("PWD");
1188: }
1189:
1190: /*
1191: * Make a directory.
1192: */
1193: makedir(argc, argv)
1194: char *argv[];
1195: {
1196:
1197: if (argc < 2) {
1198: (void) strcat(line, " ");
1199: printf("(directory-name) ");
1200: (void) gets(&line[strlen(line)]);
1201: makeargv();
1202: argc = margc;
1203: argv = margv;
1204: }
1205: if (argc < 2) {
1206: printf("usage: %s directory-name\n", argv[0]);
1207: code = -1;
1208: return;
1209: }
1210: (void) command("MKD %s", argv[1]);
1211: }
1212:
1213: /*
1214: * Remove a directory.
1215: */
1216: removedir(argc, argv)
1217: char *argv[];
1218: {
1219:
1220: if (argc < 2) {
1221: (void) strcat(line, " ");
1222: printf("(directory-name) ");
1223: (void) gets(&line[strlen(line)]);
1224: makeargv();
1225: argc = margc;
1226: argv = margv;
1227: }
1228: if (argc < 2) {
1229: printf("usage: %s directory-name\n", argv[0]);
1230: code = -1;
1231: return;
1232: }
1233: (void) command("RMD %s", argv[1]);
1234: }
1235:
1236: /*
1237: * Send a line, verbatim, to the remote machine.
1238: */
1239: quote(argc, argv)
1240: char *argv[];
1241: {
1242: int i;
1243: char buf[BUFSIZ];
1244:
1245: if (argc < 2) {
1246: (void) strcat(line, " ");
1247: printf("(command line to send) ");
1248: (void) gets(&line[strlen(line)]);
1249: makeargv();
1250: argc = margc;
1251: argv = margv;
1252: }
1253: if (argc < 2) {
1254: printf("usage: %s line-to-send\n", argv[0]);
1255: code = -1;
1256: return;
1257: }
1258: (void) strcpy(buf, argv[1]);
1259: for (i = 2; i < argc; i++) {
1260: (void) strcat(buf, " ");
1261: (void) strcat(buf, argv[i]);
1262: }
1263: if (command(buf) == PRELIM) {
1264: while (getreply(0) == PRELIM);
1265: }
1266: }
1267:
1268: /*
1269: * Ask the other side for help.
1270: */
1271: rmthelp(argc, argv)
1272: char *argv[];
1273: {
1274: int oldverbose = verbose;
1275:
1276: verbose = 1;
1277: (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
1278: verbose = oldverbose;
1279: }
1280:
1281: /*
1282: * Terminate session and exit.
1283: */
1284: /*VARARGS*/
1285: quit()
1286: {
1287:
1288: if (connected)
1289: disconnect();
1290: pswitch(1);
1291: if (connected) {
1292: disconnect();
1293: }
1294: exit(0);
1295: }
1296:
1297: /*
1298: * Terminate session, but don't exit.
1299: */
1300: disconnect()
1301: {
1302: extern FILE *cout;
1303: extern int data;
1304:
1305: if (!connected)
1306: return;
1307: (void) command("QUIT");
1308: if (cout) {
1309: (void) fclose(cout);
1310: }
1311: cout = NULL;
1312: connected = 0;
1313: data = -1;
1314: if (!proxy) {
1315: macnum = 0;
1316: }
1317: }
1318:
1319: confirm(cmd, file)
1320: char *cmd, *file;
1321: {
1322: char line[BUFSIZ];
1323:
1324: if (!interactive)
1325: return (1);
1326: printf("%s %s? ", cmd, file);
1327: (void) fflush(stdout);
1328: (void) gets(line);
1329: return (*line != 'n' && *line != 'N');
1330: }
1331:
1332: fatal(msg)
1333: char *msg;
1334: {
1335:
1336: fprintf(stderr, "ftp: %s\n", msg);
1337: exit(1);
1338: }
1339:
1340: /*
1341: * Glob a local file name specification with
1342: * the expectation of a single return value.
1343: * Can't control multiple values being expanded
1344: * from the expression, we return only the first.
1345: */
1346: globulize(cpp)
1347: char **cpp;
1348: {
1349: char **globbed;
1350:
1351: if (!doglob)
1352: return (1);
1353: globbed = glob(*cpp);
1354: if (globerr != NULL) {
1355: printf("%s: %s\n", *cpp, globerr);
1356: if (globbed)
1357: blkfree(globbed);
1358: return (0);
1359: }
1360: if (globbed) {
1361: *cpp = *globbed++;
1362: /* don't waste too much memory */
1363: if (*globbed)
1364: blkfree(globbed);
1365: }
1366: return (1);
1367: }
1368:
1369: account(argc,argv)
1370:
1371: int argc;
1372: char **argv;
1373: {
1374: char acct[50], *mygetpass(), *ap;
1375:
1376: if (argc > 1) {
1377: ++argv;
1378: --argc;
1379: (void) strncpy(acct,*argv,49);
1380: acct[50] = '\0';
1381: while (argc > 1) {
1382: --argc;
1383: ++argv;
1384: (void) strncat(acct,*argv, 49-strlen(acct));
1385: }
1386: ap = acct;
1387: }
1388: else {
1389: ap = mygetpass("Account:");
1390: }
1391: (void) command("ACCT %s", ap);
1392: }
1393:
1394: jmp_buf abortprox;
1395:
1396: proxabort()
1397: {
1398: extern int proxy;
1399:
1400: if (!proxy) {
1401: pswitch(1);
1402: }
1403: if (connected) {
1404: proxflag = 1;
1405: }
1406: else {
1407: proxflag = 0;
1408: }
1409: pswitch(0);
1410: longjmp(abortprox,1);
1411: }
1412:
1413: doproxy(argc,argv)
1414: int argc;
1415: char *argv[];
1416: {
1417: int (*oldintr)(), proxabort();
1418: register struct cmd *c;
1419: struct cmd *getcmd();
1420: extern struct cmd cmdtab[];
1421: extern jmp_buf abortprox;
1422:
1423: if (argc < 2) {
1424: (void) strcat(line, " ");
1425: printf("(command) ");
1426: (void) gets(&line[strlen(line)]);
1427: makeargv();
1428: argc = margc;
1429: argv = margv;
1430: }
1431: if (argc < 2) {
1432: printf("usage:%s command\n", argv[0]);
1433: code = -1;
1434: return;
1435: }
1436: c = getcmd(argv[1]);
1437: if (c == (struct cmd *) -1) {
1438: printf("?Ambiguous command\n");
1439: (void) fflush(stdout);
1440: code = -1;
1441: return;
1442: }
1443: if (c == 0) {
1444: printf("?Invalid command\n");
1445: (void) fflush(stdout);
1446: code = -1;
1447: return;
1448: }
1449: if (!c->c_proxy) {
1450: printf("?Invalid proxy command\n");
1451: (void) fflush(stdout);
1452: code = -1;
1453: return;
1454: }
1455: if (setjmp(abortprox)) {
1456: code = -1;
1457: return;
1458: }
1459: oldintr = signal(SIGINT, proxabort);
1460: pswitch(1);
1461: if (c->c_conn && !connected) {
1462: printf("Not connected\n");
1463: (void) fflush(stdout);
1464: pswitch(0);
1465: (void) signal(SIGINT, oldintr);
1466: code = -1;
1467: return;
1468: }
1469: (*c->c_handler)(argc-1, argv+1);
1470: if (connected) {
1471: proxflag = 1;
1472: }
1473: else {
1474: proxflag = 0;
1475: }
1476: pswitch(0);
1477: (void) signal(SIGINT, oldintr);
1478: }
1479:
1480: setcase()
1481: {
1482: mcase = !mcase;
1483: printf("Case mapping %s.\n", onoff(mcase));
1484: code = mcase;
1485: }
1486:
1487: setcr()
1488: {
1489: crflag = !crflag;
1490: printf("Carriage Return stripping %s.\n", onoff(crflag));
1491: code = crflag;
1492: }
1493:
1494: setntrans(argc,argv)
1495: int argc;
1496: char *argv[];
1497: {
1498: if (argc == 1) {
1499: ntflag = 0;
1500: printf("Ntrans off.\n");
1501: code = ntflag;
1502: return;
1503: }
1504: ntflag++;
1505: code = ntflag;
1506: (void) strncpy(ntin, argv[1], 16);
1507: ntin[16] = '\0';
1508: if (argc == 2) {
1509: ntout[0] = '\0';
1510: return;
1511: }
1512: (void) strncpy(ntout, argv[2], 16);
1513: ntout[16] = '\0';
1514: }
1515:
1516: char *
1517: dotrans(name)
1518: char *name;
1519: {
1520: static char new[MAXPATHLEN];
1521: char *cp1, *cp2 = new;
1522: register int i, ostop, found;
1523:
1524: for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++);
1525: for (cp1 = name; *cp1; cp1++) {
1526: found = 0;
1527: for (i = 0; *(ntin + i) && i < 16; i++) {
1528: if (*cp1 == *(ntin + i)) {
1529: found++;
1530: if (i < ostop) {
1531: *cp2++ = *(ntout + i);
1532: }
1533: break;
1534: }
1535: }
1536: if (!found) {
1537: *cp2++ = *cp1;
1538: }
1539: }
1540: *cp2 = '\0';
1541: return(new);
1542: }
1543:
1544: setnmap(argc, argv)
1545: int argc;
1546: char *argv[];
1547: {
1548: char *cp;
1549:
1550: if (argc == 1) {
1551: mapflag = 0;
1552: printf("Nmap off.\n");
1553: code = mapflag;
1554: return;
1555: }
1556: if (argc < 3) {
1557: (void) strcat(line, " ");
1558: printf("(mapout) ");
1559: (void) gets(&line[strlen(line)]);
1560: makeargv();
1561: argc = margc;
1562: argv = margv;
1563: }
1564: if (argc < 3) {
1565: printf("Usage: %s [mapin mapout]\n",argv[0]);
1566: code = -1;
1567: return;
1568: }
1569: mapflag = 1;
1570: code = 1;
1571: cp = index(altarg, ' ');
1572: if (proxy) {
1573: while(*++cp == ' ');
1574: altarg = cp;
1575: cp = index(altarg, ' ');
1576: }
1577: *cp = '\0';
1578: (void) strncpy(mapin, altarg, MAXPATHLEN - 1);
1579: while (*++cp == ' ');
1580: (void) strncpy(mapout, cp, MAXPATHLEN - 1);
1581: }
1582:
1583: char *
1584: domap(name)
1585: char *name;
1586: {
1587: static char new[MAXPATHLEN];
1588: register char *cp1 = name, *cp2 = mapin;
1589: char *tp[9], *te[9];
1590: int i, toks[9], toknum, match = 1;
1591:
1592: for (i=0; i < 9; ++i) {
1593: toks[i] = 0;
1594: }
1595: while (match && *cp1 && *cp2) {
1596: switch (*cp2) {
1597: case '\\':
1598: if (*++cp2 != *cp1) {
1599: match = 0;
1600: }
1601: break;
1602: case '$':
1603: if (*(cp2+1) >= '1' && (*cp2+1) <= '9') {
1604: if (*cp1 != *(++cp2+1)) {
1605: toks[toknum = *cp2 - '1']++;
1606: tp[toknum] = cp1;
1607: while (*++cp1 && *(cp2+1)
1608: != *cp1);
1609: te[toknum] = cp1;
1610: }
1611: cp2++;
1612: break;
1613: }
1614: /* intentional drop through */
1615: default:
1616: if (*cp2 != *cp1) {
1617: match = 0;
1618: }
1619: break;
1620: }
1621: if (*cp1) {
1622: cp1++;
1623: }
1624: if (*cp2) {
1625: cp2++;
1626: }
1627: }
1628: cp1 = new;
1629: *cp1 = '\0';
1630: cp2 = mapout;
1631: while (*cp2) {
1632: match = 0;
1633: switch (*cp2) {
1634: case '\\':
1635: if (*(cp2 + 1)) {
1636: *cp1++ = *++cp2;
1637: }
1638: break;
1639: case '[':
1640: LOOP:
1641: if (*++cp2 == '$' && isdigit(*(cp2+1))) {
1642: if (*++cp2 == '0') {
1643: char *cp3 = name;
1644:
1645: while (*cp3) {
1646: *cp1++ = *cp3++;
1647: }
1648: match = 1;
1649: }
1650: else if (toks[toknum = *cp2 - '1']) {
1651: char *cp3 = tp[toknum];
1652:
1653: while (cp3 != te[toknum]) {
1654: *cp1++ = *cp3++;
1655: }
1656: match = 1;
1657: }
1658: }
1659: else {
1660: while (*cp2 && *cp2 != ',' &&
1661: *cp2 != ']') {
1662: if (*cp2 == '\\') {
1663: cp2++;
1664: }
1665: else if (*cp2 == '$' &&
1666: isdigit(*(cp2+1))) {
1667: if (*++cp2 == '0') {
1668: char *cp3 = name;
1669:
1670: while (*cp3) {
1671: *cp1++ = *cp3++;
1672: }
1673: }
1674: else if (toks[toknum =
1675: *cp2 - '1']) {
1676: char *cp3=tp[toknum];
1677:
1678: while (cp3 !=
1679: te[toknum]) {
1680: *cp1++ = *cp3++;
1681: }
1682: }
1683: }
1684: else if (*cp2) {
1685: *cp1++ = *cp2++;
1686: }
1687: }
1688: if (!*cp2) {
1689: printf("nmap: unbalanced brackets\n");
1690: return(name);
1691: }
1692: match = 1;
1693: cp2--;
1694: }
1695: if (match) {
1696: while (*++cp2 && *cp2 != ']') {
1697: if (*cp2 == '\\' && *(cp2 + 1)) {
1698: cp2++;
1699: }
1700: }
1701: if (!*cp2) {
1702: printf("nmap: unbalanced brackets\n");
1703: return(name);
1704: }
1705: break;
1706: }
1707: switch (*++cp2) {
1708: case ',':
1709: goto LOOP;
1710: case ']':
1711: break;
1712: default:
1713: cp2--;
1714: goto LOOP;
1715: }
1716: break;
1717: case '$':
1718: if (isdigit(*(cp2 + 1))) {
1719: if (*++cp2 == '0') {
1720: char *cp3 = name;
1721:
1722: while (*cp3) {
1723: *cp1++ = *cp3++;
1724: }
1725: }
1726: else if (toks[toknum = *cp2 - '1']) {
1727: char *cp3 = tp[toknum];
1728:
1729: while (cp3 != te[toknum]) {
1730: *cp1++ = *cp3++;
1731: }
1732: }
1733: break;
1734: }
1735: /* intentional drop through */
1736: default:
1737: *cp1++ = *cp2;
1738: break;
1739: }
1740: cp2++;
1741: }
1742: *cp1 = '\0';
1743: if (!*new) {
1744: return(name);
1745: }
1746: return(new);
1747: }
1748:
1749: setsunique()
1750: {
1751: sunique = !sunique;
1752: printf("Store unique %s.\n", onoff(sunique));
1753: code = sunique;
1754: }
1755:
1756: setrunique()
1757: {
1758: runique = !runique;
1759: printf("Receive unique %s.\n", onoff(runique));
1760: code = runique;
1761: }
1762:
1763: /* change directory to perent directory */
1764: cdup()
1765: {
1766: (void) command("CDUP");
1767: }
1768:
1769: macdef(argc, argv)
1770: int argc;
1771: char *argv[];
1772: {
1773: char *tmp;
1774: int c;
1775:
1776: if (macnum == 16) {
1777: printf("Limit of 16 macros have already been defined\n");
1778: code = -1;
1779: return;
1780: }
1781: if (argc < 2) {
1782: (void) strcat(line, " ");
1783: printf("(macro name) ");
1784: (void) gets(&line[strlen(line)]);
1785: makeargv();
1786: argc = margc;
1787: argv = margv;
1788: }
1789: if (argc != 2) {
1790: printf("Usage: %s macro_name\n",argv[0]);
1791: code = -1;
1792: return;
1793: }
1794: if (interactive) {
1795: printf("Enter macro line by line, terminating it with a null line\n");
1796: }
1797: (void) strncpy(macros[macnum].mac_name, argv[1], 8);
1798: if (macnum == 0) {
1799: macros[macnum].mac_start = macbuf;
1800: }
1801: else {
1802: macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
1803: }
1804: tmp = macros[macnum].mac_start;
1805: while (tmp != macbuf+4096) {
1806: if ((c = getchar()) == EOF) {
1807: printf("macdef:end of file encountered\n");
1808: code = -1;
1809: return;
1810: }
1811: if ((*tmp = c) == '\n') {
1812: if (tmp == macros[macnum].mac_start) {
1813: macros[macnum++].mac_end = tmp;
1814: code = 0;
1815: return;
1816: }
1817: if (*(tmp-1) == '\0') {
1818: macros[macnum++].mac_end = tmp - 1;
1819: code = 0;
1820: return;
1821: }
1822: *tmp = '\0';
1823: }
1824: tmp++;
1825: }
1826: while (1) {
1827: while ((c = getchar()) != '\n' && c != EOF);
1828: if (c == EOF || getchar() == '\n') {
1829: printf("Macro not defined - 4k buffer exceeded\n");
1830: code = -1;
1831: return;
1832: }
1833: }
1834: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.