[BACK]Return to main.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tftp

Annotation of src/usr.bin/tftp/main.c, Revision 1.27

1.27    ! mglocker    1: /*     $OpenBSD: main.c,v 1.26 2006/07/24 17:29:58 mglocker Exp $      */
1.1       deraadt     2: /*     $NetBSD: main.c,v 1.6 1995/05/21 16:54:10 mycroft Exp $ */
                      3:
                      4: /*
                      5:  * Copyright (c) 1983, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
1.13      millert    16:  * 3. Neither the name of the University nor the names of its contributors
1.1       deraadt    17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  */
                     32:
                     33: #ifndef lint
1.12      henning    34: static const char copyright[] =
1.1       deraadt    35: "@(#) Copyright (c) 1983, 1993\n\
                     36:        The Regents of the University of California.  All rights reserved.\n";
                     37: #endif /* not lint */
                     38:
                     39: #ifndef lint
                     40: #if 0
                     41: static char sccsid[] = "@(#)main.c     8.1 (Berkeley) 6/6/93";
                     42: #endif
1.25      mglocker   43: static const char rcsid[] =
1.27    ! mglocker   44:     "$OpenBSD: main.c,v 1.26 2006/07/24 17:29:58 mglocker Exp $";
1.1       deraadt    45: #endif /* not lint */
                     46:
                     47: /*
1.25      mglocker   48:  * TFTP User Program -- Command Interface
                     49:  *
                     50:  * This version includes many modifications by Jim Guyton <guyton@rand-unix>
1.1       deraadt    51:  */
1.24      claudio    52:
1.23      millert    53: #include <sys/param.h>
1.1       deraadt    54: #include <sys/socket.h>
                     55: #include <sys/file.h>
                     56:
                     57: #include <netinet/in.h>
                     58: #include <arpa/inet.h>
1.26      mglocker   59: #include <arpa/tftp.h>
1.1       deraadt    60:
                     61: #include <ctype.h>
1.25      mglocker   62: #include <err.h>
1.1       deraadt    63: #include <errno.h>
                     64: #include <netdb.h>
1.25      mglocker   65: #include <poll.h>
1.1       deraadt    66: #include <signal.h>
                     67: #include <stdio.h>
                     68: #include <stdlib.h>
                     69: #include <string.h>
                     70: #include <unistd.h>
                     71:
                     72: #include "extern.h"
                     73:
                     74: #define        LBUFLEN         200             /* size of input buffer */
1.5       deraadt    75: #define        MAXARGV         20
1.24      claudio    76: #define HELPINDENT     (sizeof("connect"))
1.1       deraadt    77:
1.25      mglocker   78: void                    get(int, char **);
                     79: void                    help(int, char **);
                     80: void                    modecmd(int, char **);
                     81: void                    put(int, char **);
                     82: void                    quit(int, char **);
                     83: void                    setascii(int, char **);
                     84: void                    setbinary(int, char **);
                     85: void                    setpeer(int, char **);
                     86: void                    setrexmt(int, char **);
                     87: void                    settimeout(int, char **);
                     88: void                    settrace(int, char **);
                     89: void                    setverbose(int, char **);
1.26      mglocker   90: void                    settsize(int, char **);
                     91: void                    settout(int, char **);
                     92: void                    setblksize(int, char **);
1.25      mglocker   93: void                    status(int, char **);
                     94: int                     readcmd(char *, int, FILE *);
                     95: static void             getusage(char *);
                     96: static int              makeargv(void);
                     97: static void             putusage(char *);
                     98: static void             settftpmode(char *);
                     99: static __dead void      command(void);
                    100: struct cmd             *getcmd(char *);
                    101: char                   *tail(char *);
                    102:
                    103: struct sockaddr_in      peeraddr;
                    104: int                     f;
                    105: short                   port;
                    106: int                     trace;
                    107: int                     verbose;
                    108: int                     connected;
                    109: char                    mode[32];
                    110: char                    line[LBUFLEN];
                    111: int                     margc;
                    112: char                   *margv[MAXARGV+1];
                    113: char                   *prompt = "tftp";
                    114: void                    intr(int);
                    115: struct servent         *sp;
                    116: int                     rexmtval = TIMEOUT;
                    117: int                     maxtimeout = 5 * TIMEOUT;
                    118: char                    hostname[MAXHOSTNAMELEN];
                    119: FILE                   *file = NULL;
                    120: volatile sig_atomic_t   intrflag = 0;
