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