]>
git.saurik.com Git - apple/network_cmds.git/blob - tftp.tproj/main.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1983, 1993
27 * The Regents of the University of California. All rights reserved.
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. All advertising materials mentioning features or use of this software
38 * must display the following acknowledgement:
39 * This product includes software developed by the University of
40 * California, Berkeley and its contributors.
41 * 4. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 static char copyright
[] =
61 "@(#) Copyright (c) 1983, 1993\n\
62 The Regents of the University of California. All rights reserved.\n";
65 /* Many bug fixes are from Jim Guyton <guyton@rand-unix> */
68 * TFTP User Program -- Command Interface.
70 #include <sys/types.h>
71 #include <sys/socket.h>
74 #include <netinet/in.h>
76 #include <arpa/inet.h>
90 #define TIMEOUT 5 /* secs between rexmt's */
92 struct sockaddr_in peeraddr
;
102 char *prompt
= "tftp";
107 void get
__P((int, char **));
108 void help
__P((int, char **));
109 void modecmd
__P((int, char **));
110 void put
__P((int, char **));
111 void quit
__P((int, char **));
112 void setascii
__P((int, char **));
113 void setbinary
__P((int, char **));
114 void setpeer
__P((int, char **));
115 void setrexmt
__P((int, char **));
116 void settimeout
__P((int, char **));
117 void settrace
__P((int, char **));
118 void setverbose
__P((int, char **));
119 void status
__P((int, char **));
121 static __dead
void command
__P((void));
123 static void getusage
__P((char *));
124 static void makeargv
__P((void));
125 static void putusage
__P((char *));
126 static void settftpmode
__P((char *));
128 #define HELPINDENT (sizeof("connect"))
133 void (*handler
) __P((int, char **));
136 char vhelp
[] = "toggle verbose mode";
137 char thelp
[] = "toggle packet tracing";
138 char chelp
[] = "connect to remote tftp";
139 char qhelp
[] = "exit tftp";
140 char hhelp
[] = "print help information";
141 char shelp
[] = "send file";
142 char rhelp
[] = "receive file";
143 char mhelp
[] = "set file transfer mode";
144 char sthelp
[] = "show current status";
145 char xhelp
[] = "set per-packet retransmission timeout";
146 char ihelp
[] = "set total retransmission timeout";
147 char ashelp
[] = "set mode to netascii";
148 char bnhelp
[] = "set mode to octet";
150 struct cmd cmdtab
[] = {
151 { "connect", chelp
, setpeer
},
152 { "mode", mhelp
, modecmd
},
153 { "put", shelp
, put
},
154 { "get", rhelp
, get
},
155 { "quit", qhelp
, quit
},
156 { "verbose", vhelp
, setverbose
},
157 { "trace", thelp
, settrace
},
158 { "status", sthelp
, status
},
159 { "binary", bnhelp
, setbinary
},
160 { "ascii", ashelp
, setascii
},
161 { "rexmt", xhelp
, setrexmt
},
162 { "timeout", ihelp
, settimeout
},
163 { "?", hhelp
, help
},
167 struct cmd
*getcmd();
177 struct sockaddr_in sin
;
179 sp
= getservbyname("tftp", "udp");
181 fprintf(stderr
, "tftp: udp/tftp: unknown service\n");
184 f
= socket(AF_INET
, SOCK_DGRAM
, 0);
186 perror("tftp: socket");
189 bzero((char *)&sin
, sizeof(sin
));
190 sin
.sin_family
= AF_INET
;
191 if (bind(f
, (struct sockaddr
*)&sin
, sizeof(sin
)) < 0) {
192 perror("tftp: bind");
195 strcpy(mode
, "netascii");
196 signal(SIGINT
, intr
);
198 if (setjmp(toplevel
) != 0)
202 if (setjmp(toplevel
) != 0)
214 struct hostent
*host
;
217 strcpy(line
, "Connect ");
219 fgets(&line
[strlen(line
)], BUFSIZ
-strlen(line
)-1, stdin
);
225 printf("usage: %s host-name [port]\n", argv
[0]);
228 host
= gethostbyname(argv
[1]);
230 peeraddr
.sin_family
= host
->h_addrtype
;
231 bcopy(host
->h_addr
, &peeraddr
.sin_addr
, host
->h_length
);
232 strcpy(hostname
, host
->h_name
);
234 peeraddr
.sin_family
= AF_INET
;
235 peeraddr
.sin_addr
.s_addr
= inet_addr(argv
[1]);
236 if (peeraddr
.sin_addr
.s_addr
== -1) {
238 printf("%s: unknown host\n", argv
[1]);
241 strcpy(hostname
, argv
[1]);
245 port
= atoi(argv
[2]);
247 printf("%s: bad port number\n", argv
[2]);
260 { "ascii", "netascii" },
261 { "netascii", "netascii" },
262 { "binary", "octet" },
263 { "image", "octet" },
264 { "octet", "octet" },
265 /* { "mail", "mail" }, */
274 register struct modes
*p
;
278 printf("Using %s mode to transfer files.\n", mode
);
282 for (p
= modes
; p
->m_name
; p
++)
283 if (strcmp(argv
[1], p
->m_name
) == 0)
286 settftpmode(p
->m_mode
);
289 printf("%s: unknown mode\n", argv
[1]);
290 /* drop through and print usage message */
293 printf("usage: %s [", argv
[0]);
295 for (p
= modes
; p
->m_name
; p
++) {
296 printf("%s%s", sep
, p
->m_name
);
305 setbinary(argc
, argv
)
310 settftpmode("octet");
319 settftpmode("netascii");
326 strcpy(mode
, newmode
);
328 printf("mode set to %s\n", mode
);
342 register char *cp
, *targ
;
345 strcpy(line
, "send ");
347 fgets(&line
[strlen(line
)], BUFSIZ
-strlen(line
)-1, stdin
);
356 targ
= argv
[argc
- 1];
357 if (index(argv
[argc
- 1], ':')) {
361 for (n
= 1; n
< argc
- 1; n
++)
362 if (index(argv
[n
], ':')) {
367 targ
= index(cp
, ':');
369 hp
= gethostbyname(cp
);
371 fprintf(stderr
, "tftp: %s: ", cp
);
372 herror((char *)NULL
);
375 bcopy(hp
->h_addr
, (caddr_t
)&peeraddr
.sin_addr
, hp
->h_length
);
376 peeraddr
.sin_family
= hp
->h_addrtype
;
378 strcpy(hostname
, hp
->h_name
);
381 printf("No target machine specified.\n");
385 cp
= argc
== 2 ? tail(targ
) : argv
[1];
386 fd
= open(cp
, O_RDONLY
);
388 fprintf(stderr
, "tftp: "); perror(cp
);
392 printf("putting %s to %s:%s [%s]\n",
393 cp
, hostname
, targ
, mode
);
394 peeraddr
.sin_port
= port
;
395 tftp_sendfile(fd
, targ
, mode
);
398 /* this assumes the target is a directory */
399 /* on a remote unix system. hmmmm. */
400 cp
= index(targ
, '\0');
402 for (n
= 1; n
< argc
- 1; n
++) {
403 strcpy(cp
, tail(argv
[n
]));
404 fd
= open(argv
[n
], O_RDONLY
);
406 fprintf(stderr
, "tftp: "); perror(argv
[n
]);
410 printf("putting %s to %s:%s [%s]\n",
411 argv
[n
], hostname
, targ
, mode
);
412 peeraddr
.sin_port
= port
;
413 tftp_sendfile(fd
, targ
, mode
);
421 printf("usage: %s file ... host:target, or\n", s
);
422 printf(" %s file ... target (when already connected)\n", s
);
439 strcpy(line
, "get ");
441 fgets(&line
[strlen(line
)], BUFSIZ
-strlen(line
)-1, stdin
);
451 for (n
= 1; n
< argc
; n
++)
452 if (index(argv
[n
], ':') == 0) {
457 for (n
= 1; n
< argc
; n
++) {
458 src
= index(argv
[n
], ':');
465 hp
= gethostbyname(argv
[n
]);
467 fprintf(stderr
, "tftp: %s: ", argv
[n
]);
468 herror((char *)NULL
);
471 bcopy(hp
->h_addr
, (caddr_t
)&peeraddr
.sin_addr
,
473 peeraddr
.sin_family
= hp
->h_addrtype
;
475 strcpy(hostname
, hp
->h_name
);
478 cp
= argc
== 3 ? argv
[2] : tail(src
);
479 fd
= creat(cp
, 0644);
481 fprintf(stderr
, "tftp: "); perror(cp
);
485 printf("getting from %s:%s to %s [%s]\n",
486 hostname
, src
, cp
, mode
);
487 peeraddr
.sin_port
= port
;
488 recvfile(fd
, src
, mode
);
491 cp
= tail(src
); /* new .. jdg */
492 fd
= creat(cp
, 0644);
494 fprintf(stderr
, "tftp: "); perror(cp
);
498 printf("getting from %s:%s to %s [%s]\n",
499 hostname
, src
, cp
, mode
);
500 peeraddr
.sin_port
= port
;
501 recvfile(fd
, src
, mode
);
509 printf("usage: %s host:file host:file ... file, or\n", s
);
510 printf(" %s file file ... file if connected\n", s
);
513 int rexmtval
= TIMEOUT
;
523 strcpy(line
, "Rexmt-timeout ");
525 fgets(&line
[strlen(line
)], BUFSIZ
-strlen(line
)-1, stdin
);
531 printf("usage: %s value\n", argv
[0]);
536 printf("%s: bad value\n", argv
[1]);
541 int maxtimeout
= 5 * TIMEOUT
;
544 settimeout(argc
, argv
)
551 strcpy(line
, "Maximum-timeout ");
553 fgets(&line
[strlen(line
)], BUFSIZ
-strlen(line
)-1, stdin
);
559 printf("usage: %s value\n", argv
[0]);
564 printf("%s: bad value\n", argv
[1]);
575 printf("Connected to %s.\n", hostname
);
577 printf("Not connected.\n");
578 printf("Mode: %s Verbose: %s Tracing: %s\n", mode
,
579 verbose
? "on" : "off", trace
? "on" : "off");
580 printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n",
581 rexmtval
, maxtimeout
);
588 signal(SIGALRM
, SIG_IGN
);
590 longjmp(toplevel
, -1);
600 s
= rindex(filename
, '/');
616 register struct cmd
*c
;
619 printf("%s> ", prompt
);
620 if (fgets(line
, BUFSIZ
-1, stdin
) == 0) {
632 c
= getcmd(margv
[0]);
633 if (c
== (struct cmd
*)-1) {
634 printf("?Ambiguous command\n");
638 printf("?Invalid command\n");
641 (*c
->handler
)(margc
, margv
);
649 register char *p
, *q
;
650 register struct cmd
*c
, *found
;
651 register int nmatches
, longest
;
656 for (c
= cmdtab
; (p
= c
->name
) != NULL
; c
++) {
657 for (q
= name
; *q
== *p
++; q
++)
658 if (*q
== 0) /* exact match? */
660 if (!*q
) { /* the name was a prefix */
661 if (q
- name
> longest
) {
665 } else if (q
- name
== longest
)
670 return ((struct cmd
*)-1);
675 * Slice a string up into argc/argv.
681 register char **argp
= margv
;
684 for (cp
= line
; *cp
;) {
691 while (*cp
!= '\0' && !isspace(*cp
))
717 register struct cmd
*c
;
720 printf("Commands may be abbreviated. Commands are:\n\n");
721 for (c
= cmdtab
; c
->name
; c
++)
722 printf("%-*s\t%s\n", (int)HELPINDENT
, c
->name
, c
->help
);
729 if (c
== (struct cmd
*)-1)
730 printf("?Ambiguous help command %s\n", arg
);
731 else if (c
== (struct cmd
*)0)
732 printf("?Invalid help command %s\n", arg
);
734 printf("%s\n", c
->help
);
744 printf("Packet tracing %s.\n", trace
? "on" : "off");
748 setverbose(argc
, argv
)
753 printf("Verbose mode %s.\n", verbose
? "on" : "off");