diff options
Diffstat (limited to 'usr.bin/fetch/main.c')
| -rw-r--r-- | usr.bin/fetch/main.c | 903 |
1 files changed, 219 insertions, 684 deletions
diff --git a/usr.bin/fetch/main.c b/usr.bin/fetch/main.c index cc40e3290015d..50845c7bfd47f 100644 --- a/usr.bin/fetch/main.c +++ b/usr.bin/fetch/main.c @@ -27,403 +27,282 @@ /* $FreeBSD$ */ #include <sys/types.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <pwd.h> -#include <unistd.h> - -#include <netinet/in.h> - -#include <arpa/inet.h> #include <err.h> #include <errno.h> -#include <netdb.h> -#include <pwd.h> -#include <regex.h> +#include <limits.h> /* needed for INT_MAX */ +#include <setjmp.h> #include <signal.h> -#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sysexits.h> #include <unistd.h> -#include <ftpio.h> +#include <sys/param.h> /* for MAXHOSTNAMELEN */ +#include <sys/time.h> /* for struct timeval, gettimeofday */ -#define BUFFER_SIZE 1024 -#define HTTP_TIMEOUT 300 /* seconds */ -#define FTP_TIMEOUT 300 /* seconds */ +#include "fetch.h" -char buffer[BUFFER_SIZE]; +static struct fetch_state clean_fetch_state; +static sigjmp_buf sigbuf; +static int get(struct fetch_state *volatile fs); -extern char *__progname; /* from crt0.o */ - -int verbose = 1; -int ftp_verbose = 0; -int linkfile = 0; -char *outputfile = 0; -char *change_to_dir = 0; -char *host = 0; -int passive_mode = 0; -char *file_to_get = 0; -int ftp = 0; -int http_proxy = 0; -int http = 0; -int http_port = 80; -int mirror = 0; -int newtime = 0; -int restart = 0; -time_t modtime; -FILE *file = 0; -int timeout_ival = 0; - -void usage(void), die(int), rm(void), timeout(int), ftpget(void), - httpget(void), fileget(void), - display(int, int), parse(char *), output_file_name(void), - f_size(char *, off_t *, time_t *), ftperr(FILE* ftp, char *, ...), - filter(unsigned char *, int), - setup_http_proxy(void); - -int match(char *, char *), http_open(void); - -void -usage() +static void +usage(const char *argv0) { - fprintf(stderr, "usage: %s [-DHINPMTVLqlmnprv] [-o outputfile] <-f file -h host [-c dir]| URL>\n", __progname); - exit(1); -} - -void -die(int sig) -{ - int e = errno; - - rm(); - if (!sig) - fprintf (stderr, "%s: %s\n", __progname, strerror(e)); - else - warnx ("Interrupted by signal %d", sig); - exit(1); -} - -void -adjmodtime() -{ - struct timeval tv[2]; - - if (!newtime) { - tv[0].tv_usec = tv[1].tv_usec = 0; - tv[0].tv_sec = time(0); - tv[1].tv_sec = modtime; - utimes (outputfile, tv); - } + fprintf(stderr, + "%s: usage:\n\t%s [-DHINPMTVLqlmnprv] [-o outputfile] " + "[-f file -h host [-c dir] | URL]\n", argv0, argv0); + exit(EX_USAGE); } -void -rm() -{ - if (file) { - fclose(file); - if (file != stdout) { - if (!restart && !mirror) - remove(outputfile); - adjmodtime(); - } - } -} int -main(int argc, char **argv) +main(int argc, char *const *argv) { int c; - char *s; + char *ep; + struct fetch_state fs; + const char *change_to_dir, *file_to_get, *hostname; + int error, rv; + unsigned long l; - while ((c = getopt (argc, argv, "D:HINPMT:V:Lqc:f:h:o:plmnrv")) != -1) { - switch (c) { - case 'D': case 'H': case 'I': case 'N': case 'L': case 'V': - break; /* ncftp compatibility */ - - case 'q': - verbose = 0; + init_schemes(); + fs = clean_fetch_state; + fs.fs_verbose = 1; + change_to_dir = file_to_get = hostname = 0; + + while ((c = getopt(argc, argv, "D:HINPMT:V:Lqc:f:h:o:plmnrv")) != -1) { + switch (c) { + case 'D': case 'H': case 'I': case 'N': case 'L': case 'V': + break; /* ncftp compatibility */ - case 'c': - change_to_dir = optarg; - break; + case 'q': + fs.fs_verbose = 0; + + case 'c': + change_to_dir = optarg; + break; - case 'f': - file_to_get = optarg; - break; + case 'f': + file_to_get = optarg; + break; - case 'h': - host = optarg; - ftp = 1; - break; + case 'h': + hostname = optarg; + break; - case 'l': - linkfile = 1; - break; + case 'l': + fs.fs_linkfile = 1; + break; - case 'o': - outputfile = optarg; - break; - - case 'p': case 'P': - passive_mode = 1; - break; + case 'o': + fs.fs_outputfile = optarg; + break; + + case 'p': case 'P': + fs.fs_passive_mode = 1; + break; - case 'm': case 'M': - mirror = 1; - break; + case 'm': case 'M': + fs.fs_mirror = 1; + break; - case 'n': - newtime = 1; - break; + case 'n': + fs.fs_newtime = 1; + break; - case 'r': - restart = 1; - break; + case 'r': + fs.fs_restart = 1; + break; + + case 'R': + fs.fs_precious = 1; + break; - case 'v': - ftp_verbose = 1; - break; + case 'v': + if (fs.fs_verbose < 2) + fs.fs_verbose = 2; + else + fs.fs_verbose++; + break; - case 'T': - timeout_ival = atoi(optarg); - break; + case 'T': + /* strtol sets errno to ERANGE in the case of overflow */ + errno = 0; + l = strtoul(optarg, &ep, 0); + if (!optarg[0] || *ep || errno != 0 || l > INT_MAX) + errx(EX_USAGE, "invalid timeout value: `%s'", + optarg); + fs.fs_timeout = l; + break; - default: - case '?': - usage(); - } + default: + case '?': + usage(argv[0]); + } } - argc -= optind; - argv += optind; - if (argv[0]) { - if (host || change_to_dir || file_to_get) - usage(); - s = strdup(argv[0]); - if (s == NULL) - s = argv[0]; /* optomistic, I know.. malloc just failed. */ - parse(s); - } else { - if (!host || !file_to_get) - usage(); + + clean_fetch_state = fs; /* preserve option settings */ + + if (argv[optind] && (hostname || change_to_dir || file_to_get)) { + warnx("cannot use -h, -c, or -f with a URI argument"); + usage(argv[0]); } - - if (mirror && restart) - errx(1, "-m and -r are mutually exclusive."); - - output_file_name(); - - signal(SIGHUP, die); - signal(SIGINT, die); - signal(SIGQUIT, die); - signal(SIGTERM, die); - - setup_http_proxy(); - if (http) - httpget(); - else if (ftp) - ftpget(); - else - fileget(); - exit(0); -} + if (fs.fs_mirror && fs.fs_restart) + errx(EX_USAGE, "-m and -r are mutually exclusive."); + + if (argv[optind] == 0) { + char *uri; -void -timeout(int sig) -{ - fprintf (stderr, "\n%s: Timeout\n", __progname); - rm(); - exit(1); -} + if (hostname == 0) hostname = "localhost"; + if (change_to_dir == 0) change_to_dir = ""; + if (file_to_get == 0) { + usage(argv[0]); + } -void -fileget() -{ - char *basename; + uri = alloca(sizeof("ftp://") + strlen(hostname) + + strlen(change_to_dir) + 2 + strlen(file_to_get)); + strcpy(uri, "ftp://"); + strcat(uri, hostname); + /* + * XXX - we should %-map a leading `/' into `%2f', but for + * anonymous FTP it is unlikely to matter. Still, it would + * be better to follow the spec. + */ + if (change_to_dir[0] != '/') + strcat(uri, "/"); + strcat(uri, change_to_dir); + if (file_to_get[0] != '/' && uri[strlen(uri) - 1] != '/') + strcat(uri, "/"); + strcat(uri, file_to_get); - if (access(file_to_get, R_OK)) { - fprintf(stderr, "unable to access local file `%s'\n", file_to_get); - exit(1); - } - basename = strrchr(file_to_get, '/'); - if (!basename) { - fprintf(stderr, "malformed filename `%s' - expected full path.\n", - file_to_get); - exit(1); + error = parse_uri(&fs, uri); + if (error) + return error; + return get(&fs); } - ++basename; /* move over the / */ - if (!access(basename, F_OK)) { - fprintf(stderr, "%s: file already exists.\n", basename); - exit(1); - } - if (linkfile) { - if (symlink(file_to_get, basename) == -1) { - perror("symlink"); - exit(1); - } - } - else { - char *buf = alloca(strlen(file_to_get) + strlen(basename) + 15); - sprintf(buf, "/bin/cp -p %s %s", file_to_get, basename); - if (system(buf)) { - fprintf(stderr, "failed to copy %s successfully.", file_to_get); - exit(1); - } + for (rv = 0; argv[optind] != 0; optind++) { + error = parse_uri(&fs, argv[optind]); + if (error) { + rv = error; + continue; + } + + error = get(&fs); + if (error) { + rv = error; + } + fs = clean_fetch_state; } + return rv; } - -void -ftpget() -{ - FILE *ftp, *fp; - char *cp, *lp; - int status, n; - off_t size, size0, seekloc; - char ftp_pw[200]; - time_t t; - if ((cp = getenv("FTP_PASSWORD")) != NULL) - strcpy(ftp_pw, cp); - else { - sprintf (ftp_pw, "%s@", getpwuid (getuid ())->pw_name); - n = strlen (ftp_pw); - gethostname (ftp_pw + n, 200 - n); - } - if ((lp = getenv("FTP_LOGIN")) == NULL) - lp = "anonymous"; - ftp = ftpLogin(host, lp, ftp_pw, 0, ftp_verbose, &status); - if (!ftp) { - if (status) - errx(1, "%s: %s", host, ftpErrString(status)); - else - errx(1, "couldn't open FTP connection to %s: %s", - host, hstrerror(h_errno)); - } +/* + * The signal handling is probably more complex than it needs to be, + * but it doesn't cost a lot, so we'll be extra-careful. Using + * siglongjmp() to get out of the signal handler allows us to + * call rm() without having to store the state variable in some global + * spot where the signal handler can get at it. We also obviate the need + * for a separate timeout signal handler. + */ +static int +get(struct fetch_state *volatile fs) +{ + volatile int error; + struct sigaction oldhup, oldint, oldquit, oldterm; + struct sigaction catch; + volatile sigset_t omask; - /* Time to set our defaults */ - ftpBinary (ftp); - ftpPassive (ftp, passive_mode); - - if (change_to_dir) { - status = ftpChdir (ftp, change_to_dir); - if (status) - ftperr (ftp, "couldn't cd to %s: ", change_to_dir); - } - size = ftpGetSize (ftp, file_to_get); - modtime = ftpGetModtime (ftp, file_to_get); - if (modtime <= 0) { - warnx ("Couldn't get file time for %s - using current time", file_to_get); - modtime = (time_t) -1; - } - - if (!strcmp (outputfile, "-")) - restart = 0; - if (restart || mirror) { - f_size (outputfile, &size0, &t); - if (mirror && size0 == size && modtime <= t) { - fclose(ftp); - return; - } - else if (restart) { - if (size0 && size0 < size) - seekloc = size0; - else - seekloc = size0 = 0; + sigemptyset(&catch.sa_mask); + sigaddset(&catch.sa_mask, SIGHUP); + sigaddset(&catch.sa_mask, SIGINT); + sigaddset(&catch.sa_mask, SIGQUIT); + sigaddset(&catch.sa_mask, SIGTERM); + sigaddset(&catch.sa_mask, SIGALRM); + catch.sa_handler = catchsig; + catch.sa_flags = 0; + + sigprocmask(SIG_BLOCK, &catch.sa_mask, (sigset_t *)&omask); + sigaction(SIGHUP, &catch, &oldhup); + sigaction(SIGINT, &catch, &oldint); + sigaction(SIGQUIT, &catch, &oldquit); + sigaction(SIGTERM, &catch, &oldterm); + + error = sigsetjmp(sigbuf, 0); + if (error == SIGALRM) { + rm(fs); + unsetup_sigalrm(); + fprintf(stderr, "\n"); /* just in case */ + warnx("%s: %s: timed out", fs->fs_outputfile, fs->fs_status); + goto close; + } else if (error) { + rm(fs); + fprintf(stderr, "\n"); /* just in case */ + warnx("%s: interrupted by signal: %s", fs->fs_status, + sys_signame[error]); + sigdelset(&omask, error); + signal(error, SIG_DFL); + sigprocmask(SIG_SETMASK, (sigset_t *)&omask, 0); + raise(error); /* so that it gets reported as such */ } - } - else if (!restart) - seekloc = size0 = 0; - - fp = ftpGet (ftp, file_to_get, &seekloc); - if (fp == NULL) - if (ftpErrno(ftp)) - ftperr (ftp, NULL); - else - die(0); - if (size0 && !seekloc) - size0 = 0; - - if (strcmp (outputfile, "-")) { - file = fopen (outputfile, size0 ? "a" : "w"); - if (!file) - err (1, "could not open output file %s.", outputfile); - } else - file = stdout; - - if (timeout_ival) { - char env[80]; - /* Override any environment variable */ - snprintf(env, sizeof env - 1, "FTP_TIMEOUT=%d", timeout_ival); - putenv(env); - } - else { - char *cp = getenv("FTP_TIMEOUT"); - if (!cp || !(timeout_ival = atoi(cp))) - timeout_ival = FTP_TIMEOUT; - } + sigprocmask(SIG_SETMASK, (sigset_t *)&omask, 0); + error = fs->fs_retrieve(fs); - display (size, size0); - while (1) { - struct sigaction act; +close: + sigaction(SIGHUP, &oldhup, 0); + sigaction(SIGINT, &oldint, 0); + sigaction(SIGQUIT, &oldquit, 0); + sigaction(SIGTERM, &oldterm, 0); + fs->fs_close(fs); - act.sa_handler = timeout; - act.sa_mask = 0; - act.sa_flags = 0; - sigaction(SIGALRM, &act, NULL); - alarm(timeout_ival); - n = status = fread (buffer, 1, BUFFER_SIZE, fp); - alarm(0); - act.sa_handler = SIG_DFL; - sigaction(SIGALRM, &act, NULL); - if (status <= 0) - break; - display (size, n); - status = fwrite (buffer, 1, n, file); - if (status != n) - break; - } - if (status < 0) - die(0); - fclose(fp); - fclose(file); - display (size, -1); - if (file != stdout) - adjmodtime(); - exit (0); + return error; } + +/* + * Utility functions + */ + +/* + * Handle all signals by jumping back into get(). + */ void -display (int size, int n) +catchsig(int sig) { - static int bytes, pr, init = 0; + siglongjmp(sigbuf, sig); +} + +/* Used to generate the progress display when not in quiet mode. */ +void +display(struct fetch_state *fs, off_t size, ssize_t n) +{ + static off_t bytes; + static int pr, init = 0; static struct timeval t0, t_start; static char *s; struct timezone tz; struct timeval t; float d; - if (!verbose) + if (!fs->fs_verbose) return; if (init == 0) { init = 1; gettimeofday(&t0, &tz); t_start = t0; bytes = pr = 0; - s = (char *) malloc (strlen(outputfile) + 50); + s = malloc(strlen(fs->fs_outputfile) + 50); if (size > 0) - sprintf (s, "Receiving %s (%d bytes)%s", outputfile, size, + sprintf (s, "Receiving %s (%qd bytes)%s", fs->fs_outputfile, + (quad_t)size, size ? "" : " [appending]"); else - sprintf (s, "Receiving %s", outputfile); + sprintf (s, "Receiving %s", fs->fs_outputfile); printf ("%s", s); fflush (stdout); bytes = n; @@ -434,16 +313,18 @@ display (int size, int n) if (size > 0) printf ("\r%s: 100%%", s); else - printf ("\r%s: %d Kbytes", s, bytes/1024); + printf ("\r%s: %qd Kbytes", s, (quad_t)bytes/1024); d = t.tv_sec + t.tv_usec/1.e6 - t_start.tv_sec - t_start.tv_usec/1.e6; - printf ("\n%d bytes transfered in %.1f seconds", bytes, d); + printf ("\n%qd bytes transfered in %.1f seconds", (quad_t)bytes, d); d = bytes/d; if (d < 1000) - printf (" (%d Bytes/s)\n", (int)d); + printf (" (%.0f bytes/s)\n", d); else { d /=1024; - printf (" (%.2f K/s)\n", d); + printf (" (%.2f kB/s)\n", d); } + free(s); + init = 0; return; } bytes += n; @@ -453,357 +334,11 @@ display (int size, int n) t0 = t; pr++; if (size > 1000000) - printf ("\r%s: %2d%%", s, bytes/(size/100)); + printf ("\r%s: %2qd%%", s, (quad_t)bytes/(size/100)); else if (size > 0) - printf ("\r%s: %2d%%", s, 100*bytes/size); + printf ("\r%s: %2qd%%", s, (quad_t)100*bytes/size); else - printf ("\r%s: %d Kbytes", s, bytes/1024); + printf ("\r%s: %qd kB", s, (quad_t)bytes/1024); fflush (stdout); } -void -parse (char *s) -{ - char *p; - - if (strncasecmp (s, "file:", 5) == 0) { - /* file:filename */ - s += 4; - *s++ = '\0'; - host = NULL; - ftp = http = 0; - file_to_get = s; - return; - } - else if (strncasecmp (s, "ftp://", 6) == 0) { - /* ftp://host.name/file/name */ - s += 6; - p = strchr(s, '/'); - if (!p) { - warnx("no filename??"); - usage(); - } - } - else if (strncasecmp (s, "http://", 7) == 0) { - /* http://host.name/file/name */ - char *q; - s += 7; - p = strchr(s, '/'); - if (!p) { - warnx ("no filename??"); - usage (); - } - *p++ = 0; - q = strchr (s, ':'); - if (q && q < p) { - *q++ = 0; - http_port = atoi (q); - } - host = s; - file_to_get = p; - http = 1; - return; - } - else { - /* assume host.name:/file/name */ - p = strchr (s, ':'); - if (!p) { - /* assume /file/name */ - host = NULL; - ftp = http = 0; - file_to_get = s; - return; - } - } - ftp = 1; - *p++ = 0; - host = s; - s = strrchr (p, '/'); - if (s) { - *s++ = 0; - change_to_dir = p; - file_to_get = s; - } else { - change_to_dir = 0; - file_to_get = p; - } -} - -void -output_file_name () -{ - char *p; - - if (!outputfile) { - p = strrchr (file_to_get, '/'); - if (!p || (!ftp && !http)) - p = file_to_get; - else - p++; - outputfile = strdup (p); - } -} - -void -f_size (char *name, off_t *size, time_t *time) -{ - struct stat s; - - *size = 0; - - if (stat (name, &s)) - return; - *size = s.st_size; - *time = s.st_mtime; -} - -void -ftperr (FILE* ftp, char *fmt, ...) -{ - va_list ap; - va_start (ap, fmt); - - if (fmt) - vfprintf(stderr, fmt, ap); - if(ftp) { - const char *str = ftpErrString(ftpErrno(ftp)); - - if (str) - fprintf(stderr, "%s\n", str); - } - rm (); - exit (1); -} - -void -httpget () -{ - char *cp, str[1000]; - struct timeval tv; - time_t tout; - fd_set fdset; - int i, s; - - restart = 0; - - s = http_open (); - sprintf (str, "GET %s%s HTTP/1.0\r\n\r\n", - http_proxy? "" : "/", file_to_get); - i = strlen (str); - if (i != write (s, str, i)) - err (1, "could not send GET command to HTTP server."); - - FD_ZERO (&fdset); - FD_SET (s, &fdset); - if (timeout_ival) - tout = timeout_ival; - else if ((cp = getenv("HTTP_TIMEOUT")) != NULL) - tout = atoi(cp); - else - tout = HTTP_TIMEOUT; - - if (strcmp (outputfile, "-")) { - file = fopen (outputfile, "w"); - if (!file) - err (1, "could not open output file %s.", outputfile); - } else { - file = stdout; - verbose = 0; - } - - while (1) { - tv.tv_sec = tout; - tv.tv_usec = 0; - i = select (s+1, &fdset, 0, 0, &tv); - switch (i) { - case 0: - warnx ("Timeout"); - rm (); - exit (1); - case 1: - i = read (s, buffer, sizeof (buffer)); - filter (buffer, i); - if (i == 0) - exit (0); - break; - default: - err (1, "communication error with HTTP server."); - } - } -} - -int -match (char *pat, char *s) -{ - regex_t preg; - regmatch_t pmatch[2]; - - regcomp (&preg, pat, REG_EXTENDED|REG_ICASE); - if (regexec(&preg, s, 2, pmatch, 0)) - return 0; - return pmatch[1].rm_so ? pmatch[1].rm_so : -1; -} - -void -filter (unsigned char *p, int len) -{ -#define S 512 - static unsigned char s[S+2]; - static int header_len = 0, size = -1, n; - int i = len; - unsigned char *q = p; - - if (header_len < S) { - while (header_len < S && i--) - s[header_len++] = *q++; - s[header_len] = 0; - if (len && (header_len < S)) - return; - if (match ("^HTTP/[0-9]+\\.[0-9]+[ \t]+200[^0-9]", s) == 0) { - /* maybe not found, or document w/o header */ - if (match ("^HTTP/[0-9]+\\.[0-9]+[ \t]+[0-9]+", s)) { - fprintf (stderr, "%s fetching failed, header so far:\n%s\n", file_to_get, s); - rm (); - exit (1); - } - /* assume no header */ - /* write s */ - display (size, 0); - i = fwrite (s, 1, header_len, file); - if (i != header_len) - die(0); - display (size, header_len); - /* then p */ - if (p+len > q) { - i = fwrite (q, 1, p+len-q, file); - if (i != p+len-q) - die(0); - display (size, i); - } - } else { - unsigned char *t; - /* document begins with a success line. try to get size */ - i = match ("content-length:[ \t]*([0-9]+)", s); - if (i > 0) - size = atoi (s+i); - /* assume that the file to get begins after an empty line */ - i = match ("(\n\n|\r\n\r\n)", s); - if (i > 0) { - if (s[i] == '\r') - t = s+i+4; - else - t = s+i+2; - } else { - fprintf (stderr, "Can't decode the header!\n"); - rm (); - exit (1); - } - display (size, 0); - n = (s-t)+header_len; - i = fwrite (t, 1, n, file); - if (i != n) - die(0); - display (size, n); - if (p+len > q) { - n = p+len-q; - i = fwrite (q, 1, n, file); - if (i != n) - die(0); - display (size, n); - } - } - } else { - i = fwrite (p, 1, len, file); - if (i != len) - die(0); - if (len) - display (size, i); - } - if (len == 0) - display (size, -1); -} - -int -http_open() -{ - unsigned long a; - struct sockaddr_in sin, sin2; - struct hostent *h; - int s; - - a = inet_addr (host); - if (a != INADDR_NONE) { - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = a; - } else { - h = gethostbyname (host); - if (!h) - err (1, "could not lookup host %s.", host); - sin.sin_family = h->h_addrtype; - bcopy(h->h_addr, (char *)&sin.sin_addr, h->h_length); - } - sin.sin_port = htons (http_port); - if ((s = socket (sin.sin_family, SOCK_STREAM, 0)) < 0) - err (1, "socket"); - bzero ((char *)&sin2, sizeof (sin2)); - sin2.sin_family = AF_INET; - sin2.sin_port = 0; - sin2.sin_addr.s_addr = htonl (INADDR_ANY); - if (bind (s, (struct sockaddr *)&sin2, sizeof (sin2))) - err (1, "could not bind to socket."); - - if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) - err (1, "connection failed"); - return s; -} - -int -isDebug () -{ - return 0; -} - -void msgDebug (char *p) -{ - printf ("%s", p); -} - -void -setup_http_proxy() -{ - char *e; - char *p; - char *url; - unsigned short port; - - if (!(e = getenv("HTTP_PROXY")) - || !(p = strchr(e, ':')) - || (port = atoi(p+1)) == 0) - return; - - if (!(url = (char *) malloc (strlen(file_to_get) - + strlen(host) - + (change_to_dir ? strlen(change_to_dir) : 0) - + 50))) - return; - - if (http) { - sprintf(url, "http://%s:%d/%s", - host, http_port, file_to_get); - } else { - if (change_to_dir) { - sprintf(url, "ftp://%s/%s/%s", - host, change_to_dir, file_to_get); - } else { - sprintf(url, "ftp://%s/%s", host, file_to_get); - } - } - file_to_get = url; - - *p = 0; - host = strdup(e); - http_port = port; - http = 1; - http_proxy = 1; -} - |