1.26      mglocker  121: char                   *ackbuf;
                    122: int                     has_options = 0;
                    123: int                     opt_tsize = 0;
                    124: int                     opt_tout = 0;
                    125: int                     opt_blksize = 0;
1.1       deraadt   126:
                    127: char   vhelp[] = "toggle verbose mode";
                    128: char   thelp[] = "toggle packet tracing";
                    129: char   chelp[] = "connect to remote tftp";
                    130: char   qhelp[] = "exit tftp";
                    131: char   hhelp[] = "print help information";
                    132: char   shelp[] = "send file";
                    133: char   rhelp[] = "receive file";
                    134: char   mhelp[] = "set file transfer mode";
                    135: char   sthelp[] = "show current status";
                    136: char   xhelp[] = "set per-packet retransmission timeout";
                    137: char   ihelp[] = "set total retransmission timeout";
1.24      claudio   138: char   ashelp[] = "set mode to netascii";
                    139: char   bnhelp[] = "set mode to octet";
1.26      mglocker  140: char   oshelp[] = "toggle tsize option";
                    141: char   othelp[] = "toggle timeout option";
                    142: char   obhelp[] = "set alternative blksize option";
1.1       deraadt   143:
1.25      mglocker  144: struct cmd {
                    145:        char    *name;
                    146:        char    *help;
                    147:        void     (*handler)(int, char **);
                    148: };
                    149:
1.1       deraadt   150: struct cmd cmdtab[] = {
1.25      mglocker  151:        { "connect",    chelp,  setpeer },
                    152:        { "mode",       mhelp,  modecmd },
                    153:        { "put",        shelp,  put },
                    154:        { "get",        rhelp,  get },
                    155:        { "quit",       qhelp,  quit },
                    156:        { "verbose",    vhelp,  setverbose },
                    157:        { "trace",      thelp,  settrace },
                    158:        { "status",     sthelp, status },
                    159:        { "binary",     bnhelp, setbinary },
                    160:        { "ascii",      ashelp, setascii },
                    161:        { "rexmt",      xhelp,  setrexmt },
                    162:        { "timeout",    ihelp,  settimeout },
1.26      mglocker  163:        { "tsize",      oshelp, settsize },
                    164:        { "tout",       othelp, settout },
                    165:        { "blksize",    obhelp, setblksize },
1.25      mglocker  166:        { "help",       hhelp,  help },
                    167:        { "?",          hhelp,  help },
                    168:        { NULL,         NULL,   NULL }
1.1       deraadt   169: };
                    170:
1.24      claudio   171: struct modes {
1.25      mglocker  172:        char    *m_name;
                    173:        char    *m_mode;
1.24      claudio   174: } modes[] = {
                    175:        { "ascii",      "netascii" },
                    176:        { "netascii",   "netascii" },
                    177:        { "binary",     "octet" },
                    178:        { "image",      "octet" },
                    179:        { "octet",      "octet" },
                    180: /*     { "mail",       "mail" }, */
                    181:        { NULL,         NULL }
                    182: };
                    183:
