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