📄 main.c
字号:
/* $OpenBSD: main.c,v 1.4 1997/01/17 07:13:30 millert Exp $ *//* $NetBSD: main.c,v 1.6 1995/05/21 16:54:10 mycroft Exp $ *//* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "tftpsubs.h"#ifndef lintstatic const char *copyright UNUSED ="@(#) Copyright (c) 1983, 1993\n\ The Regents of the University of California. All rights reserved.\n";/* static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; *//* static char rcsid[] = "$OpenBSD: main.c,v 1.4 1997/01/17 07:13:30 millert Exp $"; */static const char *rcsid UNUSED = "tftp-hpa $Id: main.c,v 1.21 2004/01/08 20:47:00 hpa Exp $";#endif /* not lint *//* Many bug fixes are from Jim Guyton <guyton@rand-unix> *//* * TFTP User Program -- Command Interface. */#include <sys/file.h>#include <ctype.h>#include <netdb.h>#ifdef WITH_READLINE#include <readline/readline.h>#ifdef HAVE_READLINE_HISTORY_H#include <readline/history.h>#endif#endif#include "extern.h"#define TIMEOUT 5 /* secs between rexmt's */#define LBUFLEN 200 /* size of input buffer */struct modes { const char *m_name; const char *m_mode; int m_openflags;};static const struct modes modes[] = { { "netascii", "netascii", O_TEXT }, { "ascii", "netascii", O_TEXT }, { "octet", "octet", O_BINARY }, { "binary", "octet", O_BINARY }, { "image", "octet", O_BINARY }, { 0, 0, 0 }};#define MODE_OCTET (&modes[2])#define MODE_NETASCII (&modes[0])#define MODE_DEFAULT MODE_NETASCIIstruct sockaddr_in peeraddr;int f;u_short port;int trace;int verbose;int connected;const struct modes *mode;#ifdef WITH_READLINEchar *line = NULL;#elsechar line[LBUFLEN];#endifint margc;char *margv[20];const char *prompt = "tftp> ";sigjmp_buf toplevel;void intr(int);struct servent *sp;void get (int, char **);void help (int, char **);void modecmd (int, char **);void put (int, char **);void quit (int, char **);void setascii (int, char **);void setbinary (int, char **);void setpeer (int, char **);void setrexmt (int, char **);void settimeout (int, char **);void settrace (int, char **);void setverbose (int, char **);void status (int, char **);static void command (void);static void getusage (char *);static void makeargv (void);static void putusage (char *);static void settftpmode (const struct modes *);#define HELPINDENT (sizeof("connect"))struct cmd { const char *name; const char *help; void (*handler) (int, char **);};struct cmd cmdtab[] = { { "connect", "connect to remote tftp", setpeer }, { "mode", "set file transfer mode", modecmd }, { "put", "send file", put }, { "get", "receive file", get }, { "quit", "exit tftp", quit }, { "verbose", "toggle verbose mode", setverbose }, { "trace", "toggle packet tracing", settrace }, { "status", "show current status", status }, { "binary", "set mode to octet", setbinary }, { "ascii", "set mode to netascii", setascii }, { "rexmt", "set per-packet transmission timeout", setrexmt }, { "timeout", "set total retransmission timeout", settimeout }, { "?", "print help information", help }, { "help", "print help information", help }, { 0, 0, 0 }};struct cmd *getcmd(char *);char *tail(char *);char *xstrdup(const char *);const char *program;static inline void usage(int errcode){ fprintf(stderr, "Usage: %s [-v][-m mode] [host [port]] [-c command]\n", program); exit(errcode);}intmain(int argc, char *argv[]){ struct sockaddr_in s_in; int arg; static int pargc, peerargc; static int iscmd = 0; char **pargv; const char *optx; char *peerargv[3]; program = argv[0]; mode = MODE_DEFAULT; peerargv[0] = argv[0]; peerargc = 1; for ( arg = 1 ; !iscmd && arg < argc ; arg++ ) { if ( argv[arg][0] == '-' ) { for ( optx = &argv[arg][1] ; *optx ; optx++ ) { switch ( *optx ) { case 'v': verbose = 1; break; case 'V': /* Print version and configuration to stdout and exit */ printf("%s\n", TFTP_CONFIG_STR); exit(0); case 'm': if ( ++arg >= argc ) usage(EX_USAGE); { const struct modes *p; for ( p = modes ; p->m_name ; p++ ) { if (!strcmp(argv[arg], p->m_name)) break; } if (p->m_name) { settftpmode(p); } else { fprintf(stderr, "%s: invalid mode: %s\n", argv[0], argv[arg]); exit(EX_USAGE); } } break; case 'c': iscmd = 1; break; case 'h': default: usage(*optx == 'h' ? 0 : EX_USAGE); } } } else { if ( peerargc >= 3 ) usage(EX_USAGE); peerargv[peerargc++] = argv[arg]; } } pargv = argv + arg; pargc = argc - arg; sp = getservbyname("tftp", "udp"); if (sp == 0) { /* Use canned values */ if (verbose) fprintf(stderr, "tftp: tftp/udp: unknown service, faking it...\n"); sp = xmalloc(sizeof(struct servent)); sp->s_name = (char *)"tftp"; sp->s_aliases = NULL; sp->s_port = htons(IPPORT_TFTP); sp->s_proto = (char *)"udp"; } port = sp->s_port; /* Default port */ f = socket(AF_INET, SOCK_DGRAM, 0); if (f < 0) { perror("tftp: socket"); exit(EX_OSERR); } bzero((char *)&s_in, sizeof (s_in)); s_in.sin_family = AF_INET; if (bind(f, (struct sockaddr *)&s_in, sizeof (s_in)) < 0) { perror("tftp: bind"); exit(EX_OSERR); } bsd_signal(SIGINT, intr); if ( peerargc ) { /* Set peer */ if (sigsetjmp(toplevel,1) != 0) exit(EX_NOHOST); setpeer(peerargc, peerargv); } if ( iscmd && pargc ) { /* -c specified; execute command and exit */ struct cmd *c; if (sigsetjmp(toplevel,1) != 0) exit(EX_UNAVAILABLE); c = getcmd(pargv[0]); if ( c == (struct cmd *)-1 || c == (struct cmd *)0 ) { fprintf(stderr, "%s: invalid command: %s\n", argv[0], pargv[1]); exit(EX_USAGE); } (*c->handler)(pargc, pargv); exit(0); } if (sigsetjmp(toplevel,1) != 0) (void)putchar('\n'); #ifdef WITH_READLINE#ifdef HAVE_READLINE_HISTORY_H using_history();#endif#endif command(); return 0; /* Never reached */}char *hostname;/* Called when a command is incomplete; modifies the global variable "line" */static voidgetmoreargs(const char *partial, const char *mprompt){#ifdef WITH_READLINE char *eline; int len, elen; len = strlen(partial); eline = readline(mprompt); if (!eline) exit(0); /* EOF */ elen = strlen(eline); if (line) free(line); line = xmalloc(len+elen+1); strcpy(line, partial); strcpy(line+len, eline); free(eline);#ifdef HAVE_READLINE_HISTORY_H add_history(line);#endif#else int len = strlen(partial); strcpy(line, partial); fputs(mprompt, stdout); if ( fgets(line+len, LBUFLEN-len, stdin) == 0 ) if ( feof(stdin) ) exit(0); /* EOF */#endif}voidsetpeer(int argc, char *argv[]){ struct hostent *host; if (argc < 2) { getmoreargs("connect ", "(to) "); makeargv(); argc = margc; argv = margv; } if ((argc < 2) || (argc > 3)) { printf("usage: %s host-name [port]\n", argv[0]); return; } host = gethostbyname(argv[1]); if (host == 0) { connected = 0; printf("%s: unknown host\n", argv[1]); return; } peeraddr.sin_family = host->h_addrtype; bcopy(host->h_addr, &peeraddr.sin_addr, host->h_length); hostname = xstrdup(host->h_name); port = sp->s_port; if (argc == 3) { struct servent *usp; usp = getservbyname(argv[2], "udp"); if ( usp ) { port = usp->s_port; } else { unsigned long myport; char *ep; myport = strtoul(argv[2], &ep, 10); if (*ep || myport > 65535UL) { printf("%s: bad port number\n", argv[2]); connected = 0; return; } port = htons((u_short)myport); } } if (verbose) { printf("Connected to %s (%s), port %u\n", hostname, inet_ntoa(peeraddr.sin_addr), (unsigned int)ntohs(port)); } connected = 1;}voidmodecmd(int argc, char *argv[]){ const struct modes *p; const char *sep; if (argc < 2) { printf("Using %s mode to transfer files.\n", mode->m_mode); return; } if (argc == 2) { for (p = modes; p->m_name; p++) if (strcmp(argv[1], p->m_name) == 0) break; if (p->m_name) { settftpmode(p); return; } printf("%s: unknown mode\n", argv[1]); /* drop through and print usage message */ } printf("usage: %s [", argv[0]); sep = " "; for (p = modes; p->m_name; p++) { printf("%s%s", sep, p->m_name); if (*sep == ' ') sep = " | "; } printf(" ]\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -