int main(int argc, char *argv[]) { struct sockaddr_in s_in; int top; sp = getservbyname("tftp", "udp"); if (sp == 0) { fprintf(stderr, "tftp: udp/tftp: unknown service\n"); exit(1); } f = socket(AF_INET, SOCK_DGRAM, 0); if (f < 0) { perror("tftp: socket"); exit(3); } memset(&s_in, 0, sizeof(s_in)); s_in.sin_family = AF_INET; if (bind(f, (struct sockaddr *)&s_in, sizeof (s_in)) < 0) { perror("tftp: bind"); exit(1); } strcpy(mode, "netascii"); signal(SIGINT, intr); if (argc > 1) { if (sigsetjmp(toplevel, 1) != 0) exit(0); setpeer(argc, argv); } top = sigsetjmp(toplevel, 1) == 0; for (;;) command(top); }
int main(int argc, char *argv[]) { acting_as_client = 1; peer = -1; strcpy(mode, "netascii"); signal(SIGINT, intr); if (argc > 1) { if (setjmp(toplevel) != 0) exit(txrx_error); if (strncmp(argv[1], "tftp://", 7) == 0) { urihandling(argv[1]); exit(txrx_error); } setpeer(argc, argv); } if (setjmp(toplevel) != 0) (void)putchar('\n'); init_options(); command(); }
void parsearg(int argc, char *argv[]) { if (argc < 2) { strlcpy(line, "Connect ", sizeof(line)); printf("(to) "); readcmd(&line[strlen(line)], LBUFLEN - strlen(line), stdin); if (makeargv()) return; argc = margc; argv = margv; } if ((argc < 2) || (argc > 3)) { printf("usage: %s [host [port]]\n", argv[0]); return; } if (argc == 2) setpeer(argv[1], NULL); else setpeer(argv[1], argv[2]); }
int main(int argc, char *argv[]) { HistEvent he; static EditLine *el; static History *hist; bool interactive; acting_as_client = 1; peer = -1; strcpy(mode, "netascii"); signal(SIGINT, intr); interactive = isatty(STDIN_FILENO); if (interactive) { el = el_init("tftp", stdin, stdout, stderr); hist = history_init(); history(hist, &he, H_SETSIZE, 100); el_set(el, EL_HIST, history, hist); el_set(el, EL_EDITOR, "emacs"); el_set(el, EL_PROMPT, command_prompt); el_set(el, EL_SIGNAL, 1); el_source(el, NULL); } if (argc > 1) { if (setjmp(toplevel) != 0) exit(txrx_error); if (strncmp(argv[1], "tftp://", 7) == 0) { urihandling(argv[1]); exit(txrx_error); } setpeer(argc, argv); } if (setjmp(toplevel) != 0) { if (interactive) el_reset(el); (void)putchar('\n'); } init_options(); command(interactive, el, hist, &he); }
/* * === FUNCTION ====================================================================== * Name: main * Description: 主函数,处理命令行参数后,尝试连接并进入主循环 * ===================================================================================== */ int main( int argc, char *argv[] ) { char *cp; argc--, argv++; while(argc > 0 && **argv == '-'){ for(cp = *argv + 1; *cp; cp++){ switch (*cp){ case 'a': automatic = 1; break; case 'p': passivemode = 1; break; case 'h': usage(); exit(0); default: printf("ftp: %c: unknown option\n", *cp); usage(); exit(1); } } argc--, argv++; } ftpport = getftpport(); /* 有主机名,试图建立连接 */ if (argc > 0) setpeer(*argv); signal(SIGINT, SIG_IGN); signal(SIGPIPE, lostpeer); while (1) { cmdloop(); } return EXIT_SUCCESS; } /* ---------- end of function main ---------- */
/* * === FUNCTION ====================================================================== * Name: OPEN * Description: 连接到服务器,若未登录则执行登录操作 * ===================================================================================== */ void OPEN (int argc, char *argv[]) { if (argc != 2){ printf("Usage: %s hostname\n", argv[0]); return; } if (connected) { printf("Already connected to %s, use close first.\n", hostnm); return; } if (!setpeer(argv[1])){ /*----------------------------------------------------------------------------- * Set up defaults for FTP. *-----------------------------------------------------------------------------*/ strcpy(typenm, "ascii"), type = TYPE_A; automatic = 0; passivemode = 0; } } /* ----- end of function OPEN ----- */
int main (int argc, char *argv[]) { struct sockaddr_in sin; set_program_name (argv[0]); iu_argp_init ("tftp", default_program_authors); argp_parse (&argp, argc, argv, 0, NULL, NULL); sp = getservbyname ("tftp", "udp"); if (sp == 0) { fprintf (stderr, "tftp: udp/tftp: unknown service\n"); exit (1); } f = socket (AF_INET, SOCK_DGRAM, 0); if (f < 0) { perror ("tftp: socket"); exit (3); } memset (&sin, 0, sizeof (sin)); sin.sin_family = AF_INET; if (bind (f, (struct sockaddr *) &sin, sizeof (sin)) < 0) { perror ("tftp: bind"); exit (1); } strcpy (mode, "netascii"); signal (SIGINT, intr); if (hostport_argc > 1) { if (setjmp (toplevel) != 0) exit (0); setpeer (hostport_argc, hostport_argv); } if (setjmp (toplevel) != 0) putchar ('\n'); command (); }
int main(int argc, char *argv[]) { struct sockaddr_in s_in; /* socket, bind */ sp = getservbyname("tftp", "udp"); if (sp == 0) errx(1, "udp/tftp: unknown service"); f = socket(AF_INET, SOCK_DGRAM, 0); if (f < 0) err(3, "socket"); bzero((char *)&s_in, sizeof(s_in)); s_in.sin_family = AF_INET; if (bind(f, (struct sockaddr *)&s_in, sizeof(s_in)) < 0) err(1, "bind"); /* set default transfer mode */ strlcpy(mode, "netascii", sizeof(mode)); /* set peer if given */ if (argc > 1) setpeer(argc, argv); /* catch SIGINT */ signal(SIGINT, intr); /* allocate memory for packets */ if ((ackbuf = malloc(SEGSIZE_MAX + 4)) == NULL) err(1, "malloc"); /* command prompt */ command(); return (0); }
int main(volatile int argc, char **volatile argv) { register char *cp; struct servent *sp; int top; struct passwd *pw = NULL; char homedir[MAXPATHLEN]; tick = 0; sp = getservbyname("ftp", "tcp"); if (sp == 0) { fprintf(stderr, "ftp: ftp/tcp: unknown service\n"); exit(1); } ftp_port = sp->s_port; doglob = 1; interactive = 1; autologin = 1; passivemode = 0; cp = strrchr(argv[0], '/'); cp = (cp == NULL) ? argv[0] : cp+1; if (strcmp(cp, "pftp") == 0) passivemode = 1; #ifdef __USE_READLINE__ /* * Set terminal type so libreadline can parse .inputrc correctly */ rl_terminal_name = getenv("TERM"); #endif argc--, argv++; while (argc > 0 && **argv == '-') { for (cp = *argv + 1; *cp; cp++) switch (*cp) { case 'd': options |= SO_DEBUG; debug++; break; case 'v': verbose++; break; case 't': traceflag++; break; case 'i': interactive = 0; break; case 'n': autologin = 0; break; case 'p': passivemode = 1; break; case 'g': doglob = 0; break; case 'e': rl_inhibit = 1; break; case 'h': usage(); exit(0); default: fprintf(stdout, "ftp: %c: unknown option\n", *cp); exit(1); } argc--, argv++; } fromatty = isatty(fileno(stdin)); if (fromatty) verbose++; cpend = 0; /* no pending replies */ proxy = 0; /* proxy not active */ crflag = 1; /* strip c.r. on ascii gets */ sendport = -1; /* not using ports */ /* * Set up the home directory in case we're globbing. */ cp = getlogin(); if (cp != NULL) { pw = getpwnam(cp); } if (pw == NULL) pw = getpwuid(getuid()); if (pw != NULL) { strncpy(homedir, pw->pw_dir, sizeof(homedir)); homedir[sizeof(homedir)-1] = 0; home = homedir; } if (argc > 0) { if (sigsetjmp(toplevel, 1)) exit(0); (void) signal(SIGINT, intr); (void) signal(SIGPIPE, lostpeer); setpeer(argc + 1, argv - 1); } top = sigsetjmp(toplevel, 1) == 0; if (top) { (void) signal(SIGINT, intr); (void) signal(SIGPIPE, lostpeer); } for (;;) { cmdscanner(top); top = 1; } }
/* * === FUNCTION ====================================================================== * Name: cmdloop * Description: 循环执行命令 * ===================================================================================== */ static void cmdloop (void) { struct cmd *c; int l; char line[MAXLINE] = ""; for (;;) { if (!getinput(line, sizeof(line))) { QUIT(); } l = strlen(line); if (l == 0) break; if (line[--l] == '\n') { if (l == 0) break; line[l] = '\0'; } else if (l == sizeof(line) - 2) { /* it was a line without a newline */ printf("Sorry, input line too long\n"); while ((l = getchar()) != '\n' && l != EOF) ; break; } /* 如果是大写命令,直接发送到服务器处理,只适合部分控制命令,慎用 */ if (isupper(line[0])){ command(line); continue; } makearg(line); c = getcmd(margv[0]); if (c == (struct cmd *)-1) { printf("?Ambiguous command\n"); continue; } if (c == NULL) { printf("?Invalid command\n"); continue; } if (c->c_conn && !connected) { /* 试图自动建立连接 */ if (automatic && strcmp(hostnm, "")){ setpeer(hostnm); } else{ printf("Not connected.\n"); continue; } } if (c->c_handler_1) c->c_handler_1(margc, margv); else c->c_handler_0(); } signal(SIGINT, SIG_IGN); signal(SIGPIPE, lostpeer); } /* ----- end of function cmdloop ----- */
int main(volatile int argc, char *argv[]) { int ch, top, rval; struct passwd *pw = NULL; char *cp, homedir[MAXPATHLEN]; char *outfile = NULL; const char *errstr; int dumb_terminal = 0; ftpport = "ftp"; httpport = "http"; #ifndef SMALL httpsport = "https"; #endif /* !SMALL */ gateport = getenv("FTPSERVERPORT"); if (gateport == NULL || *gateport == '\0') gateport = "ftpgate"; doglob = 1; interactive = 1; autologin = 1; passivemode = 1; activefallback = 1; preserve = 1; verbose = 0; progress = 0; gatemode = 0; #ifndef SMALL editing = 0; el = NULL; hist = NULL; cookiefile = NULL; resume = 0; srcaddr = NULL; marg_sl = sl_init(); #endif /* !SMALL */ mark = HASHBYTES; #ifdef INET6 epsv4 = 1; #else epsv4 = 0; #endif epsv4bad = 0; /* Set default operation mode based on FTPMODE environment variable */ if ((cp = getenv("FTPMODE")) != NULL && *cp != '\0') { if (strcmp(cp, "passive") == 0) { passivemode = 1; activefallback = 0; } else if (strcmp(cp, "active") == 0) { passivemode = 0; activefallback = 0; } else if (strcmp(cp, "gate") == 0) { gatemode = 1; } else if (strcmp(cp, "auto") == 0) { passivemode = 1; activefallback = 1; } else warnx("unknown FTPMODE: %s. Using defaults", cp); } if (strcmp(__progname, "gate-ftp") == 0) gatemode = 1; gateserver = getenv("FTPSERVER"); if (gateserver == NULL || *gateserver == '\0') gateserver = GATE_SERVER; if (gatemode) { if (*gateserver == '\0') { warnx( "Neither $FTPSERVER nor $GATE_SERVER is defined; disabling gate-ftp"); gatemode = 0; } } cp = getenv("TERM"); dumb_terminal = (cp == NULL || *cp == '\0' || !strcmp(cp, "dumb") || !strcmp(cp, "emacs") || !strcmp(cp, "su")); fromatty = isatty(fileno(stdin)); if (fromatty) { verbose = 1; /* verbose if from a tty */ #ifndef SMALL if (!dumb_terminal) editing = 1; /* editing mode on if tty is usable */ #endif /* !SMALL */ } ttyout = stdout; if (isatty(fileno(ttyout)) && !dumb_terminal && foregroundproc()) progress = 1; /* progress bar on if tty is usable */ #ifndef SMALL cookiefile = getenv("http_cookies"); #endif /* !SMALL */ while ((ch = getopt(argc, argv, "46AaCc:dD:Eegik:mno:pP:r:S:s:tvV")) != -1) { switch (ch) { case '4': family = PF_INET; break; case '6': family = PF_INET6; break; case 'A': activefallback = 0; passivemode = 0; break; case 'a': anonftp = 1; break; case 'C': #ifndef SMALL resume = 1; #endif /* !SMALL */ break; case 'c': #ifndef SMALL cookiefile = optarg; #endif /* !SMALL */ break; case 'D': action = optarg; break; case 'd': #ifndef SMALL options |= SO_DEBUG; debug++; #endif /* !SMALL */ break; case 'E': epsv4 = 0; break; case 'e': #ifndef SMALL editing = 0; #endif /* !SMALL */ break; case 'g': doglob = 0; break; case 'i': interactive = 0; break; case 'k': keep_alive_timeout = strtonum(optarg, 0, INT_MAX, &errstr); if (errstr != NULL) { warnx("keep alive amount is %s: %s", errstr, optarg); usage(); } break; case 'm': progress = -1; break; case 'n': autologin = 0; break; case 'o': outfile = optarg; if (*outfile == '\0') { pipeout = 0; outfile = NULL; ttyout = stdout; } else { pipeout = strcmp(outfile, "-") == 0; ttyout = pipeout ? stderr : stdout; } break; case 'p': passivemode = 1; activefallback = 0; break; case 'P': ftpport = optarg; break; case 'r': retry_connect = strtonum(optarg, 0, INT_MAX, &errstr); if (errstr != NULL) { warnx("retry amount is %s: %s", errstr, optarg); usage(); } break; case 'S': #ifndef SMALL cp = optarg; while (*cp) { char *str; switch (getsubopt(&cp, ssl_verify_opts, &str)) { case SSL_CAFILE: if (str == NULL) errx(1, "missing CA file"); ssl_ca_file = str; break; case SSL_CAPATH: if (str == NULL) errx(1, "missing CA directory" " path"); ssl_ca_path = str; break; case SSL_CIPHERS: if (str == NULL) errx(1, "missing cipher list"); ssl_ciphers = str; break; case SSL_DONTVERIFY: ssl_verify = 0; break; case SSL_DOVERIFY: ssl_verify = 1; break; case SSL_VERIFYDEPTH: if (str == NULL) errx(1, "missing depth"); ssl_verify_depth = strtonum(str, 0, INT_MAX, &errstr); if (errstr) errx(1, "certificate " "validation depth is %s", errstr); break; default: errx(1, "unknown -S suboption `%s'", suboptarg ? suboptarg : ""); /* NOTREACHED */ } } #endif break; case 's': #ifndef SMALL srcaddr = optarg; #endif /* !SMALL */ break; case 't': trace = 1; break; case 'v': verbose = 1; break; case 'V': verbose = 0; break; default: usage(); } } argc -= optind; argv += optind; #ifndef SMALL cookie_load(); #endif /* !SMALL */ cpend = 0; /* no pending replies */ proxy = 0; /* proxy not active */ crflag = 1; /* strip c.r. on ascii gets */ sendport = -1; /* not using ports */ /* * Set up the home directory in case we're globbing. */ cp = getlogin(); if (cp != NULL) { pw = getpwnam(cp); } if (pw == NULL) pw = getpwuid(getuid()); if (pw != NULL) { (void)strlcpy(homedir, pw->pw_dir, sizeof homedir); home = homedir; } setttywidth(0); (void)signal(SIGWINCH, setttywidth); if (argc > 0) { if (isurl(argv[0])) { rval = auto_fetch(argc, argv, outfile); if (rval >= 0) /* -1 == connected and cd-ed */ exit(rval); } else { #ifndef SMALL char *xargv[5]; if (setjmp(toplevel)) exit(0); (void)signal(SIGINT, (sig_t)intr); (void)signal(SIGPIPE, (sig_t)lostpeer); xargv[0] = __progname; xargv[1] = argv[0]; xargv[2] = argv[1]; xargv[3] = argv[2]; xargv[4] = NULL; do { setpeer(argc+1, xargv); if (!retry_connect) break; if (!connected) { macnum = 0; fputs("Retrying...\n", ttyout); sleep(retry_connect); } } while (!connected); retry_connect = 0; /* connected, stop hiding msgs */ #endif /* !SMALL */ } } #ifndef SMALL controlediting(); top = setjmp(toplevel) == 0; if (top) { (void)signal(SIGINT, (sig_t)intr); (void)signal(SIGPIPE, (sig_t)lostpeer); } for (;;) { cmdscanner(top); top = 1; } #else /* !SMALL */ usage(); #endif /* !SMALL */ }
/* * Receive file(s). */ void get(int argc, char *argv[]) { int fd; int n; char *cp; char *src; if (argc < 2) { strlcpy(line, "get ", sizeof(line)); printf("(files) "); readcmd(&line[strlen(line)], LBUFLEN - strlen(line), stdin); if (makeargv()) return; argc = margc; argv = margv; } if (argc < 2) { getusage(argv[0]); return; } if (!connected) { for (n = 1; n < argc; n++) if (strrchr(argv[n], ':') == 0) { getusage(argv[0]); return; } } for (n = 1; n < argc; n++) { src = strrchr(argv[n], ':'); if (src == NULL) src = argv[n]; else { char *cp; *src++ = 0; cp = argv[n]; if (cp[0] == '[' && cp[strlen(cp) - 1] == ']') { cp[strlen(cp) - 1] = '\0'; cp++; } setpeer(cp, NULL); if (!connected) continue; } if (argc < 4) { cp = argc == 3 ? argv[2] : tail(src); fd = open(cp, O_CREAT | O_TRUNC | O_WRONLY, 0644); if (fd < 0) { warn("create: %s", cp); return; } if (verbose) printf("getting from %s:%s to %s [%s]\n", hostname, src, cp, mode); recvfile(fd, src, mode); break; } cp = tail(src); /* new .. jdg */ fd = open(cp, O_CREAT | O_TRUNC | O_WRONLY, 0644); if (fd < 0) { warn("create: %s", cp); continue; } if (verbose) printf("getting from %s:%s to %s [%s]\n", hostname, src, cp, mode); recvfile(fd, src, mode); } }
/* * Send file(s). */ void put(int argc, char *argv[]) { int fd; int n; char *cp, *targ; if (argc < 2) { strlcpy(line, "put ", sizeof(line)); printf("(file) "); readcmd(&line[strlen(line)], LBUFLEN - strlen(line), stdin); if (makeargv()) return; argc = margc; argv = margv; } if (argc < 2) { putusage(argv[0]); return; } targ = argv[argc - 1]; if (strrchr(argv[argc - 1], ':')) { for (n = 1; n < argc - 1; n++) if (strchr(argv[n], ':')) { putusage(argv[0]); return; } cp = argv[argc - 1]; targ = strrchr(cp, ':'); *targ++ = 0; if (cp[0] == '[' && cp[strlen(cp) - 1] == ']') { cp[strlen(cp) - 1] = '\0'; cp++; } setpeer(cp, NULL); } if (!connected) { printf("No target machine specified.\n"); return; } if (argc < 4) { cp = argc == 2 ? tail(targ) : argv[1]; fd = open(cp, O_RDONLY); if (fd < 0) { warn("open: %s", cp); return; } if (verbose) printf("putting %s to %s:%s [%s]\n", cp, hostname, targ, mode); sendfile(fd, targ, mode); return; } /* * this assumes the target is a directory on * on a remote unix system. hmmmm. */ for (n = 1; n < argc - 1; n++) { if (asprintf(&cp, "%s/%s", targ, tail(argv[n])) == -1) err(1, "asprintf"); fd = open(argv[n], O_RDONLY); if (fd < 0) { warn("open: %s", argv[n]); free(cp); continue; } if (verbose) printf("putting %s to %s:%s [%s]\n", argv[n], hostname, cp, mode); sendfile(fd, cp, mode); free(cp); } }
int main (int argc, char *argv[]) { struct sockaddr_in s_in; int c; int pargc; char **pargv; while ((c = getopt (argc, argv, "Vv")) != -1) { switch (c) { case 'v': verbose = 1; break; case 'V': /* Print version and configuration to stdout and exit */ printf ("%s\n", TFTP_CONFIG_STR); exit (0); default: fprintf (stderr, "Usage: %s [-v] [host]\n", argv[0]); exit (EX_USAGE); } } pargc = argc - (optind - 1); pargv = argv + (optind - 1); sp = getservbyname ("tftp", "udp"); if (sp == 0) { /* Use canned values */ fprintf (stderr, "tftp: tftp/udp: unknown service, faking it...\n"); sp = xmalloc (sizeof (struct servent)); sp->s_name = (char *) "tftp"; sp->s_aliases = NULL; sp->s_port = htons (IPPORT_TFTP); sp->s_proto = (char *) "udp"; exit (1); } f = socket (AF_INET, SOCK_DGRAM, 0); if (f < 0) { perror ("tftp: socket"); exit (3); } bzero ((char *) &s_in, sizeof (s_in)); s_in.sin_family = AF_INET; if (bind (f, (struct sockaddr *) &s_in, sizeof (s_in)) < 0) { perror ("tftp: bind"); exit (1); } mode = MODE_DEFAULT; bsd_signal (SIGINT, intr); if (pargc > 1) { if (sigsetjmp (toplevel, 1) != 0) exit (0); setpeer (pargc, pargv); } if (sigsetjmp (toplevel, 1) != 0) (void) putchar ('\n'); #ifdef WITH_READLINE #ifdef HAVE_READLINE_HISTORY_H using_history (); #endif #endif command (); return 0; /* Never reached */ }
int main(int volatile argc, char **volatile argv) { int ch, rval; struct passwd *pw; char *cp, *ep, *anonuser, *anonpass, *upload_path, *src_addr; int dumbterm, s, isupload; size_t len; socklen_t slen; tzset(); #if 0 /* tnftp */ /* XXX */ setlocale(LC_ALL, ""); #endif /* tnftp */ setprogname(argv[0]); sigint_raised = 0; ftpport = "ftp"; httpport = "http"; gateport = NULL; cp = getenv("FTPSERVERPORT"); if (cp != NULL) gateport = cp; else gateport = "ftpgate"; doglob = 1; interactive = 1; autologin = 1; passivemode = 1; activefallback = 1; preserve = 1; verbose = 0; progress = 0; gatemode = 0; data = -1; outfile = NULL; restartautofetch = 0; #ifndef NO_EDITCOMPLETE editing = 0; el = NULL; hist = NULL; #endif bytes = 0; mark = HASHBYTES; rate_get = 0; rate_get_incr = DEFAULTINCR; rate_put = 0; rate_put_incr = DEFAULTINCR; #ifdef INET6 epsv4 = 1; #else epsv4 = 0; #endif epsv4bad = 0; src_addr = NULL; upload_path = NULL; isupload = 0; reply_callback = NULL; family = AF_UNSPEC; netrc[0] = '\0'; cp = getenv("NETRC"); if (cp != NULL && strlcpy(netrc, cp, sizeof(netrc)) >= sizeof(netrc)) errx(1, "$NETRC `%s': %s", cp, strerror(ENAMETOOLONG)); /* * Get the default socket buffer sizes if we don't already have them. * It doesn't matter which socket we do this to, because on the first * call no socket buffer sizes will have been modified, so we are * guaranteed to get the system defaults. */ s = socket(AF_INET, SOCK_STREAM, 0); if (s == -1) err(1, "Can't create socket to determine default socket sizes"); slen = sizeof(rcvbuf_size); if (getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void *)&rcvbuf_size, &slen) == -1) err(1, "Unable to get default rcvbuf size"); slen = sizeof(sndbuf_size); if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void *)&sndbuf_size, &slen) == -1) err(1, "Unable to get default sndbuf size"); (void)close(s); /* sanity check returned buffer sizes */ if (rcvbuf_size <= 0) rcvbuf_size = 8 * 1024; if (sndbuf_size <= 0) sndbuf_size = 8 * 1024; if (sndbuf_size > 8 * 1024 * 1024) sndbuf_size = 8 * 1024 * 1024; if (rcvbuf_size > 8 * 1024 * 1024) rcvbuf_size = 8 * 1024 * 1024; marg_sl = ftp_sl_init(); if ((tmpdir = getenv("TMPDIR")) == NULL) tmpdir = _PATH_TMP; /* Set default operation mode based on FTPMODE environment variable */ if ((cp = getenv("FTPMODE")) != NULL) { if (strcasecmp(cp, "passive") == 0) { passivemode = 1; activefallback = 0; } else if (strcasecmp(cp, "active") == 0) { passivemode = 0; activefallback = 0; } else if (strcasecmp(cp, "gate") == 0) { gatemode = 1; } else if (strcasecmp(cp, "auto") == 0) { passivemode = 1; activefallback = 1; } else warnx("Unknown $FTPMODE `%s'; using defaults", cp); } if (strcmp(getprogname(), "pftp") == 0) { passivemode = 1; activefallback = 0; } else if (strcmp(getprogname(), "gate-ftp") == 0) gatemode = 1; gateserver = getenv("FTPSERVER"); if (gateserver == NULL || *gateserver == '\0') gateserver = GATE_SERVER; if (gatemode) { if (*gateserver == '\0') { warnx( "Neither $FTPSERVER nor GATE_SERVER is defined; disabling gate-ftp"); gatemode = 0; } } cp = getenv("TERM"); if (cp == NULL || strcmp(cp, "dumb") == 0) dumbterm = 1; else dumbterm = 0; fromatty = isatty(fileno(stdin)); ttyout = stdout; if (isatty(fileno(ttyout))) { verbose = 1; /* verbose if to a tty */ if (! dumbterm) { #ifndef NO_EDITCOMPLETE if (fromatty) /* editing mode on if tty is usable */ editing = 1; #endif #ifndef NO_PROGRESS if (foregroundproc()) progress = 1; /* progress bar on if fg */ #endif } } while ((ch = getopt(argc, argv, "46AadefginN:o:pP:q:r:Rs:tT:u:vV")) != -1) { switch (ch) { case '4': family = AF_INET; break; case '6': #ifdef INET6 family = AF_INET6; #else warnx("INET6 support is not available; ignoring -6"); #endif break; case 'A': activefallback = 0; passivemode = 0; break; case 'a': anonftp = 1; break; case 'd': options |= SO_DEBUG; ftp_debug++; break; case 'e': #ifndef NO_EDITCOMPLETE editing = 0; #endif break; case 'f': flushcache = 1; break; case 'g': doglob = 0; break; case 'i': interactive = 0; break; case 'n': autologin = 0; break; case 'N': if (strlcpy(netrc, optarg, sizeof(netrc)) >= sizeof(netrc)) errx(1, "%s: %s", optarg, strerror(ENAMETOOLONG)); break; case 'o': outfile = optarg; if (strcmp(outfile, "-") == 0) ttyout = stderr; break; case 'p': passivemode = 1; activefallback = 0; break; case 'P': ftpport = optarg; break; case 'q': quit_time = strtol(optarg, &ep, 10); if (quit_time < 1 || *ep != '\0') errx(1, "Bad quit value: %s", optarg); break; case 'r': retry_connect = strtol(optarg, &ep, 10); if (retry_connect < 1 || *ep != '\0') errx(1, "Bad retry value: %s", optarg); break; case 'R': restartautofetch = 1; break; case 's': src_addr = optarg; break; case 't': trace = 1; break; case 'T': { int targc; char *targv[6], *oac; /* look for `dir,max[,incr]' */ targc = 0; targv[targc++] = "-T"; oac = ftp_strdup(optarg); while ((cp = strsep(&oac, ",")) != NULL) { if (*cp == '\0') { warnx("Bad throttle value `%s'", optarg); usage(); /* NOTREACHED */ } targv[targc++] = cp; if (targc >= 5) break; } if (parserate(targc, targv, 1) == -1) usage(); free(oac); break; } case 'u': { isupload = 1; interactive = 0; upload_path = ftp_strdup(optarg); break; } case 'v': progress = verbose = 1; break; case 'V': progress = verbose = 0; break; default: usage(); } } /* set line buffering on ttyout */ setvbuf(ttyout, NULL, _IOLBF, 0); argc -= optind; argv += optind; cpend = 0; /* no pending replies */ proxy = 0; /* proxy not active */ crflag = 1; /* strip c.r. on ascii gets */ sendport = -1; /* not using ports */ if (src_addr != NULL) { struct addrinfo hints; int error; memset(&hints, 0, sizeof(hints)); hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; error = getaddrinfo(src_addr, NULL, &hints, &bindai); if (error) { errx(1, "Can't lookup `%s': %s", src_addr, (error == EAI_SYSTEM) ? strerror(errno) : gai_strerror(error)); } } /* * Cache the user name and home directory. */ localhome = NULL; localname = NULL; anonuser = "******"; cp = getenv("HOME"); if (! EMPTYSTRING(cp)) localhome = ftp_strdup(cp); pw = NULL; cp = getlogin(); if (cp != NULL) pw = getpwnam(cp); if (pw == NULL) pw = getpwuid(getuid()); if (pw != NULL) { if (localhome == NULL && !EMPTYSTRING(pw->pw_dir)) localhome = ftp_strdup(pw->pw_dir); localname = ftp_strdup(pw->pw_name); anonuser = localname; } if (netrc[0] == '\0' && localhome != NULL) { if (strlcpy(netrc, localhome, sizeof(netrc)) >= sizeof(netrc) || strlcat(netrc, "/.netrc", sizeof(netrc)) >= sizeof(netrc)) { warnx("%s/.netrc: %s", localhome, strerror(ENAMETOOLONG)); netrc[0] = '\0'; } } if (localhome == NULL) localhome = ftp_strdup("/"); /* * Every anonymous FTP server I've encountered will accept the * string "username@", and will append the hostname itself. We * do this by default since many servers are picky about not * having a FQDN in the anonymous password. * - [email protected] */ len = strlen(anonuser) + 2; anonpass = ftp_malloc(len); (void)strlcpy(anonpass, anonuser, len); (void)strlcat(anonpass, "@", len); /* * set all the defaults for options defined in * struct option optiontab[] declared in cmdtab.c */ setupoption("anonpass", getenv("FTPANONPASS"), anonpass); setupoption("ftp_proxy", getenv(FTP_PROXY), ""); setupoption("http_proxy", getenv(HTTP_PROXY), ""); setupoption("no_proxy", getenv(NO_PROXY), ""); setupoption("pager", getenv("PAGER"), DEFAULTPAGER); setupoption("prompt", getenv("FTPPROMPT"), DEFAULTPROMPT); setupoption("rprompt", getenv("FTPRPROMPT"), DEFAULTRPROMPT); free(anonpass); setttywidth(0); #ifdef SIGINFO (void)xsignal(SIGINFO, psummary); #endif (void)xsignal(SIGQUIT, psummary); (void)xsignal(SIGUSR1, crankrate); (void)xsignal(SIGUSR2, crankrate); (void)xsignal(SIGWINCH, setttywidth); if (argc > 0) { if (isupload) { rval = auto_put(argc, argv, upload_path); sigint_or_rval_exit: if (sigint_raised) { (void)xsignal(SIGINT, SIG_DFL); raise(SIGINT); } exit(rval); } else if (strchr(argv[0], ':') != NULL && ! isipv6addr(argv[0])) { rval = auto_fetch(argc, argv); if (rval >= 0) /* -1 == connected and cd-ed */ goto sigint_or_rval_exit; } else { char *xargv[4], *user, *host; if ((rval = sigsetjmp(toplevel, 1))) goto sigint_or_rval_exit; (void)xsignal(SIGINT, intr); (void)xsignal(SIGPIPE, lostpeer); user = NULL; host = argv[0]; cp = strchr(host, '@'); if (cp) { *cp = '\0'; user = host; host = cp + 1; } /* XXX discards const */ xargv[0] = (char *)getprogname(); xargv[1] = host; xargv[2] = argv[1]; xargv[3] = NULL; do { int oautologin; oautologin = autologin; if (user != NULL) { anonftp = 0; autologin = 0; } setpeer(argc+1, xargv); autologin = oautologin; if (connected == 1 && user != NULL) (void)ftp_login(host, user, NULL); if (!retry_connect) break; if (!connected) { macnum = 0; fprintf(ttyout, "Retrying in %d seconds...\n", retry_connect); sleep(retry_connect); } } while (!connected); retry_connect = 0; /* connected, stop hiding msgs */ } } if (isupload) usage(); #ifndef NO_EDITCOMPLETE controlediting(); #endif /* !NO_EDITCOMPLETE */ (void)sigsetjmp(toplevel, 1); (void)xsignal(SIGINT, intr); (void)xsignal(SIGPIPE, lostpeer); for (;;) cmdscanner(); }
/* * Retrieve multiple files from the command line, transferring * files of the form "host:path", "ftp://host/path" using the * ftp protocol, and files of the form "http://host/path" using * the http protocol. * If path has a trailing "/", then return (-1); * the path will be cd-ed into and the connection remains open, * and the function will return -1 (to indicate the connection * is alive). * If an error occurs the return value will be the offset+1 in * argv[] of the file that caused a problem (i.e, argv[x] * returns x+1) * Otherwise, 0 is returned if all files retrieved successfully. */ int auto_fetch(int argc, char *argv[], char *outfile) { char *xargv[5]; char *cp, *url, *host, *dir, *file, *portnum; char *username, *pass, *pathstart; char *ftpproxy, *httpproxy; int rval, xargc; volatile int argpos; int dirhasglob, filehasglob, oautologin; char rempath[MAXPATHLEN]; argpos = 0; if (setjmp(toplevel)) { if (connected) disconnect(0, NULL); return (argpos + 1); } (void)signal(SIGINT, (sig_t)intr); (void)signal(SIGPIPE, (sig_t)lostpeer); if ((ftpproxy = getenv(FTP_PROXY)) != NULL && *ftpproxy == '\0') ftpproxy = NULL; if ((httpproxy = getenv(HTTP_PROXY)) != NULL && *httpproxy == '\0') httpproxy = NULL; /* * Loop through as long as there's files to fetch. */ for (rval = 0; (rval == 0) && (argpos < argc); free(url), argpos++) { if (strchr(argv[argpos], ':') == NULL) break; host = dir = file = portnum = username = pass = NULL; /* * We muck with the string, so we make a copy. */ url = strdup(argv[argpos]); if (url == NULL) errx(1, "Can't allocate memory for auto-fetch."); /* * Try HTTP URL-style arguments first. */ if (strncasecmp(url, HTTP_URL, sizeof(HTTP_URL) - 1) == 0 || #ifndef SMALL /* even if we compiled without SSL, url_get will check */ strncasecmp(url, HTTPS_URL, sizeof(HTTPS_URL) -1) == 0 || #endif /* !SMALL */ strncasecmp(url, FILE_URL, sizeof(FILE_URL) - 1) == 0) { redirect_loop = 0; if (url_get(url, httpproxy, outfile) == -1) rval = argpos + 1; continue; } /* * Try FTP URL-style arguments next. If ftpproxy is * set, use url_get() instead of standard ftp. * Finally, try host:file. */ host = url; if (strncasecmp(url, FTP_URL, sizeof(FTP_URL) - 1) == 0) { char *passend, *passagain, *userend; if (ftpproxy) { if (url_get(url, ftpproxy, outfile) == -1) rval = argpos + 1; continue; } host += sizeof(FTP_URL) - 1; dir = strchr(host, '/'); /* Look for [user:pass@]host[:port] */ /* check if we have "user:pass@" */ userend = strchr(host, ':'); passend = strchr(host, '@'); if (passend && userend && userend < passend && (!dir || passend < dir)) { username = host; pass = userend + 1; host = passend + 1; *userend = *passend = '\0'; passagain = strchr(host, '@'); if (strchr(pass, '@') != NULL || (passagain != NULL && passagain < dir)) { warnx(at_encoding_warning); goto bad_ftp_url; } if (EMPTYSTRING(username)) { bad_ftp_url: warnx("Invalid URL: %s", argv[argpos]); rval = argpos + 1; continue; } username = urldecode(username); pass = urldecode(pass); } #ifdef INET6 /* check [host]:port, or [host] */ if (host[0] == '[') { cp = strchr(host, ']'); if (cp && (!dir || cp < dir)) { if (cp + 1 == dir || cp[1] == ':') { host++; *cp++ = '\0'; } else cp = NULL; } else cp = host; } else cp = host; #else cp = host; #endif /* split off host[:port] if there is */ if (cp) { portnum = strchr(cp, ':'); pathstart = strchr(cp, '/'); /* : in path is not a port # indicator */ if (portnum && pathstart && pathstart < portnum) portnum = NULL; if (!portnum) ; else { if (!dir) ; else if (portnum + 1 < dir) { *portnum++ = '\0'; /* * XXX should check if portnum * is decimal number */ } else { /* empty portnum */ goto bad_ftp_url; } } } else portnum = NULL; } else { /* classic style `host:file' */ dir = strchr(host, ':'); } if (EMPTYSTRING(host)) { rval = argpos + 1; continue; } /* * If dir is NULL, the file wasn't specified * (URL looked something like ftp://host) */ if (dir != NULL) *dir++ = '\0'; /* * Extract the file and (if present) directory name. */ if (!EMPTYSTRING(dir)) { cp = strrchr(dir, '/'); if (cp != NULL) { *cp++ = '\0'; file = cp; } else { file = dir; dir = NULL; } } #ifndef SMALL if (debug) fprintf(ttyout, "user %s:%s host %s port %s dir %s file %s\n", username, pass ? "XXXX" : NULL, host, portnum, dir, file); #endif /* !SMALL */ /* * Set up the connection. */ if (connected) disconnect(0, NULL); xargv[0] = __progname; xargv[1] = host; xargv[2] = NULL; xargc = 2; if (!EMPTYSTRING(portnum)) { xargv[2] = portnum; xargv[3] = NULL; xargc = 3; } oautologin = autologin; if (username != NULL) autologin = 0; setpeer(xargc, xargv); autologin = oautologin; if ((connected == 0) || ((connected == 1) && !ftp_login(host, username, pass))) { warnx("Can't connect or login to host `%s'", host); rval = argpos + 1; continue; } /* Always use binary transfers. */ setbinary(0, NULL); dirhasglob = filehasglob = 0; if (doglob) { if (!EMPTYSTRING(dir) && strpbrk(dir, "*?[]{}") != NULL) dirhasglob = 1; if (!EMPTYSTRING(file) && strpbrk(file, "*?[]{}") != NULL) filehasglob = 1; } /* Change directories, if necessary. */ if (!EMPTYSTRING(dir) && !dirhasglob) { xargv[0] = "cd"; xargv[1] = dir; xargv[2] = NULL; cd(2, xargv); if (!dirchange) { rval = argpos + 1; continue; } } if (EMPTYSTRING(file)) { rval = -1; continue; } if (verbose) fprintf(ttyout, "Retrieving %s/%s\n", dir ? dir : "", file); if (dirhasglob) { snprintf(rempath, sizeof(rempath), "%s/%s", dir, file); file = rempath; } /* Fetch the file(s). */ xargc = 2; xargv[0] = "get"; xargv[1] = file; xargv[2] = NULL; if (dirhasglob || filehasglob) { int ointeractive; ointeractive = interactive; interactive = 0; xargv[0] = "mget"; #ifndef SMALL if (resume) { xargc = 3; xargv[1] = "-c"; xargv[2] = file; xargv[3] = NULL; } #endif /* !SMALL */ mget(xargc, xargv); interactive = ointeractive; } else { if (outfile != NULL) { xargv[2] = outfile; xargv[3] = NULL; xargc++; } #ifndef SMALL if (resume) reget(xargc, xargv); else #endif /* !SMALL */ get(xargc, xargv); } if ((code / 100) != COMPLETE) rval = argpos + 1; } if (connected && rval != -1) disconnect(0, NULL); return (rval); }
int main (int argc, char *argv[]) { int top; int index; struct passwd *pw = NULL; char *cp; set_program_name (argv[0]); sp = getservbyname ("ftp", "tcp"); if (sp == 0) error (EXIT_FAILURE, 0, "ftp/tcp: unknown service"); doglob = 1; interactive = 1; autologin = 1; /* Parse command line */ iu_argp_init ("ftp", default_program_authors); argp_parse (&argp, argc, argv, 0, &index, NULL); argc -= index; argv += index; fromatty = isatty (fileno (stdin)); if (fromatty) { verbose++; if (!prompt) prompt = DEFAULT_PROMPT; } cpend = 0; /* no pending replies */ proxy = 0; /* proxy not active */ passivemode = 0; /* passive mode not active */ crflag = 1; /* strip c.r. on ascii gets */ sendport = -1; /* not using ports */ /* * Set up the home directory in case we're globbing. */ cp = getlogin (); if (cp != NULL) pw = getpwnam (cp); if (pw == NULL) pw = getpwuid (getuid ()); if (pw != NULL) { char *buf = malloc (strlen (pw->pw_dir) + 1); if (buf) { strcpy (buf, pw->pw_dir); home = buf; } } if (argc > 0) { char *xargv[5]; if (setjmp (toplevel)) exit (EXIT_SUCCESS); signal (SIGINT, intr); signal (SIGPIPE, lostpeer); xargv[0] = program_invocation_name; xargv[1] = argv[0]; xargv[2] = argv[1]; xargv[3] = argv[2]; xargv[4] = NULL; setpeer (argc + 1, xargv); } top = setjmp (toplevel) == 0; if (top) { signal (SIGINT, intr); signal (SIGPIPE, lostpeer); } for (;;) { cmdscanner (top); top = 1; } }