122403Sdist /* 2*26095Sminshall * Copyright (c) 1985 Regents of the University of California. 322403Sdist * All rights reserved. The Berkeley software License Agreement 422403Sdist * specifies the terms and conditions for redistribution. 522403Sdist */ 622403Sdist 714553Ssam #ifndef lint 822403Sdist char copyright[] = 922403Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 1022403Sdist All rights reserved.\n"; 1122403Sdist #endif not lint 127769Ssam 1322403Sdist #ifndef lint 14*26095Sminshall static char sccsid[] = "@(#)main.c 5.3 (Berkeley) 02/06/86"; 1522403Sdist #endif not lint 1622403Sdist 17*26095Sminshall /* Many bug fixes are from Jim Guyton <guyton@rand-unix> */ 18*26095Sminshall 197769Ssam /* 207769Ssam * TFTP User Program -- Command Interface. 217769Ssam */ 227769Ssam #include <sys/types.h> 237769Ssam #include <sys/socket.h> 2413017Ssam #include <sys/file.h> 259219Ssam 269219Ssam #include <netinet/in.h> 279219Ssam 287769Ssam #include <signal.h> 297769Ssam #include <stdio.h> 307769Ssam #include <errno.h> 317769Ssam #include <setjmp.h> 327769Ssam #include <ctype.h> 338384Ssam #include <netdb.h> 347769Ssam 3513017Ssam #define TIMEOUT 5 /* secs between rexmt's */ 3613017Ssam 37*26095Sminshall struct sockaddr_in sin; 387769Ssam int f; 39*26095Sminshall short port; 407769Ssam int trace; 41*26095Sminshall int verbose; 427769Ssam int connected; 437769Ssam char mode[32]; 447769Ssam char line[200]; 457769Ssam int margc; 467769Ssam char *margv[20]; 477769Ssam char *prompt = "tftp"; 487769Ssam jmp_buf toplevel; 497769Ssam int intr(); 508384Ssam struct servent *sp; 517769Ssam 52*26095Sminshall int quit(), help(), setverbose(), settrace(), status(); 53*26095Sminshall int get(), put(), setpeer(), modecmd(), setrexmt(), settimeout(); 54*26095Sminshall int setbinary(), setascii(); 557769Ssam 567769Ssam #define HELPINDENT (sizeof("connect")) 577769Ssam 587769Ssam struct cmd { 597769Ssam char *name; 607769Ssam char *help; 617769Ssam int (*handler)(); 627769Ssam }; 637769Ssam 64*26095Sminshall char vhelp[] = "toggle verbose mode"; 657769Ssam char thelp[] = "toggle packet tracing"; 667769Ssam char chelp[] = "connect to remote tftp"; 677769Ssam char qhelp[] = "exit tftp"; 687769Ssam char hhelp[] = "print help information"; 697769Ssam char shelp[] = "send file"; 707769Ssam char rhelp[] = "receive file"; 717769Ssam char mhelp[] = "set file transfer mode"; 727769Ssam char sthelp[] = "show current status"; 7313017Ssam char xhelp[] = "set per-packet retransmission timeout"; 7413017Ssam char ihelp[] = "set total retransmission timeout"; 75*26095Sminshall char ashelp[] = "set mode to netascii"; 76*26095Sminshall char bnhelp[] = "set mode to octet"; 777769Ssam 787769Ssam struct cmd cmdtab[] = { 797769Ssam { "connect", chelp, setpeer }, 80*26095Sminshall { "mode", mhelp, modecmd }, 817769Ssam { "put", shelp, put }, 827769Ssam { "get", rhelp, get }, 837769Ssam { "quit", qhelp, quit }, 84*26095Sminshall { "verbose", vhelp, setverbose }, 857769Ssam { "trace", thelp, settrace }, 867769Ssam { "status", sthelp, status }, 87*26095Sminshall { "binary", bnhelp, setbinary }, 88*26095Sminshall { "ascii", ashelp, setascii }, 8913017Ssam { "rexmt", xhelp, setrexmt }, 9013017Ssam { "timeout", ihelp, settimeout }, 917769Ssam { "?", hhelp, help }, 927769Ssam 0 937769Ssam }; 947769Ssam 957769Ssam struct cmd *getcmd(); 967769Ssam char *tail(); 977769Ssam char *index(); 987769Ssam char *rindex(); 997769Ssam 1007769Ssam main(argc, argv) 1017769Ssam char *argv[]; 1027769Ssam { 103*26095Sminshall struct sockaddr_in sin; 10413017Ssam int top; 10513017Ssam 1068384Ssam sp = getservbyname("tftp", "udp"); 1078384Ssam if (sp == 0) { 1088384Ssam fprintf(stderr, "tftp: udp/tftp: unknown service\n"); 1098384Ssam exit(1); 1108384Ssam } 1119262Ssam f = socket(AF_INET, SOCK_DGRAM, 0, 0); 1127769Ssam if (f < 0) { 11313017Ssam perror("tftp: socket"); 1147769Ssam exit(3); 1157769Ssam } 116*26095Sminshall bzero((char *)&sin, sizeof (sin)); 117*26095Sminshall sin.sin_family = AF_INET; 11813017Ssam if (bind(f, &sin, sizeof (sin)) < 0) { 11913017Ssam perror("tftp: bind"); 12013017Ssam exit(1); 12113017Ssam } 122*26095Sminshall strcpy(mode, "netascii"); 12313017Ssam signal(SIGINT, intr); 1247769Ssam if (argc > 1) { 1257769Ssam if (setjmp(toplevel) != 0) 1267769Ssam exit(0); 1277769Ssam setpeer(argc, argv); 1287769Ssam } 12913017Ssam top = setjmp(toplevel) == 0; 1307769Ssam for (;;) 13113017Ssam command(top); 1327769Ssam } 1337769Ssam 134*26095Sminshall char hostname[100]; 1357769Ssam 1367769Ssam setpeer(argc, argv) 1377769Ssam int argc; 1387769Ssam char *argv[]; 1397769Ssam { 1408384Ssam struct hostent *host; 1417769Ssam 1427769Ssam if (argc < 2) { 1437769Ssam strcpy(line, "Connect "); 1447769Ssam printf("(to) "); 1457769Ssam gets(&line[strlen(line)]); 1467769Ssam makeargv(); 1477769Ssam argc = margc; 1487769Ssam argv = margv; 1497769Ssam } 1507769Ssam if (argc > 3) { 1517769Ssam printf("usage: %s host-name [port]\n", argv[0]); 1527769Ssam return; 1537769Ssam } 1548384Ssam host = gethostbyname(argv[1]); 1558384Ssam if (host) { 1569219Ssam sin.sin_family = host->h_addrtype; 1578384Ssam bcopy(host->h_addr, &sin.sin_addr, host->h_length); 158*26095Sminshall strcpy(hostname, host->h_name); 1598384Ssam } else { 1609219Ssam sin.sin_family = AF_INET; 1618384Ssam sin.sin_addr.s_addr = inet_addr(argv[1]); 1628384Ssam if (sin.sin_addr.s_addr == -1) { 1638384Ssam connected = 0; 1648384Ssam printf("%s: unknown host\n", argv[1]); 1658384Ssam return; 1668384Ssam } 167*26095Sminshall strcpy(hostname, argv[1]); 1687769Ssam } 169*26095Sminshall port = sp->s_port; 1707769Ssam if (argc == 3) { 171*26095Sminshall port = atoi(argv[2]); 172*26095Sminshall if (port < 0) { 1737769Ssam printf("%s: bad port number\n", argv[2]); 1747769Ssam connected = 0; 1757769Ssam return; 1767769Ssam } 177*26095Sminshall port = htons(port); 1788384Ssam } 1797769Ssam connected = 1; 1807769Ssam } 1817769Ssam 1827769Ssam struct modes { 1837769Ssam char *m_name; 1847769Ssam char *m_mode; 1857769Ssam } modes[] = { 186*26095Sminshall { "ascii", "netascii" }, 187*26095Sminshall { "netascii", "netascii" }, 188*26095Sminshall { "binary", "octet" }, 189*26095Sminshall { "image", "octet" }, 190*26095Sminshall { "octect", "octet" }, 191*26095Sminshall /* { "mail", "mail" }, */ 1927769Ssam { 0, 0 } 1937769Ssam }; 1947769Ssam 195*26095Sminshall modecmd(argc, argv) 1967769Ssam char *argv[]; 1977769Ssam { 1987769Ssam register struct modes *p; 199*26095Sminshall char *sep; 2007769Ssam 2017769Ssam if (argc < 2) { 2027769Ssam printf("Using %s mode to transfer files.\n", mode); 2037769Ssam return; 2047769Ssam } 205*26095Sminshall if (argc == 2) { 206*26095Sminshall for (p = modes; p->m_name; p++) 207*26095Sminshall if (strcmp(argv[1], p->m_name) == 0) 208*26095Sminshall break; 209*26095Sminshall if (p->m_name) { 210*26095Sminshall setmode(p->m_mode); 211*26095Sminshall return; 212*26095Sminshall } 2137769Ssam printf("%s: unknown mode\n", argv[1]); 214*26095Sminshall /* drop through and print usage message */ 215*26095Sminshall } 216*26095Sminshall 217*26095Sminshall printf("usage: %s [", argv[0]); 218*26095Sminshall sep = " "; 219*26095Sminshall for (p = modes; p->m_name; p++) { 220*26095Sminshall printf("%s%s", sep, p->m_name); 221*26095Sminshall if (*sep == ' ') 222*26095Sminshall sep = " | "; 223*26095Sminshall } 224*26095Sminshall printf(" ]\n"); 225*26095Sminshall return; 2267769Ssam } 2277769Ssam 228*26095Sminshall setbinary(argc, argv) 229*26095Sminshall char *argv[]; 230*26095Sminshall { setmode("octet"); 231*26095Sminshall } 232*26095Sminshall 233*26095Sminshall setascii(argc, argv) 234*26095Sminshall char *argv[]; 235*26095Sminshall { setmode("netascii"); 236*26095Sminshall } 237*26095Sminshall 238*26095Sminshall setmode(newmode) 239*26095Sminshall char *newmode; 240*26095Sminshall { 241*26095Sminshall strcpy(mode, newmode); 242*26095Sminshall if (verbose) 243*26095Sminshall printf("mode set to %s\n", mode); 244*26095Sminshall } 245*26095Sminshall 246*26095Sminshall 2477769Ssam /* 2487769Ssam * Send file(s). 2497769Ssam */ 2507769Ssam put(argc, argv) 2517769Ssam char *argv[]; 2527769Ssam { 2537769Ssam int fd; 254*26095Sminshall register int n; 2557769Ssam register char *cp, *targ; 2567769Ssam 2577769Ssam if (argc < 2) { 2587769Ssam strcpy(line, "send "); 2597769Ssam printf("(file) "); 2607769Ssam gets(&line[strlen(line)]); 2617769Ssam makeargv(); 2627769Ssam argc = margc; 2637769Ssam argv = margv; 2647769Ssam } 2657769Ssam if (argc < 2) { 2667769Ssam putusage(argv[0]); 2677769Ssam return; 2687769Ssam } 2697769Ssam targ = argv[argc - 1]; 2707769Ssam if (index(argv[argc - 1], ':')) { 2718384Ssam char *cp; 2728384Ssam struct hostent *hp; 2737769Ssam 2747769Ssam for (n = 1; n < argc - 1; n++) 2757769Ssam if (index(argv[n], ':')) { 2767769Ssam putusage(argv[0]); 2777769Ssam return; 2787769Ssam } 2798384Ssam cp = argv[argc - 1]; 2808384Ssam targ = index(cp, ':'); 2817769Ssam *targ++ = 0; 2828384Ssam hp = gethostbyname(cp); 2838384Ssam if (hp == 0) { 2848384Ssam printf("%s: Unknown host.\n", cp); 2857769Ssam return; 2867769Ssam } 2879219Ssam bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); 2888384Ssam sin.sin_family = hp->h_addrtype; 2897769Ssam connected = 1; 290*26095Sminshall strcpy(hostname, hp->h_name); 2917769Ssam } 2927769Ssam if (!connected) { 2937769Ssam printf("No target machine specified.\n"); 2947769Ssam return; 2957769Ssam } 2967769Ssam if (argc < 4) { 2977769Ssam cp = argc == 2 ? tail(targ) : argv[1]; 29813017Ssam fd = open(cp, O_RDONLY); 2997769Ssam if (fd < 0) { 30013017Ssam fprintf(stderr, "tftp: "); perror(cp); 3017769Ssam return; 3027769Ssam } 303*26095Sminshall if (verbose) 304*26095Sminshall printf("putting %s to %s:%s [%s]\n", 305*26095Sminshall cp, hostname, targ, mode); 306*26095Sminshall sin.sin_port = port; 307*26095Sminshall sendfile(fd, targ, mode); 3087769Ssam return; 3097769Ssam } 310*26095Sminshall /* this assumes the target is a directory */ 311*26095Sminshall /* on a remote unix system. hmmmm. */ 3127769Ssam cp = index(targ, '\0'); 3137769Ssam *cp++ = '/'; 3147769Ssam for (n = 1; n < argc - 1; n++) { 3157769Ssam strcpy(cp, tail(argv[n])); 31613017Ssam fd = open(argv[n], O_RDONLY); 3177769Ssam if (fd < 0) { 31813017Ssam fprintf(stderr, "tftp: "); perror(argv[n]); 3197769Ssam continue; 3207769Ssam } 321*26095Sminshall if (verbose) 322*26095Sminshall printf("putting %s to %s:%s [%s]\n", 323*26095Sminshall argv[n], hostname, targ, mode); 324*26095Sminshall sin.sin_port = port; 325*26095Sminshall sendfile(fd, targ, mode); 3267769Ssam } 3277769Ssam } 3287769Ssam 3297769Ssam putusage(s) 3307769Ssam char *s; 3317769Ssam { 3327769Ssam printf("usage: %s file ... host:target, or\n", s); 3337769Ssam printf(" %s file ... target (when already connected)\n", s); 3347769Ssam } 3357769Ssam 3367769Ssam /* 3377769Ssam * Receive file(s). 3387769Ssam */ 3397769Ssam get(argc, argv) 3407769Ssam char *argv[]; 3417769Ssam { 3427769Ssam int fd; 343*26095Sminshall register int n; 3447769Ssam register char *cp; 3457769Ssam char *src; 3467769Ssam 3477769Ssam if (argc < 2) { 3487769Ssam strcpy(line, "get "); 3497769Ssam printf("(files) "); 3507769Ssam gets(&line[strlen(line)]); 3517769Ssam makeargv(); 3527769Ssam argc = margc; 3537769Ssam argv = margv; 3547769Ssam } 3557769Ssam if (argc < 2) { 3567769Ssam getusage(argv[0]); 3577769Ssam return; 3587769Ssam } 359*26095Sminshall if (!connected) { 360*26095Sminshall for (n = 1; n < argc ; n++) 3617769Ssam if (index(argv[n], ':') == 0) { 3627769Ssam getusage(argv[0]); 3637769Ssam return; 3647769Ssam } 365*26095Sminshall } 366*26095Sminshall for (n = 1; n < argc ; n++) { 3677769Ssam src = index(argv[n], ':'); 3687769Ssam if (src == NULL) 3697769Ssam src = argv[n]; 3707769Ssam else { 3718384Ssam struct hostent *hp; 3728384Ssam 3737769Ssam *src++ = 0; 3748384Ssam hp = gethostbyname(argv[n]); 3758384Ssam if (hp == 0) { 3767769Ssam printf("%s: Unknown host.\n", argv[n]); 3777769Ssam continue; 3787769Ssam } 3799219Ssam bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); 3808384Ssam sin.sin_family = hp->h_addrtype; 3817769Ssam connected = 1; 382*26095Sminshall strcpy(hostname, hp->h_name); 3837769Ssam } 3847769Ssam if (argc < 4) { 3857769Ssam cp = argc == 3 ? argv[2] : tail(src); 3867769Ssam fd = creat(cp, 0644); 3877769Ssam if (fd < 0) { 38813017Ssam fprintf(stderr, "tftp: "); perror(cp); 3897769Ssam return; 3907769Ssam } 391*26095Sminshall if (verbose) 392*26095Sminshall printf("getting from %s:%s to %s [%s]\n", 393*26095Sminshall hostname, src, cp, mode); 394*26095Sminshall sin.sin_port = port; 395*26095Sminshall recvfile(fd, src, mode); 3967769Ssam break; 3977769Ssam } 398*26095Sminshall cp = tail(src); /* new .. jdg */ 399*26095Sminshall fd = creat(cp, 0644); 4007769Ssam if (fd < 0) { 401*26095Sminshall fprintf(stderr, "tftp: "); perror(cp); 4027769Ssam continue; 4037769Ssam } 404*26095Sminshall if (verbose) 405*26095Sminshall printf("getting from %s:%s to %s [%s]\n", 406*26095Sminshall hostname, src, cp, mode); 407*26095Sminshall sin.sin_port = port; 408*26095Sminshall recvfile(fd, src, mode); 4097769Ssam } 4107769Ssam } 4117769Ssam 4127769Ssam getusage(s) 4137769Ssam { 4147769Ssam printf("usage: %s host:file host:file ... file, or\n", s); 4157769Ssam printf(" %s file file ... file if connected\n", s); 4167769Ssam } 4177769Ssam 41813017Ssam int rexmtval = TIMEOUT; 41913017Ssam 42013017Ssam setrexmt(argc, argv) 42113017Ssam char *argv[]; 42213017Ssam { 42313017Ssam int t; 42413017Ssam 42513017Ssam if (argc < 2) { 42613017Ssam strcpy(line, "Rexmt-timeout "); 42713017Ssam printf("(value) "); 42813017Ssam gets(&line[strlen(line)]); 42913017Ssam makeargv(); 43013017Ssam argc = margc; 43113017Ssam argv = margv; 43213017Ssam } 43313017Ssam if (argc != 2) { 43413017Ssam printf("usage: %s value\n", argv[0]); 43513017Ssam return; 43613017Ssam } 43713017Ssam t = atoi(argv[1]); 43813017Ssam if (t < 0) 43913017Ssam printf("%s: bad value\n", t); 44013017Ssam else 44113017Ssam rexmtval = t; 44213017Ssam } 44313017Ssam 44413017Ssam int maxtimeout = 5 * TIMEOUT; 44513017Ssam 44613017Ssam settimeout(argc, argv) 44713017Ssam char *argv[]; 44813017Ssam { 44913017Ssam int t; 45013017Ssam 45113017Ssam if (argc < 2) { 45213017Ssam strcpy(line, "Maximum-timeout "); 45313017Ssam printf("(value) "); 45413017Ssam gets(&line[strlen(line)]); 45513017Ssam makeargv(); 45613017Ssam argc = margc; 45713017Ssam argv = margv; 45813017Ssam } 45913017Ssam if (argc != 2) { 46013017Ssam printf("usage: %s value\n", argv[0]); 46113017Ssam return; 46213017Ssam } 46313017Ssam t = atoi(argv[1]); 46413017Ssam if (t < 0) 46513017Ssam printf("%s: bad value\n", t); 46613017Ssam else 46713017Ssam maxtimeout = t; 46813017Ssam } 46913017Ssam 4707769Ssam status(argc, argv) 4717769Ssam char *argv[]; 4727769Ssam { 4737769Ssam if (connected) 4748384Ssam printf("Connected to %s.\n", hostname); 4757769Ssam else 4767769Ssam printf("Not connected.\n"); 477*26095Sminshall printf("Mode: %s Verbose: %s Tracing: %s\n", mode, 478*26095Sminshall verbose ? "on" : "off", trace ? "on" : "off"); 47913017Ssam printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n", 48013017Ssam rexmtval, maxtimeout); 4817769Ssam } 4827769Ssam 4837769Ssam intr() 4847769Ssam { 485*26095Sminshall signal(SIGALRM, SIG_IGN); 48616382Ssam alarm(0); 4877769Ssam longjmp(toplevel, -1); 4887769Ssam } 4897769Ssam 4907769Ssam char * 4917769Ssam tail(filename) 4927769Ssam char *filename; 4937769Ssam { 4947769Ssam register char *s; 4957769Ssam 4967769Ssam while (*filename) { 4977769Ssam s = rindex(filename, '/'); 4987769Ssam if (s == NULL) 4997769Ssam break; 5007769Ssam if (s[1]) 5017769Ssam return (s + 1); 5027769Ssam *s = '\0'; 5037769Ssam } 5047769Ssam return (filename); 5057769Ssam } 5067769Ssam 5077769Ssam /* 5087769Ssam * Command parser. 5097769Ssam */ 5107769Ssam command(top) 5117769Ssam int top; 5127769Ssam { 5137769Ssam register struct cmd *c; 5147769Ssam 5157769Ssam if (!top) 5167769Ssam putchar('\n'); 5177769Ssam for (;;) { 5187769Ssam printf("%s> ", prompt); 519*26095Sminshall if (gets(line) == 0) 520*26095Sminshall continue; 5217769Ssam if (line[0] == 0) 52213017Ssam continue; 5237769Ssam makeargv(); 5247769Ssam c = getcmd(margv[0]); 5257769Ssam if (c == (struct cmd *)-1) { 5267769Ssam printf("?Ambiguous command\n"); 5277769Ssam continue; 5287769Ssam } 5297769Ssam if (c == 0) { 5307769Ssam printf("?Invalid command\n"); 5317769Ssam continue; 5327769Ssam } 5337769Ssam (*c->handler)(margc, margv); 5347769Ssam } 5357769Ssam } 5367769Ssam 5377769Ssam struct cmd * 5387769Ssam getcmd(name) 5397769Ssam register char *name; 5407769Ssam { 5417769Ssam register char *p, *q; 5427769Ssam register struct cmd *c, *found; 5437769Ssam register int nmatches, longest; 5447769Ssam 5457769Ssam longest = 0; 5467769Ssam nmatches = 0; 5477769Ssam found = 0; 5487769Ssam for (c = cmdtab; p = c->name; c++) { 5497769Ssam for (q = name; *q == *p++; q++) 5507769Ssam if (*q == 0) /* exact match? */ 5517769Ssam return (c); 5527769Ssam if (!*q) { /* the name was a prefix */ 5537769Ssam if (q - name > longest) { 5547769Ssam longest = q - name; 5557769Ssam nmatches = 1; 5567769Ssam found = c; 5577769Ssam } else if (q - name == longest) 5587769Ssam nmatches++; 5597769Ssam } 5607769Ssam } 5617769Ssam if (nmatches > 1) 5627769Ssam return ((struct cmd *)-1); 5637769Ssam return (found); 5647769Ssam } 5657769Ssam 5667769Ssam /* 5677769Ssam * Slice a string up into argc/argv. 5687769Ssam */ 5697769Ssam makeargv() 5707769Ssam { 5717769Ssam register char *cp; 5727769Ssam register char **argp = margv; 5737769Ssam 5747769Ssam margc = 0; 5757769Ssam for (cp = line; *cp;) { 5767769Ssam while (isspace(*cp)) 5777769Ssam cp++; 5787769Ssam if (*cp == '\0') 5797769Ssam break; 5807769Ssam *argp++ = cp; 5817769Ssam margc += 1; 5827769Ssam while (*cp != '\0' && !isspace(*cp)) 5837769Ssam cp++; 5847769Ssam if (*cp == '\0') 5857769Ssam break; 5867769Ssam *cp++ = '\0'; 5877769Ssam } 5887769Ssam *argp++ = 0; 5897769Ssam } 5907769Ssam 5917769Ssam /*VARARGS*/ 5927769Ssam quit() 5937769Ssam { 5947769Ssam exit(0); 5957769Ssam } 5967769Ssam 5977769Ssam /* 5987769Ssam * Help command. 5997769Ssam */ 6007769Ssam help(argc, argv) 6017769Ssam int argc; 6027769Ssam char *argv[]; 6037769Ssam { 6047769Ssam register struct cmd *c; 6057769Ssam 6067769Ssam if (argc == 1) { 6077769Ssam printf("Commands may be abbreviated. Commands are:\n\n"); 6087769Ssam for (c = cmdtab; c->name; c++) 6097769Ssam printf("%-*s\t%s\n", HELPINDENT, c->name, c->help); 6107769Ssam return; 6117769Ssam } 6127769Ssam while (--argc > 0) { 6137769Ssam register char *arg; 6147769Ssam arg = *++argv; 6157769Ssam c = getcmd(arg); 6167769Ssam if (c == (struct cmd *)-1) 6177769Ssam printf("?Ambiguous help command %s\n", arg); 6187769Ssam else if (c == (struct cmd *)0) 6197769Ssam printf("?Invalid help command %s\n", arg); 6207769Ssam else 6217769Ssam printf("%s\n", c->help); 6227769Ssam } 6237769Ssam } 6247769Ssam 6257769Ssam /*VARARGS*/ 6267769Ssam settrace() 6277769Ssam { 6287769Ssam trace = !trace; 6297769Ssam printf("Packet tracing %s.\n", trace ? "on" : "off"); 6307769Ssam } 631*26095Sminshall 632*26095Sminshall /*VARARGS*/ 633*26095Sminshall setverbose() 634*26095Sminshall { 635*26095Sminshall verbose = !verbose; 636*26095Sminshall printf("Verbose mode %s.\n", verbose ? "on" : "off"); 637*26095Sminshall } 638