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