Annotation of 42BSD/ucb/ftp/main.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.