1996-06-22 21:42:14 +00:00
|
|
|
|
/*-
|
|
|
|
|
* Copyright (c) 1996
|
1996-06-22 23:24:13 +00:00
|
|
|
|
* Jean-Marc Zucconi
|
1996-06-22 21:42:14 +00:00
|
|
|
|
*
|
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
|
* are met:
|
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
|
*
|
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
|
* IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
|
|
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
|
*/
|
|
|
|
|
|
1996-08-31 22:03:05 +00:00
|
|
|
|
/* $Id: main.c,v 1.19 1996/08/23 06:21:17 jkh Exp $ */
|
1996-06-19 09:32:11 +00:00
|
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <pwd.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
#include <netdb.h>
|
|
|
|
|
#include <sys/time.h>
|
|
|
|
|
#include <regex.h>
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <sys/errno.h>
|
|
|
|
|
#include <err.h>
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
|
|
#include <ftpio.h>
|
|
|
|
|
|
1996-07-05 00:06:36 +00:00
|
|
|
|
#define BUFFER_SIZE 1024
|
1996-06-19 09:32:11 +00:00
|
|
|
|
#define HTTP_TIMEOUT 60 /* seconds */
|
|
|
|
|
#define FTP_TIMEOUT 300 /* seconds */
|
|
|
|
|
|
|
|
|
|
char buffer[BUFFER_SIZE];
|
|
|
|
|
|
|
|
|
|
char *progname;
|
|
|
|
|
|
|
|
|
|
int verbose = 1;
|
1996-08-31 22:03:05 +00:00
|
|
|
|
int ftp_verbose = 0;
|
1996-08-22 21:30:51 +00:00
|
|
|
|
int linkfile = 0;
|
1996-06-19 09:32:11 +00:00
|
|
|
|
char *outputfile = 0;
|
|
|
|
|
char *change_to_dir = 0;
|
|
|
|
|
char *host = 0;
|
|
|
|
|
int passive_mode = 0;
|
|
|
|
|
char *file_to_get = 0;
|
1996-08-22 21:30:51 +00:00
|
|
|
|
int ftp = 0;
|
1996-08-14 17:50:23 +00:00
|
|
|
|
int http_proxy = 0;
|
1996-06-19 09:32:11 +00:00
|
|
|
|
int http = 0;
|
|
|
|
|
int http_port = 80;
|
1996-06-22 21:42:14 +00:00
|
|
|
|
int mirror = 0;
|
1996-07-18 00:08:02 +00:00
|
|
|
|
int newtime = 0;
|
1996-06-19 09:32:11 +00:00
|
|
|
|
int restart = 0;
|
|
|
|
|
time_t modtime;
|
|
|
|
|
FILE *file = 0;
|
1996-08-22 21:30:51 +00:00
|
|
|
|
int timeout_ival = 0;
|
1996-06-19 09:32:11 +00:00
|
|
|
|
|
1996-08-22 21:30:51 +00:00
|
|
|
|
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);
|
1996-06-19 09:32:11 +00:00
|
|
|
|
|
|
|
|
|
void
|
1996-08-22 21:30:51 +00:00
|
|
|
|
usage()
|
1996-06-19 09:32:11 +00:00
|
|
|
|
{
|
1996-08-31 22:03:05 +00:00
|
|
|
|
fprintf(stderr, "usage: %s [-DHINPMTVLqlmnprv] [-o outputfile] <-f file -h host [-c dir]| URL>\n", progname);
|
1996-08-22 21:30:51 +00:00
|
|
|
|
exit(1);
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
1996-08-22 21:30:51 +00:00
|
|
|
|
die(int sig)
|
1996-06-19 09:32:11 +00:00
|
|
|
|
{
|
1996-08-22 21:30:51 +00:00
|
|
|
|
int e = errno;
|
|
|
|
|
|
|
|
|
|
rm();
|
1996-08-22 23:25:24 +00:00
|
|
|
|
if (!sig)
|
1996-08-22 21:30:51 +00:00
|
|
|
|
fprintf (stderr, "%s: %s\n", progname, sys_errlist[e]);
|
|
|
|
|
else
|
1996-08-22 23:25:24 +00:00
|
|
|
|
fprintf (stderr, "%s: Interrupted by signal %d\n", progname, sig);
|
1996-08-22 21:30:51 +00:00
|
|
|
|
exit(1);
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
1996-08-12 12:55:26 +00:00
|
|
|
|
adjmodtime()
|
1996-06-19 09:32:11 +00:00
|
|
|
|
{
|
1996-08-12 12:55:26 +00:00
|
|
|
|
struct timeval tv[2];
|
1996-08-22 21:30:51 +00:00
|
|
|
|
|
1996-08-12 12:55:26 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
rm()
|
|
|
|
|
{
|
|
|
|
|
if (file) {
|
1996-08-22 21:30:51 +00:00
|
|
|
|
fclose(file);
|
1996-08-12 12:55:26 +00:00
|
|
|
|
if (file != stdout) {
|
|
|
|
|
if (!restart && !mirror)
|
1996-08-22 21:30:51 +00:00
|
|
|
|
remove(outputfile);
|
1996-08-12 12:55:26 +00:00
|
|
|
|
adjmodtime();
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
1996-08-12 12:55:26 +00:00
|
|
|
|
}
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
1996-08-22 21:30:51 +00:00
|
|
|
|
main(int argc, char **argv)
|
1996-06-19 09:32:11 +00:00
|
|
|
|
{
|
1996-08-22 21:30:51 +00:00
|
|
|
|
int c;
|
|
|
|
|
char *s = strrchr (argv[0], '/');
|
|
|
|
|
|
|
|
|
|
progname = s ? s+1 : argv[0];
|
|
|
|
|
|
1996-08-31 22:03:05 +00:00
|
|
|
|
while ((c = getopt (argc, argv, "D:HINPMT:V:Lqc:f:h:o:plmnrv")) != EOF) {
|
1996-08-22 21:30:51 +00:00
|
|
|
|
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;
|
|
|
|
|
|
1996-08-31 22:03:05 +00:00
|
|
|
|
case 'v':
|
|
|
|
|
ftp_verbose = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
1996-08-22 21:30:51 +00:00
|
|
|
|
case 'T':
|
|
|
|
|
timeout_ival = atoi(optarg);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
case '?':
|
|
|
|
|
usage();
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
1996-08-22 21:30:51 +00:00
|
|
|
|
}
|
|
|
|
|
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.");
|
|
|
|
|
|
|
|
|
|
output_file_name();
|
|
|
|
|
|
|
|
|
|
signal(SIGHUP, die);
|
|
|
|
|
signal(SIGINT, die);
|
|
|
|
|
signal(SIGQUIT, die);
|
|
|
|
|
signal(SIGTERM, die);
|
|
|
|
|
|
|
|
|
|
setup_http_proxy();
|
1996-08-31 22:03:05 +00:00
|
|
|
|
|
1996-08-22 21:30:51 +00:00
|
|
|
|
if (http)
|
|
|
|
|
httpget();
|
|
|
|
|
else if (ftp)
|
|
|
|
|
ftpget();
|
|
|
|
|
else
|
|
|
|
|
fileget();
|
|
|
|
|
exit(0);
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
1996-08-22 21:30:51 +00:00
|
|
|
|
timeout(int sig)
|
1996-06-19 09:32:11 +00:00
|
|
|
|
{
|
1996-08-22 21:30:51 +00:00
|
|
|
|
fprintf(stderr, "\n%s: Timeout\n", progname);
|
|
|
|
|
rm();
|
|
|
|
|
exit(1);
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
1996-08-22 21:30:51 +00:00
|
|
|
|
fileget()
|
1996-06-19 09:32:11 +00:00
|
|
|
|
{
|
1996-08-22 21:30:51 +00:00
|
|
|
|
char *basename;
|
1996-08-04 00:35:39 +00:00
|
|
|
|
|
1996-08-22 21:30:51 +00:00
|
|
|
|
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);
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
1996-08-22 21:30:51 +00:00
|
|
|
|
}
|
|
|
|
|
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);
|
1996-06-22 20:16:57 +00:00
|
|
|
|
}
|
1996-08-22 21:30:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
1996-06-19 09:32:11 +00:00
|
|
|
|
|
1996-08-22 21:30:51 +00:00
|
|
|
|
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";
|
1996-08-31 22:03:05 +00:00
|
|
|
|
ftp = ftpLogin(host, lp, ftp_pw, 0, ftp_verbose);
|
1996-08-22 21:30:51 +00:00
|
|
|
|
if (!ftp)
|
|
|
|
|
err(1, "couldn't open FTP connection or login to %s.", host);
|
|
|
|
|
|
|
|
|
|
/* 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;
|
1996-06-19 09:32:11 +00:00
|
|
|
|
else
|
1996-08-22 21:30:51 +00:00
|
|
|
|
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);
|
1996-07-05 00:06:36 +00:00
|
|
|
|
else
|
1996-08-22 21:30:51 +00:00
|
|
|
|
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;
|
1996-07-05 00:06:36 +00:00
|
|
|
|
timer.it_interval.tv_usec = timer.it_value.tv_usec = 0;
|
|
|
|
|
setitimer(ITIMER_REAL, &timer, 0);
|
1996-08-22 21:30:51 +00:00
|
|
|
|
}
|
|
|
|
|
if (status < 0)
|
|
|
|
|
die(0);
|
|
|
|
|
fclose(fp);
|
|
|
|
|
fclose(file);
|
|
|
|
|
display (size, -1);
|
|
|
|
|
if (file != stdout)
|
|
|
|
|
adjmodtime();
|
|
|
|
|
exit (0);
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
display (int size, int n)
|
|
|
|
|
{
|
1996-08-22 21:30:51 +00:00
|
|
|
|
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) {
|
1996-06-19 09:32:11 +00:00
|
|
|
|
if (size > 0)
|
1996-08-22 21:30:51 +00:00
|
|
|
|
printf ("\r%s: 100%%", s);
|
1996-06-19 09:32:11 +00:00
|
|
|
|
else
|
|
|
|
|
printf ("\r%s: %d Kbytes", s, bytes/1024);
|
1996-08-22 21:30:51 +00:00
|
|
|
|
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);
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
parse (char *s)
|
|
|
|
|
{
|
1996-08-22 21:30:51 +00:00
|
|
|
|
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 ();
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
|
|
|
|
*p++ = 0;
|
1996-08-22 21:30:51 +00:00
|
|
|
|
q = strchr (s, ':');
|
|
|
|
|
if (q && q < p) {
|
|
|
|
|
*q++ = 0;
|
|
|
|
|
http_port = atoi (q);
|
|
|
|
|
}
|
1996-06-19 09:32:11 +00:00
|
|
|
|
host = s;
|
1996-08-22 21:30:51 +00:00
|
|
|
|
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 ();
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
1996-08-22 21:30:51 +00:00
|
|
|
|
}
|
|
|
|
|
*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;
|
|
|
|
|
}
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
output_file_name ()
|
|
|
|
|
{
|
1996-08-22 21:30:51 +00:00
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
|
|
if (!outputfile) {
|
|
|
|
|
p = strrchr (file_to_get, '/');
|
|
|
|
|
if (!p || (!ftp && !http))
|
|
|
|
|
p = file_to_get;
|
|
|
|
|
else
|
|
|
|
|
p++;
|
|
|
|
|
outputfile = strdup (p);
|
|
|
|
|
}
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
f_size (char *name, int *size, time_t *time)
|
|
|
|
|
{
|
1996-08-22 21:30:51 +00:00
|
|
|
|
struct stat s;
|
|
|
|
|
|
|
|
|
|
*size = 0;
|
|
|
|
|
|
|
|
|
|
if (stat (name, &s))
|
|
|
|
|
return;
|
|
|
|
|
*size = s.st_size;
|
|
|
|
|
*time = s.st_mtime;
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ftperr (FILE* ftp, char *fmt, ...)
|
|
|
|
|
{
|
1996-08-22 21:30:51 +00:00
|
|
|
|
va_list ap;
|
|
|
|
|
va_start (ap, fmt);
|
|
|
|
|
|
|
|
|
|
if (fmt)
|
|
|
|
|
vfprintf(stderr, fmt, ap);
|
|
|
|
|
if(ftp) {
|
1996-08-22 23:25:24 +00:00
|
|
|
|
const char *str = ftpErrString(ftpErrno(ftp));
|
|
|
|
|
|
|
|
|
|
if (str)
|
|
|
|
|
fprintf(stderr, "%s\n", str);
|
1996-08-22 21:30:51 +00:00
|
|
|
|
}
|
|
|
|
|
rm ();
|
|
|
|
|
exit (1);
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
httpget ()
|
|
|
|
|
{
|
1996-08-22 21:30:51 +00:00
|
|
|
|
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.");
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
1996-08-22 21:30:51 +00:00
|
|
|
|
}
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
match (char *pat, char *s)
|
|
|
|
|
{
|
1996-08-22 21:30:51 +00:00
|
|
|
|
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;
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
filter (unsigned char *p, int len)
|
|
|
|
|
{
|
1996-06-25 21:33:18 +00:00
|
|
|
|
#define S 512
|
1996-08-22 21:30:51 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
1996-06-19 09:32:11 +00:00
|
|
|
|
} else {
|
1996-08-22 21:30:51 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
1996-08-22 21:30:51 +00:00
|
|
|
|
} else {
|
|
|
|
|
i = fwrite (p, 1, len, file);
|
|
|
|
|
if (i != len)
|
|
|
|
|
die(0);
|
|
|
|
|
if (len)
|
|
|
|
|
display (size, i);
|
|
|
|
|
}
|
|
|
|
|
if (len == 0)
|
|
|
|
|
display (size, -1);
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
1996-08-22 21:30:51 +00:00
|
|
|
|
int
|
|
|
|
|
http_open()
|
1996-06-19 09:32:11 +00:00
|
|
|
|
{
|
1996-08-22 21:30:51 +00:00
|
|
|
|
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;
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
isDebug ()
|
|
|
|
|
{
|
1996-08-22 21:30:51 +00:00
|
|
|
|
return 0;
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void msgDebug (char *p)
|
|
|
|
|
{
|
1996-08-22 21:30:51 +00:00
|
|
|
|
printf ("%s", p);
|
1996-06-19 09:32:11 +00:00
|
|
|
|
}
|
1996-08-14 17:50:23 +00:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
setup_http_proxy()
|
|
|
|
|
{
|
1996-08-22 21:30:51 +00:00
|
|
|
|
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);
|
1996-08-14 17:50:23 +00:00
|
|
|
|
} else {
|
1996-08-22 21:30:51 +00:00
|
|
|
|
sprintf(url, "ftp://%s/%s", host, file_to_get);
|
1996-08-14 17:50:23 +00:00
|
|
|
|
}
|
1996-08-22 21:30:51 +00:00
|
|
|
|
}
|
|
|
|
|
file_to_get = url;
|
|
|
|
|
|
|
|
|
|
*p = 0;
|
|
|
|
|
host = strdup(e);
|
|
|
|
|
http_port = port;
|
|
|
|
|
http = 1;
|
|
|
|
|
http_proxy = 1;
|
1996-08-14 17:50:23 +00:00
|
|
|
|
}
|
|
|
|
|
|