]>
git.saurik.com Git - apple/network_cmds.git/blob - tftp.tproj/main.c
7e110cc5a4318d55b1726ec3a4f3882f55a49857
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * Copyright (c) 1983, 1993
26 * The Regents of the University of California. All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 static char copyright
[] =
60 "@(#) Copyright (c) 1983, 1993\n\
61 The Regents of the University of California. All rights reserved.\n";
64 /* Many bug fixes are from Jim Guyton <guyton@rand-unix> */
67 * TFTP User Program -- Command Interface.
69 #include <sys/types.h>
70 #include <sys/socket.h>
73 #include <netinet/in.h>
75 #include <arpa/inet.h>
89 #define TIMEOUT 5 /* secs between rexmt's */
91 struct sockaddr_in peeraddr
;
101 char *prompt
= "tftp";
106 void get
__P((int, char **));
107 void help
__P((int, char **));
108 void modecmd
__P((int, char **));
109 void put
__P((int, char **));
110 void quit
__P((int, char **));
111 void setascii
__P((int, char **));
112 void setbinary
__P((int, char **));
113 void setpeer
__P((int, char **));
114 void setrexmt
__P((int, char **));
115 void settimeout
__P((int, char **));
116 void settrace
__P((int, char **));
117 void setverbose
__P((int, char **));
118 void status
__P((int, char **));
120 static __dead
void command
__P((void));
122 static void getusage
__P((char *));
123 static void makeargv
__P((void));
124 static void putusage
__P((char *));
125 static void settftpmode
__P((char *));
127 #define HELPINDENT (sizeof("connect"))
132 void (*handler
) __P((int, char **));
135 char vhelp
[] = "toggle verbose mode";
136 char thelp
[] = "toggle packet tracing";
137 char chelp
[] = "connect to remote tftp";
138 char qhelp
[] = "exit tftp";
139 char hhelp
[] = "print help information";
140 char shelp
[] = "send file";
141 char rhelp
[] = "receive file";
142 char mhelp
[] = "set file transfer mode";
143 char sthelp
[] = "show current status";
144 char xhelp
[] = "set per-packet retransmission timeout";
145 char ihelp
[] = "set total retransmission timeout";
146 char ashelp
[] = "set mode to netascii";
147 char bnhelp
[] = "set mode to octet";
149 struct cmd cmdtab
[] = {
150 { "connect", chelp
, setpeer
},
151 { "mode", mhelp
, modecmd
},
152 { "put", shelp
, put
},
153 { "get", rhelp
, get
},
154 { "quit", qhelp
, quit
},
155 { "verbose", vhelp
, setverbose
},
156 { "trace", thelp
, settrace
},
157 { "status", sthelp
, status
},
158 { "binary", bnhelp
, setbinary
},
159 { "ascii", ashelp
, setascii
},
160 { "rexmt", xhelp
, setrexmt
},
161 { "timeout", ihelp
, settimeout
},
162 { "?", hhelp
, help
},
166 struct cmd
*getcmd();
176 struct sockaddr_in sin
;
178 sp
= getservbyname("tftp", "udp");
180 fprintf(stderr
, "tftp: udp/tftp: unknown service\n");
183 f
= socket(AF_INET
, SOCK_DGRAM
, 0);
185 perror("tftp: socket");
188 bzero((char *)&sin
, sizeof(sin
));
189 sin
.sin_family
= AF_INET
;
190 if (bind(f
, (struct sockaddr
*)&sin
, sizeof(sin
)) < 0) {
191 perror("tftp: bind");
194 strcpy(mode
, "netascii");
195 signal(SIGINT
, intr
);
197 if (setjmp(toplevel
) != 0)
201 if (setjmp(toplevel
) != 0)
213 struct hostent
*host
;
216 strcpy(line
, "Connect ");
218 fgets(&line
[strlen(line
)], BUFSIZ
-strlen(line
)-1, stdin
);
224 printf("usage: %s host-name [port]\n", argv
[0]);
227 host
= gethostbyname(argv
[1]);
229 peeraddr
.sin_family
= host
->h_addrtype
;
230 bcopy(host
->h_addr
, &peeraddr
.sin_addr
, host
->h_length
);
231 strcpy(hostname
, host
->h_name
);
233 peeraddr
.sin_family
= AF_INET
;
234 peeraddr
.sin_addr
.s_addr
= inet_addr(argv
[1]);
235 if (peeraddr
.sin_addr
.s_addr
== -1) {
237 printf("%s: unknown host\n", argv
[1]);
240 strcpy(hostname
, argv
[1]);
244 port
= atoi(argv
[2]);
246 printf("%s: bad port number\n", argv
[2]);
259 { "ascii", "netascii" },
260 { "netascii", "netascii" },
261 { "binary", "octet" },
262 { "image", "octet" },
263 { "octet", "octet" },
264 /* { "mail", "mail" }, */
273 register struct modes
*p
;
277 printf("Using %s mode to transfer files.\n", mode
);
281 for (p
= modes
; p
->m_name
; p
++)
282 if (strcmp(argv
[1], p
->m_name
) == 0)
285 settftpmode(p
->m_mode
);
288 printf("%s: unknown mode\n", argv
[1]);
289 /* drop through and print usage message */
292 printf("usage: %s [", argv
[0]);
294 for (p
= modes
; p
->m_name
; p
++) {
295 printf("%s%s", sep
, p
->m_name
);
304 setbinary(argc
, argv
)
309 settftpmode("octet");
318 settftpmode("netascii");
325 strcpy(mode
, newmode
);
327 printf("mode set to %s\n", mode
);
341 register char *cp
, *targ
;
344 strcpy(line
, "send ");
346 fgets(&line
[strlen(line
)], BUFSIZ
-strlen(line
)-1, stdin
);
355 targ
= argv
[argc
- 1];
356 if (index(argv
[argc
- 1], ':')) {
360 for (n
= 1; n
< argc
- 1; n
++)
361 if (index(argv
[n
], ':')) {
366 targ
= index(cp
, ':');
368 hp
= gethostbyname(cp
);
370 fprintf(stderr
, "tftp: %s: ", cp
);
371 herror((char *)NULL
);
374 bcopy(hp
->h_addr
, (caddr_t
)&peeraddr
.sin_addr
, hp
->h_length
);
375 peeraddr
.sin_family
= hp
->h_addrtype
;
377 strcpy(hostname
, hp
->h_name
);
380 printf("No target machine specified.\n");
384 cp
= argc
== 2 ? tail(targ
) : argv
[1];
385 fd
= open(cp
, O_RDONLY
);
387 fprintf(stderr
, "tftp: "); perror(cp
);
391 printf("putting %s to %s:%s [%s]\n",
392 cp
, hostname
, targ
, mode
);
393 peeraddr
.sin_port
= port
;
394 tftp_sendfile(fd
, targ
, mode
);
397 /* this assumes the target is a directory */
398 /* on a remote unix system. hmmmm. */
399 cp
= index(targ
, '\0');
401 for (n
= 1; n
< argc
- 1; n
++) {
402 strcpy(cp
, tail(argv
[n
]));
403 fd
= open(argv
[n
], O_RDONLY
);
405 fprintf(stderr
, "tftp: "); perror(argv
[n
]);
409 printf("putting %s to %s:%s [%s]\n",
410 argv
[n
], hostname
, targ
, mode
);
411 peeraddr
.sin_port
= port
;
412 tftp_sendfile(fd
, targ
, mode
);
420 printf("usage: %s file ... host:target, or\n", s
);
421 printf(" %s file ... target (when already connected)\n", s
);
438 strcpy(line
, "get ");
440 fgets(&line
[strlen(line
)], BUFSIZ
-strlen(line
)-1, stdin
);
450 for (n
= 1; n
< argc
; n
++)
451 if (index(argv
[n
], ':') == 0) {
456 for (n
= 1; n
< argc
; n
++) {
457 src
= index(argv
[n
], ':');
464 hp
= gethostbyname(argv
[n
]);
466 fprintf(stderr
, "tftp: %s: ", argv
[n
]);
467 herror((char *)NULL
);
470 bcopy(hp
->h_addr
, (caddr_t
)&peeraddr
.sin_addr
,
472 peeraddr
.sin_family
= hp
->h_addrtype
;
474 strcpy(hostname
, hp
->h_name
);
477 cp
= argc
== 3 ? argv
[2] : tail(src
);
478 fd
= creat(cp
, 0644);
480 fprintf(stderr
, "tftp: "); perror(cp
);
484 printf("getting from %s:%s to %s [%s]\n",
485 hostname
, src
, cp
, mode
);
486 peeraddr
.sin_port
= port
;
487 recvfile(fd
, src
, mode
);
490 cp
= tail(src
); /* new .. jdg */
491 fd
= creat(cp
, 0644);
493 fprintf(stderr
, "tftp: "); perror(cp
);
497 printf("getting from %s:%s to %s [%s]\n",
498 hostname
, src
, cp
, mode
);
499 peeraddr
.sin_port
= port
;
500 recvfile(fd
, src
, mode
);
508 printf("usage: %s host:file host:file ... file, or\n", s
);
509 printf(" %s file file ... file if connected\n", s
);
512 int rexmtval
= TIMEOUT
;
522 strcpy(line
, "Rexmt-timeout ");
524 fgets(&line
[strlen(line
)], BUFSIZ
-strlen(line
)-1, stdin
);
530 printf("usage: %s value\n", argv
[0]);
535 printf("%s: bad value\n", argv
[1]);
540 int maxtimeout
= 5 * TIMEOUT
;
543 settimeout(argc
, argv
)
550 strcpy(line
, "Maximum-timeout ");
552 fgets(&line
[strlen(line
)], BUFSIZ
-strlen(line
)-1, stdin
);
558 printf("usage: %s value\n", argv
[0]);
563 printf("%s: bad value\n", argv
[1]);
574 printf("Connected to %s.\n", hostname
);
576 printf("Not connected.\n");
577 printf("Mode: %s Verbose: %s Tracing: %s\n", mode
,
578 verbose
? "on" : "off", trace
? "on" : "off");
579 printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n",
580 rexmtval
, maxtimeout
);
587 signal(SIGALRM
, SIG_IGN
);
589 longjmp(toplevel
, -1);
599 s
= rindex(filename
, '/');
615 register struct cmd
*c
;
618 printf("%s> ", prompt
);
619 if (fgets(line
, BUFSIZ
-1, stdin
) == 0) {
631 c
= getcmd(margv
[0]);
632 if (c
== (struct cmd
*)-1) {
633 printf("?Ambiguous command\n");
637 printf("?Invalid command\n");
640 (*c
->handler
)(margc
, margv
);
648 register char *p
, *q
;
649 register struct cmd
*c
, *found
;
650 register int nmatches
, longest
;
655 for (c
= cmdtab
; (p
= c
->name
) != NULL
; c
++) {
656 for (q
= name
; *q
== *p
++; q
++)
657 if (*q
== 0) /* exact match? */
659 if (!*q
) { /* the name was a prefix */
660 if (q
- name
> longest
) {
664 } else if (q
- name
== longest
)
669 return ((struct cmd
*)-1);
674 * Slice a string up into argc/argv.
680 register char **argp
= margv
;
683 for (cp
= line
; *cp
;) {
690 while (*cp
!= '\0' && !isspace(*cp
))
716 register struct cmd
*c
;
719 printf("Commands may be abbreviated. Commands are:\n\n");
720 for (c
= cmdtab
; c
->name
; c
++)
721 printf("%-*s\t%s\n", (int)HELPINDENT
, c
->name
, c
->help
);
728 if (c
== (struct cmd
*)-1)
729 printf("?Ambiguous help command %s\n", arg
);
730 else if (c
== (struct cmd
*)0)
731 printf("?Invalid help command %s\n", arg
);
733 printf("%s\n", c
->help
);
743 printf("Packet tracing %s.\n", trace
? "on" : "off");
747 setverbose(argc
, argv
)
752 printf("Verbose mode %s.\n", verbose
? "on" : "off");