1.1       deraadt   184: int
1.14      deraadt   185: main(int argc, char *argv[])
1.1       deraadt   186: {
1.25      mglocker  187:        struct sockaddr_in      s_in;
1.1       deraadt   188:
1.24      claudio   189:        /* socket, bind */
1.1       deraadt   190:        sp = getservbyname("tftp", "udp");
1.6       mickey    191:        if (sp == 0)
                    192:                errx(1, "udp/tftp: unknown service");
1.1       deraadt   193:        f = socket(AF_INET, SOCK_DGRAM, 0);
1.6       mickey    194:        if (f < 0)
1.21      deraadt   195:                err(3, "socket");
1.24      claudio   196:        bzero((char *)&s_in, sizeof(s_in));
1.1       deraadt   197:        s_in.sin_family = AF_INET;
1.24      claudio   198:        if (bind(f, (struct sockaddr *)&s_in, sizeof(s_in)) < 0)
1.21      deraadt   199:                err(1, "bind");
1.24      claudio   200:
                    201:        /* set default transfer mode */
                    202:        strlcpy(mode, "netascii", sizeof(mode));
                    203:
                    204:        /* set peer if given */
                    205:        if (argc > 1)
                    206:                setpeer(argc, argv);
                    207:
                    208:        /* catch SIGINT */
1.1       deraadt   209:        signal(SIGINT, intr);
1.24      claudio   210:
1.26      mglocker  211:        /* allocate memory for packets */
                    212:        if ((ackbuf = malloc(SEGSIZE_MAX + 4)) == NULL)
                    213:                err(1, "malloc");
                    214:
1.24      claudio   215:        /* command prompt */
1.1       deraadt   216:        command();
1.24      claudio   217:
1.7       pvalchev  218:        return (0);
1.1       deraadt   219: }
                    220:
                    221: void
1.14      deraadt   222: setpeer(int argc, char *argv[])
1.1       deraadt   223: {
1.25      mglocker  224:        struct hostent  *host;
1.1       deraadt   225:
                    226:        if (argc < 2) {
1.25      mglocker  227:                strlcpy(line, "Connect ", sizeof(line));
1.1       deraadt   228:                printf("(to) ");
1.25      mglocker  229:                readcmd(&line[strlen(line)], LBUFLEN - strlen(line), stdin);
1.5       deraadt   230:                if (makeargv())
                    231:                        return;
1.1       deraadt   232:                argc = margc;
                    233:                argv = margv;
                    234:        }
                    235:        if ((argc < 2) || (argc > 3)) {
1.20      jmc       236:                printf("usage: %s [host [port]]\n", argv[0]);
1.1       deraadt   237:                return;
                    238:        }
                    239:        if (inet_aton(argv[1], &peeraddr.sin_addr) != 0) {
                    240:                peeraddr.sin_family = AF_INET;
1.25      mglocker  241:                (void)strncpy(hostname, argv[1], sizeof(hostname));
                    242:                hostname[sizeof(hostname) - 1] = '\0';
1.1       deraadt   243:        } else {
                    244:                host = gethostbyname(argv[1]);
                    245:                if (host == 0) {
                    246:                        connected = 0;
                    247:                        printf("%s: unknown host\n", argv[1]);
                    248:                        return;
                    249:                }
                    250:                peeraddr.sin_family = host->h_addrtype;
                    251:                bcopy(host->h_addr, &peeraddr.sin_addr, host->h_length);
1.25      mglocker  252:                (void)strlcpy(hostname, host->h_name, sizeof(hostname));
1.1       deraadt   253:        }
                    254:        port = sp->s_port;
                    255:        if (argc == 3) {
                    256:                port = atoi(argv[2]);
                    257:                if (port < 0) {
                    258:                        printf("%s: bad port number\n", argv[2]);
                    259:                        connected = 0;
                    260:                        return;
                    261:                }
                    262:                port = htons(port);
                    263:        }
                    264:        connected = 1;
                    265: }
                    266:
                    267: void
1.14      deraadt   268: modecmd(int argc, char *argv[])
1.1       deraadt   269: {
1.25      mglocker  270:        struct modes    *p;
                    271:        char            *sep;
1.1       deraadt   272:
                    273:        if (argc < 2) {
                    274:                printf("Using %s mode to transfer files.\n", mode);
                    275:                return;
                    276:        }
                    277:        if (argc == 2) {
1.8       mpech     278:                for (p = modes; p->m_name != NULL; p++)
1.1       deraadt   279:                        if (strcmp(argv[1], p->m_name) == 0)
                    280:                                break;
                    281:                if (p->m_name) {
                    282:                        settftpmode(p->m_mode);
                    283:                        return;
                    284:                }
                    285:                printf("%s: unknown mode\n", argv[1]);
                    286:                /* drop through and print usage message */
                    287:        }
                    288:
                    289:        printf("usage: %s [", argv[0]);
                    290:        sep = " ";
1.8       mpech     291:        for (p = modes; p->m_name != NULL; p++) {
1.1       deraadt   292:                printf("%s%s", sep, p->m_name);
                    293:                if (*sep == ' ')
                    294:                        sep = " | ";
                    295:        }
                    296:        printf(" ]\n");
1.25      mglocker  297:
1.1       deraadt   298:        return;
                    299: }
                    300:
                    301: void
