📄 main.c
字号:
/* * 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. * 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. */#ifndef lintstatic char copyright[] = "@(#) Copyright (c) 1983, 1993\n\ The Regents of the University of California. All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93";#endif /* not lint *//* Many bug fixes are from Jim Guyton <guyton@rand-unix> *//* * TFTP User Program -- Command Interface. */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <sys/types.h>#include <sys/socket.h>#include <sys/file.h>#include <netinet/in.h>#include <arpa/inet.h>#include <ctype.h>#include <errno.h>#include <fcntl.h>#include <netdb.h>#include <setjmp.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include "xalloc.h"#include "extern.h"#define TIMEOUT 5 /* secs between rexmt's */struct sockaddr_in peeraddr;int f;short port;int trace;int verbose;int connected;char mode[32];char line[200];int margc;char *margv[20];char *prompt = "tftp";jmp_buf toplevel;void intr ();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 (char *);#define HELPINDENT (sizeof("connect"))struct cmd{ char *name; char *help; void (*handler) (int, char **);};char vhelp[] = "toggle verbose mode";char thelp[] = "toggle packet tracing";char chelp[] = "connect to remote tftp";char qhelp[] = "exit tftp";char hhelp[] = "print help information";char shelp[] = "send file";char rhelp[] = "receive file";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";struct cmd cmdtab[] = { {"connect", chelp, setpeer}, {"mode", mhelp, modecmd}, {"put", shelp, put}, {"get", rhelp, get}, {"quit", qhelp, quit}, {"verbose", vhelp, setverbose}, {"trace", thelp, settrace}, {"status", sthelp, status}, {"binary", bnhelp, setbinary}, {"ascii", ashelp, setascii}, {"rexmt", xhelp, setrexmt}, {"timeout", ihelp, settimeout}, {"?", hhelp, help}, {0}};struct cmd *getcmd ();char *tail ();char *program_name;intmain (int argc, char *argv[]){ struct sockaddr_in sin; program_name = argv[0]; sp = getservbyname ("tftp", "udp"); if (sp == 0) { fprintf (stderr, "tftp: udp/tftp: unknown service\n"); exit (1); } f = socket (AF_INET, SOCK_DGRAM, 0); if (f < 0) { perror ("tftp: socket"); exit (3); } memset (&sin, 0, sizeof (sin)); sin.sin_family = AF_INET; if (bind (f, (struct sockaddr *) &sin, sizeof (sin)) < 0) { perror ("tftp: bind"); exit (1); } strcpy (mode, "netascii"); signal (SIGINT, intr); if (argc > 1) { if (setjmp (toplevel) != 0) exit (0); setpeer (argc, argv); } if (setjmp (toplevel) != 0) putchar ('\n'); command ();}char *hostname;#define RESOLVE_OK 0#define RESOLVE_FAIL -1#define RESOLVE_NOT_RESOLVED 1 /* Resolve NAME. Fill in peeraddr, hostname and set connected on success. Return value: RESOLVE_OK success RESOLVE_FAIL error RESOLVE_NOT_RESOLVED name is not resolved and ALLOW_NULL is true */static intresolve_name (char *name, int allow_null){ struct hostent *hp = gethostbyname (name); if (hp == NULL) { if (allow_null) return RESOLVE_NOT_RESOLVED; fprintf (stderr, "tftp: %s: ", name); herror ((char *) NULL); return RESOLVE_FAIL; } else if (hp->h_length != sizeof peeraddr.sin_addr) { fprintf (stderr, "tftp: resolving %s returns unexpected length", name); return RESOLVE_FAIL; } memcpy (&peeraddr.sin_addr, hp->h_addr, hp->h_length); peeraddr.sin_family = hp->h_addrtype; connected = 1; free (hostname); hostname = xstrdup (hp->h_name); return RESOLVE_OK;}/* Prompt for more arguments from the user with PROMPT, putting the results into ARGC & ARGV, with an initial argument of ARG0. Global variables LINE, MARGC, and MARGV are changed. */static voidget_args (char *arg0, char *prompt, int *argc, char ***argv){ size_t arg0_len = strlen (arg0); strcpy (line, arg0); strcat (line, " "); printf ("%s", prompt); fgets (line + arg0_len + 1, sizeof line - arg0_len - 1, stdin); makeargv (); *argc = margc; *argv = margv;}voidsetpeer (int argc, char *argv[]){ if (argc < 2) get_args ("Connect", "(to) ", &argc, &argv); if (argc < 2 || argc > 3) { printf ("usage: %s host-name [port]\n", argv[0]); return; } switch (resolve_name (argv[1], 1)) { case RESOLVE_OK: break; case RESOLVE_FAIL: return; case RESOLVE_NOT_RESOLVED: peeraddr.sin_family = AF_INET; peeraddr.sin_addr.s_addr = inet_addr (argv[1]); if (peeraddr.sin_addr.s_addr == -1) { connected = 0; printf ("%s: unknown host\n", argv[1]); return; } hostname = xstrdup (argv[1]); } port = sp->s_port; if (argc == 3) { port = atoi (argv[2]); if (port < 0) { printf ("%s: bad port number\n", argv[2]); connected = 0; return; } port = htons (port); } connected = 1;}struct modes{ char *m_name; char *m_mode;}modes[] ={ {"ascii", "netascii"}, {"netascii", "netascii"}, {"binary", "octet"}, {"image", "octet"}, {"octet", "octet"},/* { "mail", "mail" }, */ {0, 0}};voidmodecmd (int argc, char *argv[]){ register struct modes *p; char *sep; if (argc < 2) { printf ("Using %s mode to transfer files.\n", 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->m_mode); 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"); return;}voidsetbinary (int argc, char *argv[]){ settftpmode ("octet");}voidsetascii (int argc, char *argv[]){ settftpmode ("netascii");}static voidsettftpmode (char *newmode){ strcpy (mode, newmode); if (verbose) printf ("mode set to %s\n", mode);}/* * Send file(s). */voidput (int argc, char *argv[]){ int fd; register int n; register char *cp, *targ; if (argc < 2) get_args ("send", "(file) ", &argc, &argv); if (argc < 2)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -