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