1.14      deraadt   302: setbinary(int argc, char *argv[])
1.6       mickey    303: {
1.1       deraadt   304:        settftpmode("octet");
                    305: }
                    306:
                    307: void
1.14      deraadt   308: setascii(int argc, char *argv[])
1.1       deraadt   309: {
                    310:        settftpmode("netascii");
                    311: }
                    312:
                    313: static void
1.14      deraadt   314: settftpmode(char *newmode)
1.1       deraadt   315: {
1.25      mglocker  316:        strlcpy(mode, newmode, sizeof(mode));
1.1       deraadt   317:        if (verbose)
                    318:                printf("mode set to %s\n", mode);
                    319: }
                    320:
                    321: /*
                    322:  * Send file(s).
                    323:  */
                    324: void
1.14      deraadt   325: put(int argc, char *argv[])
1.1       deraadt   326: {
1.25      mglocker  327:        int      fd;
                    328:        int      n;
                    329:        char    *cp, *targ;
1.1       deraadt   330:
                    331:        if (argc < 2) {
1.25      mglocker  332:                strlcpy(line, "send ", sizeof(line));
1.1       deraadt   333:                printf("(file) ");
1.24      claudio   334:                readcmd(&line[strlen(line)], LBUFLEN - strlen(line), stdin);
1.5       deraadt   335:                if (makeargv())
                    336:                        return;
1.1       deraadt   337:                argc = margc;
                    338:                argv = margv;
                    339:        }
                    340:        if (argc < 2) {
                    341:                putusage(argv[0]);
                    342:                return;
                    343:        }
                    344:        targ = argv[argc - 1];
1.4       millert   345:        if (strchr(argv[argc - 1], ':')) {
1.25      mglocker  346:                char            *cp;
                    347:                struct hostent  *hp;
1.1       deraadt   348:
                    349:                for (n = 1; n < argc - 1; n++)
1.4       millert   350:                        if (strchr(argv[n], ':')) {
1.1       deraadt   351:                                putusage(argv[0]);
                    352:                                return;
                    353:                        }
                    354:                cp = argv[argc - 1];
1.4       millert   355:                targ = strchr(cp, ':');
1.1       deraadt   356:                *targ++ = 0;
                    357:                hp = gethostbyname(cp);
                    358:                if (hp == NULL) {
1.6       mickey    359:                        warnx("%s: %s", cp, hstrerror(h_errno));
1.1       deraadt   360:                        return;
                    361:                }
                    362:                bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr, hp->h_length);
                    363:                peeraddr.sin_family = hp->h_addrtype;
                    364:                connected = 1;
1.17      deraadt   365:                port = sp->s_port;
1.25      mglocker  366:                strlcpy(hostname, hp->h_name, sizeof(hostname));
1.1       deraadt   367:        }
                    368:        if (!connected) {
                    369:                printf("No target machine specified.\n");
                    370:                return;
                    371:        }
                    372:        if (argc < 4) {
                    373:                cp = argc == 2 ? tail(targ) : argv[1];
                    374:                fd = open(cp, O_RDONLY);
                    375:                if (fd < 0) {
1.6       mickey    376:                        warn("open: %s", cp);
1.1       deraadt   377:                        return;
                    378:                }
                    379:                if (verbose)
                    380:                        printf("putting %s to %s:%s [%s]\n",
1.18      deraadt   381:                            cp, hostname, targ, mode);
1.1       deraadt   382:                peeraddr.sin_port = port;
                    383:                sendfile(fd, targ, mode);
                    384:                return;
                    385:        }
1.18      deraadt   386:
1.24      claudio   387:        /*
                    388:         * this assumes the target is a directory on
                    389:         * on a remote unix system.  hmmmm.
                    390:         */
