Second of a series of cleanups to libfetch.

This commit introduces the following features:

 a) the fetchStat*() functions, which return meta-information for a
    document, such as size, modification time, etc.

 b) the use of the com_err(3) facilities to report errors.

It also fixes a bunch of style bugs and a few logic bugs and somewhat
improves the man page.

Changed files, in alphabetical order:

 Makefile:
  Don't generate macros in {ftp,http}err.c.

  Generate category fields for the error message lists.

  Compile the error table.

  Install fetch_err.h along with fetch.h.

 common.c:
  Remove the _netdb_errstring() macro, and add FETCH_ERR_NETDB to the
  error code in the _netdb_seterr() macro.

  Add categories to the _netdb_errlist table.

  Report errors through the Common Error library.

 common.h:
  Add the DEBUG macros.

  Add prototype for fetchConnect().

  Remove the prototype for _fetch_errstring(), which is local to common.c

  Add a categroy field to struct fetcherr, and define constants for
  error categories.

  Define macros for _{url,netdb,ftp,http}_seterr().

 errors.et: (new file)
  List error categories.

 fetch.3:
  Document the fetchStat*() functions.

  Move the "unimplemented functionality" comments from NOTES to BUGS.

  Document that applications which use libfetch must also use
  libcom_err, and list existing error codes.

  Undocument fetchLastErr{Code,String}.

  Remove the (empty) DIAGNOSTICS section.

  Mention Eugene Skepner in the AUTHORS section.

 fetch.c:
  Move the DEBUG macros to common.c

  Add fetchStat() and fetchStatURL().

  Generate error messages for URL parser errors, and fix a minor bug
  in the parser.

  Use 'struct url' instead of 'url_t'.

  Remove fetchLastErr{Code,String}.

 fetch.h:
  Use 'struct url' instead of 'url_t', and remove the typedef.

  Define struct url_stat (used by fetchStat()).

  Add prototypes for fetchStat*().

  Remove the declarations for fetchLastErr{Code,String}.

  Include fetch_err.h.

 fetch_err.et: (new file)
  Error table for libfetch.

 file.c:
  Add fetchStatFile().

  Use 'struct url' instead of 'url_t'.

 ftp.c:
  Add fetchStatFTP().

  Use 'struct url' instead of 'url_t'.

  Don't use fetchLastErrCode.

 ftp.errors:
  Add categories to all error messages.

 http.c:
  Add fetchStatHTTP().

  Use 'struct url' instead of 'url_t'.

  Don't use fetchLastErr{Code,Text}.

 http.errors:
  Add categories to all error messages.

Prompted by: jkh and Eugene Skepner
Numerous sugestions from: Garett Wollman and Eugene Skepner
This commit is contained in:
Dag-Erling Smørgrav 1998-11-06 22:14:08 +00:00
parent 171a7528a8
commit d8acd8dc5c
12 changed files with 570 additions and 232 deletions

View File

@ -1,12 +1,12 @@
# $Id: Makefile,v 1.5 1998/08/17 20:39:09 bde Exp $
# $Id: Makefile,v 1.6 1998/11/05 19:48:16 des Exp $
LIB= fetch
CFLAGS+= -I. -Wall -pedantic
.if !defined(DEBUG)
CFLAGS+= -DNDEBUG
.endif
SRCS= fetch.c common.c ftp.c http.c file.c
DPSRCS= ftperr.c httperr.c
SRCS= fetch.c common.c ftp.c http.c file.c fetch_err.c
DPSRCS= ftperr.inc httperr.inc fetch_err.c fetch_err.h
MAN3= fetch.3
CLEANFILES= ${DPSRCS}
@ -15,36 +15,37 @@ SHLIB_MINOR= 0
beforedepend: ${DPSRCS}
beforeinstall:
beforeinstall: fetch.h fetch_err.h
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/fetch.h \
${DESTDIR}/usr/include
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/fetch_err.h \
${DESTDIR}/usr/include
ftperr.c: ftp.errors
@echo "static struct fetcherr _ftp_errlist[] = {" \ >> ${.TARGET}
ftperr.inc: ftp.errors
@echo "static struct fetcherr _ftp_errlist[] = {" > ${.TARGET}
@cat ${.ALLSRC} \
| grep -v ^# \
| sort \
| while read NUM STRING; do \
echo " { $${NUM}, \"$${STRING}\" },"; \
| while read NUM CAT STRING; do \
echo " { $${NUM}, FETCH_$${CAT}, \"$${STRING}\" },"; \
done >> ${.TARGET}
@echo " { -1, \"Unknown FTP error\" }" >> ${.TARGET}
@echo " { -1, FETCH_UNKNOWN, \"Unknown FTP error\" }" >> ${.TARGET}
@echo "};" >> ${.TARGET}
@echo "#define _ftp_errstring(n) _fetch_errstring(_ftp_errlist, n)" >> ${.TARGET}
@echo "#define _ftp_seterr(n) _fetch_seterr(_ftp_errlist, n)" >> ${.TARGET}
httperr.c: http.errors
@echo "static struct fetcherr _http_errlist[] = {" \ >> ${.TARGET}
httperr.inc: http.errors
@echo "static struct fetcherr _http_errlist[] = {" > ${.TARGET}
@cat ${.ALLSRC} \
| grep -v ^# \
| sort \
| while read NUM STRING; do \
echo " { $${NUM}, \"$${STRING}\" },"; \
| while read NUM CAT STRING; do \
echo " { $${NUM}, FETCH_$${CAT}, \"$${STRING}\" },"; \
done >> ${.TARGET}
@echo " { -1, \"Unknown HTTP error\" }" >> ${.TARGET}
@echo " { -1, FETCH_UNKNOWN, \"Unknown FTP error\" }" >> ${.TARGET}
@echo "};" >> ${.TARGET}
@echo "#define _http_errstring(n) _fetch_errstring(_http_errlist, n)" >> ${.TARGET}
@echo "#define _http_seterr(n) _fetch_seterr(_http_errlist, n)" >> ${.TARGET}
fetch_err.c fetch_err.h: fetch_err.et
compile_et ${.ALLSRC}
.include <bsd.lib.mk>

