1 /* utftp.c: simple tftp client to put files */
2 /*
3 * Copyright (C) 1999 Uwe Ohse
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 #include "config.h"
20 #include <sys/types.h>
21 #include <sys/ioctl.h>
22 #include <sys/stat.h>
23 #include <signal.h>
24 #include <fcntl.h>
25
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include "no_tftp.h"
29 #include <netdb.h>
30 #include <pwd.h>
31 #include <grp.h>
32
33 #include <setjmp.h>
34 #include <syslog.h>
35 #include <errno.h>
36 #include <ctype.h>
37 #include <string.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include "uogetopt.h"
41 #include "timselsysdep.h"
42 #include "nonblock.h"
43 #include "str2num.h"
44 #include "uostr.h"
45 #include "uoio.h"
46 #include "cdb.h"
47 #include "sys/wait.h"
48 #include "wildmat.h"
49 #include "tftplib.h"
50
51
52 static const char *argv0;
53 static char *opt_revision;
54 static uoio_t io_e;
55 static int opt_netascii=0;
56 static int opt_is_put=0;
57 static int opt_stop=0;
58 static int opt_duplicate_ack=0;
59 static unsigned long opt_force_timeout=0;
60 static unsigned long opt_segsize=512;
61 static unsigned long opt_timeout=5;
62 static unsigned long opt_retries=5;
63 static int opt_send_garbage=0;
64
65 static uogetopt_t myopts[]={
66 {'b',"blocksize", UOGO_ULONG,&opt_segsize,0, "use a blocksize different from the default 512.\n",0},
67 {'d',"duplicate-ack", UOGO_FLAG,&opt_duplicate_ack,1,
68 "duplicate ACKs sent\n",0},
69 {'f',"force-timeout", UOGO_ULONG,&opt_force_timeout,0,
70 "test server timeout handling\n"
71 "by sleeping some seconds","SECONDS"},
72 {'G',"garbage", UOGO_FLAG,&opt_send_garbage,1,
73 "send 2 garbage bytes after the request (test only)\n",0},
74 {'g',"get", UOGO_FLAG,&opt_is_put,0, "get file from server (default)\n",0},
75 {'n',"netascii", UOGO_FLAG,&opt_netascii,1, "use netascii conversion\n",0},
76 {'p',"put", UOGO_FLAG,&opt_is_put,1, "put file onto server\n",0},
77 {'r',"revision", UOGO_STRING,&opt_revision,1, "get or put revision REV\n","REV"},
78 {'R',"retries", UOGO_ULONG,&opt_retries,0, "number of retries on timeout (1..255, default 5).\n",0},
79 {'S',"stop", UOGO_FLAG,&opt_stop,1, "stop upload after the first block.\n",0},
80 {'t',"timeout", UOGO_ULONG,&opt_timeout,0, "timeout value (1..255, default 5).\n",0},
81 {0,0,0,0,0,0,0}
82 };
83
84 static void
die(int e,const char * where)85 die (int e, const char *where)
86 {
87 uoio_write_cstr (&io_e, argv0);
88 uoio_write_cstr (&io_e, ": ");
89 uoio_write_cstr (&io_e, where);
90 if (e) {
91 uoio_write_cstr (&io_e, ": ");
92 uoio_write_cstr (&io_e, strerror (e));
93 }
94 uoio_write_cstr (&io_e, "\n");
95 uoio_flush (&io_e);
96 _exit (1);
97 }
98
99
100 static void
usage(void)101 usage(void)
102 { die(0,"Give --help for usage information"); _exit(1); }
103
104 int
main(int argc,char ** argv)105 main (int argc, char **argv)
106 {
107 int port;
108 struct servent *sp;
109 char *p;
110 struct tftplib_ctrl *ctrl;
111 const char *target;
112 const char *source;
113 #ifdef HAVE_LIBEFENCE
114 /* hack around efence. Don't care about error messages here */
115 {int fd,fd2;void *waste;
116 if (-1==(fd=open("/dev/null",O_WRONLY))) _exit(1);
117 if (-1==(fd2=dup(2))) _exit(1);
118 if (-1==(dup2(fd,2))) _exit(1);
119 waste=malloc(1);
120 if (-1==(dup2(fd2,2))) _exit(1);
121 close(fd); close(fd2);
122 }
123 #endif
124
125 argv0 = strrchr (argv[0], '/');
126 if (argv0)
127 argv0++;
128 else
129 argv0 = argv[0];
130 uoio_assign_w (&io_e, 2, write, 0);
131 if (strstr(argv0,"put")) opt_is_put=1;
132
133 uogetopt ("utftp", PACKAGE, VERSION, &argc, argv, uogetopt_out,
134 "usage: utftp host[:port] filename-on-host [local-file-name]",
135 myopts,
136 " \"local-file-name\" defaults to \"filename-on-host\" without any directory part.\n"
137 " Report bugs to uwe-utftpd@bulkmail.ohse.de");
138
139 if (!argv[1] || !argv[2] || (argv[3] && argv[4]))
140 usage ();
141 if (opt_segsize<512) {
142 /* this can't work: if the server doesn't know about the blksize option it will send 512 byte blocks */
143 die(0,"blocksize to low. 512 is minimum");
144 }
145 #ifdef LOG_PERROR
146 openlog(argv0,LOG_PERROR|LOG_PID,LOG_USER);
147 #else
148 /* damned, HPUX 9.00 doesn't have LOG_PERROR. */
149 openlog(argv0,LOG_PID,LOG_USER);
150 #endif
151 if (opt_timeout<1 || opt_timeout >255) die(0,"illegal timeout value");
152 if (opt_retries<1 || opt_retries >255) die(0,"illegal retry value");
153
154 p=strchr(argv[1],':');
155 if (p) {
156 unsigned long ul;
157 *p++=0;
158 if (-1==str2ulong(p,&ul,0)) die(0,"not a valid port number");
159 port=ul;
160 if (ul!=(unsigned long) port) die(0,"not a valid port number");
161 port=htons((unsigned short)port);
162 } else {
163 sp = getservbyname ("tftp", "udp");
164 if (sp == 0) die (0, "udp/tftp: unknown service");
165 port=sp->s_port;
166 }
167
168 ctrl=tftp_setup_ctrl(0, opt_segsize);
169 if (!ctrl) die(0,"out of memory");
170 ctrl->netascii=opt_netascii;
171 ctrl->timeout=opt_timeout;
172 ctrl->retries=opt_retries;
173 ctrl->send_garbage=opt_send_garbage;
174 if (opt_revision) ctrl->revision=opt_revision;
175 source=argv[2];
176
177 target=argv[3];
178 if (!target || 0==strcmp(target,"--")) {
179 target=strrchr(source,'/');
180 if (target) target++;
181 else target=source;
182 }
183 ctrl->force_timeout=opt_force_timeout;
184 ctrl->force_stop=opt_stop;
185 ctrl->duplicate_ack=opt_duplicate_ack;
186
187 if (opt_is_put)
188 return tftp_send(argv[1],port,source,target,ctrl);
189 else
190 return tftp_receive(argv[1],port,source,target,ctrl);
191 }
192