summaryrefslogtreecommitdiffstats
path: root/contrib/tftp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tftp')
-rw-r--r--contrib/tftp/Makefile56
-rw-r--r--contrib/tftp/README28
-rw-r--r--contrib/tftp/arpa/tftp.h80
-rw-r--r--contrib/tftp/main.c684
-rw-r--r--contrib/tftp/tftp.1159
-rw-r--r--contrib/tftp/tftp.c536
-rw-r--r--contrib/tftp/tftpd.875
-rw-r--r--contrib/tftp/tftpd.c742
-rw-r--r--contrib/tftp/tftpsubs.c260
9 files changed, 0 insertions, 2620 deletions
diff --git a/contrib/tftp/Makefile b/contrib/tftp/Makefile
deleted file mode 100644
index bd427cd0..00000000
--- a/contrib/tftp/Makefile
+++ /dev/null
@@ -1,56 +0,0 @@
-#
-# Copyright (c) 1987 Regents of the University of California.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms are permitted
-# provided that the above copyright notice and this paragraph are
-# duplicated in all such forms and that any documentation,
-# advertising materials, and other materials related to such
-# distribution and use acknowledge that the software was developed
-# by the University of California, Berkeley. The name of the
-# University may not be used to endorse or promote products derived
-# from this software without specific prior written permission.
-# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
-# WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-#
-# @(#)Makefile 5.8 (Berkeley) 9/20/88
-#
-# We override /usr/include/arpa/tftp.h with our own because
-# we want tu_block to be unsigned short, not short as on most platforms
-#
-CFLAGS= -I. -O2 -Dsin=sin_x
-SRCS= main.c tftp.c tftpsubs.c tftpd.c
-OBJS= main.o tftp.o tftpsubs.o
-DOBJS= tftpd.o tftpsubs.o
-CC= gcc
-LIBS= # -linet
-
-all: tftp tftpd
-
-tftp: ${OBJS}
- ${CC} -o $@ ${CFLAGS} ${OBJS} # -linet
-
-tftpd: ${DOBJS}
- ${CC} -o $@ ${CFLAGS} ${DOBJS} ${LIBS}
-
-clean:
- rm -f ${OBJS} ${DOBJS} core tftp tftpd
-
-cleandir: clean
- rm -f tags .depend
-
-depend: ${SRCS}
- mkdep ${CFLAGS} ${SRCS}
-
-install:
- install -s -o root -g root -m 755 tftp /usr/bin/tftp
- install -c -o root -g root -m 444 tftp.1 /usr/man/man1
- install -s -o root -g root -m 755 tftpd /usr/sbin/in.tftpd
- install -c -o root -g root -m 444 tftpd.8 /usr/man/man8
-
-lint: ${SRCS}
- lint ${CFLAGS} ${SRCS}
-
-tags: ${SRCS}
- ctags ${SRCS}
diff --git a/contrib/tftp/README b/contrib/tftp/README
deleted file mode 100644
index e4957202..00000000
--- a/contrib/tftp/README
+++ /dev/null
@@ -1,28 +0,0 @@
-This is a copy of the TFTP client as available from
-ftp://sunsite.unc.edu/pub/linux/system/Network/file-transfer; I
-modified the code, so that it understands RFC1782 and RFC1783
-extensions to the TFTP protocol. This allows for negotating an
-extended transfer block size of up to 1432 bytes (as oppossed to the
-standard 512 bytes). On busy networks, this will result in
-considerably improved throughput and less load on the network.
-
-For further information and for licensing conditions, please have a
-look at the header of the source files.
-
-Markus Gutschke <gutschk@math.uni-muenster.de>
-
-This is a copy of the TFTP server as available from
-ftp://sunsite.unc.edu/pub/linux/system/Network/file-transfer; I
-modified the code, so that it understands RFC1782 and RFC1783
-extensions to the TFTP protocol. This allows for negotating an
-extended transfer block size of up to 1432 bytes (as oppossed to the
-standard 512 bytes). On busy networks, this will result in
-considerably improved throughput and less load on the network.
-
-I also added two command line options for changing the root directory
-and for enabling debugging output.
-
-For further information and for licensing conditions, please have a
-look at the header of the source files.
-
-Markus Gutschke <gutschk@math.uni-muenster.de>
diff --git a/contrib/tftp/arpa/tftp.h b/contrib/tftp/arpa/tftp.h
deleted file mode 100644
index 0904407c..00000000
--- a/contrib/tftp/arpa/tftp.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.
- *
- * @(#)tftp.h 8.1 (Berkeley) 6/2/93
- */
-
-#ifndef _ARPA_TFTP_H
-#define _ARPA_TFTP_H 1
-
-/*
- * Trivial File Transfer Protocol (IEN-133)
- */
-#define SEGSIZE 512 /* data segment size */
-
-/*
- * Packet types.
- */
-#define RRQ 01 /* read request */
-#define WRQ 02 /* write request */
-#define DATA 03 /* data packet */
-#define ACK 04 /* acknowledgement */
-#define ERROR 05 /* error code */
-
-struct tftphdr {
- short th_opcode; /* packet type */
- union {
- unsigned short tu_block; /* block # */
- short tu_code; /* error code */
- char tu_stuff[1]; /* request packet stuff */
- } th_u;
- char th_data[1]; /* data or error string */
-};
-
-#define th_block th_u.tu_block
-#define th_code th_u.tu_code
-#define th_stuff th_u.tu_stuff
-#define th_msg th_data
-
-/*
- * Error codes.
- */
-#define EUNDEF 0 /* not defined */
-#define ENOTFOUND 1 /* file not found */
-#define EACCESS 2 /* access violation */
-#define ENOSPACE 3 /* disk full or allocation exceeded */
-#define EBADOP 4 /* illegal TFTP operation */
-#define EBADID 5 /* unknown transfer ID */
-#define EEXISTS 6 /* file already exists */
-#define ENOUSER 7 /* no such user */
-
-#endif /* arpa/tftp.h */
diff --git a/contrib/tftp/main.c b/contrib/tftp/main.c
deleted file mode 100644
index ca4427a1..00000000
--- a/contrib/tftp/main.c
+++ /dev/null
@@ -1,684 +0,0 @@
-/*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1983 Regents of the University of California.\n\
- All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)main.c 5.8 (Berkeley) 10/11/88";
-#endif /* not lint */
-
-/* Many bug fixes are from Jim Guyton <guyton@rand-unix> */
-
-/*
- * TFTP User Program -- Command Interface.
- */
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/file.h>
-
-#include <netinet/in.h>
-
-#include <signal.h>
-#include <stdio.h>
-#include <errno.h>
-#include <setjmp.h>
-#include <ctype.h>
-#include <netdb.h>
-
-#define TIMEOUT 5 /* secs between rexmt's */
-
-struct sockaddr_in sin;
-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(int);
-struct servent *sp;
-
-int segsize = 512;
-
-int quit(), help(), setverbose(), settrace(), status();
-int get(), put(), setpeer(), modecmd(), setrexmt(), settimeout();
-int setbinary(), setascii(), setblocksize();
-
-#define HELPINDENT (sizeof("connect"))
-
-struct cmd {
- char *name;
- char *help;
- int (*handler)();
-};
-
-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";
-char bshelp[] = "set blocksize for next transfer";
-
-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 },
- { "blocksize", bshelp, setblocksize },
- { "?", hhelp, help },
- 0
-};
-
-struct cmd *getcmd();
-char *tail();
-char *index();
-char *rindex();
-
-main(argc, argv)
- char *argv[];
-{
- struct sockaddr_in sin;
- int top;
-
- 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);
- }
- bzero((char *)&sin, 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);
- }
- top = setjmp(toplevel) == 0;
- for (;;)
- command(top);
-}
-
-char hostname[100];
-
-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) - 1, 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) {
- sin.sin_family = host->h_addrtype;
- bcopy(host->h_addr, &sin.sin_addr, host->h_length);
- strcpy(hostname, host->h_name);
- } else {
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = inet_addr(argv[1]);
- if (sin.sin_addr.s_addr == -1) {
- connected = 0;
- printf("%s: unknown host\n", argv[1]);
- return;
- }
- strcpy(hostname, 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 }
-};
-
-modecmd(argc, argv)
- 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) {
- setmode(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;
-}
-
-setbinary(argc, argv)
-char *argv[];
-{ setmode("octet");
-}
-
-setascii(argc, argv)
-char *argv[];
-{ setmode("netascii");
-}
-
-setmode(newmode)
-char *newmode;
-{
- strcpy(mode, newmode);
- if (verbose)
- printf("mode set to %s\n", mode);
-}
-
-
-/*
- * Send file(s).
- */
-put(argc, argv)
- char *argv[];
-{
- int fd;
- register int n;
- register char *cp, *targ;
-
- if (argc < 2) {
- strcpy(line, "send ");
- printf("(file) ");
- fgets(&line[strlen(line)], sizeof(line) - strlen(line) - 1, 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)&sin.sin_addr, hp->h_length);
- sin.sin_family = hp->h_addrtype;
- connected = 1;
- strcpy(hostname, hp->h_name);
- }
- if (!connected) {
- printf("No target machine specified.\n");
- return;
- }
- if (argc < 4) {
- cp = argc == 2 ? tail(targ) : argv[1];
- fd = open(cp, O_RDONLY);
- if (fd < 0) {
- fprintf(stderr, "tftp: "); perror(cp);
- return;
- }
- if (verbose)
- printf("putting %s to %s:%s [%s]\n",
- cp, hostname, targ, mode);
- sin.sin_port = port;
- sendfile(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]));
- fd = open(argv[n], O_RDONLY);
- if (fd < 0) {
- fprintf(stderr, "tftp: "); perror(argv[n]);
- continue;
- }
- if (verbose)
- printf("putting %s to %s:%s [%s]\n",
- argv[n], hostname, targ, mode);
- sin.sin_port = port;
- sendfile(fd, targ, mode);
- }
-}
-
-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).
- */
-get(argc, argv)
- char *argv[];
-{
- int fd;
- register int n;
- register char *cp;
- char *src;
-
- if (argc < 2) {
- strcpy(line, "get ");
- printf("(files) ");
- fgets(&line[strlen(line)], sizeof(line) - strlen(line) - 1, 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)&sin.sin_addr, hp->h_length);
- sin.sin_family = hp->h_addrtype;
- connected = 1;
- strcpy(hostname, hp->h_name);
- }
- if (argc < 4) {
- cp = argc == 3 ? argv[2] : tail(src);
- fd = creat(cp, 0644);
- if (fd < 0) {
- fprintf(stderr, "tftp: "); perror(cp);
- return;
- }
- if (verbose)
- printf("getting from %s:%s to %s [%s]\n",
- hostname, src, cp, mode);
- sin.sin_port = port;
- recvfile(fd, src, mode);
- break;
- }
- cp = tail(src); /* new .. jdg */
- fd = creat(cp, 0644);
- if (fd < 0) {
- fprintf(stderr, "tftp: "); perror(cp);
- continue;
- }
- if (verbose)
- printf("getting from %s:%s to %s [%s]\n",
- hostname, src, cp, mode);
- sin.sin_port = port;
- recvfile(fd, src, mode);
- }
-}
-
-getusage(s)
-char * s;
-{
- printf("usage: %s host:file host:file ... file, or\n", s);
- printf(" %s file file ... file if connected\n", s);
-}
-
-int rexmtval = TIMEOUT;
-
-setrexmt(argc, argv)
- char *argv[];
-{
- int t;
-
- if (argc < 2) {
- strcpy(line, "Rexmt-timeout ");
- printf("(value) ");
- fgets(&line[strlen(line)], sizeof(line) - strlen(line) - 1, stdin);
- makeargv();
- argc = margc;
- argv = margv;
- }
- if (argc != 2) {
- printf("usage: %s value\n", argv[0]);
- return;
- }
- t = atoi(argv[1]);
- if (t < 0)
- printf("%d: bad value\n", t);
- else
- rexmtval = t;
-}
-
-int maxtimeout = 5 * TIMEOUT;
-
-settimeout(argc, argv)
- char *argv[];
-{
- int t;
-
- if (argc < 2) {
- strcpy(line, "Maximum-timeout ");
- printf("(value) ");
- fgets(&line[strlen(line)], sizeof(line) - strlen(line) - 1, stdin);
- makeargv();
- argc = margc;
- argv = margv;
- }
- if (argc != 2) {
- printf("usage: %s value\n", argv[0]);
- return;
- }
- t = atoi(argv[1]);
- if (t < 0)
- printf("%d: bad value\n", t);
- else
- maxtimeout = t;
-}
-
-status(argc, argv)
- char *argv[];
-{
- if (connected)
- printf("Connected to %s.\n", hostname);
- else
- printf("Not connected.\n");
- printf("Mode: %s Verbose: %s Tracing: %s\n", mode,
- verbose ? "on" : "off", trace ? "on" : "off");
- printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n",
- rexmtval, maxtimeout);
-}
-
-void intr(int sig)
-{
- signal(SIGALRM, SIG_IGN);
- alarm(0);
- longjmp(toplevel, -1);
-}
-
-char *
-tail(filename)
- char *filename;
-{
- register char *s;
-
- while (*filename) {
- s = rindex(filename, '/');
- if (s == NULL)
- break;
- if (s[1])
- return (s + 1);
- *s = '\0';
- }
- return (filename);
-}
-
-/*
- * Command parser.
- */
-command(top)
- int top;
-{
- register struct cmd *c;
-
- if (!top)
- putchar('\n');
- for (;;) {
- printf("%s> ", prompt);
- if (fgets(line, sizeof(line), stdin) == 0) {
- if (feof(stdin)) {
- quit();
- } else {
- continue;
- }
- }
- if (line[0] == 0)
- continue;
- makeargv();
- c = getcmd(margv[0]);
- if (c == (struct cmd *)-1) {
- printf("?Ambiguous command\n");
- continue;
- }
- if (c == 0) {
- printf("?Invalid command\n");
- continue;
- }
- (*c->handler)(margc, margv);
- }
-}
-
-struct cmd *
-getcmd(name)
- register char *name;
-{
- register char *p, *q;
- register struct cmd *c, *found;
- register int nmatches, longest;
-
- longest = 0;
- nmatches = 0;
- found = 0;
- for (c = cmdtab; p = c->name; c++) {
- for (q = name; *q == *p++; q++)
- if (*q == 0) /* exact match? */
- return (c);
- if (!*q) { /* the name was a prefix */
- if (q - name > longest) {
- longest = q - name;
- nmatches = 1;
- found = c;
- } else if (q - name == longest)
- nmatches++;
- }
- }
- if (nmatches > 1)
- return ((struct cmd *)-1);
- return (found);
-}
-
-/*
- * Slice a string up into argc/argv.
- */
-makeargv()
-{
- register char *cp;
- register char **argp = margv;
-
- margc = 0;
- for (cp = line; *cp;) {
- while (isspace(*cp))
- cp++;
- if (*cp == '\0')
- break;
- *argp++ = cp;
- margc += 1;
- while (*cp != '\0' && !isspace(*cp))
- cp++;
- if (*cp == '\0')
- break;
- *cp++ = '\0';
- }
- *argp++ = 0;
-}
-
-/*VARARGS*/
-quit()
-{
- exit(0);
-}
-
-/*
- * Help command.
- */
-help(argc, argv)
- int argc;
- char *argv[];
-{
- register struct cmd *c;
-
- if (argc == 1) {
- printf("Commands may be abbreviated. Commands are:\n\n");
- for (c = cmdtab; c->name; c++)
- printf("%-*s\t%s\n", HELPINDENT, c->name, c->help);
- return;
- }
- while (--argc > 0) {
- register char *arg;
- arg = *++argv;
- c = getcmd(arg);
- if (c == (struct cmd *)-1)
- printf("?Ambiguous help command %s\n", arg);
- else if (c == (struct cmd *)0)
- printf("?Invalid help command %s\n", arg);
- else
- printf("%s\n", c->help);
- }
-}
-
-/*VARARGS*/
-settrace()
-{
- trace = !trace;
- printf("Packet tracing %s.\n", trace ? "on" : "off");
-}
-
-/*VARARGS*/
-setverbose()
-{
- verbose = !verbose;
- printf("Verbose mode %s.\n", verbose ? "on" : "off");
-}
-
-setblocksize(argc, argv)
- char *argv[];
-{
- int t;
-
- if (argc < 2) {
- strcpy(line, "blocksize ");
- printf("(value) ");
- fgets(&line[strlen(line)], sizeof(line) - strlen(line) - 1, stdin);
- makeargv();
- argc = margc;
- argv = margv;
- }
- if (argc != 2) {
- printf("usage: %s value\n", argv[0]);
- return;
- }
- t = atoi(argv[1]);
- if (t < 8 || t > 1432)
- printf("%d: bad value\n", t);
- else
- segsize = t;
-}
diff --git a/contrib/tftp/tftp.1 b/contrib/tftp/tftp.1
deleted file mode 100644
index fc235b2a..00000000
--- a/contrib/tftp/tftp.1
+++ /dev/null
@@ -1,159 +0,0 @@
-.\" Copyright (c) 1986 The Regents of the University of California.
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms are permitted
-.\" provided that the above copyright notice and this paragraph are
-.\" duplicated in all such forms and that any documentation,
-.\" advertising materials, and other materials related to such
-.\" distribution and use acknowledge that the software was developed
-.\" by the University of California, Berkeley. The name of the
-.\" University may not be used to endorse or promote products derived
-.\" from this software without specific prior written permission.
-.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
-.\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-.\"
-.\" @(#)tftp.1 5.3 (Berkeley) 9/20/88
-.\"
-.TH TFTP 1 "September 20, 1988"
-.UC 6
-.SH NAME
-tftp \- trivial file transfer program
-.SH SYNOPSIS
-.B tftp
-[
-host
-]
-.SH DESCRIPTION
-.I Tftp
-is the user interface to the Internet TFTP
-(Trivial File Transfer Protocol),
-which allows users to transfer files to and from a remote machine.
-The remote
-.I host
-may be specified on the command line, in which case
-.I tftp
-uses
-.I host
-as the default host for future transfers (see the
-.B connect
-command below).
-.SH COMMANDS
-Once
-.I tftp
-is running, it issues the prompt
-.B tftp>
-and recognizes the following commands:
-.TP
-\fBconnect\fP \fIhost-name\fP [ \fIport\fP ]
-Set the
-.I host
-(and optionally
-.IR port )
-for transfers.
-Note that the TFTP protocol, unlike the FTP protocol,
-does not maintain connections betweeen transfers; thus, the
-.I connect
-command does not actually create a connection,
-but merely remembers what host is to be used for transfers.
-You do not have to use the
-.I connect
-command; the remote host can be specified as part of the
-.I get
-or
-.I put
-commands.
-.TP
-\fBmode\fP \fItransfer-mode\fP
-Set the mode for transfers;
-.I transfer-mode
-may be one of
-.IR ascii
-or
-.IR binary .
-The default is
-.IR ascii .
-.TP
-\fBput\fP \fIfile\fP
-.ns
-.TP
-\fBput\fP \fIlocalfile remotefile\fP
-.ns
-.TP
-\fBput\fP \fIfile1 file2 ... fileN remote-directory\fP
-Put a file or set of files to the specified
-remote file or directory.
-The destination
-can be in one of two forms:
-a filename on the remote host, if the host has already been specified,
-or a string of the form
-.I host:filename
-to specify both a host and filename at the same time.
-If the latter form is used,
-the hostname specified becomes the default for future transfers.
-If the remote-directory form is used, the remote host is
-assumed to be a
-.I UNIX
-machine.
-.TP
-\fBget\fP \fIfilename\fP
-.ns
-.TP
-\fBget\fP \fIremotename\fP \fIlocalname\fP
-.ns
-.TP
-\fBget\fP \fIfile1\fP \fIfile2\fP ... \fIfileN\fP
-Get a file or set of files from the specified
-.IR sources .
-.I Source
-can be in one of two forms:
-a filename on the remote host, if the host has already been specified,
-or a string of the form
-.I host:filename
-to specify both a host and filename at the same time.
-If the latter form is used,
-the last hostname specified becomes the default for future transfers.
-.TP
-.B quit
-Exit
-.IR tftp .
-An end of file also exits.
-.TP
-.B verbose
-Toggle verbose mode.
-.TP
-.B trace
-Toggle packet tracing.
-.TP
-.B status
-Show current status.
-.TP
-\fBrexmt\fP \fIretransmission-timeout\fP
-Set the per-packet retransmission timeout, in seconds.
-.TP
-\fBtimeout\fP \fItotal-transmission-timeout\fP
-Set the total transmission timeout, in seconds.
-.TP
-.B ascii
-Shorthand for "mode ascii"
-.TP
-.B binary
-Shorthand for "mode binary"
-.TP
-\fBblocksize\fP \fItransfer-blocksize\fP
-Set the blocksize that is used for transfers. This assumes that the
-server knows about RFC1782 and RFC1783 extensions to the TFTP
-protocol; automatic fallback is supported and will result in a default
-blocksize of 512 octets.
-.TP
-\fB?\fP \ [ \fIcommand-name\fP ... ]
-Print help information.
-.SH BUGS
-.PP
-Because there is no user-login or validation within
-the
-.I TFTP
-protocol, the remote site will probably have some
-sort of file-access restrictions in place. The
-exact methods are specific to each site and therefore
-difficult to document here.
diff --git a/contrib/tftp/tftp.c b/contrib/tftp/tftp.c
deleted file mode 100644
index 894e535e..00000000
--- a/contrib/tftp/tftp.c
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)tftp.c 5.7 (Berkeley) 6/29/88";
-#endif /* not lint */
-
-/* Many bug fixes are from Jim Guyton <guyton@rand-unix> */
-
-/*
- * TFTP User Program -- Protocol Machines
- */
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-
-#include <netinet/in.h>
-
-#include <arpa/tftp.h>
-
-#include <signal.h>
-#include <stdio.h>
-#include <errno.h>
-#include <setjmp.h>
-
-extern int errno;
-
-extern struct sockaddr_in sin; /* filled in by main */
-extern int f; /* the opened socket */
-extern int trace;
-extern int verbose;
-extern int rexmtval;
-extern int maxtimeout;
-extern int segsize;
-
-#define PKTSIZE (1432+4) /* SEGSIZE+4 */
-char ackbuf[PKTSIZE];
-int timeout;
-jmp_buf toplevel;
-jmp_buf timeoutbuf;
-
-#ifndef OACK
-#define OACK 6
-#endif
-
-void timer(int sig)
-{
-
- signal(SIGALRM, timer);
- timeout += rexmtval;
- if (timeout >= maxtimeout) {
- printf("Transfer timed out.\n");
- longjmp(toplevel, -1);
- }
- longjmp(timeoutbuf, 1);
-}
-
-strnlen(s, n)
- char *s;
- int n;
-{
- int i = 0;
-
- while (n-- > 0 && *s++) i++;
- return(i);
-}
-
-/*
- * Parse an OACK package and set blocksize accordingly
- */
-parseoack(cp, sz)
- char *cp;
- int sz;
-{
- int n;
-
- segsize = 512;
- while (sz > 0 && *cp) {
- n = strnlen(cp, sz);
- if (n == 7 && !strncmp("blksize", cp, 7)) {
- cp += 8;
- sz -= 8;
- if (sz <= 0)
- break;
- for (segsize = 0, n = strnlen(cp, sz); n > 0;
- n--, cp++, sz--) {
- if (*cp < '0' || *cp > '9')
- break;
- segsize = 10*segsize + *cp - '0'; }
- }
- cp += n + 1;
- sz -= n + 1;
- }
- if (segsize < 8 || segsize > 1432) {
- printf("Remote host negotiated illegal blocksize %d\n",
- segsize);
- segsize = 512;
- longjmp(timeoutbuf, -1);
- }
-}
-
-/*
- * Send the requested file.
- */
-sendfile(fd, name, mode)
- int fd;
- char *name;
- char *mode;
-{
- register struct tftphdr *ap; /* data and ack packets */
- struct tftphdr *r_init(), *dp;
- register int size, n;
- u_short block = 0;
- register unsigned long amount = 0;
- struct sockaddr_in from;
- int fromlen;
- int convert; /* true if doing nl->crlf conversion */
- FILE *file;
-
- startclock(); /* start stat's clock */
- dp = r_init(); /* reset fillbuf/read-ahead code */
- ap = (struct tftphdr *)ackbuf;
- file = fdopen(fd, "r");
- convert = !strcmp(mode, "netascii");
-
- signal(SIGALRM, timer);
- do {
- if (block == 0)
- size = makerequest(WRQ, name, dp, mode) - 4;
- else {
- /* size = read(fd, dp->th_data, SEGSIZE); */
- size = readit(file, &dp, convert);
- if (size < 0) {
- nak(errno + 100);
- break;
- }
- dp->th_opcode = htons((u_short)DATA);
- dp->th_block = htons(block);
- }
- timeout = 0;
- (void) setjmp(timeoutbuf);
-send_data:
- if (trace)
- tpacket("sent", dp, size + 4);
- n = sendto(f, dp, size + 4, 0, (struct sockaddr *)&sin,
- sizeof (sin));
- if (n != size + 4) {
- perror("tftp: sendto");
- goto abort;
- }
- if (block) /* do not start reading until the blocksize
- has been negotiated */
- read_ahead(file, convert);
- for ( ; ; ) {
- alarm(rexmtval);
- do {
- fromlen = sizeof (from);
- n = recvfrom(f, ackbuf, sizeof (ackbuf), 0,
- (struct sockaddr *)&from,
- &fromlen);
- } while (n <= 0);
- alarm(0);
- if (n < 0) {
- perror("tftp: recvfrom");
- goto abort;
- }
- sin.sin_port = from.sin_port; /* added */
- if (trace)
- tpacket("received", ap, n);
- /* should verify packet came from server */
- ap->th_opcode = ntohs(ap->th_opcode);
- if (ap->th_opcode == ERROR) {
- printf("Error code %d: %s\n", ap->th_code,
- ap->th_msg);
- goto abort;
- }
- if (ap->th_opcode == ACK) {
- int j;
-
- ap->th_block = ntohs(ap->th_block);
-
- if (block == 0) {
- if (trace)
- printf("server does not know "
- "about RFC1782; reset"
- "ting blocksize\n");
- segsize = 512;
- }
- if (ap->th_block == block) {
- break;
- }
- /* On an error, try to synchronize
- * both sides.
- */
- j = synchnet(f);
- if (j && trace) {
- printf("discarded %d packets\n",
- j);
- }
- if (ap->th_block == (block-1)) {
- goto send_data;
- }
- }
- else if (ap->th_opcode == OACK) {
- if (block) {
- printf("protocol violation\n");
- longjmp(toplevel, -1);
- }
- parseoack(&ap->th_stuff, n - 2);
- break;
- }
- }
- if (block > 0)
- amount += size;
- else
- read_ahead(file, convert);
- block++;
- } while (size == segsize || block == 1);
-abort:
- fclose(file);
- stopclock();
- if (amount > 0)
- printstats("Sent", amount);
-}
-
-/*
- * Receive a file.
- */
-recvfile(fd, name, mode)
- int fd;
- char *name;
- char *mode;
-{
- register struct tftphdr *ap;
- struct tftphdr *dp, *w_init();
- register int n, size;
- u_short block = 1;
- unsigned long amount = 0;
- struct sockaddr_in from;
- int fromlen, firsttrip = 1;
- FILE *file;
- int convert; /* true if converting crlf -> lf */
- int waitforoack = 1;
-
- startclock();
- dp = w_init();
- ap = (struct tftphdr *)ackbuf;
- file = fdopen(fd, "w");
- convert = !strcmp(mode, "netascii");
-
- signal(SIGALRM, timer);
- do {
- if (firsttrip) {
- size = makerequest(RRQ, name, ap, mode);
- firsttrip = 0;
- } else {
- ap->th_opcode = htons((u_short)ACK);
- ap->th_block = htons(block);
- size = 4;
- block++;
- }
- timeout = 0;
- (void) setjmp(timeoutbuf);
-send_ack:
- if (trace)
- tpacket("sent", ap, size);
- if (sendto(f, ackbuf, size, 0, (struct sockaddr *)&sin,
- sizeof (sin)) != size) {
- alarm(0);
- perror("tftp: sendto");
- goto abort;
- }
- if (!waitforoack)
- write_behind(file, convert);
- for ( ; ; ) {
- alarm(rexmtval);
- do {
- fromlen = sizeof (from);
- n = recvfrom(f, dp, PKTSIZE, 0,
- (struct sockaddr *)&from, &fromlen);
- } while (n <= 0);
- alarm(0);
- if (n < 0) {
- perror("tftp: recvfrom");
- goto abort;
- }
- sin.sin_port = from.sin_port; /* added */
- if (trace)
- tpacket("received", dp, n);
- /* should verify client address */
- dp->th_opcode = ntohs(dp->th_opcode);
- if (dp->th_opcode == ERROR) {
- printf("Error code %d: %s\n", dp->th_code,
- dp->th_msg);
- goto abort;
- }
- if (dp->th_opcode == DATA) {
- int j;
-
- if (waitforoack) {
- if (trace)
- printf("server does not know "
- "about RFC1782; reset"
- "ting blocksize\n");
- waitforoack = 0;
- segsize = 512;
- }
- dp->th_block = ntohs(dp->th_block);
- if (dp->th_block == block) {
- break; /* have next packet */
- }
- /* On an error, try to synchronize
- * both sides.
- */
- j = synchnet(f);
- if (j && trace) {
- printf("discarded %d packets\n", j);
- }
- if (dp->th_block == (block-1)) {
- goto send_ack; /* resend ack */
- }
- }
- else if (dp->th_opcode == OACK) {
- if (block != 1 || !waitforoack) {
- printf("protocol violation\n");
- longjmp(toplevel, -1);
- }
- waitforoack = 0;
- parseoack(&dp->th_stuff, n - 2);
- ap->th_opcode = htons((u_short)ACK);
- ap->th_block = htons(0);
- size = 4;
- goto send_ack;
- }
- }
- /* size = write(fd, dp->th_data, n - 4); */
- size = writeit(file, &dp, n - 4, convert);
- if (size < 0) {
- nak(errno + 100);
- break;
- }
- amount += size;
- } while (size == segsize);
-abort: /* ok to ack, since user */
- ap->th_opcode = htons((u_short)ACK); /* has seen err msg */
- ap->th_block = htons(block);
- (void) sendto(f, ackbuf, 4, 0, (struct sockaddr *)&sin, sizeof (sin));
- write_behind(file, convert); /* flush last buffer */
- fclose(file);
- stopclock();
- if (amount > 0)
- printstats("Received", amount);
-}
-
-makerequest(request, name, tp, mode)
- int request;
- char *name, *mode;
- struct tftphdr *tp;
-{
- register char *cp;
-
- tp->th_opcode = htons((u_short)request);
- cp = tp->th_stuff;
- strcpy(cp, name);
- cp += strlen(name);
- *cp++ = '\0';
- strcpy(cp, mode);
- cp += strlen(mode);
- *cp++ = '\0';
- strcpy(cp, "blksize");
- cp += 7;
- *cp++ = '\0';
- sprintf(cp, "%d", segsize);
- cp += strlen(cp) + 1;
- return (cp - (char *)tp);
-}
-
-struct errmsg {
- int e_code;
- const char *e_msg;
-} errmsgs[] = {
- { EUNDEF, "Undefined error code" },
- { ENOTFOUND, "File not found" },
- { EACCESS, "Access violation" },
- { ENOSPACE, "Disk full or allocation exceeded" },
- { EBADOP, "Illegal TFTP operation" },
- { EBADID, "Unknown transfer ID" },
- { EEXISTS, "File already exists" },
- { ENOUSER, "No such user" },
- { -1, 0 }
-};
-
-/*
- * Send a nak packet (error message).
- * Error code passed in is one of the
- * standard TFTP codes, or a UNIX errno
- * offset by 100.
- */
-nak(error)
- int error;
-{
- register struct tftphdr *tp;
- int length;
- register struct errmsg *pe;
-/* extern char *sys_errlist[]; */
-
- tp = (struct tftphdr *)ackbuf;
- tp->th_opcode = htons((u_short)ERROR);
- tp->th_code = htons((u_short)error);
- for (pe = errmsgs; pe->e_code >= 0; pe++)
- if (pe->e_code == error)
- break;
- if (pe->e_code < 0) {
- pe->e_msg = sys_errlist[error - 100];
- tp->th_code = EUNDEF;
- }
- strcpy(tp->th_msg, pe->e_msg);
- length = strlen(pe->e_msg) + 4;
- if (trace)
- tpacket("sent", tp, length);
- if (sendto(f, ackbuf, length, 0, (struct sockaddr *)&sin, sizeof (sin))
- != length)
- perror("nak");
-}
-
-topts(cp, sz)
- char *cp;
- int sz;
-{
- int n, i = 0;
-
- while (sz > 0 && *cp) {
- n = strnlen(cp, sz);
- if (n > 0) {
- printf("%s%s=", i++ ? ", " : "", cp);
- cp += n + 1;
- sz -= n + 1;
- if (sz <= 0)
- break;
- n = strnlen(cp, sz);
- if (n > 0)
- printf("%s", cp);
- }
- cp += n + 1;
- sz -= n + 1;
- }
-}
-
-tpacket(s, tp, n)
- char *s;
- struct tftphdr *tp;
- int n;
-{
- static char *opcodes[] =
- { "#0", "RRQ", "WRQ", "DATA", "ACK", "ERROR", "OACK" };
- register char *cp, *file;
- u_short op = ntohs(tp->th_opcode);
- char *index();
-
- if (op < RRQ || op > OACK)
- printf("%s opcode=%x ", s, op);
- else
- printf("%s %s ", s, opcodes[op]);
- switch (op) {
-
- case RRQ:
- case WRQ:
- n -= 2;
- file = cp = tp->th_stuff;
- cp = index(cp, '\0');
- printf("<file=%s, mode=%s, opts: ", file, cp + 1);
- topts(index(cp + 1, '\000') + 1, n - strlen(file)
- - strlen(cp + 1) - 2);
- printf(">\n");
- break;
-
- case DATA:
- printf("<block=%d, %d bytes>\n", ntohs(tp->th_block), n - 4);
- break;
-
- case ACK:
- printf("<block=%d>\n", ntohs(tp->th_block));
- break;
-
- case ERROR:
- printf("<code=%d, msg=%s>\n", ntohs(tp->th_code), tp->th_msg);
- break;
- case OACK:
- printf("<");
- topts(tp->th_stuff, n - 2);
- printf(">\n");
- break;
- }
-}
-
-struct timeval tstart;
-struct timeval tstop;
-struct timezone zone;
-
-startclock() {
- gettimeofday(&tstart, &zone);
-}
-
-stopclock() {
- gettimeofday(&tstop, &zone);
-}
-
-printstats(direction, amount)
-char *direction;
-unsigned long amount;
-{
- double delta;
- /* compute delta in 1/10's second units */
- delta = ((tstop.tv_sec*10.)+(tstop.tv_usec/100000)) -
- ((tstart.tv_sec*10.)+(tstart.tv_usec/100000));
- delta = delta/10.; /* back to seconds */
- printf("%s %ld bytes in %.1f seconds", direction, amount, delta);
- if ((verbose) && (delta >= 0.1))
- printf(" [%.0f bits/sec]", (amount*8.)/delta);
- putchar('\n');
-}
-
diff --git a/contrib/tftp/tftpd.8 b/contrib/tftp/tftpd.8
deleted file mode 100644
index 6a154c10..00000000
--- a/contrib/tftp/tftpd.8
+++ /dev/null
@@ -1,75 +0,0 @@
-.\" Copyright (c) 1983 The Regents of the University of California.
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms are permitted
-.\" provided that the above copyright notice and this paragraph are
-.\" duplicated in all such forms and that any documentation,
-.\" advertising materials, and other materials related to such
-.\" distribution and use acknowledge that the software was developed
-.\" by the University of California, Berkeley. The name of the
-.\" University may not be used to endorse or promote products derived
-.\" from this software without specific prior written permission.
-.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
-.\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-.\"
-.\" @(#)tftpd.8 6.3 (Berkeley) 9/20/88
-.\"
-.TH TFTPD 8 "September 20, 1988"
-.UC 5
-.SH NAME
-tftpd \- DARPA Trivial File Transfer Protocol server
-.SH SYNOPSIS
-.B /etc/tftpd
-[
-.SM \-c
-<rootdir> ] [
-.SM \-d
-] [
-.SM \-r
-<filter> ]
-.SH DESCRIPTION
-.I Tftpd
-is a server which supports the DARPA Trivial File Transfer
-Protocol.
-The TFTP server operates
-at the port indicated in the ``tftp'' service description;
-see
-.IR services (5).
-The server is normally started by
-.IR inetd (8).
-.PP
-The use of
-.I tftp
-does not require an account or password on the remote system.
-Due to the lack of authentication information,
-.I tftpd
-will allow only publicly readable files to be
-accessed.
-Files may be written only if they already exist and are publicly writable.
-Note that this extends the concept of ``public'' to include
-all users on all hosts that can be reached through the network;
-this may not be appropriate on all systems, and its implications
-should be considered before enabling tftp service.
-The server should have the user ID with the lowest possible privilege.
-.SH OPTIONS
-.TP
-.B \-c
-Pathname of a directory that is considered the rootdirectory for all
-transfers. N.B.
-.I tftpd
-does not actually perform a
-.IR chroot (2)
-call; you should be aware of the security implications and you
-probably should run the server from an unpriviledged account.
-.TP
-.B \-d
-Increased debugging level.
-.TP
-.B \-r
-Pathname of a file that is considered to be a filter program. Whenever
-a client tries to download this file, the filter will be started and
-its output is send to the client. An arbitrary amount of these
-filters can be specified.
-.SH "SEE ALSO"
-tftp(1), inetd(8)
diff --git a/contrib/tftp/tftpd.c b/contrib/tftp/tftpd.c
deleted file mode 100644
index 325a7134..00000000
--- a/contrib/tftp/tftpd.c
+++ /dev/null
@@ -1,742 +0,0 @@
-/*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1983 Regents of the University of California.\n\
- All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)tftpd.c 5.8 (Berkeley) 6/18/88";
-#endif /* not lint */
-
-/*
- * Trivial file transfer protocol server.
- *
- * This version includes many modifications by Jim Guyton <guyton@rand-unix>
- *
- * Further modifications by Markus Gutschke <gutschk@math.uni-muenster.de>
- * - RFC1782 option parsing
- * - RFC1783 extended blocksize
- * - "-c" option for changing the root directory
- * - "-d" option for debugging output
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-
-#include <netinet/in.h>
-
-#include <arpa/tftp.h>
-
-#include <alloca.h>
-#include <string.h>
-#include <signal.h>
-#include <stdio.h>
-#include <errno.h>
-#include <ctype.h>
-#include <netdb.h>
-#include <setjmp.h>
-#include <syslog.h>
-
-#define TIMEOUT 5
-
-#ifndef OACK
-#define OACK 06
-#endif
-
-#ifndef EOPTNEG
-#define EOPTNEG 8
-#endif
-
-extern int errno;
-struct sockaddr_in sin = { AF_INET };
-int peer;
-int rexmtval = TIMEOUT;
-int maxtimeout = 5*TIMEOUT;
-
-#define PKTSIZE (1432+4) /* SEGSIZE+4 */
-int segsize = SEGSIZE;
-char buf[PKTSIZE];
-char ackbuf[PKTSIZE];
-struct sockaddr_in from;
-int fromlen;
-
-char *rootdir = NULL;
-int debug = 0;
-
-struct filters {
- struct filters *next;
- char *fname;
-} *filters = NULL;
-int isfilter = 0;
-
-main(argc, argv)
- char *argv[];
-{
- register struct tftphdr *tp;
- register int n;
- int on = 1;
- extern int optind;
- extern char *optarg;
-
- openlog(argv[0], LOG_PID, LOG_DAEMON);
-
- while ((n = getopt(argc, argv, "c:dr:")) >= 0) {
- switch (n) {
- case 'c':
- if (rootdir)
- goto usage;
- rootdir = optarg;
- break;
- case 'd':
- debug++;
- break;
- case 'r': {
- struct filters *fp = (void *)
- malloc(sizeof(struct filters) +
- strlen(optarg) + 1);
- fp->next = filters;
- fp->fname = (char *)(fp + 1);
- strcpy(fp->fname, optarg);
- filters = fp;
- break; }
- default:
- usage:
- syslog(LOG_ERR, "Usage: %s [-c chroot] "
- "[-r readfilter] [-d]\n",
- argv[0]);
- exit(1);
- }
- }
- if (argc-optind != 0)
- goto usage;
-
- ioctl(0, FIONBIO, &on);
-/* if (ioctl(0, FIONBIO, &on) < 0) {
- syslog(LOG_ERR, "ioctl(FIONBIO): %m\n");
- exit(1);
- }
-*/
- fromlen = sizeof (from);
- n = recvfrom(0, buf, segsize+4, 0,
- (struct sockaddr *)&from, &fromlen);
- if (n < 0) {
- syslog(LOG_ERR, "recvfrom: %m\n");
- exit(1);
- }
- /*
- * Now that we have read the message out of the UDP
- * socket, we fork and exit. Thus, inetd will go back
- * to listening to the tftp port, and the next request
- * to come in will start up a new instance of tftpd.
- *
- * We do this so that inetd can run tftpd in "wait" mode.
- * The problem with tftpd running in "nowait" mode is that
- * inetd may get one or more successful "selects" on the
- * tftp port before we do our receive, so more than one
- * instance of tftpd may be started up. Worse, if tftpd
- * break before doing the above "recvfrom", inetd would
- * spawn endless instances, clogging the system.
- */
- {
- int pid;
- int i, j;
-
- for (i = 1; i < 20; i++) {
- pid = fork();
- if (pid < 0) {
- sleep(i);
- /*
- * flush out to most recently sent request.
- *
- * This may drop some request, but those
- * will be resent by the clients when
- * they timeout. The positive effect of
- * this flush is to (try to) prevent more
- * than one tftpd being started up to service
- * a single request from a single client.
- */
- j = sizeof from;
- i = recvfrom(0, buf, segsize+4, 0,
- (struct sockaddr *)&from, &j);
- if (i > 0) {
- n = i;
- fromlen = j;
- }
- } else {
- break;
- }
- }
- if (pid < 0) {
- syslog(LOG_ERR, "fork: %m\n");
- exit(1);
- } else if (pid != 0) {
- exit(0);
- }
- }
- from.sin_family = AF_INET;
- alarm(0);
- close(0);
- close(1);
- peer = socket(AF_INET, SOCK_DGRAM, 0);
- if (peer < 0) {
- syslog(LOG_ERR, "socket: %m\n");
- exit(1);
- }
- if (bind(peer, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
- syslog(LOG_ERR, "bind: %m\n");
- exit(1);
- }
- if (connect(peer, (struct sockaddr *)&from, sizeof(from)) < 0) {
- syslog(LOG_ERR, "connect: %m\n");
- exit(1);
- }
- tp = (struct tftphdr *)buf;
- tp->th_opcode = ntohs(tp->th_opcode);
- if (tp->th_opcode == RRQ || tp->th_opcode == WRQ)
- tftp(tp, n);
- exit(1);
-}
-
-int validate_access();
-int sendfile(), recvfile();
-
-struct formats {
- char *f_mode;
- int (*f_validate)();
- int (*f_send)();
- int (*f_recv)();
- int f_convert;
-} formats[] = {
- { "netascii", validate_access, sendfile, recvfile, 1 },
- { "octet", validate_access, sendfile, recvfile, 0 },
-#ifdef notdef
- { "mail", validate_user, sendmail, recvmail, 1 },
-#endif
- { 0 }
-};
-
-int set_blksize();
-
-struct options {
- char *o_opt;
- int (*o_fnc)();
-} options[] = {
- { "blksize", set_blksize },
- { 0 }
-};
-
-/*
- * Set a non-standard block size (c.f. RFC1783)
- */
-
-set_blksize(val, ret)
- char *val;
- char **ret;
-{
- static char b_ret[5];
- int sz = atoi(val);
-
- if (sz < 8) {
- if (debug)
- syslog(LOG_ERR, "Requested packetsize %d < 8\n", sz);
- return(0);
- } else if (sz > PKTSIZE-4) {
- if (debug)
- syslog(LOG_INFO, "Requested packetsize %d > %d\n",
- sz, PKTSIZE-4);
- sz = PKTSIZE-4;
- } else if (debug)
- syslog(LOG_INFO, "Adjusted packetsize to %d octets\n", sz);
-
- segsize = sz;
- sprintf(*ret = b_ret, "%d", sz);
- return(1);
-}
-
-/*
- * Parse RFC1782 style options
- */
-
-do_opt(opt, val, ap)
- char *opt;
- char *val;
- char **ap;
-{
- struct options *po;
- char *ret;
-
- for (po = options; po->o_opt; po++)
- if (strcasecmp(po->o_opt, opt) == 0) {
- if (po->o_fnc(val, &ret)) {
- if (*ap + strlen(opt) + strlen(ret) + 2 >=
- ackbuf + sizeof(ackbuf)) {
- if (debug)
- syslog(LOG_ERR,
- "Ackbuf overflow\n");
- nak(ENOSPACE);
- exit(1);
- }
- *ap = strrchr(strcpy(strrchr(strcpy(*ap, opt),
- '\000')+1, val),
- '\000')+1;
- } else {
- nak(EOPTNEG);
- exit(1);
- }
- break;
- }
- if (debug && !po->o_opt)
- syslog(LOG_WARNING, "Unhandled option: %d = %d\n", opt, val);
- return;
-}
-
-/*
- * Handle initial connection protocol.
- */
-tftp(tp, size)
- struct tftphdr *tp;
- int size;
-{
- register char *cp;
- int argn = 0, ecode;
- register struct formats *pf;
- char *filename, *mode;
- char *val, *opt;
- char *ap = ackbuf+2;
- int isopts;
-
- ((struct tftphdr *)ackbuf)->th_opcode = ntohs(OACK);
- filename = cp = tp->th_stuff;
-again:
- while (cp < buf + size) {
- if (*cp == '\0')
- break;
- cp++;
- }
- if (*cp != '\0') {
- if (debug)
- syslog(LOG_WARNING, "Received illegal request\n");
- nak(EBADOP);
- exit(1);
- }
- if (!argn++) {
- mode = ++cp;
- goto again;
- } else {
- if (debug && argn == 3)
- syslog(LOG_INFO, "Found RFC1782 style options\n");
- *(argn & 1 ? &val : &opt) = ++cp;
- if (argn & 1)
- do_opt(opt, val, &ap);
- if (cp < buf + size && *cp != '\000')
- goto again;
- }
-
- for (cp = mode; *cp; cp++)
- if (isupper(*cp))
- *cp = tolower(*cp);
- for (pf = formats; pf->f_mode; pf++)
- if (strcmp(pf->f_mode, mode) == 0)
- break;
- if (pf->f_mode == 0) {
- if (debug)
- syslog(LOG_WARNING, "Unknown data format: %s\n", mode);
- nak(EBADOP);
- exit(1);
- }
-
- if (rootdir) {
- cp = alloca(strlen(rootdir) + strlen(filename) + 1);
- if (cp == NULL) {
- nak(100+ENOMEM);
- exit(1);
- }
- if (*filename != '/') {
- if (debug)
- syslog(LOG_ERR,
- "Filename has to be absolute: %s\n",
- filename);
- nak(EACCESS);
- exit(1);
- }
- filename = strcat(strcpy(cp, rootdir), filename);
- }
-
- ecode = (*pf->f_validate)(filename, tp->th_opcode);
- if (ecode) {
- nak(ecode, ERROR);
- exit(1);
- }
- isopts = ap != (ackbuf+2);
- (tp->th_opcode == WRQ ? *pf->f_recv : *pf->f_send)
- (pf, isopts ? ackbuf : NULL, isopts ? ap-ackbuf : 0);
- exit(0);
-}
-
-
-FILE *file;
-
-/*
- * Validate file access. Since we
- * have no uid or gid, for now require
- * file to exist and be publicly
- * readable/writable.
- * Note also, full path name must be
- * given as we have no login directory.
- */
-validate_access(filename, mode)
- char *filename;
- int mode;
-{
- struct stat stbuf;
- int fd;
- char *cp;
-
- isfilter = 0;
- if (mode == RRQ) {
- struct filters *fp = filters;
- for (; fp; fp = fp->next) {
- if (!strcmp(fp->fname,
- filename +
- (rootdir ? strlen(rootdir) : 0))) {
- if (debug)
- syslog(LOG_INFO, "Opening input "
- "filter: %s\n", filename);
- if ((file = popen(filename, "r")) == NULL) {
- syslog(LOG_ERR, "Failed to open input "
- "filter\n");
- return (EACCESS); }
- fd = fileno(file);
- isfilter = 1;
- return (0);
- }
- }
- }
-
- if (*filename != '/') {
- if (debug)
- syslog(LOG_ERR, "Filename has to be absolute: %s\n",
- filename);
- return (EACCESS);
- }
- for (cp = filename; *cp; cp++)
- if (*cp == '~' || *cp == '$' ||
- (*cp == '/' && cp[1] == '.' && cp[2] == '.')) {
- if (debug)
- syslog(LOG_ERR, "Illegal filename: %s\n",
- filename);
- return (EACCESS);
- }
- if (debug)
- syslog(LOG_INFO, "Validating \"%s\" for %sing\n",
- filename, mode == RRQ ? "read" : "writ");
- if (stat(filename, &stbuf) < 0)
- return (errno == ENOENT ? ENOTFOUND : EACCESS);
- if (mode == RRQ) {
- if ((stbuf.st_mode&(S_IREAD >> 6)) == 0)
- return (EACCESS);
- } else {
- if ((stbuf.st_mode&(S_IWRITE >> 6)) == 0)
- return (EACCESS);
- }
- fd = open(filename, mode == RRQ ? 0 : 1);
- if (fd < 0)
- return (errno + 100);
- file = fdopen(fd, (mode == RRQ)? "r":"w");
- if (file == NULL) {
- return errno+100;
- }
- return (0);
-}
-
-int timeout;
-jmp_buf timeoutbuf;
-
-void timer(int sig)
-{
-
- timeout += rexmtval;
- if (timeout >= maxtimeout) {
- if (debug)
- syslog(LOG_WARNING, "Timeout!\n");
- exit(1);
- }
- longjmp(timeoutbuf, 1);
-}
-
-/*
- * Send the requested file.
- */
-sendfile(pf, oap, oacklen)
- struct formats *pf;
- struct tftphdr *oap;
- int oacklen;
-{
- struct tftphdr *dp, *r_init();
- register struct tftphdr *ap; /* ack packet */
- register int size, n;
- u_short block = 1;
-
- signal(SIGALRM, timer);
-
- ap = (struct tftphdr *)ackbuf;
-
- if (oap) {
- timeout = 0;
- (void) setjmp(timeoutbuf);
- oack:
- if (send(peer, oap, oacklen, 0) != oacklen) {
- syslog(LOG_ERR, "tftpd: write: %m\n");
- goto abort;
- }
- for ( ; ; ) {
- alarm(rexmtval);
- n = recv(peer, ackbuf, sizeof (ackbuf), 0);
- alarm(0);
- if (n < 0) {
- syslog(LOG_ERR, "tftpd: read: %m\n");
- goto abort;
- }
- ap->th_opcode = ntohs((u_short)ap->th_opcode);
- ap->th_block = ntohs(ap->th_block);
-
- if (ap->th_opcode == ERROR) {
- if (debug)
- syslog(LOG_ERR, "Client does not "
- "accept options\n");
- goto abort; }
-
- if (ap->th_opcode == ACK) {
- if (ap->th_block == 0) {
- if (debug)
- syslog(LOG_DEBUG,
- "RFC1782 option "
- "negotiation "
- "succeeded\n");
- break;
- }
- /* Re-synchronize with the other side */
- (void) synchnet(peer);
- goto oack;
- }
- }
- }
-
- dp = r_init();
- do {
- size = readit(file, &dp, pf->f_convert);
- if (size < 0) {
- nak(errno + 100);
- goto abort;
- }
- dp->th_opcode = htons((u_short)DATA);
- dp->th_block = htons(block);
- timeout = 0;
- (void) setjmp(timeoutbuf);
-
-send_data:
- if (send(peer, dp, size + 4, 0) != size + 4) {
- syslog(LOG_ERR, "tftpd: write: %m\n");
- goto abort;
- }
- read_ahead(file, pf->f_convert);
- for ( ; ; ) {
- alarm(rexmtval); /* read the ack */
- n = recv(peer, ackbuf, sizeof (ackbuf), 0);
- alarm(0);
- if (n < 0) {
- syslog(LOG_ERR, "tftpd: read: %m\n");
- goto abort;
- }
- ap->th_opcode = ntohs((u_short)ap->th_opcode);
- ap->th_block = ntohs(ap->th_block);
-
- if (ap->th_opcode == ERROR)
- goto abort;
-
- if (ap->th_opcode == ACK) {
- if (ap->th_block == block) {
- break;
- }
- /* Re-synchronize with the other side */
- (void) synchnet(peer);
- if (ap->th_block == (block -1)) {
- goto send_data;
- }
- }
-
- }
- block++;
- } while (size == segsize);
-abort:
- if (isfilter)
- pclose(file);
- else
- (void) fclose(file);
- isfilter = 0;
-}
-
-void justquit(int sig)
-{
- exit(0);
-}
-
-
-/*
- * Receive a file.
- */
-recvfile(pf, oap, oacklen)
- struct formats *pf;
- struct tftphdr *oap;
- int oacklen;
-{
- struct tftphdr *dp, *w_init();
- register struct tftphdr *ap; /* ack buffer */
- register int acksize, n, size;
- u_short block = 0;
-
- signal(SIGALRM, timer);
- dp = w_init();
- do {
- timeout = 0;
-
- if (!block++ && oap) {
- ap = (struct tftphdr *)oap;
- acksize = oacklen;
- } else {
- ap = (struct tftphdr *)ackbuf;
- ap->th_opcode = htons((u_short)ACK);
- ap->th_block = htons(block-1);
- acksize = 4;
- }
- (void) setjmp(timeoutbuf);
-send_ack:
- if (send(peer, (char *)ap, acksize, 0) != acksize) {
- syslog(LOG_ERR, "tftpd: write: %m\n");
- goto abort;
- }
- write_behind(file, pf->f_convert);
- for ( ; ; ) {
- alarm(rexmtval);
- n = recv(peer, dp, segsize+4, 0);
- alarm(0);
- if (n < 0) { /* really? */
- syslog(LOG_ERR, "tftpd: read: %m\n");
- goto abort;
- }
- dp->th_opcode = ntohs((u_short)dp->th_opcode);
- dp->th_block = ntohs(dp->th_block);
- if (dp->th_opcode == ERROR)
- goto abort;
- if (dp->th_opcode == DATA) {
- if (dp->th_block == block) {
- break; /* normal */
- }
- /* Re-synchronize with the other side */
- (void) synchnet(peer);
- if (dp->th_block == (block-1))
- goto send_ack; /* rexmit */
- }
- }
- /* size = write(file, dp->th_data, n - 4); */
- size = writeit(file, &dp, n - 4, pf->f_convert);
- if (size != (n-4)) { /* ahem */
- if (size < 0) nak(errno + 100);
- else nak(ENOSPACE);
- goto abort;
- }
- } while (size == segsize);
- write_behind(file, pf->f_convert);
- if (isfilter)
- pclose(file);
- else
- (void) fclose(file); /* close data file */
- isfilter = 0;
-
- ap = (struct tftphdr *)ackbuf;
- ap->th_opcode = htons((u_short)ACK); /* send the "final" ack */
- ap->th_block = htons(block);
- (void) send(peer, ackbuf, 4, 0);
-
- signal(SIGALRM, justquit); /* just quit on timeout */
- alarm(rexmtval);
- n = recv(peer, buf, segsize, 0); /* normally times out and quits */
- alarm(0);
- if (n >= 4 && /* if read some data */
- dp->th_opcode == DATA && /* and got a data block */
- block == dp->th_block) { /* then my last ack was lost */
- (void) send(peer, ackbuf, 4, 0); /* resend final ack */
- }
-abort:
- return;
-}
-
-struct errmsg {
- int e_code;
- const char *e_msg;
-} errmsgs[] = {
- { EUNDEF, "Undefined error code" },
- { ENOTFOUND, "File not found" },
- { EACCESS, "Access violation" },
- { ENOSPACE, "Disk full or allocation exceeded" },
- { EBADOP, "Illegal TFTP operation" },
- { EBADID, "Unknown transfer ID" },
- { EEXISTS, "File already exists" },
- { ENOUSER, "No such user" },
- { EOPTNEG, "Failure to negotiate RFC1782 options" },
- { -1, 0 }
-};
-
-/*
- * Send a nak packet (error message).
- * Error code passed in is one of the
- * standard TFTP codes, or a UNIX errno
- * offset by 100.
- */
-nak(error)
- int error;
-{
- register struct tftphdr *tp;
- int length;
- register struct errmsg *pe;
-/* extern char *sys_errlist[]; */
-
- tp = (struct tftphdr *)buf;
- tp->th_opcode = htons((u_short)ERROR);
- tp->th_code = htons((u_short)error);
- for (pe = errmsgs; pe->e_code >= 0; pe++)
- if (pe->e_code == error)
- break;
- if (pe->e_code < 0) {
- pe->e_msg = sys_errlist[error -100];
- tp->th_code = EUNDEF; /* set 'undef' errorcode */
- }
- strcpy(tp->th_msg, pe->e_msg);
- length = strlen(pe->e_msg);
- tp->th_msg[length] = '\0';
- length += 5;
- if (debug)
- syslog(LOG_ERR, "Negative acknowledge: %s\n", tp->th_msg);
- if (send(peer, buf, length, 0) != length)
- syslog(LOG_ERR, "nak: %m\n");
-}
diff --git a/contrib/tftp/tftpsubs.c b/contrib/tftp/tftpsubs.c
deleted file mode 100644
index 608d64ec..00000000
--- a/contrib/tftp/tftpsubs.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)tftpsubs.c 5.4 (Berkeley) 6/29/88";
-#endif /* not lint */
-
-/* Simple minded read-ahead/write-behind subroutines for tftp user and
- server. Written originally with multiple buffers in mind, but current
- implementation has two buffer logic wired in.
-
- Todo: add some sort of final error check so when the write-buffer
- is finally flushed, the caller can detect if the disk filled up
- (or had an i/o error) and return a nak to the other side.
-
- Jim Guyton 10/85
- */
-
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <netinet/in.h>
-#include <arpa/tftp.h>
-#include <stdio.h>
-
-#define PKTSIZE (1432+4) /* SEGSIZE+4 */ /* should be moved to tftp.h */
-
-struct bf {
- int counter; /* size of data in buffer, or flag */
- char buf[PKTSIZE]; /* room for data packet */
-} bfs[2];
-
- /* Values for bf.counter */
-#define BF_ALLOC -3 /* alloc'd but not yet filled */
-#define BF_FREE -2 /* free */
-/* [-1 .. SEGSIZE] = size of data in the data buffer */
-
-extern int segsize;
-
-static int nextone; /* index of next buffer to use */
-static int current; /* index of buffer in use */
-
- /* control flags for crlf conversions */
-int newline = 0; /* fillbuf: in middle of newline expansion */
-int prevchar = -1; /* putbuf: previous char (cr check) */
-
-struct tftphdr *rw_init();
-
-struct tftphdr *w_init() { return rw_init(0); } /* write-behind */
-struct tftphdr *r_init() { return rw_init(1); } /* read-ahead */
-
-struct tftphdr *
-rw_init(x) /* init for either read-ahead or write-behind */
-int x; /* zero for write-behind, one for read-head */
-{
- newline = 0; /* init crlf flag */
- prevchar = -1;
- bfs[0].counter = BF_ALLOC; /* pass out the first buffer */
- current = 0;
- bfs[1].counter = BF_FREE;
- nextone = x; /* ahead or behind? */
- return (struct tftphdr *)bfs[0].buf;
-}
-
-
-/* Have emptied current buffer by sending to net and getting ack.
- Free it and return next buffer filled with data.
- */
-readit(file, dpp, convert)
- FILE *file; /* file opened for read */
- struct tftphdr **dpp;
- int convert; /* if true, convert to ascii */
-{
- struct bf *b;
-
- bfs[current].counter = BF_FREE; /* free old one */
- current = !current; /* "incr" current */
-
- b = &bfs[current]; /* look at new buffer */
- if (b->counter == BF_FREE) /* if it's empty */
- read_ahead(file, convert); /* fill it */
-/* assert(b->counter != BF_FREE); /* check */
- *dpp = (struct tftphdr *)b->buf; /* set caller's ptr */
- return b->counter;
-}
-
-/*
- * fill the input buffer, doing ascii conversions if requested
- * conversions are lf -> cr,lf and cr -> cr, nul
- */
-read_ahead(file, convert)
- FILE *file; /* file opened for read */
- int convert; /* if true, convert to ascii */
-{
- register int i;
- register char *p;
- register int c;
- struct bf *b;
- struct tftphdr *dp;
-
- b = &bfs[nextone]; /* look at "next" buffer */
- if (b->counter != BF_FREE) /* nop if not free */
- return;
- nextone = !nextone; /* "incr" next buffer ptr */
-
- dp = (struct tftphdr *)b->buf;
-
- if (convert == 0) {
- int i;
- b->counter = 0;
- do {
- i = read(fileno(file), dp->th_data + b->counter,
- segsize - b->counter);
- if (i > 0)
- b->counter += i;
- } while (i != 0 && !(i < 0 && errno != EINTR) &&
- b->counter < segsize);
- return;
- }
-
- p = dp->th_data;
- for (i = 0 ; i < segsize; i++) {
- if (newline) {
- if (prevchar == '\n')
- c = '\n'; /* lf to cr,lf */
- else c = '\0'; /* cr to cr,nul */
- newline = 0;
- }
- else {
- c = getc(file);
- if (c == EOF) break;
- if (c == '\n' || c == '\r') {
- prevchar = c;
- c = '\r';
- newline = 1;
- }
- }
- *p++ = c;
- }
- b->counter = (int)(p - dp->th_data);
-}
-
-/* Update count associated with the buffer, get new buffer
- from the queue. Calls write_behind only if next buffer not
- available.
- */
-writeit(file, dpp, ct, convert)
- FILE *file;
- struct tftphdr **dpp;
- int convert;
-{
- bfs[current].counter = ct; /* set size of data to write */
- current = !current; /* switch to other buffer */
- if (bfs[current].counter != BF_FREE) /* if not free */
- write_behind(file, convert); /* flush it */
- bfs[current].counter = BF_ALLOC; /* mark as alloc'd */
- *dpp = (struct tftphdr *)bfs[current].buf;
- return ct; /* this is a lie of course */
-}
-
-/*
- * Output a buffer to a file, converting from netascii if requested.
- * CR,NUL -> CR and CR,LF => LF.
- * Note spec is undefined if we get CR as last byte of file or a
- * CR followed by anything else. In this case we leave it alone.
- */
-write_behind(file, convert)
- FILE *file;
- int convert;
-{
- char *buf;
- int count;
- register int ct;
- register char *p;
- register int c; /* current character */
- struct bf *b;
- struct tftphdr *dp;
-
- b = &bfs[nextone];
- if (b->counter < -1) /* anything to flush? */
- return 0; /* just nop if nothing to do */
-
- count = b->counter; /* remember byte count */
- b->counter = BF_FREE; /* reset flag */
- dp = (struct tftphdr *)b->buf;
- nextone = !nextone; /* incr for next time */
- buf = dp->th_data;
-
- if (count <= 0) return -1; /* nak logic? */
-
- if (convert == 0)
- return write(fileno(file), buf, count);
-
- p = buf;
- ct = count;
- while (ct--) { /* loop over the buffer */
- c = *p++; /* pick up a character */
- if (prevchar == '\r') { /* if prev char was cr */
- if (c == '\n') /* if have cr,lf then just */
- fseek(file, -1, 1); /* smash lf on top of the cr */
- else
- if (c == '\0') /* if have cr,nul then */
- goto skipit; /* just skip over the putc */
- /* else just fall through and allow it */
- }
- putc(c, file);
-skipit:
- prevchar = c;
- }
- return count;
-}
-
-
-/* When an error has occurred, it is possible that the two sides
- * are out of synch. Ie: that what I think is the other side's
- * response to packet N is really their response to packet N-1.
- *
- * So, to try to prevent that, we flush all the input queued up
- * for us on the network connection on our host.
- *
- * We return the number of packets we flushed (mostly for reporting
- * when trace is active).
- */
-
-int
-synchnet(f)
-int f; /* socket to flush */
-{
- int i, j = 0;
- char rbuf[PKTSIZE];
- struct sockaddr_in from;
- int fromlen;
-
- while (1) {
- (void) ioctl(f, FIONREAD, &i);
- if (i) {
- j++;
- fromlen = sizeof from;
- (void) recvfrom(f, rbuf, sizeof (rbuf), 0,
- (struct sockaddr *)&from, &fromlen);
- } else {
- return(j);
- }
- }
-}