1 /* Author: Hagen Fritsch <fritsch+wput-src@in.tum.de>
2 (C) 2002-2006 by Hagen Fritsch
3
4 This file is part of wput.
5
6 This programm is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The wput is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
15 You should have received a copy of the GNU General Public
16 License along with the wput; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
19
20 /* command-line-parsing routines and core control functions */
21
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <errno.h>
25 #ifndef WIN32
26 # include <netinet/in.h>
27 #endif
28
29 #include "wput.h"
30 #include "netrc.h"
31
32 #ifdef WIN32
33 # include "getopt/getopt.h"
34 #else
35 # define _GNU_SOURCE
36 # ifdef HAVE_GETOPT_H
37 # include <getopt.h>
38 # else
39 # ifdef HAVE_GNUGETOPT_GETOPT_H
40 # include <gnugetopt/getopt.h>
41 # else
42 # include "getopt/getopt.h"
43 # endif
44 # endif
45 #endif
46
47 #ifdef ENABLE_NLS
48 # ifdef HAVE_LOCALE_H
49 # include <locale.h>
50 # endif
51 #endif
52
53 #include "progress.h"
54 #include "_queue.h"
55 #include "utils.h"
56
57 extern char *optarg;
58
59 #ifdef WIN32
60 const static char * version = "0.6.2-w32";
61 #else
62 const static char * version = "0.6.2";
63 #endif
64
65 _fsession * fsession_queue_entry_point = NULL;
66
67 void commandlineoptions(int argc, char * argv[]);
68 int start_fsession();
69 int start_ftp();
70 int start_recur_ftp();
71 void read_netrc_file(void);
72 opt_t opt;
73
main(int argc,char * argv[])74 int main(int argc, char *argv[]){
75 #ifdef WIN32
76 /* i don't know why, but if i call WSAStartup just once, there is an
77 * error when initialising sockets later (10093). quite strange and
78 * took me quite a while to figure out *dang* */
79 WSADATA sa;
80 if(WSAStartup(MAKEWORD(2,2),&sa) != 0) {
81 fprintf(stderr, "1st: Error Initializing Windows Socket DLL (WSAStartup Failed).\nError-Code: 0x%x", GetLastError());
82 exit(4);
83 }
84 if(WSAStartup(MAKEWORD(2,2),&sa) != 0) {
85 fprintf(stderr, "2nd: Error Initializing Windows Socket DLL (WSAStartup Failed).\nError-Code: 0x%x", GetLastError());
86 exit(4);
87 }
88 #endif
89 signal(SIGPIPE, SIG_IGN);
90 /* i18n */
91 #ifdef ENABLE_NLS
92 /* LC_MESSAGES is enough as the only thing that is done is
93 * the translation of text-messages */
94 # ifdef LC_MESSAGES
95 setlocale (LC_MESSAGES, "");
96 setlocale (LC_CTYPE, "");
97 # else
98 setlocale (LC_ALL, "");
99 # endif
100 /* Set the text message domain. */
101 bindtextdomain ("wput", LOCALEDIR);
102 textdomain ("wput");
103 #endif
104
105
106 /* initialise global options and set default values */
107 memset(&opt, 0, sizeof(opt));
108
109 /* create the ssl framework */
110 #ifdef HAVE_SSL
111 SSL_library_init();
112 #endif
113
114 opt.sbuf = malloc(82);
115 opt.retry = -1;
116 opt.retry_interval = 10;
117 opt.time_deviation = 10;
118 opt.binary = TYPE_UNDEFINED;
119 opt.output = stdout;
120
121 opt.verbose = vNORMAL;
122 opt.bindaddr = INADDR_ANY;
123 opt.barstyle = 1;
124 opt.ps.bind = 1;
125 opt.session_start = wtimer_alloc();
126
127 opt.resume_table.small_large = RESUME_TABLE_UPLOAD;
128 opt.resume_table.large_large = RESUME_TABLE_SKIP;
129 opt.resume_table.large_small = RESUME_TABLE_RESUME;
130
131 opt.email_address = cpy("wput@localhost.com");
132
133 if(!strncmp(&argv[0][strlen(argv[0])-4], "wdel", 5))
134 opt.wdel = 1;
135
136 /* env overrides home overrides system wputrc */
137 #ifdef SYSTEM_WPUTRC
138 readwputrc(SYSTEM_WPUTRC);
139 #endif
140 readwputrc(NULL); /*homedir*/
141 readwputrc(getenv("WPUTRC"));
142
143 parse_proxy(getenv("ftp_proxy"));
144
145 read_netrc_file();
146 read_password_file(getenv("PASSWORDFILE"));
147
148 wtimer_reset(opt.session_start);
149
150 commandlineoptions(argc, argv);
151
152 #ifndef WIN32
153 /* If we are still at stdout, then redirect output to 'wput-log'. */
154 if(opt.background) {
155 if(opt.output == stdout) {
156 printout(vLESS, _("Resuming in background. Logging output to 'wput-log'.\n"));
157 opt.output = fopen("wput-log", "a");
158 if(opt.output == NULL) { perror(_("Unable to open logfile")); exit(4); }
159 opt.barstyle = 0;
160 } else
161 puts("Resuming in background.\n");
162
163 if(fork() > 0) exit(0);
164
165 if(opt.input_pipe) {
166 printout(vNORMAL, _("Warning: "));
167 printout(vNORMAL, _("background-mode might not work correctly, if the input-pipe needs to read from stdin (like cat -).\n"));
168 }
169 if(opt.input != stdin) {
170 /* create a new session and release the console-descriptors... */
171 setsid ();
172 freopen ("/dev/null", "r", stdin);
173 freopen ("/dev/null", "w", stdout);
174 freopen ("/dev/null", "w", stderr);
175 } else {
176 printout(vNORMAL, _("Warning: "));
177 printout(vNORMAL, _("reading urls from stdin, while running in background-mode is not reliable.\n"));
178 }
179 }
180 #endif
181 /* this sets the barstyle to the old one unless wput runs on a tty */
182 if(opt.barstyle && !isatty( fileno(stdout) ))
183 opt.barstyle = 0;
184
185 if((opt.ps.ip == 0 || opt.ps.port == 0) && opt.ps.type != PROXY_OFF) {
186 printout(vNORMAL, _("Warning: "));
187 printout(vNORMAL, _("Ignoring request to turn proxy-usage on, since no proxy is configured.\n"));
188 opt.ps.type = PROXY_OFF;
189 }
190
191 /* WDEL separate the urls from a potential file and ensure that the urls end in a '/' */
192 if(opt.wdel) separate_urls();
193
194 /* WPUT process all url/file combinations that were supplied by commandline */
195 if(!opt.wdel) queue_process(0);
196
197 /* read URLs from input-file */
198 if(opt.input != 0) read_urls();
199
200 /* WPUT if there are lonely files remaining, give them the last (user-supplied) url */
201 if(!opt.wdel) process_missing();
202 else queue_process(0); /* later process in WDEL */
203
204 /* now we've everything we need or are already done */
205 if(opt.sorturls) {
206 printout(vDEBUG, "Transmitting sorted fsessions\n");
207 while(fsession_queue_entry_point != NULL) {
208 int res = fsession_process_file(fsession_queue_entry_point, opt.curftp);
209 if(res == -1) opt.failed++;
210 else if(res == -2) opt.skipped++;
211 opt.curftp = fsession_queue_entry_point->ftp;
212 free_fsession(fsession_queue_entry_point);
213 }
214 }
215
216 /* finally close any existing connections */
217 if(opt.curftp) ftp_quit(opt.curftp);
218
219 if(opt.transfered == 0 && opt.skipped == 0 && opt.failed == 0)
220 printout(vNORMAL, _("Nothing done. Try `%s --help'.\n"), argv[0]);
221 else
222 printout(vNORMAL, _("FINISHED --%s--\n"), time_str());
223
224 if(opt.transfered > 0) {
225 if(!opt.wdel) {
226 printout(vNORMAL, opt.transfered == 1 ?
227 _("Transfered %s bytes in %d file at %s\n") :
228 _("Transfered %s bytes in %d files at %s\n"),
229 legible(opt.transfered_bytes),
230 opt.transfered,
231 calculate_transfer_rate(
232 wtimer_elapsed(opt.session_start),
233 opt.transfered_bytes,
234 0)
235 );
236 } else
237 printout(vNORMAL, opt.transfered == 1 ?
238 _("Deleted %d file\n") :
239 _("Deleted %d files\n"),
240 opt.transfered);
241
242 }
243
244 if(opt.skipped > 0)
245 printout(vNORMAL, opt.skipped == 1 ? _("Skipped %d file.\n") : _("Skipped %d files.\n"), opt.skipped);
246 if(opt.failed > 0)
247 printout(vNORMAL, !opt.wdel ?
248 (opt.failed == 1 ? _("Transmission of %d file failed.\n") : _("Transmission of %d files failed.\n")) :
249 (opt.failed == 1 ? _("Deletion of %d file failed.\n") : _("Deletion of %d files failed.\n")), opt.failed);
250
251 /* clean up */
252 free(opt.session_start);
253 free(opt.email_address);
254 free(opt.sbuf);
255
256 if(opt.ps.pass) free(opt.ps.pass);
257 if(opt.ps.user) free(opt.ps.user);
258 if(opt.last_url) free(opt.last_url);
259
260 if(opt.pl) password_list_free(opt.pl);
261 skiplist_free(opt.skipdlist);
262
263 #ifdef MEMDBG
264 print_unfree();
265 #endif
266
267 return ((opt.failed != 0) * 2) | (opt.skipped != 0);
268 }
269 /* read urls/files from input-file as though they were supplied as command-line-arguments */
read_urls(void)270 int read_urls(void) {
271 char * url;
272 char * p;
273 while ((url = p = read_line(opt.input))) {
274 /* skip spaces and skip lines beginning with a # */
275 printout(vDEBUG, "read `%s'\n", p);
276
277 while( isspace(*p) ) p++;
278 if(*p == '#') {
279 free(url);
280 continue;
281 }
282
283 /* just foolproof check for \r\n */
284 if(url[strlen(url)-2] == '\r')
285 url[strlen(url)-2] = 0;
286 url[strlen(url)-1] = 0;
287
288 if(!strncmp(p, "ftp://", 6))
289 opt.wdel ? wdel_queue_add_entry(NULL, cpy(p)) : queue_add_url(cpy(p));
290 else
291 opt.wdel ? wdel_queue_add_file(cpy(p)) : queue_add_file(cpy(p));
292
293 free(url);
294 /* process anything that's already complete */
295 queue_process(0);
296 }
297 return 0;
298 }
299 /* ugly code to parse through the wputrc-options */
set_option(char * com,char * val)300 int set_option(char * com, char * val) {
301 printout(vDEBUG, "Setting option '%s' to '%s'\n", com, val);
302
303 switch(*com) {
304 case '1':
305 case '2':
306 if(!strncmp(com, "2_1", 4)) {
307 if(!strncasecmp(val, "SKIP", 5))
308 opt.resume_table.large_small = RESUME_TABLE_SKIP;
309 else
310 opt.resume_table.large_small = !strncasecmp(val, "UPLOAD", 7) ? RESUME_TABLE_UPLOAD : RESUME_TABLE_RESUME;
311 } else if(!strncmp(com, "2_2", 4))
312 opt.resume_table.large_large = !strncasecmp(val, "UPLOAD", 7) ? RESUME_TABLE_UPLOAD : RESUME_TABLE_SKIP;
313 else if(!strncmp(com, "1_2", 4))
314 opt.resume_table.small_large = !strncasecmp(val, "UPLOAD", 7) ? RESUME_TABLE_UPLOAD : RESUME_TABLE_SKIP;
315 else
316 return -1;
317 return 0;
318 case 'b':
319 if(!strncasecmp(com, "bind-address", 13)) {
320 if(get_ip_addr(optarg, &opt.bindaddr) == -1) {
321 printout(vMORE, _("Error: "));
322 printout(vMORE, _("`%s' could not be resolved. "), optarg);
323 printout(vLESS, _("Exiting.\n"));
324 exit(4);
325 }
326 return 0;
327 } else return -1;
328 case 'c':
329 if(!strncasecmp(com, "connection_mode", 16)) {
330 if(!strncasecmp(val, "pasv", 5)) {
331 opt.portmode = 0;
332 } else if(!strncasecmp(val, "port", 4)) {
333 opt.portmode = 1;
334 } else return -1;
335 }
336 else if(!strncasecmp(com, "chmod", 6)) {
337 int invalid = 0;
338 if(opt.wdel) return 0; /* disabled for wdel */
339 if(strlen(val) == 3) {
340 int modecounter;
341 for (modecounter = 0; modecounter < 3; modecounter++) {
342 if (val[modecounter] < '0' || val[modecounter] > '7') {
343 invalid = 1;
344 break;
345 }
346 }
347 } else {
348 invalid = 1;
349 }
350 if (!invalid)
351 opt.chmod = val;
352 else return -2;
353 } else return -1;
354 return 0;
355 #ifdef HAVE_SSL
356 case 'f':
357 if(!strncmp(com, "force_tls", 9))
358 opt.tls = !strncasecmp(val, "on", 3);
359 else
360 return -1;
361 return 0;
362 #endif
363 case 'm':
364 if(!strncmp(com, "email_address", 13))
365 opt.email_address = cpy(val);
366 else return -1;
367 return 0;
368 case 'p':
369 if(!strncasecmp(com, "proxy", 6)) {
370 if(!strncmp(val, "http", 5))
371 opt.ps.type = PROXY_HTTP;
372 else if(!strncasecmp(val, "socks", 6))
373 opt.ps.type = PROXY_SOCKS;
374 else
375 opt.ps.type = PROXY_OFF;
376 }
377 else if(!strncasecmp(com, "proxy_host", 11)) {
378 if(get_ip_addr(val, &opt.ps.ip) == -1) {
379 printout(vLESS, _("Warning: "));
380 printout(vLESS, _("`%s' could not be resolved. "), val);
381 printout(vLESS, _("Disabling proxy support.\n"));
382 opt.ps.type = 0;
383 }
384 }
385 else if(!strncasecmp(com, "proxy_port", 11))
386 opt.ps.port = atoi(val);
387 else if(!strncasecmp(com, "proxy_user", 11))
388 opt.ps.user = cpy(val);
389 else if(!strncasecmp(com, "proxy_pass", 11))
390 opt.ps.pass = cpy(val);
391 else if(!strncasecmp(com, "proxy_bind", 11))
392 opt.ps.bind = !strncasecmp(val, "on", 3);
393 else if(!strncasecmp(com, "passwordfile", 13) || !strncasecmp(com, "password_file", 14))
394 read_password_file(val);
395 else return -1;
396 return 0;
397 case 'r':
398 if(!strncasecmp(com, "rate", 5)) {
399 if(opt.wdel) return 0; /* disabled for wdel */
400 opt.speed_limit = atoi(val);
401 while(*val) {
402 if(*val == 'K') opt.speed_limit *= 1024;
403 if(*val == 'M') opt.speed_limit *= 1024 * 1024;
404 val++;
405 }
406 printout(vDEBUG, "Rate-Limit is set to %d Bytes per second\n", opt.speed_limit);
407 } else if(!strncasecmp(com, "retry_count", 12))
408 opt.retry = atoi(val);
409 else return -1;
410 return 0;
411 case 's':
412 //if(!strncmp(com, "script_file", 12))
413 //load_script(val);
414 //else
415 if(!strncasecmp(com, "sort_urls", 10))
416 opt.sorturls = !strncasecmp(val, "on", 3);
417 else return -1;
418 return 0;
419 case 't':
420 if(!strncasecmp(com, "timeout", 8))
421 socket_set_default_timeout(atoi(val));
422 else if(!strncasecmp(com, "timestamping", 13)) {
423 if(opt.wdel) return 0; /* disabled for wdel */
424 opt.timestamping = !strncasecmp(val, "on", 3); }
425 else if(!strncasecmp(com, "timeoffset", 11))
426 opt.time_offset = atoi(val);
427 else if(!strncasecmp(com, "timeoffset", 11))
428 opt.time_deviation = atoi(val);
429 else if(!strncasecmp(com, "transfer_type", 14)) {
430 if(opt.wdel) return 0; /* disabled for wdel */
431 if(!strncasecmp(val, "auto", 5)) opt.binary = TYPE_UNDEFINED;
432 else if(!strncasecmp(val, "ascii", 6)) opt.binary = TYPE_A;
433 else if(!strncasecmp(val, "binary", 7)) opt.binary = TYPE_I;
434 else return -2;
435 } else return -1;
436 return 0;
437 case 'v':
438 if(!strncasecmp(com, "verbosity", 10)) {
439 char * levels[] = {"quite", "less", "normal", "more", "debug"};
440 int i;
441 for(i=0;i<5;i++)
442 if(!strcasecmp(val, levels[i])) {
443 opt.verbose = i;
444 return 0;
445 }
446 return -2;
447 } else return -1;
448 case 'w':
449 if(!strncasecmp(com, "wait_retry", 11))
450 opt.retry_interval = atoi(val);
451 else return -1;
452 return 0;
453 }
454 return -1;
455 }
456
457 #define NETRC_FILE_NAME ".netrc"
458
459 /* read the netrc file and store its contents in a linked list */
read_netrc_file(void)460 void read_netrc_file(void) {
461 /* Find ~/.netrc. */
462 char *path, *home;
463 acc_t *netrc_list, *l;
464
465 home = home_dir ();
466 if (!home)
467 return;
468
469 path = (char *) malloc(strlen (home) + 1 +
470 strlen (NETRC_FILE_NAME) + 1);
471 if (!path)
472 return;
473
474 sprintf (path, "%s/%s", home, NETRC_FILE_NAME);
475 free (home);
476
477 if (!file_exists(path)) {
478 printout(vMORE, _("netrc file '%s' cannot be read. skipping\n"), path);
479 return;
480 }
481
482 printout(vDEBUG, "Reading netrc file '%s'", path);
483 netrc_list = parse_netrc (path);
484 free(path);
485
486 /* If nothing to do... */
487 if (!netrc_list)
488 return;
489
490 for (l = netrc_list; l; l = l->next) {
491 if (!l->host)
492 continue;
493 opt.pl = password_list_add(opt.pl, cpy(l->host), l->acc ? cpy(l->acc) : NULL, l->passwd ? cpy(l->passwd) : NULL);
494 printout(vDEBUG, "added %s:%s@%s to the password-list (%x)\n", l->acc, l->passwd, l->host, opt.pl);
495 }
496
497 free_netrc(netrc_list);
498 }
499
500 /* read the password file and store its contents in a linked list */
read_password_file(char * f)501 void read_password_file(char * f) {
502 FILE * fp;
503 char * line;
504 char * tmp;
505 char * user;
506 char * pass;
507 if(!file_exists(f)) {
508 printout(vMORE, _("password_file '%s' cannot be read. skipping\n"), f);
509 return;
510 }
511 printout(vNORMAL, _("Warning: You are using a wput password file. This is deprecated!\n"
512 " Please consider switch to the widely used netrc-files.\n"));
513 printout(vDEBUG, "Reading password-file '%s'", f);
514 fp = fopen(f, "r");
515 while( (tmp = line = read_line(fp)) ) {
516 while(isspace(*tmp) && *tmp) tmp++;
517 strtok(tmp, "\t");
518 user = strtok(NULL, "\t");
519 pass = strtok(NULL, "\t");
520 if(*tmp == 0 || *tmp == '#' || user == NULL || pass == NULL) {
521 free(line);
522 continue;
523 }
524 if(pass[strlen(pass)-2] == '\r') pass[strlen(pass)-2] = 0;
525 else if(pass[strlen(pass)-1] == '\n') pass[strlen(pass)-1] = 0;
526 opt.pl = password_list_add(opt.pl, cpy(tmp), cpy(user), cpy(pass));
527 printout(vDEBUG, "added %s:%s@%s to the password-list (%x)\n", user, pass, tmp, opt.pl);
528 free(line);
529 }
530 }
531 /* reads a wputrc file. parses its options and gives error-reports if necessary */
readwputrc(char * f)532 void readwputrc(char * f) {
533 FILE * fp;
534 char * file;
535 char * line;
536 int ln = 1;
537
538 if(f == NULL) {
539 char * home = home_dir();
540 file = malloc(strlen(home) + 10); /* home + slash + (.wputrc | wput.ini) + 0-char */
541 sprintf(file, "%s/%s", home, WPUTRC_FILENAME);
542 free(home);
543 } else file = cpy(f);
544
545 printout(vDEBUG, "Reading wputrc-file: %s\n", file);
546
547 if(!file_exists(file)) {
548 printout(vDEBUG, "wputrc-file '%s' is not readable. skipping.\n", file);
549 free(file);
550 return;
551 }
552
553 fp = fopen (file, "r");
554 if(!fp) {
555 printout(vLESS, _("Fatal error while opening '%s': %s\n"), file, strerror (errno));
556 free(file);
557 return;
558 }
559
560 while ((line = read_line (fp))) {
561 char * tmp = line;
562 char * com;
563 char * val;
564 /* skip leading spaces */
565 while(isspace(*tmp) && *tmp) tmp++;
566
567 /* discard comment lines */
568 if(*tmp == '#' || *tmp == ';' || *tmp == 0) {
569 free(line);
570 continue;
571 }
572 com = tmp;
573
574 /* search for space, end or '=' */
575 while(!isspace(*tmp) && *tmp && *tmp != '=') tmp++;
576 *tmp++= 0;
577
578 while((isspace(*tmp) || *tmp == '=') && *tmp) tmp++;
579 val = tmp;
580
581 /* suppress the new-line-char */
582 while(*tmp != 0 && *tmp != '\n') tmp++;
583 if(*(tmp-1) == '\r') *(tmp-1) = 0;
584 else * tmp = 0;
585
586 /* we mis-use tmp to store the ret_val, and print a message if something was not parse-able */
587 tmp = (char *) set_option(com, val);
588 if(tmp == (char *) -1) printout(vLESS, _("%s#%d: Option '%s' not recognized\n"), file, ln, com);
589 if(tmp == (char *) -2) printout(vLESS, _("%s#%d: Unknow value '%s' for '%s'\n"), file, ln, val, com);
590 free(line);
591 ln++;
592 }
593 free(file);
594 }
595
596 /* parses all the commandline-options available. */
commandlineoptions(int argc,char * argv[])597 void commandlineoptions(int argc, char * argv[]){
598 int c;
599
600 /* TODO IMP windows doesn't automatically fill *.txt with the
601 * TODO IMP corresponding filenames. So this must be done by us (*urgs*) */
602
603 int option_index = 0;
604 static struct option long_options[] =
605 {
606 {"append-output", 1, 0, 'a'}, //0
607 {"ascii", 0, 0, 'A'},
608 {"background", 0, 0, 'b'},
609 {"basename", 1, 0, 0},
610 {"binary", 0, 0, 'B'},
611 {"bind-address", 1, 0, 0}, //5
612 {"compile-options", 0, 0, 0},
613 {"debug", 0, 0, 'd'},
614 {"dont-continue", 0, 0, 0},
615 {"force-tls", 0, 0, 0},
616 {"help", 0, 0, 'h'}, //10
617 {"input-file", 1, 0, 'i'},
618 {"input-pipe", 1, 0, 'I'},
619 {"less-verbose", 0, 0, 0},
620 {"limit-rate", 1, 0, 'l'},
621 {"no-directories", 0, 0, 0}, //15
622 {"output-file", 1, 0, 'o'},
623 {"port-mode", 0, 0, 'p'},
624 {"proxy", 1, 0, 'Y'},
625 {"proxy-user", 1, 0, 0},
626 {"proxy-pass", 1, 0, 0}, //20
627 {"quiet", 0, 0, 'q'},
628 {"random-wait", 0, 0, 0},
629 {"remove-source-files", 0, 0, 'R'},
630 {"reupload", 0, 0, 'u'},
631 {"script", 1, 0, 'S'}, //25
632 {"skip-existing", 0, 0, 0},
633 {"skip-larger", 0, 0, 0},
634 {"sort", 0, 0, 's'},
635 {"timeoffset", 1, 0, 0},
636 {"timeout", 1, 0, 'T'}, //30
637 {"timestamping", 0, 0, 'N'},
638 {"tries", 1, 0, 't'},
639 {"use-proxy", 1, 0, 'Y'},
640 {"verbose", 0, 0, 'v'},
641 {"version", 0, 0, 'V'}, //35
642 {"wait", 1, 0, 'w'},
643 {"waitretry", 1, 0, 0},
644 {"chmod", 1, 0, 'm'},
645 {"disable-tls", 0, 0, 0},
646 {0, 0, 0, 0} //40
647 };
648 while (1)
649 {
650 c = getopt_long (argc, argv, "Y:Vhbo:a:dqvn:i:I:t:NT:w:Rl:pABsS:um:",
651 long_options, &option_index);
652
653 if (c == -1)
654 break;
655
656 switch (c)
657 {
658 case 0:
659 switch(option_index) {
660 case 13: //less-verbose
661 opt.verbose--; break;
662 case 5: set_option("bind-address", optarg); break;
663 case 8: //dont-continue
664 if(opt.resume_table.large_small == RESUME_TABLE_RESUME)
665 opt.resume_table.large_small = RESUME_TABLE_UPLOAD;
666 break;
667 case 22: //random-wait
668 opt.random_wait = 1; break;
669 case 17: //port-mode
670 opt.portmode = 1; break;
671 case 19: set_option("proxy_user", optarg); break;
672 case 20: set_option("proxy_pass", optarg); break;
673 case 6: //compile-options
674 fprintf(opt.output, "wput version: %s\n\n#defined options:\n", version);
675 #ifdef TIMER_GETTIMEOFDAY
676 fprintf(opt.output, "TIMER_GETTIMEOFDAY\n");
677 #endif
678 #ifdef HAVE_SSL
679 fprintf(opt.output, "HAVE_SSL\n");
680 #endif
681 fprintf(opt.output, "\nUsing %d-Bytes for off_t\n", sizeof(off_t));
682 exit(0);
683 case 27: //skip-larger
684 opt.resume_table.small_large = RESUME_TABLE_SKIP; break;
685 case 26: //skip-existing
686 opt.resume_table.large_small = RESUME_TABLE_SKIP;
687 opt.resume_table.large_large = RESUME_TABLE_SKIP;
688 opt.resume_table.small_large = RESUME_TABLE_SKIP; break;
689 case 29: //timeoffset
690 set_option("timeoffset", optarg); break;
691 #ifdef HAVE_SSL
692 case 9: //force-tls
693 set_option("force_tls", "on"); break;
694 #endif
695 case 15: //no-directories
696 opt.no_directories = 1; break;
697 case 3: //basename
698 opt.basename = optarg; break;
699 case 37: //waitretry
700 opt.retry_interval = atoi(optarg); break;
701 case 39: //disable-tls
702 opt.tls = 2; break;
703 default:
704 fprintf(stderr, _("Option %s should not appear here :|\n"), long_options[option_index].name);
705 }
706 break;
707 case 'o':
708 case 'a': opt.output = fopen(optarg, (c == 'o') ? "w" : "a");
709 if(opt.output == NULL) { perror(_("Unable to open logfile")); exit(4); }
710 opt.barstyle = 0;
711 break;
712 #ifndef WIN32
713 case 'b': opt.background = 1; break;
714 #endif
715 case 't':
716 opt.retry = atoi(optarg) + 1;
717 if(opt.retry <= 0) opt.retry = -1;
718 break;
719 case 'T': socket_set_default_timeout(atoi(optarg));
720 break;
721 case 'p': opt.portmode = 1; break;
722 case 'n':
723 if(optarg[0] == 'v') opt.verbose--;
724 if(optarg[0] == 'd') opt.no_directories = 1;
725 if(optarg[0] == 'c')
726 if(opt.resume_table.large_small == RESUME_TABLE_RESUME)
727 opt.resume_table.large_small = RESUME_TABLE_UPLOAD;
728 break;
729 case 'u': opt.resume_table.large_large = RESUME_TABLE_UPLOAD; break;
730 case 'N': opt.timestamping = 1; break;
731 case 'v': opt.verbose++; break;
732 case 'q': opt.verbose=0; break;
733 case 'd': opt.verbose=vDEBUG; break;
734 case 'w': opt.wait =atoi(optarg); break;
735 case 'A': opt.binary = TYPE_A; break;
736 case 'B': opt.binary = TYPE_I; break;
737 case 's': opt.sorturls = 1; break;
738 case 'S': Abort("TODO SCRIPTING\n"); break;
739 case 'l': set_option("rate", optarg); break;
740 case 'i':
741 if(!strncmp(optarg, "-", 2)) {
742 printout(vDEBUG, "Reading URLs from stdin\n");
743 opt.input = stdin;
744 } else {
745 printout(vDEBUG, "Reading URLs from `%s'\n", optarg);
746 opt.input = fopen(optarg, "r");
747 if(opt.input == NULL) {
748 perror(optarg);
749 exit(4);
750 }
751 }
752 break;
753 case 'I': printout(vNORMAL, _("Warning: "));
754 printout(vNORMAL, _("You supplied an input-pipe. "
755 "This is only to be used as fallback, if no filename "
756 "can be found from the URL. This might not be the desired "
757 "behavour. TODO\n"));
758 opt.input_pipe = optarg; break;
759 case 'R': opt.unlink = 1; break;
760 case 'Y': set_option("proxy", optarg); break;
761 case 'm': set_option("chmod", optarg); break;
762 case 'V':
763 fprintf(opt.output, _("wput version: %s\n"), version);
764 exit(0);
765 case 'h':
766 default:
767 fprintf(stderr, _("Usage: wput [options] [file]... [url]...\n"
768 " url ftp://[username[:password]@]hostname[:port][/[path/][file]]\n\n"
769 "Startup:\n"
770 " -V, --version Display the version of wput and exit.\n"
771 " -h, --help Print this help-screen\n"));
772 #ifndef WIN32
773 fprintf(stderr, _(
774 " -b, --background go to background after startup\n"));
775 #endif
776 fprintf(stderr, "\n");
777
778 fprintf(stderr, _(
779 "Logging and input file:\n"
780 " -o, --output-file=FILE log messages to FILE\n"
781 " -a, --append-output=FILE append log messages to FILE\n"
782 " -q, --quiet quiet (no output)\n"
783 " -v, --verbose be verbose\n"
784 " -d, --debug debug output\n"
785 " -nv, --less-verbose be less verbose\n"
786 " -i, --input-file=FILE read the URLs from FILE\n"
787 " -s, --sort sorts all input URLs by server-ip and path\n"
788 " --basename=PATH snip PATH off each file when appendig to an URL\n"
789 " -I, --input-pipe=COMMAND take the output of COMMAND as data-source\n"
790 /* will execute the command with the url and file as param and use its output as input
791 for the uploading file */
792 " -R, --remove-source-files unlink files upon successful upload\n"
793 "\n"));
794 fprintf(stderr, _(
795 "Connection:\n"
796 " --bind-address=ADDR bind to ADDR (hostname or IP) on local host\n"
797 " -t, --tries=NUMBER set retry count to NUMBER (-1 means infinite)\n"
798 " -nc, --dont-continue do not resume partially-uploaded files\n"
799 " -u, --reupload do not skip already completed files\n"
800 " --skip-larger do not upload files if remote size is larger\n"
801 " --skip-existing do not upload files that exist remotely\n"
802 " -N, --timestamping don't re-upload files unless newer than remote\n"
803 " -T, --timeout=10th-SECONDS set various timeouts to 10th-SECONDS\n"
804 " -w, --wait=10th-SECONDS wait 10th-SECONDS between uploads. (default: 0)\n"
805 " --random-wait wait from 0...2*WAIT secs between uploads.\n"
806 " --waitretry=SECONDS wait SECONDS between retries of an upload\n"
807 " -l, --limit-rate=RATE limit upload rate to RATE\n"
808 " -nd, --no-directories do not create any directories\n"
809 " -Y, --proxy=http/socks/off set proxy type or turn off\n"
810 " --proxy-user=NAME set the proxy-username to NAME\n"
811 " --proxy-pass=PASS set the proxy-password to PASS\n"
812 "\n"));
813 fprintf(stderr, _(
814 "FTP-Options:\n"
815 " -p, --port-mode no-passive, turn on port mode ftp (def. pasv)\n"
816 " -A, --ascii force ASCII mode-transfer\n"
817 " -B, --binary force BINARY mode-transfer\n"
818 " -m, --chmod change mode of transferred files ([0-7]{3})\n"));
819
820 #ifdef HAVE_SSL
821 fprintf(stderr, _(
822 " --force-tls force the useage of TLS\n"
823 " --disable-tls disable the usage of TLS\n"));
824 #endif
825 /*" -f, --peace force wput not to be aggressive\n"*/
826 /*" -S, --script=FILE TODO USS load a wput-script\n\n"*/
827 fprintf(stderr, _(
828 "\n"
829 "See wput(1) for more detailed descriptions of the options.\n"
830 "Report bugs and suggestions via SourceForge at\n"
831 "http://sourceforge.net/tracker/?group_id=141519\n"));
832 exit(0);
833 }
834 }
835
836 /* TODO NRV check if we got any input urls. otherwise print usage information */
837 while(optind < argc) {
838 if(!strncmp(argv[optind], "ftp://", 6))
839 opt.wdel ? wdel_queue_add_entry(NULL, cpy(argv[optind])) : queue_add_url(cpy(argv[optind]));
840 else
841 opt.wdel ? wdel_queue_add_file(cpy(argv[optind])) : queue_add_file(cpy(argv[optind]));
842 /* delete argv content, so passwords are not displayed by ps */
843 memset(argv[optind], ' ', strlen(argv[optind]));
844
845 optind++;
846 }
847 }
848