1.1       deraadt   391:        for (n = 1; n < argc - 1; n++) {
1.12      henning   392:                if (asprintf(&cp, "%s/%s", targ, tail(argv[n])) == -1)
                    393:                        err(1, "asprintf");
1.1       deraadt   394:                fd = open(argv[n], O_RDONLY);
                    395:                if (fd < 0) {
1.6       mickey    396:                        warn("open: %s", argv[n]);
1.22      mpech     397:                        free(cp);
1.1       deraadt   398:                        continue;
                    399:                }
                    400:                if (verbose)
                    401:                        printf("putting %s to %s:%s [%s]\n",
1.18      deraadt   402:                            argv[n], hostname, cp, mode);
1.1       deraadt   403:                peeraddr.sin_port = port;
1.12      henning   404:                sendfile(fd, cp, mode);
                    405:                free(cp);
1.1       deraadt   406:        }
                    407: }
                    408:
                    409: static void
1.14      deraadt   410: putusage(char *s)
1.1       deraadt   411: {
1.19      jmc       412:        printf("usage: %s file [[host:]remotename]\n", s);
1.24      claudio   413:        printf("       %s file1 file2 ... fileN [[host:]remote-directory]\n",
                    414:            s);
1.1       deraadt   415: }
                    416:
                    417: /*
                    418:  * Receive file(s).
                    419:  */
                    420: void
1.14      deraadt   421: get(int argc, char *argv[])
1.1       deraadt   422: {
1.25      mglocker  423:        int      fd;
                    424:        int      n;
                    425:        char    *cp;
                    426:        char    *src;
1.1       deraadt   427:
                    428:        if (argc < 2) {
1.25      mglocker  429:                strlcpy(line, "get ", sizeof(line));
1.1       deraadt   430:                printf("(files) ");
1.25      mglocker  431:                readcmd(&line[strlen(line)], LBUFLEN - strlen(line), stdin);
1.5       deraadt   432:                if (makeargv())
                    433:                        return;
1.1       deraadt   434:                argc = margc;
                    435:                argv = margv;
                    436:        }
                    437:        if (argc < 2) {
                    438:                getusage(argv[0]);
                    439:                return;
                    440:        }
                    441:        if (!connected) {
1.25      mglocker  442:                for (n = 1; n < argc; n++)
1.4       millert   443:                        if (strchr(argv[n], ':') == 0) {
1.1       deraadt   444:                                getusage(argv[0]);
                    445:                                return;
                    446:                        }
                    447:        }
1.25      mglocker  448:        for (n = 1; n < argc; n++) {
1.4       millert   449:                src = strchr(argv[n], ':');
1.1       deraadt   450:                if (src == NULL)
                    451:                        src = argv[n];
                    452:                else {
1.25      mglocker  453:                        struct hostent  *hp;
1.1       deraadt   454:
                    455:                        *src++ = 0;
                    456:                        hp = gethostbyname(argv[n]);
                    457:                        if (hp == NULL) {
1.6       mickey    458:                                warnx("%s: %s", argv[n], hstrerror(h_errno));
1.1       deraadt   459:                                continue;
                    460:                        }
                    461:                        bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr,
                    462:                            hp->h_length);
                    463:                        peeraddr.sin_family = hp->h_addrtype;
                    464:                        connected = 1;
1.25      mglocker  465:                        strlcpy(hostname, hp->h_name, sizeof(hostname));
1.1       deraadt   466:                }
                    467:                if (argc < 4) {
                    468:                        cp = argc == 3 ? argv[2] : tail(src);
                    469:                        fd = creat(cp, 0644);
                    470:                        if (fd < 0) {
1.6       mickey    471:                                warn("create: %s", cp);
1.1       deraadt   472:                                return;
                    473:                        }
                    474:                        if (verbose)
                    475:                                printf("getting from %s:%s to %s [%s]\n",
1.18      deraadt   476:                                    hostname, src, cp, mode);
1.1       deraadt   477:                        peeraddr.sin_port = port;
                    478:                        recvfile(fd, src, mode);
                    479:                        break;
                    480:                }
1.25      mglocker  481:                cp = tail(src); /* new .. jdg */
1.1       deraadt   482:                fd = creat(cp, 0644);
                    483:                if (fd < 0) {
1.6       mickey    484:                        warn("create: %s", cp);
1.1       deraadt   485:                        continue;
                    486:                }
                    487:                if (verbose)
                    488:                        printf("getting from %s:%s to %s [%s]\n",
1.18      deraadt   489:                            hostname, src, cp, mode);
1.1       deraadt   490:                peeraddr.sin_port = port;
                    491:                recvfile(fd, src, mode);
                    492:        }
                    493: }
                    494:
                    495: static void
