|
|
1.1 root 1: /*
2: * FTP User Program -- Command Interface.
3: */
4: #include <sys/types.h>
5: #include <sys/ioctl.h>
6:
7: #include <signal.h>
8: #include <stdio.h>
9: #include <errno.h>
10: #include <ctype.h>
11: #include <libc.h>
12: #include "ftp.h"
13: #include "ftp_var.h"
14:
15: int intr();
16: int lostpeer();
17:
18: main(argc, argv)
19: char *argv[];
20: {
21: register char *cp;
22: int top;
23:
24: sp = in_service("ftp", "tcp", 0);
25: if (sp == 0) {
26: fprintf(stderr, "ftp: ftp/tcp: unknown service\n");
27: exit(1);
28: }
29: argc--, argv++;
30: while (argc > 0 && **argv == '-') {
31: for (cp = *argv + 1; *cp; cp++)
32: switch (*cp) {
33:
34: case 'd':
35: debug++;
36: break;
37:
38: case 'v':
39: verbose++;
40: break;
41:
42: case 't':
43: trace++;
44: break;
45:
46: case 'i':
47: interactive++;
48: break;
49:
50: case 'n':
51: autologin = 0;
52: break;
53:
54: default:
55: fprintf(stderr,
56: "ftp: %c: unknown option\n", *cp);
57: exit(1);
58: }
59: argc--, argv++;
60: }
61: fromatty = isatty(fileno(stdin));
62: /*
63: * Set up defaults for FTP.
64: */
65: strcpy(typename, "ascii"), type = TYPE_A;
66: strcpy(formname, "non-print"), form = FORM_N;
67: strcpy(modename, "stream"), mode = MODE_S;
68: strcpy(structname, "file"), stru = STRU_F;
69: strcpy(bytename, "8"), bytesize = 8;
70: if (fromatty)
71: verbose++;
72: if (argc > 0) {
73: if (setjmp(toplevel))
74: exit(0);
75: signal(SIGINT, intr);
76: signal(SIGPIPE, lostpeer);
77: setpeer(argc + 1, argv - 1);
78: }
79: top = setjmp(toplevel) == 0;
80: if (top) {
81: signal(SIGINT, intr);
82: signal(SIGPIPE, lostpeer);
83: }
84: for (;;) {
85: cmdscanner(top);
86: top = 1;
87: }
88: }
89:
90: intr()
91: {
92:
93: longjmp(toplevel, 1);
94: }
95:
96: lostpeer()
97: {
98: extern FILE *cout;
99: extern int data;
100:
101: if (connected) {
102: if (cout != NULL) {
103: fclose(cout);
104: cout = NULL;
105: }
106: if (data >= 0) {
107: (void) close(data);
108: data = -1;
109: }
110: connected = 0;
111: }
112: longjmp(toplevel, 1);
113: }
114:
115: char *
116: tail(filename)
117: char *filename;
118: {
119: register char *s;
120:
121: while (*filename) {
122: s = strrchr(filename, '/');
123: if (s == NULL)
124: break;
125: if (s[1])
126: return (s + 1);
127: *s = '\0';
128: }
129: return (filename);
130: }
131:
132: /*
133: * Command parser.
134: */
135: cmdscanner(top)
136: int top;
137: {
138: register struct cmd *c;
139: struct cmd *getcmd();
140: extern struct cmd cmdtab[];
141: extern int help();
142:
143: if (!top)
144: putchar('\n');
145: for (;;) {
146: if (fromatty) {
147: printf("ftp> ");
148: fflush(stdout);
149: }
150: if (gets(line) == 0)
151: break;
152: if (line[0] == 0)
153: break;
154: makeargv();
155: c = getcmd(margv[0]);
156: if (c == (struct cmd *)-1) {
157: printf("?Ambiguous command\n");
158: continue;
159: }
160: if (c == 0) {
161: printf("?Invalid command\n");
162: continue;
163: }
164: (*c->c_handler)(margc, margv);
165: if (bell && c->c_bell)
166: putchar(007);
167: if (c->c_handler != help)
168: break;
169: }
170: longjmp(toplevel, 0);
171: }
172:
173: struct cmd *
174: getcmd(name)
175: register char *name;
176: {
177: register char *p, *q;
178: register struct cmd *c, *found;
179: register int nmatches, longest;
180:
181: longest = 0;
182: nmatches = 0;
183: found = 0;
184: for (c = cmdtab; p = c->c_name; c++) {
185: for (q = name; *q == *p++; q++)
186: if (*q == 0) /* exact match? */
187: return (c);
188: if (!*q) { /* the name was a prefix */
189: if (q - name > longest) {
190: longest = q - name;
191: nmatches = 1;
192: found = c;
193: } else if (q - name == longest)
194: nmatches++;
195: }
196: }
197: if (nmatches > 1)
198: return ((struct cmd *)-1);
199: return (found);
200: }
201:
202: /*
203: * Slice a string up into argc/argv.
204: */
205: makeargv()
206: {
207: char **argp;
208: char *slurpstring();
209:
210: margc = 0;
211: argp = margv;
212: stringbase = line; /* scan from first of buffer */
213: argbase = argbuf; /* store from first of buffer */
214: while (*argp++ = slurpstring())
215: margc++;
216: }
217:
218: /*
219: * Parse string into argbuf;
220: * implemented with FSM to
221: * handle quoting and strings
222: */
223: char *
224: slurpstring()
225: {
226: int got_one = 0;
227: register char *sb = stringbase;
228: register char *ap = argbase;
229: char *tmp = argbase; /* will return this if token found */
230:
231: S0:
232: switch (*sb) {
233:
234: case '\0':
235: goto OUT;
236:
237: case ' ':
238: case '\t':
239: sb++; goto S0;
240:
241: default:
242: goto S1;
243: }
244:
245: S1:
246: switch (*sb) {
247:
248: case ' ':
249: case '\t':
250: case '\0':
251: goto OUT; /* end of token */
252:
253: case '\\':
254: sb++; goto S2; /* slurp next character */
255:
256: case '"':
257: sb++; goto S3; /* slurp quoted string */
258:
259: default:
260: *ap++ = *sb++; /* add character to token */
261: got_one = 1;
262: goto S1;
263: }
264:
265: S2:
266: switch (*sb) {
267:
268: case '\0':
269: goto OUT;
270:
271: default:
272: *ap++ = *sb++;
273: got_one = 1;
274: goto S1;
275: }
276:
277: S3:
278: switch (*sb) {
279:
280: case '\0':
281: goto OUT;
282:
283: case '"':
284: sb++; goto S1;
285:
286: default:
287: *ap++ = *sb++;
288: got_one = 1;
289: goto S3;
290: }
291:
292: OUT:
293: if (got_one)
294: *ap++ = '\0';
295: argbase = ap; /* update storage pointer */
296: stringbase = sb; /* update scan pointer */
297: if (got_one)
298: return(tmp);
299: return((char *)0);
300: }
301:
302: #define HELPINDENT (sizeof ("directory"))
303:
304: /*
305: * Help command.
306: * Call each command handler with argc == 0 and argv[0] == name.
307: */
308: help(argc, argv)
309: int argc;
310: char *argv[];
311: {
312: register struct cmd *c;
313:
314: if (argc == 1) {
315: register int i, j, w;
316: int columns, width = 0, lines;
317: extern int NCMDS;
318:
319: printf("Commands may be abbreviated. Commands are:\n\n");
320: for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
321: int len = strlen(c->c_name);
322:
323: if (len > width)
324: width = len;
325: }
326: width = (width + 8) &~ 7;
327: columns = 80 / width;
328: if (columns == 0)
329: columns = 1;
330: lines = (NCMDS + columns - 1) / columns;
331: for (i = 0; i < lines; i++) {
332: for (j = 0; j < columns; j++) {
333: c = cmdtab + j * lines + i;
334: printf("%s", c->c_name);
335: if (c + lines >= &cmdtab[NCMDS]) {
336: printf("\n");
337: break;
338: }
339: w = strlen(c->c_name);
340: while (w < width) {
341: w = (w + 8) &~ 7;
342: putchar('\t');
343: }
344: }
345: }
346: return;
347: }
348: while (--argc > 0) {
349: register char *arg;
350: arg = *++argv;
351: c = getcmd(arg);
352: if (c == (struct cmd *)-1)
353: printf("?Ambiguous help command %s\n", arg);
354: else if (c == (struct cmd *)0)
355: printf("?Invalid help command %s\n", arg);
356: else
357: printf("%-*s\t%s\n", HELPINDENT,
358: c->c_name, c->c_help);
359: }
360: }
361:
362: /*
363: * Call routine with argc, argv set from args (terminated by 0).
364: */
365: /* VARARGS2 */
366: call(routine, args)
367: int (*routine)();
368: int args;
369: {
370: register int *argp;
371: register int argc;
372:
373: for (argc = 0, argp = &args; *argp++ != 0; argc++)
374: ;
375: (*routine)(argc, &args);
376: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.