version 1.13, 1997/07/24 14:22:21 |
version 1.14, 1997/07/25 21:56:20 |
|
|
/* $OpenBSD$ */ |
/* $OpenBSD$ */ |
/* $NetBSD: fetch.c,v 1.8 1997/04/21 18:45:47 lukem Exp $ */ |
/* $NetBSD: fetch.c,v 1.13 1997/07/20 12:49:26 lukem Exp $ */ |
|
|
/*- |
/*- |
* Copyright (c) 1997 The NetBSD Foundation, Inc. |
* Copyright (c) 1997 The NetBSD Foundation, Inc. |
|
|
|
|
#include "ftp_var.h" |
#include "ftp_var.h" |
|
|
|
static int url_get __P((const char *, const char *, int)); |
|
void aborthttp __P((int)); |
|
|
|
|
#define FTP_URL "ftp://" /* ftp URL prefix */ |
#define FTP_URL "ftp://" /* ftp URL prefix */ |
#define HTTP_URL "http://" /* http URL prefix */ |
#define HTTP_URL "http://" /* http URL prefix */ |
#define FTP_PROXY "ftp_proxy" /* env var with ftp proxy location */ |
#define FTP_PROXY "ftp_proxy" /* env var with ftp proxy location */ |
|
|
* Modifies the string argument given. |
* Modifies the string argument given. |
* Returns -1 on failure, 0 on success |
* Returns -1 on failure, 0 on success |
*/ |
*/ |
int |
static int |
url_get(line, proxyenv, fd) |
url_get(origline, proxyenv, fd) |
char *line; |
const char *origline; |
char *proxyenv; |
const char *proxyenv; |
int fd; |
int fd; |
{ |
{ |
struct sockaddr_in sin; |
struct sockaddr_in sin; |
int i, out, port, s; |
int i, out, isftpurl; |
size_t buflen, len; |
in_port_t port; |
char c, *cp, *cp2, *savefile, *portnum, *path, buf[4096]; |
volatile int s; |
char *proxy, *host; |
size_t len; |
sig_t oldintr; |
char c, *cp, *ep, *portnum, *path, buf[4096]; |
|
const char *savefile; |
|
char *line, *proxy, *host; |
|
volatile sig_t oldintr; |
off_t hashbytes; |
off_t hashbytes; |
|
|
s = -1; |
s = -1; |
proxy = NULL; |
proxy = NULL; |
|
isftpurl = 0; |
|
|
|
#ifdef __GNUC__ /* XXX: to shut up gcc warnings */ |
|
(void)&out; |
|
(void)&proxy; |
|
(void)&savefile; |
|
#endif |
|
|
|
line = strdup(origline); |
|
if (line == NULL) |
|
errx(1, "Can't allocate memory to parse URL"); |
if (strncasecmp(line, HTTP_URL, sizeof(HTTP_URL) - 1) == 0) |
if (strncasecmp(line, HTTP_URL, sizeof(HTTP_URL) - 1) == 0) |
host = line + sizeof(HTTP_URL) - 1; |
host = line + sizeof(HTTP_URL) - 1; |
else if (strncasecmp(line, FTP_URL, sizeof(FTP_URL) - 1) == 0) |
else if (strncasecmp(line, FTP_URL, sizeof(FTP_URL) - 1) == 0) { |
host = line + sizeof(FTP_URL) - 1; |
host = line + sizeof(FTP_URL) - 1; |
else |
isftpurl = 1; |
errx(1, "url_get: invalid url '%s'", line); |
} else |
|
errx(1, "url_get: Invalid URL '%s'", line); |
|
|
path = strchr(host, '/'); /* find path */ |
path = strchr(host, '/'); /* find path */ |
if (EMPTYSTRING(path)) |
if (EMPTYSTRING(path)) { |
|
if (isftpurl) |
|
goto noftpautologin; |
|
warnx("Invalid URL (no `/' after host): %s", origline); |
goto cleanup_url_get; |
goto cleanup_url_get; |
|
} |
*path++ = '\0'; |
*path++ = '\0'; |
if (EMPTYSTRING(path)) |
if (EMPTYSTRING(path)) { |
|
if (isftpurl) |
|
goto noftpautologin; |
|
warnx("Invalid URL (no file after host): %s", origline); |
goto cleanup_url_get; |
goto cleanup_url_get; |
|
} |
|
|
savefile = strrchr(path, '/'); /* find savefile */ |
savefile = strrchr(path, '/'); /* find savefile */ |
if (savefile != NULL) |
if (savefile != NULL) |
savefile++; |
savefile++; |
else |
else |
savefile = path; |
savefile = path; |
if (EMPTYSTRING(savefile)) |
if (EMPTYSTRING(savefile)) { |
|
if (isftpurl) |
|
goto noftpautologin; |
|
warnx("Invalid URL (no file after directory): %s", origline); |
goto cleanup_url_get; |
goto cleanup_url_get; |
|
} |
|
|
if (proxyenv != NULL) { /* use proxy */ |
if (proxyenv != NULL) { /* use proxy */ |
proxy = strdup(proxyenv); |
proxy = strdup(proxyenv); |
if (proxy == NULL) |
if (proxy == NULL) |
errx(1, "Can't allocate memory for proxy url."); |
errx(1, "Can't allocate memory for proxy URL."); |
if (strncasecmp(proxy, HTTP_URL, sizeof(HTTP_URL) - 1) == 0) |
if (strncasecmp(proxy, HTTP_URL, sizeof(HTTP_URL) - 1) == 0) |
host = proxy + sizeof(HTTP_URL) - 1; |
host = proxy + sizeof(HTTP_URL) - 1; |
else if (strncasecmp(proxy, FTP_URL, sizeof(FTP_URL) - 1) == 0) |
else if (strncasecmp(proxy, FTP_URL, sizeof(FTP_URL) - 1) == 0) |
host = proxy + sizeof(FTP_URL) - 1; |
host = proxy + sizeof(FTP_URL) - 1; |
else { |
else { |
warnx("Malformed proxy URL: %s", proxy); |
warnx("Malformed proxy URL: %s", proxyenv); |
goto cleanup_url_get; |
goto cleanup_url_get; |
} |
} |
if (EMPTYSTRING(host)) |
if (EMPTYSTRING(host)) { |
|
warnx("Malformed proxy URL: %s", proxyenv); |
goto cleanup_url_get; |
goto cleanup_url_get; |
|
} |
*--path = '/'; /* add / back to real path */ |
*--path = '/'; /* add / back to real path */ |
path = strchr(host, '/'); /* remove trailing / on host */ |
path = strchr(host, '/'); /* remove trailing / on host */ |
if (! EMPTYSTRING(path)) |
if (! EMPTYSTRING(path)) |
|
|
warnx("%s: not an Internet address?", host); |
warnx("%s: not an Internet address?", host); |
goto cleanup_url_get; |
goto cleanup_url_get; |
} |
} |
memcpy(&sin.sin_addr, hp->h_addr, hp->h_length); |
memcpy(&sin.sin_addr, hp->h_addr, (size_t)hp->h_length); |
} |
} |
|
|
if (! EMPTYSTRING(portnum)) { |
if (! EMPTYSTRING(portnum)) { |
port = atoi(portnum); |
char *ep; |
if (port < 1 || (port & 0xffff) != port) { |
long nport; |
|
|
|
nport = strtol(portnum, &ep, 10); |
|
if (nport < 1 || nport > 0xffff || *ep != '\0') { |
warnx("Invalid port: %s", portnum); |
warnx("Invalid port: %s", portnum); |
goto cleanup_url_get; |
goto cleanup_url_get; |
} |
} |
port = htons(port); |
port = htons((in_port_t)nport); |
} else |
} else |
port = httpport; |
port = httpport; |
sin.sin_port = port; |
sin.sin_port = port; |
|
|
s = socket(AF_INET, SOCK_STREAM, 0); |
s = socket(AF_INET, SOCK_STREAM, 0); |
if (s == -1) { |
if (s == -1) { |
warnx("Can't create socket"); |
warn("Can't create socket"); |
goto cleanup_url_get; |
goto cleanup_url_get; |
} |
} |
|
|
|
|
* status of "200". Proxy requests don't want leading /. |
* status of "200". Proxy requests don't want leading /. |
*/ |
*/ |
if (!proxy) |
if (!proxy) |
fprintf(ttyout, "Requesting %s:%d/%s\n", line, ntohs(port), |
fprintf(ttyout, "Requesting %s\n", origline); |
path); |
|
else |
else |
fprintf(ttyout, "Requesting %s (via %s)\n", line, proxyenv); |
fprintf(ttyout, "Requesting %s (via %s)\n", origline, proxyenv); |
snprintf(buf, sizeof(buf), "GET %s%s HTTP/1.0\r\n\r\n", |
snprintf(buf, sizeof(buf), "GET %s%s HTTP/1.0\r\n\r\n", |
proxy ? "" : "/", path); |
proxy ? "" : "/", path); |
buflen = strlen(buf); |
len = strlen(buf); |
if (write(s, buf, buflen) < buflen) { |
if (write(s, buf, len) < len) { |
warn("write"); |
warn("Writing HTTP request"); |
goto cleanup_url_get; |
goto cleanup_url_get; |
} |
} |
memset(buf, 0, sizeof(buf)); |
memset(buf, 0, sizeof(buf)); |
for (i = 0, buflen = sizeof(buf), cp = buf; i < buflen; cp++, i++) { |
for (cp = buf; cp < buf + sizeof(buf); ) { |
if (read(s, cp, 1) != 1) |
if (read(s, cp, 1) != 1) |
goto improper; |
goto improper; |
if (*cp == '\r') |
if (*cp == '\r') |
continue; |
continue; |
if (*cp == '\n') |
if (*cp == '\n') |
break; |
break; |
|
cp++; |
} |
} |
buf[buflen - 1] = '\0'; /* sanity */ |
buf[sizeof(buf) - 1] = '\0'; /* sanity */ |
cp = strchr(buf, ' '); |
cp = strchr(buf, ' '); |
if (cp == NULL) |
if (cp == NULL) |
goto improper; |
goto improper; |
|
|
*/ |
*/ |
memset(buf, 0, sizeof(buf)); |
memset(buf, 0, sizeof(buf)); |
c = '\0'; |
c = '\0'; |
for (i = 0, buflen = sizeof(buf), cp = buf; i < buflen; cp++, i++) { |
for (cp = buf; cp < buf + sizeof(buf); ) { |
if (read(s, cp, 1) != 1) |
if (read(s, cp, 1) != 1) |
goto improper; |
goto improper; |
if (*cp == '\r') |
if (*cp == '\r') |
|
|
if (*cp == '\n' && c == '\n') |
if (*cp == '\n' && c == '\n') |
break; |
break; |
c = *cp; |
c = *cp; |
|
cp++; |
} |
} |
buf[buflen - 1] = '\0'; /* sanity */ |
buf[sizeof(buf) - 1] = '\0'; /* sanity */ |
|
|
/* Look for the "Content-length: " header. */ |
/* Look for the "Content-length: " header. */ |
#define CONTENTLEN "Content-Length: " |
#define CONTENTLEN "Content-Length: " |
|
|
} |
} |
if (*cp != '\0') { |
if (*cp != '\0') { |
cp += sizeof(CONTENTLEN) - 1; |
cp += sizeof(CONTENTLEN) - 1; |
cp2 = strchr(cp, '\n'); |
ep = strchr(cp, '\n'); |
if (cp2 == NULL) |
if (ep == NULL) |
goto improper; |
goto improper; |
else |
else |
*cp2 = '\0'; |
*ep = '\0'; |
filesize = atoi(cp); |
filesize = strtol(cp, &ep, 10); |
if (filesize < 1) |
if (filesize < 1 || *ep != '\0') |
goto improper; |
goto improper; |
} else |
} else |
filesize = -1; |
filesize = -1; |
|
|
close(out); |
close(out); |
if (proxy) |
if (proxy) |
free(proxy); |
free(proxy); |
|
free(line); |
return (0); |
return (0); |
|
|
|
noftpautologin: |
|
warnx( |
|
"Auto-login using ftp URLs isn't supported when using $ftp_proxy"); |
|
goto cleanup_url_get; |
|
|
improper: |
improper: |
warnx("Improper response from %s", host); |
warnx("Improper response from %s", host); |
|
|
cleanup_url_get: |
cleanup_url_get: |
if (s != -1) |
if (s != -1) |
close(s); |
close(s); |
if (proxy) |
if (proxy) |
free(proxy); |
free(proxy); |
|
free(line); |
return (-1); |
return (-1); |
} |
} |
|
|
|
|
char *cp, *line, *host, *dir, *file, *portnum; |
char *cp, *line, *host, *dir, *file, *portnum; |
char *user, *pass; |
char *user, *pass; |
char *ftpproxy, *httpproxy; |
char *ftpproxy, *httpproxy; |
int rval, xargc, argpos; |
int rval, xargc; |
|
volatile int argpos; |
int dirhasglob, filehasglob; |
int dirhasglob, filehasglob; |
char rempath[MAXPATHLEN], fakedev[MAXPATHLEN]; |
char rempath[MAXPATHLEN]; |
|
|
argpos = 0; |
argpos = 0; |
|
|
|
|
} |
} |
if (pass == host || *pass == '@') { |
if (pass == host || *pass == '@') { |
bad_ftp_url: |
bad_ftp_url: |
warnx("Bad ftp URL: %s", argv[argpos]); |
warnx("Invalid URL: %s", argv[argpos]); |
rval = argpos + 1; |
rval = argpos + 1; |
continue; |
continue; |
} |
} |
|
|
setpeer(xargc, xargv); |
setpeer(xargc, xargv); |
autologin = oautologin; |
autologin = oautologin; |
if ((connected == 0) || |
if ((connected == 0) || |
((connected == 1) && !login(host, user, pass)) ) { |
((connected == 1) && !login(host, user, pass))) { |
warnx("Can't connect or login to host `%s'", |
warnx("Can't connect or login to host `%s'", |
host); |
host); |
rval = argpos + 1; |
rval = argpos + 1; |