aboutsummaryrefslogtreecommitdiff
path: root/usr.bin/fetch/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/fetch/main.c')
-rw-r--r--usr.bin/fetch/main.c903
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;
-}
-