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