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