|
|
1.1 root 1: #ifndef lint
2: static char RCSid[] = "$Header: cmds.c,v 2.0 85/11/21 07:22:41 jqj Exp $";
3: #endif
4: /* $Log: cmds.c,v $
5: * Revision 2.0 85/11/21 07:22:41 jqj
6: * 4.3BSD standard release
7: *
8: * Revision 1.2 85/10/30 08:06:37 root
9: * if prompt=off but verbose=on, print the name of each file during
10: * multiplefile transfers.
11: *
12: * Revision 1.1 85/05/27 06:30:51 jqj
13: * Initial revision
14: *
15: * based on Berkeley tcp/ftp
16: */
17: /* static char sccsid[] = "@(#)cmds.c 4.9 (Berkeley) 7/26/83"; */
18:
19: /*
20: * FTP User Program -- Command Routines.
21: */
22: #include <sys/param.h>
23: #include <sys/stat.h>
24: #include <sys/socket.h>
25:
26: #include <signal.h>
27: #include <stdio.h>
28: #include <errno.h>
29:
30: #include "ftp_var.h"
31:
32: extern char *globerr;
33: extern char **glob();
34: extern char *home;
35: extern short gflag;
36: extern char *remglob();
37: extern char *getenv();
38: extern char *index();
39: extern char *rindex();
40:
41: /*
42: * Connect to peer server and
43: * auto-login, if possible.
44: */
45: setpeer(argc, argv)
46: int argc;
47: char *argv[];
48: {
49: CourierConnection *hookup();
50:
51: if (connected != (CourierConnection*)0) {
52: printf("Already connected to %s, use disconnect first.\n",
53: hostname);
54: return;
55: }
56: if (argc < 2) {
57: strcat(line, " ");
58: printf("(to) ");
59: gets(&line[strlen(line)]);
60: makeargv();
61: argc = margc;
62: argv = margv;
63: }
64: if (argc > 2) {
65: printf("usage: %s fileservice-name\n", argv[0]);
66: return;
67: }
68: connected = hookup(argv[1]);
69: if (connected != (CourierConnection*)0) {
70: if (autologin) {
71: char *pwd, name[128], *getXNSpass();
72: printf("XNS UserName: ");
73: gets(name);
74: pwd = getXNSpass("Password:");
75: login(name,pwd);
76: }
77: }
78: }
79:
80: struct types {
81: char *t_name;
82: char *t_mode;
83: int t_type;
84: char *t_arg;
85: } types[] = {
86: { "ascii", "A", TYPE_A, 0 },
87: { "binary", "I", TYPE_I, 0 },
88: { "image", "I", TYPE_I, 0 },
89: /* { "ebcdic", "E", TYPE_E, 0 }, */
90: /* { "tenex", "L", TYPE_L, bytename }, */
91: 0
92: };
93:
94: /*
95: * Set transfer type.
96: */
97: settype(argc, argv)
98: char *argv[];
99: {
100: register struct types *p;
101: int comret;
102:
103: if (argc > 2) {
104: char *sep;
105:
106: printf("usage: %s [", argv[0]);
107: sep = " ";
108: for (p = types; p->t_name; p++) {
109: printf("%s%s", sep, p->t_name);
110: if (*sep == ' ')
111: sep = " | ";
112: }
113: printf(" ]\n");
114: return;
115: }
116: if (argc < 2) {
117: printf("Using %s mode to transfer files.\n", typename);
118: return;
119: }
120: for (p = types; p->t_name; p++)
121: if (strcmp(argv[1], p->t_name) == 0)
122: break;
123: if (p->t_name == 0) {
124: printf("%s: unknown mode\n", argv[1]);
125: return;
126: }
127: strcpy(typename, p->t_name);
128: typevalue = p->t_type;
129: }
130:
131: /*
132: * Set binary transfer type.
133: */
134: /*VARARGS*/
135: setbinary()
136: {
137:
138: call(settype, "type", "binary", 0);
139: }
140:
141: /*
142: * Set ascii transfer type.
143: */
144: /*VARARGS*/
145: setascii()
146: {
147:
148: call(settype, "type", "ascii", 0);
149: }
150:
151: /*
152: * Set tenex transfer type.
153: */
154: /*VARARGS*/
155: settenex()
156: {
157:
158: call(settype, "type", "tenex", 0);
159: }
160:
161: /*
162: * Set ebcdic transfer type.
163: */
164: /*VARARGS*/
165: setebcdic()
166: {
167:
168: call(settype, "type", "ebcdic", 0);
169: }
170:
171: /*
172: * Set file transfer mode.
173: */
174: setmode(argc, argv)
175: char *argv[];
176: {
177:
178: printf("We only support %s mode, sorry.\n", modename);
179: }
180:
181: /*
182: * Set file transfer format.
183: */
184: setform(argc, argv)
185: char *argv[];
186: {
187:
188: printf("We only support %s format, sorry.\n", formname);
189: }
190:
191: /*
192: * Set file transfer structure.
193: */
194: setstruct(argc, argv)
195: char *argv[];
196: {
197:
198: printf("We only support %s structure, sorry.\n", structname);
199: }
200:
201: put(argc, argv)
202: int argc;
203: char *argv[];
204: {
205: char *cmd;
206:
207: if (argc == 2)
208: argc++, argv[2] = argv[1];
209: if (argc < 2) {
210: strcat(line, " ");
211: printf("(local-file) ");
212: gets(&line[strlen(line)]);
213: makeargv();
214: argc = margc;
215: argv = margv;
216: }
217: if (argc < 2) {
218: usage:
219: printf("%s local-file remote-file\n", argv[0]);
220: return;
221: }
222: if (argc < 3) {
223: strcat(line, " ");
224: printf("(remote-file) ");
225: gets(&line[strlen(line)]);
226: makeargv();
227: argc = margc;
228: argv = margv;
229: }
230: if (argc < 3)
231: goto usage;
232: if (!globulize(&argv[1]))
233: return;
234: cmd = (argv[0][0] == 'a') ? "APPE" : "STOR";
235: sendrequest(cmd, argv[1], argv[2]);
236:
237: }
238:
239: /*
240: * Send multiple files.
241: */
242: mput(argc, argv)
243: char *argv[];
244: {
245: register int i;
246:
247: if (argc < 2) {
248: strcat(line, " ");
249: printf("(local-files) ");
250: gets(&line[strlen(line)]);
251: makeargv();
252: argc = margc;
253: argv = margv;
254: }
255: if (argc < 2) {
256: printf("%s local-files\n", argv[0]);
257: return;
258: }
259: for (i = 1; i < argc; i++) {
260: register char **cpp, **gargs;
261:
262: if (!doglob) {
263: if (confirm(argv[0], argv[i]))
264: sendrequest("STOR", argv[i], argv[i]);
265: continue;
266: }
267: gargs = glob(argv[i]);
268: if (globerr != NULL) {
269: printf("%s\n", globerr);
270: if (gargs)
271: blkfree(gargs);
272: continue;
273: }
274: for (cpp = gargs; cpp && *cpp != NULL; cpp++)
275: if (confirm(argv[0], *cpp))
276: sendrequest("STOR", *cpp, *cpp);
277: if (gargs != NULL)
278: blkfree(gargs);
279: }
280: }
281:
282: /*
283: * Receive one file.
284: */
285: get(argc, argv)
286: char *argv[];
287: {
288:
289: if (argc == 2)
290: argc++, argv[2] = argv[1];
291: if (argc < 2) {
292: strcat(line, " ");
293: printf("(remote-file) ");
294: gets(&line[strlen(line)]);
295: makeargv();
296: argc = margc;
297: argv = margv;
298: }
299: if (argc < 2) {
300: usage:
301: printf("%s remote-file [ local-file ]\n", argv[0]);
302: return;
303: }
304: if (argc < 3) {
305: strcat(line, " ");
306: printf("(local-file) ");
307: gets(&line[strlen(line)]);
308: makeargv();
309: argc = margc;
310: argv = margv;
311: }
312: if (argc < 3)
313: goto usage;
314: if (!globulize(&argv[2]))
315: return;
316: recvrequest("RETR", argv[2], argv[1], "w");
317: }
318: /*
319: * given a remote file name, strip directory path and version number
320: */
321: char *
322: getlocalname(cp)
323: char *cp;
324: {
325: char *result;
326: static char buf[MAXPATHLEN];
327:
328: result = rindex(cp,'/'); /* find last component */
329: if (result == NULL) result = cp;
330: strcpy(buf, result);
331: result = index(buf,'!'); /* strip version # if any */
332: if (result != NULL && result != buf) *result = '\000';
333: return(buf);
334: }
335:
336: /*
337: * Get multiple files.
338: */
339: mget(argc, argv)
340: char *argv[];
341: {
342: char *cp;
343: char *tailp;
344:
345: if (argc < 2) {
346: strcat(line, " ");
347: printf("(remote-files) ");
348: gets(&line[strlen(line)]);
349: makeargv();
350: argc = margc;
351: argv = margv;
352: }
353: if (argc < 2) {
354: printf("%s remote-files\n", argv[0]);
355: return;
356: }
357: while ((cp = remglob(argc, argv)) != NULL)
358: if (confirm(argv[0], cp)) {
359: tailp = getlocalname(cp);
360: recvrequest("RETR", cp, tailp, "w");
361: }
362: }
363:
364: char *
365: remglob(argc, argv)
366: char *argv[];
367: {
368: char temp[16];
369: static char buf[MAXPATHLEN];
370: static FILE *ftemp = NULL;
371: static char **args;
372: int oldverbose, oldhash;
373: char *cp, *mode;
374:
375: if (!doglob) {
376: if (args == NULL)
377: args = argv;
378: if ((cp = *++args) == NULL)
379: args = NULL;
380: return (cp);
381: }
382: if (ftemp == NULL) {
383: strcpy(temp, "/tmp/ftpXXXXXX");
384: mktemp(temp);
385: oldverbose = verbose, verbose = 0;
386: oldhash = hash, hash = 0;
387: for (mode = "w"; *++argv != NULL; mode = "a")
388: recvrequest("NLST", temp, *argv, mode);
389: verbose = oldverbose; hash = oldhash;
390: ftemp = fopen(temp, "r");
391: unlink(temp);
392: if (ftemp == NULL) {
393: printf("can't find list of remote files, oops\n");
394: return (NULL);
395: }
396: }
397: if (fgets(buf, sizeof (buf), ftemp) == NULL) {
398: fclose(ftemp), ftemp = NULL;
399: return (NULL);
400: }
401: if ((cp = index(buf, '\n')) != NULL)
402: *cp = '\0';
403: return (buf);
404: }
405:
406: char *
407: onoff(bool)
408: int bool;
409: {
410:
411: return (bool ? "on" : "off");
412: }
413:
414: /*
415: * Show status.
416: */
417: status(argc, argv)
418: char *argv[];
419: {
420:
421: if (connected)
422: printf("Connected to %s.\n", hostname);
423: else
424: printf("Not connected.\n");
425: printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n",
426: modename, typename, formname, structname);
427: printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n",
428: onoff(verbose), onoff(bell), onoff(interactive),
429: onoff(doglob));
430: printf("Hash mark printing: %s\n",
431: onoff(hash));
432: }
433:
434: /*
435: * Set beep on cmd completed mode.
436: */
437: /*VARARGS*/
438: setbell()
439: {
440:
441: bell = !bell;
442: printf("Bell mode %s.\n", onoff(bell));
443: }
444:
445: /*
446: * Turn on packet tracing.
447: */
448: /*VARARGS*/
449: settrace()
450: {
451:
452: trace = !trace;
453: printf("Packet tracing %s.\n", onoff(trace));
454: }
455:
456: /*
457: * Toggle hash mark printing during transfers.
458: */
459: /*VARARGS*/
460: sethash()
461: {
462:
463: hash = !hash;
464: printf("Hash mark printing %s", onoff(hash));
465: if (hash)
466: printf(" (1 packet/hash mark)");
467: printf(".\n");
468: }
469:
470: /*
471: * Turn on printing of server echo's.
472: */
473: /*VARARGS*/
474: setverbose()
475: {
476:
477: verbose = !verbose;
478: printf("Verbose mode %s.\n", onoff(verbose));
479: }
480:
481: /*
482: * Turn on interactive prompting
483: * during mget, mput, and mdelete.
484: */
485: /*VARARGS*/
486: setprompt()
487: {
488:
489: interactive = !interactive;
490: printf("Interactive mode %s.\n", onoff(interactive));
491: }
492:
493: /*
494: * Toggle metacharacter interpretation
495: * on local file names.
496: */
497: /*VARARGS*/
498: setglob()
499: {
500:
501: doglob = !doglob;
502: printf("Globbing %s.\n", onoff(doglob));
503: }
504:
505: /*
506: * Set debugging mode on/off and/or
507: * set level of debugging.
508: */
509: /*VARARGS*/
510: setdebug(argc, argv)
511: char *argv[];
512: {
513: int val;
514:
515: if (argc > 1) {
516: val = atoi(argv[1]);
517: if (val < 0) {
518: printf("%s: bad debugging value.\n", argv[1]);
519: return;
520: }
521: } else
522: val = !debug;
523: debug = val;
524: printf("Debugging %s (debug=%d).\n", onoff(debug), debug);
525: }
526:
527: /*
528: * Set current working directory
529: * on remote machine.
530: */
531: cd(argc, argv)
532: char *argv[];
533: {
534:
535: if (argc < 2) {
536: strcat(line, " ");
537: printf("(remote-directory) ");
538: gets(&line[strlen(line)]);
539: makeargv();
540: argc = margc;
541: argv = margv;
542: }
543: if (argc < 2) {
544: printf("%s remote-directory\n", argv[0]);
545: return;
546: }
547: (void) docd(argv[1]);
548: }
549:
550: /*
551: * Set current working directory
552: * on local machine.
553: */
554: lcd(argc, argv)
555: char *argv[];
556: {
557: char buf[MAXPATHLEN];
558:
559: if (argc < 2)
560: argc++, argv[1] = home;
561: if (argc != 2) {
562: printf("%s local-directory\n", argv[0]);
563: return;
564: }
565: if (!globulize(&argv[1]))
566: return;
567: if (chdir(argv[1]) < 0) {
568: perror(argv[1]);
569: return;
570: }
571: printf("Local directory now %s\n", getwd(buf));
572: }
573:
574: /*
575: * Delete a single file.
576: */
577: delete(argc, argv)
578: char *argv[];
579: {
580:
581: if (argc < 2) {
582: strcat(line, " ");
583: printf("(remote-file) ");
584: gets(&line[strlen(line)]);
585: makeargv();
586: argc = margc;
587: argv = margv;
588: }
589: if (argc < 2) {
590: printf("%s remote-file\n", argv[0]);
591: return;
592: }
593: (void) dodelete( argv[1]);
594: }
595:
596: /*
597: * Delete multiple files.
598: */
599: mdelete(argc, argv)
600: char *argv[];
601: {
602: char *cp;
603:
604: if (argc < 2) {
605: strcat(line, " ");
606: printf("(remote-files) ");
607: gets(&line[strlen(line)]);
608: makeargv();
609: argc = margc;
610: argv = margv;
611: }
612: if (argc < 2) {
613: printf("%s remote-files\n", argv[0]);
614: return;
615: }
616: while ((cp = remglob(argc, argv)) != NULL)
617: if (confirm(argv[0], cp))
618: (void) dodelete( cp);
619: }
620:
621: /*
622: * Rename a remote file.
623: */
624: renamefile(argc, argv)
625: char *argv[];
626: {
627:
628: if (argc < 2) {
629: strcat(line, " ");
630: printf("(from-name) ");
631: gets(&line[strlen(line)]);
632: makeargv();
633: argc = margc;
634: argv = margv;
635: }
636: if (argc < 2) {
637: usage:
638: printf("%s from-name to-name\n", argv[0]);
639: return;
640: }
641: if (argc < 3) {
642: strcat(line, " ");
643: printf("(to-name) ");
644: gets(&line[strlen(line)]);
645: makeargv();
646: argc = margc;
647: argv = margv;
648: }
649: if (argc < 3)
650: goto usage;
651: dorename(argv[1], argv[2]);
652: }
653:
654: /*
655: * Get a directory listing
656: * of remote files.
657: */
658: ls(argc, argv)
659: char *argv[];
660: {
661: char *cmd;
662:
663: if (argc < 2)
664: argc++, argv[1] = NULL;
665: if (argc < 3)
666: argc++, argv[2] = "-";
667: if (argc > 3) {
668: printf("usage: %s remote-directory local-file\n", argv[0]);
669: return;
670: }
671: cmd = argv[0][0] == 'l' ? "NLST" : "LIST";
672: if (strcmp(argv[2], "-") && !globulize(&argv[2]))
673: return;
674: recvrequest(cmd, argv[2], argv[1], "w");
675: }
676:
677: /*
678: * Get a directory listing
679: * of multiple remote files.
680: */
681: mls(argc, argv)
682: char *argv[];
683: {
684: char *cmd, *mode, *cp, *dest;
685:
686: if (argc < 2) {
687: strcat(line, " ");
688: printf("(remote-files) ");
689: gets(&line[strlen(line)]);
690: makeargv();
691: argc = margc;
692: argv = margv;
693: }
694: if (argc < 3) {
695: strcat(line, " ");
696: printf("(local-file) ");
697: gets(&line[strlen(line)]);
698: makeargv();
699: argc = margc;
700: argv = margv;
701: }
702: if (argc < 3) {
703: printf("%s remote-files local-file\n", argv[0]);
704: return;
705: }
706: dest = argv[argc - 1];
707: argv[argc - 1] = NULL;
708: if (strcmp(dest, "-"))
709: if (globulize(&dest) && confirm("local-file", dest))
710: return;
711: cmd = argv[0][1] == 'l' ? "NLST" : "LIST";
712: for (mode = "w"; cp = remglob(argc, argv); mode = "a")
713: if (confirm(argv[0], cp))
714: recvrequest(cmd, argv[2], argv[1], "w");
715: }
716:
717: /*
718: * Do a shell escape
719: */
720: shell(argc, argv)
721: char *argv[];
722: {
723: int pid, status, (*old1)(), (*old2)();
724: char shellnam[40], *shell, *namep;
725: char **cpp, **gargs;
726:
727: old1 = signal (SIGINT, SIG_IGN);
728: old2 = signal (SIGQUIT, SIG_IGN);
729: if ((pid = fork()) == 0) {
730: for (pid = 3; pid < 20; pid++)
731: close(pid);
732: signal(SIGINT, SIG_DFL);
733: signal(SIGQUIT, SIG_DFL);
734: if (argc <= 1) {
735: shell = getenv("SHELL");
736: if (shell == NULL)
737: shell = "/bin/sh";
738: namep = rindex(shell,'/');
739: if (namep == NULL)
740: namep = shell;
741: strcpy(shellnam,"-");
742: strcat(shellnam, ++namep);
743: if (strcmp(namep, "sh") != 0)
744: shellnam[0] = '+';
745: if (debug) {
746: printf ("%s\n", shell);
747: fflush (stdout);
748: }
749: execl(shell, shellnam, 0);
750: perror(shell);
751: exit(1);
752: }
753: cpp = &argv[1];
754: if (argc > 2) {
755: if ((gargs = glob(cpp)) != NULL)
756: cpp = gargs;
757: if (globerr != NULL) {
758: printf("%s\n", globerr);
759: exit(1);
760: }
761: }
762: if (debug) {
763: register char **zip = cpp;
764:
765: printf("%s", *zip);
766: while (*++zip != NULL)
767: printf(" %s", *zip);
768: printf("\n");
769: fflush(stdout);
770: }
771: execvp(argv[1], cpp);
772: perror(argv[1]);
773: exit(1);
774: }
775: if (pid > 0)
776: while (wait(&status) != pid)
777: ;
778: signal(SIGINT, old1);
779: signal(SIGQUIT, old2);
780: if (pid == -1)
781: perror("Try again later");
782: return (0);
783: }
784:
785: /*
786: * Send new user information (re-login)
787: */
788: user(argc, argv)
789: int argc;
790: char **argv;
791: {
792: char *getXNSpass();
793:
794: if (argc < 2) {
795: strcat(line, " ");
796: printf("(XNS username) ");
797: gets(&line[strlen(line)]);
798: makeargv();
799: argc = margc;
800: argv = margv;
801: }
802: if (argc > 3) {
803: printf("usage: %s username [password]\n", argv[0]);
804: return (0);
805: }
806: if (argc < 3 )
807: argv[2] = getXNSpass("Password: "), argc++;
808: login(argv[1], argv[2]);
809: return (1);
810: }
811:
812: /*
813: * Print working directory.
814: */
815: /*VARARGS*/
816: pwd()
817: {
818: dopwd();
819: }
820:
821: /*
822: * Make a directory.
823: */
824: makedir(argc, argv)
825: char *argv[];
826: {
827:
828: if (argc < 2) {
829: strcat(line, " ");
830: printf("(directory-name) ");
831: gets(&line[strlen(line)]);
832: makeargv();
833: argc = margc;
834: argv = margv;
835: }
836: if (argc < 2) {
837: printf("%s directory-name\n", argv[0]);
838: return;
839: }
840: domakedir(argv[1]);
841: }
842:
843: /*
844: * Remove a directory.
845: */
846: removedir(argc, argv)
847: char *argv[];
848: {
849:
850: if (argc < 2) {
851: strcat(line, " ");
852: printf("(directory-name) ");
853: gets(&line[strlen(line)]);
854: makeargv();
855: argc = margc;
856: argv = margv;
857: }
858: if (argc < 2) {
859: printf("%s directory-name\n", argv[0]);
860: return;
861: }
862: doremovedir(argv[1]);
863: }
864:
865: /*
866: * Terminate session and exit.
867: */
868: /*VARARGS*/
869: quit()
870: {
871:
872: disconnect();
873: exit(0);
874: }
875:
876: /*
877: * Terminate session, but don't exit.
878: */
879: disconnect()
880: {
881: extern FILE *cout;
882: extern int data;
883:
884: if (!connected)
885: return;
886: logout();
887: CourierClose(connected);
888: connected = (CourierConnection *)0;
889: }
890:
891: confirm(cmd, file)
892: char *cmd, *file;
893: {
894: char line[BUFSIZ];
895:
896: if (!interactive) {
897: if (verbose)
898: printf("%s %s\n", cmd, file);
899: return (1);
900: }
901: printf("%s %s? ", cmd, file);
902: fflush(stdout);
903: gets(line);
904: return (*line != 'n' && *line != 'N');
905: }
906:
907: fatal(msg)
908: char *msg;
909: {
910:
911: fprintf(stderr, "ftp: %s\n");
912: exit(1);
913: }
914:
915: /*
916: * Glob a local file name specification with
917: * the expectation of a single return value.
918: * Can't control multiple values being expanded
919: * from the expression, we return only the first.
920: */
921: globulize(cpp)
922: char **cpp;
923: {
924: char **globbed;
925:
926: if (!doglob)
927: return (1);
928: globbed = glob(*cpp);
929: if (globerr != NULL) {
930: printf("%s: %s\n", *cpp, globerr);
931: if (globbed)
932: blkfree(globbed);
933: return (0);
934: }
935: if (globbed) {
936: *cpp = *globbed++;
937: /* don't waste too much memory */
938: if (*globbed)
939: blkfree(globbed);
940: }
941: return (1);
942: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.