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*60062Storek static char sccsid[] = "@(#)main.c 5.12 (Berkeley) 05/16/93"; 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 29*60062Storek #include <arpa/inet.h> 30*60062Storek 31*60062Storek #include <ctype.h> 32*60062Storek #include <errno.h> 33*60062Storek #include <netdb.h> 34*60062Storek #include <setjmp.h> 357769Ssam #include <signal.h> 367769Ssam #include <stdio.h> 37*60062Storek #include <stdlib.h> 38*60062Storek #include <string.h> 39*60062Storek #include <unistd.h> 407769Ssam 41*60062Storek #include "extern.h" 42*60062Storek 4313017Ssam #define TIMEOUT 5 /* secs between rexmt's */ 4413017Ssam 45*60062Storek struct sockaddr_in peeraddr; 467769Ssam int f; 4726095Sminshall short port; 487769Ssam int trace; 4926095Sminshall int verbose; 507769Ssam int connected; 517769Ssam char mode[32]; 527769Ssam char line[200]; 537769Ssam int margc; 547769Ssam char *margv[20]; 557769Ssam char *prompt = "tftp"; 567769Ssam jmp_buf toplevel; 5746861Sbostic void intr(); 588384Ssam struct servent *sp; 597769Ssam 60*60062Storek void get __P((int, char **)); 61*60062Storek void help __P((int, char **)); 62*60062Storek void modecmd __P((int, char **)); 63*60062Storek void put __P((int, char **)); 64*60062Storek void quit __P((int, char **)); 65*60062Storek void setascii __P((int, char **)); 66*60062Storek void setbinary __P((int, char **)); 67*60062Storek void setpeer __P((int, char **)); 68*60062Storek void setrexmt __P((int, char **)); 69*60062Storek void settimeout __P((int, char **)); 70*60062Storek void settrace __P((int, char **)); 71*60062Storek void setverbose __P((int, char **)); 72*60062Storek void status __P((int, char **)); 737769Ssam 74*60062Storek static __dead void command __P((void)); 75*60062Storek 76*60062Storek static void getusage __P((char *)); 77*60062Storek static void makeargv __P((void)); 78*60062Storek static void putusage __P((char *)); 79*60062Storek static void settftpmode __P((char *)); 80*60062Storek 817769Ssam #define HELPINDENT (sizeof("connect")) 827769Ssam 837769Ssam struct cmd { 847769Ssam char *name; 857769Ssam char *help; 86*60062Storek void (*handler) __P((int, char **)); 877769Ssam }; 887769Ssam 8926095Sminshall char vhelp[] = "toggle verbose mode"; 907769Ssam char thelp[] = "toggle packet tracing"; 917769Ssam char chelp[] = "connect to remote tftp"; 927769Ssam char qhelp[] = "exit tftp"; 937769Ssam char hhelp[] = "print help information"; 947769Ssam char shelp[] = "send file"; 957769Ssam char rhelp[] = "receive file"; 967769Ssam char mhelp[] = "set file transfer mode"; 977769Ssam char sthelp[] = "show current status"; 9813017Ssam char xhelp[] = "set per-packet retransmission timeout"; 9913017Ssam char ihelp[] = "set total retransmission timeout"; 10026095Sminshall char ashelp[] = "set mode to netascii"; 10126095Sminshall char bnhelp[] = "set mode to octet"; 1027769Ssam 1037769Ssam struct cmd cmdtab[] = { 1047769Ssam { "connect", chelp, setpeer }, 10526095Sminshall { "mode", mhelp, modecmd }, 1067769Ssam { "put", shelp, put }, 1077769Ssam { "get", rhelp, get }, 1087769Ssam { "quit", qhelp, quit }, 10926095Sminshall { "verbose", vhelp, setverbose }, 1107769Ssam { "trace", thelp, settrace }, 1117769Ssam { "status", sthelp, status }, 11226095Sminshall { "binary", bnhelp, setbinary }, 11326095Sminshall { "ascii", ashelp, setascii }, 11413017Ssam { "rexmt", xhelp, setrexmt }, 11513017Ssam { "timeout", ihelp, settimeout }, 1167769Ssam { "?", hhelp, help }, 117*60062Storek { 0 } 1187769Ssam }; 1197769Ssam 1207769Ssam struct cmd *getcmd(); 1217769Ssam char *tail(); 1227769Ssam char *index(); 1237769Ssam char *rindex(); 1247769Ssam 125*60062Storek int 1267769Ssam main(argc, argv) 127*60062Storek int argc; 1287769Ssam char *argv[]; 1297769Ssam { 13026095Sminshall struct sockaddr_in sin; 13113017Ssam 1328384Ssam sp = getservbyname("tftp", "udp"); 1338384Ssam if (sp == 0) { 1348384Ssam fprintf(stderr, "tftp: udp/tftp: unknown service\n"); 1358384Ssam exit(1); 1368384Ssam } 13726110Sminshall f = socket(AF_INET, SOCK_DGRAM, 0); 1387769Ssam if (f < 0) { 13913017Ssam perror("tftp: socket"); 1407769Ssam exit(3); 1417769Ssam } 142*60062Storek bzero((char *)&sin, sizeof(sin)); 14326095Sminshall sin.sin_family = AF_INET; 144*60062Storek if (bind(f, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 14513017Ssam perror("tftp: bind"); 14613017Ssam exit(1); 14713017Ssam } 14826095Sminshall strcpy(mode, "netascii"); 14913017Ssam signal(SIGINT, intr); 1507769Ssam if (argc > 1) { 1517769Ssam if (setjmp(toplevel) != 0) 1527769Ssam exit(0); 1537769Ssam setpeer(argc, argv); 1547769Ssam } 155*60062Storek if (setjmp(toplevel) != 0) 156*60062Storek (void)putchar('\n'); 157*60062Storek command(); 1587769Ssam } 1597769Ssam 16026095Sminshall char hostname[100]; 1617769Ssam 162*60062Storek void 1637769Ssam setpeer(argc, argv) 1647769Ssam int argc; 1657769Ssam char *argv[]; 1667769Ssam { 1678384Ssam struct hostent *host; 1687769Ssam 1697769Ssam if (argc < 2) { 1707769Ssam strcpy(line, "Connect "); 1717769Ssam printf("(to) "); 1727769Ssam gets(&line[strlen(line)]); 1737769Ssam makeargv(); 1747769Ssam argc = margc; 1757769Ssam argv = margv; 1767769Ssam } 1777769Ssam if (argc > 3) { 1787769Ssam printf("usage: %s host-name [port]\n", argv[0]); 1797769Ssam return; 1807769Ssam } 1818384Ssam host = gethostbyname(argv[1]); 1828384Ssam if (host) { 183*60062Storek peeraddr.sin_family = host->h_addrtype; 184*60062Storek bcopy(host->h_addr, &peeraddr.sin_addr, host->h_length); 18526095Sminshall strcpy(hostname, host->h_name); 1868384Ssam } else { 187*60062Storek peeraddr.sin_family = AF_INET; 188*60062Storek peeraddr.sin_addr.s_addr = inet_addr(argv[1]); 189*60062Storek if (peeraddr.sin_addr.s_addr == -1) { 1908384Ssam connected = 0; 1918384Ssam printf("%s: unknown host\n", argv[1]); 1928384Ssam return; 1938384Ssam } 19426095Sminshall strcpy(hostname, argv[1]); 1957769Ssam } 19626095Sminshall port = sp->s_port; 1977769Ssam if (argc == 3) { 19826095Sminshall port = atoi(argv[2]); 19926095Sminshall if (port < 0) { 2007769Ssam printf("%s: bad port number\n", argv[2]); 2017769Ssam connected = 0; 2027769Ssam return; 2037769Ssam } 20426095Sminshall port = htons(port); 2058384Ssam } 2067769Ssam connected = 1; 2077769Ssam } 2087769Ssam 2097769Ssam struct modes { 2107769Ssam char *m_name; 2117769Ssam char *m_mode; 2127769Ssam } modes[] = { 21326095Sminshall { "ascii", "netascii" }, 21426095Sminshall { "netascii", "netascii" }, 21526095Sminshall { "binary", "octet" }, 21626095Sminshall { "image", "octet" }, 21726103Sminshall { "octet", "octet" }, 21826095Sminshall /* { "mail", "mail" }, */ 2197769Ssam { 0, 0 } 2207769Ssam }; 2217769Ssam 222*60062Storek void 22326095Sminshall modecmd(argc, argv) 224*60062Storek int argc; 2257769Ssam char *argv[]; 2267769Ssam { 2277769Ssam register struct modes *p; 22826095Sminshall char *sep; 2297769Ssam 2307769Ssam if (argc < 2) { 2317769Ssam printf("Using %s mode to transfer files.\n", mode); 2327769Ssam return; 2337769Ssam } 23426095Sminshall if (argc == 2) { 23526095Sminshall for (p = modes; p->m_name; p++) 23626095Sminshall if (strcmp(argv[1], p->m_name) == 0) 23726095Sminshall break; 23826095Sminshall if (p->m_name) { 239*60062Storek settftpmode(p->m_mode); 24026095Sminshall return; 24126095Sminshall } 2427769Ssam printf("%s: unknown mode\n", argv[1]); 24326095Sminshall /* drop through and print usage message */ 24426095Sminshall } 24526095Sminshall 24626095Sminshall printf("usage: %s [", argv[0]); 24726095Sminshall sep = " "; 24826095Sminshall for (p = modes; p->m_name; p++) { 24926095Sminshall printf("%s%s", sep, p->m_name); 25026095Sminshall if (*sep == ' ') 25126095Sminshall sep = " | "; 25226095Sminshall } 25326095Sminshall printf(" ]\n"); 25426095Sminshall return; 2557769Ssam } 2567769Ssam 257*60062Storek void 25826095Sminshall setbinary(argc, argv) 259*60062Storek int argc; 260*60062Storek char *argv[]; 261*60062Storek { 262*60062Storek 263*60062Storek settftpmode("octet"); 26426095Sminshall } 26526095Sminshall 266*60062Storek void 26726095Sminshall setascii(argc, argv) 268*60062Storek int argc; 269*60062Storek char *argv[]; 270*60062Storek { 271*60062Storek 272*60062Storek settftpmode("netascii"); 27326095Sminshall } 27426095Sminshall 275*60062Storek static void 276*60062Storek settftpmode(newmode) 277*60062Storek char *newmode; 27826095Sminshall { 27926095Sminshall strcpy(mode, newmode); 28026095Sminshall if (verbose) 28126095Sminshall printf("mode set to %s\n", mode); 28226095Sminshall } 28326095Sminshall 28426095Sminshall 2857769Ssam /* 2867769Ssam * Send file(s). 2877769Ssam */ 288*60062Storek void 2897769Ssam put(argc, argv) 290*60062Storek int argc; 2917769Ssam char *argv[]; 2927769Ssam { 2937769Ssam int fd; 29426095Sminshall register int n; 2957769Ssam register char *cp, *targ; 2967769Ssam 2977769Ssam if (argc < 2) { 2987769Ssam strcpy(line, "send "); 2997769Ssam printf("(file) "); 3007769Ssam gets(&line[strlen(line)]); 3017769Ssam makeargv(); 3027769Ssam argc = margc; 3037769Ssam argv = margv; 3047769Ssam } 3057769Ssam if (argc < 2) { 3067769Ssam putusage(argv[0]); 3077769Ssam return; 3087769Ssam } 3097769Ssam targ = argv[argc - 1]; 3107769Ssam if (index(argv[argc - 1], ':')) { 3118384Ssam char *cp; 3128384Ssam struct hostent *hp; 3137769Ssam 3147769Ssam for (n = 1; n < argc - 1; n++) 3157769Ssam if (index(argv[n], ':')) { 3167769Ssam putusage(argv[0]); 3177769Ssam return; 3187769Ssam } 3198384Ssam cp = argv[argc - 1]; 3208384Ssam targ = index(cp, ':'); 3217769Ssam *targ++ = 0; 3228384Ssam hp = gethostbyname(cp); 32335788Sbostic if (hp == NULL) { 32435788Sbostic fprintf(stderr, "tftp: %s: ", cp); 32535788Sbostic herror((char *)NULL); 3267769Ssam return; 3277769Ssam } 328*60062Storek bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr, hp->h_length); 329*60062Storek peeraddr.sin_family = hp->h_addrtype; 3307769Ssam connected = 1; 33126095Sminshall strcpy(hostname, hp->h_name); 3327769Ssam } 3337769Ssam if (!connected) { 3347769Ssam printf("No target machine specified.\n"); 3357769Ssam return; 3367769Ssam } 3377769Ssam if (argc < 4) { 3387769Ssam cp = argc == 2 ? tail(targ) : argv[1]; 33913017Ssam fd = open(cp, O_RDONLY); 3407769Ssam if (fd < 0) { 34113017Ssam fprintf(stderr, "tftp: "); perror(cp); 3427769Ssam return; 3437769Ssam } 34426095Sminshall if (verbose) 34526095Sminshall printf("putting %s to %s:%s [%s]\n", 34626095Sminshall cp, hostname, targ, mode); 347*60062Storek peeraddr.sin_port = port; 34826095Sminshall sendfile(fd, targ, mode); 3497769Ssam return; 3507769Ssam } 35126095Sminshall /* this assumes the target is a directory */ 35226095Sminshall /* on a remote unix system. hmmmm. */ 3537769Ssam cp = index(targ, '\0'); 3547769Ssam *cp++ = '/'; 3557769Ssam for (n = 1; n < argc - 1; n++) { 3567769Ssam strcpy(cp, tail(argv[n])); 35713017Ssam fd = open(argv[n], O_RDONLY); 3587769Ssam if (fd < 0) { 35913017Ssam fprintf(stderr, "tftp: "); perror(argv[n]); 3607769Ssam continue; 3617769Ssam } 36226095Sminshall if (verbose) 36326095Sminshall printf("putting %s to %s:%s [%s]\n", 36426095Sminshall argv[n], hostname, targ, mode); 365*60062Storek peeraddr.sin_port = port; 36626095Sminshall sendfile(fd, targ, mode); 3677769Ssam } 3687769Ssam } 3697769Ssam 370*60062Storek static void 3717769Ssam putusage(s) 3727769Ssam char *s; 3737769Ssam { 3747769Ssam printf("usage: %s file ... host:target, or\n", s); 3757769Ssam printf(" %s file ... target (when already connected)\n", s); 3767769Ssam } 3777769Ssam 3787769Ssam /* 3797769Ssam * Receive file(s). 3807769Ssam */ 381*60062Storek void 3827769Ssam get(argc, argv) 383*60062Storek int argc; 3847769Ssam char *argv[]; 3857769Ssam { 3867769Ssam int fd; 38726095Sminshall register int n; 3887769Ssam register char *cp; 3897769Ssam char *src; 3907769Ssam 3917769Ssam if (argc < 2) { 3927769Ssam strcpy(line, "get "); 3937769Ssam printf("(files) "); 3947769Ssam gets(&line[strlen(line)]); 3957769Ssam makeargv(); 3967769Ssam argc = margc; 3977769Ssam argv = margv; 3987769Ssam } 3997769Ssam if (argc < 2) { 4007769Ssam getusage(argv[0]); 4017769Ssam return; 4027769Ssam } 40326095Sminshall if (!connected) { 40426095Sminshall for (n = 1; n < argc ; n++) 4057769Ssam if (index(argv[n], ':') == 0) { 4067769Ssam getusage(argv[0]); 4077769Ssam return; 4087769Ssam } 40926095Sminshall } 41026095Sminshall for (n = 1; n < argc ; n++) { 4117769Ssam src = index(argv[n], ':'); 4127769Ssam if (src == NULL) 4137769Ssam src = argv[n]; 4147769Ssam else { 4158384Ssam struct hostent *hp; 4168384Ssam 4177769Ssam *src++ = 0; 4188384Ssam hp = gethostbyname(argv[n]); 41935788Sbostic if (hp == NULL) { 42035788Sbostic fprintf(stderr, "tftp: %s: ", argv[n]); 42135788Sbostic herror((char *)NULL); 4227769Ssam continue; 4237769Ssam } 424*60062Storek bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr, 425*60062Storek hp->h_length); 426*60062Storek peeraddr.sin_family = hp->h_addrtype; 4277769Ssam connected = 1; 42826095Sminshall strcpy(hostname, hp->h_name); 4297769Ssam } 4307769Ssam if (argc < 4) { 4317769Ssam cp = argc == 3 ? argv[2] : tail(src); 4327769Ssam fd = creat(cp, 0644); 4337769Ssam if (fd < 0) { 43413017Ssam fprintf(stderr, "tftp: "); perror(cp); 4357769Ssam return; 4367769Ssam } 43726095Sminshall if (verbose) 43826095Sminshall printf("getting from %s:%s to %s [%s]\n", 43926095Sminshall hostname, src, cp, mode); 440*60062Storek peeraddr.sin_port = port; 44126095Sminshall recvfile(fd, src, mode); 4427769Ssam break; 4437769Ssam } 44426095Sminshall cp = tail(src); /* new .. jdg */ 44526095Sminshall fd = creat(cp, 0644); 4467769Ssam if (fd < 0) { 44726095Sminshall fprintf(stderr, "tftp: "); perror(cp); 4487769Ssam continue; 4497769Ssam } 45026095Sminshall if (verbose) 45126095Sminshall printf("getting from %s:%s to %s [%s]\n", 45226095Sminshall hostname, src, cp, mode); 453*60062Storek peeraddr.sin_port = port; 45426095Sminshall recvfile(fd, src, mode); 4557769Ssam } 4567769Ssam } 4577769Ssam 458*60062Storek static void 4597769Ssam getusage(s) 460*60062Storek char *s; 4617769Ssam { 4627769Ssam printf("usage: %s host:file host:file ... file, or\n", s); 4637769Ssam printf(" %s file file ... file if connected\n", s); 4647769Ssam } 4657769Ssam 46613017Ssam int rexmtval = TIMEOUT; 46713017Ssam 468*60062Storek void 46913017Ssam setrexmt(argc, argv) 470*60062Storek int argc; 47113017Ssam char *argv[]; 47213017Ssam { 47313017Ssam int t; 47413017Ssam 47513017Ssam if (argc < 2) { 47613017Ssam strcpy(line, "Rexmt-timeout "); 47713017Ssam printf("(value) "); 47813017Ssam gets(&line[strlen(line)]); 47913017Ssam makeargv(); 48013017Ssam argc = margc; 48113017Ssam argv = margv; 48213017Ssam } 48313017Ssam if (argc != 2) { 48413017Ssam printf("usage: %s value\n", argv[0]); 48513017Ssam return; 48613017Ssam } 48713017Ssam t = atoi(argv[1]); 48813017Ssam if (t < 0) 489*60062Storek printf("%s: bad value\n", argv[1]); 49013017Ssam else 49113017Ssam rexmtval = t; 49213017Ssam } 49313017Ssam 49413017Ssam int maxtimeout = 5 * TIMEOUT; 49513017Ssam 496*60062Storek void 49713017Ssam settimeout(argc, argv) 498*60062Storek int argc; 49913017Ssam char *argv[]; 50013017Ssam { 50113017Ssam int t; 50213017Ssam 50313017Ssam if (argc < 2) { 50413017Ssam strcpy(line, "Maximum-timeout "); 50513017Ssam printf("(value) "); 50613017Ssam gets(&line[strlen(line)]); 50713017Ssam makeargv(); 50813017Ssam argc = margc; 50913017Ssam argv = margv; 51013017Ssam } 51113017Ssam if (argc != 2) { 51213017Ssam printf("usage: %s value\n", argv[0]); 51313017Ssam return; 51413017Ssam } 51513017Ssam t = atoi(argv[1]); 51613017Ssam if (t < 0) 517*60062Storek printf("%s: bad value\n", argv[1]); 51813017Ssam else 51913017Ssam maxtimeout = t; 52013017Ssam } 52113017Ssam 522*60062Storek void 5237769Ssam status(argc, argv) 524*60062Storek int argc; 5257769Ssam char *argv[]; 5267769Ssam { 5277769Ssam if (connected) 5288384Ssam printf("Connected to %s.\n", hostname); 5297769Ssam else 5307769Ssam printf("Not connected.\n"); 53126095Sminshall printf("Mode: %s Verbose: %s Tracing: %s\n", mode, 53226095Sminshall verbose ? "on" : "off", trace ? "on" : "off"); 53313017Ssam printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n", 53413017Ssam rexmtval, maxtimeout); 5357769Ssam } 5367769Ssam 53746861Sbostic void 5387769Ssam intr() 5397769Ssam { 540*60062Storek 54126095Sminshall signal(SIGALRM, SIG_IGN); 54216382Ssam alarm(0); 5437769Ssam longjmp(toplevel, -1); 5447769Ssam } 5457769Ssam 5467769Ssam char * 5477769Ssam tail(filename) 5487769Ssam char *filename; 5497769Ssam { 5507769Ssam register char *s; 5517769Ssam 5527769Ssam while (*filename) { 5537769Ssam s = rindex(filename, '/'); 5547769Ssam if (s == NULL) 5557769Ssam break; 5567769Ssam if (s[1]) 5577769Ssam return (s + 1); 5587769Ssam *s = '\0'; 5597769Ssam } 5607769Ssam return (filename); 5617769Ssam } 5627769Ssam 5637769Ssam /* 5647769Ssam * Command parser. 5657769Ssam */ 566*60062Storek static __dead void 567*60062Storek command() 5687769Ssam { 5697769Ssam register struct cmd *c; 5707769Ssam 5717769Ssam for (;;) { 5727769Ssam printf("%s> ", prompt); 57326103Sminshall if (gets(line) == 0) { 57426103Sminshall if (feof(stdin)) { 575*60062Storek exit(0); 57626103Sminshall } else { 57726103Sminshall continue; 57826103Sminshall } 57926103Sminshall } 5807769Ssam if (line[0] == 0) 58113017Ssam continue; 5827769Ssam makeargv(); 58356221Sandrew if (margc == 0) 58456221Sandrew continue; 5857769Ssam c = getcmd(margv[0]); 5867769Ssam if (c == (struct cmd *)-1) { 5877769Ssam printf("?Ambiguous command\n"); 5887769Ssam continue; 5897769Ssam } 5907769Ssam if (c == 0) { 5917769Ssam printf("?Invalid command\n"); 5927769Ssam continue; 5937769Ssam } 5947769Ssam (*c->handler)(margc, margv); 5957769Ssam } 5967769Ssam } 5977769Ssam 5987769Ssam struct cmd * 5997769Ssam getcmd(name) 6007769Ssam register char *name; 6017769Ssam { 6027769Ssam register char *p, *q; 6037769Ssam register struct cmd *c, *found; 6047769Ssam register int nmatches, longest; 6057769Ssam 6067769Ssam longest = 0; 6077769Ssam nmatches = 0; 6087769Ssam found = 0; 609*60062Storek for (c = cmdtab; (p = c->name) != NULL; c++) { 6107769Ssam for (q = name; *q == *p++; q++) 6117769Ssam if (*q == 0) /* exact match? */ 6127769Ssam return (c); 6137769Ssam if (!*q) { /* the name was a prefix */ 6147769Ssam if (q - name > longest) { 6157769Ssam longest = q - name; 6167769Ssam nmatches = 1; 6177769Ssam found = c; 6187769Ssam } else if (q - name == longest) 6197769Ssam nmatches++; 6207769Ssam } 6217769Ssam } 6227769Ssam if (nmatches > 1) 6237769Ssam return ((struct cmd *)-1); 6247769Ssam return (found); 6257769Ssam } 6267769Ssam 6277769Ssam /* 6287769Ssam * Slice a string up into argc/argv. 6297769Ssam */ 630*60062Storek static void 6317769Ssam makeargv() 6327769Ssam { 6337769Ssam register char *cp; 6347769Ssam register char **argp = margv; 6357769Ssam 6367769Ssam margc = 0; 6377769Ssam for (cp = line; *cp;) { 6387769Ssam while (isspace(*cp)) 6397769Ssam cp++; 6407769Ssam if (*cp == '\0') 6417769Ssam break; 6427769Ssam *argp++ = cp; 6437769Ssam margc += 1; 6447769Ssam while (*cp != '\0' && !isspace(*cp)) 6457769Ssam cp++; 6467769Ssam if (*cp == '\0') 6477769Ssam break; 6487769Ssam *cp++ = '\0'; 6497769Ssam } 6507769Ssam *argp++ = 0; 6517769Ssam } 6527769Ssam 653*60062Storek void 654*60062Storek quit(argc, argv) 655*60062Storek int argc; 656*60062Storek char *argv[]; 6577769Ssam { 658*60062Storek 6597769Ssam exit(0); 6607769Ssam } 6617769Ssam 6627769Ssam /* 6637769Ssam * Help command. 6647769Ssam */ 665*60062Storek void 6667769Ssam help(argc, argv) 6677769Ssam int argc; 6687769Ssam char *argv[]; 6697769Ssam { 6707769Ssam register struct cmd *c; 6717769Ssam 6727769Ssam if (argc == 1) { 6737769Ssam printf("Commands may be abbreviated. Commands are:\n\n"); 6747769Ssam for (c = cmdtab; c->name; c++) 675*60062Storek printf("%-*s\t%s\n", (int)HELPINDENT, c->name, c->help); 6767769Ssam return; 6777769Ssam } 6787769Ssam while (--argc > 0) { 6797769Ssam register char *arg; 6807769Ssam arg = *++argv; 6817769Ssam c = getcmd(arg); 6827769Ssam if (c == (struct cmd *)-1) 6837769Ssam printf("?Ambiguous help command %s\n", arg); 6847769Ssam else if (c == (struct cmd *)0) 6857769Ssam printf("?Invalid help command %s\n", arg); 6867769Ssam else 6877769Ssam printf("%s\n", c->help); 6887769Ssam } 6897769Ssam } 6907769Ssam 691*60062Storek void 692*60062Storek settrace(argc, argv) 693*60062Storek int argc; 694*60062Storek char **argv; 6957769Ssam { 6967769Ssam trace = !trace; 6977769Ssam printf("Packet tracing %s.\n", trace ? "on" : "off"); 6987769Ssam } 69926095Sminshall 700*60062Storek void 701*60062Storek setverbose(argc, argv) 702*60062Storek int argc; 703*60062Storek char **argv; 70426095Sminshall { 70526095Sminshall verbose = !verbose; 70626095Sminshall printf("Verbose mode %s.\n", verbose ? "on" : "off"); 70726095Sminshall } 708