* Copyright (c) 1983 Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 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
"@(#) Copyright (c) 1983 Regents of the University of California.\n\
static char sccsid
[] = "@(#)main.c 5.10 (Berkeley) 3/1/91";
/* Many bug fixes are from Jim Guyton <guyton@rand-unix> */
* TFTP User Program -- Command Interface.
#define TIMEOUT 5 /* secs between rexmt's */
int quit(), help(), setverbose(), settrace(), status();
int get(), put(), setpeer(), modecmd(), setrexmt(), settimeout();
int setbinary(), setascii();
#define HELPINDENT (sizeof("connect"))
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";
{ "connect", chelp
, setpeer
},
{ "mode", mhelp
, modecmd
},
{ "verbose", vhelp
, setverbose
},
{ "trace", thelp
, settrace
},
{ "status", sthelp
, status
},
{ "binary", bnhelp
, setbinary
},
{ "ascii", ashelp
, setascii
},
{ "rexmt", xhelp
, setrexmt
},
{ "timeout", ihelp
, settimeout
},
sp
= getservbyname("tftp", "udp");
fprintf(stderr
, "tftp: udp/tftp: unknown service\n");
f
= socket(AF_INET
, SOCK_DGRAM
, 0);
bzero((char *)&s_in
, sizeof (s_in
));
s_in
.sin_family
= AF_INET
;
if (bind(f
, (struct sockaddr
*)&s_in
, sizeof (s_in
)) < 0) {
strcpy(mode
, "netascii");
if (setjmp(toplevel
) != 0)
top
= setjmp(toplevel
) == 0;
strcpy(line
, "Connect ");
gets(&line
[strlen(line
)]);
printf("usage: %s host-name [port]\n", argv
[0]);
host
= gethostbyname(argv
[1]);
s_in
.sin_family
= host
->h_addrtype
;
bcopy(host
->h_addr
, &s_in
.sin_addr
, host
->h_length
);
strcpy(hostname
, host
->h_name
);
s_in
.sin_family
= AF_INET
;
s_in
.sin_addr
.s_addr
= inet_addr(argv
[1]);
if (s_in
.sin_addr
.s_addr
== -1) {
printf("%s: unknown host\n", argv
[1]);
strcpy(hostname
, argv
[1]);
printf("%s: bad port number\n", argv
[2]);
{ "netascii", "netascii" },
/* { "mail", "mail" }, */
register struct modes
*p
;
printf("Using %s mode to transfer files.\n", mode
);
for (p
= modes
; p
->m_name
; p
++)
if (strcmp(argv
[1], p
->m_name
) == 0)
printf("%s: unknown mode\n", argv
[1]);
/* drop through and print usage message */
printf("usage: %s [", argv
[0]);
for (p
= modes
; p
->m_name
; p
++) {
printf("%s%s", sep
, p
->m_name
);
printf("mode set to %s\n", mode
);
register char *cp
, *targ
;
gets(&line
[strlen(line
)]);
if (index(argv
[argc
- 1], ':')) {
for (n
= 1; n
< argc
- 1; n
++)
if (index(argv
[n
], ':')) {
fprintf(stderr
, "tftp: %s: ", cp
);
bcopy(hp
->h_addr
, (caddr_t
)&s_in
.sin_addr
, hp
->h_length
);
s_in
.sin_family
= hp
->h_addrtype
;
strcpy(hostname
, hp
->h_name
);
printf("No target machine specified.\n");
cp
= argc
== 2 ? tail(targ
) : argv
[1];
fprintf(stderr
, "tftp: "); perror(cp
);
printf("putting %s to %s:%s [%s]\n",
cp
, hostname
, targ
, mode
);
sendfile(fd
, targ
, mode
);
/* this assumes the target is a directory */
/* on a remote unix system. hmmmm. */
for (n
= 1; n
< argc
- 1; n
++) {
strcpy(cp
, tail(argv
[n
]));
fd
= open(argv
[n
], O_RDONLY
);
fprintf(stderr
, "tftp: "); perror(argv
[n
]);
printf("putting %s to %s:%s [%s]\n",
argv
[n
], hostname
, targ
, mode
);
sendfile(fd
, targ
, mode
);
printf("usage: %s file ... host:target, or\n", s
);
printf(" %s file ... target (when already connected)\n", s
);
gets(&line
[strlen(line
)]);
for (n
= 1; n
< argc
; n
++)
if (index(argv
[n
], ':') == 0) {
for (n
= 1; n
< argc
; n
++) {
src
= index(argv
[n
], ':');
hp
= gethostbyname(argv
[n
]);
fprintf(stderr
, "tftp: %s: ", argv
[n
]);
bcopy(hp
->h_addr
, (caddr_t
)&s_in
.sin_addr
, hp
->h_length
);
s_in
.sin_family
= hp
->h_addrtype
;
strcpy(hostname
, hp
->h_name
);
cp
= argc
== 3 ? argv
[2] : tail(src
);
fprintf(stderr
, "tftp: "); perror(cp
);
printf("getting from %s:%s to %s [%s]\n",
hostname
, src
, cp
, mode
);
cp
= tail(src
); /* new .. jdg */
fprintf(stderr
, "tftp: "); perror(cp
);
printf("getting from %s:%s to %s [%s]\n",
hostname
, src
, cp
, mode
);
printf("usage: %s host:file host:file ... file, or\n", s
);
printf(" %s file file ... file if connected\n", s
);
strcpy(line
, "Rexmt-timeout ");
gets(&line
[strlen(line
)]);
printf("usage: %s value\n", argv
[0]);
printf("%s: bad value\n", t
);
int maxtimeout
= 5 * TIMEOUT
;
strcpy(line
, "Maximum-timeout ");
gets(&line
[strlen(line
)]);
printf("usage: %s value\n", argv
[0]);
printf("%s: bad value\n", t
);
printf("Connected to %s.\n", hostname
);
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",
signal(SIGALRM
, SIG_IGN
);
s
= rindex(filename
, '/');
if (c
== (struct cmd
*)-1) {
printf("?Ambiguous command\n");
printf("?Invalid command\n");
(*c
->handler
)(margc
, margv
);
register struct cmd
*c
, *found
;
register int nmatches
, longest
;
for (c
= cmdtab
; p
= c
->name
; c
++) {
for (q
= name
; *q
== *p
++; q
++)
if (*q
== 0) /* exact match? */
if (!*q
) { /* the name was a prefix */
if (q
- name
> longest
) {
} else if (q
- name
== longest
)
return ((struct cmd
*)-1);
* Slice a string up into argc/argv.
register char **argp
= margv
;
while (*cp
!= '\0' && !isspace(*cp
))
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
);
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
);
printf("Packet tracing %s.\n", trace
? "on" : "off");
printf("Verbose mode %s.\n", verbose
? "on" : "off");