122403Sdist /* 233821Sbostic * Copyright (c) 1983 Regents of the University of California. 333821Sbostic * All rights reserved. 433821Sbostic * 542770Sbostic * %sccs.include.redist.c% 622403Sdist */ 722403Sdist 814553Ssam #ifndef lint 922403Sdist char copyright[] = 1022403Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 1122403Sdist All rights reserved.\n"; 1233821Sbostic #endif /* not lint */ 137769Ssam 1422403Sdist #ifndef lint 15*46861Sbostic static char sccsid[] = "@(#)main.c 5.10 (Berkeley) 03/01/91"; 1633821Sbostic #endif /* not lint */ 1722403Sdist 1826095Sminshall /* Many bug fixes are from Jim Guyton <guyton@rand-unix> */ 1926095Sminshall 207769Ssam /* 217769Ssam * TFTP User Program -- Command Interface. 227769Ssam */ 237769Ssam #include <sys/types.h> 247769Ssam #include <sys/socket.h> 2513017Ssam #include <sys/file.h> 269219Ssam 279219Ssam #include <netinet/in.h> 289219Ssam 297769Ssam #include <signal.h> 307769Ssam #include <stdio.h> 317769Ssam #include <errno.h> 327769Ssam #include <setjmp.h> 337769Ssam #include <ctype.h> 348384Ssam #include <netdb.h> 357769Ssam 3613017Ssam #define TIMEOUT 5 /* secs between rexmt's */ 3713017Ssam 3826095Sminshall struct sockaddr_in sin; 397769Ssam int f; 4026095Sminshall short port; 417769Ssam int trace; 4226095Sminshall int verbose; 437769Ssam int connected; 447769Ssam char mode[32]; 457769Ssam char line[200]; 467769Ssam int margc; 477769Ssam char *margv[20]; 487769Ssam char *prompt = "tftp"; 497769Ssam jmp_buf toplevel; 50*46861Sbostic void intr(); 518384Ssam struct servent *sp; 527769Ssam 5326095Sminshall int quit(), help(), setverbose(), settrace(), status(); 5426095Sminshall int get(), put(), setpeer(), modecmd(), setrexmt(), settimeout(); 5526095Sminshall int setbinary(), setascii(); 567769Ssam 577769Ssam #define HELPINDENT (sizeof("connect")) 587769Ssam 597769Ssam struct cmd { 607769Ssam char *name; 617769Ssam char *help; 627769Ssam int (*handler)(); 637769Ssam }; 647769Ssam 6526095Sminshall char vhelp[] = "toggle verbose mode"; 667769Ssam char thelp[] = "toggle packet tracing"; 677769Ssam char chelp[] = "connect to remote tftp"; 687769Ssam char qhelp[] = "exit tftp"; 697769Ssam char hhelp[] = "print help information"; 707769Ssam char shelp[] = "send file"; 717769Ssam char rhelp[] = "receive file"; 727769Ssam char mhelp[] = "set file transfer mode"; 737769Ssam char sthelp[] = "show current status"; 7413017Ssam char xhelp[] = "set per-packet retransmission timeout"; 7513017Ssam char ihelp[] = "set total retransmission timeout"; 7626095Sminshall char ashelp[] = "set mode to netascii"; 7726095Sminshall char bnhelp[] = "set mode to octet"; 787769Ssam 797769Ssam struct cmd cmdtab[] = { 807769Ssam { "connect", chelp, setpeer }, 8126095Sminshall { "mode", mhelp, modecmd }, 827769Ssam { "put", shelp, put }, 837769Ssam { "get", rhelp, get }, 847769Ssam { "quit", qhelp, quit }, 8526095Sminshall { "verbose", vhelp, setverbose }, 867769Ssam { "trace", thelp, settrace }, 877769Ssam { "status", sthelp, status }, 8826095Sminshall { "binary", bnhelp, setbinary }, 8926095Sminshall { "ascii", ashelp, setascii }, 9013017Ssam { "rexmt", xhelp, setrexmt }, 9113017Ssam { "timeout", ihelp, settimeout }, 927769Ssam { "?", hhelp, help }, 937769Ssam 0 947769Ssam }; 957769Ssam 967769Ssam struct cmd *getcmd(); 977769Ssam char *tail(); 987769Ssam char *index(); 997769Ssam char *rindex(); 1007769Ssam 1017769Ssam main(argc, argv) 1027769Ssam char *argv[]; 1037769Ssam { 10426095Sminshall struct sockaddr_in sin; 10513017Ssam int top; 10613017Ssam 1078384Ssam sp = getservbyname("tftp", "udp"); 1088384Ssam if (sp == 0) { 1098384Ssam fprintf(stderr, "tftp: udp/tftp: unknown service\n"); 1108384Ssam exit(1); 1118384Ssam } 11226110Sminshall f = socket(AF_INET, SOCK_DGRAM, 0); 1137769Ssam if (f < 0) { 11413017Ssam perror("tftp: socket"); 1157769Ssam exit(3); 1167769Ssam } 11726095Sminshall bzero((char *)&sin, sizeof (sin)); 11826095Sminshall sin.sin_family = AF_INET; 119*46861Sbostic if (bind(f, (struct sockaddr *)&sin, sizeof (sin)) < 0) { 12013017Ssam perror("tftp: bind"); 12113017Ssam exit(1); 12213017Ssam } 12326095Sminshall strcpy(mode, "netascii"); 12413017Ssam signal(SIGINT, intr); 1257769Ssam if (argc > 1) { 1267769Ssam if (setjmp(toplevel) != 0) 1277769Ssam exit(0); 1287769Ssam setpeer(argc, argv); 1297769Ssam } 13013017Ssam top = setjmp(toplevel) == 0; 1317769Ssam for (;;) 13213017Ssam command(top); 1337769Ssam } 1347769Ssam 13526095Sminshall char hostname[100]; 1367769Ssam 1377769Ssam setpeer(argc, argv) 1387769Ssam int argc; 1397769Ssam char *argv[]; 1407769Ssam { 1418384Ssam struct hostent *host; 1427769Ssam 1437769Ssam if (argc < 2) { 1447769Ssam strcpy(line, "Connect "); 1457769Ssam printf("(to) "); 1467769Ssam gets(&line[strlen(line)]); 1477769Ssam makeargv(); 1487769Ssam argc = margc; 1497769Ssam argv = margv; 1507769Ssam } 1517769Ssam if (argc > 3) { 1527769Ssam printf("usage: %s host-name [port]\n", argv[0]); 1537769Ssam return; 1547769Ssam } 1558384Ssam host = gethostbyname(argv[1]); 1568384Ssam if (host) { 1579219Ssam sin.sin_family = host->h_addrtype; 1588384Ssam bcopy(host->h_addr, &sin.sin_addr, host->h_length); 15926095Sminshall strcpy(hostname, host->h_name); 1608384Ssam } else { 1619219Ssam sin.sin_family = AF_INET; 1628384Ssam sin.sin_addr.s_addr = inet_addr(argv[1]); 1638384Ssam if (sin.sin_addr.s_addr == -1) { 1648384Ssam connected = 0; 1658384Ssam printf("%s: unknown host\n", argv[1]); 1668384Ssam return; 1678384Ssam } 16826095Sminshall strcpy(hostname, argv[1]); 1697769Ssam } 17026095Sminshall port = sp->s_port; 1717769Ssam if (argc == 3) { 17226095Sminshall port = atoi(argv[2]); 17326095Sminshall if (port < 0) { 1747769Ssam printf("%s: bad port number\n", argv[2]); 1757769Ssam connected = 0; 1767769Ssam return; 1777769Ssam } 17826095Sminshall port = htons(port); 1798384Ssam } 1807769Ssam connected = 1; 1817769Ssam } 1827769Ssam 1837769Ssam struct modes { 1847769Ssam char *m_name; 1857769Ssam char *m_mode; 1867769Ssam } modes[] = { 18726095Sminshall { "ascii", "netascii" }, 18826095Sminshall { "netascii", "netascii" }, 18926095Sminshall { "binary", "octet" }, 19026095Sminshall { "image", "octet" }, 19126103Sminshall { "octet", "octet" }, 19226095Sminshall /* { "mail", "mail" }, */ 1937769Ssam { 0, 0 } 1947769Ssam }; 1957769Ssam 19626095Sminshall modecmd(argc, argv) 1977769Ssam char *argv[]; 1987769Ssam { 1997769Ssam register struct modes *p; 20026095Sminshall char *sep; 2017769Ssam 2027769Ssam if (argc < 2) { 2037769Ssam printf("Using %s mode to transfer files.\n", mode); 2047769Ssam return; 2057769Ssam } 20626095Sminshall if (argc == 2) { 20726095Sminshall for (p = modes; p->m_name; p++) 20826095Sminshall if (strcmp(argv[1], p->m_name) == 0) 20926095Sminshall break; 21026095Sminshall if (p->m_name) { 21126095Sminshall setmode(p->m_mode); 21226095Sminshall return; 21326095Sminshall } 2147769Ssam printf("%s: unknown mode\n", argv[1]); 21526095Sminshall /* drop through and print usage message */ 21626095Sminshall } 21726095Sminshall 21826095Sminshall printf("usage: %s [", argv[0]); 21926095Sminshall sep = " "; 22026095Sminshall for (p = modes; p->m_name; p++) { 22126095Sminshall printf("%s%s", sep, p->m_name); 22226095Sminshall if (*sep == ' ') 22326095Sminshall sep = " | "; 22426095Sminshall } 22526095Sminshall printf(" ]\n"); 22626095Sminshall return; 2277769Ssam } 2287769Ssam 22926095Sminshall setbinary(argc, argv) 23026095Sminshall char *argv[]; 23126095Sminshall { setmode("octet"); 23226095Sminshall } 23326095Sminshall 23426095Sminshall setascii(argc, argv) 23526095Sminshall char *argv[]; 23626095Sminshall { setmode("netascii"); 23726095Sminshall } 23826095Sminshall 23926095Sminshall setmode(newmode) 24026095Sminshall char *newmode; 24126095Sminshall { 24226095Sminshall strcpy(mode, newmode); 24326095Sminshall if (verbose) 24426095Sminshall printf("mode set to %s\n", mode); 24526095Sminshall } 24626095Sminshall 24726095Sminshall 2487769Ssam /* 2497769Ssam * Send file(s). 2507769Ssam */ 2517769Ssam put(argc, argv) 2527769Ssam char *argv[]; 2537769Ssam { 2547769Ssam int fd; 25526095Sminshall register int n; 2567769Ssam register char *cp, *targ; 2577769Ssam 2587769Ssam if (argc < 2) { 2597769Ssam strcpy(line, "send "); 2607769Ssam printf("(file) "); 2617769Ssam gets(&line[strlen(line)]); 2627769Ssam makeargv(); 2637769Ssam argc = margc; 2647769Ssam argv = margv; 2657769Ssam } 2667769Ssam if (argc < 2) { 2677769Ssam putusage(argv[0]); 2687769Ssam return; 2697769Ssam } 2707769Ssam targ = argv[argc - 1]; 2717769Ssam if (index(argv[argc - 1], ':')) { 2728384Ssam char *cp; 2738384Ssam struct hostent *hp; 2747769Ssam 2757769Ssam for (n = 1; n < argc - 1; n++) 2767769Ssam if (index(argv[n], ':')) { 2777769Ssam putusage(argv[0]); 2787769Ssam return; 2797769Ssam } 2808384Ssam cp = argv[argc - 1]; 2818384Ssam targ = index(cp, ':'); 2827769Ssam *targ++ = 0; 2838384Ssam hp = gethostbyname(cp); 28435788Sbostic if (hp == NULL) { 28535788Sbostic fprintf(stderr, "tftp: %s: ", cp); 28635788Sbostic herror((char *)NULL); 2877769Ssam return; 2887769Ssam } 2899219Ssam bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); 2908384Ssam sin.sin_family = hp->h_addrtype; 2917769Ssam connected = 1; 29226095Sminshall strcpy(hostname, hp->h_name); 2937769Ssam } 2947769Ssam if (!connected) { 2957769Ssam printf("No target machine specified.\n"); 2967769Ssam return; 2977769Ssam } 2987769Ssam if (argc < 4) { 2997769Ssam cp = argc == 2 ? tail(targ) : argv[1]; 30013017Ssam fd = open(cp, O_RDONLY); 3017769Ssam if (fd < 0) { 30213017Ssam fprintf(stderr, "tftp: "); perror(cp); 3037769Ssam return; 3047769Ssam } 30526095Sminshall if (verbose) 30626095Sminshall printf("putting %s to %s:%s [%s]\n", 30726095Sminshall cp, hostname, targ, mode); 30826095Sminshall sin.sin_port = port; 30926095Sminshall sendfile(fd, targ, mode); 3107769Ssam return; 3117769Ssam } 31226095Sminshall /* this assumes the target is a directory */ 31326095Sminshall /* on a remote unix system. hmmmm. */ 3147769Ssam cp = index(targ, '\0'); 3157769Ssam *cp++ = '/'; 3167769Ssam for (n = 1; n < argc - 1; n++) { 3177769Ssam strcpy(cp, tail(argv[n])); 31813017Ssam fd = open(argv[n], O_RDONLY); 3197769Ssam if (fd < 0) { 32013017Ssam fprintf(stderr, "tftp: "); perror(argv[n]); 3217769Ssam continue; 3227769Ssam } 32326095Sminshall if (verbose) 32426095Sminshall printf("putting %s to %s:%s [%s]\n", 32526095Sminshall argv[n], hostname, targ, mode); 32626095Sminshall sin.sin_port = port; 32726095Sminshall sendfile(fd, targ, mode); 3287769Ssam } 3297769Ssam } 3307769Ssam 3317769Ssam putusage(s) 3327769Ssam char *s; 3337769Ssam { 3347769Ssam printf("usage: %s file ... host:target, or\n", s); 3357769Ssam printf(" %s file ... target (when already connected)\n", s); 3367769Ssam } 3377769Ssam 3387769Ssam /* 3397769Ssam * Receive file(s). 3407769Ssam */ 3417769Ssam get(argc, argv) 3427769Ssam char *argv[]; 3437769Ssam { 3447769Ssam int fd; 34526095Sminshall register int n; 3467769Ssam register char *cp; 3477769Ssam char *src; 3487769Ssam 3497769Ssam if (argc < 2) { 3507769Ssam strcpy(line, "get "); 3517769Ssam printf("(files) "); 3527769Ssam gets(&line[strlen(line)]); 3537769Ssam makeargv(); 3547769Ssam argc = margc; 3557769Ssam argv = margv; 3567769Ssam } 3577769Ssam if (argc < 2) { 3587769Ssam getusage(argv[0]); 3597769Ssam return; 3607769Ssam } 36126095Sminshall if (!connected) { 36226095Sminshall for (n = 1; n < argc ; n++) 3637769Ssam if (index(argv[n], ':') == 0) { 3647769Ssam getusage(argv[0]); 3657769Ssam return; 3667769Ssam } 36726095Sminshall } 36826095Sminshall for (n = 1; n < argc ; n++) { 3697769Ssam src = index(argv[n], ':'); 3707769Ssam if (src == NULL) 3717769Ssam src = argv[n]; 3727769Ssam else { 3738384Ssam struct hostent *hp; 3748384Ssam 3757769Ssam *src++ = 0; 3768384Ssam hp = gethostbyname(argv[n]); 37735788Sbostic if (hp == NULL) { 37835788Sbostic fprintf(stderr, "tftp: %s: ", argv[n]); 37935788Sbostic herror((char *)NULL); 3807769Ssam continue; 3817769Ssam } 3829219Ssam bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); 3838384Ssam sin.sin_family = hp->h_addrtype; 3847769Ssam connected = 1; 38526095Sminshall strcpy(hostname, hp->h_name); 3867769Ssam } 3877769Ssam if (argc < 4) { 3887769Ssam cp = argc == 3 ? argv[2] : tail(src); 3897769Ssam fd = creat(cp, 0644); 3907769Ssam if (fd < 0) { 39113017Ssam fprintf(stderr, "tftp: "); perror(cp); 3927769Ssam return; 3937769Ssam } 39426095Sminshall if (verbose) 39526095Sminshall printf("getting from %s:%s to %s [%s]\n", 39626095Sminshall hostname, src, cp, mode); 39726095Sminshall sin.sin_port = port; 39826095Sminshall recvfile(fd, src, mode); 3997769Ssam break; 4007769Ssam } 40126095Sminshall cp = tail(src); /* new .. jdg */ 40226095Sminshall fd = creat(cp, 0644); 4037769Ssam if (fd < 0) { 40426095Sminshall fprintf(stderr, "tftp: "); perror(cp); 4057769Ssam continue; 4067769Ssam } 40726095Sminshall if (verbose) 40826095Sminshall printf("getting from %s:%s to %s [%s]\n", 40926095Sminshall hostname, src, cp, mode); 41026095Sminshall sin.sin_port = port; 41126095Sminshall recvfile(fd, src, mode); 4127769Ssam } 4137769Ssam } 4147769Ssam 4157769Ssam getusage(s) 41626110Sminshall char * s; 4177769Ssam { 4187769Ssam printf("usage: %s host:file host:file ... file, or\n", s); 4197769Ssam printf(" %s file file ... file if connected\n", s); 4207769Ssam } 4217769Ssam 42213017Ssam int rexmtval = TIMEOUT; 42313017Ssam 42413017Ssam setrexmt(argc, argv) 42513017Ssam char *argv[]; 42613017Ssam { 42713017Ssam int t; 42813017Ssam 42913017Ssam if (argc < 2) { 43013017Ssam strcpy(line, "Rexmt-timeout "); 43113017Ssam printf("(value) "); 43213017Ssam gets(&line[strlen(line)]); 43313017Ssam makeargv(); 43413017Ssam argc = margc; 43513017Ssam argv = margv; 43613017Ssam } 43713017Ssam if (argc != 2) { 43813017Ssam printf("usage: %s value\n", argv[0]); 43913017Ssam return; 44013017Ssam } 44113017Ssam t = atoi(argv[1]); 44213017Ssam if (t < 0) 44313017Ssam printf("%s: bad value\n", t); 44413017Ssam else 44513017Ssam rexmtval = t; 44613017Ssam } 44713017Ssam 44813017Ssam int maxtimeout = 5 * TIMEOUT; 44913017Ssam 45013017Ssam settimeout(argc, argv) 45113017Ssam char *argv[]; 45213017Ssam { 45313017Ssam int t; 45413017Ssam 45513017Ssam if (argc < 2) { 45613017Ssam strcpy(line, "Maximum-timeout "); 45713017Ssam printf("(value) "); 45813017Ssam gets(&line[strlen(line)]); 45913017Ssam makeargv(); 46013017Ssam argc = margc; 46113017Ssam argv = margv; 46213017Ssam } 46313017Ssam if (argc != 2) { 46413017Ssam printf("usage: %s value\n", argv[0]); 46513017Ssam return; 46613017Ssam } 46713017Ssam t = atoi(argv[1]); 46813017Ssam if (t < 0) 46913017Ssam printf("%s: bad value\n", t); 47013017Ssam else 47113017Ssam maxtimeout = t; 47213017Ssam } 47313017Ssam 4747769Ssam status(argc, argv) 4757769Ssam char *argv[]; 4767769Ssam { 4777769Ssam if (connected) 4788384Ssam printf("Connected to %s.\n", hostname); 4797769Ssam else 4807769Ssam printf("Not connected.\n"); 48126095Sminshall printf("Mode: %s Verbose: %s Tracing: %s\n", mode, 48226095Sminshall verbose ? "on" : "off", trace ? "on" : "off"); 48313017Ssam printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n", 48413017Ssam rexmtval, maxtimeout); 4857769Ssam } 4867769Ssam 487*46861Sbostic void 4887769Ssam intr() 4897769Ssam { 49026095Sminshall signal(SIGALRM, SIG_IGN); 49116382Ssam alarm(0); 4927769Ssam longjmp(toplevel, -1); 4937769Ssam } 4947769Ssam 4957769Ssam char * 4967769Ssam tail(filename) 4977769Ssam char *filename; 4987769Ssam { 4997769Ssam register char *s; 5007769Ssam 5017769Ssam while (*filename) { 5027769Ssam s = rindex(filename, '/'); 5037769Ssam if (s == NULL) 5047769Ssam break; 5057769Ssam if (s[1]) 5067769Ssam return (s + 1); 5077769Ssam *s = '\0'; 5087769Ssam } 5097769Ssam return (filename); 5107769Ssam } 5117769Ssam 5127769Ssam /* 5137769Ssam * Command parser. 5147769Ssam */ 5157769Ssam command(top) 5167769Ssam int top; 5177769Ssam { 5187769Ssam register struct cmd *c; 5197769Ssam 5207769Ssam if (!top) 5217769Ssam putchar('\n'); 5227769Ssam for (;;) { 5237769Ssam printf("%s> ", prompt); 52426103Sminshall if (gets(line) == 0) { 52526103Sminshall if (feof(stdin)) { 52626103Sminshall quit(); 52726103Sminshall } else { 52826103Sminshall continue; 52926103Sminshall } 53026103Sminshall } 5317769Ssam if (line[0] == 0) 53213017Ssam continue; 5337769Ssam makeargv(); 5347769Ssam c = getcmd(margv[0]); 5357769Ssam if (c == (struct cmd *)-1) { 5367769Ssam printf("?Ambiguous command\n"); 5377769Ssam continue; 5387769Ssam } 5397769Ssam if (c == 0) { 5407769Ssam printf("?Invalid command\n"); 5417769Ssam continue; 5427769Ssam } 5437769Ssam (*c->handler)(margc, margv); 5447769Ssam } 5457769Ssam } 5467769Ssam 5477769Ssam struct cmd * 5487769Ssam getcmd(name) 5497769Ssam register char *name; 5507769Ssam { 5517769Ssam register char *p, *q; 5527769Ssam register struct cmd *c, *found; 5537769Ssam register int nmatches, longest; 5547769Ssam 5557769Ssam longest = 0; 5567769Ssam nmatches = 0; 5577769Ssam found = 0; 5587769Ssam for (c = cmdtab; p = c->name; c++) { 5597769Ssam for (q = name; *q == *p++; q++) 5607769Ssam if (*q == 0) /* exact match? */ 5617769Ssam return (c); 5627769Ssam if (!*q) { /* the name was a prefix */ 5637769Ssam if (q - name > longest) { 5647769Ssam longest = q - name; 5657769Ssam nmatches = 1; 5667769Ssam found = c; 5677769Ssam } else if (q - name == longest) 5687769Ssam nmatches++; 5697769Ssam } 5707769Ssam } 5717769Ssam if (nmatches > 1) 5727769Ssam return ((struct cmd *)-1); 5737769Ssam return (found); 5747769Ssam } 5757769Ssam 5767769Ssam /* 5777769Ssam * Slice a string up into argc/argv. 5787769Ssam */ 5797769Ssam makeargv() 5807769Ssam { 5817769Ssam register char *cp; 5827769Ssam register char **argp = margv; 5837769Ssam 5847769Ssam margc = 0; 5857769Ssam for (cp = line; *cp;) { 5867769Ssam while (isspace(*cp)) 5877769Ssam cp++; 5887769Ssam if (*cp == '\0') 5897769Ssam break; 5907769Ssam *argp++ = cp; 5917769Ssam margc += 1; 5927769Ssam while (*cp != '\0' && !isspace(*cp)) 5937769Ssam cp++; 5947769Ssam if (*cp == '\0') 5957769Ssam break; 5967769Ssam *cp++ = '\0'; 5977769Ssam } 5987769Ssam *argp++ = 0; 5997769Ssam } 6007769Ssam 6017769Ssam /*VARARGS*/ 6027769Ssam quit() 6037769Ssam { 6047769Ssam exit(0); 6057769Ssam } 6067769Ssam 6077769Ssam /* 6087769Ssam * Help command. 6097769Ssam */ 6107769Ssam help(argc, argv) 6117769Ssam int argc; 6127769Ssam char *argv[]; 6137769Ssam { 6147769Ssam register struct cmd *c; 6157769Ssam 6167769Ssam if (argc == 1) { 6177769Ssam printf("Commands may be abbreviated. Commands are:\n\n"); 6187769Ssam for (c = cmdtab; c->name; c++) 6197769Ssam printf("%-*s\t%s\n", HELPINDENT, c->name, c->help); 6207769Ssam return; 6217769Ssam } 6227769Ssam while (--argc > 0) { 6237769Ssam register char *arg; 6247769Ssam arg = *++argv; 6257769Ssam c = getcmd(arg); 6267769Ssam if (c == (struct cmd *)-1) 6277769Ssam printf("?Ambiguous help command %s\n", arg); 6287769Ssam else if (c == (struct cmd *)0) 6297769Ssam printf("?Invalid help command %s\n", arg); 6307769Ssam else 6317769Ssam printf("%s\n", c->help); 6327769Ssam } 6337769Ssam } 6347769Ssam 6357769Ssam /*VARARGS*/ 6367769Ssam settrace() 6377769Ssam { 6387769Ssam trace = !trace; 6397769Ssam printf("Packet tracing %s.\n", trace ? "on" : "off"); 6407769Ssam } 64126095Sminshall 64226095Sminshall /*VARARGS*/ 64326095Sminshall setverbose() 64426095Sminshall { 64526095Sminshall verbose = !verbose; 64626095Sminshall printf("Verbose mode %s.\n", verbose ? "on" : "off"); 64726095Sminshall } 648