1 /*
2 * main.c -- parses command line options and starts Yafc
3 *
4 * Yet Another FTP Client
5 * Copyright (C) 1998-2001, Martin Hedenfalk <mhe@stacken.kth.se>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version. See COPYING for more details.
11 */
12
13 #include "syshdr.h"
14 #include "ftp.h"
15 #include "gvars.h"
16 #include "help.h"
17 #include "alias.h"
18 #include "input.h"
19 #include "cmd.h"
20 #include "completion.h"
21 #include "login.h"
22 #include "strq.h"
23 #include "utils.h"
24 #include "rc.h"
25 #include "ltag.h"
26 #include "lscolors.h"
27
28 #ifdef HAVE_LOCALE_H
29 # include <locale.h>
30 #endif
31
32 #include "yafcrc.h"
33
print_syntax_and_exit(const char * argv0)34 void print_syntax_and_exit(const char* argv0)
35 {
36 printf(COPYLINE "\n");
37 printf(_("This is yet another FTP client.\n"));
38 printf(_("Usage: %s [options] [[proto://][user[:password]@]hostname[:port][/directory] ...]\n"), argv0);
39 printf(_("Options:\n"));
40 printf(_(" -a, --anon (*) anonymous login\n"));
41 printf(_(" -d, --debug print all commands sent to/from server\n"));
42 printf(_(" -D, --dump-rc prints the default config file to stdout\n"));
43 printf(_(" -m, --mechanism=MECH\n"
44 " (*) try MECH as security mechanism(s)\n"));
45 printf(_(" -n, --norc don't parse config file\n"));
46 printf(_(" -p, --noproxy (*) don't connect via proxy\n"));
47 printf(_(" -q, --quiet don't print the yafc welcome message\n"));
48 printf(_(" -r, --rcfile=FILE use other config file instead of ~/.yafc/yafcrc\n"));
49 printf(_(" -t, --trace[=FILE] use a trace file (mainly for debugging)\n"
50 " if FILE specified, use it instead of ~/.yafc/trace/trace.<pid>\n"));
51 printf(_(" -u, --noauto (*) disable autologin\n"));
52 printf(_(" -U, --noalias (*) disable bookmark alias lookup and abbreviation\n"));
53 printf(_(" -v, --verbose print all replies from server\n"));
54 printf(_(" -w, --wait=TIME use a different wait time for reconnecting\n"));
55 printf(_(" -W, --workdir=DIR use a different working directory (instead of ~/.yafc)\n"));
56 printf(_(" -V, --version print version information and quit\n"));
57 printf(_(" -h, --help print this help and quit\n"));
58 printf("\n");
59 printf(_("(*) only applies for login to host specified on the command line\n"));
60 printf("\n");
61 printf(_("Report bugs to %s\n\n"), PACKAGE_BUGREPORT);
62 exit(0);
63 }
64
tstp_sighandler(int signum)65 void tstp_sighandler(int signum)
66 {
67 if(signum == SIGTSTP) {
68 reset_xterm_title();
69 raise(SIGSTOP);
70 } else if(signum == SIGCONT) {
71 if(readline_running)
72 input_redisplay_prompt();
73 print_xterm_title();
74 }
75 ftp_set_signal(signum, tstp_sighandler);
76 }
77
init_ftp(void)78 void init_ftp(void)
79 {
80 ftp->getuser_hook = getuser_hook;
81 ftp->getpass_hook = getpass_hook;
82
83 ftp->open_timeout = gvConnectionTimeout;
84 ftp->reply_timeout = gvCommandTimeout;
85
86 ftp_set_verbosity(vbError); /* default */
87 if(gvVerbose)
88 ftp_set_verbosity(vbCommand);
89 if(gvDebug)
90 ftp_set_verbosity(vbDebug);
91 }
92
init_yafc(void)93 void init_yafc(void)
94 {
95 gvFtpList = list_new((listfunc)ftp_destroy);
96 list_additem(gvFtpList, ftp_create());
97 gvCurrentFtp = gvFtpList->first;
98 ftp_use((Ftp *)gvCurrentFtp->data);
99 ftp_initsigs();
100
101 gvEditor = getenv("EDITOR");
102 if(!gvEditor)
103 gvEditor = getenv("VISUAL");
104 if(gvEditor)
105 gvEditor = xstrdup(gvEditor);
106 else
107 gvEditor = xstrdup("vi");
108
109 #ifdef HAVE_UNAME
110 struct utsname unbuf;
111 if(uname(&unbuf) == 0)
112 gvLocalHost = xstrdup(unbuf.nodename);
113 #endif
114 if(!gvLocalHost)
115 gvLocalHost = xstrdup(getenv("HOST"));
116 if(!gvLocalHost)
117 gvLocalHost = xstrdup("localhost");
118
119 {
120 struct passwd *pwd;
121 pwd = getpwuid(geteuid());
122 gvUsername = xstrdup(pwd->pw_name);
123 gvLocalHomeDir = xstrdup(pwd->pw_dir);
124 }
125
126 if(!gvLocalHomeDir)
127 gvLocalHomeDir = xstrdup(getenv("HOME"));
128
129 char* curdir = getcwd(NULL, 0);
130 gvWorkingDirectory = path_absolute(
131 gvWorkingDirectory ? gvWorkingDirectory : "~/.yafc",
132 curdir,
133 gvLocalHomeDir);
134 free(curdir);
135
136 gvAnonPasswd = xstrdup("anonymous@");
137
138 /* init colors from LS_COLORS for ls */
139 init_colors();
140
141 /* choose default security mechanism */
142 gvDefaultMechanism = list_new((listfunc)free);
143 #ifdef HAVE_KRB5
144 # ifdef USE_SSL
145 listify_string("krb5:ssl:none", gvDefaultMechanism);
146 # else
147 listify_string("krb5:none", gvDefaultMechanism);
148 # endif
149 #elif defined(USE_SSL)
150 listify_string("ssl", gvDefaultMechanism);
151 #else
152 listify_string("none", gvDefaultMechanism);
153 #endif
154
155 gvPrompt1 = xstrdup("yafc> ");
156 gvPrompt2 = xstrdup("yafc %h> ");
157 gvPrompt3 = xstrdup("yafc %h:%42~> ");
158
159 gvTerm = xstrdup(getenv("TERM"));
160 if(!gvTerm)
161 gvTerm = xstrdup("dummy");
162 gvXtermTitleTerms = xstrdup("xterm xterm-debian rxvt");
163
164 gvBookmarks = list_new((listfunc)url_destroy);
165 gvAliases = list_new((listfunc)alias_destroy);
166 gvAsciiMasks = list_new((listfunc)free);
167 gvTransferFirstMasks = list_new((listfunc)free);
168 gvIgnoreMasks = list_new((listfunc)free);
169 gvLocalTagList = list_new((listfunc)free);
170 gvProxyExclude = list_new((listfunc)free);
171
172 if (asprintf(&gvHistoryFile, "%s/history", gvWorkingDirectory) == -1)
173 {
174 fprintf(stderr, _("Failed to allocate memory.\n"));
175 exit_yafc();
176 }
177
178 gvSendmailPath = xstrdup("/usr/sbin/sendmail");
179
180 ftp_set_signal(SIGTSTP, tstp_sighandler);
181 ftp_set_signal(SIGCONT, tstp_sighandler);
182
183 gvTransferBeginString = xstrdup("%-70R\n");
184 gvTransferString = xstrdup("%5p%% [%25v] %s/%S ETA %e %B");
185 /* gvTransferEndString = xstrdup("%-40R %s in %t @ %b\n");*/
186
187 gvTransferXtermString = xstrdup("\x1B]0;yafc - (%p%%) %r\x07");
188
189 gvStatsTransfer = stats_create();
190
191 input_init();
192 }
193
check_if_first_time(void)194 void check_if_first_time(void)
195 {
196 if (access(gvWorkingDirectory, X_OK) == 0)
197 return;
198
199 if(errno == ENOENT) {
200 char *dir;
201
202 /* printf(_("This seems to be the first time you run Yafc...\n"));*/
203
204 printf(_("creating working directory %s: "), gvWorkingDirectory);
205 fflush(stdout);
206 if(mkdir(gvWorkingDirectory, S_IRUSR|S_IWUSR|S_IXUSR) != 0) {
207 perror("");
208 return;
209 }
210 chmod(gvWorkingDirectory, S_IRUSR|S_IWUSR|S_IXUSR);
211 printf(_("done\n"));
212
213 if (asprintf(&dir, "%s/trace", gvWorkingDirectory) == -1)
214 {
215 fprintf(stderr, _("Failed to allocate memory.\n"));
216 exit_yafc();
217 }
218 printf(_("creating directory %s: "), dir);
219 fflush(stdout);
220 if(mkdir(dir, S_IRUSR|S_IWUSR|S_IXUSR) != 0) {
221 perror("");
222 free(dir);
223 return;
224 }
225 chmod(dir, S_IRUSR|S_IWUSR|S_IXUSR);
226 printf(_("done\n"));
227 free(dir);
228 dir = NULL;
229
230 if (asprintf(&dir, "%s/nohup", gvWorkingDirectory) == -1)
231 {
232 fprintf(stderr, _("Failed to allocate memory.\n"));
233 exit_yafc();
234 }
235 printf(_("creating directory %s: "), dir);
236 fflush(stdout);
237 if(mkdir(dir, S_IRUSR|S_IWUSR|S_IXUSR) != 0) {
238 perror("");
239 free(dir);
240 return;
241 }
242 chmod(dir, S_IRUSR|S_IWUSR|S_IXUSR);
243 printf(_("done\n"));
244 free(dir);
245 } else
246 perror(gvWorkingDirectory);
247 }
248
main(int argc,char ** argv,char ** envp)249 int main(int argc, char **argv, char **envp)
250 {
251 int c;
252 char *configfile = 0;
253 bool dotrace = false;
254 char *tracefile = 0;
255 unsigned int open_opt = 0;
256 int wait_time = -1;
257
258 bool override_yafcrc = false;
259 bool override_debug = false;
260 bool override_verbose = false;
261 bool override_welcome = false;
262
263 char *mech = 0;
264
265 struct option longopts[] = {
266 {"anon", no_argument, 0, 'a'},
267 {"debug", no_argument, 0, 'd'},
268 {"dump-rc", no_argument, 0, 'D'},
269 {"norc", no_argument, 0, 'n'},
270 {"quiet", no_argument, 0, 'q'},
271 {"rcfile", required_argument, 0, 'r'},
272 {"mechanism", required_argument, 0, 'm'},
273 {"noproxy", no_argument, 0, 'p'},
274 {"trace", optional_argument, 0, 't'},
275 {"noauto", no_argument, 0, 'u'},
276 {"verbose", no_argument, 0, 'v'},
277 {"version", no_argument, 0, 'V'},
278 {"wait", required_argument, 0, 'w'},
279 {"workdir", required_argument, 0, 'W'},
280 {"help", no_argument, 0, 'h'},
281 {0, 0, 0, 0},
282 };
283
284 #ifdef SOCKS
285 SOCKSinit(argv[0]);
286 #endif
287
288 #ifdef ENABLE_NLS
289 setlocale(LC_ALL, "");
290 bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
291 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
292 textdomain(GETTEXT_PACKAGE);
293 #endif
294 #if 0 && (!defined(HAVE_SETPROCTITLE) && defined(linux))
295 initsetproctitle(argc, argv, envp);
296 #endif
297
298 while((c = getopt_long(argc, argv,
299 "qhdDgant::r:uUm:pvVw:W:", longopts, 0)) != EOF)
300 {
301 switch(c) {
302 case 'a':
303 open_opt |= OP_ANON;
304 break;
305 case 'n':
306 override_yafcrc = true;
307 break;
308 case 'r':
309 configfile = xstrdup(optarg);
310 break;
311 case 't':
312 dotrace = true;
313 if(optarg)
314 tracefile = xstrdup(optarg);
315 break;
316 case 'u':
317 open_opt |= OP_NOAUTO;
318 break;
319 case 'U':
320 open_opt |= OP_NOALIAS;
321 break;
322 case 'm':
323 mech = xstrdup(optarg);
324 break;
325 case 'p':
326 open_opt |= OP_NOPROXY;
327 break;
328 case 'd':
329 override_debug = true;
330 break;
331 case 'D':
332 printf("%s", default_yafcrc);
333 return 0;
334 case 'q':
335 override_welcome = true;
336 break;
337 case 'v':
338 override_verbose = true;
339 break;
340 case 'V':
341 printf(PACKAGE " " VERSION "\n");
342 return 0;
343 case 'w':
344 wait_time = atoi(optarg);
345 break;
346 case 'W':
347 stripslash(optarg);
348 gvWorkingDirectory = xstrdup(optarg);
349 break;
350 case 'h':
351 print_syntax_and_exit(argv[0]);
352 break;
353 case '?':
354 return 1;
355 }
356 }
357
358 if(!override_welcome)
359 puts(_(FULLVER));
360
361 init_yafc();
362
363 if(!configfile)
364 if (asprintf(&configfile, "%s/yafcrc", gvWorkingDirectory) == -1)
365 {
366 fprintf(stderr, _("Failed to allocate memory.\n"));
367 exit_yafc();
368 }
369
370 check_if_first_time();
371
372 if(!override_yafcrc) {
373 char *tmp;
374 parse_rc(SYSCONFDIR "/yafcrc", false);
375 parse_rc(configfile, false);
376 if (asprintf(&tmp, "%s/bookmarks", gvWorkingDirectory) == -1)
377 {
378 fprintf(stderr, _("Failed to allocate memory.\n"));
379 exit_yafc();
380 }
381 parse_rc(tmp, false);
382 free(tmp);
383 }
384 free(configfile);
385 configfile = NULL;
386
387 if(gvReadNetrc)
388 parse_rc("~/.netrc", false);
389
390 if(gvProxyType != 0 && gvProxyUrl == 0) {
391 fprintf(stderr, _("No proxy host defined!\n\n"));
392 gvProxyType = 0;
393 }
394
395 if(override_debug)
396 gvDebug = true;
397 if(override_verbose)
398 gvVerbose = true;
399 if(wait_time != -1) {
400 if(wait_time < 0)
401 fprintf(stderr, _("Invalid value for --wait: %d\n"), wait_time);
402 else
403 gvConnectWaitTime = wait_time;
404 }
405
406 init_ftp();
407
408 if(dotrace || gvTrace) {
409 if(!tracefile)
410 if (asprintf(&tracefile, "%s/trace/trace.%u",
411 gvWorkingDirectory, getpid()) == -1)
412 {
413 fprintf(stderr, _("Failed to allocate memory.\n"));
414 exit_yafc();
415 }
416 if(ftp_set_trace(tracefile) != 0)
417 fprintf(stderr, _("Couldn't open tracefile '%s': %s\n"),
418 tracefile, strerror(errno));
419 free(tracefile);
420 }
421
422 if(optind < argc) {
423 #ifdef HAVE_LIBREADLINE
424 char *s;
425 #endif
426 int i;
427
428 if(!gvAutologin)
429 open_opt |= OP_NOAUTO;
430
431 for(i=optind; i<argc; i++) {
432 #ifdef HAVE_GETTIMEOFDAY
433 struct timeval beg, end;
434 gettimeofday(&beg, 0);
435 #endif
436 yafc_open(argv[i], open_opt, mech, 0);
437 #ifdef HAVE_GETTIMEOFDAY
438 gettimeofday(&end, 0);
439 end.tv_sec -= beg.tv_sec;
440 if(gvBeepLongCommand && end.tv_sec > gvLongCommandTime)
441 fputc('\007', stderr);
442 #endif
443 #ifdef HAVE_LIBREADLINE /* add appropriate 'open' command to history */
444 if (asprintf(&s, "open %s%s",
445 argv[i], test(open_opt, OP_ANON) ? " --anon" : "") == -1)
446 {
447 fprintf(stderr, _("Failed to allocate memory.\n"));
448 exit_yafc();
449 }
450 add_history(s);
451 free(s);
452 #endif
453 }
454 }
455
456 load_ltaglist(false, false, 0);
457
458 command_loop();
459 /* should not return */
460 list_free(gvFtpList);
461 gvFtpList = NULL;
462 return 0;
463 }
464