main.c revision 13068
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 351590Srgrimesstatic 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 411590Srgrimesstatic char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; 421590Srgrimes#endif /* not lint */ 431590Srgrimes 441590Srgrimes/* Many bug fixes are from Jim Guyton <guyton@rand-unix> */ 451590Srgrimes 461590Srgrimes/* 471590Srgrimes * TFTP User Program -- Command Interface. 481590Srgrimes */ 491590Srgrimes#include <sys/types.h> 501590Srgrimes#include <sys/socket.h> 511590Srgrimes#include <sys/file.h> 521590Srgrimes 531590Srgrimes#include <netinet/in.h> 541590Srgrimes 551590Srgrimes#include <arpa/inet.h> 561590Srgrimes 571590Srgrimes#include <ctype.h> 581590Srgrimes#include <errno.h> 591590Srgrimes#include <netdb.h> 601590Srgrimes#include <setjmp.h> 611590Srgrimes#include <signal.h> 621590Srgrimes#include <stdio.h> 631590Srgrimes#include <stdlib.h> 641590Srgrimes#include <string.h> 651590Srgrimes#include <unistd.h> 661590Srgrimes 671590Srgrimes#include "extern.h" 681590Srgrimes 691590Srgrimes#define TIMEOUT 5 /* secs between rexmt's */ 701590Srgrimes 711590Srgrimesstruct sockaddr_in peeraddr; 721590Srgrimesint f; 731590Srgrimesshort port; 741590Srgrimesint trace; 751590Srgrimesint verbose; 761590Srgrimesint connected; 771590Srgrimeschar mode[32]; 781590Srgrimeschar line[200]; 791590Srgrimesint margc; 801590Srgrimeschar *margv[20]; 811590Srgrimeschar *prompt = "tftp"; 821590Srgrimesjmp_buf toplevel; 831590Srgrimesvoid intr(); 841590Srgrimesstruct servent *sp; 851590Srgrimes 861590Srgrimesvoid get __P((int, char **)); 871590Srgrimesvoid help __P((int, char **)); 881590Srgrimesvoid modecmd __P((int, char **)); 891590Srgrimesvoid put __P((int, char **)); 901590Srgrimesvoid quit __P((int, char **)); 911590Srgrimesvoid setascii __P((int, char **)); 921590Srgrimesvoid setbinary __P((int, char **)); 931590Srgrimesvoid setpeer __P((int, char **)); 941590Srgrimesvoid setrexmt __P((int, char **)); 951590Srgrimesvoid settimeout __P((int, char **)); 961590Srgrimesvoid settrace __P((int, char **)); 971590Srgrimesvoid setverbose __P((int, char **)); 981590Srgrimesvoid status __P((int, char **)); 991590Srgrimes 1001590Srgrimesstatic __dead void command __P((void)); 1011590Srgrimes 1021590Srgrimesstatic void getusage __P((char *)); 1031590Srgrimesstatic void makeargv __P((void)); 1041590Srgrimesstatic void putusage __P((char *)); 1051590Srgrimesstatic void settftpmode __P((char *)); 1061590Srgrimes 1071590Srgrimes#define HELPINDENT (sizeof("connect")) 1081590Srgrimes 1091590Srgrimesstruct cmd { 1101590Srgrimes char *name; 1111590Srgrimes char *help; 1121590Srgrimes void (*handler) __P((int, char **)); 1131590Srgrimes}; 1141590Srgrimes 1151590Srgrimeschar vhelp[] = "toggle verbose mode"; 1161590Srgrimeschar thelp[] = "toggle packet tracing"; 1171590Srgrimeschar chelp[] = "connect to remote tftp"; 1181590Srgrimeschar qhelp[] = "exit tftp"; 1191590Srgrimeschar hhelp[] = "print help information"; 1201590Srgrimeschar shelp[] = "send file"; 1211590Srgrimeschar rhelp[] = "receive file"; 1221590Srgrimeschar mhelp[] = "set file transfer mode"; 1231590Srgrimeschar sthelp[] = "show current status"; 1241590Srgrimeschar xhelp[] = "set per-packet retransmission timeout"; 1251590Srgrimeschar ihelp[] = "set total retransmission timeout"; 1261590Srgrimeschar ashelp[] = "set mode to netascii"; 1271590Srgrimeschar bnhelp[] = "set mode to octet"; 1281590Srgrimes 1291590Srgrimesstruct cmd cmdtab[] = { 1301590Srgrimes { "connect", chelp, setpeer }, 1311590Srgrimes { "mode", mhelp, modecmd }, 1321590Srgrimes { "put", shelp, put }, 1331590Srgrimes { "get", rhelp, get }, 1341590Srgrimes { "quit", qhelp, quit }, 1351590Srgrimes { "verbose", vhelp, setverbose }, 1361590Srgrimes { "trace", thelp, settrace }, 1371590Srgrimes { "status", sthelp, status }, 1381590Srgrimes { "binary", bnhelp, setbinary }, 1391590Srgrimes { "ascii", ashelp, setascii }, 1401590Srgrimes { "rexmt", xhelp, setrexmt }, 1411590Srgrimes { "timeout", ihelp, settimeout }, 1421590Srgrimes { "?", hhelp, help }, 1431590Srgrimes { 0 } 1441590Srgrimes}; 1451590Srgrimes 1461590Srgrimesstruct cmd *getcmd(); 1471590Srgrimeschar *tail(); 1481590Srgrimeschar *index(); 1491590Srgrimeschar *rindex(); 1501590Srgrimes 1511590Srgrimesint 1521590Srgrimesmain(argc, argv) 1531590Srgrimes int argc; 1541590Srgrimes char *argv[]; 1551590Srgrimes{ 1561590Srgrimes struct sockaddr_in sin; 1571590Srgrimes 1581590Srgrimes sp = getservbyname("tftp", "udp"); 1591590Srgrimes if (sp == 0) { 1601590Srgrimes fprintf(stderr, "tftp: udp/tftp: unknown service\n"); 1611590Srgrimes exit(1); 1621590Srgrimes } 1631590Srgrimes f = socket(AF_INET, SOCK_DGRAM, 0); 1641590Srgrimes if (f < 0) { 1651590Srgrimes perror("tftp: socket"); 1661590Srgrimes exit(3); 1671590Srgrimes } 1681590Srgrimes bzero((char *)&sin, sizeof(sin)); 1691590Srgrimes sin.sin_family = AF_INET; 1701590Srgrimes if (bind(f, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 1711590Srgrimes perror("tftp: bind"); 1721590Srgrimes exit(1); 1731590Srgrimes } 1741590Srgrimes strcpy(mode, "netascii"); 1751590Srgrimes signal(SIGINT, intr); 1761590Srgrimes if (argc > 1) { 1771590Srgrimes if (setjmp(toplevel) != 0) 1781590Srgrimes exit(0); 1791590Srgrimes setpeer(argc, argv); 1801590Srgrimes } 1811590Srgrimes if (setjmp(toplevel) != 0) 1821590Srgrimes (void)putchar('\n'); 1831590Srgrimes command(); 1841590Srgrimes} 1851590Srgrimes 1861590Srgrimeschar hostname[100]; 1871590Srgrimes 1881590Srgrimesvoid 1891590Srgrimessetpeer(argc, argv) 1901590Srgrimes int argc; 1911590Srgrimes char *argv[]; 1921590Srgrimes{ 1931590Srgrimes struct hostent *host; 1941590Srgrimes 1951590Srgrimes if (argc < 2) { 1961590Srgrimes strcpy(line, "Connect "); 1971590Srgrimes printf("(to) "); 19813068Sjoerg fgets(&line[strlen(line)], sizeof line - strlen(line), stdin); 1991590Srgrimes makeargv(); 2001590Srgrimes argc = margc; 2011590Srgrimes argv = margv; 2021590Srgrimes } 2031590Srgrimes if (argc > 3) { 2041590Srgrimes printf("usage: %s host-name [port]\n", argv[0]); 2051590Srgrimes return; 2061590Srgrimes } 2071590Srgrimes host = gethostbyname(argv[1]); 2081590Srgrimes if (host) { 2091590Srgrimes peeraddr.sin_family = host->h_addrtype; 2101590Srgrimes bcopy(host->h_addr, &peeraddr.sin_addr, host->h_length); 2111590Srgrimes strcpy(hostname, host->h_name); 2121590Srgrimes } else { 2131590Srgrimes peeraddr.sin_family = AF_INET; 2141590Srgrimes peeraddr.sin_addr.s_addr = inet_addr(argv[1]); 2151590Srgrimes if (peeraddr.sin_addr.s_addr == -1) { 2161590Srgrimes connected = 0; 2171590Srgrimes printf("%s: unknown host\n", argv[1]); 2181590Srgrimes return; 2191590Srgrimes } 2201590Srgrimes strcpy(hostname, argv[1]); 2211590Srgrimes } 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 } 3541590Srgrimes bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr, hp->h_length); 3551590Srgrimes peeraddr.sin_family = hp->h_addrtype; 3561590Srgrimes connected = 1; 3571590Srgrimes strcpy(hostname, hp->h_name); 3581590Srgrimes } 3591590Srgrimes if (!connected) { 3601590Srgrimes printf("No target machine specified.\n"); 3611590Srgrimes return; 3621590Srgrimes } 3631590Srgrimes if (argc < 4) { 3641590Srgrimes cp = argc == 2 ? tail(targ) : argv[1]; 3651590Srgrimes fd = open(cp, O_RDONLY); 3661590Srgrimes if (fd < 0) { 3671590Srgrimes fprintf(stderr, "tftp: "); perror(cp); 3681590Srgrimes return; 3691590Srgrimes } 3701590Srgrimes if (verbose) 3711590Srgrimes printf("putting %s to %s:%s [%s]\n", 3721590Srgrimes cp, hostname, targ, mode); 3731590Srgrimes peeraddr.sin_port = port; 3741590Srgrimes sendfile(fd, targ, mode); 3751590Srgrimes return; 3761590Srgrimes } 3771590Srgrimes /* this assumes the target is a directory */ 3781590Srgrimes /* on a remote unix system. hmmmm. */ 3798874Srgrimes cp = index(targ, '\0'); 3801590Srgrimes *cp++ = '/'; 3811590Srgrimes for (n = 1; n < argc - 1; n++) { 3821590Srgrimes strcpy(cp, tail(argv[n])); 3831590Srgrimes fd = open(argv[n], O_RDONLY); 3841590Srgrimes if (fd < 0) { 3851590Srgrimes fprintf(stderr, "tftp: "); perror(argv[n]); 3861590Srgrimes continue; 3871590Srgrimes } 3881590Srgrimes if (verbose) 3891590Srgrimes printf("putting %s to %s:%s [%s]\n", 3901590Srgrimes argv[n], hostname, targ, mode); 3911590Srgrimes peeraddr.sin_port = port; 3921590Srgrimes sendfile(fd, targ, mode); 3931590Srgrimes } 3941590Srgrimes} 3951590Srgrimes 3961590Srgrimesstatic void 3971590Srgrimesputusage(s) 3981590Srgrimes char *s; 3991590Srgrimes{ 4001590Srgrimes printf("usage: %s file ... host:target, or\n", s); 4011590Srgrimes printf(" %s file ... target (when already connected)\n", s); 4021590Srgrimes} 4031590Srgrimes 4041590Srgrimes/* 4051590Srgrimes * Receive file(s). 4061590Srgrimes */ 4071590Srgrimesvoid 4081590Srgrimesget(argc, argv) 4091590Srgrimes int argc; 4101590Srgrimes char *argv[]; 4111590Srgrimes{ 4121590Srgrimes int fd; 4131590Srgrimes register int n; 4141590Srgrimes register char *cp; 4151590Srgrimes char *src; 4161590Srgrimes 4171590Srgrimes if (argc < 2) { 4181590Srgrimes strcpy(line, "get "); 4191590Srgrimes printf("(files) "); 42013068Sjoerg fgets(&line[strlen(line)], sizeof line - strlen(line), stdin); 4211590Srgrimes makeargv(); 4221590Srgrimes argc = margc; 4231590Srgrimes argv = margv; 4241590Srgrimes } 4251590Srgrimes if (argc < 2) { 4261590Srgrimes getusage(argv[0]); 4271590Srgrimes return; 4281590Srgrimes } 4291590Srgrimes if (!connected) { 4301590Srgrimes for (n = 1; n < argc ; n++) 4311590Srgrimes if (index(argv[n], ':') == 0) { 4321590Srgrimes getusage(argv[0]); 4331590Srgrimes return; 4341590Srgrimes } 4351590Srgrimes } 4361590Srgrimes for (n = 1; n < argc ; n++) { 4371590Srgrimes src = index(argv[n], ':'); 4381590Srgrimes if (src == NULL) 4391590Srgrimes src = argv[n]; 4401590Srgrimes else { 4411590Srgrimes struct hostent *hp; 4421590Srgrimes 4431590Srgrimes *src++ = 0; 4441590Srgrimes hp = gethostbyname(argv[n]); 4451590Srgrimes if (hp == NULL) { 4461590Srgrimes fprintf(stderr, "tftp: %s: ", argv[n]); 4471590Srgrimes herror((char *)NULL); 4481590Srgrimes continue; 4491590Srgrimes } 4501590Srgrimes bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr, 4511590Srgrimes hp->h_length); 4521590Srgrimes peeraddr.sin_family = hp->h_addrtype; 4531590Srgrimes connected = 1; 4541590Srgrimes strcpy(hostname, hp->h_name); 4551590Srgrimes } 4561590Srgrimes if (argc < 4) { 4571590Srgrimes cp = argc == 3 ? argv[2] : tail(src); 4581590Srgrimes fd = creat(cp, 0644); 4591590Srgrimes if (fd < 0) { 4601590Srgrimes fprintf(stderr, "tftp: "); perror(cp); 4611590Srgrimes return; 4621590Srgrimes } 4631590Srgrimes if (verbose) 4641590Srgrimes printf("getting from %s:%s to %s [%s]\n", 4651590Srgrimes hostname, src, cp, mode); 4661590Srgrimes peeraddr.sin_port = port; 4671590Srgrimes recvfile(fd, src, mode); 4681590Srgrimes break; 4691590Srgrimes } 4701590Srgrimes cp = tail(src); /* new .. jdg */ 4711590Srgrimes fd = creat(cp, 0644); 4721590Srgrimes if (fd < 0) { 4731590Srgrimes fprintf(stderr, "tftp: "); perror(cp); 4741590Srgrimes continue; 4751590Srgrimes } 4761590Srgrimes if (verbose) 4771590Srgrimes printf("getting from %s:%s to %s [%s]\n", 4781590Srgrimes hostname, src, cp, mode); 4791590Srgrimes peeraddr.sin_port = port; 4801590Srgrimes recvfile(fd, src, mode); 4811590Srgrimes } 4821590Srgrimes} 4831590Srgrimes 4841590Srgrimesstatic void 4851590Srgrimesgetusage(s) 4861590Srgrimes char *s; 4871590Srgrimes{ 4881590Srgrimes printf("usage: %s host:file host:file ... file, or\n", s); 4891590Srgrimes printf(" %s file file ... file if connected\n", s); 4901590Srgrimes} 4911590Srgrimes 4921590Srgrimesint rexmtval = TIMEOUT; 4931590Srgrimes 4941590Srgrimesvoid 4951590Srgrimessetrexmt(argc, argv) 4961590Srgrimes int argc; 4971590Srgrimes char *argv[]; 4981590Srgrimes{ 4991590Srgrimes int t; 5001590Srgrimes 5011590Srgrimes if (argc < 2) { 5021590Srgrimes strcpy(line, "Rexmt-timeout "); 5031590Srgrimes printf("(value) "); 50413068Sjoerg fgets(&line[strlen(line)], sizeof line - strlen(line), stdin); 5051590Srgrimes makeargv(); 5061590Srgrimes argc = margc; 5071590Srgrimes argv = margv; 5081590Srgrimes } 5091590Srgrimes if (argc != 2) { 5101590Srgrimes printf("usage: %s value\n", argv[0]); 5111590Srgrimes return; 5121590Srgrimes } 5131590Srgrimes t = atoi(argv[1]); 5141590Srgrimes if (t < 0) 5151590Srgrimes printf("%s: bad value\n", argv[1]); 5161590Srgrimes else 5171590Srgrimes rexmtval = t; 5181590Srgrimes} 5191590Srgrimes 5201590Srgrimesint maxtimeout = 5 * TIMEOUT; 5211590Srgrimes 5221590Srgrimesvoid 5231590Srgrimessettimeout(argc, argv) 5241590Srgrimes int argc; 5251590Srgrimes char *argv[]; 5261590Srgrimes{ 5271590Srgrimes int t; 5281590Srgrimes 5291590Srgrimes if (argc < 2) { 5301590Srgrimes strcpy(line, "Maximum-timeout "); 5311590Srgrimes printf("(value) "); 53213068Sjoerg fgets(&line[strlen(line)], sizeof line - strlen(line), stdin); 5331590Srgrimes makeargv(); 5341590Srgrimes argc = margc; 5351590Srgrimes argv = margv; 5361590Srgrimes } 5371590Srgrimes if (argc != 2) { 5381590Srgrimes printf("usage: %s value\n", argv[0]); 5391590Srgrimes return; 5401590Srgrimes } 5411590Srgrimes t = atoi(argv[1]); 5421590Srgrimes if (t < 0) 5431590Srgrimes printf("%s: bad value\n", argv[1]); 5441590Srgrimes else 5451590Srgrimes maxtimeout = t; 5461590Srgrimes} 5471590Srgrimes 5481590Srgrimesvoid 5491590Srgrimesstatus(argc, argv) 5501590Srgrimes int argc; 5511590Srgrimes char *argv[]; 5521590Srgrimes{ 5531590Srgrimes if (connected) 5541590Srgrimes printf("Connected to %s.\n", hostname); 5551590Srgrimes else 5561590Srgrimes printf("Not connected.\n"); 5571590Srgrimes printf("Mode: %s Verbose: %s Tracing: %s\n", mode, 5581590Srgrimes verbose ? "on" : "off", trace ? "on" : "off"); 5591590Srgrimes printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n", 5601590Srgrimes rexmtval, maxtimeout); 5611590Srgrimes} 5621590Srgrimes 5631590Srgrimesvoid 5641590Srgrimesintr() 5651590Srgrimes{ 5661590Srgrimes 5671590Srgrimes signal(SIGALRM, SIG_IGN); 5681590Srgrimes alarm(0); 5691590Srgrimes longjmp(toplevel, -1); 5701590Srgrimes} 5711590Srgrimes 5721590Srgrimeschar * 5731590Srgrimestail(filename) 5741590Srgrimes char *filename; 5751590Srgrimes{ 5761590Srgrimes register char *s; 5778874Srgrimes 5781590Srgrimes while (*filename) { 5791590Srgrimes s = rindex(filename, '/'); 5801590Srgrimes if (s == NULL) 5811590Srgrimes break; 5821590Srgrimes if (s[1]) 5831590Srgrimes return (s + 1); 5841590Srgrimes *s = '\0'; 5851590Srgrimes } 5861590Srgrimes return (filename); 5871590Srgrimes} 5881590Srgrimes 5891590Srgrimes/* 5901590Srgrimes * Command parser. 5911590Srgrimes */ 5921590Srgrimesstatic __dead void 5931590Srgrimescommand() 5941590Srgrimes{ 5951590Srgrimes register struct cmd *c; 59613068Sjoerg char *cp; 5971590Srgrimes 5981590Srgrimes for (;;) { 5991590Srgrimes printf("%s> ", prompt); 60013068Sjoerg if (fgets(line, sizeof line , stdin) == 0) { 6011590Srgrimes if (feof(stdin)) { 6021590Srgrimes exit(0); 6031590Srgrimes } else { 6041590Srgrimes continue; 6051590Srgrimes } 6061590Srgrimes } 60713068Sjoerg if ((cp = strchr(line, '\n'))) 60813068Sjoerg *cp = '\0'; 6091590Srgrimes if (line[0] == 0) 6101590Srgrimes continue; 6111590Srgrimes makeargv(); 6121590Srgrimes if (margc == 0) 6131590Srgrimes continue; 6141590Srgrimes c = getcmd(margv[0]); 6151590Srgrimes if (c == (struct cmd *)-1) { 6161590Srgrimes printf("?Ambiguous command\n"); 6171590Srgrimes continue; 6181590Srgrimes } 6191590Srgrimes if (c == 0) { 6201590Srgrimes printf("?Invalid command\n"); 6211590Srgrimes continue; 6221590Srgrimes } 6231590Srgrimes (*c->handler)(margc, margv); 6241590Srgrimes } 6251590Srgrimes} 6261590Srgrimes 6271590Srgrimesstruct cmd * 6281590Srgrimesgetcmd(name) 6291590Srgrimes register char *name; 6301590Srgrimes{ 6311590Srgrimes register char *p, *q; 6321590Srgrimes register struct cmd *c, *found; 6331590Srgrimes register int nmatches, longest; 6341590Srgrimes 6351590Srgrimes longest = 0; 6361590Srgrimes nmatches = 0; 6371590Srgrimes found = 0; 6381590Srgrimes for (c = cmdtab; (p = c->name) != NULL; c++) { 6391590Srgrimes for (q = name; *q == *p++; q++) 6401590Srgrimes if (*q == 0) /* exact match? */ 6411590Srgrimes return (c); 6421590Srgrimes if (!*q) { /* the name was a prefix */ 6431590Srgrimes if (q - name > longest) { 6441590Srgrimes longest = q - name; 6451590Srgrimes nmatches = 1; 6461590Srgrimes found = c; 6471590Srgrimes } else if (q - name == longest) 6481590Srgrimes nmatches++; 6491590Srgrimes } 6501590Srgrimes } 6511590Srgrimes if (nmatches > 1) 6521590Srgrimes return ((struct cmd *)-1); 6531590Srgrimes return (found); 6541590Srgrimes} 6551590Srgrimes 6561590Srgrimes/* 6571590Srgrimes * Slice a string up into argc/argv. 6581590Srgrimes */ 6591590Srgrimesstatic void 6601590Srgrimesmakeargv() 6611590Srgrimes{ 6621590Srgrimes register char *cp; 6631590Srgrimes register char **argp = margv; 6641590Srgrimes 6651590Srgrimes margc = 0; 66613068Sjoerg if ((cp = strchr(line, '\n'))) 66713068Sjoerg *cp = '\0'; 6681590Srgrimes for (cp = line; *cp;) { 6691590Srgrimes while (isspace(*cp)) 6701590Srgrimes cp++; 6711590Srgrimes if (*cp == '\0') 6721590Srgrimes break; 6731590Srgrimes *argp++ = cp; 6741590Srgrimes margc += 1; 6751590Srgrimes while (*cp != '\0' && !isspace(*cp)) 6761590Srgrimes cp++; 6771590Srgrimes if (*cp == '\0') 6781590Srgrimes break; 6791590Srgrimes *cp++ = '\0'; 6801590Srgrimes } 6811590Srgrimes *argp++ = 0; 6821590Srgrimes} 6831590Srgrimes 6841590Srgrimesvoid 6851590Srgrimesquit(argc, argv) 6861590Srgrimes int argc; 6871590Srgrimes char *argv[]; 6881590Srgrimes{ 6891590Srgrimes 6901590Srgrimes exit(0); 6911590Srgrimes} 6921590Srgrimes 6931590Srgrimes/* 6941590Srgrimes * Help command. 6951590Srgrimes */ 6961590Srgrimesvoid 6971590Srgrimeshelp(argc, argv) 6981590Srgrimes int argc; 6991590Srgrimes char *argv[]; 7001590Srgrimes{ 7011590Srgrimes register struct cmd *c; 7021590Srgrimes 7031590Srgrimes if (argc == 1) { 7041590Srgrimes printf("Commands may be abbreviated. Commands are:\n\n"); 7051590Srgrimes for (c = cmdtab; c->name; c++) 7061590Srgrimes printf("%-*s\t%s\n", (int)HELPINDENT, c->name, c->help); 7071590Srgrimes return; 7081590Srgrimes } 7091590Srgrimes while (--argc > 0) { 7101590Srgrimes register char *arg; 7111590Srgrimes arg = *++argv; 7121590Srgrimes c = getcmd(arg); 7131590Srgrimes if (c == (struct cmd *)-1) 7141590Srgrimes printf("?Ambiguous help command %s\n", arg); 7151590Srgrimes else if (c == (struct cmd *)0) 7161590Srgrimes printf("?Invalid help command %s\n", arg); 7171590Srgrimes else 7181590Srgrimes printf("%s\n", c->help); 7191590Srgrimes } 7201590Srgrimes} 7211590Srgrimes 7221590Srgrimesvoid 7231590Srgrimessettrace(argc, argv) 7241590Srgrimes int argc; 7251590Srgrimes char **argv; 7261590Srgrimes{ 7271590Srgrimes trace = !trace; 7281590Srgrimes printf("Packet tracing %s.\n", trace ? "on" : "off"); 7291590Srgrimes} 7301590Srgrimes 7311590Srgrimesvoid 7321590Srgrimessetverbose(argc, argv) 7331590Srgrimes int argc; 7341590Srgrimes char **argv; 7351590Srgrimes{ 7361590Srgrimes verbose = !verbose; 7371590Srgrimes printf("Verbose mode %s.\n", verbose ? "on" : "off"); 7381590Srgrimes} 739