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