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