freebsd-dev/usr.bin/fetch/uri.c
Garrett Wollman 78be319939 Here is my long-threatened revamping of fetch. Jean-Marc probably won't
recognize it any more.  This makes the following significant changes:

- The main body of the program doesn't know a thing about URIs,
  HTTP, or FTP.  This makes it possible to easily plug in other
  protocols.  (The next revision will probably be able to dynamically
  add new recognizers.)

- There are no longer arbitrary timeouts for the protocols.  If you want
  to set one for yourself, use the environment variables.

- FTP proxies are now supported (if I implemented it right).

- The HTTP implementation is much more complete, and can now do restarts,
  preserve modtimes, and mrun in mirror mode.  It's not yet up to 1.1,
  but it's getting there.

- Transaction TCP is now used for sending HTTP requests.  The HTTP/1.1 syntax
  for requesting that the connection be closed after one request is
  implemented.

In all of this, I have doubtless broken somebody.  Please test it and tell me
about the bugs.
1997-01-30 21:43:44 +00:00

123 lines
3.1 KiB
C

/*-
* Copyright 1997 Massachusetts Institute of Technology
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
* granted, provided that both the above copyright notice and this
* permission notice appear in all copies, that both the above
* copyright notice and this permission notice appear in all
* supporting documentation, and that the name of M.I.T. not be used
* in advertising or publicity pertaining to distribution of the
* software without specific, written prior permission. M.I.T. makes
* no representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied
* warranty.
*
* THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
* ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
* SHALL M.I.T. 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.
*
* $Id$
*/
#include <sys/types.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
#include "fetch.h"
struct uri_scheme *schemes[] = {
&http_scheme, &ftp_scheme, &file_scheme, 0
};
static struct uri_scheme *
find_scheme(const char *name)
{
int i;
for (i = 0; schemes[i]; i++) {
if (strcasecmp(schemes[i]->sc_name, name) == 0)
return schemes[i];
}
return 0;
}
void
init_schemes(void)
{
int i;
char schemebuf[32];
const char *s, *t;
struct uri_scheme *scp;
for (i = 0; schemes[i]; i++) {
if (getenv(schemes[i]->sc_proxy_envar) != 0)
schemes[i]->sc_can_proxy = 1;
}
for (i = 0; schemes[i]; i++) {
s = schemes[i]->sc_proxy_by;
while (s && *s) {
t = strchr(s, ',');
if (t) {
schemebuf[0] = '\0';
strncat(schemebuf, s, t - s);
s = t + 1;
} else {
strcpy(schemebuf, s);
s = 0;
}
scp = find_scheme(schemebuf);
if (scp && scp->sc_can_proxy) {
schemes[i]->sc_proxyproto = scp;
break;
}
}
}
}
int
parse_uri(struct fetch_state *fs, const char *uri)
{
const char *colon, *slash;
char *scheme;
struct uri_scheme *scp;
fs->fs_status = "parsing URI";
colon = strchr(uri, ':');
slash = strchr(uri, '/');
if (!colon || !slash || slash < colon) {
warnx("%s: an absolute URI is required", uri);
return EX_USAGE;
}
scheme = alloca(colon - uri + 1);
scheme[0] = '\0';
strncat(scheme, uri, colon - uri);
scp = find_scheme(scheme);
if (scp == 0) {
warnx("%s: unknown URI scheme", scheme);
return EX_USAGE;
}
if (scp->sc_proxyproto)
return scp->sc_proxyproto->sc_proxy_parse(fs, uri);
else
return scp->sc_parse(fs, uri);
}