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