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

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)main.c     4.7 (Berkeley) 8/11/83";
                      3: #endif
                      4: 
                      5: /*
                      6:  * TFTP User Program -- Command Interface.
                      7:  */
                      8: #include <sys/types.h>
                      9: #include <sys/socket.h>
                     10: #include <sys/file.h>
                     11: 
                     12: #include <netinet/in.h>
                     13: 
                     14: #include <signal.h>
                     15: #include <stdio.h>
                     16: #include <errno.h>
                     17: #include <setjmp.h>
                     18: #include <ctype.h>
                     19: #include <netdb.h>
                     20: 
                     21: #define        TIMEOUT         5               /* secs between rexmt's */
                     22: 
                     23: struct sockaddr_in sin;
                     24: int    f;
                     25: int    trace;
                     26: int    verbose;
                     27: int    connected;
                     28: char   mode[32];
                     29: char   line[200];
                     30: int    margc;
                     31: char   *margv[20];
                     32: char   *prompt = "tftp";
                     33: jmp_buf        toplevel;
                     34: int    intr();
                     35: struct servent *sp;
                     36: 
                     37: int    quit(), help(), setverbose(), settrace(), status();
                     38: int    get(), put(), setpeer(), setmode(), setrexmt(), settimeout();
                     39: 
                     40: #define HELPINDENT (sizeof("connect"))
                     41: 
                     42: struct cmd {
                     43:        char    *name;
                     44:        char    *help;
                     45:        int     (*handler)();
                     46: };
                     47: 
                     48: char   vhelp[] = "toggle verbose mode";
                     49: char   thelp[] = "toggle packet tracing";
                     50: char   chelp[] = "connect to remote tftp";
                     51: char   qhelp[] = "exit tftp";
                     52: char   hhelp[] = "print help information";
                     53: char   shelp[] = "send file";
                     54: char   rhelp[] = "receive file";
                     55: char   mhelp[] = "set file transfer mode";
                     56: char   sthelp[] = "show current status";
                     57: char   xhelp[] = "set per-packet retransmission timeout";
                     58: char   ihelp[] = "set total retransmission timeout";
                     59: 
                     60: struct cmd cmdtab[] = {
                     61:        { "connect",    chelp,          setpeer },
                     62:        { "mode",       mhelp,          setmode },
                     63:        { "put",        shelp,          put },
                     64:        { "get",        rhelp,          get },
                     65:        { "quit",       qhelp,          quit },
                     66:        { "verbose",    vhelp,          setverbose },
                     67:        { "trace",      thelp,          settrace },
                     68:        { "status",     sthelp,         status },
                     69:        { "rexmt",      xhelp,          setrexmt },
                     70:        { "timeout",    ihelp,          settimeout },
                     71:        { "?",          hhelp,          help },
                     72:        0
                     73: };
                     74: 
                     75: struct cmd *getcmd();
                     76: char   *tail();
                     77: char   *index();
                     78: char   *rindex();
                     79: 
                     80: main(argc, argv)
                     81:        char *argv[];
                     82: {
                     83:        struct sockaddr_in sin;
                     84:        int top;
                     85: 
                     86:        sp = getservbyname("tftp", "udp");
                     87:        if (sp == 0) {
                     88:                fprintf(stderr, "tftp: udp/tftp: unknown service\n");
                     89:                exit(1);
                     90:        }
                     91:        f = socket(AF_INET, SOCK_DGRAM, 0, 0);
                     92:        if (f < 0) {
                     93:                perror("tftp: socket");
                     94:                exit(3);
                     95:        }
                     96:        bzero((char *)&sin, sizeof (sin));
                     97:        sin.sin_family = AF_INET;
                     98:        if (bind(f, &sin, sizeof (sin)) < 0) {
                     99:                perror("tftp: bind");
                    100:                exit(1);
                    101:        }
                    102:        strcpy(mode, "netascii");
                    103:        signal(SIGINT, intr);
                    104:        if (argc > 1) {
                    105:                if (setjmp(toplevel) != 0)
                    106:                        exit(0);
                    107:                setpeer(argc, argv);
                    108:        }
                    109:        top = setjmp(toplevel) == 0;
                    110:        for (;;)
                    111:                command(top);
                    112: }
                    113: 
                    114: char   *hostname;
                    115: char   hnamebuf[32];
                    116: 
                    117: setpeer(argc, argv)
                    118:        int argc;
                    119:        char *argv[];
                    120: {
                    121:        register int c;
                    122:        struct hostent *host;
                    123: 
                    124:        if (argc < 2) {
                    125:                strcpy(line, "Connect ");
                    126:                printf("(to) ");
                    127:                gets(&line[strlen(line)]);
                    128:                makeargv();
                    129:                argc = margc;
                    130:                argv = margv;
                    131:        }
                    132:        if (argc > 3) {
                    133:                printf("usage: %s host-name [port]\n", argv[0]);
                    134:                return;
                    135:        }
                    136:        host = gethostbyname(argv[1]);
                    137:        if (host) {
                    138:                sin.sin_family = host->h_addrtype;
                    139:                bcopy(host->h_addr, &sin.sin_addr, host->h_length);
                    140:                hostname = host->h_name;
                    141:        } else {
                    142:                sin.sin_family = AF_INET;
                    143:                sin.sin_addr.s_addr = inet_addr(argv[1]);
                    144:                if (sin.sin_addr.s_addr == -1) {
                    145:                        connected = 0;
                    146:                        printf("%s: unknown host\n", argv[1]);
                    147:                        return;
                    148:                }
                    149:                strcpy(hnamebuf, argv[1]);
                    150:                hostname = hnamebuf;
                    151:        }
                    152:        sin.sin_port = sp->s_port;
                    153:        if (argc == 3) {
                    154:                sin.sin_port = atoi(argv[2]);
                    155:                if (sin.sin_port < 0) {
                    156:                        printf("%s: bad port number\n", argv[2]);
                    157:                        connected = 0;
                    158:                        return;
                    159:                }
                    160:                sin.sin_port = htons((u_short)sin.sin_port);
                    161:        }
                    162:        connected = 1;
                    163: }
                    164: 
                    165: struct modes {
                    166:        char *m_name;
                    167:        char *m_mode;
                    168: } modes[] = {
                    169:        { "ascii",      "netascii" },
                    170:        { "binary",     "octect" },
                    171:        { "mail",       "mail" },
                    172:        { 0,            0 }
                    173: };
                    174: 
                    175: setmode(argc, argv)
                    176:        char *argv[];
                    177: {
                    178:        register struct modes *p;
                    179: 
                    180:        if (argc > 2) {
                    181:                char *sep;
                    182: 
                    183:                printf("usage: %s [", argv[0]);
                    184:                sep = " ";
                    185:                for (p = modes; p->m_name; p++) {
                    186:                        printf("%s%s", sep, p->m_name);
                    187:                        if (*sep == ' ')
                    188:                                sep = " | ";
                    189:                }
                    190:                printf(" ]\n");
                    191:                return;
                    192:        }
                    193:        if (argc < 2) {
                    194:                printf("Using %s mode to transfer files.\n", mode);
                    195:                return;
                    196:        }
                    197:        for (p = modes; p->m_name; p++)
                    198:                if (strcmp(argv[1], p->m_name) == 0)
                    199:                        break;
                    200:        if (p->m_name)
                    201:                strcpy(mode, p->m_mode);
                    202:        else
                    203:                printf("%s: unknown mode\n", argv[1]);
                    204: }
                    205: 
                    206: /*
                    207:  * Send file(s).
                    208:  */
                    209: put(argc, argv)
                    210:        char *argv[];
                    211: {
                    212:        int fd;
                    213:        register int n, addr;
                    214:        register char *cp, *targ;
                    215: 
                    216:        if (argc < 2) {
                    217:                strcpy(line, "send ");
                    218:                printf("(file) ");
                    219:                gets(&line[strlen(line)]);
                    220:                makeargv();
                    221:                argc = margc;
                    222:                argv = margv;
                    223:        }
                    224:        if (argc < 2) {
                    225:                putusage(argv[0]);
                    226:                return;
                    227:        }
                    228:        targ = argv[argc - 1];
                    229:        if (index(argv[argc - 1], ':')) {
                    230:                char *cp;
                    231:                struct hostent *hp;
                    232: 
                    233:                for (n = 1; n < argc - 1; n++)
                    234:                        if (index(argv[n], ':')) {
                    235:                                putusage(argv[0]);
                    236:                                return;
                    237:                        }
                    238:                cp = argv[argc - 1];
                    239:                targ = index(cp, ':');
                    240:                *targ++ = 0;
                    241:                hp = gethostbyname(cp);
                    242:                if (hp == 0) {
                    243:                        printf("%s: Unknown host.\n", cp);
                    244:                        return;
                    245:                }
                    246:                bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
                    247:                sin.sin_family = hp->h_addrtype;
                    248:                connected = 1;
                    249:                hostname = hp->h_name;
                    250:        }
                    251:        if (!connected) {
                    252:                printf("No target machine specified.\n");
                    253:                return;
                    254:        }
                    255:        if (argc < 4) {
                    256:                cp = argc == 2 ? tail(targ) : argv[1];
                    257:                fd = open(cp, O_RDONLY);
                    258:                if (fd < 0) {
                    259:                        fprintf(stderr, "tftp: "); perror(cp);
                    260:                        return;
                    261:                }
                    262:                sendfile(fd, targ);
                    263:                return;
                    264:        }
                    265:        cp = index(targ, '\0'); 
                    266:        *cp++ = '/';
                    267:        for (n = 1; n < argc - 1; n++) {
                    268:                strcpy(cp, tail(argv[n]));
                    269:                fd = open(argv[n], O_RDONLY);
                    270:                if (fd < 0) {
                    271:                        fprintf(stderr, "tftp: "); perror(argv[n]);
                    272:                        continue;
                    273:                }
                    274:                sendfile(fd, targ);
                    275:        }
                    276: }
                    277: 
                    278: putusage(s)
                    279:        char *s;
                    280: {
                    281:        printf("usage: %s file ... host:target, or\n", s);
                    282:        printf("       %s file ... target (when already connected)\n", s);
                    283: }
                    284: 
                    285: /*
                    286:  * Receive file(s).
                    287:  */
                    288: get(argc, argv)
                    289:        char *argv[];
                    290: {
                    291:        int fd;
                    292:        register int n, addr;
                    293:        register char *cp;
                    294:        char *src;
                    295: 
                    296:        if (argc < 2) {
                    297:                strcpy(line, "get ");
                    298:                printf("(files) ");
                    299:                gets(&line[strlen(line)]);
                    300:                makeargv();
                    301:                argc = margc;
                    302:                argv = margv;
                    303:        }
                    304:        if (argc < 2) {
                    305:                getusage(argv[0]);
                    306:                return;
                    307:        }
                    308:        if (!connected)
                    309:                for (n = 1; n < argc - 1; n++)
                    310:                        if (index(argv[n], ':') == 0) {
                    311:                                getusage(argv[0]);
                    312:                                return;
                    313:                        }
                    314:        for (n = 1; argc == 2 || n < argc - 1; n++) {
                    315:                src = index(argv[n], ':');
                    316:                if (src == NULL)
                    317:                        src = argv[n];
                    318:                else {
                    319:                        struct hostent *hp;
                    320: 
                    321:                        *src++ = 0;
                    322:                        hp = gethostbyname(argv[n]);
                    323:                        if (hp == 0) {
                    324:                                printf("%s: Unknown host.\n", argv[n]);
                    325:                                continue;
                    326:                        }
                    327:                        bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
                    328:                        sin.sin_family = hp->h_addrtype;
                    329:                        connected = 1;
                    330:                        hostname = hp->h_name;
                    331:                }
                    332:                if (argc < 4) {
                    333:                        cp = argc == 3 ? argv[2] : tail(src);
                    334:                        fd = creat(cp, 0644);
                    335:                        if (fd < 0) {
                    336:                                fprintf(stderr, "tftp: "); perror(cp);
                    337:                                return;
                    338:                        }
                    339:                        recvfile(fd, src);
                    340:                        break;
                    341:                }
                    342:                cp = index(argv[argc - 1], '\0');
                    343:                *cp++ = '/';
                    344:                strcpy(cp, tail(src));
                    345:                fd = creat(src, 0644);
                    346:                if (fd < 0) {
                    347:                        fprintf(stderr, "tftp: "); perror(src);
                    348:                        continue;
                    349:                }
                    350:                recvfile(fd, src);
                    351:        }
                    352: }
                    353: 
                    354: getusage(s)
                    355: {
                    356:        printf("usage: %s host:file host:file ... file, or\n", s);
                    357:        printf("       %s file file ... file if connected\n", s);
                    358: }
                    359: 
                    360: int    rexmtval = TIMEOUT;
                    361: 
                    362: setrexmt(argc, argv)
                    363:        char *argv[];
                    364: {
                    365:        int t;
                    366: 
                    367:        if (argc < 2) {
                    368:                strcpy(line, "Rexmt-timeout ");
                    369:                printf("(value) ");
                    370:                gets(&line[strlen(line)]);
                    371:                makeargv();
                    372:                argc = margc;
                    373:                argv = margv;
                    374:        }
                    375:        if (argc != 2) {
                    376:                printf("usage: %s value\n", argv[0]);
                    377:                return;
                    378:        }
                    379:        t = atoi(argv[1]);
                    380:        if (t < 0)
                    381:                printf("%s: bad value\n", t);
                    382:        else
                    383:                rexmtval = t;
                    384: }
                    385: 
                    386: int    maxtimeout = 5 * TIMEOUT;
                    387: 
                    388: settimeout(argc, argv)
                    389:        char *argv[];
                    390: {
                    391:        int t;
                    392: 
                    393:        if (argc < 2) {
                    394:                strcpy(line, "Maximum-timeout ");
                    395:                printf("(value) ");
                    396:                gets(&line[strlen(line)]);
                    397:                makeargv();
                    398:                argc = margc;
                    399:                argv = margv;
                    400:        }
                    401:        if (argc != 2) {
                    402:                printf("usage: %s value\n", argv[0]);
                    403:                return;
                    404:        }
                    405:        t = atoi(argv[1]);
                    406:        if (t < 0)
                    407:                printf("%s: bad value\n", t);
                    408:        else
                    409:                maxtimeout = t;
                    410: }
                    411: 
                    412: status(argc, argv)
                    413:        char *argv[];
                    414: {
                    415:        if (connected)
                    416:                printf("Connected to %s.\n", hostname);
                    417:        else
                    418:                printf("Not connected.\n");
                    419:        printf("Mode: %s Verbose: %s Tracing: %s\n", mode,
                    420:                verbose ? "on" : "off", trace ? "on" : "off");
                    421:        printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n",
                    422:                rexmtval, maxtimeout);
                    423: }
                    424: 
                    425: intr()
                    426: {
                    427: 
                    428:        longjmp(toplevel, -1);
                    429: }
                    430: 
                    431: char *
                    432: tail(filename)
                    433:        char *filename;
                    434: {
                    435:        register char *s;
                    436:        
                    437:        while (*filename) {
                    438:                s = rindex(filename, '/');
                    439:                if (s == NULL)
                    440:                        break;
                    441:                if (s[1])
                    442:                        return (s + 1);
                    443:                *s = '\0';
                    444:        }
                    445:        return (filename);
                    446: }
                    447: 
                    448: /*
                    449:  * Command parser.
                    450:  */
                    451: command(top)
                    452:        int top;
                    453: {
                    454:        register struct cmd *c;
                    455: 
                    456:        if (!top)
                    457:                putchar('\n');
                    458:        for (;;) {
                    459:                printf("%s> ", prompt);
                    460:                if (gets(line) == 0)
                    461:                        continue;
                    462:                if (line[0] == 0)
                    463:                        continue;
                    464:                makeargv();
                    465:                c = getcmd(margv[0]);
                    466:                if (c == (struct cmd *)-1) {
                    467:                        printf("?Ambiguous command\n");
                    468:                        continue;
                    469:                }
                    470:                if (c == 0) {
                    471:                        printf("?Invalid command\n");
                    472:                        continue;
                    473:                }
                    474:                (*c->handler)(margc, margv);
                    475:        }
                    476: }
                    477: 
                    478: struct cmd *
                    479: getcmd(name)
                    480:        register char *name;
                    481: {
                    482:        register char *p, *q;
                    483:        register struct cmd *c, *found;
                    484:        register int nmatches, longest;
                    485: 
                    486:        longest = 0;
                    487:        nmatches = 0;
                    488:        found = 0;
                    489:        for (c = cmdtab; p = c->name; c++) {
                    490:                for (q = name; *q == *p++; q++)
                    491:                        if (*q == 0)            /* exact match? */
                    492:                                return (c);
                    493:                if (!*q) {                      /* the name was a prefix */
                    494:                        if (q - name > longest) {
                    495:                                longest = q - name;
                    496:                                nmatches = 1;
                    497:                                found = c;
                    498:                        } else if (q - name == longest)
                    499:                                nmatches++;
                    500:                }
                    501:        }
                    502:        if (nmatches > 1)
                    503:                return ((struct cmd *)-1);
                    504:        return (found);
                    505: }
                    506: 
                    507: /*
                    508:  * Slice a string up into argc/argv.
                    509:  */
                    510: makeargv()
                    511: {
                    512:        register char *cp;
                    513:        register char **argp = margv;
                    514: 
                    515:        margc = 0;
                    516:        for (cp = line; *cp;) {
                    517:                while (isspace(*cp))
                    518:                        cp++;
                    519:                if (*cp == '\0')
                    520:                        break;
                    521:                *argp++ = cp;
                    522:                margc += 1;
                    523:                while (*cp != '\0' && !isspace(*cp))
                    524:                        cp++;
                    525:                if (*cp == '\0')
                    526:                        break;
                    527:                *cp++ = '\0';
                    528:        }
                    529:        *argp++ = 0;
                    530: }
                    531: 
                    532: /*VARARGS*/
                    533: quit()
                    534: {
                    535:        exit(0);
                    536: }
                    537: 
                    538: /*
                    539:  * Help command.
                    540:  */
                    541: help(argc, argv)
                    542:        int argc;
                    543:        char *argv[];
                    544: {
                    545:        register struct cmd *c;
                    546: 
                    547:        if (argc == 1) {
                    548:                printf("Commands may be abbreviated.  Commands are:\n\n");
                    549:                for (c = cmdtab; c->name; c++)
                    550:                        printf("%-*s\t%s\n", HELPINDENT, c->name, c->help);
                    551:                return;
                    552:        }
                    553:        while (--argc > 0) {
                    554:                register char *arg;
                    555:                arg = *++argv;
                    556:                c = getcmd(arg);
                    557:                if (c == (struct cmd *)-1)
                    558:                        printf("?Ambiguous help command %s\n", arg);
                    559:                else if (c == (struct cmd *)0)
                    560:                        printf("?Invalid help command %s\n", arg);
                    561:                else
                    562:                        printf("%s\n", c->help);
                    563:        }
                    564: }
                    565: 
                    566: /*
                    567:  * Call routine with argc, argv set from args (terminated by 0).
                    568:  */
                    569: /* VARARGS2 */
                    570: call(routine, args)
                    571:        int (*routine)();
                    572:        int args;
                    573: {
                    574:        register int *argp;
                    575:        register int argc;
                    576: 
                    577:        for (argc = 0, argp = &args; *argp++ != 0; argc++)
                    578:                ;
                    579:        (*routine)(argc, &args);
                    580: }
                    581: 
                    582: /*VARARGS*/
                    583: settrace()
                    584: {
                    585:        trace = !trace;
                    586:        printf("Packet tracing %s.\n", trace ? "on" : "off");
                    587: }
                    588: 
                    589: /*VARARGS*/
                    590: setverbose()
                    591: {
                    592:        verbose = !verbose;
                    593:        printf("Verbose mode %s.\n", verbose ? "on" : "off");
                    594: }

unix.superglobalmegacorp.com

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