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