xref: /freebsd/lib/libfetch/fetch.c (revision c97925ad4e79dd82554760f514089a3e683147be)
14ca1ab94SDag-Erling Smørgrav /*-
24ca1ab94SDag-Erling Smørgrav  * Copyright (c) 1998 Dag-Erling Co�dan Sm�rgrav
34ca1ab94SDag-Erling Smørgrav  * All rights reserved.
44ca1ab94SDag-Erling Smørgrav  *
54ca1ab94SDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
64ca1ab94SDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
74ca1ab94SDag-Erling Smørgrav  * are met:
84ca1ab94SDag-Erling Smørgrav  * 1. Redistributions of source code must retain the above copyright
94ca1ab94SDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer
104ca1ab94SDag-Erling Smørgrav  *    in this position and unchanged.
114ca1ab94SDag-Erling Smørgrav  * 2. Redistributions in binary form must reproduce the above copyright
124ca1ab94SDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer in the
134ca1ab94SDag-Erling Smørgrav  *    documentation and/or other materials provided with the distribution.
144ca1ab94SDag-Erling Smørgrav  * 3. The name of the author may not be used to endorse or promote products
154ca1ab94SDag-Erling Smørgrav  *    derived from this software without specific prior written permission
164ca1ab94SDag-Erling Smørgrav  *
174ca1ab94SDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
184ca1ab94SDag-Erling Smørgrav  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
194ca1ab94SDag-Erling Smørgrav  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
204ca1ab94SDag-Erling Smørgrav  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
214ca1ab94SDag-Erling Smørgrav  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
224ca1ab94SDag-Erling Smørgrav  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
234ca1ab94SDag-Erling Smørgrav  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
244ca1ab94SDag-Erling Smørgrav  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
254ca1ab94SDag-Erling Smørgrav  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
264ca1ab94SDag-Erling Smørgrav  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
274ca1ab94SDag-Erling Smørgrav  *
287f3dea24SPeter Wemm  * $FreeBSD$
294ca1ab94SDag-Erling Smørgrav  */
304ca1ab94SDag-Erling Smørgrav 
314ca1ab94SDag-Erling Smørgrav #include <sys/param.h>
32d8acd8dcSDag-Erling Smørgrav #include <sys/errno.h>
334ca1ab94SDag-Erling Smørgrav 
344ca1ab94SDag-Erling Smørgrav #include <ctype.h>
354ca1ab94SDag-Erling Smørgrav #include <stdio.h>
364ca1ab94SDag-Erling Smørgrav #include <stdlib.h>
374ca1ab94SDag-Erling Smørgrav #include <string.h>
384ca1ab94SDag-Erling Smørgrav 
394ca1ab94SDag-Erling Smørgrav #include "fetch.h"
40d8acd8dcSDag-Erling Smørgrav #include "common.h"
414ca1ab94SDag-Erling Smørgrav 
424ca1ab94SDag-Erling Smørgrav 
430fba3a00SDag-Erling Smørgrav int fetchLastErrCode;
44fc6e9e65SDag-Erling Smørgrav int fetchTimeout;
450fba3a00SDag-Erling Smørgrav 
460fba3a00SDag-Erling Smørgrav 
47d8acd8dcSDag-Erling Smørgrav /*** Local data **************************************************************/
48d8acd8dcSDag-Erling Smørgrav 
49d8acd8dcSDag-Erling Smørgrav /*
50d8acd8dcSDag-Erling Smørgrav  * Error messages for parser errors
51d8acd8dcSDag-Erling Smørgrav  */
52d8acd8dcSDag-Erling Smørgrav #define URL_MALFORMED		1
53d8acd8dcSDag-Erling Smørgrav #define URL_BAD_SCHEME		2
54d8acd8dcSDag-Erling Smørgrav #define URL_BAD_PORT		3
55d8acd8dcSDag-Erling Smørgrav static struct fetcherr _url_errlist[] = {
56d8acd8dcSDag-Erling Smørgrav     { URL_MALFORMED,	FETCH_URL,	"Malformed URL" },
57d8acd8dcSDag-Erling Smørgrav     { URL_BAD_SCHEME,	FETCH_URL,	"Invalid URL scheme" },
58d8acd8dcSDag-Erling Smørgrav     { URL_BAD_PORT,	FETCH_URL,	"Invalid server port" },
59d8acd8dcSDag-Erling Smørgrav     { -1,		FETCH_UNKNOWN,	"Unknown parser error" }
60d8acd8dcSDag-Erling Smørgrav };
61d8acd8dcSDag-Erling Smørgrav 
62d8acd8dcSDag-Erling Smørgrav 
63d8acd8dcSDag-Erling Smørgrav /*** Public API **************************************************************/
644ca1ab94SDag-Erling Smørgrav 
65842a95ccSDag-Erling Smørgrav /*
66842a95ccSDag-Erling Smørgrav  * Select the appropriate protocol for the URL scheme, and return a
67842a95ccSDag-Erling Smørgrav  * read-only stream connected to the document referenced by the URL.
68842a95ccSDag-Erling Smørgrav  */
69ecc91352SDag-Erling Smørgrav FILE *
70d8acd8dcSDag-Erling Smørgrav fetchGet(struct url *URL, char *flags)
71ecc91352SDag-Erling Smørgrav {
72c97925adSHajimu UMEMOTO     int direct;
73c97925adSHajimu UMEMOTO 
74c97925adSHajimu UMEMOTO     direct = (flags && strchr(flags, 'd'));
75ecc91352SDag-Erling Smørgrav     if (strcasecmp(URL->scheme, "file") == 0)
76ecc91352SDag-Erling Smørgrav 	return fetchGetFile(URL, flags);
77ecc91352SDag-Erling Smørgrav     else if (strcasecmp(URL->scheme, "http") == 0)
78ecc91352SDag-Erling Smørgrav 	return fetchGetHTTP(URL, flags);
79c97925adSHajimu UMEMOTO     else if (strcasecmp(URL->scheme, "ftp") == 0) {
80c97925adSHajimu UMEMOTO 	if (!direct &&
81c97925adSHajimu UMEMOTO 	    getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL)
82c97925adSHajimu UMEMOTO 	    return fetchGetHTTP(URL, flags);
83ecc91352SDag-Erling Smørgrav 	return fetchGetFTP(URL, flags);
84c97925adSHajimu UMEMOTO     } else {
85d8acd8dcSDag-Erling Smørgrav 	_url_seterr(URL_BAD_SCHEME);
86d8acd8dcSDag-Erling Smørgrav 	return NULL;
87d8acd8dcSDag-Erling Smørgrav     }
88ecc91352SDag-Erling Smørgrav }
89ecc91352SDag-Erling Smørgrav 
90842a95ccSDag-Erling Smørgrav /*
91842a95ccSDag-Erling Smørgrav  * Select the appropriate protocol for the URL scheme, and return a
92842a95ccSDag-Erling Smørgrav  * write-only stream connected to the document referenced by the URL.
93842a95ccSDag-Erling Smørgrav  */
94ecc91352SDag-Erling Smørgrav FILE *
95d8acd8dcSDag-Erling Smørgrav fetchPut(struct url *URL, char *flags)
96ecc91352SDag-Erling Smørgrav {
97c97925adSHajimu UMEMOTO     int direct;
98c97925adSHajimu UMEMOTO 
99c97925adSHajimu UMEMOTO     direct = (flags && strchr(flags, 'd'));
100ecc91352SDag-Erling Smørgrav     if (strcasecmp(URL->scheme, "file") == 0)
101ecc91352SDag-Erling Smørgrav 	return fetchPutFile(URL, flags);
102ecc91352SDag-Erling Smørgrav     else if (strcasecmp(URL->scheme, "http") == 0)
103ecc91352SDag-Erling Smørgrav 	return fetchPutHTTP(URL, flags);
104c97925adSHajimu UMEMOTO     else if (strcasecmp(URL->scheme, "ftp") == 0) {
105c97925adSHajimu UMEMOTO 	if (!direct &&
106c97925adSHajimu UMEMOTO 	    getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL)
107c97925adSHajimu UMEMOTO 	    return fetchPutHTTP(URL, flags);
108ecc91352SDag-Erling Smørgrav 	return fetchPutFTP(URL, flags);
109c97925adSHajimu UMEMOTO     } else {
110d8acd8dcSDag-Erling Smørgrav 	_url_seterr(URL_BAD_SCHEME);
111d8acd8dcSDag-Erling Smørgrav 	return NULL;
112d8acd8dcSDag-Erling Smørgrav     }
113d8acd8dcSDag-Erling Smørgrav }
114d8acd8dcSDag-Erling Smørgrav 
115d8acd8dcSDag-Erling Smørgrav /*
116d8acd8dcSDag-Erling Smørgrav  * Select the appropriate protocol for the URL scheme, and return the
117d8acd8dcSDag-Erling Smørgrav  * size of the document referenced by the URL if it exists.
118d8acd8dcSDag-Erling Smørgrav  */
119d8acd8dcSDag-Erling Smørgrav int
120d8acd8dcSDag-Erling Smørgrav fetchStat(struct url *URL, struct url_stat *us, char *flags)
121d8acd8dcSDag-Erling Smørgrav {
122c97925adSHajimu UMEMOTO     int direct;
123c97925adSHajimu UMEMOTO 
124c97925adSHajimu UMEMOTO     direct = (flags && strchr(flags, 'd'));
125d8acd8dcSDag-Erling Smørgrav     if (strcasecmp(URL->scheme, "file") == 0)
126d8acd8dcSDag-Erling Smørgrav 	return fetchStatFile(URL, us, flags);
127d8acd8dcSDag-Erling Smørgrav     else if (strcasecmp(URL->scheme, "http") == 0)
128d8acd8dcSDag-Erling Smørgrav 	return fetchStatHTTP(URL, us, flags);
129c97925adSHajimu UMEMOTO     else if (strcasecmp(URL->scheme, "ftp") == 0) {
130c97925adSHajimu UMEMOTO 	if (!direct &&
131c97925adSHajimu UMEMOTO 	    getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL)
132c97925adSHajimu UMEMOTO 	    return fetchStatHTTP(URL, us, flags);
133d8acd8dcSDag-Erling Smørgrav 	return fetchStatFTP(URL, us, flags);
134c97925adSHajimu UMEMOTO     } else {
135d8acd8dcSDag-Erling Smørgrav 	_url_seterr(URL_BAD_SCHEME);
136d8acd8dcSDag-Erling Smørgrav 	return -1;
137d8acd8dcSDag-Erling Smørgrav     }
138ecc91352SDag-Erling Smørgrav }
139ecc91352SDag-Erling Smørgrav 
140842a95ccSDag-Erling Smørgrav /*
141ce71b736SDag-Erling Smørgrav  * Select the appropriate protocol for the URL scheme, and return a
142ce71b736SDag-Erling Smørgrav  * list of files in the directory pointed to by the URL.
143ce71b736SDag-Erling Smørgrav  */
144ce71b736SDag-Erling Smørgrav struct url_ent *
145ce71b736SDag-Erling Smørgrav fetchList(struct url *URL, char *flags)
146ce71b736SDag-Erling Smørgrav {
147c97925adSHajimu UMEMOTO     int direct;
148c97925adSHajimu UMEMOTO 
149c97925adSHajimu UMEMOTO     direct = (flags && strchr(flags, 'd'));
150ce71b736SDag-Erling Smørgrav     if (strcasecmp(URL->scheme, "file") == 0)
151ce71b736SDag-Erling Smørgrav 	return fetchListFile(URL, flags);
152ce71b736SDag-Erling Smørgrav     else if (strcasecmp(URL->scheme, "http") == 0)
153ce71b736SDag-Erling Smørgrav 	return fetchListHTTP(URL, flags);
154c97925adSHajimu UMEMOTO     else if (strcasecmp(URL->scheme, "ftp") == 0) {
155c97925adSHajimu UMEMOTO 	if (!direct &&
156c97925adSHajimu UMEMOTO 	    getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL)
157c97925adSHajimu UMEMOTO 	    return fetchListHTTP(URL, flags);
158ce71b736SDag-Erling Smørgrav 	return fetchListFTP(URL, flags);
159c97925adSHajimu UMEMOTO     } else {
160ce71b736SDag-Erling Smørgrav 	_url_seterr(URL_BAD_SCHEME);
161ce71b736SDag-Erling Smørgrav 	return NULL;
162ce71b736SDag-Erling Smørgrav     }
163ce71b736SDag-Erling Smørgrav }
164ce71b736SDag-Erling Smørgrav 
165ce71b736SDag-Erling Smørgrav /*
166842a95ccSDag-Erling Smørgrav  * Attempt to parse the given URL; if successful, call fetchGet().
167842a95ccSDag-Erling Smørgrav  */
1684ca1ab94SDag-Erling Smørgrav FILE *
1694ca1ab94SDag-Erling Smørgrav fetchGetURL(char *URL, char *flags)
1704ca1ab94SDag-Erling Smørgrav {
171d8acd8dcSDag-Erling Smørgrav     struct url *u;
1724ca1ab94SDag-Erling Smørgrav     FILE *f;
1734ca1ab94SDag-Erling Smørgrav 
1744ca1ab94SDag-Erling Smørgrav     if ((u = fetchParseURL(URL)) == NULL)
1754ca1ab94SDag-Erling Smørgrav 	return NULL;
1764ca1ab94SDag-Erling Smørgrav 
177ecc91352SDag-Erling Smørgrav     f = fetchGet(u, flags);
1784ca1ab94SDag-Erling Smørgrav 
17960245e42SDag-Erling Smørgrav     fetchFreeURL(u);
1804ca1ab94SDag-Erling Smørgrav     return f;
1814ca1ab94SDag-Erling Smørgrav }
1824ca1ab94SDag-Erling Smørgrav 
1834ca1ab94SDag-Erling Smørgrav 
184842a95ccSDag-Erling Smørgrav /*
185842a95ccSDag-Erling Smørgrav  * Attempt to parse the given URL; if successful, call fetchPut().
186842a95ccSDag-Erling Smørgrav  */
1874ca1ab94SDag-Erling Smørgrav FILE *
1884ca1ab94SDag-Erling Smørgrav fetchPutURL(char *URL, char *flags)
1894ca1ab94SDag-Erling Smørgrav {
190d8acd8dcSDag-Erling Smørgrav     struct url *u;
1914ca1ab94SDag-Erling Smørgrav     FILE *f;
1924ca1ab94SDag-Erling Smørgrav 
1934ca1ab94SDag-Erling Smørgrav     if ((u = fetchParseURL(URL)) == NULL)
1944ca1ab94SDag-Erling Smørgrav 	return NULL;
1954ca1ab94SDag-Erling Smørgrav 
196ecc91352SDag-Erling Smørgrav     f = fetchPut(u, flags);
1974ca1ab94SDag-Erling Smørgrav 
19860245e42SDag-Erling Smørgrav     fetchFreeURL(u);
1994ca1ab94SDag-Erling Smørgrav     return f;
2004ca1ab94SDag-Erling Smørgrav }
2014ca1ab94SDag-Erling Smørgrav 
2024ca1ab94SDag-Erling Smørgrav /*
203d8acd8dcSDag-Erling Smørgrav  * Attempt to parse the given URL; if successful, call fetchStat().
204d8acd8dcSDag-Erling Smørgrav  */
205d8acd8dcSDag-Erling Smørgrav int
206d8acd8dcSDag-Erling Smørgrav fetchStatURL(char *URL, struct url_stat *us, char *flags)
207d8acd8dcSDag-Erling Smørgrav {
208d8acd8dcSDag-Erling Smørgrav     struct url *u;
209d8acd8dcSDag-Erling Smørgrav     int s;
210d8acd8dcSDag-Erling Smørgrav 
211d8acd8dcSDag-Erling Smørgrav     if ((u = fetchParseURL(URL)) == NULL)
212d8acd8dcSDag-Erling Smørgrav 	return -1;
213d8acd8dcSDag-Erling Smørgrav 
214d8acd8dcSDag-Erling Smørgrav     s = fetchStat(u, us, flags);
215d8acd8dcSDag-Erling Smørgrav 
21660245e42SDag-Erling Smørgrav     fetchFreeURL(u);
217d8acd8dcSDag-Erling Smørgrav     return s;
218d8acd8dcSDag-Erling Smørgrav }
219d8acd8dcSDag-Erling Smørgrav 
220d8acd8dcSDag-Erling Smørgrav /*
221ce71b736SDag-Erling Smørgrav  * Attempt to parse the given URL; if successful, call fetchList().
222ce71b736SDag-Erling Smørgrav  */
223ce71b736SDag-Erling Smørgrav struct url_ent *
224ce71b736SDag-Erling Smørgrav fetchListURL(char *URL, char *flags)
225ce71b736SDag-Erling Smørgrav {
226ce71b736SDag-Erling Smørgrav     struct url *u;
227ce71b736SDag-Erling Smørgrav     struct url_ent *ue;
228ce71b736SDag-Erling Smørgrav 
229ce71b736SDag-Erling Smørgrav     if ((u = fetchParseURL(URL)) == NULL)
230ce71b736SDag-Erling Smørgrav 	return NULL;
231ce71b736SDag-Erling Smørgrav 
232ce71b736SDag-Erling Smørgrav     ue = fetchList(u, flags);
233ce71b736SDag-Erling Smørgrav 
23460245e42SDag-Erling Smørgrav     fetchFreeURL(u);
235ce71b736SDag-Erling Smørgrav     return ue;
236ce71b736SDag-Erling Smørgrav }
237ce71b736SDag-Erling Smørgrav 
238ce71b736SDag-Erling Smørgrav /*
2394ca1ab94SDag-Erling Smørgrav  * Split an URL into components. URL syntax is:
2404ca1ab94SDag-Erling Smørgrav  * method:[//[user[:pwd]@]host[:port]]/[document]
2414ca1ab94SDag-Erling Smørgrav  * This almost, but not quite, RFC1738 URL syntax.
2424ca1ab94SDag-Erling Smørgrav  */
243d8acd8dcSDag-Erling Smørgrav struct url *
2444ca1ab94SDag-Erling Smørgrav fetchParseURL(char *URL)
2454ca1ab94SDag-Erling Smørgrav {
2464ca1ab94SDag-Erling Smørgrav     char *p, *q;
247d8acd8dcSDag-Erling Smørgrav     struct url *u;
2484ca1ab94SDag-Erling Smørgrav     int i;
2494ca1ab94SDag-Erling Smørgrav 
250d8acd8dcSDag-Erling Smørgrav     /* allocate struct url */
251807c941cSDag-Erling Smørgrav     if ((u = calloc(1, sizeof *u)) == NULL) {
252d8acd8dcSDag-Erling Smørgrav 	errno = ENOMEM;
253d8acd8dcSDag-Erling Smørgrav 	_fetch_syserr();
2544ca1ab94SDag-Erling Smørgrav 	return NULL;
255d8acd8dcSDag-Erling Smørgrav     }
2564ca1ab94SDag-Erling Smørgrav 
2574ca1ab94SDag-Erling Smørgrav     /* scheme name */
2584ca1ab94SDag-Erling Smørgrav     for (i = 0; *URL && (*URL != ':'); URL++)
2594ca1ab94SDag-Erling Smørgrav 	if (i < URL_SCHEMELEN)
2604ca1ab94SDag-Erling Smørgrav 	    u->scheme[i++] = *URL;
261d8acd8dcSDag-Erling Smørgrav     if (!URL[0] || (URL[1] != '/')) {
262d8acd8dcSDag-Erling Smørgrav 	_url_seterr(URL_BAD_SCHEME);
2634ca1ab94SDag-Erling Smørgrav 	goto ouch;
264d8acd8dcSDag-Erling Smørgrav     }
2654ca1ab94SDag-Erling Smørgrav     else URL++;
2664ca1ab94SDag-Erling Smørgrav     if (URL[1] != '/') {
2674ca1ab94SDag-Erling Smørgrav 	p = URL;
2684ca1ab94SDag-Erling Smørgrav 	goto nohost;
2694ca1ab94SDag-Erling Smørgrav     }
2704ca1ab94SDag-Erling Smørgrav     else URL += 2;
2714ca1ab94SDag-Erling Smørgrav 
2724ca1ab94SDag-Erling Smørgrav     p = strpbrk(URL, "/@");
2730fba3a00SDag-Erling Smørgrav     if (p && *p == '@') {
2744ca1ab94SDag-Erling Smørgrav 	/* username */
2754ca1ab94SDag-Erling Smørgrav 	for (q = URL, i = 0; (*q != ':') && (*q != '@'); q++)
2764ca1ab94SDag-Erling Smørgrav 	    if (i < URL_USERLEN)
2774ca1ab94SDag-Erling Smørgrav 		u->user[i++] = *q;
2784ca1ab94SDag-Erling Smørgrav 
2794ca1ab94SDag-Erling Smørgrav 	/* password */
2804ca1ab94SDag-Erling Smørgrav 	if (*q == ':')
2814ca1ab94SDag-Erling Smørgrav 	    for (q++, i = 0; (*q != ':') && (*q != '@'); q++)
2824ca1ab94SDag-Erling Smørgrav 		if (i < URL_PWDLEN)
2834ca1ab94SDag-Erling Smørgrav 		    u->pwd[i++] = *q;
2844ca1ab94SDag-Erling Smørgrav 
2854ca1ab94SDag-Erling Smørgrav 	p++;
2864ca1ab94SDag-Erling Smørgrav     } else p = URL;
2874ca1ab94SDag-Erling Smørgrav 
2884ca1ab94SDag-Erling Smørgrav     /* hostname */
2894ca1ab94SDag-Erling Smørgrav     for (i = 0; *p && (*p != '/') && (*p != ':'); p++)
2904ca1ab94SDag-Erling Smørgrav 	if (i < MAXHOSTNAMELEN)
2914ca1ab94SDag-Erling Smørgrav 	    u->host[i++] = *p;
2924ca1ab94SDag-Erling Smørgrav 
2934ca1ab94SDag-Erling Smørgrav     /* port */
2944ca1ab94SDag-Erling Smørgrav     if (*p == ':') {
2954ca1ab94SDag-Erling Smørgrav 	for (q = ++p; *q && (*q != '/'); q++)
2964ca1ab94SDag-Erling Smørgrav 	    if (isdigit(*q))
2974ca1ab94SDag-Erling Smørgrav 		u->port = u->port * 10 + (*q - '0');
298d8acd8dcSDag-Erling Smørgrav 	    else {
299d8acd8dcSDag-Erling Smørgrav 		/* invalid port */
300d8acd8dcSDag-Erling Smørgrav 		_url_seterr(URL_BAD_PORT);
301d8acd8dcSDag-Erling Smørgrav 		goto ouch;
302d8acd8dcSDag-Erling Smørgrav 	    }
3034ca1ab94SDag-Erling Smørgrav 	while (*p && (*p != '/'))
3044ca1ab94SDag-Erling Smørgrav 	    p++;
3054ca1ab94SDag-Erling Smørgrav     }
3064ca1ab94SDag-Erling Smørgrav 
3074ca1ab94SDag-Erling Smørgrav nohost:
3084ca1ab94SDag-Erling Smørgrav     /* document */
30960245e42SDag-Erling Smørgrav     if (!*p)
31060245e42SDag-Erling Smørgrav 	p = "/";
31160245e42SDag-Erling Smørgrav 
31260245e42SDag-Erling Smørgrav     if ((u->doc = strdup(p)) == NULL) {
313d8acd8dcSDag-Erling Smørgrav 	errno = ENOMEM;
314d8acd8dcSDag-Erling Smørgrav 	_fetch_syserr();
3154ca1ab94SDag-Erling Smørgrav 	goto ouch;
316d8acd8dcSDag-Erling Smørgrav     }
3174ca1ab94SDag-Erling Smørgrav 
3184ca1ab94SDag-Erling Smørgrav     DEBUG(fprintf(stderr,
3194ca1ab94SDag-Erling Smørgrav 		  "scheme:   [\033[1m%s\033[m]\n"
3204ca1ab94SDag-Erling Smørgrav 		  "user:     [\033[1m%s\033[m]\n"
3214ca1ab94SDag-Erling Smørgrav 		  "password: [\033[1m%s\033[m]\n"
3224ca1ab94SDag-Erling Smørgrav 		  "host:     [\033[1m%s\033[m]\n"
3234ca1ab94SDag-Erling Smørgrav 		  "port:     [\033[1m%d\033[m]\n"
3244ca1ab94SDag-Erling Smørgrav 		  "document: [\033[1m%s\033[m]\n",
3254ca1ab94SDag-Erling Smørgrav 		  u->scheme, u->user, u->pwd,
3264ca1ab94SDag-Erling Smørgrav 		  u->host, u->port, u->doc));
3274ca1ab94SDag-Erling Smørgrav 
3284ca1ab94SDag-Erling Smørgrav     return u;
3294ca1ab94SDag-Erling Smørgrav 
3304ca1ab94SDag-Erling Smørgrav ouch:
3314ca1ab94SDag-Erling Smørgrav     free(u);
3324ca1ab94SDag-Erling Smørgrav     return NULL;
3334ca1ab94SDag-Erling Smørgrav }
33460245e42SDag-Erling Smørgrav 
33560245e42SDag-Erling Smørgrav /*
33660245e42SDag-Erling Smørgrav  * Free a URL
33760245e42SDag-Erling Smørgrav  */
33860245e42SDag-Erling Smørgrav void
33960245e42SDag-Erling Smørgrav fetchFreeURL(struct url *u)
34060245e42SDag-Erling Smørgrav {
34160245e42SDag-Erling Smørgrav     free(u->doc);
34260245e42SDag-Erling Smørgrav     free(u);
34360245e42SDag-Erling Smørgrav }
344