1.15      deraadt   496: getusage(char *s)
1.1       deraadt   497: {
1.19      jmc       498:        printf("usage: %s [host:]file [localname]\n", s);
                    499:        printf("       %s [host1:]file1 [host2:]file2 ... [hostN:]fileN\n", s);
1.1       deraadt   500: }
                    501:
                    502: void
1.14      deraadt   503: setrexmt(int argc, char *argv[])
1.1       deraadt   504: {
1.26      mglocker  505:        int              t;
                    506:        const char      *errstr;
1.1       deraadt   507:
                    508:        if (argc < 2) {
1.25      mglocker  509:                strlcpy(line, "Rexmt-timeout ", sizeof(line));
1.1       deraadt   510:                printf("(value) ");
1.25      mglocker  511:                readcmd(&line[strlen(line)], LBUFLEN - strlen(line), stdin);
1.5       deraadt   512:                if (makeargv())
                    513:                        return;
1.1       deraadt   514:                argc = margc;
                    515:                argv = margv;
                    516:        }
                    517:        if (argc != 2) {
                    518:                printf("usage: %s value\n", argv[0]);
                    519:                return;
                    520:        }
1.27    ! mglocker  521:        t = strtonum(argv[1], TIMEOUT_MIN, TIMEOUT_MAX, &errstr);
1.26      mglocker  522:        if (errstr)
                    523:                printf("%s: value is %s\n", argv[1], errstr);
1.1       deraadt   524:        else
                    525:                rexmtval = t;
                    526: }
                    527:
                    528: void
1.14      deraadt   529: settimeout(int argc, char *argv[])
1.1       deraadt   530: {
1.27    ! mglocker  531:        int              t;
        !           532:        const char      *errstr;
1.1       deraadt   533:
                    534:        if (argc < 2) {
1.25      mglocker  535:                strlcpy(line, "Maximum-timeout ", sizeof(line));
1.1       deraadt   536:                printf("(value) ");
1.25      mglocker  537:                readcmd(&line[strlen(line)], LBUFLEN - strlen(line), stdin);
1.5       deraadt   538:                if (makeargv())
                    539:                        return;
1.1       deraadt   540:                argc = margc;
                    541:                argv = margv;
                    542:        }
                    543:        if (argc != 2) {
                    544:                printf("usage: %s value\n", argv[0]);
                    545:                return;
                    546:        }
                    547:        t = atoi(argv[1]);
1.27    ! mglocker  548:        t = strtonum(argv[1], TIMEOUT_MIN, TIMEOUT_MAX, &errstr);
        !           549:        if (errstr)
        !           550:                printf("%s: value is %s\n", argv[1], errstr);
1.1       deraadt   551:        else
                    552:                maxtimeout = t;
                    553: }
                    554:
                    555: void
1.14      deraadt   556: status(int argc, char *argv[])
1.1       deraadt   557: {
                    558:        if (connected)
                    559:                printf("Connected to %s.\n", hostname);
                    560:        else
                    561:                printf("Not connected.\n");
1.25      mglocker  562:        printf("Mode: %s Verbose: %s Tracing: %s\n",
                    563:            mode, verbose ? "on" : "off", trace ? "on" : "off");
1.1       deraadt   564:        printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n",
1.25      mglocker  565:            rexmtval, maxtimeout);
1.1       deraadt   566: }
                    567:
                    568: void
1.16      deraadt   569: intr(int signo)
1.1       deraadt   570: {
1.24      claudio   571:        intrflag = 1;
1.1       deraadt   572: }
                    573:
                    574: char *
