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

unix.superglobalmegacorp.com

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