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