1.14      deraadt   575: tail(char *filename)
1.1       deraadt   576: {
1.25      mglocker  577:        char    *s;
1.6       mickey    578:
1.1       deraadt   579:        while (*filename) {
1.4       millert   580:                s = strrchr(filename, '/');
1.1       deraadt   581:                if (s == NULL)
                    582:                        break;
                    583:                if (s[1])
                    584:                        return (s + 1);
                    585:                *s = '\0';
                    586:        }
1.25      mglocker  587:
1.1       deraadt   588:        return (filename);
                    589: }
                    590:
                    591: /*
                    592:  * Command parser.
                    593:  */
                    594: static __dead void
1.14      deraadt   595: command(void)
1.1       deraadt   596: {
1.25      mglocker  597:        struct cmd      *c;
1.1       deraadt   598:
                    599:        for (;;) {
                    600:                printf("%s> ", prompt);
1.24      claudio   601:                if (readcmd(line, LBUFLEN, stdin) < 1)
                    602:                        continue;
1.1       deraadt   603:                if ((line[0] == 0) || (line[0] == '\n'))
                    604:                        continue;
1.5       deraadt   605:                if (makeargv())
                    606:                        continue;
1.1       deraadt   607:                if (margc == 0)
                    608:                        continue;
                    609:                c = getcmd(margv[0]);
1.25      mglocker  610:                if (c == (struct cmd *) - 1) {
1.1       deraadt   611:                        printf("?Ambiguous command\n");
                    612:                        continue;
                    613:                }
                    614:                if (c == 0) {
                    615:                        printf("?Invalid command\n");
                    616:                        continue;
                    617:                }
                    618:                (*c->handler)(margc, margv);
                    619:        }
                    620: }
                    621:
                    622: struct cmd *
1.14      deraadt   623: getcmd(char *name)
1.1       deraadt   624: {
1.25      mglocker  625:        char            *p, *q;
                    626:        struct cmd      *c, *found;
                    627:        int              nmatches, longest;
1.1       deraadt   628:
                    629:        longest = 0;
                    630:        nmatches = 0;
                    631:        found = 0;
1.24      claudio   632:        intrflag = 0;
1.1       deraadt   633:        for (c = cmdtab; (p = c->name) != NULL; c++) {
                    634:                for (q = name; *q == *p++; q++)
                    635:                        if (*q == 0)            /* exact match? */
                    636:                                return (c);
                    637:                if (!*q) {                      /* the name was a prefix */
                    638:                        if (q - name > longest) {
                    639:                                longest = q - name;
                    640:                                nmatches = 1;
                    641:                                found = c;
                    642:                        } else if (q - name == longest)
                    643:                                nmatches++;
                    644:                }
                    645:        }
                    646:        if (nmatches > 1)
1.25      mglocker  647:                return ((struct cmd *) - 1);
                    648:
1.1       deraadt   649:        return (found);
                    650: }
                    651:
                    652: /*
                    653:  * Slice a string up into argc/argv.
                    654:  */
1.5       deraadt   655: static int
1.14      deraadt   656: makeargv(void)
1.1       deraadt   657: {
1.25      mglocker  658:        char     *cp;
                    659:        char    **argp = margv;
                    660:        int       ret = 0;
1.1       deraadt   661:
                    662:        margc = 0;
                    663:        for (cp = line; *cp;) {
1.5       deraadt   664:                if (margc >= MAXARGV) {
                    665:                        printf("too many arguments\n");
                    666:                        ret = 1;
                    667:                        break;
                    668:                }
1.1       deraadt   669:                while (isspace(*cp))
                    670:                        cp++;
                    671:                if (*cp == '\0')
                    672:                        break;
                    673:                *argp++ = cp;
                    674:                margc += 1;
                    675:                while (*cp != '\0' && !isspace(*cp))
                    676:                        cp++;
                    677:                if (*cp == '\0')
                    678:                        break;
                    679:                *cp++ = '\0';
                    680:        }
                    681:        *argp++ = 0;
1.25      mglocker  682:
1.5       deraadt   683:        return (ret);
1.1       deraadt   684: }
                    685:
                    686: void
1.14      deraadt   687: quit(int argc, char *argv[])
1.1       deraadt   688: {
                    689:        exit(0);
                    690: }
                    691:
                    692: /*
                    693:  * Help command.
                    694:  */
                    695: void
