28 |
*/ |
*/ |
29 |
|
|
30 |
#ifndef lint |
#ifndef lint |
31 |
static char copyright[] = |
static char copyright[] = "@(#) Copyright (c) 1983, 1993\n\ |
|
"@(#) Copyright (c) 1983, 1993\n\ |
|
32 |
The Regents of the University of California. All rights reserved.\n"; |
The Regents of the University of California. All rights reserved.\n"; |
33 |
#endif /* not lint */ |
#endif /* not lint */ |
34 |
|
|
35 |
#ifndef lint |
#ifndef lint |
36 |
static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; |
static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; |
37 |
#endif /* not lint */ |
#endif /* not lint */ |
38 |
|
|
39 |
/* Many bug fixes are from Jim Guyton <guyton@rand-unix> */ |
/* Many bug fixes are from Jim Guyton <guyton@rand-unix> */ |
65 |
#include <string.h> |
#include <string.h> |
66 |
#include <unistd.h> |
#include <unistd.h> |
67 |
|
|
68 |
|
#include <xalloc.h> |
69 |
#include "extern.h" |
#include "extern.h" |
70 |
|
|
71 |
#define TIMEOUT 5 /* secs between rexmt's */ |
#define TIMEOUT 5 /* secs between rexmt's */ |
72 |
|
|
73 |
struct sockaddr_in peeraddr; |
struct sockaddr_in peeraddr; |
74 |
int f; |
int f; |
75 |
short port; |
short port; |
76 |
int trace; |
int trace; |
77 |
int verbose; |
int verbose; |
78 |
int connected; |
int connected; |
79 |
char mode[32]; |
char mode[32]; |
80 |
char line[200]; |
char line[200]; |
81 |
int margc; |
int margc; |
82 |
char *margv[20]; |
char *margv[20]; |
83 |
char *prompt = "tftp"; |
char *prompt = "tftp"; |
84 |
jmp_buf toplevel; |
jmp_buf toplevel; |
85 |
void intr(); |
void intr (); |
86 |
struct servent *sp; |
struct servent *sp; |
87 |
|
|
88 |
void get __P((int, char **)); |
void get __P ((int, char **)); |
89 |
void help __P((int, char **)); |
void help __P ((int, char **)); |
90 |
void modecmd __P((int, char **)); |
void modecmd __P ((int, char **)); |
91 |
void put __P((int, char **)); |
void put __P ((int, char **)); |
92 |
void quit __P((int, char **)); |
void quit __P ((int, char **)); |
93 |
void setascii __P((int, char **)); |
void setascii __P ((int, char **)); |
94 |
void setbinary __P((int, char **)); |
void setbinary __P ((int, char **)); |
95 |
void setpeer __P((int, char **)); |
void setpeer __P ((int, char **)); |
96 |
void setrexmt __P((int, char **)); |
void setrexmt __P ((int, char **)); |
97 |
void settimeout __P((int, char **)); |
void settimeout __P ((int, char **)); |
98 |
void settrace __P((int, char **)); |
void settrace __P ((int, char **)); |
99 |
void setverbose __P((int, char **)); |
void setverbose __P ((int, char **)); |
100 |
void status __P((int, char **)); |
void status __P ((int, char **)); |
101 |
|
|
102 |
static void command __P((void)); |
static void command __P ((void)); |
103 |
|
|
104 |
static void getusage __P((char *)); |
static void getusage __P ((char *)); |
105 |
static void makeargv __P((void)); |
static void makeargv __P ((void)); |
106 |
static void putusage __P((char *)); |
static void putusage __P ((char *)); |
107 |
static void settftpmode __P((char *)); |
static void settftpmode __P ((char *)); |
108 |
|
|
109 |
#define HELPINDENT (sizeof("connect")) |
#define HELPINDENT (sizeof("connect")) |
110 |
|
|
111 |
struct cmd { |
struct cmd |
112 |
char *name; |
{ |
113 |
char *help; |
char *name; |
114 |
void (*handler) __P((int, char **)); |
char *help; |
115 |
|
void (*handler) __P ((int, char **)); |
116 |
}; |
}; |
117 |
|
|
118 |
char vhelp[] = "toggle verbose mode"; |
char vhelp[] = "toggle verbose mode"; |
119 |
char thelp[] = "toggle packet tracing"; |
char thelp[] = "toggle packet tracing"; |
120 |
char chelp[] = "connect to remote tftp"; |
char chelp[] = "connect to remote tftp"; |
121 |
char qhelp[] = "exit tftp"; |
char qhelp[] = "exit tftp"; |
122 |
char hhelp[] = "print help information"; |
char hhelp[] = "print help information"; |
123 |
char shelp[] = "send file"; |
char shelp[] = "send file"; |
124 |
char rhelp[] = "receive file"; |
char rhelp[] = "receive file"; |
125 |
char mhelp[] = "set file transfer mode"; |
char mhelp[] = "set file transfer mode"; |
126 |
char sthelp[] = "show current status"; |
char sthelp[] = "show current status"; |
127 |
char xhelp[] = "set per-packet retransmission timeout"; |
char xhelp[] = "set per-packet retransmission timeout"; |
128 |
char ihelp[] = "set total retransmission timeout"; |
char ihelp[] = "set total retransmission timeout"; |
129 |
char ashelp[] = "set mode to netascii"; |
char ashelp[] = "set mode to netascii"; |
130 |
char bnhelp[] = "set mode to octet"; |
char bnhelp[] = "set mode to octet"; |
131 |
|
|
132 |
struct cmd cmdtab[] = { |
struct cmd cmdtab[] = { |
133 |
{ "connect", chelp, setpeer }, |
{"connect", chelp, setpeer}, |
134 |
{ "mode", mhelp, modecmd }, |
{"mode", mhelp, modecmd}, |
135 |
{ "put", shelp, put }, |
{"put", shelp, put}, |
136 |
{ "get", rhelp, get }, |
{"get", rhelp, get}, |
137 |
{ "quit", qhelp, quit }, |
{"quit", qhelp, quit}, |
138 |
{ "verbose", vhelp, setverbose }, |
{"verbose", vhelp, setverbose}, |
139 |
{ "trace", thelp, settrace }, |
{"trace", thelp, settrace}, |
140 |
{ "status", sthelp, status }, |
{"status", sthelp, status}, |
141 |
{ "binary", bnhelp, setbinary }, |
{"binary", bnhelp, setbinary}, |
142 |
{ "ascii", ashelp, setascii }, |
{"ascii", ashelp, setascii}, |
143 |
{ "rexmt", xhelp, setrexmt }, |
{"rexmt", xhelp, setrexmt}, |
144 |
{ "timeout", ihelp, settimeout }, |
{"timeout", ihelp, settimeout}, |
145 |
{ "?", hhelp, help }, |
{"?", hhelp, help}, |
146 |
{ 0 } |
{0} |
147 |
}; |
}; |
148 |
|
|
149 |
struct cmd *getcmd(); |
struct cmd *getcmd (); |
150 |
char *tail(); |
char *tail (); |
151 |
|
|
152 |
int |
int |
153 |
main(argc, argv) |
main (int argc, char *argv[]) |
154 |
int argc; |
{ |
155 |
char *argv[]; |
struct sockaddr_in sin; |
|
{ |
|
|
struct sockaddr_in sin; |
|
|
|
|
|
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); |
|
|
} |
|
|
if (setjmp(toplevel) != 0) |
|
|
(void)putchar('\n'); |
|
|
command(); |
|
|
} |
|
156 |
|
|
157 |
char hostname[100]; |
sp = getservbyname ("tftp", "udp"); |
158 |
|
if (sp == 0) |
159 |
|
{ |
160 |
|
fprintf (stderr, "tftp: udp/tftp: unknown service\n"); |
161 |
|
exit (1); |
162 |
|
} |
163 |
|
f = socket (AF_INET, SOCK_DGRAM, 0); |
164 |
|
if (f < 0) |
165 |
|
{ |
166 |
|
perror ("tftp: socket"); |
167 |
|
exit (3); |
168 |
|
} |
169 |
|
memset (&sin, 0, sizeof (sin)); |
170 |
|
sin.sin_family = AF_INET; |
171 |
|
if (bind (f, (struct sockaddr *) &sin, sizeof (sin)) < 0) |
172 |
|
{ |
173 |
|
perror ("tftp: bind"); |
174 |
|
exit (1); |
175 |
|
} |
176 |
|
strcpy (mode, "netascii"); |
177 |
|
signal (SIGINT, intr); |
178 |
|
if (argc > 1) |
179 |
|
{ |
180 |
|
if (setjmp (toplevel) != 0) |
181 |
|
exit (0); |
182 |
|
setpeer (argc, argv); |
183 |
|
} |
184 |
|
if (setjmp (toplevel) != 0) |
185 |
|
(void) putchar ('\n'); |
186 |
|
command (); |
187 |
|
} |
188 |
|
|
189 |
|
char *hostname; |
190 |
|
|
191 |
|
#define RESOLVE_OK 0 |
192 |
|
#define RESOLVE_FAIL -1 |
193 |
|
#define RESOLVE_NOT_RESOLVED 1 |
194 |
|
|
195 |
|
/* Resolve NAME. Fill in peeraddr, hostname and set connected on success. |
196 |
|
Return value: RESOLVE_OK success |
197 |
|
RESOLVE_FAIL error |
198 |
|
RESOLVE_NOT_RESOLVED name is not resolved and ALLOW_NULL |
199 |
|
is true */ |
200 |
|
static int |
201 |
|
resolve_name (char *name, int allow_null) |
202 |
|
{ |
203 |
|
struct hostent *hp = gethostbyname (name); |
204 |
|
if (hp == NULL) |
205 |
|
{ |
206 |
|
if (allow_null) |
207 |
|
return RESOLVE_NOT_RESOLVED; |
208 |
|
fprintf (stderr, "tftp: %s: ", name); |
209 |
|
herror ((char *) NULL); |
210 |
|
return RESOLVE_FAIL; |
211 |
|
} |
212 |
|
else if (hp->h_length != sizeof peeraddr.sin_addr) |
213 |
|
{ |
214 |
|
fprintf (stderr, "tftp: resolving %s returns unexpected length", name); |
215 |
|
return RESOLVE_FAIL; |
216 |
|
} |
217 |
|
memcpy (&peeraddr.sin_addr, hp->h_addr, hp->h_length); |
218 |
|
peeraddr.sin_family = hp->h_addrtype; |
219 |
|
connected = 1; |
220 |
|
free (hostname); |
221 |
|
hostname = xstrdup (hp->h_name); |
222 |
|
return RESOLVE_OK; |
223 |
|
} |
224 |
|
|
225 |
/* Prompt for more arguments from the user with PROMPT, putting the results |
/* Prompt for more arguments from the user with PROMPT, putting the results |
226 |
into ARGC & ARGV, with an initial argument of ARG0. Global variables |
into ARGC & ARGV, with an initial argument of ARG0. Global variables |
227 |
LINE, MARGC, and MARGV are changed. */ |
LINE, MARGC, and MARGV are changed. */ |
228 |
static void |
static void |
229 |
get_args (arg0, prompt, argc, argv) |
get_args (char *arg0, char *prompt, int *argc, char ***argv) |
|
char *arg0, *prompt; |
|
|
int *argc; |
|
|
char ***argv; |
|
230 |
{ |
{ |
231 |
size_t arg0_len = strlen (arg0); |
size_t arg0_len = strlen (arg0); |
232 |
|
|
233 |
strcpy (line, arg0); |
strcpy (line, arg0); |
234 |
strcat (line, " "); |
strcat (line, " "); |
235 |
|
|
236 |
printf("%s", prompt); |
printf ("%s", prompt); |
237 |
fgets (line + arg0_len + 1, sizeof line - arg0_len - 1, stdin); |
fgets (line + arg0_len + 1, sizeof line - arg0_len - 1, stdin); |
238 |
|
|
239 |
makeargv(); |
makeargv (); |
240 |
*argc = margc; |
*argc = margc; |
241 |
*argv = margv; |
*argv = margv; |
242 |
} |
} |
243 |
|
|
244 |
void |
void |
245 |
setpeer(argc, argv) |
setpeer (int argc, char *argv[]) |
246 |
int argc; |
{ |
247 |
char *argv[]; |
if (argc < 2) |
248 |
{ |
get_args ("Connect", "(to) ", &argc, &argv); |
249 |
struct hostent *host; |
|
250 |
|
if (argc < 2 || argc > 3) |
251 |
if (argc < 2) |
{ |
252 |
get_args ("Connect", "(to) ", &argc, &argv); |
printf ("usage: %s host-name [port]\n", argv[0]); |
253 |
|
return; |
254 |
if (argc > 3) { |
} |
255 |
printf("usage: %s host-name [port]\n", argv[0]); |
|
256 |
return; |
switch (resolve_name (argv[1], 1)) |
257 |
} |
{ |
258 |
host = gethostbyname(argv[1]); |
case RESOLVE_OK: |
259 |
if (host) { |
break; |
260 |
peeraddr.sin_family = host->h_addrtype; |
|
261 |
bcopy(host->h_addr, &peeraddr.sin_addr, host->h_length); |
case RESOLVE_FAIL: |
262 |
strcpy(hostname, host->h_name); |
return; |
263 |
} else { |
|
264 |
peeraddr.sin_family = AF_INET; |
case RESOLVE_NOT_RESOLVED: |
265 |
peeraddr.sin_addr.s_addr = inet_addr(argv[1]); |
peeraddr.sin_family = AF_INET; |
266 |
if (peeraddr.sin_addr.s_addr == -1) { |
peeraddr.sin_addr.s_addr = inet_addr (argv[1]); |
267 |
connected = 0; |
if (peeraddr.sin_addr.s_addr == -1) |
268 |
printf("%s: unknown host\n", argv[1]); |
{ |
269 |
return; |
connected = 0; |
270 |
} |
printf ("%s: unknown host\n", argv[1]); |
271 |
strcpy(hostname, argv[1]); |
return; |
272 |
} |
} |
273 |
port = sp->s_port; |
hostname = xstrdup (argv[1]); |
274 |
if (argc == 3) { |
} |
275 |
port = atoi(argv[2]); |
|
276 |
if (port < 0) { |
port = sp->s_port; |
277 |
printf("%s: bad port number\n", argv[2]); |
if (argc == 3) |
278 |
connected = 0; |
{ |
279 |
return; |
port = atoi (argv[2]); |
280 |
} |
if (port < 0) |
281 |
port = htons(port); |
{ |
282 |
} |
printf ("%s: bad port number\n", argv[2]); |
283 |
connected = 1; |
connected = 0; |
284 |
} |
return; |
285 |
|
} |
286 |
struct modes { |
port = htons (port); |
287 |
char *m_name; |
} |
288 |
char *m_mode; |
connected = 1; |
289 |
} modes[] = { |
} |
290 |
{ "ascii", "netascii" }, |
|
291 |
{ "netascii", "netascii" }, |
struct modes |
292 |
{ "binary", "octet" }, |
{ |
293 |
{ "image", "octet" }, |
char *m_name; |
294 |
{ "octet", "octet" }, |
char *m_mode; |
295 |
|
} |
296 |
|
modes[] = |
297 |
|
{ |
298 |
|
{"ascii", "netascii"}, |
299 |
|
{"netascii", "netascii"}, |
300 |
|
{"binary", "octet"}, |
301 |
|
{"image", "octet"}, |
302 |
|
{"octet", "octet"}, |
303 |
/* { "mail", "mail" }, */ |
/* { "mail", "mail" }, */ |
304 |
{ 0, 0 } |
{0, 0} |
305 |
}; |
}; |
306 |
|
|
307 |
void |
void |
308 |
modecmd(argc, argv) |
modecmd (int argc, char *argv[]) |
309 |
int argc; |
{ |
310 |
char *argv[]; |
register struct modes *p; |
311 |
{ |
char *sep; |
312 |
register struct modes *p; |
|
313 |
char *sep; |
if (argc < 2) |
314 |
|
{ |
315 |
if (argc < 2) { |
printf ("Using %s mode to transfer files.\n", mode); |
316 |
printf("Using %s mode to transfer files.\n", mode); |
return; |
317 |
return; |
} |
318 |
} |
if (argc == 2) |
319 |
if (argc == 2) { |
{ |
320 |
for (p = modes; p->m_name; p++) |
for (p = modes; p->m_name; p++) |
321 |
if (strcmp(argv[1], p->m_name) == 0) |
if (strcmp (argv[1], p->m_name) == 0) |
322 |
break; |
break; |
323 |
if (p->m_name) { |
if (p->m_name) |
324 |
settftpmode(p->m_mode); |
{ |
325 |
return; |
settftpmode (p->m_mode); |
326 |
} |
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 = " | "; |
|
327 |
} |
} |
328 |
printf(" ]\n"); |
printf ("%s: unknown mode\n", argv[1]); |
329 |
return; |
/* drop through and print usage message */ |
330 |
|
} |
331 |
|
|
332 |
|
printf ("usage: %s [", argv[0]); |
333 |
|
sep = " "; |
334 |
|
for (p = modes; p->m_name; p++) |
335 |
|
{ |
336 |
|
printf ("%s%s", sep, p->m_name); |
337 |
|
if (*sep == ' ') |
338 |
|
sep = " | "; |
339 |
|
} |
340 |
|
printf (" ]\n"); |
341 |
|
return; |
342 |
} |
} |
343 |
|
|
344 |
void |
void |
345 |
setbinary(argc, argv) |
setbinary (int argc, char *argv[]) |
|
int argc; |
|
|
char *argv[]; |
|
346 |
{ |
{ |
347 |
|
settftpmode ("octet"); |
|
settftpmode("octet"); |
|
348 |
} |
} |
349 |
|
|
350 |
void |
void |
351 |
setascii(argc, argv) |
setascii (int argc, char *argv[]) |
|
int argc; |
|
|
char *argv[]; |
|
352 |
{ |
{ |
353 |
|
settftpmode ("netascii"); |
|
settftpmode("netascii"); |
|
354 |
} |
} |
355 |
|
|
356 |
static void |
static void |
357 |
settftpmode(newmode) |
settftpmode (char *newmode) |
|
char *newmode; |
|
358 |
{ |
{ |
359 |
strcpy(mode, newmode); |
strcpy (mode, newmode); |
360 |
if (verbose) |
if (verbose) |
361 |
printf("mode set to %s\n", mode); |
printf ("mode set to %s\n", mode); |
362 |
} |
} |
363 |
|
|
|
|
|
364 |
/* |
/* |
365 |
* Send file(s). |
* Send file(s). |
366 |
*/ |
*/ |
367 |
void |
void |
368 |
put(argc, argv) |
put (int argc, char *argv[]) |
369 |
int argc; |
{ |
370 |
char *argv[]; |
int fd; |
371 |
{ |
register int n; |
372 |
int fd; |
register char *cp, *targ; |
373 |
register int n; |
|
374 |
register char *cp, *targ; |
if (argc < 2) |
375 |
|
get_args ("send", "(file) ", &argc, &argv); |
376 |
if (argc < 2) |
|
377 |
get_args ("send", "(file) ", &argc, &argv); |
if (argc < 2) |
378 |
|
{ |
379 |
if (argc < 2) { |
putusage (argv[0]); |
380 |
putusage(argv[0]); |
return; |
381 |
return; |
} |
382 |
} |
targ = argv[argc - 1]; |
383 |
targ = argv[argc - 1]; |
if (strchr (argv[argc - 1], ':')) |
384 |
if (strchr (argv[argc - 1], ':')) { |
{ |
385 |
char *cp; |
char *cp; |
386 |
struct hostent *hp; |
|
387 |
|
for (n = 1; n < argc - 1; n++) |
388 |
for (n = 1; n < argc - 1; n++) |
if (strchr (argv[n], ':')) |
389 |
if (strchr (argv[n], ':')) { |
{ |
390 |
putusage(argv[0]); |
putusage (argv[0]); |
391 |
return; |
return; |
392 |
} |
} |
393 |
cp = argv[argc - 1]; |
cp = argv[argc - 1]; |
394 |
targ = strchr (cp, ':'); |
targ = strchr (cp, ':'); |
395 |
*targ++ = 0; |
*targ++ = 0; |
396 |
hp = gethostbyname(cp); |
if (resolve_name (cp, 0) != RESOLVE_OK) |
397 |
if (hp == NULL) { |
return; |
398 |
fprintf(stderr, "tftp: %s: ", cp); |
} |
399 |
herror((char *)NULL); |
if (!connected) |
400 |
return; |
{ |
401 |
} |
printf ("No target machine specified.\n"); |
402 |
bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr, hp->h_length); |
return; |
403 |
peeraddr.sin_family = hp->h_addrtype; |
} |
404 |
connected = 1; |
if (argc < 4) |
405 |
strcpy(hostname, hp->h_name); |
{ |
406 |
} |
cp = argc == 2 ? tail (targ) : argv[1]; |
407 |
if (!connected) { |
fd = open (cp, O_RDONLY); |
408 |
printf("No target machine specified.\n"); |
if (fd < 0) |
409 |
return; |
{ |
410 |
} |
fprintf (stderr, "tftp: "); |
411 |
if (argc < 4) { |
perror (cp); |
412 |
cp = argc == 2 ? tail(targ) : argv[1]; |
return; |
413 |
fd = open(cp, O_RDONLY); |
} |
414 |
if (fd < 0) { |
if (verbose) |
415 |
fprintf(stderr, "tftp: "); perror(cp); |
printf ("putting %s to %s:%s [%s]\n", cp, hostname, targ, mode); |
416 |
return; |
peeraddr.sin_port = port ? port : sp->s_port; |
417 |
} |
send_file (fd, targ, mode); |
418 |
if (verbose) |
return; |
419 |
printf("putting %s to %s:%s [%s]\n", |
} |
420 |
cp, hostname, targ, mode); |
/* this assumes the target is a directory */ |
421 |
peeraddr.sin_port = port; |
/* on a remote unix system. hmmmm. */ |
422 |
send_file(fd, targ, mode); |
cp = strchr (targ, '\0'); |
423 |
return; |
*cp++ = '/'; |
424 |
} |
for (n = 1; n < argc - 1; n++) |
425 |
/* this assumes the target is a directory */ |
{ |
426 |
/* on a remote unix system. hmmmm. */ |
strcpy (cp, tail (argv[n])); |
427 |
cp = strchr (targ, '\0'); |
fd = open (argv[n], O_RDONLY); |
428 |
*cp++ = '/'; |
if (fd < 0) |
429 |
for (n = 1; n < argc - 1; n++) { |
{ |
430 |
strcpy(cp, tail(argv[n])); |
fprintf (stderr, "tftp: "); |
431 |
fd = open(argv[n], O_RDONLY); |
perror (argv[n]); |
432 |
if (fd < 0) { |
continue; |
433 |
fprintf(stderr, "tftp: "); perror(argv[n]); |
} |
434 |
continue; |
if (verbose) |
435 |
} |
printf ("putting %s to %s:%s [%s]\n", argv[n], hostname, targ, mode); |
436 |
if (verbose) |
peeraddr.sin_port = port ? port : sp->s_port; |
437 |
printf("putting %s to %s:%s [%s]\n", |
send_file (fd, targ, mode); |
438 |
argv[n], hostname, targ, mode); |
} |
|
peeraddr.sin_port = port; |
|
|
send_file(fd, targ, mode); |
|
|
} |
|
439 |
} |
} |
440 |
|
|
441 |
static void |
static void |
442 |
putusage(s) |
putusage (char *s) |
|
char *s; |
|
443 |
{ |
{ |
444 |
printf("usage: %s file ... host:target, or\n", s); |
printf ("usage: %s file ... host:target, or\n", s); |
445 |
printf(" %s file ... target (when already connected)\n", s); |
printf (" %s file ... target (when already connected)\n", s); |
446 |
} |
} |
447 |
|
|
448 |
/* |
/* |
449 |
* Receive file(s). |
* Receive file(s). |
450 |
*/ |
*/ |
451 |
void |
void |
452 |
get(argc, argv) |
get (int argc, char *argv[]) |
453 |
int argc; |
{ |
454 |
char *argv[]; |
int fd; |
455 |
{ |
register int n; |
456 |
int fd; |
register char *cp; |
457 |
register int n; |
char *src; |
458 |
register char *cp; |
|
459 |
char *src; |
if (argc < 2) |
460 |
|
get_args ("get", "(files) ", &argc, &argv); |
461 |
if (argc < 2) |
|
462 |
get_args ("get", "(files) ", &argc, &argv); |
if (argc < 2) |
463 |
|
{ |
464 |
if (argc < 2) { |
getusage (argv[0]); |
465 |
getusage(argv[0]); |
return; |
466 |
return; |
} |
467 |
} |
if (!connected) |
468 |
if (!connected) { |
{ |
469 |
for (n = 1; n < argc ; n++) |
for (n = 1; n < argc; n++) |
470 |
if (strchr (argv[n], ':') == 0) { |
if (strchr (argv[n], ':') == 0) |
471 |
getusage(argv[0]); |
{ |
472 |
return; |
getusage (argv[0]); |
473 |
} |
return; |
474 |
} |
} |
475 |
for (n = 1; n < argc ; n++) { |
} |
476 |
src = strchr (argv[n], ':'); |
for (n = 1; n < argc; n++) |
477 |
if (src == NULL) |
{ |
478 |
src = argv[n]; |
src = strchr (argv[n], ':'); |
479 |
else { |
if (src == NULL) |
480 |
struct hostent *hp; |
src = argv[n]; |
481 |
|
else |
482 |
*src++ = 0; |
{ |
483 |
hp = gethostbyname(argv[n]); |
*src++ = 0; |
484 |
if (hp == NULL) { |
if (resolve_name (argv[n], 0) != RESOLVE_OK) |
485 |
fprintf(stderr, "tftp: %s: ", argv[n]); |
continue; |
486 |
herror((char *)NULL); |
} |
487 |
continue; |
|
488 |
} |
if (argc < 4) |
489 |
bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr, |
{ |
490 |
hp->h_length); |
cp = argc == 3 ? argv[2] : tail (src); |
491 |
peeraddr.sin_family = hp->h_addrtype; |
fd = creat (cp, 0644); |
492 |
connected = 1; |
if (fd < 0) |
493 |
strcpy(hostname, hp->h_name); |
{ |
494 |
} |
fprintf (stderr, "tftp: "); |
495 |
if (argc < 4) { |
perror (cp); |
496 |
cp = argc == 3 ? argv[2] : tail(src); |
return; |
497 |
fd = creat(cp, 0644); |
} |
498 |
if (fd < 0) { |
if (verbose) |
499 |
fprintf(stderr, "tftp: "); perror(cp); |
printf ("getting from %s:%s to %s [%s]\n", |
500 |
return; |
hostname, src, cp, mode); |
501 |
} |
peeraddr.sin_port = port ? port : sp->s_port; |
502 |
if (verbose) |
recvfile (fd, src, mode); |
503 |
printf("getting from %s:%s to %s [%s]\n", |
break; |
504 |
hostname, src, cp, mode); |
} |
505 |
peeraddr.sin_port = port; |
cp = tail (src); /* new .. jdg */ |
506 |
recvfile(fd, src, mode); |
fd = creat (cp, 0644); |
507 |
break; |
if (fd < 0) |
508 |
} |
{ |
509 |
cp = tail(src); /* new .. jdg */ |
fprintf (stderr, "tftp: "); |
510 |
fd = creat(cp, 0644); |
perror (cp); |
511 |
if (fd < 0) { |
continue; |
512 |
fprintf(stderr, "tftp: "); perror(cp); |
} |
513 |
continue; |
if (verbose) |
514 |
} |
printf ("getting from %s:%s to %s [%s]\n", hostname, src, cp, mode); |
515 |
if (verbose) |
peeraddr.sin_port = port ? port : sp->s_port; |
516 |
printf("getting from %s:%s to %s [%s]\n", |
recvfile (fd, src, mode); |
517 |
hostname, src, cp, mode); |
} |
|
peeraddr.sin_port = port; |
|
|
recvfile(fd, src, mode); |
|
|
} |
|
518 |
} |
} |
519 |
|
|
520 |
static void |
static void |
521 |
getusage(s) |
getusage (char *s) |
|
char *s; |
|
522 |
{ |
{ |
523 |
printf("usage: %s host:file host:file ... file, or\n", s); |
printf ("usage: %s host:file host:file ... file, or\n", s); |
524 |
printf(" %s file file ... file if connected\n", s); |
printf (" %s file file ... file if connected\n", s); |
525 |
} |
} |
526 |
|
|
527 |
int rexmtval = TIMEOUT; |
int rexmtval = TIMEOUT; |
528 |
|
|
529 |
void |
void |
530 |
setrexmt(argc, argv) |
setrexmt (int argc, char *argv[]) |
|
int argc; |
|
|
char *argv[]; |
|
531 |
{ |
{ |
532 |
int t; |
int t; |
533 |
|
|
534 |
if (argc < 2) |
if (argc < 2) |
535 |
get_args ("Rexmt-timeout", "(value) ", &argc, &argv); |
get_args ("Rexmt-timeout", "(value) ", &argc, &argv); |
536 |
|
|
537 |
if (argc != 2) { |
if (argc != 2) |
538 |
printf("usage: %s value\n", argv[0]); |
{ |
539 |
return; |
printf ("usage: %s value\n", argv[0]); |
540 |
} |
return; |
541 |
t = atoi(argv[1]); |
} |
542 |
if (t < 0) |
t = atoi (argv[1]); |
543 |
printf("%s: bad value\n", argv[1]); |
if (t < 0) |
544 |
else |
printf ("%s: bad value\n", argv[1]); |
545 |
rexmtval = t; |
else |
546 |
|
rexmtval = t; |
547 |
} |
} |
548 |
|
|
549 |
int maxtimeout = 5 * TIMEOUT; |
int maxtimeout = 5 * TIMEOUT; |
550 |
|
|
551 |
void |
void |
552 |
settimeout(argc, argv) |
settimeout (int argc, char *argv[]) |
|
int argc; |
|
|
char *argv[]; |
|
553 |
{ |
{ |
554 |
int t; |
int t; |
555 |
|
|
556 |
if (argc < 2) |
if (argc < 2) |
557 |
get_args ("Maximum-timeout", "(value) ", &argc, &argv); |
get_args ("Maximum-timeout", "(value) ", &argc, &argv); |
558 |
|
|
559 |
if (argc != 2) { |
if (argc != 2) |
560 |
printf("usage: %s value\n", argv[0]); |
{ |
561 |
return; |
printf ("usage: %s value\n", argv[0]); |
562 |
} |
return; |
563 |
t = atoi(argv[1]); |
} |
564 |
if (t < 0) |
t = atoi (argv[1]); |
565 |
printf("%s: bad value\n", argv[1]); |
if (t < 0) |
566 |
else |
printf ("%s: bad value\n", argv[1]); |
567 |
maxtimeout = t; |
else |
568 |
|
maxtimeout = t; |
569 |
} |
} |
570 |
|
|
571 |
void |
void |
572 |
status(argc, argv) |
status (int argc, char *argv[]) |
|
int argc; |
|
|
char *argv[]; |
|
573 |
{ |
{ |
574 |
if (connected) |
if (connected) |
575 |
printf("Connected to %s.\n", hostname); |
printf ("Connected to %s.\n", hostname); |
576 |
else |
else |
577 |
printf("Not connected.\n"); |
printf ("Not connected.\n"); |
578 |
printf("Mode: %s Verbose: %s Tracing: %s\n", mode, |
printf ("Mode: %s Verbose: %s Tracing: %s\n", mode, |
579 |
verbose ? "on" : "off", trace ? "on" : "off"); |
verbose ? "on" : "off", trace ? "on" : "off"); |
580 |
printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n", |
printf ("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n", |
581 |
rexmtval, maxtimeout); |
rexmtval, maxtimeout); |
582 |
} |
} |
583 |
|
|
584 |
void |
void |
585 |
intr() |
intr () |
586 |
{ |
{ |
587 |
|
signal (SIGALRM, SIG_IGN); |
588 |
signal(SIGALRM, SIG_IGN); |
alarm (0); |
589 |
alarm(0); |
longjmp (toplevel, -1); |
|
longjmp(toplevel, -1); |
|
590 |
} |
} |
591 |
|
|
592 |
char * |
char * |
593 |
tail(filename) |
tail (char *filename) |
|
char *filename; |
|
594 |
{ |
{ |
595 |
register char *s; |
register char *s; |
596 |
|
|
597 |
while (*filename) { |
while (*filename) |
598 |
s = strrchr (filename, '/'); |
{ |
599 |
if (s == NULL) |
s = strrchr (filename, '/'); |
600 |
break; |
if (s == NULL) |
601 |
if (s[1]) |
break; |
602 |
return (s + 1); |
if (s[1]) |
603 |
*s = '\0'; |
return (s + 1); |
604 |
} |
*s = '\0'; |
605 |
return (filename); |
} |
606 |
|
return filename; |
607 |
} |
} |
608 |
|
|
609 |
/* |
/* |
610 |
* Command parser. |
* Command parser. |
611 |
*/ |
*/ |
612 |
static void |
static void |
613 |
command() |
command () |
614 |
{ |
{ |
615 |
register struct cmd *c; |
register struct cmd *c; |
616 |
|
|
617 |
for (;;) { |
for (;;) |
618 |
printf("%s> ", prompt); |
{ |
619 |
if (fgets (line, sizeof line, stdin) == 0) { |
printf ("%s> ", prompt); |
620 |
if (feof(stdin)) { |
if (fgets (line, sizeof line, stdin) == 0) |
621 |
exit(0); |
{ |
622 |
} else { |
if (feof (stdin)) |
623 |
continue; |
exit (0); |
624 |
} |
else |
625 |
} |
continue; |
626 |
if (line[0] == 0) |
} |
627 |
continue; |
if (line[0] == 0) |
628 |
makeargv(); |
continue; |
629 |
if (margc == 0) |
makeargv (); |
630 |
continue; |
if (margc == 0) |
631 |
c = getcmd(margv[0]); |
continue; |
632 |
if (c == (struct cmd *)-1) { |
c = getcmd (margv[0]); |
633 |
printf("?Ambiguous command\n"); |
if (c == (struct cmd *) -1) |
634 |
continue; |
{ |
635 |
} |
printf ("?Ambiguous command\n"); |
636 |
if (c == 0) { |
continue; |
637 |
printf("?Invalid command\n"); |
} |
638 |
continue; |
if (c == 0) |
639 |
} |
{ |
640 |
(*c->handler)(margc, margv); |
printf ("?Invalid command\n"); |
641 |
|
continue; |
642 |
} |
} |
643 |
|
(*c->handler) (margc, margv); |
644 |
|
} |
645 |
} |
} |
646 |
|
|
647 |
struct cmd * |
struct cmd * |
648 |
getcmd(name) |
getcmd (register char *name) |
|
register char *name; |
|
649 |
{ |
{ |
650 |
register char *p, *q; |
register char *p, *q; |
651 |
register struct cmd *c, *found; |
register struct cmd *c, *found; |
652 |
register int nmatches, longest; |
register int nmatches, longest; |
653 |
|
|
654 |
longest = 0; |
longest = 0; |
655 |
nmatches = 0; |
nmatches = 0; |
656 |
found = 0; |
found = 0; |
657 |
for (c = cmdtab; (p = c->name) != NULL; c++) { |
for (c = cmdtab; (p = c->name) != NULL; c++) |
658 |
for (q = name; *q == *p++; q++) |
{ |
659 |
if (*q == 0) /* exact match? */ |
for (q = name; *q == *p++; q++) |
660 |
return (c); |
if (*q == 0) /* exact match? */ |
661 |
if (!*q) { /* the name was a prefix */ |
return (c); |
662 |
if (q - name > longest) { |
|
663 |
longest = q - name; |
if (!*q) |
664 |
nmatches = 1; |
{ /* the name was a prefix */ |
665 |
found = c; |
if (q - name > longest) |
666 |
} else if (q - name == longest) |
{ |
667 |
nmatches++; |
longest = q - name; |
668 |
} |
nmatches = 1; |
669 |
} |
found = c; |
670 |
if (nmatches > 1) |
} |
671 |
return ((struct cmd *)-1); |
else if (q - name == longest) |
672 |
return (found); |
nmatches++; |
673 |
|
} |
674 |
|
} |
675 |
|
if (nmatches > 1) |
676 |
|
return (struct cmd *) -1; |
677 |
|
return found; |
678 |
} |
} |
679 |
|
|
680 |
/* |
/* |
681 |
* Slice a string up into argc/argv. |
* Slice a string up into argc/argv. |
682 |
*/ |
*/ |
683 |
static void |
static void |
684 |
makeargv() |
makeargv () |
685 |
{ |
{ |
686 |
register char *cp; |
register char *cp; |
687 |
register char **argp = margv; |
register char **argp = margv; |
688 |
|
|
689 |
margc = 0; |
margc = 0; |
690 |
for (cp = line; *cp;) { |
for (cp = line; *cp;) |
691 |
while (isspace(*cp)) |
{ |
692 |
cp++; |
while (isspace (*cp)) |
693 |
if (*cp == '\0') |
cp++; |
694 |
break; |
if (*cp == '\0') |
695 |
*argp++ = cp; |
break; |
696 |
margc += 1; |
*argp++ = cp; |
697 |
while (*cp != '\0' && !isspace(*cp)) |
margc += 1; |
698 |
cp++; |
while (*cp != '\0' && !isspace (*cp)) |
699 |
if (*cp == '\0') |
cp++; |
700 |
break; |
if (*cp == '\0') |
701 |
*cp++ = '\0'; |
break; |
702 |
} |
*cp++ = '\0'; |
703 |
*argp++ = 0; |
} |
704 |
|
*argp++ = 0; |
705 |
} |
} |
706 |
|
|
707 |
void |
void |
708 |
quit(argc, argv) |
quit (int argc, char *argv[]) |
|
int argc; |
|
|
char *argv[]; |
|
709 |
{ |
{ |
710 |
|
exit (0); |
|
exit(0); |
|
711 |
} |
} |
712 |
|
|
713 |
/* |
/* |
714 |
* Help command. |
* Help command. |
715 |
*/ |
*/ |
716 |
void |
void |
717 |
help(argc, argv) |
help (int argc, char *argv[]) |
|
int argc; |
|
|
char *argv[]; |
|
718 |
{ |
{ |
719 |
register struct cmd *c; |
register struct cmd *c; |
720 |
|
|
721 |
if (argc == 1) { |
if (argc == 1) |
722 |
printf("Commands may be abbreviated. Commands are:\n\n"); |
{ |
723 |
for (c = cmdtab; c->name; c++) |
printf ("Commands may be abbreviated. Commands are:\n\n"); |
724 |
printf("%-*s\t%s\n", (int)HELPINDENT, c->name, c->help); |
for (c = cmdtab; c->name; c++) |
725 |
return; |
printf ("%-*s\t%s\n", (int) HELPINDENT, c->name, c->help); |
726 |
} |
return; |
727 |
while (--argc > 0) { |
} |
728 |
register char *arg; |
|
729 |
arg = *++argv; |
while (--argc > 0) |
730 |
c = getcmd(arg); |
{ |
731 |
if (c == (struct cmd *)-1) |
register char *arg; |
732 |
printf("?Ambiguous help command %s\n", arg); |
|
733 |
else if (c == (struct cmd *)0) |
arg = *++argv; |
734 |
printf("?Invalid help command %s\n", arg); |
c = getcmd (arg); |
735 |
else |
if (c == (struct cmd *) -1) |
736 |
printf("%s\n", c->help); |
printf ("?Ambiguous help command %s\n", arg); |
737 |
} |
else if (c == (struct cmd *) 0) |
738 |
|
printf ("?Invalid help command %s\n", arg); |
739 |
|
else |
740 |
|
printf ("%s\n", c->help); |
741 |
|
} |
742 |
} |
} |
743 |
|
|
744 |
void |
void |
745 |
settrace(argc, argv) |
settrace (int argc, char **argv) |
|
int argc; |
|
|
char **argv; |
|
746 |
{ |
{ |
747 |
trace = !trace; |
trace = !trace; |
748 |
printf("Packet tracing %s.\n", trace ? "on" : "off"); |
printf ("Packet tracing %s.\n", trace ? "on" : "off"); |
749 |
} |
} |
750 |
|
|
751 |
void |
void |
752 |
setverbose(argc, argv) |
setverbose (int argc, char **argv) |
|
int argc; |
|
|
char **argv; |
|
753 |
{ |
{ |
754 |
verbose = !verbose; |
verbose = !verbose; |
755 |
printf("Verbose mode %s.\n", verbose ? "on" : "off"); |
printf ("Verbose mode %s.\n", verbose ? "on" : "off"); |
756 |
} |
} |