Commit dcc5f29f authored by Robert Sprowson's avatar Robert Sprowson
Browse files

Import of Tftp

From https://svnweb.freebsd.org/base/stable/4/usr.bin/tftp/ revision 57955.
parent 9b56720c
|
| Copyright (c) 2016, RISC OS Open Ltd
| All rights reserved.
|
| Redistribution and use in source and binary forms, with or without
| modification, are permitted provided that the following conditions are met:
| * Redistributions of source code must retain the above copyright
| notice, this list of conditions and the following disclaimer.
| * 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.
| * Neither the name of RISC OS Open Ltd 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
|
Dir <Obey$Dir>
amu_machine all THROWBACK=-throwback
|
| Copyright (c) 2016, RISC OS Open Ltd
| All rights reserved.
|
| Redistribution and use in source and binary forms, with or without
| modification, are permitted provided that the following conditions are met:
| * Redistributions of source code must retain the above copyright
| notice, this list of conditions and the following disclaimer.
| * 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.
| * Neither the name of RISC OS Open Ltd 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
|
Dir <Obey$Dir>
amu_machine clean
stripdepnd
\ No newline at end of file
#
# Copyright (c) 2016, RISC OS Open Ltd
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * 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.
# * Neither the name of RISC OS Open Ltd 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
#
# Makefile for Tftp
#
COMPONENT = Tftp
INSTTYPE = app
OBJS = main tftp tftpsubs
LIBS = ${NET5LIBS}
CINCLUDES = -ITCPIPLibs:,C:
CDEFINES = -DRISCOS_TWEAK -D__P(A)=A -Dlint
include CApp
C_WARNINGS = -wp
# Dynamic dependencies:
/*
* 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.
*/
#ifndef lint
static const char copyright[] =
"@(#) Copyright (c) 1983, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
/* Many bug fixes are from Jim Guyton <guyton@rand-unix> */
/*
* TFTP User Program -- Command Interface.
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifdef RISCOS_TWEAK
#include "unixlib.h"
#include "socklib.h"
extern int isspace(int); /* Avoid conflicting __P macro in <ctype.h> */
const char *__progname = "tftp";
#else
#include <ctype.h>
#endif
#include <err.h>
#include <netdb.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.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 __P((int, char **));
void help __P((int, char **));
void modecmd __P((int, char **));
void put __P((int, char **));
void quit __P((int, char **));
void setascii __P((int, char **));
void setbinary __P((int, char **));
void setpeer __P((int, char **));
void setrexmt __P((int, char **));
void settimeout __P((int, char **));
void settrace __P((int, char **));
void setverbose __P((int, char **));
void status __P((int, char **));
static void command __P((void)) __dead2;
static void getusage __P((char *));
static void makeargv __P((void));
static void putusage __P((char *));
static void settftpmode __P((char *));
#define HELPINDENT (sizeof("connect"))
struct cmd {
char *name;
char *help;
void (*handler) __P((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();
#ifdef RISCOS_TWEAK
static void tidyup(void)
{
if (f >= 0) {
/* Ensure socket closed on exit */
socketclose(f);
f = -1;
}
}
#endif
int
main(argc, argv)
int argc;
char *argv[];
{
struct sockaddr_in sin;
#ifdef RISCOS_TWEAK /* Ensure socket closed on exit */
f = -1;
atexit(tidyup);
#endif
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 *)&sin, sizeof(sin));
sin.sin_family = AF_INET;
if (bind(f, (struct sockaddr *)&sin, sizeof(sin)) < 0)
err(1, "bind");
strcpy(mode, "netascii");
signal(SIGINT, intr);
if (argc > 1) {
#ifdef RISCOS_TWEAK /* Add help */
if (strcmp(argv[1], "-help") == 0) {
printf("Usage: tftp [host]\n"
" trivial file transfer program\n");
exit(0);
}
#endif
if (setjmp(toplevel) != 0)
exit(0);
setpeer(argc, argv);
}
if (setjmp(toplevel) != 0)
(void)putchar('\n');
command();
}
char hostname[MAXHOSTNAMELEN];
void
setpeer(argc, argv)
int argc;
char *argv[];
{
struct hostent *host;
if (argc < 2) {
strcpy(line, "Connect ");
printf("(to) ");
fgets(&line[strlen(line)], sizeof line - strlen(line), stdin);
makeargv();
argc = margc;
argv = margv;
}
if (argc > 3) {
printf("usage: %s host-name [port]\n", argv[0]);
return;
}
host = gethostbyname(argv[1]);
if (host) {
peeraddr.sin_family = host->h_addrtype;
bcopy(host->h_addr, &peeraddr.sin_addr,
MIN(sizeof(peeraddr.sin_addr), host->h_length));
strncpy(hostname, host->h_name, sizeof(hostname));
} else {
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;
}
strncpy(hostname, argv[1], sizeof(hostname));
}
hostname[sizeof(hostname) - 1] = '\0';
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 }
};
void
modecmd(argc, argv)
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;
}
void
setbinary(argc, argv)
int argc;
char *argv[];
{
settftpmode("octet");
}
void
setascii(argc, argv)
int argc;
char *argv[];
{
settftpmode("netascii");
}
static void
settftpmode(newmode)
char *newmode;
{
strcpy(mode, newmode);
if (verbose)
printf("mode set to %s\n", mode);
}
/*
* Send file(s).
*/
void
put(argc, argv)
int argc;
char *argv[];
{
#ifdef RISCOS_TWEAK
FILE *fd;
#else
int fd;
#endif
register int n;
register char *cp, *targ;
if (argc < 2) {
strcpy(line, "send ");
printf("(file) ");
fgets(&line[strlen(line)], sizeof line - strlen(line), stdin);
makeargv();
argc = margc;
argv = margv;
}
if (argc < 2) {
putusage(argv[0]);
return;
}
targ = argv[argc - 1];
if (index(argv[argc - 1], ':')) {
char *cp;
struct hostent *hp;
for (n = 1; n < argc - 1; n++)
if (index(argv[n], ':')) {
putusage(argv[0]);
return;
}
cp = argv[argc - 1];
targ = index(cp, ':');
*targ++ = 0;
hp = gethostbyname(cp);
if (hp == NULL) {
fprintf(stderr, "tftp: %s: ", cp);
herror((char *)NULL);
return;
}
bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr,
MIN(sizeof(peeraddr.sin_addr), hp->h_length));
peeraddr.sin_family = hp->h_addrtype;
connected = 1;
strncpy(hostname, hp->h_name, sizeof(hostname));
hostname[sizeof(hostname) - 1] = '\0';
}
if (!connected) {
printf("No target machine specified.\n");
return;
}
if (argc < 4) {
cp = argc == 2 ? tail(targ) : argv[1];
#ifdef RISCOS_TWEAK /* Alternate open method */
fd = fopen(cp, "rb");
if (fd == NULL) {
/* warn() in unixlib uses _inet_err, which fopen doesn't touch */
fprintf(stderr, "Could not open %s for reading\n", cp);
#else
fd = open(cp, O_RDONLY);
if (fd < 0) {
warn("%s", cp);
#endif
return;
}
if (verbose)
printf("putting %s to %s:%s [%s]\n",
cp, hostname, targ, mode);
peeraddr.sin_port = port;
xmitfile(fd, targ, mode);
return;
}
/* this assumes the target is a directory */
/* on a remote unix system. hmmmm. */
cp = index(targ, '\0');
*cp++ = '/';
for (n = 1; n < argc - 1; n++) {
strcpy(cp, tail(argv[n]));
#ifdef RISCOS_TWEAK /* Alternate open method */
fd = fopen(argv[n], "rb");
if (fd == NULL) {
/* warn() in unixlib uses _inet_err, which fopen doesn't touch */
fprintf(stderr, "Could not open %s for reading\n", argv[n]);
#else
fd = open(argv[n], O_RDONLY);
if (fd < 0) {
warn("%s", argv[n]);
#endif
continue;
}
if (verbose)
printf("putting %s to %s:%s [%s]\n",
argv[n], hostname, targ, mode);
peeraddr.sin_port = port;
xmitfile(fd, targ, mode);
}
}
static void
putusage(s)
char *s;
{
printf("usage: %s file ... host:target, or\n", s);
printf(" %s file ... target (when already connected)\n", s);
}
/*
* Receive file(s).
*/
void
get(argc, argv)
int argc;
char *argv[];
{
#ifdef RISCOS_TWEAK
FILE *fd;
#else
int fd;
#endif
register int n;
register char *cp;
char *src;
if (argc < 2) {
strcpy(line, "get ");
printf("(files) ");
fgets(&line[strlen(line)], sizeof line - strlen(line), stdin);
makeargv();
argc = margc;
argv = margv;
}
if (argc < 2) {
getusage(argv[0]);
return;
}
if (!connected) {
for (n = 1; n < argc ; n++)
if (index(argv[n], ':') == 0) {
getusage(argv[0]);
return;
}
}
for (n = 1; n < argc ; n++) {
src = index(argv[n], ':');
if (src == NULL)
src = argv[n];
else {
struct hostent *hp;
*src++ = 0;
hp = gethostbyname(argv[n]);
if (hp == NULL) {
fprintf(stderr, "tftp: %s: ", argv[n]);
herror((char *)NULL);
continue;
}
bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr,
MIN(sizeof(peeraddr.sin_addr), hp->h_length));
peeraddr.sin_family = hp->h_addrtype;
connected = 1;
strncpy(hostname, hp->h_name, sizeof(hostname));
hostname[sizeof(hostname) - 1] = '\0';
}
if (argc < 4) {
cp = argc == 3 ? argv[2] : tail(src);
#ifdef RISCOS_TWEAK /* Alternate creat method */
fd = fopen(cp, "wb");
if (fd == NULL) {
/* warn() in unixlib uses _inet_err, which fopen doesn't touch */
fprintf(stderr, "Could not open %s for writing\n", cp);
#else
fd = creat(cp, 0644);
if (fd < 0) {
warn("%s", cp);
#endif