1.14      deraadt   696: help(int argc, char *argv[])
1.1       deraadt   697: {
1.25      mglocker  698:        struct cmd      *c;
1.1       deraadt   699:
                    700:        if (argc == 1) {
                    701:                printf("Commands may be abbreviated.  Commands are:\n\n");
1.8       mpech     702:                for (c = cmdtab; c->name != NULL; c++)
1.1       deraadt   703:                        printf("%-*s\t%s\n", (int)HELPINDENT, c->name, c->help);
                    704:                return;
                    705:        }
                    706:        while (--argc > 0) {
1.9       mpech     707:                char *arg;
1.1       deraadt   708:                arg = *++argv;
                    709:                c = getcmd(arg);
1.25      mglocker  710:                if (c == (struct cmd *) - 1)
1.1       deraadt   711:                        printf("?Ambiguous help command %s\n", arg);
                    712:                else if (c == (struct cmd *)0)
                    713:                        printf("?Invalid help command %s\n", arg);
                    714:                else
                    715:                        printf("%s\n", c->help);
                    716:        }
                    717: }
                    718:
                    719: void
1.14      deraadt   720: settrace(int argc, char *argv[])
1.1       deraadt   721: {
                    722:        trace = !trace;
                    723:        printf("Packet tracing %s.\n", trace ? "on" : "off");
                    724: }
                    725:
                    726: void
1.14      deraadt   727: setverbose(int argc, char *argv[])
1.1       deraadt   728: {
                    729:        verbose = !verbose;
                    730:        printf("Verbose mode %s.\n", verbose ? "on" : "off");
1.26      mglocker  731: }
                    732:
                    733: void
                    734: settsize(int argc, char *argv[])
                    735: {
                    736:        opt_tsize = !opt_tsize;
                    737:        printf("Tsize option %s.\n", opt_tsize ? "on" : "off");
                    738:        if (opt_tsize)
                    739:                has_options++;
                    740:        else
                    741:                has_options--;
                    742: }
                    743:
                    744: void
                    745: settout(int argc, char *argv[])
                    746: {
                    747:        opt_tout = !opt_tout;
                    748:        printf("Timeout option %s.\n", opt_tout ? "on" : "off");
                    749:        if (opt_tout)
                    750:                has_options++;
                    751:        else
                    752:                has_options--;
                    753: }
                    754:
                    755: void
                    756: setblksize(int argc, char *argv[])
                    757: {
                    758:        int              t;
                    759:        const char      *errstr;
                    760:
                    761:        if (argc < 2) {
                    762:                strlcpy(line, "Blocksize ", sizeof(line));
                    763:                printf("(value) ");
                    764:                readcmd(&line[strlen(line)], LBUFLEN - strlen(line), stdin);
                    765:                if (makeargv())
                    766:                        return;
                    767:                argc = margc;
                    768:                argv = margv;
                    769:        }
                    770:        if (argc != 2) {
                    771:                printf("usage: %s value\n", argv[0]);
                    772:                return;
                    773:        }
                    774:        t = strtonum(argv[1], SEGSIZE_MIN, SEGSIZE_MAX, &errstr);
                    775:        if (errstr)
                    776:                printf("%s: value is %s\n", argv[1], errstr);
                    777:        else {
                    778:                if (opt_blksize == 0)
                    779:                        has_options++;
                    780:                opt_blksize = t;
                    781:        }
1.24      claudio   782: }
                    783:
                    784: int
                    785: readcmd(char *input, int len, FILE *stream)
                    786: {
                    787:        int             nfds;
                    788:        struct pollfd   pfd[1];
                    789:
                    790:        fflush(stdout);
                    791:
                    792:        pfd[0].fd = 0;
                    793:        pfd[0].events = POLLIN;
                    794:        nfds = poll(pfd, 1, INFTIM);
                    795:        if (nfds == -1) {
                    796:                if (intrflag) {
                    797:                        intrflag = 0;
                    798:                        putchar('\n');
                    799:                        return (0);
                    800:                }
                    801:                exit(1);
                    802:        }
                    803:
                    804:        if (fgets(input, len, stream) == NULL) {
                    805:                if (feof(stdin))
                    806:                        exit(0);
                    807:                else
                    808:                        return (-1);
                    809:        }
                    810:
                    811:        return (1);
1.1       deraadt   812: }