]> git.cameronkatri.com Git - apple_cmds.git/blob - remote_cmds/tftp.tproj/main.c
remote_cmds: All compiling
[apple_cmds.git] / remote_cmds / tftp.tproj / main.c
1 /* $NetBSD: main.c,v 1.19 2003/10/02 23:31:52 itojun Exp $ */
2
3 /*
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #ifndef lint
33 __attribute__((__used__))
34 static const char copyright[] =
35 "@(#) Copyright (c) 1983, 1993\n\
36 The Regents of the University of California. All rights reserved.\n";
37 #endif
38
39 #if 0
40 #ifndef lint
41 static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93";
42 #endif
43 #endif
44
45 #include <sys/cdefs.h>
46 __FBSDID("$FreeBSD: src/usr.bin/tftp/main.c,v 1.22 2005/10/19 15:37:42 stefanf Exp $");
47
48 /* Many bug fixes are from Jim Guyton <guyton@rand-unix> */
49
50 /*
51 * TFTP User Program -- Command Interface.
52 */
53 #include <sys/param.h>
54 #include <sys/types.h>
55 #include <sys/socket.h>
56 #include <sys/file.h>
57 #include <sys/param.h>
58
59 #include <netinet/in.h>
60
61 #include <arpa/inet.h>
62 #include <arpa/tftp.h>
63
64 #include <ctype.h>
65 #include <fcntl.h>
66 #include <err.h>
67 #include <histedit.h>
68 #include <netdb.h>
69 #include <setjmp.h>
70 #include <signal.h>
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <string.h>
74 #include <unistd.h>
75
76 #include "extern.h"
77
78 #define MAXLINE 200
79 #define TIMEOUT 5 /* secs between rexmt's */
80 #define MAXSEGSIZE 65464
81 struct sockaddr_storage peeraddr;
82 int f;
83 int trace;
84 int verbose;
85 int tsize=0;
86 int tout=0;
87 int def_blksize=SEGSIZE;
88 int blksize=SEGSIZE;
89 int connected;
90 char mode[32];
91 char line[MAXLINE];
92 int margc;
93 #define MAX_MARGV 20
94 char *margv[MAX_MARGV];
95 jmp_buf toplevel;
96 volatile int txrx_error;
97
98 void get(int, char **);
99 void help(int, char **);
100 void intr(int);
101 void modecmd(int, char **);
102 void put(int, char **);
103 void quit(int, char **);
104 void setascii(int, char **);
105 void setbinary(int, char **);
106 void setpeer0(char *, const char *);
107 void setpeer(int, char **);
108 void setrexmt(int, char **);
109 void settimeout(int, char **);
110 void settrace(int, char **);
111 void setverbose(int, char **);
112 #ifdef __APPLE__
113 void setblksize(int, char **);
114 void settsize(int, char **);
115 void settimeoutopt(int, char **);
116 #endif
117 void status(int, char **);
118 #ifdef __APPLE__
119 char *tail(char *);
120 int main(int, char *[]);
121 void intr(int);
122 struct cmd *getcmd(char *);
123 #endif
124
125 static void command(void) __dead2;
126 static const char *command_prompt(void);
127
128 static void getusage(char *);
129 static void makeargv(void);
130 static void putusage(char *);
131 static void settftpmode(const char *);
132
133 char *tail(char *);
134 struct cmd *getcmd(char *);
135
136 #define HELPINDENT (sizeof("connect"))
137
138 struct cmd {
139 const char *name;
140 char *help;
141 void (*handler)(int, char **);
142 };
143
144 char vhelp[] = "toggle verbose mode";
145 char thelp[] = "toggle packet tracing";
146 #ifdef __APPLE__
147 char tshelp[] = "toggle extended tsize option";
148 char tohelp[] = "toggle extended timeout option";
149 char blhelp[] = "set an alternative blocksize (def. 512)";
150 #endif
151 char chelp[] = "connect to remote tftp";
152 char qhelp[] = "exit tftp";
153 char hhelp[] = "print help information";
154 char shelp[] = "send file";
155 char rhelp[] = "receive file";
156 char mhelp[] = "set file transfer mode";
157 char sthelp[] = "show current status";
158 char xhelp[] = "set per-packet retransmission timeout";
159 char ihelp[] = "set total retransmission timeout";
160 char ashelp[] = "set mode to netascii";
161 char bnhelp[] = "set mode to octet";
162
163 struct cmd cmdtab[] = {
164 { "connect", chelp, setpeer },
165 { "mode", mhelp, modecmd },
166 { "put", shelp, put },
167 { "get", rhelp, get },
168 { "quit", qhelp, quit },
169 { "verbose", vhelp, setverbose },
170 #ifdef __APPLE__
171 { "blksize", blhelp, setblksize },
172 { "tsize", tshelp, settsize },
173 #endif
174 { "trace", thelp, settrace },
175 { "status", sthelp, status },
176 { "binary", bnhelp, setbinary },
177 { "ascii", ashelp, setascii },
178 { "rexmt", xhelp, setrexmt },
179 { "timeout", ihelp, settimeout },
180 #ifdef __APPLE__
181 { "tout", tohelp, settimeoutopt },
182 #endif
183 { "?", hhelp, help },
184 { NULL, NULL, NULL }
185 };
186
187 int
188 main(argc, argv)
189 int argc;
190 char *argv[];
191 {
192 int c;
193
194 f = -1;
195 strcpy(mode, "netascii");
196 signal(SIGINT, intr);
197
198 setprogname(argv[0]);
199 while ((c = getopt(argc, argv, "e")) != -1) {
200 switch (c) {
201 case 'e':
202 blksize = MAXSEGSIZE;
203 strcpy(mode, "octet");
204 tsize = 1;
205 tout = 1;
206 break;
207 default:
208 printf("usage: %s [-e] host-name [port]\n",
209 getprogname());
210 exit(1);
211 }
212 }
213 argc -= optind;
214 argv += optind;
215
216 if (argc >= 1) {
217 if (setjmp(toplevel) != 0)
218 exit(txrx_error);
219 argc++;
220 argv--;
221 setpeer(argc, argv);
222 }
223 if (setjmp(toplevel) != 0)
224 (void)putchar('\n');
225 command();
226 return (0);
227 }
228
229 char hostname[MAXHOSTNAMELEN];
230
231 void
232 setpeer0(host, port)
233 char *host;
234 const char *port;
235 {
236 struct addrinfo hints, *res0, *res;
237 int error, soopt;
238 struct sockaddr_storage ss;
239 const char *cause = "unknown";
240
241 if (connected) {
242 close(f);
243 f = -1;
244 }
245 connected = 0;
246
247 memset(&hints, 0, sizeof(hints));
248 hints.ai_family = PF_UNSPEC;
249 hints.ai_socktype = SOCK_DGRAM;
250 hints.ai_protocol = IPPROTO_UDP;
251 hints.ai_flags = AI_CANONNAME;
252 if (!port)
253 port = "tftp";
254 error = getaddrinfo(host, port, &hints, &res0);
255 if (error) {
256 warnx("%s", gai_strerror(error));
257 return;
258 }
259
260 for (res = res0; res; res = res->ai_next) {
261 if (res->ai_addrlen > sizeof(peeraddr))
262 continue;
263 f = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
264 if (f < 0) {
265 cause = "socket";
266 continue;
267 }
268
269 memset(&ss, 0, sizeof(ss));
270 ss.ss_family = res->ai_family;
271 ss.ss_len = res->ai_addrlen;
272 if (bind(f, (struct sockaddr *)&ss, ss.ss_len) < 0) {
273 cause = "bind";
274 close(f);
275 f = -1;
276 continue;
277 }
278
279 break;
280 }
281
282 if (f >= 0) {
283 soopt = 65536;
284 if (setsockopt(f, SOL_SOCKET, SO_SNDBUF, &soopt, sizeof(soopt))
285 < 0) {
286 close(f);
287 f = -1;
288 cause = "setsockopt SNDBUF";
289 }
290 if (setsockopt(f, SOL_SOCKET, SO_RCVBUF, &soopt, sizeof(soopt))
291 < 0) {
292 close(f);
293 f = -1;
294 cause = "setsockopt RCVBUF";
295 }
296 }
297
298 if (f < 0)
299 warn("%s", cause);
300 else {
301 /* res->ai_addr <= sizeof(peeraddr) is guaranteed */
302 memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
303 if (res->ai_canonname) {
304 (void) strlcpy(hostname, res->ai_canonname,
305 sizeof(hostname));
306 } else
307 (void) strlcpy(hostname, host, sizeof(hostname));
308 connected = 1;
309 }
310
311 freeaddrinfo(res0);
312 }
313
314 void
315 setpeer(argc, argv)
316 int argc;
317 char *argv[];
318 {
319
320 if (argc < 2) {
321 strcpy(line, "Connect ");
322 printf("(to) ");
323 fgets(&line[strlen(line)], sizeof line - strlen(line), stdin);
324 makeargv();
325 argc = margc;
326 argv = margv;
327 }
328 if ((argc < 2) || (argc > 3)) {
329 printf("usage: %s [-e] host-name [port]\n", getprogname());
330 return;
331 }
332 if (argc == 3)
333 setpeer0(argv[1], argv[2]);
334 else
335 setpeer0(argv[1], NULL);
336 }
337
338 struct modes {
339 const char *m_name;
340 const char *m_mode;
341 } modes[] = {
342 { "ascii", "netascii" },
343 { "netascii", "netascii" },
344 { "binary", "octet" },
345 { "image", "octet" },
346 { "octet", "octet" },
347 /* { "mail", "mail" }, */
348 { 0, 0 }
349 };
350
351 void
352 modecmd(argc, argv)
353 int argc;
354 char *argv[];
355 {
356 struct modes *p;
357 const char *sep;
358
359 if (argc < 2) {
360 printf("Using %s mode to transfer files.\n", mode);
361 return;
362 }
363 if (argc == 2) {
364 for (p = modes; p->m_name; p++)
365 if (strcmp(argv[1], p->m_name) == 0)
366 break;
367 if (p->m_name) {
368 settftpmode(p->m_mode);
369 return;
370 }
371 printf("%s: unknown mode\n", argv[1]);
372 /* drop through and print usage message */
373 }
374
375 printf("usage: %s [", argv[0]);
376 sep = " ";
377 for (p = modes; p->m_name; p++) {
378 printf("%s%s", sep, p->m_name);
379 if (*sep == ' ')
380 sep = " | ";
381 }
382 printf(" ]\n");
383 return;
384 }
385
386 void
387 setbinary(argc, argv)
388 int argc __unused;
389 char *argv[] __unused;
390 {
391
392 settftpmode("octet");
393 }
394
395 void
396 setascii(argc, argv)
397 int argc __unused;
398 char *argv[] __unused;
399 {
400
401 settftpmode("netascii");
402 }
403
404 static void
405 settftpmode(newmode)
406 const char *newmode;
407 {
408 strcpy(mode, newmode);
409 if (verbose)
410 printf("mode set to %s\n", mode);
411 }
412
413
414 /*
415 * Send file(s).
416 */
417 void
418 put(argc, argv)
419 int argc;
420 char *argv[];
421 {
422 int fd;
423 int n;
424 char *cp, *targ;
425 #ifdef __APPLE__
426 char targbuf[PATH_MAX];
427 #endif /* __APPLE__ */
428
429 if (argc < 2) {
430 strcpy(line, "send ");
431 printf("(file) ");
432 fgets(&line[strlen(line)], sizeof line - strlen(line), stdin);
433 makeargv();
434 argc = margc;
435 argv = margv;
436 }
437 if (argc < 2) {
438 putusage(argv[0]);
439 return;
440 }
441 targ = argv[argc - 1];
442 if (rindex(argv[argc - 1], ':')) {
443 char *lcp;
444
445 for (n = 1; n < argc - 1; n++)
446 if (index(argv[n], ':')) {
447 putusage(argv[0]);
448 return;
449 }
450 lcp = argv[argc - 1];
451 targ = rindex(lcp, ':');
452 *targ++ = 0;
453 if (lcp[0] == '[' && lcp[strlen(lcp) - 1] == ']') {
454 lcp[strlen(lcp) - 1] = '\0';
455 lcp++;
456 }
457 setpeer0(lcp, NULL);
458 }
459 if (!connected) {
460 printf("No target machine specified.\n");
461 return;
462 }
463 if (argc < 4) {
464 cp = argc == 2 ? tail(targ) : argv[1];
465 fd = open(cp, O_RDONLY);
466 if (fd < 0) {
467 warn("%s", cp);
468 return;
469 }
470 if (verbose)
471 printf("putting %s to %s:%s [%s]\n",
472 cp, hostname, targ, mode);
473 xmitfile(fd, targ, mode);
474 return;
475 }
476 /* this assumes the target is a directory */
477 /* on a remote unix system. hmmmm. */
478 #ifdef __APPLE__
479 snprintf(targbuf, sizeof(targbuf), "%s/", targ);
480 cp = targbuf + strlen(targbuf);
481 #else /* !__APPLE__ */
482 cp = index(targ, '\0');
483 *cp++ = '/';
484 #endif /* __APPLE__ */
485 for (n = 1; n < argc - 1; n++) {
486 #ifdef __APPLE__
487 strlcpy(cp, tail(argv[n]), sizeof(targbuf) - (cp - targbuf));
488 #else /* !__APPLE__ */
489 strcpy(cp, tail(argv[n]));
490 #endif /* __APPLE__ */
491 fd = open(argv[n], O_RDONLY);
492 if (fd < 0) {
493 warn("%s", argv[n]);
494 continue;
495 }
496 if (verbose)
497 printf("putting %s to %s:%s [%s]\n",
498 #ifdef __APPLE__
499 argv[n], hostname, targbuf, mode);
500 #else /* !__APPLE__ */
501 argv[n], hostname, targ, mode);
502 #endif /* __APPLE__ */
503 xmitfile(fd, targ, mode);
504 }
505 }
506
507 static void
508 putusage(s)
509 char *s;
510 {
511 printf("usage: %s file ... host:target, or\n", s);
512 printf(" %s file ... target (when already connected)\n", s);
513 }
514
515 /*
516 * Receive file(s).
517 */
518 void
519 get(argc, argv)
520 int argc;
521 char *argv[];
522 {
523 int fd;
524 int n;
525 char *cp;
526 char *src;
527
528 if (argc < 2) {
529 strcpy(line, "get ");
530 printf("(files) ");
531 fgets(&line[strlen(line)], sizeof line - strlen(line), stdin);
532 makeargv();
533 argc = margc;
534 argv = margv;
535 }
536 if (argc < 2) {
537 getusage(argv[0]);
538 return;
539 }
540 if (!connected) {
541 for (n = 1; n < argc ; n++)
542 if (rindex(argv[n], ':') == 0) {
543 getusage(argv[0]);
544 return;
545 }
546 }
547 for (n = 1; n < argc ; n++) {
548 src = rindex(argv[n], ':');
549 if (src == NULL)
550 src = argv[n];
551 else {
552 char *lcp;
553
554 *src++ = 0;
555 lcp = argv[n];
556 if (lcp[0] == '[' && lcp[strlen(lcp) - 1] == ']') {
557 lcp[strlen(lcp) - 1] = '\0';
558 lcp++;
559 }
560 setpeer0(lcp, NULL);
561 if (!connected)
562 continue;
563 }
564 if (argc < 4) {
565 cp = argc == 3 ? argv[2] : tail(src);
566 fd = creat(cp, 0644);
567 if (fd < 0) {
568 warn("%s", cp);
569 return;
570 }
571 if (verbose)
572 printf("getting from %s:%s to %s [%s]\n",
573 hostname, src, cp, mode);
574 recvfile(fd, src, mode);
575 break;
576 }
577 cp = tail(src); /* new .. jdg */
578 fd = creat(cp, 0644);
579 if (fd < 0) {
580 warn("%s", cp);
581 continue;
582 }
583 if (verbose)
584 printf("getting from %s:%s to %s [%s]\n",
585 hostname, src, cp, mode);
586 recvfile(fd, src, mode);
587 }
588 }
589
590 static void
591 getusage(s)
592 char *s;
593 {
594 printf("usage: %s host:file host:file ... file, or\n", s);
595 printf(" %s file file ... file if connected\n", s);
596 }
597
598 void
599 setblksize(argc, argv)
600 int argc;
601 char *argv[];
602 {
603 int t;
604
605 if (argc < 2) {
606 strcpy(line, "blksize ");
607 printf("(blksize) ");
608 fgets(&line[strlen(line)], sizeof line - strlen(line), stdin);
609 makeargv();
610 argc = margc;
611 argv = margv;
612 }
613 if (argc != 2) {
614 printf("usage: %s value\n", argv[0]);
615 return;
616 }
617 t = atoi(argv[1]);
618 if (t < 8 || t > 65464)
619 printf("%s: bad value\n", argv[1]);
620 else
621 blksize = t;
622 }
623
624 int def_rexmtval = TIMEOUT;
625 int rexmtval = TIMEOUT;
626
627 void
628 setrexmt(argc, argv)
629 int argc;
630 char *argv[];
631 {
632 int t;
633
634 if (argc < 2) {
635 strcpy(line, "Rexmt-timeout ");
636 printf("(value) ");
637 fgets(&line[strlen(line)], sizeof line - strlen(line), stdin);
638 makeargv();
639 argc = margc;
640 argv = margv;
641 }
642 if (argc != 2) {
643 printf("usage: %s value\n", argv[0]);
644 return;
645 }
646 t = atoi(argv[1]);
647 if (t < 0)
648 printf("%s: bad value\n", argv[1]);
649 else
650 rexmtval = t;
651 }
652
653 int maxtimeout = 5 * TIMEOUT;
654
655 void
656 settimeout(argc, argv)
657 int argc;
658 char *argv[];
659 {
660 int t;
661
662 if (argc < 2) {
663 strcpy(line, "Maximum-timeout ");
664 printf("(value) ");
665 fgets(&line[strlen(line)], sizeof line - strlen(line), stdin);
666 makeargv();
667 argc = margc;
668 argv = margv;
669 }
670 if (argc != 2) {
671 printf("usage: %s value\n", argv[0]);
672 return;
673 }
674 t = atoi(argv[1]);
675 if (t < 0)
676 printf("%s: bad value\n", argv[1]);
677 else
678 maxtimeout = t;
679 }
680
681 void
682 status(argc, argv)
683 int argc __unused;
684 char *argv[] __unused;
685 {
686 if (connected)
687 printf("Connected to %s.\n", hostname);
688 else
689 printf("Not connected.\n");
690 printf("Mode: %s Verbose: %s Tracing: %s\n", mode,
691 verbose ? "on" : "off", trace ? "on" : "off");
692 printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n",
693 rexmtval, maxtimeout);
694 }
695
696 void
697 intr(dummy)
698 int dummy __unused;
699 {
700
701 signal(SIGALRM, SIG_IGN);
702 alarm(0);
703 longjmp(toplevel, -1);
704 }
705
706 char *
707 tail(filename)
708 char *filename;
709 {
710 char *s;
711
712 while (*filename) {
713 s = rindex(filename, '/');
714 if (s == NULL)
715 break;
716 if (s[1])
717 return (s + 1);
718 *s = '\0';
719 }
720 return (filename);
721 }
722
723 static const char *
724 command_prompt()
725 {
726
727 return ("tftp> ");
728 }
729
730 /*
731 * Command parser.
732 */
733 static void
734 command()
735 {
736 HistEvent he;
737 struct cmd *c;
738 static EditLine *el;
739 static History *hist;
740 const char *bp;
741 char *cp;
742 int len, num, vrbose;
743
744 vrbose = isatty(0);
745 if (vrbose) {
746 el = el_init("tftp", stdin, stdout, stderr);
747 hist = history_init();
748 history(hist, &he, H_SETSIZE, 100);
749 el_set(el, EL_HIST, history, hist);
750 el_set(el, EL_EDITOR, "emacs");
751 el_set(el, EL_PROMPT, command_prompt);
752 el_set(el, EL_SIGNAL, 1);
753 el_source(el, NULL);
754 }
755 for (;;) {
756 if (vrbose) {
757 if ((bp = el_gets(el, &num)) == NULL || num == 0)
758 exit(0);
759 len = (num > MAXLINE) ? MAXLINE : num;
760 memcpy(line, bp, len);
761 line[len] = '\0';
762 history(hist, &he, H_ENTER, bp);
763 } else {
764 if (fgets(line, sizeof line , stdin) == 0) {
765 if (feof(stdin)) {
766 exit(txrx_error);
767 } else {
768 continue;
769 }
770 }
771 }
772 if ((cp = strchr(line, '\n')))
773 *cp = '\0';
774 if (line[0] == 0)
775 continue;
776 makeargv();
777 if (margc == 0)
778 continue;
779 c = getcmd(margv[0]);
780 if (c == (struct cmd *)-1) {
781 printf("?Ambiguous command\n");
782 continue;
783 }
784 if (c == 0) {
785 printf("?Invalid command\n");
786 continue;
787 }
788 (*c->handler)(margc, margv);
789 }
790 }
791
792 struct cmd *
793 getcmd(name)
794 char *name;
795 {
796 const char *p, *q;
797 struct cmd *c, *found;
798 int nmatches, longest;
799
800 longest = 0;
801 nmatches = 0;
802 found = 0;
803 for (c = cmdtab; (p = c->name) != NULL; c++) {
804 for (q = name; *q == *p++; q++)
805 if (*q == 0) /* exact match? */
806 return (c);
807 if (!*q) { /* the name was a prefix */
808 if (q - name > longest) {
809 longest = q - name;
810 nmatches = 1;
811 found = c;
812 } else if (q - name == longest)
813 nmatches++;
814 }
815 }
816 if (nmatches > 1)
817 return ((struct cmd *)-1);
818 return (found);
819 }
820
821 /*
822 * Slice a string up into argc/argv.
823 */
824 static void
825 makeargv()
826 {
827 char *cp;
828 char **argp = margv;
829
830 margc = 0;
831 if ((cp = strchr(line, '\n')))
832 *cp = '\0';
833 for (cp = line; margc < MAX_MARGV - 1 && *cp;) {
834 while (isspace((unsigned char)*cp))
835 cp++;
836 if (*cp == '\0')
837 break;
838 *argp++ = cp;
839 margc += 1;
840 while (*cp != '\0' && !isspace((unsigned char)*cp))
841 cp++;
842 if (*cp == '\0')
843 break;
844 *cp++ = '\0';
845 }
846 *argp++ = 0;
847 }
848
849 void
850 quit(argc, argv)
851 int argc __unused;
852 char *argv[] __unused;
853 {
854 exit(txrx_error);
855 }
856
857 /*
858 * Help command.
859 */
860 void
861 help(argc, argv)
862 int argc;
863 char *argv[];
864 {
865 struct cmd *c;
866
867 if (argc == 1) {
868 printf("Commands may be abbreviated. Commands are:\n\n");
869 for (c = cmdtab; c->name; c++)
870 printf("%-*s\t%s\n", (int)HELPINDENT, c->name, c->help);
871 return;
872 }
873 while (--argc > 0) {
874 char *arg;
875 arg = *++argv;
876 c = getcmd(arg);
877 if (c == (struct cmd *)-1)
878 printf("?Ambiguous help command %s\n", arg);
879 else if (c == (struct cmd *)0)
880 printf("?Invalid help command %s\n", arg);
881 else
882 printf("%s\n", c->help);
883 }
884 }
885
886 void
887 settrace(argc, argv)
888 int argc __unused;
889 char **argv __unused;
890 {
891 trace = !trace;
892 printf("Packet tracing %s.\n", trace ? "on" : "off");
893 }
894
895 void
896 setverbose(argc, argv)
897 int argc __unused;
898 char **argv __unused;
899 {
900 verbose = !verbose;
901 printf("Verbose mode %s.\n", verbose ? "on" : "off");
902 }
903
904 void
905 settsize(argc, argv)
906 int argc __unused;
907 char **argv __unused;
908 {
909 tsize = !tsize;
910 printf("Tsize mode %s.\n", tsize ? "on" : "off");
911 }
912
913 void
914 settimeoutopt(argc, argv)
915 int argc __unused;
916 char **argv __unused;
917 {
918 tout = !tout;
919 printf("Timeout option %s.\n", tout ? "on" : "off");
920 }