diff options
Diffstat (limited to 'usr.bin/tftp/main.c')
-rw-r--r-- | usr.bin/tftp/main.c | 151 |
1 files changed, 89 insertions, 62 deletions
diff --git a/usr.bin/tftp/main.c b/usr.bin/tftp/main.c index dec04278a25..a41b14e8e7c 100644 --- a/usr.bin/tftp/main.c +++ b/usr.bin/tftp/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.23 2006/01/23 17:29:22 millert Exp $ */ +/* $OpenBSD: main.c,v 1.24 2006/05/08 13:02:51 claudio Exp $ */ /* $NetBSD: main.c,v 1.6 1995/05/21 16:54:10 mycroft Exp $ */ /* @@ -40,7 +40,7 @@ static const char copyright[] = #if 0 static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; #endif -static const char rcsid[] = "$OpenBSD: main.c,v 1.23 2006/01/23 17:29:22 millert Exp $"; +static const char rcsid[] = "$OpenBSD: main.c,v 1.24 2006/05/08 13:02:51 claudio Exp $"; #endif /* not lint */ /* Many bug fixes are from Jim Guyton <guyton@rand-unix> */ @@ -48,34 +48,35 @@ static const char rcsid[] = "$OpenBSD: main.c,v 1.23 2006/01/23 17:29:22 millert /* * TFTP User Program -- Command Interface. */ + #include <sys/param.h> #include <sys/socket.h> #include <sys/file.h> #include <netinet/in.h> - #include <arpa/inet.h> #include <ctype.h> #include <errno.h> #include <netdb.h> -#include <setjmp.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <err.h> +#include <poll.h> #include "extern.h" #define TIMEOUT 5 /* secs between rexmt's */ #define LBUFLEN 200 /* size of input buffer */ #define MAXARGV 20 +#define HELPINDENT (sizeof("connect")) struct sockaddr_in peeraddr; int f; -short port; +short port; int trace; int verbose; int connected; @@ -84,9 +85,14 @@ char line[LBUFLEN]; int margc; char *margv[MAXARGV+1]; char *prompt = "tftp"; -jmp_buf toplevel; void intr(int); struct servent *sp; +int rexmtval = TIMEOUT; +int maxtimeout = 5 * TIMEOUT; +char hostname[MAXHOSTNAMELEN]; +FILE *file = NULL; + +volatile sig_atomic_t intrflag = 0; void get(int, char **); void help(int, char **); @@ -101,6 +107,7 @@ void settimeout(int, char **); void settrace(int, char **); void setverbose(int, char **); void status(int, char **); +int readcmd(char *, int, FILE *); static __dead void command(void); @@ -109,8 +116,6 @@ static int makeargv(void); static void putusage(char *); static void settftpmode(char *); -#define HELPINDENT (sizeof("connect")) - struct cmd { char *name; char *help; @@ -128,8 +133,8 @@ char mhelp[] = "set file transfer mode"; char sthelp[] = "show current status"; char xhelp[] = "set per-packet retransmission timeout"; char ihelp[] = "set total retransmission timeout"; -char ashelp[] = "set mode to netascii"; -char bnhelp[] = "set mode to octet"; +char ashelp[] = "set mode to netascii"; +char bnhelp[] = "set mode to octet"; struct cmd cmdtab[] = { { "connect", chelp, setpeer }, @@ -144,10 +149,24 @@ struct cmd cmdtab[] = { { "ascii", ashelp, setascii }, { "rexmt", xhelp, setrexmt }, { "timeout", ihelp, settimeout }, + { "help", hhelp, help }, { "?", hhelp, help }, { NULL, NULL, NULL } }; +struct modes { + char *m_name; + char *m_mode; +} modes[] = { + { "ascii", "netascii" }, + { "netascii", "netascii" }, + { "binary", "octet" }, + { "image", "octet" }, + { "octet", "octet" }, +/* { "mail", "mail" }, */ + { NULL, NULL } +}; + struct cmd *getcmd(char *); char *tail(char *); @@ -156,31 +175,34 @@ main(int argc, char *argv[]) { struct sockaddr_in s_in; + /* socket, bind */ sp = getservbyname("tftp", "udp"); if (sp == 0) errx(1, "udp/tftp: unknown service"); f = socket(AF_INET, SOCK_DGRAM, 0); if (f < 0) err(3, "socket"); - bzero((char *)&s_in, sizeof (s_in)); + bzero((char *)&s_in, sizeof(s_in)); s_in.sin_family = AF_INET; - if (bind(f, (struct sockaddr *)&s_in, sizeof (s_in)) < 0) + if (bind(f, (struct sockaddr *)&s_in, sizeof(s_in)) < 0) err(1, "bind"); - strlcpy(mode, "netascii", sizeof mode); - signal(SIGINT, intr); - if (argc > 1) { - if (setjmp(toplevel) != 0) - exit(0); + + /* set default transfer mode */ + strlcpy(mode, "netascii", sizeof(mode)); + + /* set peer if given */ + if (argc > 1) setpeer(argc, argv); - } - if (setjmp(toplevel) != 0) - (void)putchar('\n'); + + /* catch SIGINT */ + signal(SIGINT, intr); + + /* command prompt */ command(); + return (0); } -char hostname[MAXHOSTNAMELEN]; - void setpeer(int argc, char *argv[]) { @@ -189,7 +211,7 @@ setpeer(int argc, char *argv[]) if (argc < 2) { strlcpy(line, "Connect ", sizeof line); printf("(to) "); - fgets(&line[strlen(line)], LBUFLEN-strlen(line), stdin); + readcmd(&line[strlen(line)], LBUFLEN-strlen(line), stdin); if (makeargv()) return; argc = margc; @@ -227,19 +249,6 @@ setpeer(int argc, char *argv[]) connected = 1; } -struct modes { - char *m_name; - char *m_mode; -} modes[] = { - { "ascii", "netascii" }, - { "netascii", "netascii" }, - { "binary", "octet" }, - { "image", "octet" }, - { "octet", "octet" }, -/* { "mail", "mail" }, */ - { NULL, NULL } -}; - void modecmd(int argc, char *argv[]) { @@ -276,14 +285,12 @@ modecmd(int argc, char *argv[]) void setbinary(int argc, char *argv[]) { - settftpmode("octet"); } void setascii(int argc, char *argv[]) { - settftpmode("netascii"); } @@ -295,7 +302,6 @@ settftpmode(char *newmode) printf("mode set to %s\n", mode); } - /* * Send file(s). */ @@ -309,7 +315,7 @@ put(int argc, char *argv[]) if (argc < 2) { strlcpy(line, "send ", sizeof line); printf("(file) "); - fgets(&line[strlen(line)], LBUFLEN-strlen(line), stdin); + readcmd(&line[strlen(line)], LBUFLEN - strlen(line), stdin); if (makeargv()) return; argc = margc; @@ -362,8 +368,10 @@ put(int argc, char *argv[]) return; } - /* this assumes the target is a directory */ - /* on a remote unix system. hmmmm. */ + /* + * this assumes the target is a directory on + * on a remote unix system. hmmmm. + */ for (n = 1; n < argc - 1; n++) { if (asprintf(&cp, "%s/%s", targ, tail(argv[n])) == -1) err(1, "asprintf"); @@ -386,7 +394,8 @@ static void putusage(char *s) { printf("usage: %s file [[host:]remotename]\n", s); - printf(" %s file1 file2 ... fileN [[host:]remote-directory]\n", s); + printf(" %s file1 file2 ... fileN [[host:]remote-directory]\n", + s); } /* @@ -403,7 +412,7 @@ get(int argc, char *argv[]) if (argc < 2) { strlcpy(line, "get ", sizeof line); printf("(files) "); - fgets(&line[strlen(line)], LBUFLEN-strlen(line), stdin); + readcmd(&line[strlen(line)], LBUFLEN-strlen(line), stdin); if (makeargv()) return; argc = margc; @@ -474,8 +483,6 @@ getusage(char *s) printf(" %s [host1:]file1 [host2:]file2 ... [hostN:]fileN\n", s); } -int rexmtval = TIMEOUT; - void setrexmt(int argc, char *argv[]) { @@ -484,7 +491,7 @@ setrexmt(int argc, char *argv[]) if (argc < 2) { strlcpy(line, "Rexmt-timeout ", sizeof line); printf("(value) "); - fgets(&line[strlen(line)], LBUFLEN-strlen(line), stdin); + readcmd(&line[strlen(line)], LBUFLEN-strlen(line), stdin); if (makeargv()) return; argc = margc; @@ -501,8 +508,6 @@ setrexmt(int argc, char *argv[]) rexmtval = t; } -int maxtimeout = 5 * TIMEOUT; - void settimeout(int argc, char *argv[]) { @@ -511,7 +516,7 @@ settimeout(int argc, char *argv[]) if (argc < 2) { strlcpy(line, "Maximum-timeout ", sizeof line); printf("(value) "); - fgets(&line[strlen(line)], LBUFLEN-strlen(line), stdin); + readcmd(&line[strlen(line)], LBUFLEN-strlen(line), stdin); if (makeargv()) return; argc = margc; @@ -544,10 +549,7 @@ status(int argc, char *argv[]) void intr(int signo) { - - signal(SIGALRM, SIG_IGN); - alarm(0); - longjmp(toplevel, -1); + intrflag = 1; } char * @@ -576,13 +578,8 @@ command(void) for (;;) { printf("%s> ", prompt); - if (fgets(line, LBUFLEN, stdin) == 0) { - if (feof(stdin)) { - exit(0); - } else { - continue; - } - } + if (readcmd(line, LBUFLEN, stdin) < 1) + continue; if ((line[0] == 0) || (line[0] == '\n')) continue; if (makeargv()) @@ -612,6 +609,7 @@ getcmd(char *name) longest = 0; nmatches = 0; found = 0; + intrflag = 0; for (c = cmdtab; (p = c->name) != NULL; c++) { for (q = name; *q == *p++; q++) if (*q == 0) /* exact match? */ @@ -666,7 +664,6 @@ makeargv(void) void quit(int argc, char *argv[]) { - exit(0); } @@ -710,3 +707,33 @@ setverbose(int argc, char *argv[]) verbose = !verbose; printf("Verbose mode %s.\n", verbose ? "on" : "off"); } + +int +readcmd(char *input, int len, FILE *stream) +{ + int nfds; + struct pollfd pfd[1]; + + fflush(stdout); + + pfd[0].fd = 0; + pfd[0].events = POLLIN; + nfds = poll(pfd, 1, INFTIM); + if (nfds == -1) { + if (intrflag) { + intrflag = 0; + putchar('\n'); + return (0); + } + exit(1); + } + + if (fgets(input, len, stream) == NULL) { + if (feof(stdin)) + exit(0); + else + return (-1); + } + + return (1); +} |