version 1.30, 2009/10/27 23:59:44 |
version 1.31, 2012/05/01 04:23:21 |
|
|
void quit(int, char **); |
void quit(int, char **); |
void setascii(int, char **); |
void setascii(int, char **); |
void setbinary(int, char **); |
void setbinary(int, char **); |
void setpeer(int, char **); |
void setpeer(char *, char *); |
|
void parsearg(int, char **); |
void setrexmt(int, char **); |
void setrexmt(int, char **); |
void settimeout(int, char **); |
void settimeout(int, char **); |
void settrace(int, char **); |
void settrace(int, char **); |
|
|
struct cmd *getcmd(char *); |
struct cmd *getcmd(char *); |
char *tail(char *); |
char *tail(char *); |
|
|
struct sockaddr_in peeraddr; |
struct sockaddr_storage peeraddr; |
int f; |
int f; |
short port; |
|
int trace; |
int trace; |
int verbose; |
int verbose; |
int connected; |
int connected; |
|
|
char *margv[MAXARGV+1]; |
char *margv[MAXARGV+1]; |
char *prompt = "tftp"; |
char *prompt = "tftp"; |
void intr(int); |
void intr(int); |
struct servent *sp; |
|
int rexmtval = TIMEOUT; |
int rexmtval = TIMEOUT; |
int maxtimeout = 5 * TIMEOUT; |
int maxtimeout = 5 * TIMEOUT; |
char hostname[MAXHOSTNAMELEN]; |
char hostname[MAXHOSTNAMELEN]; |
|
|
}; |
}; |
|
|
struct cmd cmdtab[] = { |
struct cmd cmdtab[] = { |
{ "connect", chelp, setpeer }, |
{ "connect", chelp, parsearg }, |
{ "mode", mhelp, modecmd }, |
{ "mode", mhelp, modecmd }, |
{ "put", shelp, put }, |
{ "put", shelp, put }, |
{ "get", rhelp, get }, |
{ "get", rhelp, get }, |
|
|
int |
int |
main(int argc, char *argv[]) |
main(int argc, char *argv[]) |
{ |
{ |
struct sockaddr_in s_in; |
f = -1; |
|
|
/* socket, bind */ |
|
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 *)&s_in, sizeof(s_in)); |
|
s_in.sin_family = AF_INET; |
|
if (bind(f, (struct sockaddr *)&s_in, sizeof(s_in)) < 0) |
|
err(1, "bind"); |
|
|
|
/* set default transfer mode */ |
/* set default transfer mode */ |
strlcpy(mode, "netascii", sizeof(mode)); |
strlcpy(mode, "netascii", sizeof(mode)); |
|
|
/* set peer if given */ |
/* set peer if given */ |
if (argc > 1) |
if (argc > 1) |
setpeer(argc, argv); |
parsearg(argc, argv); |
|
|
/* catch SIGINT */ |
/* catch SIGINT */ |
signal(SIGINT, intr); |
signal(SIGINT, intr); |
|
|
} |
} |
|
|
void |
void |
setpeer(int argc, char *argv[]) |
setpeer(char *host, char *port) |
{ |
{ |
struct hostent *host; |
struct addrinfo hints, *res0, *res; |
const char *errstr; |
int error; |
|
struct sockaddr_storage ss; |
|
char *cause = "unknown"; |
|
|
|
if (connected) { |
|
close(f); |
|
f = -1; |
|
} |
|
connected = 0; |
|
|
|
memset(&hints, 0, sizeof(hints)); |
|
hints.ai_family = PF_UNSPEC; |
|
hints.ai_socktype = SOCK_DGRAM; |
|
hints.ai_protocol = IPPROTO_UDP; |
|
hints.ai_flags = AI_CANONNAME; |
|
if (!port) |
|
port = "tftp"; |
|
error = getaddrinfo(host, port, &hints, &res0); |
|
if (error) { |
|
warnx("%s", gai_strerror(error)); |
|
return; |
|
} |
|
|
|
for (res = res0; res; res = res->ai_next) { |
|
if (res->ai_addrlen > sizeof(peeraddr)) |
|
continue; |
|
f = socket(res->ai_family, res->ai_socktype, res->ai_protocol); |
|
if (f < 0) { |
|
cause = "socket"; |
|
continue; |
|
} |
|
|
|
memset(&ss, 0, sizeof(ss)); |
|
ss.ss_family = res->ai_family; |
|
ss.ss_len = res->ai_addrlen; |
|
if (bind(f, (struct sockaddr *)&ss, ss.ss_len) < 0) { |
|
cause = "bind"; |
|
close(f); |
|
f = -1; |
|
continue; |
|
} |
|
|
|
break; |
|
} |
|
|
|
if (f < 0) |
|
warn("%s", cause); |
|
else { |
|
/* res->ai_addr <= sizeof(peeraddr) is guaranteed */ |
|
memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); |
|
if (res->ai_canonname) { |
|
(void) strncpy(hostname, res->ai_canonname, |
|
sizeof(hostname)); |
|
} else |
|
(void) strncpy(hostname, host, sizeof(hostname)); |
|
hostname[sizeof(hostname)-1] = 0; |
|
connected = 1; |
|
} |
|
freeaddrinfo(res0); |
|
} |
|
|
|
void |
|
parsearg(int argc, char *argv[]) |
|
{ |
if (argc < 2) { |
if (argc < 2) { |
strlcpy(line, "Connect ", sizeof(line)); |
strlcpy(line, "Connect ", sizeof(line)); |
printf("(to) "); |
printf("(to) "); |
|
|
printf("usage: %s [host [port]]\n", argv[0]); |
printf("usage: %s [host [port]]\n", argv[0]); |
return; |
return; |
} |
} |
if (inet_aton(argv[1], &peeraddr.sin_addr) != 0) { |
if (argc == 2) |
peeraddr.sin_family = AF_INET; |
setpeer(argv[1], NULL); |
(void)strncpy(hostname, argv[1], sizeof(hostname)); |
else |
hostname[sizeof(hostname) - 1] = '\0'; |
setpeer(argv[1], argv[2]); |
} else { |
|
host = gethostbyname(argv[1]); |
|
if (host == 0) { |
|
connected = 0; |
|
printf("%s: unknown host\n", argv[1]); |
|
return; |
|
} |
|
peeraddr.sin_family = host->h_addrtype; |
|
bcopy(host->h_addr, &peeraddr.sin_addr, host->h_length); |
|
(void)strlcpy(hostname, host->h_name, sizeof(hostname)); |
|
} |
|
port = sp->s_port; |
|
if (argc == 3) { |
|
port = strtonum(argv[2], 1, 65535, &errstr); |
|
if (errstr) { |
|
printf("%s: port number is %s\n", argv[2], errstr); |
|
connected = 0; |
|
return; |
|
} |
|
port = htons(port); |
|
} |
|
connected = 1; |
|
} |
} |
|
|
void |
void |
|
|
return; |
return; |
} |
} |
targ = argv[argc - 1]; |
targ = argv[argc - 1]; |
if (strchr(argv[argc - 1], ':')) { |
if (strrchr(argv[argc - 1], ':')) { |
struct hostent *hp; |
|
|
|
for (n = 1; n < argc - 1; n++) |
for (n = 1; n < argc - 1; n++) |
if (strchr(argv[n], ':')) { |
if (strchr(argv[n], ':')) { |
|
|
return; |
return; |
} |
} |
cp = argv[argc - 1]; |
cp = argv[argc - 1]; |
targ = strchr(cp, ':'); |
targ = strrchr(cp, ':'); |
*targ++ = 0; |
*targ++ = 0; |
hp = gethostbyname(cp); |
if (cp[0] == '[' && cp[strlen(cp) - 1] == ']') { |
if (hp == NULL) { |
cp[strlen(cp) - 1] = '\0'; |
warnx("%s: %s", cp, hstrerror(h_errno)); |
cp++; |
return; |
|
} |
} |
bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr, hp->h_length); |
setpeer(cp, NULL); |
peeraddr.sin_family = hp->h_addrtype; |
|
connected = 1; |
|
port = sp->s_port; |
|
strlcpy(hostname, hp->h_name, sizeof(hostname)); |
|
} |
} |
if (!connected) { |
if (!connected) { |
printf("No target machine specified.\n"); |
printf("No target machine specified.\n"); |
|
|
if (verbose) |
if (verbose) |
printf("putting %s to %s:%s [%s]\n", |
printf("putting %s to %s:%s [%s]\n", |
cp, hostname, targ, mode); |
cp, hostname, targ, mode); |
peeraddr.sin_port = port; |
|
sendfile(fd, targ, mode); |
sendfile(fd, targ, mode); |
return; |
return; |
} |
} |
|
|
if (verbose) |
if (verbose) |
printf("putting %s to %s:%s [%s]\n", |
printf("putting %s to %s:%s [%s]\n", |
argv[n], hostname, cp, mode); |
argv[n], hostname, cp, mode); |
peeraddr.sin_port = port; |
|
sendfile(fd, cp, mode); |
sendfile(fd, cp, mode); |
free(cp); |
free(cp); |
} |
} |
|
|
} |
} |
if (!connected) { |
if (!connected) { |
for (n = 1; n < argc; n++) |
for (n = 1; n < argc; n++) |
if (strchr(argv[n], ':') == 0) { |
if (strrchr(argv[n], ':') == 0) { |
getusage(argv[0]); |
getusage(argv[0]); |
return; |
return; |
} |
} |
} |
} |
for (n = 1; n < argc; n++) { |
for (n = 1; n < argc; n++) { |
src = strchr(argv[n], ':'); |
src = strrchr(argv[n], ':'); |
if (src == NULL) |
if (src == NULL) |
src = argv[n]; |
src = argv[n]; |
else { |
else { |
struct hostent *hp; |
char *cp; |
|
|
*src++ = 0; |
*src++ = 0; |
hp = gethostbyname(argv[n]); |
cp = argv[n]; |
if (hp == NULL) { |
if (cp[0] == '[' && cp[strlen(cp) - 1] == ']') { |
warnx("%s: %s", argv[n], hstrerror(h_errno)); |
cp[strlen(cp) - 1] = '\0'; |
continue; |
cp++; |
} |
} |
bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr, |
setpeer(cp, NULL); |
hp->h_length); |
if (!connected) |
peeraddr.sin_family = hp->h_addrtype; |
continue; |
connected = 1; |
|
strlcpy(hostname, hp->h_name, sizeof(hostname)); |
|
} |
} |
if (argc < 4) { |
if (argc < 4) { |
cp = argc == 3 ? argv[2] : tail(src); |
cp = argc == 3 ? argv[2] : tail(src); |
|
|
if (verbose) |
if (verbose) |
printf("getting from %s:%s to %s [%s]\n", |
printf("getting from %s:%s to %s [%s]\n", |
hostname, src, cp, mode); |
hostname, src, cp, mode); |
peeraddr.sin_port = port; |
|
recvfile(fd, src, mode); |
recvfile(fd, src, mode); |
break; |
break; |
} |
} |
|
|
if (verbose) |
if (verbose) |
printf("getting from %s:%s to %s [%s]\n", |
printf("getting from %s:%s to %s [%s]\n", |
hostname, src, cp, mode); |
hostname, src, cp, mode); |
peeraddr.sin_port = port; |
|
recvfile(fd, src, mode); |
recvfile(fd, src, mode); |
} |
} |
} |
} |