diff options
author | jkh <jkh@FreeBSD.org> | 1996-08-22 21:30:51 +0000 |
---|---|---|
committer | jkh <jkh@FreeBSD.org> | 1996-08-22 21:30:51 +0000 |
commit | 6e3ba357ba8136aae4c355e11be07a892072ca75 (patch) | |
tree | 23bb5602e767db49e568fe1f5a5b336a826df146 /usr.bin | |
parent | 1fe796a5c3283fd9badf6d524b5108aa39a3a1f9 (diff) | |
download | FreeBSD-src-6e3ba357ba8136aae4c355e11be07a892072ca75.zip FreeBSD-src-6e3ba357ba8136aae4c355e11be07a892072ca75.tar.gz |
1. Understand file:/path style URLs.
2. Add a -l flag for symlinking to rather than copying file:/path style URLs.
3. Add a -T flag for setting the timeout interval (overrides FTP_TIMEOUT if set)
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/fetch/fetch.1 | 18 | ||||
-rw-r--r-- | usr.bin/fetch/main.c | 1096 |
2 files changed, 600 insertions, 514 deletions
diff --git a/usr.bin/fetch/fetch.1 b/usr.bin/fetch/fetch.1 index fcc33b1..a952a7b 100644 --- a/usr.bin/fetch/fetch.1 +++ b/usr.bin/fetch/fetch.1 @@ -1,4 +1,4 @@ -.\" $Id: fetch.1,v 1.3 1996/07/18 00:07:59 jkh Exp $ +.\" $Id: fetch.1,v 1.4 1996/08/14 17:50:22 jkh Exp $ .Dd July 2, 1996 .Dt FETCH 1 .Os @@ -34,6 +34,11 @@ For compatibility with the form .Em site.domain:/path/to/the/file is also accepted. +To denote a local filename to be copied or linked to (see +.Fl l +flag), the +.Em file:/path/to/the/file +URL form is used. The second form of the command can be used to get a file using the .Em ftp @@ -68,6 +73,17 @@ on the remote host. Set the .Ar host for transfer. +.It Fl l +If target is a +.Ar file:/ +style of URL, make a link to the target rather than trying +to copy it. +.It Fl T Ar seconds +Set timeout value to +.Ar seconds. +Overrides +.Ev FTP_TIMEOUT +environment variable, if set. .It Fl q Quiet mode. Do not report transfer progress on the terminal. .It Fl r diff --git a/usr.bin/fetch/main.c b/usr.bin/fetch/main.c index 33bf709..5e5f998 100644 --- a/usr.bin/fetch/main.c +++ b/usr.bin/fetch/main.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. */ -/* $Id: main.c,v 1.15 1996/08/14 17:50:23 jkh Exp $ */ +/* $Id: main.c,v 1.16 1996/08/21 01:27:25 jkh Exp $ */ #include <stdlib.h> #include <stdio.h> @@ -55,11 +55,13 @@ char buffer[BUFFER_SIZE]; char *progname; int verbose = 1; +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; @@ -68,38 +70,42 @@ int newtime = 0; int restart = 0; time_t modtime; FILE *file = 0; +int timeout_ival = 0; -void usage (), die (), rm (), t_out (), ftpget (), httpget (), - display (int, int), parse (char *), output_file_name(), - f_size (char *, int *, time_t *), ftperr (FILE* ftp, char *, ...), - filter (unsigned char *, int), - setup_http_proxy(); -int match (char *, char *), http_open (); +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 *, int *, time_t *), ftperr(FILE* ftp, char *, ...), + filter(unsigned char *, int), + setup_http_proxy(void); + +int match(char *, char *), http_open(void); void -usage () +usage() { - fprintf (stderr, "usage: %s [-D:HINPMV:Lqmnpr] [-o outputfile] <-f file -h host [-c dir]| URL>\n", progname); - exit (1); + fprintf(stderr, "usage: %s [-DHINPMTVLqlmnpr] [-o outputfile] <-f file -h host [-c dir]| URL>\n", progname); + exit(1); } void -die () +die(int sig) { - int e = errno; - rm (); - if (errno) - fprintf (stderr, "%s: %s\n", progname, sys_errlist[e]); - else - fprintf (stderr, "%s: Interrupted by signal\n", progname); - exit (1); + int e = errno; + + rm(); + if (errno) + fprintf (stderr, "%s: %s\n", progname, sys_errlist[e]); + else + fprintf (stderr, "%s: Interrupted by signal\n", progname); + 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); @@ -112,596 +118,660 @@ void rm() { if (file) { - fclose (file); + fclose(file); if (file != stdout) { if (!restart && !mirror) - remove (outputfile); + remove(outputfile); adjmodtime(); } } } int -main (int argc, char **argv) +main(int argc, char **argv) { - int c; - char *s = strrchr (argv[0], '/'); - - progname = s ? s+1 : argv[0]; - - while ((c = getopt (argc, argv, "D:HINPMV:Lqc:f:h:o:pmnr")) != EOF) { - switch (c) { - case 'D': case 'H': case 'I': case 'N': case 'L': case 'V': - break; /* ncftp compatibility */ - - case 'q': - verbose = 0; - - case 'c': - change_to_dir = optarg; - break; - - case 'f': - file_to_get = optarg; - break; - - case 'h': - host = optarg; - break; - - case 'o': - outputfile = optarg; - break; - - case 'p': case 'P': - passive_mode = 1; - break; - - case 'm': case 'M': - mirror = 1; - break; - - case 'n': - newtime = 1; - break; - - case 'r': - restart = 1; - break; - - default: - case '?': - usage (); - } - } - argc -= optind; - argv += optind; - if (argv[0]) { - if (host || change_to_dir || file_to_get) - usage (); - parse (argv[0]); - } else { - if (!host || !file_to_get) - usage (); + int c; + char *s = strrchr (argv[0], '/'); + + progname = s ? s+1 : argv[0]; + + while ((c = getopt (argc, argv, "D:HINPMT:V:Lqc:f:h:o:plmnr")) != EOF) { + switch (c) { + case 'D': case 'H': case 'I': case 'N': case 'L': case 'V': + break; /* ncftp compatibility */ + + case 'q': + verbose = 0; + + case 'c': + change_to_dir = optarg; + break; + + case 'f': + file_to_get = optarg; + break; + + case 'h': + host = optarg; + break; + + case 'l': + linkfile = 1; + break; + + case 'o': + outputfile = optarg; + break; + + case 'p': case 'P': + passive_mode = 1; + break; + + case 'm': case 'M': + mirror = 1; + break; + + case 'n': + newtime = 1; + break; + + case 'r': + restart = 1; + break; + + case 'T': + timeout_ival = atoi(optarg); + break; + + default: + case '?': + usage(); } - - 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 - ftpget (); - exit (0); + } + argc -= optind; + argv += optind; + if (argv[0]) { + if (host || change_to_dir || file_to_get) + usage(); + parse(argv[0]); + } else { + if (!host || !file_to_get) + usage(); + } + + if (mirror && restart) + errx(1, "-m and -r are mutually exclusive."); + + if ((ftp || http) && linkfile) + warnx("-l flag is meaningless with http or ftp URL specifications"); + + 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); } void -t_out () +timeout(int sig) { - fprintf (stderr, "\n%s: Timeout\n", progname); - rm (); - exit (1); + fprintf(stderr, "\n%s: Timeout\n", progname); + rm(); + exit(1); } void -ftpget () +fileget() { - FILE *ftp, *fp; - char *cp, *lp; - int status, n; - ssize_t size, size0, seekloc; - char ftp_pw[200]; - time_t t; - struct itimerval timer; - - 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, verbose); - if (!ftp) - err(1, "couldn't open FTP connection or login to %s.", host); - - ftpVerbose (ftp, 0); + char *basename; - /* 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); + 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); + } + ++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); } - size = ftpGetSize (ftp, file_to_get); - modtime = ftpGetModtime (ftp, file_to_get); - if (modtime < -1) { - warnx ("Couldn't get file time for %s - using current time", file_to_get); - modtime = (time_t) -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); } + } +} - 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 && modtime == t) - seekloc = size0; - else - seekloc = size0 = 0; - } - } - else if (!restart) - seekloc = size0 = 0; - - fp = ftpGet (ftp, file_to_get, &seekloc); - if (fp == NULL) - if (ftpErrno(ftp)) - ftperr (ftp, NULL); +void +ftpget() +{ + FILE *ftp, *fp; + char *cp, *lp; + int status, n; + ssize_t size, size0, seekloc; + char ftp_pw[200]; + time_t t; + struct itimerval timer; + + 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, verbose); + if (!ftp) + err(1, "couldn't open FTP connection or login to %s.", host); + + ftpVerbose (ftp, 0); + + /* 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 < -1) { + 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 && modtime == t) + seekloc = size0; else - die (); - 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; - - signal (SIGALRM, t_out); - if ((cp = getenv("FTP_TIMEOUT")) != NULL) - timer.it_interval.tv_sec = timer.it_value.tv_sec = atoi(cp); + seekloc = size0 = 0; + } + } + else if (!restart) + seekloc = size0 = 0; + + fp = ftpGet (ftp, file_to_get, &seekloc); + if (fp == NULL) + if (ftpErrno(ftp)) + ftperr (ftp, NULL); else - timer.it_interval.tv_sec = timer.it_value.tv_sec = FTP_TIMEOUT; + 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; + + signal (SIGALRM, timeout); + if (timeout_ival) + timer.it_interval.tv_sec = timer.it_value.tv_sec = timeout_ival; + else if ((cp = getenv("FTP_TIMEOUT")) != NULL) + timer.it_interval.tv_sec = timer.it_value.tv_sec = atoi(cp); + else + timer.it_interval.tv_sec = timer.it_value.tv_sec = FTP_TIMEOUT; + timer.it_interval.tv_usec = timer.it_value.tv_usec = 0; + setitimer(ITIMER_REAL, &timer, 0); + + display (size, size0); + while (1) { + n = status = fread (buffer, 1, BUFFER_SIZE, fp); + if (status <= 0) + break; + display (size, n); + status = fwrite (buffer, 1, n, file); + if (status != n) + break; + timer.it_interval.tv_sec = timer.it_value.tv_sec = FTP_TIMEOUT; timer.it_interval.tv_usec = timer.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &timer, 0); - - display (size, size0); - while (1) { - n = status = fread (buffer, 1, BUFFER_SIZE, fp); - if (status <= 0) - break; - display (size, n); - status = fwrite (buffer, 1, n, file); - if (status != n) - break; - timer.it_interval.tv_sec = timer.it_value.tv_sec = FTP_TIMEOUT; - timer.it_interval.tv_usec = timer.it_value.tv_usec = 0; - setitimer(ITIMER_REAL, &timer, 0); - } - if (status < 0) - die (); - fclose(fp); - fclose(file); - display (size, -1); - if (file != stdout) - adjmodtime(); - exit (0); + } + if (status < 0) + die(0); + fclose(fp); + fclose(file); + display (size, -1); + if (file != stdout) + adjmodtime(); + exit (0); } void display (int size, int n) { - static int bytes, pr, init = 0; - static struct timeval t0, t_start; - static char *s; - struct timezone tz; - struct timeval t; - float d; - - if (!verbose) - return; - if (init == 0) { - init = 1; - gettimeofday(&t0, &tz); - t_start = t0; - bytes = pr = 0; - s = (char *) malloc (strlen(outputfile) + 50); - if (size > 0) - sprintf (s, "Receiving %s (%d bytes)%s", outputfile, size, - size ? "" : " [appending]"); - else - sprintf (s, "Receiving %s", outputfile); - printf ("%s", s); - fflush (stdout); - bytes = n; - return; - } - gettimeofday(&t, &tz); - if (n == -1) { - if (size > 0) - printf ("\r%s: 100%%", s); - else - printf ("\r%s: %d Kbytes", s, 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); - d = bytes/d; - if (d < 1000) - printf (" (%d Bytes/s)\n", (int)d); - else { - d /=1024; - printf (" (%.2f K/s)\n", d); - } - return; - } - bytes += n; - d = t.tv_sec + t.tv_usec/1.e6 - t0.tv_sec - t0.tv_usec/1.e6; - if (d < 5) /* display every 5 sec. */ - return; - t0 = t; - pr++; + static int bytes, pr, init = 0; + static struct timeval t0, t_start; + static char *s; + struct timezone tz; + struct timeval t; + float d; + + if (!verbose) + return; + if (init == 0) { + init = 1; + gettimeofday(&t0, &tz); + t_start = t0; + bytes = pr = 0; + s = (char *) malloc (strlen(outputfile) + 50); + if (size > 0) + sprintf (s, "Receiving %s (%d bytes)%s", outputfile, size, + size ? "" : " [appending]"); + else + sprintf (s, "Receiving %s", outputfile); + printf ("%s", s); + fflush (stdout); + bytes = n; + return; + } + gettimeofday(&t, &tz); + if (n == -1) { if (size > 0) - printf ("\r%s: %2d%%", s, 100*bytes/size); + printf ("\r%s: 100%%", s); else printf ("\r%s: %d Kbytes", s, bytes/1024); - fflush (stdout); + 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); + d = bytes/d; + if (d < 1000) + printf (" (%d Bytes/s)\n", (int)d); + else { + d /=1024; + printf (" (%.2f K/s)\n", d); + } + return; + } + bytes += n; + d = t.tv_sec + t.tv_usec/1.e6 - t0.tv_sec - t0.tv_usec/1.e6; + if (d < 5) /* display every 5 sec. */ + return; + t0 = t; + pr++; + if (size > 0) + printf ("\r%s: %2d%%", s, 100*bytes/size); + else + printf ("\r%s: %d Kbytes", s, bytes/1024); + fflush (stdout); } void parse (char *s) { - char *p; - - if (strncasecmp (s, "ftp://", 6) == 0) { - /* ftp://host.name/file/name */ - s += 6; - p = strchr (s, '/'); - if (!p) { - fprintf (stderr, "%s: no filename??\n", progname); - usage (); - } - } else if (strncasecmp (s, "http://", 7) == 0) { - /* http://host.name/file/name */ - char *q; - s += 7; - p = strchr (s, '/'); - if (!p) { - fprintf (stderr, "%s: no filename??\n", progname); - 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) { - fprintf (stderr, "%s: no filename??\n", progname); - usage (); - } + 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) { + fprintf(stderr, "%s: no filename??\n", progname); + usage(); + } + ftp = 1; + } + else if (strncasecmp (s, "http://", 7) == 0) { + /* http://host.name/file/name */ + char *q; + s += 7; + p = strchr(s, '/'); + if (!p) { + fprintf (stderr, "%s: no filename??\n", progname); + usage (); } *p++ = 0; + q = strchr (s, ':'); + if (q && q < p) { + *q++ = 0; + http_port = atoi (q); + } 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; + file_to_get = p; + http = 1; + return; + } + else { + /* assume /host.name:/file/name */ + p = strchr (s, ':'); + if (!p) { + fprintf (stderr, "%s: no filename??\n", progname); + usage (); } + } + *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) - p = file_to_get; - else - p++; - outputfile = strdup (p); - } + 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, int *size, time_t *time) { - struct stat s; - - *size = 0; - - if (stat (name, &s)) - return; - *size = s.st_size; - *time = s.st_mtime; + 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) { - switch (ftpErrno(ftp)) { - case 421: fprintf (stderr, "Service not available\n"); break; - case 450: fprintf (stderr, "File not available\n"); break; - case 550: fprintf (stderr, "No such file or directory\n"); break; - } + va_list ap; + va_start (ap, fmt); + + if (fmt) + vfprintf(stderr, fmt, ap); + if(ftp) { + switch (ftpErrno(ftp)) { + case 421: fprintf (stderr, "Service not available\n"); break; + case 450: fprintf (stderr, "File not available\n"); break; + case 550: fprintf (stderr, "No such file or directory\n"); break; } - rm (); - exit (1); + } + rm (); + exit (1); } void httpget () { - char *cp, str[1000]; - struct timeval 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 ((cp = getenv("HTTP_TIMEOUT")) != NULL) - tout.tv_sec = atoi(cp); - else - tout.tv_sec = HTTP_TIMEOUT; - tout.tv_usec = 0; - - 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) { - i = select (s+1, &fdset, 0, 0, &tout); - switch (i) { - case 0: - fprintf (stderr, "%s: Timeout\n", progname); - 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."); - } + char *cp, str[1000]; + struct timeval 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 ((cp = getenv("HTTP_TIMEOUT")) != NULL) + tout.tv_sec = atoi(cp); + else + tout.tv_sec = HTTP_TIMEOUT; + tout.tv_usec = 0; + + 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) { + i = select (s+1, &fdset, 0, 0, &tout); + switch (i) { + case 0: + fprintf (stderr, "%s: Timeout\n", progname); + 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; + 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 (); - display (size, header_len); - /* then p */ - if (p+len > q) { - i = fwrite (q, 1, p+len-q, file); - if (i != p+len-q) - die (); - 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 (); - display (size, n); - if (p+len > q) { - n = p+len-q; - i = fwrite (q, 1, n, file); - if (i != n) - die (); - display (size, n); - } - } + 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 { - i = fwrite (p, 1, len, file); - if (i != len) - die (); - if (len) - display (size, i); + 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); + } } - if (len == 0) - display (size, -1); + } 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 () +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, 0); - 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; + 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, 0); + 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; + return 0; } void msgDebug (char *p) { - printf ("%s", 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); + 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 { - 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); - } + 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; + } + file_to_get = url; + + *p = 0; + host = strdup(e); + http_port = port; + http = 1; + http_proxy = 1; } |