|
|
1.1 root 1: /*
2: * Copyright (c) 1985 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that the above copyright notice and this paragraph are
7: * duplicated in all such forms and that any documentation,
8: * advertising materials, and other materials related to such
9: * distribution and use acknowledge that the software was developed
10: * by the University of California, Berkeley. The name of the
11: * University may not be used to endorse or promote products derived
12: * from this software without specific prior written permission.
13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16: */
17:
18: #ifndef lint
19: char copyright[] =
20: "@(#) Copyright (c) 1985 Regents of the University of California.\n\
21: All rights reserved.\n";
22: #endif /* not lint */
23:
24: #ifndef lint
25: static char sccsid[] = "@(#)main.c 5.12 (Berkeley) 2/28/89";
26: #endif /* not lint */
27:
28: /*
29: * FTP User Program -- Command Interface.
30: */
31:
32: #include "ftp_var.h"
33: #include "ftp.h"
34: #include <sys/types.h>
35:
36: #include <stdio.h>
37: #include <errno.h>
38: #include <ctype.h>
39: #include <pwd.h>
40: #include <varargs.h>
41:
42:
43: int getuid();
44: extern char *home;
45: char *getlogin();
46:
47: main(argc, argv)
48: char *argv[];
49: {
50: register char *cp;
51: int top;
52: struct passwd *pw = NULL;
53: char homedir[MAXPATHLEN];
54:
55: doglob = 1;
56: interactive = 1;
57: autologin = 1;
58: argc--, argv++;
59: while (argc > 0 && **argv == '-') {
60: for (cp = *argv + 1; *cp; cp++)
61: switch (*cp) {
62:
63: case 'd':
64: #ifdef REMOVE
65: options |= SO_DEBUG;
66: #endif
67: debug++;
68: break;
69:
70: case 'v':
71: verbose++;
72: break;
73:
74: case 't':
75: trace++;
76: break;
77:
78: case 'i':
79: interactive = 0;
80: break;
81:
82: case 'n':
83: autologin = 0;
84: break;
85:
86: case 'g':
87: doglob = 0;
88: break;
89:
90: default:
91: fprintf(stdout,
92: "ftp: %c: unknown option\n", *cp);
93: exit(1);
94: }
95: argc--, argv++;
96: }
97: fromatty = isatty(fileno(stdin));
98: /*
99: * Set up defaults for FTP.
100: */
101: (void) strcpy(typename, "ascii"), type = TYPE_A;
102: (void) strcpy(formname, "non-print"), form = FORM_N;
103: (void) strcpy(modename, "stream"), mode = MODE_S;
104: (void) strcpy(structname, "file"), stru = STRU_F;
105: (void) strcpy(bytename, "8"), bytesize = 8;
106: if (fromatty)
107: verbose++;
108: cpend = 0; /* no pending replies */
109: proxy = 0; /* proxy not active */
110: crflag = 1; /* strip c.r. on ascii gets */
111: /*
112: * Set up the home directory in case we're globbing.
113: */
114: cp = getlogin();
115: if (cp != NULL) {
116: pw = getpwnam(cp);
117: }
118: if (pw == NULL)
119: pw = getpwuid(getuid());
120: if (pw != NULL) {
121: home = homedir;
122: (void) strcpy(home, pw->pw_dir);
123: }
124: if (argc > 0) {
125: setpeer(argc + 1, argv - 1);
126: }
127: top = 1;
128: for (;;) {
129: cmdscanner(top);
130: top = 1;
131: }
132: }
133:
134: lostpeer()
135: {
136: extern FILE *cout;
137: extern int data;
138:
139: if (connected) {
140: if (cout != NULL) {
141: (void) fclose(cout);
142: cout = NULL;
143: }
144: if (data >= 0) {
145: (void) close(data);
146: data = -1;
147: }
148: connected = 0;
149: }
150: pswitch(1);
151: if (connected) {
152: if (cout != NULL) {
153: (void) fclose(cout);
154: cout = NULL;
155: }
156: connected = 0;
157: }
158: proxflag = 0;
159: pswitch(0);
160: }
161:
162: /*char *
163: tail(filename)
164: char *filename;
165: {
166: register char *s;
167:
168: while (*filename) {
169: s = rindex(filename, '/');
170: if (s == NULL)
171: break;
172: if (s[1])
173: return (s + 1);
174: *s = '\0';
175: }
176: return (filename);
177: }
178: */
179: /*
180: * Command parser.
181: */
182: cmdscanner(top)
183: int top;
184: {
185: register struct cmd *c;
186: struct cmd *getcmd();
187: extern int help();
188:
189: if (!top)
190: (void) putchar('\n');
191: for (;;) {
192: if (fromatty) {
193: printf("ftp> ");
194: (void) fflush(stdout);
195: }
196: if (safegets(line, sizeof(line)) == 0) {
197: if (feof(stdin) || ferror(stdin))
198: quit();
199: break;
200: }
201: if (line[0] == 0)
202: break;
203: makeargv();
204: if (margc == 0) {
205: continue;
206: }
207: c = getcmd(margv[0]);
208: if (c == (struct cmd *)-1) {
209: printf("?Ambiguous command\n");
210: continue;
211: }
212: if (c == 0) {
213: printf("?Invalid command\n");
214: continue;
215: }
216: if (c->c_conn && !connected) {
217: printf ("Not connected.\n");
218: continue;
219: }
220: (*c->c_handler)(margc, margv);
221: if (bell && c->c_bell)
222: (void) putchar('\007');
223: if (c->c_handler != help)
224: break;
225: }
226: }
227:
228: struct cmd *
229: getcmd(name)
230: register char *name;
231: {
232: extern struct cmd cmdtab[];
233: register char *p, *q;
234: register struct cmd *c, *found;
235: register int nmatches, longest;
236:
237: longest = 0;
238: nmatches = 0;
239: found = 0;
240: for (c = cmdtab; p = c->c_name; c++) {
241: for (q = name; *q == *p++; q++)
242: if (*q == 0) /* exact match? */
243: return (c);
244: if (!*q) { /* the name was a prefix */
245: if (q - name > longest) {
246: longest = q - name;
247: nmatches = 1;
248: found = c;
249: } else if (q - name == longest)
250: nmatches++;
251: }
252: }
253: if (nmatches > 1)
254: return ((struct cmd *)-1);
255: return (found);
256: }
257:
258: /*
259: * Slice a string up into argc/argv.
260: */
261:
262: int slrflag;
263:
264: makeargv()
265: {
266: char **argp;
267: char *slurpstring();
268:
269: margc = 0;
270: argp = margv;
271: stringbase = line; /* scan from first of buffer */
272: argbase = argbuf; /* store from first of buffer */
273: slrflag = 0;
274: while (*argp++ = slurpstring())
275: margc++;
276: }
277:
278: /*
279: * Parse string into argbuf;
280: * implemented with FSM to
281: * handle quoting and strings
282: */
283: char *
284: slurpstring()
285: {
286: int got_one = 0;
287: register char *sb = stringbase;
288: register char *ap = argbase;
289: char *tmp = argbase; /* will return this if token found */
290:
291: if (*sb == '!' || *sb == '$') { /* recognize ! as a token for shell */
292: switch (slrflag) { /* and $ as token for macro invoke */
293: case 0:
294: slrflag++;
295: stringbase++;
296: return ((*sb == '!') ? "!" : "$");
297: /* NOTREACHED */
298: case 1:
299: slrflag++;
300: altarg = stringbase;
301: break;
302: default:
303: break;
304: }
305: }
306:
307: S0:
308: switch (*sb) {
309:
310: case '\0':
311: goto OUT;
312:
313: case ' ':
314: case '\t':
315: sb++; goto S0;
316:
317: default:
318: switch (slrflag) {
319: case 0:
320: slrflag++;
321: break;
322: case 1:
323: slrflag++;
324: altarg = sb;
325: break;
326: default:
327: break;
328: }
329: goto S1;
330: }
331:
332: S1:
333: switch (*sb) {
334:
335: case ' ':
336: case '\t':
337: case '\0':
338: goto OUT; /* end of token */
339:
340: case '\\':
341: sb++; goto S2; /* slurp next character */
342:
343: case '"':
344: sb++; goto S3; /* slurp quoted string */
345:
346: default:
347: *ap++ = *sb++; /* add character to token */
348: got_one = 1;
349: goto S1;
350: }
351:
352: S2:
353: switch (*sb) {
354:
355: case '\0':
356: goto OUT;
357:
358: default:
359: *ap++ = *sb++;
360: got_one = 1;
361: goto S1;
362: }
363:
364: S3:
365: switch (*sb) {
366:
367: case '\0':
368: goto OUT;
369:
370: case '"':
371: sb++; goto S1;
372:
373: default:
374: *ap++ = *sb++;
375: got_one = 1;
376: goto S3;
377: }
378:
379: OUT:
380: if (got_one)
381: *ap++ = '\0';
382: argbase = ap; /* update storage pointer */
383: stringbase = sb; /* update scan pointer */
384: if (got_one) {
385: return(tmp);
386: }
387: switch (slrflag) {
388: case 0:
389: slrflag++;
390: break;
391: case 1:
392: slrflag++;
393: altarg = (char *) 0;
394: break;
395: default:
396: break;
397: }
398: return((char *)0);
399: }
400:
401: #define HELPINDENT (sizeof ("directory"))
402:
403: /*
404: * Help command.
405: * Call each command handler with argc == 0 and argv[0] == name.
406: */
407: help(argc, argv)
408: int argc;
409: char *argv[];
410: {
411: extern struct cmd cmdtab[];
412: register struct cmd *c;
413:
414: if (argc == 1) {
415: register int i, j, w, k;
416: int columns, width = 0, lines;
417: extern int NCMDS;
418:
419: printf("Commands may be abbreviated. Commands are:\n\n");
420: for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
421: int len = strlen(c->c_name);
422:
423: if (len > width)
424: width = len;
425: }
426: width = (width + 8) &~ 7;
427: columns = 80 / width;
428: if (columns == 0)
429: columns = 1;
430: lines = (NCMDS + columns - 1) / columns;
431: for (i = 0; i < lines; i++) {
432: for (j = 0; j < columns; j++) {
433: c = cmdtab + j * lines + i;
434: if (c->c_name && (!proxy || c->c_proxy)) {
435: printf("%s", c->c_name);
436: }
437: else if (c->c_name) {
438: for (k=0; k < strlen(c->c_name); k++) {
439: (void) putchar(' ');
440: }
441: }
442: if (c + lines >= &cmdtab[NCMDS]) {
443: printf("\n");
444: break;
445: }
446: w = strlen(c->c_name);
447: while (w < width) {
448: w = (w + 8) &~ 7;
449: (void) putchar('\t');
450: }
451: }
452: }
453: return;
454: }
455: while (--argc > 0) {
456: register char *arg;
457: arg = *++argv;
458: c = getcmd(arg);
459: if (c == (struct cmd *)-1)
460: printf("?Ambiguous help command %s\n", arg);
461: else if (c == (struct cmd *)0)
462: printf("?Invalid help command %s\n", arg);
463: else
464: printf("%-*s\t%s\n", HELPINDENT,
465: c->c_name, c->c_help);
466: }
467: }
468:
469: /*
470: * Call routine with argc, argv set from args (terminated by 0).
471: */
472: call(routine, va_alist)
473: int (*routine)();
474: va_dcl
475: {
476: va_list ap;
477: char *argv[10];
478: register int argc = 0;
479:
480: va_start(ap);
481: while ((argv[argc] = va_arg(ap, char *)) != (char *)0)
482: argc++;
483: va_end(ap);
484: return (*routine)(argc, argv);
485: }
486:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.