122403Sdist /* 2*33821Sbostic * Copyright (c) 1983 Regents of the University of California. 3*33821Sbostic * All rights reserved. 4*33821Sbostic * 5*33821Sbostic * Redistribution and use in source and binary forms are permitted 6*33821Sbostic * provided that this notice is preserved and that due credit is given 7*33821Sbostic * to the University of California at Berkeley. The name of the University 8*33821Sbostic * may not be used to endorse or promote products derived from this 9*33821Sbostic * software without specific prior written permission. This software 10*33821Sbostic * is provided ``as is'' without express or implied warranty. 1122403Sdist */ 1222403Sdist 1314553Ssam #ifndef lint 1422403Sdist char copyright[] = 1522403Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 1622403Sdist All rights reserved.\n"; 17*33821Sbostic #endif /* not lint */ 187769Ssam 1922403Sdist #ifndef lint 20*33821Sbostic static char sccsid[] = "@(#)main.c 5.6 (Berkeley) 03/28/88"; 21*33821Sbostic #endif /* not lint */ 2222403Sdist 2326095Sminshall /* Many bug fixes are from Jim Guyton <guyton@rand-unix> */ 2426095Sminshall 257769Ssam /* 267769Ssam * TFTP User Program -- Command Interface. 277769Ssam */ 287769Ssam #include <sys/types.h> 297769Ssam #include <sys/socket.h> 3013017Ssam #include <sys/file.h> 319219Ssam 329219Ssam #include <netinet/in.h> 339219Ssam 347769Ssam #include <signal.h> 357769Ssam #include <stdio.h> 367769Ssam #include <errno.h> 377769Ssam #include <setjmp.h> 387769Ssam #include <ctype.h> 398384Ssam #include <netdb.h> 407769Ssam 4113017Ssam #define TIMEOUT 5 /* secs between rexmt's */ 4213017Ssam 4326095Sminshall struct sockaddr_in sin; 447769Ssam int f; 4526095Sminshall short port; 467769Ssam int trace; 4726095Sminshall int verbose; 487769Ssam int connected; 497769Ssam char mode[32]; 507769Ssam char line[200]; 517769Ssam int margc; 527769Ssam char *margv[20]; 537769Ssam char *prompt = "tftp"; 547769Ssam jmp_buf toplevel; 557769Ssam int intr(); 568384Ssam struct servent *sp; 577769Ssam 5826095Sminshall int quit(), help(), setverbose(), settrace(), status(); 5926095Sminshall int get(), put(), setpeer(), modecmd(), setrexmt(), settimeout(); 6026095Sminshall int setbinary(), setascii(); 617769Ssam 627769Ssam #define HELPINDENT (sizeof("connect")) 637769Ssam 647769Ssam struct cmd { 657769Ssam char *name; 667769Ssam char *help; 677769Ssam int (*handler)(); 687769Ssam }; 697769Ssam 7026095Sminshall char vhelp[] = "toggle verbose mode"; 717769Ssam char thelp[] = "toggle packet tracing"; 727769Ssam char chelp[] = "connect to remote tftp"; 737769Ssam char qhelp[] = "exit tftp"; 747769Ssam char hhelp[] = "print help information"; 757769Ssam char shelp[] = "send file"; 767769Ssam char rhelp[] = "receive file"; 777769Ssam char mhelp[] = "set file transfer mode"; 787769Ssam char sthelp[] = "show current status"; 7913017Ssam char xhelp[] = "set per-packet retransmission timeout"; 8013017Ssam char ihelp[] = "set total retransmission timeout"; 8126095Sminshall char ashelp[] = "set mode to netascii"; 8226095Sminshall char bnhelp[] = "set mode to octet"; 837769Ssam 847769Ssam struct cmd cmdtab[] = { 857769Ssam { "connect", chelp, setpeer }, 8626095Sminshall { "mode", mhelp, modecmd }, 877769Ssam { "put", shelp, put }, 887769Ssam { "get", rhelp, get }, 897769Ssam { "quit", qhelp, quit }, 9026095Sminshall { "verbose", vhelp, setverbose }, 917769Ssam { "trace", thelp, settrace }, 927769Ssam { "status", sthelp, status }, 9326095Sminshall { "binary", bnhelp, setbinary }, 9426095Sminshall { "ascii", ashelp, setascii }, 9513017Ssam { "rexmt", xhelp, setrexmt }, 9613017Ssam { "timeout", ihelp, settimeout }, 977769Ssam { "?", hhelp, help }, 987769Ssam 0 997769Ssam }; 1007769Ssam 1017769Ssam struct cmd *getcmd(); 1027769Ssam char *tail(); 1037769Ssam char *index(); 1047769Ssam char *rindex(); 1057769Ssam 1067769Ssam main(argc, argv) 1077769Ssam char *argv[]; 1087769Ssam { 10926095Sminshall struct sockaddr_in sin; 11013017Ssam int top; 11113017Ssam 1128384Ssam sp = getservbyname("tftp", "udp"); 1138384Ssam if (sp == 0) { 1148384Ssam fprintf(stderr, "tftp: udp/tftp: unknown service\n"); 1158384Ssam exit(1); 1168384Ssam } 11726110Sminshall f = socket(AF_INET, SOCK_DGRAM, 0); 1187769Ssam if (f < 0) { 11913017Ssam perror("tftp: socket"); 1207769Ssam exit(3); 1217769Ssam } 12226095Sminshall bzero((char *)&sin, sizeof (sin)); 12326095Sminshall sin.sin_family = AF_INET; 12413017Ssam if (bind(f, &sin, sizeof (sin)) < 0) { 12513017Ssam perror("tftp: bind"); 12613017Ssam exit(1); 12713017Ssam } 12826095Sminshall strcpy(mode, "netascii"); 12913017Ssam signal(SIGINT, intr); 1307769Ssam if (argc > 1) { 1317769Ssam if (setjmp(toplevel) != 0) 1327769Ssam exit(0); 1337769Ssam setpeer(argc, argv); 1347769Ssam } 13513017Ssam top = setjmp(toplevel) == 0; 1367769Ssam for (;;) 13713017Ssam command(top); 1387769Ssam } 1397769Ssam 14026095Sminshall char hostname[100]; 1417769Ssam 1427769Ssam setpeer(argc, argv) 1437769Ssam int argc; 1447769Ssam char *argv[]; 1457769Ssam { 1468384Ssam struct hostent *host; 1477769Ssam 1487769Ssam if (argc < 2) { 1497769Ssam strcpy(line, "Connect "); 1507769Ssam printf("(to) "); 1517769Ssam gets(&line[strlen(line)]); 1527769Ssam makeargv(); 1537769Ssam argc = margc; 1547769Ssam argv = margv; 1557769Ssam } 1567769Ssam if (argc > 3) { 1577769Ssam printf("usage: %s host-name [port]\n", argv[0]); 1587769Ssam return; 1597769Ssam } 1608384Ssam host = gethostbyname(argv[1]); 1618384Ssam if (host) { 1629219Ssam sin.sin_family = host->h_addrtype; 1638384Ssam bcopy(host->h_addr, &sin.sin_addr, host->h_length); 16426095Sminshall strcpy(hostname, host->h_name); 1658384Ssam } else { 1669219Ssam sin.sin_family = AF_INET; 1678384Ssam sin.sin_addr.s_addr = inet_addr(argv[1]); 1688384Ssam if (sin.sin_addr.s_addr == -1) { 1698384Ssam connected = 0; 1708384Ssam printf("%s: unknown host\n", argv[1]); 1718384Ssam return; 1728384Ssam } 17326095Sminshall strcpy(hostname, argv[1]); 1747769Ssam } 17526095Sminshall port = sp->s_port; 1767769Ssam if (argc == 3) { 17726095Sminshall port = atoi(argv[2]); 17826095Sminshall if (port < 0) { 1797769Ssam printf("%s: bad port number\n", argv[2]); 1807769Ssam connected = 0; 1817769Ssam return; 1827769Ssam } 18326095Sminshall port = htons(port); 1848384Ssam } 1857769Ssam connected = 1; 1867769Ssam } 1877769Ssam 1887769Ssam struct modes { 1897769Ssam char *m_name; 1907769Ssam char *m_mode; 1917769Ssam } modes[] = { 19226095Sminshall { "ascii", "netascii" }, 19326095Sminshall { "netascii", "netascii" }, 19426095Sminshall { "binary", "octet" }, 19526095Sminshall { "image", "octet" }, 19626103Sminshall { "octet", "octet" }, 19726095Sminshall /* { "mail", "mail" }, */ 1987769Ssam { 0, 0 } 1997769Ssam }; 2007769Ssam 20126095Sminshall modecmd(argc, argv) 2027769Ssam char *argv[]; 2037769Ssam { 2047769Ssam register struct modes *p; 20526095Sminshall char *sep; 2067769Ssam 2077769Ssam if (argc < 2) { 2087769Ssam printf("Using %s mode to transfer files.\n", mode); 2097769Ssam return; 2107769Ssam } 21126095Sminshall if (argc == 2) { 21226095Sminshall for (p = modes; p->m_name; p++) 21326095Sminshall if (strcmp(argv[1], p->m_name) == 0) 21426095Sminshall break; 21526095Sminshall if (p->m_name) { 21626095Sminshall setmode(p->m_mode); 21726095Sminshall return; 21826095Sminshall } 2197769Ssam printf("%s: unknown mode\n", argv[1]); 22026095Sminshall /* drop through and print usage message */ 22126095Sminshall } 22226095Sminshall 22326095Sminshall printf("usage: %s [", argv[0]); 22426095Sminshall sep = " "; 22526095Sminshall for (p = modes; p->m_name; p++) { 22626095Sminshall printf("%s%s", sep, p->m_name); 22726095Sminshall if (*sep == ' ') 22826095Sminshall sep = " | "; 22926095Sminshall } 23026095Sminshall printf(" ]\n"); 23126095Sminshall return; 2327769Ssam } 2337769Ssam 23426095Sminshall setbinary(argc, argv) 23526095Sminshall char *argv[]; 23626095Sminshall { setmode("octet"); 23726095Sminshall } 23826095Sminshall 23926095Sminshall setascii(argc, argv) 24026095Sminshall char *argv[]; 24126095Sminshall { setmode("netascii"); 24226095Sminshall } 24326095Sminshall 24426095Sminshall setmode(newmode) 24526095Sminshall char *newmode; 24626095Sminshall { 24726095Sminshall strcpy(mode, newmode); 24826095Sminshall if (verbose) 24926095Sminshall printf("mode set to %s\n", mode); 25026095Sminshall } 25126095Sminshall 25226095Sminshall 2537769Ssam /* 2547769Ssam * Send file(s). 2557769Ssam */ 2567769Ssam put(argc, argv) 2577769Ssam char *argv[]; 2587769Ssam { 2597769Ssam int fd; 26026095Sminshall register int n; 2617769Ssam register char *cp, *targ; 2627769Ssam 2637769Ssam if (argc < 2) { 2647769Ssam strcpy(line, "send "); 2657769Ssam printf("(file) "); 2667769Ssam gets(&line[strlen(line)]); 2677769Ssam makeargv(); 2687769Ssam argc = margc; 2697769Ssam argv = margv; 2707769Ssam } 2717769Ssam if (argc < 2) { 2727769Ssam putusage(argv[0]); 2737769Ssam return; 2747769Ssam } 2757769Ssam targ = argv[argc - 1]; 2767769Ssam if (index(argv[argc - 1], ':')) { 2778384Ssam char *cp; 2788384Ssam struct hostent *hp; 2797769Ssam 2807769Ssam for (n = 1; n < argc - 1; n++) 2817769Ssam if (index(argv[n], ':')) { 2827769Ssam putusage(argv[0]); 2837769Ssam return; 2847769Ssam } 2858384Ssam cp = argv[argc - 1]; 2868384Ssam targ = index(cp, ':'); 2877769Ssam *targ++ = 0; 2888384Ssam hp = gethostbyname(cp); 2898384Ssam if (hp == 0) { 2908384Ssam printf("%s: Unknown host.\n", cp); 2917769Ssam return; 2927769Ssam } 2939219Ssam bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); 2948384Ssam sin.sin_family = hp->h_addrtype; 2957769Ssam connected = 1; 29626095Sminshall strcpy(hostname, hp->h_name); 2977769Ssam } 2987769Ssam if (!connected) { 2997769Ssam printf("No target machine specified.\n"); 3007769Ssam return; 3017769Ssam } 3027769Ssam if (argc < 4) { 3037769Ssam cp = argc == 2 ? tail(targ) : argv[1]; 30413017Ssam fd = open(cp, O_RDONLY); 3057769Ssam if (fd < 0) { 30613017Ssam fprintf(stderr, "tftp: "); perror(cp); 3077769Ssam return; 3087769Ssam } 30926095Sminshall if (verbose) 31026095Sminshall printf("putting %s to %s:%s [%s]\n", 31126095Sminshall cp, hostname, targ, mode); 31226095Sminshall sin.sin_port = port; 31326095Sminshall sendfile(fd, targ, mode); 3147769Ssam return; 3157769Ssam } 31626095Sminshall /* this assumes the target is a directory */ 31726095Sminshall /* on a remote unix system. hmmmm. */ 3187769Ssam cp = index(targ, '\0'); 3197769Ssam *cp++ = '/'; 3207769Ssam for (n = 1; n < argc - 1; n++) { 3217769Ssam strcpy(cp, tail(argv[n])); 32213017Ssam fd = open(argv[n], O_RDONLY); 3237769Ssam if (fd < 0) { 32413017Ssam fprintf(stderr, "tftp: "); perror(argv[n]); 3257769Ssam continue; 3267769Ssam } 32726095Sminshall if (verbose) 32826095Sminshall printf("putting %s to %s:%s [%s]\n", 32926095Sminshall argv[n], hostname, targ, mode); 33026095Sminshall sin.sin_port = port; 33126095Sminshall sendfile(fd, targ, mode); 3327769Ssam } 3337769Ssam } 3347769Ssam 3357769Ssam putusage(s) 3367769Ssam char *s; 3377769Ssam { 3387769Ssam printf("usage: %s file ... host:target, or\n", s); 3397769Ssam printf(" %s file ... target (when already connected)\n", s); 3407769Ssam } 3417769Ssam 3427769Ssam /* 3437769Ssam * Receive file(s). 3447769Ssam */ 3457769Ssam get(argc, argv) 3467769Ssam char *argv[]; 3477769Ssam { 3487769Ssam int fd; 34926095Sminshall register int n; 3507769Ssam register char *cp; 3517769Ssam char *src; 3527769Ssam 3537769Ssam if (argc < 2) { 3547769Ssam strcpy(line, "get "); 3557769Ssam printf("(files) "); 3567769Ssam gets(&line[strlen(line)]); 3577769Ssam makeargv(); 3587769Ssam argc = margc; 3597769Ssam argv = margv; 3607769Ssam } 3617769Ssam if (argc < 2) { 3627769Ssam getusage(argv[0]); 3637769Ssam return; 3647769Ssam } 36526095Sminshall if (!connected) { 36626095Sminshall for (n = 1; n < argc ; n++) 3677769Ssam if (index(argv[n], ':') == 0) { 3687769Ssam getusage(argv[0]); 3697769Ssam return; 3707769Ssam } 37126095Sminshall } 37226095Sminshall for (n = 1; n < argc ; n++) { 3737769Ssam src = index(argv[n], ':'); 3747769Ssam if (src == NULL) 3757769Ssam src = argv[n]; 3767769Ssam else { 3778384Ssam struct hostent *hp; 3788384Ssam 3797769Ssam *src++ = 0; 3808384Ssam hp = gethostbyname(argv[n]); 3818384Ssam if (hp == 0) { 3827769Ssam printf("%s: Unknown host.\n", argv[n]); 3837769Ssam continue; 3847769Ssam } 3859219Ssam bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); 3868384Ssam sin.sin_family = hp->h_addrtype; 3877769Ssam connected = 1; 38826095Sminshall strcpy(hostname, hp->h_name); 3897769Ssam } 3907769Ssam if (argc < 4) { 3917769Ssam cp = argc == 3 ? argv[2] : tail(src); 3927769Ssam fd = creat(cp, 0644); 3937769Ssam if (fd < 0) { 39413017Ssam fprintf(stderr, "tftp: "); perror(cp); 3957769Ssam return; 3967769Ssam } 39726095Sminshall if (verbose) 39826095Sminshall printf("getting from %s:%s to %s [%s]\n", 39926095Sminshall hostname, src, cp, mode); 40026095Sminshall sin.sin_port = port; 40126095Sminshall recvfile(fd, src, mode); 4027769Ssam break; 4037769Ssam } 40426095Sminshall cp = tail(src); /* new .. jdg */ 40526095Sminshall fd = creat(cp, 0644); 4067769Ssam if (fd < 0) { 40726095Sminshall fprintf(stderr, "tftp: "); perror(cp); 4087769Ssam continue; 4097769Ssam } 41026095Sminshall if (verbose) 41126095Sminshall printf("getting from %s:%s to %s [%s]\n", 41226095Sminshall hostname, src, cp, mode); 41326095Sminshall sin.sin_port = port; 41426095Sminshall recvfile(fd, src, mode); 4157769Ssam } 4167769Ssam } 4177769Ssam 4187769Ssam getusage(s) 41926110Sminshall char * s; 4207769Ssam { 4217769Ssam printf("usage: %s host:file host:file ... file, or\n", s); 4227769Ssam printf(" %s file file ... file if connected\n", s); 4237769Ssam } 4247769Ssam 42513017Ssam int rexmtval = TIMEOUT; 42613017Ssam 42713017Ssam setrexmt(argc, argv) 42813017Ssam char *argv[]; 42913017Ssam { 43013017Ssam int t; 43113017Ssam 43213017Ssam if (argc < 2) { 43313017Ssam strcpy(line, "Rexmt-timeout "); 43413017Ssam printf("(value) "); 43513017Ssam gets(&line[strlen(line)]); 43613017Ssam makeargv(); 43713017Ssam argc = margc; 43813017Ssam argv = margv; 43913017Ssam } 44013017Ssam if (argc != 2) { 44113017Ssam printf("usage: %s value\n", argv[0]); 44213017Ssam return; 44313017Ssam } 44413017Ssam t = atoi(argv[1]); 44513017Ssam if (t < 0) 44613017Ssam printf("%s: bad value\n", t); 44713017Ssam else 44813017Ssam rexmtval = t; 44913017Ssam } 45013017Ssam 45113017Ssam int maxtimeout = 5 * TIMEOUT; 45213017Ssam 45313017Ssam settimeout(argc, argv) 45413017Ssam char *argv[]; 45513017Ssam { 45613017Ssam int t; 45713017Ssam 45813017Ssam if (argc < 2) { 45913017Ssam strcpy(line, "Maximum-timeout "); 46013017Ssam printf("(value) "); 46113017Ssam gets(&line[strlen(line)]); 46213017Ssam makeargv(); 46313017Ssam argc = margc; 46413017Ssam argv = margv; 46513017Ssam } 46613017Ssam if (argc != 2) { 46713017Ssam printf("usage: %s value\n", argv[0]); 46813017Ssam return; 46913017Ssam } 47013017Ssam t = atoi(argv[1]); 47113017Ssam if (t < 0) 47213017Ssam printf("%s: bad value\n", t); 47313017Ssam else 47413017Ssam maxtimeout = t; 47513017Ssam } 47613017Ssam 4777769Ssam status(argc, argv) 4787769Ssam char *argv[]; 4797769Ssam { 4807769Ssam if (connected) 4818384Ssam printf("Connected to %s.\n", hostname); 4827769Ssam else 4837769Ssam printf("Not connected.\n"); 48426095Sminshall printf("Mode: %s Verbose: %s Tracing: %s\n", mode, 48526095Sminshall verbose ? "on" : "off", trace ? "on" : "off"); 48613017Ssam printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n", 48713017Ssam rexmtval, maxtimeout); 4887769Ssam } 4897769Ssam 4907769Ssam intr() 4917769Ssam { 49226095Sminshall signal(SIGALRM, SIG_IGN); 49316382Ssam alarm(0); 4947769Ssam longjmp(toplevel, -1); 4957769Ssam } 4967769Ssam 4977769Ssam char * 4987769Ssam tail(filename) 4997769Ssam char *filename; 5007769Ssam { 5017769Ssam register char *s; 5027769Ssam 5037769Ssam while (*filename) { 5047769Ssam s = rindex(filename, '/'); 5057769Ssam if (s == NULL) 5067769Ssam break; 5077769Ssam if (s[1]) 5087769Ssam return (s + 1); 5097769Ssam *s = '\0'; 5107769Ssam } 5117769Ssam return (filename); 5127769Ssam } 5137769Ssam 5147769Ssam /* 5157769Ssam * Command parser. 5167769Ssam */ 5177769Ssam command(top) 5187769Ssam int top; 5197769Ssam { 5207769Ssam register struct cmd *c; 5217769Ssam 5227769Ssam if (!top) 5237769Ssam putchar('\n'); 5247769Ssam for (;;) { 5257769Ssam printf("%s> ", prompt); 52626103Sminshall if (gets(line) == 0) { 52726103Sminshall if (feof(stdin)) { 52826103Sminshall quit(); 52926103Sminshall } else { 53026103Sminshall continue; 53126103Sminshall } 53226103Sminshall } 5337769Ssam if (line[0] == 0) 53413017Ssam continue; 5357769Ssam makeargv(); 5367769Ssam c = getcmd(margv[0]); 5377769Ssam if (c == (struct cmd *)-1) { 5387769Ssam printf("?Ambiguous command\n"); 5397769Ssam continue; 5407769Ssam } 5417769Ssam if (c == 0) { 5427769Ssam printf("?Invalid command\n"); 5437769Ssam continue; 5447769Ssam } 5457769Ssam (*c->handler)(margc, margv); 5467769Ssam } 5477769Ssam } 5487769Ssam 5497769Ssam struct cmd * 5507769Ssam getcmd(name) 5517769Ssam register char *name; 5527769Ssam { 5537769Ssam register char *p, *q; 5547769Ssam register struct cmd *c, *found; 5557769Ssam register int nmatches, longest; 5567769Ssam 5577769Ssam longest = 0; 5587769Ssam nmatches = 0; 5597769Ssam found = 0; 5607769Ssam for (c = cmdtab; p = c->name; c++) { 5617769Ssam for (q = name; *q == *p++; q++) 5627769Ssam if (*q == 0) /* exact match? */ 5637769Ssam return (c); 5647769Ssam if (!*q) { /* the name was a prefix */ 5657769Ssam if (q - name > longest) { 5667769Ssam longest = q - name; 5677769Ssam nmatches = 1; 5687769Ssam found = c; 5697769Ssam } else if (q - name == longest) 5707769Ssam nmatches++; 5717769Ssam } 5727769Ssam } 5737769Ssam if (nmatches > 1) 5747769Ssam return ((struct cmd *)-1); 5757769Ssam return (found); 5767769Ssam } 5777769Ssam 5787769Ssam /* 5797769Ssam * Slice a string up into argc/argv. 5807769Ssam */ 5817769Ssam makeargv() 5827769Ssam { 5837769Ssam register char *cp; 5847769Ssam register char **argp = margv; 5857769Ssam 5867769Ssam margc = 0; 5877769Ssam for (cp = line; *cp;) { 5887769Ssam while (isspace(*cp)) 5897769Ssam cp++; 5907769Ssam if (*cp == '\0') 5917769Ssam break; 5927769Ssam *argp++ = cp; 5937769Ssam margc += 1; 5947769Ssam while (*cp != '\0' && !isspace(*cp)) 5957769Ssam cp++; 5967769Ssam if (*cp == '\0') 5977769Ssam break; 5987769Ssam *cp++ = '\0'; 5997769Ssam } 6007769Ssam *argp++ = 0; 6017769Ssam } 6027769Ssam 6037769Ssam /*VARARGS*/ 6047769Ssam quit() 6057769Ssam { 6067769Ssam exit(0); 6077769Ssam } 6087769Ssam 6097769Ssam /* 6107769Ssam * Help command. 6117769Ssam */ 6127769Ssam help(argc, argv) 6137769Ssam int argc; 6147769Ssam char *argv[]; 6157769Ssam { 6167769Ssam register struct cmd *c; 6177769Ssam 6187769Ssam if (argc == 1) { 6197769Ssam printf("Commands may be abbreviated. Commands are:\n\n"); 6207769Ssam for (c = cmdtab; c->name; c++) 6217769Ssam printf("%-*s\t%s\n", HELPINDENT, c->name, c->help); 6227769Ssam return; 6237769Ssam } 6247769Ssam while (--argc > 0) { 6257769Ssam register char *arg; 6267769Ssam arg = *++argv; 6277769Ssam c = getcmd(arg); 6287769Ssam if (c == (struct cmd *)-1) 6297769Ssam printf("?Ambiguous help command %s\n", arg); 6307769Ssam else if (c == (struct cmd *)0) 6317769Ssam printf("?Invalid help command %s\n", arg); 6327769Ssam else 6337769Ssam printf("%s\n", c->help); 6347769Ssam } 6357769Ssam } 6367769Ssam 6377769Ssam /*VARARGS*/ 6387769Ssam settrace() 6397769Ssam { 6407769Ssam trace = !trace; 6417769Ssam printf("Packet tracing %s.\n", trace ? "on" : "off"); 6427769Ssam } 64326095Sminshall 64426095Sminshall /*VARARGS*/ 64526095Sminshall setverbose() 64626095Sminshall { 64726095Sminshall verbose = !verbose; 64826095Sminshall printf("Verbose mode %s.\n", verbose ? "on" : "off"); 64926095Sminshall } 650