View File

@ -25,13 +25,14 @@
* (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$
* $Id: common.c,v 1.1 1998/11/05 19:48:16 des Exp $
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <com_err.h>
#include <errno.h>
#include <netdb.h>
#include <string.h>
@ -40,34 +41,45 @@
#include "fetch.h"
#include "common.h"
/*** Local data **************************************************************/
/*
* Error messages for resolver errors
*/
static struct fetcherr _netdb_errlist[] = {
{ HOST_NOT_FOUND, "Host not found" },
{ TRY_AGAIN, "Transient resolver failure" },
{ NO_RECOVERY, "Non-recoverable resolver failure" },
{ NO_DATA, "No address record" },
{ -1, "Unknown resolver error" }
{ HOST_NOT_FOUND, FETCH_RESOLV, "Host not found" },
{ TRY_AGAIN, FETCH_RESOLV, "Transient resolver failure" },
{ NO_RECOVERY, FETCH_RESOLV, "Non-recoverable resolver failure" },
{ NO_DATA, FETCH_RESOLV, "No address record" },
{ -1, FETCH_UNKNOWN, "Unknown resolver error" }
};
#define _netdb_errstring(n) _fetch_errstring(_netdb_errlist, n)
#define _netdb_seterr(n) _fetch_seterr(_netdb_errlist, n)
static int com_err_initialized;
/*** Error-reporting functions ***********************************************/
/*
* Initialize the common error library
*/
static void
_fetch_init_com_err(void)
{
initialize_ftch_error_table();
com_err_initialized = 1;
}
/*
* Map error code to string
*/
const char *
_fetch_errstring(struct fetcherr *p, int e)
static int
_fetch_finderr(struct fetcherr *p, int e)
{
while ((p->num != -1) && (p->num != e))
p++;
return p->string;
int i;
for (i = 0; p[i].num != -1; i++)
if (p[i].num == e)
break;
return i;
}
/*
@ -76,8 +88,13 @@ _fetch_errstring(struct fetcherr *p, int e)
void
_fetch_seterr(struct fetcherr *p, int e)
{
fetchLastErrCode = e;
fetchLastErrText = _fetch_errstring(p, e);
int n;
if (!com_err_initialized)
_fetch_init_com_err();
n = _fetch_finderr(p, e);
com_err("libfetch", p[n].cat, "(%d %s)", e, p[n].string);
}
/*
@ -86,8 +103,62 @@ _fetch_seterr(struct fetcherr *p, int e)
void
_fetch_syserr(void)
{
fetchLastErrCode = errno;
fetchLastErrText = strerror(errno);
int cat;
if (!com_err_initialized)
_fetch_init_com_err();
switch (errno) {
case 0:
cat = FETCH_OK;
break;
case EPERM:
case EACCES:
case EROFS:
case EAUTH:
case ENEEDAUTH:
cat = FETCH_AUTH;
break;
case ENOENT:
case EISDIR: /* XXX */
cat = FETCH_UNAVAIL;
break;
case ENOMEM:
cat = FETCH_MEMORY;
break;
case EBUSY:
case EAGAIN:
cat = FETCH_TEMP;
break;
case EEXIST:
cat = FETCH_EXISTS;
break;
case ENOSPC:
cat = FETCH_FULL;
break;
case EADDRINUSE:
case EADDRNOTAVAIL:
case ENETDOWN:
case ENETUNREACH:
case ENETRESET:
case EHOSTUNREACH:
cat = FETCH_NETWORK;
break;
case ECONNABORTED:
case ECONNRESET:
cat = FETCH_ABORT;
break;
case ETIMEDOUT:
cat = FETCH_TIMEOUT;
break;
case ECONNREFUSED:
case EHOSTDOWN:
cat = FETCH_DOWN;
break;
default:
cat = FETCH_UNKNOWN;
}
com_err("libfetch", cat, "(%02d %s)", errno, strerror(errno));
}

View File

