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