main.c revision 36792
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1983, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 3528202Scharnierstatic const char copyright[] = 361590Srgrimes"@(#) Copyright (c) 1983, 1993\n\ 371590Srgrimes The Regents of the University of California. All rights reserved.\n"; 381590Srgrimes#endif /* not lint */ 391590Srgrimes 401590Srgrimes#ifndef lint 4128202Scharnier#if 0 421590Srgrimesstatic char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; 4328202Scharnier#endif 4428202Scharnierstatic const char rcsid[] = 4536792Simp "$Id: main.c,v 1.5 1997/08/14 06:47:39 charnier Exp $"; 461590Srgrimes#endif /* not lint */ 471590Srgrimes 481590Srgrimes/* Many bug fixes are from Jim Guyton <guyton@rand-unix> */ 491590Srgrimes 501590Srgrimes/* 511590Srgrimes * TFTP User Program -- Command Interface. 521590Srgrimes */ 5328202Scharnier#include <sys/param.h> 541590Srgrimes#include <sys/types.h> 551590Srgrimes#include <sys/socket.h> 561590Srgrimes#include <sys/file.h> 5736792Simp#include <sys/param.h> 581590Srgrimes 591590Srgrimes#include <netinet/in.h> 601590Srgrimes 611590Srgrimes#include <arpa/inet.h> 621590Srgrimes 631590Srgrimes#include <ctype.h> 6428202Scharnier#include <err.h> 651590Srgrimes#include <netdb.h> 661590Srgrimes#include <setjmp.h> 671590Srgrimes#include <signal.h> 681590Srgrimes#include <stdio.h> 691590Srgrimes#include <stdlib.h> 701590Srgrimes#include <string.h> 711590Srgrimes#include <unistd.h> 721590Srgrimes 731590Srgrimes#include "extern.h" 741590Srgrimes 751590Srgrimes#define TIMEOUT 5 /* secs between rexmt's */ 761590Srgrimes 771590Srgrimesstruct sockaddr_in peeraddr; 781590Srgrimesint f; 791590Srgrimesshort port; 801590Srgrimesint trace; 811590Srgrimesint verbose; 821590Srgrimesint connected; 831590Srgrimeschar mode[32]; 841590Srgrimeschar line[200]; 851590Srgrimesint margc; 861590Srgrimeschar *margv[20]; 871590Srgrimeschar *prompt = "tftp"; 881590Srgrimesjmp_buf toplevel; 891590Srgrimesvoid intr(); 901590Srgrimesstruct servent *sp; 911590Srgrimes 921590Srgrimesvoid get __P((int, char **)); 931590Srgrimesvoid help __P((int, char **)); 941590Srgrimesvoid modecmd __P((int, char **)); 951590Srgrimesvoid put __P((int, char **)); 961590Srgrimesvoid quit __P((int, char **)); 971590Srgrimesvoid setascii __P((int, char **)); 981590Srgrimesvoid setbinary __P((int, char **)); 991590Srgrimesvoid setpeer __P((int, char **)); 1001590Srgrimesvoid setrexmt __P((int, char **)); 1011590Srgrimesvoid settimeout __P((int, char **)); 1021590Srgrimesvoid settrace __P((int, char **)); 1031590Srgrimesvoid setverbose __P((int, char **)); 1041590Srgrimesvoid status __P((int, char **)); 1051590Srgrimes 10618286Sbdestatic void command __P((void)) __dead2; 1071590Srgrimes 1081590Srgrimesstatic void getusage __P((char *)); 1091590Srgrimesstatic void makeargv __P((void)); 1101590Srgrimesstatic void putusage __P((char *)); 1111590Srgrimesstatic void settftpmode __P((char *)); 1121590Srgrimes 1131590Srgrimes#define HELPINDENT (sizeof("connect")) 1141590Srgrimes 1151590Srgrimesstruct cmd { 1161590Srgrimes char *name; 1171590Srgrimes char *help; 1181590Srgrimes void (*handler) __P((int, char **)); 1191590Srgrimes}; 1201590Srgrimes 1211590Srgrimeschar vhelp[] = "toggle verbose mode"; 1221590Srgrimeschar thelp[] = "toggle packet tracing"; 1231590Srgrimeschar chelp[] = "connect to remote tftp"; 1241590Srgrimeschar qhelp[] = "exit tftp"; 1251590Srgrimeschar hhelp[] = "print help information"; 1261590Srgrimeschar shelp[] = "send file"; 1271590Srgrimeschar rhelp[] = "receive file"; 1281590Srgrimeschar mhelp[] = "set file transfer mode"; 1291590Srgrimeschar sthelp[] = "show current status"; 1301590Srgrimeschar xhelp[] = "set per-packet retransmission timeout"; 1311590Srgrimeschar ihelp[] = "set total retransmission timeout"; 1321590Srgrimeschar ashelp[] = "set mode to netascii"; 1331590Srgrimeschar bnhelp[] = "set mode to octet"; 1341590Srgrimes 1351590Srgrimesstruct cmd cmdtab[] = { 1361590Srgrimes { "connect", chelp, setpeer }, 1371590Srgrimes { "mode", mhelp, modecmd }, 1381590Srgrimes { "put", shelp, put }, 1391590Srgrimes { "get", rhelp, get }, 1401590Srgrimes { "quit", qhelp, quit }, 1411590Srgrimes { "verbose", vhelp, setverbose }, 1421590Srgrimes { "trace", thelp, settrace }, 1431590Srgrimes { "status", sthelp, status }, 1441590Srgrimes { "binary", bnhelp, setbinary }, 1451590Srgrimes { "ascii", ashelp, setascii }, 1461590Srgrimes { "rexmt", xhelp, setrexmt }, 1471590Srgrimes { "timeout", ihelp, settimeout }, 1481590Srgrimes { "?", hhelp, help }, 1491590Srgrimes { 0 } 1501590Srgrimes}; 1511590Srgrimes 1521590Srgrimesstruct cmd *getcmd(); 1531590Srgrimeschar *tail(); 1541590Srgrimes 1551590Srgrimesint 1561590Srgrimesmain(argc, argv) 1571590Srgrimes int argc; 1581590Srgrimes char *argv[]; 1591590Srgrimes{ 1601590Srgrimes struct sockaddr_in sin; 1611590Srgrimes 1621590Srgrimes sp = getservbyname("tftp", "udp"); 16328202Scharnier if (sp == 0) 16428202Scharnier errx(1, "udp/tftp: unknown service"); 1651590Srgrimes f = socket(AF_INET, SOCK_DGRAM, 0); 16628202Scharnier if (f < 0) 16728202Scharnier err(3, "socket"); 1681590Srgrimes bzero((char *)&sin, sizeof(sin)); 1691590Srgrimes sin.sin_family = AF_INET; 17028202Scharnier if (bind(f, (struct sockaddr *)&sin, sizeof(sin)) < 0) 17128202Scharnier err(1, "bind"); 1721590Srgrimes strcpy(mode, "netascii"); 1731590Srgrimes signal(SIGINT, intr); 1741590Srgrimes if (argc > 1) { 1751590Srgrimes if (setjmp(toplevel) != 0) 1761590Srgrimes exit(0); 1771590Srgrimes setpeer(argc, argv); 1781590Srgrimes } 1791590Srgrimes if (setjmp(toplevel) != 0) 1801590Srgrimes (void)putchar('\n'); 1811590Srgrimes command(); 1821590Srgrimes} 1831590Srgrimes 18428202Scharnierchar hostname[MAXHOSTNAMELEN]; 1851590Srgrimes 1861590Srgrimesvoid 1871590Srgrimessetpeer(argc, argv) 1881590Srgrimes int argc; 1891590Srgrimes char *argv[]; 1901590Srgrimes{ 1911590Srgrimes struct hostent *host; 1921590Srgrimes 1931590Srgrimes if (argc < 2) { 1941590Srgrimes strcpy(line, "Connect "); 1951590Srgrimes printf("(to) "); 19613068Sjoerg fgets(&line[strlen(line)], sizeof line - strlen(line), stdin); 1971590Srgrimes makeargv(); 1981590Srgrimes argc = margc; 1991590Srgrimes argv = margv; 2001590Srgrimes } 2011590Srgrimes if (argc > 3) { 2021590Srgrimes printf("usage: %s host-name [port]\n", argv[0]); 2031590Srgrimes return; 2041590Srgrimes } 2051590Srgrimes host = gethostbyname(argv[1]); 2061590Srgrimes if (host) { 2071590Srgrimes peeraddr.sin_family = host->h_addrtype; 20836792Simp bcopy(host->h_addr, &peeraddr.sin_addr, 20936792Simp MIN(sizeof(peeraddr.sin_addr), host->h_length)); 21036792Simp strncpy(hostname, host->h_name, sizeof(hostname)); 2111590Srgrimes } else { 2121590Srgrimes peeraddr.sin_family = AF_INET; 2131590Srgrimes peeraddr.sin_addr.s_addr = inet_addr(argv[1]); 2141590Srgrimes if (peeraddr.sin_addr.s_addr == -1) { 2151590Srgrimes connected = 0; 2161590Srgrimes printf("%s: unknown host\n", argv[1]); 2171590Srgrimes return; 2181590Srgrimes } 21936792Simp strncpy(hostname, argv[1], sizeof(hostname)); 2201590Srgrimes } 22136792Simp hostname[sizeof(hostname) - 1] = '\0'; 2221590Srgrimes port = sp->s_port; 2231590Srgrimes if (argc == 3) { 2241590Srgrimes port = atoi(argv[2]); 2251590Srgrimes if (port < 0) { 2261590Srgrimes printf("%s: bad port number\n", argv[2]); 2271590Srgrimes connected = 0; 2281590Srgrimes return; 2291590Srgrimes } 2301590Srgrimes port = htons(port); 2311590Srgrimes } 2321590Srgrimes connected = 1; 2331590Srgrimes} 2341590Srgrimes 2351590Srgrimesstruct modes { 2361590Srgrimes char *m_name; 2371590Srgrimes char *m_mode; 2381590Srgrimes} modes[] = { 2391590Srgrimes { "ascii", "netascii" }, 2401590Srgrimes { "netascii", "netascii" }, 2411590Srgrimes { "binary", "octet" }, 2421590Srgrimes { "image", "octet" }, 2431590Srgrimes { "octet", "octet" }, 2441590Srgrimes/* { "mail", "mail" }, */ 2451590Srgrimes { 0, 0 } 2461590Srgrimes}; 2471590Srgrimes 2481590Srgrimesvoid 2491590Srgrimesmodecmd(argc, argv) 2501590Srgrimes int argc; 2511590Srgrimes char *argv[]; 2521590Srgrimes{ 2531590Srgrimes register struct modes *p; 2541590Srgrimes char *sep; 2551590Srgrimes 2561590Srgrimes if (argc < 2) { 2571590Srgrimes printf("Using %s mode to transfer files.\n", mode); 2581590Srgrimes return; 2591590Srgrimes } 2601590Srgrimes if (argc == 2) { 2611590Srgrimes for (p = modes; p->m_name; p++) 2621590Srgrimes if (strcmp(argv[1], p->m_name) == 0) 2631590Srgrimes break; 2641590Srgrimes if (p->m_name) { 2651590Srgrimes settftpmode(p->m_mode); 2661590Srgrimes return; 2671590Srgrimes } 2681590Srgrimes printf("%s: unknown mode\n", argv[1]); 2691590Srgrimes /* drop through and print usage message */ 2701590Srgrimes } 2711590Srgrimes 2721590Srgrimes printf("usage: %s [", argv[0]); 2731590Srgrimes sep = " "; 2741590Srgrimes for (p = modes; p->m_name; p++) { 2751590Srgrimes printf("%s%s", sep, p->m_name); 2761590Srgrimes if (*sep == ' ') 2771590Srgrimes sep = " | "; 2781590Srgrimes } 2791590Srgrimes printf(" ]\n"); 2801590Srgrimes return; 2811590Srgrimes} 2821590Srgrimes 2831590Srgrimesvoid 2841590Srgrimessetbinary(argc, argv) 2851590Srgrimes int argc; 2861590Srgrimes char *argv[]; 2878874Srgrimes{ 2881590Srgrimes 2891590Srgrimes settftpmode("octet"); 2901590Srgrimes} 2911590Srgrimes 2921590Srgrimesvoid 2931590Srgrimessetascii(argc, argv) 2941590Srgrimes int argc; 2951590Srgrimes char *argv[]; 2961590Srgrimes{ 2971590Srgrimes 2981590Srgrimes settftpmode("netascii"); 2991590Srgrimes} 3001590Srgrimes 3011590Srgrimesstatic void 3021590Srgrimessettftpmode(newmode) 3031590Srgrimes char *newmode; 3041590Srgrimes{ 3051590Srgrimes strcpy(mode, newmode); 3061590Srgrimes if (verbose) 3071590Srgrimes printf("mode set to %s\n", mode); 3081590Srgrimes} 3091590Srgrimes 3101590Srgrimes 3111590Srgrimes/* 3121590Srgrimes * Send file(s). 3131590Srgrimes */ 3141590Srgrimesvoid 3151590Srgrimesput(argc, argv) 3161590Srgrimes int argc; 3171590Srgrimes char *argv[]; 3181590Srgrimes{ 3191590Srgrimes int fd; 3201590Srgrimes register int n; 3211590Srgrimes register char *cp, *targ; 3221590Srgrimes 3231590Srgrimes if (argc < 2) { 3241590Srgrimes strcpy(line, "send "); 3251590Srgrimes printf("(file) "); 32613068Sjoerg fgets(&line[strlen(line)], sizeof line - strlen(line), stdin); 3271590Srgrimes makeargv(); 3281590Srgrimes argc = margc; 3291590Srgrimes argv = margv; 3301590Srgrimes } 3311590Srgrimes if (argc < 2) { 3321590Srgrimes putusage(argv[0]); 3331590Srgrimes return; 3341590Srgrimes } 3351590Srgrimes targ = argv[argc - 1]; 3361590Srgrimes if (index(argv[argc - 1], ':')) { 3371590Srgrimes char *cp; 3381590Srgrimes struct hostent *hp; 3391590Srgrimes 3401590Srgrimes for (n = 1; n < argc - 1; n++) 3411590Srgrimes if (index(argv[n], ':')) { 3421590Srgrimes putusage(argv[0]); 3431590Srgrimes return; 3441590Srgrimes } 3451590Srgrimes cp = argv[argc - 1]; 3461590Srgrimes targ = index(cp, ':'); 3471590Srgrimes *targ++ = 0; 3481590Srgrimes hp = gethostbyname(cp); 3491590Srgrimes if (hp == NULL) { 3501590Srgrimes fprintf(stderr, "tftp: %s: ", cp); 3511590Srgrimes herror((char *)NULL); 3521590Srgrimes return; 3531590Srgrimes } 35436792Simp bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr, 35536792Simp MIN(sizeof(peeraddr.sin_addr), hp->h_length)); 3561590Srgrimes peeraddr.sin_family = hp->h_addrtype; 3571590Srgrimes connected = 1; 35836792Simp strncpy(hostname, hp->h_name, sizeof(hostname)); 35936792Simp hostname[sizeof(hostname) - 1] = '\0'; 3601590Srgrimes } 3611590Srgrimes if (!connected) { 3621590Srgrimes printf("No target machine specified.\n"); 3631590Srgrimes return; 3641590Srgrimes } 3651590Srgrimes if (argc < 4) { 3661590Srgrimes cp = argc == 2 ? tail(targ) : argv[1]; 3671590Srgrimes fd = open(cp, O_RDONLY); 3681590Srgrimes if (fd < 0) { 36928202Scharnier warn("%s", cp); 3701590Srgrimes return; 3711590Srgrimes } 3721590Srgrimes if (verbose) 3731590Srgrimes printf("putting %s to %s:%s [%s]\n", 3741590Srgrimes cp, hostname, targ, mode); 3751590Srgrimes peeraddr.sin_port = port; 3761590Srgrimes sendfile(fd, targ, mode); 3771590Srgrimes return; 3781590Srgrimes } 3791590Srgrimes /* this assumes the target is a directory */ 3801590Srgrimes /* on a remote unix system. hmmmm. */ 3818874Srgrimes cp = index(targ, '\0'); 3821590Srgrimes *cp++ = '/'; 3831590Srgrimes for (n = 1; n < argc - 1; n++) { 3841590Srgrimes strcpy(cp, tail(argv[n])); 3851590Srgrimes fd = open(argv[n], O_RDONLY); 3861590Srgrimes if (fd < 0) { 38728202Scharnier warn("%s", argv[n]); 3881590Srgrimes continue; 3891590Srgrimes } 3901590Srgrimes if (verbose) 3911590Srgrimes printf("putting %s to %s:%s [%s]\n", 3921590Srgrimes argv[n], hostname, targ, mode); 3931590Srgrimes peeraddr.sin_port = port; 3941590Srgrimes sendfile(fd, targ, mode); 3951590Srgrimes } 3961590Srgrimes} 3971590Srgrimes 3981590Srgrimesstatic void 3991590Srgrimesputusage(s) 4001590Srgrimes char *s; 4011590Srgrimes{ 4021590Srgrimes printf("usage: %s file ... host:target, or\n", s); 4031590Srgrimes printf(" %s file ... target (when already connected)\n", s); 4041590Srgrimes} 4051590Srgrimes 4061590Srgrimes/* 4071590Srgrimes * Receive file(s). 4081590Srgrimes */ 4091590Srgrimesvoid 4101590Srgrimesget(argc, argv) 4111590Srgrimes int argc; 4121590Srgrimes char *argv[]; 4131590Srgrimes{ 4141590Srgrimes int fd; 4151590Srgrimes register int n; 4161590Srgrimes register char *cp; 4171590Srgrimes char *src; 4181590Srgrimes 4191590Srgrimes if (argc < 2) { 4201590Srgrimes strcpy(line, "get "); 4211590Srgrimes printf("(files) "); 42213068Sjoerg fgets(&line[strlen(line)], sizeof line - strlen(line), stdin); 4231590Srgrimes makeargv(); 4241590Srgrimes argc = margc; 4251590Srgrimes argv = margv; 4261590Srgrimes } 4271590Srgrimes if (argc < 2) { 4281590Srgrimes getusage(argv[0]); 4291590Srgrimes return; 4301590Srgrimes } 4311590Srgrimes if (!connected) { 4321590Srgrimes for (n = 1; n < argc ; n++) 4331590Srgrimes if (index(argv[n], ':') == 0) { 4341590Srgrimes getusage(argv[0]); 4351590Srgrimes return; 4361590Srgrimes } 4371590Srgrimes } 4381590Srgrimes for (n = 1; n < argc ; n++) { 4391590Srgrimes src = index(argv[n], ':'); 4401590Srgrimes if (src == NULL) 4411590Srgrimes src = argv[n]; 4421590Srgrimes else { 4431590Srgrimes struct hostent *hp; 4441590Srgrimes 4451590Srgrimes *src++ = 0; 4461590Srgrimes hp = gethostbyname(argv[n]); 4471590Srgrimes if (hp == NULL) { 4481590Srgrimes fprintf(stderr, "tftp: %s: ", argv[n]); 4491590Srgrimes herror((char *)NULL); 4501590Srgrimes continue; 4511590Srgrimes } 4521590Srgrimes bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr, 45336792Simp MIN(sizeof(peeraddr.sin_addr), hp->h_length)); 4541590Srgrimes peeraddr.sin_family = hp->h_addrtype; 4551590Srgrimes connected = 1; 45636792Simp strncpy(hostname, hp->h_name, sizeof(hostname)); 45736792Simp hostname[sizeof(hostname) - 1] = '\0'; 4581590Srgrimes } 4591590Srgrimes if (argc < 4) { 4601590Srgrimes cp = argc == 3 ? argv[2] : tail(src); 4611590Srgrimes fd = creat(cp, 0644); 4621590Srgrimes if (fd < 0) { 46328202Scharnier warn("%s", cp); 4641590Srgrimes return; 4651590Srgrimes } 4661590Srgrimes if (verbose) 4671590Srgrimes printf("getting from %s:%s to %s [%s]\n", 4681590Srgrimes hostname, src, cp, mode); 4691590Srgrimes peeraddr.sin_port = port; 4701590Srgrimes recvfile(fd, src, mode); 4711590Srgrimes break; 4721590Srgrimes } 4731590Srgrimes cp = tail(src); /* new .. jdg */ 4741590Srgrimes fd = creat(cp, 0644); 4751590Srgrimes if (fd < 0) { 47628202Scharnier warn("%s", cp); 4771590Srgrimes continue; 4781590Srgrimes } 4791590Srgrimes if (verbose) 4801590Srgrimes printf("getting from %s:%s to %s [%s]\n", 4811590Srgrimes hostname, src, cp, mode); 4821590Srgrimes peeraddr.sin_port = port; 4831590Srgrimes recvfile(fd, src, mode); 4841590Srgrimes } 4851590Srgrimes} 4861590Srgrimes 4871590Srgrimesstatic void 4881590Srgrimesgetusage(s) 4891590Srgrimes char *s; 4901590Srgrimes{ 4911590Srgrimes printf("usage: %s host:file host:file ... file, or\n", s); 4921590Srgrimes printf(" %s file file ... file if connected\n", s); 4931590Srgrimes} 4941590Srgrimes 4951590Srgrimesint rexmtval = TIMEOUT; 4961590Srgrimes 4971590Srgrimesvoid 4981590Srgrimessetrexmt(argc, argv) 4991590Srgrimes int argc; 5001590Srgrimes char *argv[]; 5011590Srgrimes{ 5021590Srgrimes int t; 5031590Srgrimes 5041590Srgrimes if (argc < 2) { 5051590Srgrimes strcpy(line, "Rexmt-timeout "); 5061590Srgrimes printf("(value) "); 50713068Sjoerg fgets(&line[strlen(line)], sizeof line - strlen(line), stdin); 5081590Srgrimes makeargv(); 5091590Srgrimes argc = margc; 5101590Srgrimes argv = margv; 5111590Srgrimes } 5121590Srgrimes if (argc != 2) { 5131590Srgrimes printf("usage: %s value\n", argv[0]); 5141590Srgrimes return; 5151590Srgrimes } 5161590Srgrimes t = atoi(argv[1]); 5171590Srgrimes if (t < 0) 5181590Srgrimes printf("%s: bad value\n", argv[1]); 5191590Srgrimes else 5201590Srgrimes rexmtval = t; 5211590Srgrimes} 5221590Srgrimes 5231590Srgrimesint maxtimeout = 5 * TIMEOUT; 5241590Srgrimes 5251590Srgrimesvoid 5261590Srgrimessettimeout(argc, argv) 5271590Srgrimes int argc; 5281590Srgrimes char *argv[]; 5291590Srgrimes{ 5301590Srgrimes int t; 5311590Srgrimes 5321590Srgrimes if (argc < 2) { 5331590Srgrimes strcpy(line, "Maximum-timeout "); 5341590Srgrimes printf("(value) "); 53513068Sjoerg fgets(&line[strlen(line)], sizeof line - strlen(line), stdin); 5361590Srgrimes makeargv(); 5371590Srgrimes argc = margc; 5381590Srgrimes argv = margv; 5391590Srgrimes } 5401590Srgrimes if (argc != 2) { 5411590Srgrimes printf("usage: %s value\n", argv[0]); 5421590Srgrimes return; 5431590Srgrimes } 5441590Srgrimes t = atoi(argv[1]); 5451590Srgrimes if (t < 0) 5461590Srgrimes printf("%s: bad value\n", argv[1]); 5471590Srgrimes else 5481590Srgrimes maxtimeout = t; 5491590Srgrimes} 5501590Srgrimes 5511590Srgrimesvoid 5521590Srgrimesstatus(argc, argv) 5531590Srgrimes int argc; 5541590Srgrimes char *argv[]; 5551590Srgrimes{ 5561590Srgrimes if (connected) 5571590Srgrimes printf("Connected to %s.\n", hostname); 5581590Srgrimes else 5591590Srgrimes printf("Not connected.\n"); 5601590Srgrimes printf("Mode: %s Verbose: %s Tracing: %s\n", mode, 5611590Srgrimes verbose ? "on" : "off", trace ? "on" : "off"); 5621590Srgrimes printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n", 5631590Srgrimes rexmtval, maxtimeout); 5641590Srgrimes} 5651590Srgrimes 5661590Srgrimesvoid 5671590Srgrimesintr() 5681590Srgrimes{ 5691590Srgrimes 5701590Srgrimes signal(SIGALRM, SIG_IGN); 5711590Srgrimes alarm(0); 5721590Srgrimes longjmp(toplevel, -1); 5731590Srgrimes} 5741590Srgrimes 5751590Srgrimeschar * 5761590Srgrimestail(filename) 5771590Srgrimes char *filename; 5781590Srgrimes{ 5791590Srgrimes register char *s; 5808874Srgrimes 5811590Srgrimes while (*filename) { 5821590Srgrimes s = rindex(filename, '/'); 5831590Srgrimes if (s == NULL) 5841590Srgrimes break; 5851590Srgrimes if (s[1]) 5861590Srgrimes return (s + 1); 5871590Srgrimes *s = '\0'; 5881590Srgrimes } 5891590Srgrimes return (filename); 5901590Srgrimes} 5911590Srgrimes 5921590Srgrimes/* 5931590Srgrimes * Command parser. 5941590Srgrimes */ 59518286Sbdestatic void 5961590Srgrimescommand() 5971590Srgrimes{ 5981590Srgrimes register struct cmd *c; 59913068Sjoerg char *cp; 6001590Srgrimes 6011590Srgrimes for (;;) { 6021590Srgrimes printf("%s> ", prompt); 60313068Sjoerg if (fgets(line, sizeof line , stdin) == 0) { 6041590Srgrimes if (feof(stdin)) { 6051590Srgrimes exit(0); 6061590Srgrimes } else { 6071590Srgrimes continue; 6081590Srgrimes } 6091590Srgrimes } 61013068Sjoerg if ((cp = strchr(line, '\n'))) 61113068Sjoerg *cp = '\0'; 6121590Srgrimes if (line[0] == 0) 6131590Srgrimes continue; 6141590Srgrimes makeargv(); 6151590Srgrimes if (margc == 0) 6161590Srgrimes continue; 6171590Srgrimes c = getcmd(margv[0]); 6181590Srgrimes if (c == (struct cmd *)-1) { 6191590Srgrimes printf("?Ambiguous command\n"); 6201590Srgrimes continue; 6211590Srgrimes } 6221590Srgrimes if (c == 0) { 6231590Srgrimes printf("?Invalid command\n"); 6241590Srgrimes continue; 6251590Srgrimes } 6261590Srgrimes (*c->handler)(margc, margv); 6271590Srgrimes } 6281590Srgrimes} 6291590Srgrimes 6301590Srgrimesstruct cmd * 6311590Srgrimesgetcmd(name) 6321590Srgrimes register char *name; 6331590Srgrimes{ 6341590Srgrimes register char *p, *q; 6351590Srgrimes register struct cmd *c, *found; 6361590Srgrimes register int nmatches, longest; 6371590Srgrimes 6381590Srgrimes longest = 0; 6391590Srgrimes nmatches = 0; 6401590Srgrimes found = 0; 6411590Srgrimes for (c = cmdtab; (p = c->name) != NULL; c++) { 6421590Srgrimes for (q = name; *q == *p++; q++) 6431590Srgrimes if (*q == 0) /* exact match? */ 6441590Srgrimes return (c); 6451590Srgrimes if (!*q) { /* the name was a prefix */ 6461590Srgrimes if (q - name > longest) { 6471590Srgrimes longest = q - name; 6481590Srgrimes nmatches = 1; 6491590Srgrimes found = c; 6501590Srgrimes } else if (q - name == longest) 6511590Srgrimes nmatches++; 6521590Srgrimes } 6531590Srgrimes } 6541590Srgrimes if (nmatches > 1) 6551590Srgrimes return ((struct cmd *)-1); 6561590Srgrimes return (found); 6571590Srgrimes} 6581590Srgrimes 6591590Srgrimes/* 6601590Srgrimes * Slice a string up into argc/argv. 6611590Srgrimes */ 6621590Srgrimesstatic void 6631590Srgrimesmakeargv() 6641590Srgrimes{ 6651590Srgrimes register char *cp; 6661590Srgrimes register char **argp = margv; 6671590Srgrimes 6681590Srgrimes margc = 0; 66913068Sjoerg if ((cp = strchr(line, '\n'))) 67013068Sjoerg *cp = '\0'; 6711590Srgrimes for (cp = line; *cp;) { 6721590Srgrimes while (isspace(*cp)) 6731590Srgrimes cp++; 6741590Srgrimes if (*cp == '\0') 6751590Srgrimes break; 6761590Srgrimes *argp++ = cp; 6771590Srgrimes margc += 1; 6781590Srgrimes while (*cp != '\0' && !isspace(*cp)) 6791590Srgrimes cp++; 6801590Srgrimes if (*cp == '\0') 6811590Srgrimes break; 6821590Srgrimes *cp++ = '\0'; 6831590Srgrimes } 6841590Srgrimes *argp++ = 0; 6851590Srgrimes} 6861590Srgrimes 6871590Srgrimesvoid 6881590Srgrimesquit(argc, argv) 6891590Srgrimes int argc; 6901590Srgrimes char *argv[]; 6911590Srgrimes{ 6921590Srgrimes 6931590Srgrimes exit(0); 6941590Srgrimes} 6951590Srgrimes 6961590Srgrimes/* 6971590Srgrimes * Help command. 6981590Srgrimes */ 6991590Srgrimesvoid 7001590Srgrimeshelp(argc, argv) 7011590Srgrimes int argc; 7021590Srgrimes char *argv[]; 7031590Srgrimes{ 7041590Srgrimes register struct cmd *c; 7051590Srgrimes 7061590Srgrimes if (argc == 1) { 7071590Srgrimes printf("Commands may be abbreviated. Commands are:\n\n"); 7081590Srgrimes for (c = cmdtab; c->name; c++) 7091590Srgrimes printf("%-*s\t%s\n", (int)HELPINDENT, c->name, c->help); 7101590Srgrimes return; 7111590Srgrimes } 7121590Srgrimes while (--argc > 0) { 7131590Srgrimes register char *arg; 7141590Srgrimes arg = *++argv; 7151590Srgrimes c = getcmd(arg); 7161590Srgrimes if (c == (struct cmd *)-1) 7171590Srgrimes printf("?Ambiguous help command %s\n", arg); 7181590Srgrimes else if (c == (struct cmd *)0) 7191590Srgrimes printf("?Invalid help command %s\n", arg); 7201590Srgrimes else 7211590Srgrimes printf("%s\n", c->help); 7221590Srgrimes } 7231590Srgrimes} 7241590Srgrimes 7251590Srgrimesvoid 7261590Srgrimessettrace(argc, argv) 7271590Srgrimes int argc; 7281590Srgrimes char **argv; 7291590Srgrimes{ 7301590Srgrimes trace = !trace; 7311590Srgrimes printf("Packet tracing %s.\n", trace ? "on" : "off"); 7321590Srgrimes} 7331590Srgrimes 7341590Srgrimesvoid 7351590Srgrimessetverbose(argc, argv) 7361590Srgrimes int argc; 7371590Srgrimes char **argv; 7381590Srgrimes{ 7391590Srgrimes verbose = !verbose; 7401590Srgrimes printf("Verbose mode %s.\n", verbose ? "on" : "off"); 7411590Srgrimes} 742