@ -25,20 +25,32 @@
* (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$
* $Id: common.h,v 1.1 1998/11/05 19:48:16 des Exp $
*/
#ifndef _COMMON_H_INCLUDED
#define _COMMON_H_INCLUDED
/* Structure used for error message lists */
#define ERRCAT_
struct fetcherr {
const int num;
const char *string;
const int num, cat;
const char *string;
};
const char *_fetch_errstring(struct fetcherr *, int);
void _fetch_seterr(struct fetcherr *, int);
void _fetch_syserr(void);
int fetchConnect(char *, int);
#define _ftp_seterr(n) _fetch_seterr(_ftp_errlist, n)
#define _http_seterr(n) _fetch_seterr(_http_errlist, n)
#define _netdb_seterr(n) _fetch_seterr(_netdb_errlist, n)
#define _url_seterr(n) _fetch_seterr(_url_errlist, n)
#ifndef NDEBUG
#define DEBUG(x) do x; while (0)
#else
#define DEBUG(x) do { } while (0)
#endif
#endif

View File

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: fetch.3,v 1.2 1998/09/26 20:42:44 des Exp $
.\" $Id: fetch.3,v 1.3 1998/11/05 19:48:16 des Exp $
.\"
.Dd July 1, 1998
.Dt FETCH 3
@ -30,15 +30,20 @@
.Sh NAME
.Nm fetchGetURL ,
.Nm fetchPutURL ,
.Nm fetchStatURL ,
.Nm fetchParseURL ,
.Nm fetchGet ,
.Nm fetchPut ,
.Nm fetchStat ,
.Nm fetchGetFile ,
.Nm fetchPutFile ,
.Nm fetchStatFile ,
.Nm fetchGetHTTP ,
.Nm fetchPutHTTP ,
.Nm fetchStatHTTP ,
.Nm fetchGetFTP ,
.Nm fetchPutFTP
.Nm fetchStatFTP
.Nd file transfer library
.Sh SYNOPSIS
.Fd #include <fetch.h>
@ -46,27 +51,36 @@
.Fn fetchGetURL "char *URL" "char *flags"
.Ft FILE *
.Fn fetchPutURL "char *URL" "char *flags"
.Ft url_t *
.Ft int
.Fn fetchStatURL "char *URL" "struct url_stat *us" "char *flags"
.Ft struct url *
.Fn fetchParseURL "char *URL" "char *flags"
.Ft FILE *
.Fn fetchGet "url_t *URL" "char *flags"
.Fn fetchGet "struct url *URL" "char *flags"
.Ft FILE *
.Fn fetchPut "url_t *URL" "char *flags"
.Fn fetchPut "struct url *URL" "char *flags"
.Ft int
.Fn fetchStat "struct url *URL" "struct url_stat *us" "char *flags"
.Ft FILE *
.Fn fetchGetFile "url_t *u" "char *flags"
.Fn fetchGetFile "struct url *u" "char *flags"
.Ft FILE *
.Fn fetchPutFile "url_t *u" "char *flags"
.Fn fetchPutFile "struct url *u" "char *flags"
.Ft int
.Fn fetchStatFile "struct url *URL" "struct url_stat *us" "char *flags"
.Ft FILE *
.Fn fetchGetHTTP "url_t *u" "char *flags"
.Fn fetchGetHTTP "struct url *u" "char *flags"
.Ft FILE *
.Fn fetchPutHTTP "url_t *u" "char *flags"
.Fn fetchPutHTTP "struct url *u" "char *flags"
.Ft int
.Fn fetchStatHTTP "struct url *URL" "struct url_stat *us" "char *flags"
.Ft FILE *
.Fn fetchGetFTP "url_t *u" "char *flags"
.Fn fetchGetFTP "struct url *u" "char *flags"
.Ft FILE *
.Fn fetchPutFTP "url_t *u" "char *flags"
.Vt extern int fetchLastErrCode;
.Vt extern const char *fetchLastErrText;
.Fn fetchPutFTP "struct url *u" "char *flags"
.Ft int
.Fn fetchStatFTP "struct url *URL" "struct url_stat *us" "char *flags"
.Sh DESCRIPTION
.Pp
These functions implement a high-level library for retrieving and
uploading files using Uniform Resource Locators (URLs).
.Pp
@ -83,6 +97,19 @@ argument is a string of characters which specify transfer options. The
meaning of the individual flags is scheme-dependent, and is detailed
in the appropriate section below.
.Pp
.Fn fetchStatURL
attempts to obtain the requested document's metadata and fill in the
structure pointed to by it's second argument. The
.Fa url_stat
structure is defined as follows in
.Aq Pa fetch.h :
.Bd -literal
struct url_stat {
off_t size;
time_t time;
};
.Ed
.Pp
.Fn fetchParseURL
takes a URL in the form of a null-terminated string and splits it into
its components function according to the Common Internet Scheme Syntax
@ -101,17 +128,19 @@ The pointer returned by
should be freed using
.Fn free .
.Pp
.Fn fetchGet
and
.Fn fetchGet ,
.Fn fetchPut
are similar to
.Fn fetchGetURL
and
.Fn fetchPutURL ,
.Fn fetchStat
are similar to
.Fn fetchGetURL ,
.Fn fetchPutURL
and
.Fn fetchStatURL ,
except that they expect a pre-parsed URL in the form of a pointer to
an
.Fa url_t
structure rather than a string.
a
.Fa struct url
rather than a string.
.Pp
All of the
.Fn fetchGetXXX
@ -175,19 +204,66 @@ is currently unimplemented.
.Sh RETURN VALUES
.Fn fetchParseURL
returns a pointer to a
.Fa url_t
structure containing the individual components of the URL. If it is
.Fa struct url
containing the individual components of the URL. If it is
unable to allocate memory, or the URL is syntactically incorrect,
.Fn fetchParseURL
returns a NULL pointer.
.Pp
The
.Fn fetchStat
functions return 0 on success and -1 on failure.
.Pp
All other functions return a stream pointer which may be used to
access the requested document, or NULL if an error occurred. In the
latter case, the variables
.Va fetchLastErrCode
and
.Va fetchLastErrText
are set to appropriately descriptive values.
access the requested document, or NULL if an error occurred.
.Pp
.Nm Libfetch
uses the Common Error Library
.Nm ( libcom_err )
to report errors. The error code passed to
.Fn com_err
is one of:
.Bl -tag -width Er
.It Bq Er FETCH_ABORT
Operation aborted
.It Bq Er FETCH_AUTH
Authentication failed
.It Bq Er FETCH_DOWN
Service unavailable
.It Bq Er FETCH_EXISTS
File exists
.It Bq Er FETCH_FULL
File system full
.It Bq Er FETCH_INFO
Informational response
.It Bq Er FETCH_MEMORY
Insufficient memory
.It Bq Er FETCH_MOVED
File has moved
.It Bq Er FETCH_NETWORK
Network error
.It Bq Er FETCH_OK
No error
.It Bq Er FETCH_PROTO
Protocol error
.It Bq Er FETCH_RESOLV
Resolver error
.It Bq Er FETCH_SERVER
Server error
.It Bq Er FETCH_TEMP
Temporary error
.It Bq Er FETCH_TIMEOUT
Operation timed out
.It Bq Er FETCH_UNAVAIL
File is not available
.It Bq Er FETCH_UNKNOWN
Unknown error
.It Bq Er FETCH_URL
Invalid URL
.El
.Pp
The accompanying error message includes a protocol-specific error code
and message, e.g. "File is not available (404 Not Found)"
.Sh ENVIRONMENT
The FTP and HTTP related functions use the
.Ev HTTP_PROXY
@ -196,6 +272,7 @@ and
environment variables, respectively, as the address of a proxy server
to use for transferring files.
.Sh SEE ALSO
.Xr com_err 3 ,
.Xr fetch 1 ,
.Xr ftpio 3
.Rs
@ -216,13 +293,14 @@ to use for transferring files.
.%B File Transfer Protocol
.%O RFC959
.Re
.Sh DIAGNOSTICS
Add later.
.Sh NOTES
Some parts of the library are not yet implemented. The most notable
examples of this are
.Fn fetchPutHTTP
and proxy support for the FTP access method.
The
.Nm fetch
library uses the Common Error library, and applications which link
with
.Nm libfetch
must therefore also link with
.Nm libcom_err .
.Sh HISTORY
The
.Nm fetch
@ -234,18 +312,26 @@ The
library was mostly written by
.An Dag-Erling Coïdan Smørgrav Aq des@FreeBSD.org
with numerous suggestions from
.An Jordan K. Hubbard Aq jkh@FreeBSD.org
.An Jordan K. Hubbard Aq jkh@FreeBSD.org ,
.An Eugene Skepner Aq eu@qub.com
and other FreeBSD developers.
It incorporates the older
It replaces the older
.Nm ftpio
library, which was originally written by
.Nm Poul-Henning Kamp Aq pkh@FreeBSD.org
and later turned inside out by
library written by
.An Poul-Henning Kamp Aq pkh@FreeBSD.org
and
.An Jordan K. Hubbard Aq jkh@FreeBSD.org .
.Pp
This manual page was written by
.An Dag-Erling Coïdan Smørgrav Aq des@FreeBSD.org
.Sh BUGS
Some parts of the library are not yet implemented. The most notable
examples of this are
.Fn fetchPutHTTP ,
.Fn fetchStatFTP ,
.Fn fetchStatHTTP
and FTP proxy support.
.Pp
There's no way to select a proxy at run-time other than setting the
.Ev HTTP_PROXY
or

View File

@ -25,10 +25,11 @@
* (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: fetch.c,v 1.4 1998/08/17 09:30:19 des Exp $
* $Id: fetch.c,v 1.5 1998/11/05 19:48:17 des Exp $
*/
#include <sys/param.h>
#include <sys/errno.h>
#include <ctype.h>
#include <stdio.h>
@ -36,22 +37,33 @@
#include <string.h>
#include "fetch.h"
#include "common.h"
#ifndef NDEBUG
#define DEBUG(x) do x; while (0)
#else
#define DEBUG(x) do { } while (0)
#endif
int fetchLastErrCode;
const char *fetchLastErrText;
/*** Local data **************************************************************/
/*
* Error messages for parser errors
*/
#define URL_MALFORMED 1
#define URL_BAD_SCHEME 2
#define URL_BAD_PORT 3
static struct fetcherr _url_errlist[] = {
{ URL_MALFORMED, FETCH_URL, "Malformed URL" },
{ URL_BAD_SCHEME, FETCH_URL, "Invalid URL scheme" },
{ URL_BAD_PORT, FETCH_URL, "Invalid server port" },
{ -1, FETCH_UNKNOWN, "Unknown parser error" }
};
/*** Public API **************************************************************/
/*
* Select the appropriate protocol for the URL scheme, and return a
* read-only stream connected to the document referenced by the URL.
*/
FILE *
fetchGet(url_t *URL, char *flags)
fetchGet(struct url *URL, char *flags)
{
if (strcasecmp(URL->scheme, "file") == 0)
return fetchGetFile(URL, flags);
@ -59,8 +71,10 @@ fetchGet(url_t *URL, char *flags)
return fetchGetHTTP(URL, flags);
else if (strcasecmp(URL->scheme, "ftp") == 0)
return fetchGetFTP(URL, flags);
else return NULL;
else {
_url_seterr(URL_BAD_SCHEME);
return NULL;
}
}
/*
@ -68,7 +82,7 @@ fetchGet(url_t *URL, char *flags)
* write-only stream connected to the document referenced by the URL.
*/
FILE *
fetchPut(url_t *URL, char *flags)
fetchPut(struct url *URL, char *flags)
{
if (strcasecmp(URL->scheme, "file") == 0)
return fetchPutFile(URL, flags);
@ -76,7 +90,29 @@ fetchPut(url_t *URL, char *flags)
return fetchPutHTTP(URL, flags);
else if (strcasecmp(URL->scheme, "ftp") == 0)
return fetchPutFTP(URL, flags);
else return NULL;
else {
_url_seterr(URL_BAD_SCHEME);
return NULL;
}
}
/*
* Select the appropriate protocol for the URL scheme, and return the
* size of the document referenced by the URL if it exists.
*/
int
fetchStat(struct url *URL, struct url_stat *us, char *flags)
{
if (strcasecmp(URL->scheme, "file") == 0)
return fetchStatFile(URL, us, flags);
else if (strcasecmp(URL->scheme, "http") == 0)
return fetchStatHTTP(URL, us, flags);
else if (strcasecmp(URL->scheme, "ftp") == 0)
return fetchStatFTP(URL, us, flags);
else {
_url_seterr(URL_BAD_SCHEME);
return -1;
}
}
/*
@ -85,7 +121,7 @@ fetchPut(url_t *URL, char *flags)
FILE *
fetchGetURL(char *URL, char *flags)
{
url_t *u;
struct url *u;
FILE *f;
if ((u = fetchParseURL(URL)) == NULL)
@ -104,7 +140,7 @@ fetchGetURL(char *URL, char *flags)
FILE *
fetchPutURL(char *URL, char *flags)
{
url_t *u;
struct url *u;
FILE *f;
if ((u = fetchParseURL(URL)) == NULL)
@ -116,28 +152,51 @@ fetchPutURL(char *URL, char *flags)
return f;
}
/*
* Attempt to parse the given URL; if successful, call fetchStat().
*/
int
fetchStatURL(char *URL, struct url_stat *us, char *flags)
{
struct url *u;
int s;
if ((u = fetchParseURL(URL)) == NULL)
return -1;
s = fetchStat(u, us, flags);
free(u);
return s;
}
/*
* Split an URL into components. URL syntax is:
* method:[//[user[:pwd]@]host[:port]]/[document]
* This almost, but not quite, RFC1738 URL syntax.
*/
url_t *
struct url *
fetchParseURL(char *URL)
{
char *p, *q;
url_t *u;
struct url *u;
int i;
/* allocate url_t */
if ((u = calloc(1, sizeof(url_t))) == NULL)
/* allocate struct url */
if ((u = calloc(1, sizeof(struct url))) == NULL) {
errno = ENOMEM;
_fetch_syserr();
return NULL;
}
/* scheme name */
for (i = 0; *URL && (*URL != ':'); URL++)
if (i < URL_SCHEMELEN)
u->scheme[i++] = *URL;
if (!URL[0] || (URL[1] != '/'))
if (!URL[0] || (URL[1] != '/')) {
_url_seterr(URL_BAD_SCHEME);
goto ouch;
}
else URL++;
if (URL[1] != '/') {
p = URL;
@ -171,7 +230,11 @@ fetchParseURL(char *URL)
for (q = ++p; *q && (*q != '/'); q++)
if (isdigit(*q))
u->port = u->port * 10 + (*q - '0');
else return 0; /* invalid port */
else {
/* invalid port */
_url_seterr(URL_BAD_PORT);
goto ouch;
}
while (*p && (*p != '/'))
p++;
}
@ -179,10 +242,13 @@ fetchParseURL(char *URL)
nohost:
/* document */
if (*p) {
url_t *t;
struct url *t;
t = realloc(u, sizeof(*u)+strlen(p)-1);
if (t == NULL)
if (t == NULL) {
errno = ENOMEM;
_fetch_syserr();
goto ouch;
}
u = t;
strcpy(u->doc, p);
} else {

View File

@ -25,7 +25,7 @@
* (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: fetch.h,v 1.4 1998/08/17 09:30:19 des Exp $
* $Id: fetch.h,v 1.5 1998/11/05 19:48:17 des Exp $
*/
#ifndef _FETCH_H_INCLUDED
@ -34,47 +34,51 @@
#include <sys/param.h>
#include <stdio.h>
#include <fetch_err.h>
#define _LIBFETCH_VER "libfetch/1.0"
#define URL_SCHEMELEN 16
#define URL_USERLEN 256
#define URL_PWDLEN 256
struct url_s {
char scheme[URL_SCHEMELEN+1];
char user[URL_USERLEN+1];
char pwd[URL_PWDLEN+1];
char host[MAXHOSTNAMELEN+1];
int port;
char doc[2];
struct url {
char scheme[URL_SCHEMELEN+1];
char user[URL_USERLEN+1];
char pwd[URL_PWDLEN+1];
char host[MAXHOSTNAMELEN+1];
int port;
char doc[2];
};
typedef struct url_s url_t;
struct url_stat {
off_t size;
time_t time;
};
/* FILE-specific functions */
FILE *fetchGetFile(url_t *, char *);
FILE *fetchPutFile(url_t *, char *);
FILE *fetchGetFile(struct url *, char *);
FILE *fetchPutFile(struct url *, char *);
int fetchStatFile(struct url *, struct url_stat *, char *);
/* HTTP-specific functions */
char *fetchContentType(FILE *);
FILE *fetchGetHTTP(url_t *, char *);
FILE *fetchPutHTTP(url_t *, char *);
char *fetchContentType(FILE *);
FILE *fetchGetHTTP(struct url *, char *);
FILE *fetchPutHTTP(struct url *, char *);
int fetchStatHTTP(struct url *, struct url_stat *, char *);
/* FTP-specific functions */
FILE *fetchGetFTP(url_t *, char *);
FILE *fetchPutFTP(url_t *, char *);
FILE *fetchGetFTP(struct url *, char *);
FILE *fetchPutFTP(struct url *, char *);
int fetchStatFTP(struct url *, struct url_stat *, char *);
/* Generic functions */
int fetchConnect(char *, int);
url_t *fetchParseURL(char *);
void fetchFreeURL(url_t *);
FILE *fetchGetURL(char *, char *);
FILE *fetchPutURL(char *, char *);
FILE *fetchGet(url_t *, char *);
FILE *fetchPut(url_t *, char *);
/* Error code and string */
extern int fetchLastErrCode;
extern const char *fetchLastErrText;
struct url *fetchParseURL(char *);
FILE *fetchGetURL(char *, char *);
FILE *fetchPutURL(char *, char *);
int fetchStatURL(char *, struct url_stat *, char *);
FILE *fetchGet(struct url *, char *);
FILE *fetchPut(struct url *, char *);
int fetchStat(struct url *, struct url_stat *, char *);
#endif

49
lib/libfetch/fetch_err.et Normal file
View File

@ -0,0 +1,49 @@
#-
# Copyright (c) 1998 Dag-Erling Coïdan Smørgrav
# All rights reserved.
#
# 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
# in this position and unchanged.
# 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.
# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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$
#
et ftch
ec FETCH_ABORT, "Operation aborted"
ec FETCH_AUTH, "Authentication failed"
ec FETCH_DOWN, "Service unavailable"
ec FETCH_EXISTS, "File exists"
ec FETCH_FULL, "File system full"
ec FETCH_INFO, "Informational response"
ec FETCH_MEMORY, "Insufficient memory"
ec FETCH_MOVED, "File has moved"
ec FETCH_NETWORK, "Network error"
ec FETCH_OK, "No error"
ec FETCH_PROTO, "Protocol error"
ec FETCH_RESOLV, "Resolver error"
ec FETCH_SERVER, "Server error"
ec FETCH_TEMP, "Temporary error"
ec FETCH_TIMEOUT, "Operation timed out"
ec FETCH_UNAVAIL, "File is not available"
ec FETCH_UNKNOWN, "Unknown error"
ec FETCH_URL, "Invalid URL"
end

View File

@ -25,25 +25,54 @@
* (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$
* $Id: file.c,v 1.1.1.1 1998/07/09 16:52:41 des Exp $
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include "fetch.h"
#include "common.h"
FILE *
fetchGetFile(url_t *u, char *flags)
fetchGetFile(struct url *u, char *flags)
{
flags = flags; /* unused */
return fopen(u->doc, "r");
FILE *f;
f = fopen(u->doc, "r");
if (f == NULL)
_fetch_syserr();
return f;
}
FILE *
fetchPutFile(url_t *u, char *flags)
fetchPutFile(struct url *u, char *flags)
{
FILE *f;
if (strchr(flags, 'a'))
return fopen(u->doc, "a");
else return fopen(u->doc, "w");
f = fopen(u->doc, "a");
else
f = fopen(u->doc, "w");
if (f == NULL)
_fetch_syserr();
return f;
}
int
fetchStatFile(struct url *u, struct url_stat *us, char *flags)
{
struct stat sb;
if (stat(u->doc, &sb) == -1) {
_fetch_syserr();
return -1;
}
us->size = sb.st_size;
us->time = sb.st_mtime;
return 0;
}

View File

@ -25,7 +25,7 @@
* (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: ftp.c,v 1.5 1998/08/17 09:30:19 des Exp $
* $Id: ftp.c,v 1.6 1998/11/05 19:48:17 des Exp $
*/
/*
@ -71,7 +71,7 @@
#include "fetch.h"
#include "common.h"
#include "ftperr.c"
#include "ftperr.inc"
#define FTP_DEFAULT_TO_ANONYMOUS
#define FTP_ANONYMOUS_USER "ftp"
@ -88,7 +88,7 @@
#define ENDL "\r\n"
static url_t cached_host;
static struct url cached_host;
static FILE *cached_socket;
static char *_ftp_last_reply;
@ -101,6 +101,7 @@ _ftp_chkerr(FILE *s, int *e)
{
char *line;
size_t len;
int err;
if (e)
*e = 0;
@ -122,14 +123,15 @@ _ftp_chkerr(FILE *s, int *e)
if (!isdigit(line[1]) || !isdigit(line[1])
|| !isdigit(line[2]) || (line[3] != ' ')) {
_ftp_seterr(-1);
_ftp_seterr(0);
return -1;
}
_ftp_seterr((line[0] - '0') * 100 + (line[1] - '0') * 10 + (line[2] - '0'));
err = (line[0] - '0') * 100 + (line[1] - '0') * 10 + (line[2] - '0');
_ftp_seterr(err);
if (e)
*e = fetchLastErrCode;
*e = err;
return (line[0] == '2') - 1;
}
@ -365,7 +367,7 @@ _ftp_disconnect(FILE *f)
* Check if we're already connected
*/
static int
_ftp_isconnected(url_t *url)
_ftp_isconnected(struct url *url)
{
return (cached_socket
&& (strcmp(url->host, cached_host.host) == 0)
@ -378,7 +380,7 @@ _ftp_isconnected(url_t *url)
* FTP session
*/
static FILE *
fetchXxxFTP(url_t *url, char *oper, char *mode, char *flags)
fetchXxxFTP(struct url *url, char *oper, char *mode, char *flags)
{
FILE *cf = NULL;
int e;
@ -402,7 +404,7 @@ fetchXxxFTP(url_t *url, char *oper, char *mode, char *flags)
if (cached_socket)
_ftp_disconnect(cached_socket);
cached_socket = cf;
memcpy(&cached_host, url, sizeof(url_t));
memcpy(&cached_host, url, sizeof(struct url));
}
/* initiate the transfer */
@ -413,15 +415,24 @@ fetchXxxFTP(url_t *url, char *oper, char *mode, char *flags)
* Itsy bitsy teeny weenie
*/
FILE *
fetchGetFTP(url_t *url, char *flags)
fetchGetFTP(struct url *url, char *flags)
{
return fetchXxxFTP(url, "RETR", "r", flags);
}
FILE *
fetchPutFTP(url_t *url, char *flags)
fetchPutFTP(struct url *url, char *flags)
{
if (flags && strchr(flags, 'a'))
return fetchXxxFTP(url, "APPE", "w", flags);
else return fetchXxxFTP(url, "STOR", "w", flags);
}
extern void warnx(char *fmt, ...);
int
fetchStatFTP(struct url *url, struct url_stat *us, char *flags)
{
warnx("fetchStatFTP(): not implemented");
return -1;
}

View File

@ -1,44 +1,44 @@
# $Id: ftp.errors,v 1.3 1997/02/22 15:06:47 peter Exp $
# $Id: ftp.errors,v 1.1.1.1 1998/07/09 16:52:43 des Exp $
#
# This list is taken from RFC 959.
# It probably needs a going over.
#
110 Restart marker reply
120 Service ready in a few minutes
125 Data connection already open; transfer starting
150 File status okay; about to open data connection
200 Command okay
202 Command not implemented, superfluous at this site
211 System status, or system help reply
212 Directory status
213 File status
214 Help message
215 Set system type
220 Service ready for new user
221 Service closing control connection
225 Data connection open; no transfer in progress
226 Requested file action successful
227 Entering Passive Mode
230 User logged in, proceed
250 Requested file action okay, completed
257 File/directory created
331 User name okay, need password
332 Need account for login
350 Requested file action pending further information
421 Service not available, closing control connection
425 Can't open data connection
426 Connection closed; transfer aborted
450 File unavailable (e.g., file busy)
451 Requested action aborted: local error in processing
452 Insufficient storage space in system
500 Syntax error, command unrecognized
501 Syntax error in parameters or arguments
502 Command not implemented
503 Bad sequence of commands
504 Command not implemented for that parameter
530 Not logged in
532 Need account for storing files
550 File unavailable (e.g., file not found, no access)
551 Requested action aborted. Page type unknown
552 Exceeded storage allocation
553 File name not allowed
110 OK Restart marker reply
120 TEMP Service ready in a few minutes
125 OK Data connection already open; transfer starting
150 OK File status okay; about to open data connection
200 OK Command okay
202 PROTO Command not implemented, superfluous at this site
211 INFO System status, or system help reply
212 INFO Directory status
213 INFO File status
214 INFO Help message
215 INFO Set system type
220 OK Service ready for new user
221 OK Service closing control connection
225 OK Data connection open; no transfer in progress
226 OK Requested file action successful
227 OK Entering Passive Mode
230 OK User logged in, proceed
250 OK Requested file action okay, completed
257 OK File/directory created
331 AUTH User name okay, need password
332 AUTH Need account for login
350 OK Requested file action pending further information
421 DOWN Service not available, closing control connection
425 NETWORK Can't open data connection
426 ABORT Connection closed; transfer aborted
450 UNAVAIL File unavailable (e.g., file busy)
451 SERVER Requested action aborted: local error in processing
452 FULL Insufficient storage space in system
500 PROTO Syntax error, command unrecognized
501 PROTO Syntax error in parameters or arguments
502 PROTO Command not implemented
503 PROTO Bad sequence of commands
504 PROTO Command not implemented for that parameter
530 AUTH Not logged in
532 AUTH Need account for storing files
550 UNAVAIL File unavailable (e.g., file not found, no access)
551 PROTO Requested action aborted. Page type unknown
552 FULL Exceeded storage allocation
553 EXISTS File name not allowed

View File

@ -25,7 +25,7 @@
* (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: http.c,v 1.5 1998/08/17 09:30:19 des Exp $
* $Id: http.c,v 1.6 1998/11/05 19:48:17 des Exp $
*/
/*
@ -78,7 +78,7 @@
#include "fetch.h"
#include "common.h"
#include "httperr.c"
#include "httperr.inc"
#ifndef NDEBUG
#define DEBUG(x) do x; while (0)
@ -300,10 +300,10 @@ _http_auth(char *usr, char *pwd)
}
/*
* retrieve a file by HTTP
* Retrieve a file by HTTP
*/
FILE *
fetchGetHTTP(url_t *URL, char *flags)
fetchGetHTTP(struct url *URL, char *flags)
{
int sd = -1, err, i, enc = ENC_NONE;
struct cookie *c;
@ -389,8 +389,7 @@ fetchGetHTTP(url_t *URL, char *flags)
/* add code to handle redirects later */
if (err != 200) {
fetchLastErrCode = err;
fetchLastErrText = _http_errstring(err);
_http_seterr(err);
goto fouch;
}
@ -452,8 +451,18 @@ fetchGetHTTP(url_t *URL, char *flags)
}
FILE *
fetchPutHTTP(url_t *URL, char *flags)
fetchPutHTTP(struct url *URL, char *flags)
{
warnx("fetchPutHTTP(): not implemented");
return NULL;
}
/*
* Get an HTTP document's metadata
*/
int
fetchStatHTTP(struct url *url, struct url_stat *us, char *flags)
{
warnx("fetchStatHTTP(): not implemented");
return -1;
}

View File

@ -1,41 +1,41 @@
# $Id$
# $Id: http.errors,v 1.1.1.1 1998/07/09 16:52:44 des Exp $
#
# This list is taken from RFC 2068.
#
100 Continue
101 Switching Protocols
200 OK
201 Created
202 Accepted
203 Non-Authoritative Information
204 No Content
205 Reset Content
206 Partial Content
300 Multiple Choices
301 Moved Permanently
302 Moved Temporarily
303 See Other
304 Not Modified
305 Use Proxy
400 Bad Request
401 Unauthorized
402 Payment Required
403 Forbidden
404 Not Found
405 Method Not Allowed
406 Not Acceptable
407 Proxy Authentication Required
408 Request Time-out
409 Conflict
410 Gone
411 Length Required
412 Precondition Failed
413 Request Entity Too Large
414 Request-URI Too Large
415 Unsupported Media Type
500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Time-out
505 HTTP Version not supported
100 OK Continue
101 OK Switching Protocols
200 OK OK
201 OK Created
202 OK Accepted
203 INFO Non-Authoritative Information
204 OK No Content
205 OK Reset Content
206 OK Partial Content
300 MOVED Multiple Choices
301 MOVED Moved Permanently
302 MOVED Moved Temporarily
303 MOVED See Other
304 OK Not Modified
305 INFO Use Proxy
400 PROTO Bad Request
401 AUTH Unauthorized
402 AUTH Payment Required
403 AUTH Forbidden
404 UNAVAIL Not Found
405 PROTO Method Not Allowed
406 PROTO Not Acceptable
407 AUTH Proxy Authentication Required
408 TIMEOUT Request Time-out
409 EXISTS Conflict
410 UNAVAIL Gone
411 PROTO Length Required
412 SERVER Precondition Failed
413 PROTO Request Entity Too Large
414 PROTO Request-URI Too Large
415 PROTO Unsupported Media Type
500 SERVER Internal Server Error
501 PROTO Not Implemented
502 SERVER Bad Gateway
503 TEMP Service Unavailable
504 TIMEOUT Gateway Time-out
505 PROTO HTTP Version not supported