Pullup ticket #6832 - requested by riastradh net/libfetch: enable HTTPS cert validation on NetBSD 10 pkgtools/pkg_install, pkgtools/pkgin: revbump (via patch) net/libfetch: Enable HTTPS certificate validation, but limit it to NetBSD>=10 for now. The switch has been flipped on for all platforms in pkgsrc-current with net/libfetch 2.40. To avoid trouble with future updates to pkgsrc-2024Q1, the attached patch -- which is limited at compile-time to NetBSD>=10 -- bumps the version to 2.39nb3 instead, so that the version in pkgsrc-2024Q1 will appear newer. See https://mail-index.netbsd.org/pkgsrc-users/2023/12/31/msg038682.html https://mail-index.netbsd.org/tech-pkg/2023/12/09/msg028590.html for discussion. (A future pullup might rip off the NetBSD>=10 bandaid, but I'd like to get this part in ASAP.)diff -r1.64 -r1.64.2.1 pkgsrc/net/libfetch/Makefile
(bsiegert)
@@ -1,34 +1,34 @@ | @@ -1,34 +1,34 @@ | |||
1 | # $NetBSD: Makefile,v 1.64 2023/10/24 22:10:22 wiz Exp $ | 1 | # $NetBSD: Makefile,v 1.64.2.1 2024/01/13 12:49:09 bsiegert Exp $ | |
2 | 2 | |||
3 | DISTNAME= libfetch-2.39 | 3 | DISTNAME= libfetch-2.39 | |
4 | PKGREVISION= 2 | 4 | PKGREVISION= 3 | |
5 | CATEGORIES= net | 5 | CATEGORIES= net | |
6 | MASTER_SITES= # empty | 6 | MASTER_SITES= # empty | |
7 | DISTFILES= # empty | 7 | DISTFILES= # empty | |
8 | 8 | |||
9 | MAINTAINER= pkgsrc-users@NetBSD.org | 9 | MAINTAINER= pkgsrc-users@NetBSD.org | |
10 | HOMEPAGE= https://www.FreeBSD.org/ | 10 | HOMEPAGE= https://www.FreeBSD.org/ | |
11 | COMMENT= Library to access HTTP/FTP server | 11 | COMMENT= Library to access HTTP/FTP server | |
12 | LICENSE= modified-bsd | 12 | LICENSE= modified-bsd | |
13 | 13 | |||
14 | USE_FEATURES= nbcompat | 14 | USE_FEATURES= nbcompat | |
15 | 15 | |||
16 | USE_BSD_MAKEFILE= yes | 16 | USE_BSD_MAKEFILE= yes | |
17 | 17 | |||
18 | .include "../../mk/bsd.prefs.mk" | 18 | .include "../../mk/bsd.prefs.mk" | |
19 | .if !empty(FETCH_USING:Mfetch) | 19 | .if !empty(FETCH_USING:Mfetch) | |
20 | CHECK_PERMS= no | 20 | CHECK_PERMS= no | |
21 | .endif | 21 | .endif | |
22 | 22 | |||
23 | INSTALLATION_DIRS= include lib ${PKGMANDIR}/cat3 ${PKGMANDIR}/man3 | 23 | INSTALLATION_DIRS= include lib ${PKGMANDIR}/cat3 ${PKGMANDIR}/man3 | |
24 | 24 | |||
25 | BUILD_TARGET= depend all | 25 | BUILD_TARGET= depend all | |
26 | INSTALL_TARGET= install includes | 26 | INSTALL_TARGET= install includes | |
27 | 27 | |||
28 | do-extract: | 28 | do-extract: | |
29 | ${CP} -r ${FILESDIR} ${WRKSRC} | 29 | ${CP} -r ${FILESDIR} ${WRKSRC} | |
30 | ${TOUCH} ${WRKSRC}/fetch.cat3 | 30 | ${TOUCH} ${WRKSRC}/fetch.cat3 | |
31 | 31 | |||
32 | .include "options.mk" | 32 | .include "options.mk" | |
33 | 33 | |||
34 | .include "../../mk/bsd.pkg.mk" | 34 | .include "../../mk/bsd.pkg.mk" |
@@ -1,1085 +1,1095 @@ | @@ -1,1085 +1,1095 @@ | |||
1 | /* $NetBSD: common.c,v 1.31 2016/10/20 21:25:57 joerg Exp $ */ | 1 | /* $NetBSD: common.c,v 1.31.58.1 2024/01/13 12:49:09 bsiegert Exp $ */ | |
2 | /*- | 2 | /*- | |
3 | * Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav | 3 | * Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav | |
4 | * Copyright (c) 2008, 2010 Joerg Sonnenberger <joerg@NetBSD.org> | 4 | * Copyright (c) 2008, 2010 Joerg Sonnenberger <joerg@NetBSD.org> | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer | 11 | * notice, this list of conditions and the following disclaimer | |
12 | * in this position and unchanged. | 12 | * in this position and unchanged. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | 13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | 14 | * notice, this list of conditions and the following disclaimer in the | |
15 | * documentation and/or other materials provided with the distribution. | 15 | * documentation and/or other materials provided with the distribution. | |
16 | * 3. The name of the author may not be used to endorse or promote products | 16 | * 3. The name of the author may not be used to endorse or promote products | |
17 | * derived from this software without specific prior written permission | 17 | * derived from this software without specific prior written permission | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
21 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 21 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
22 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 22 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
23 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 23 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
24 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
28 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 | * | 29 | * | |
30 | * $FreeBSD: common.c,v 1.53 2007/12/19 00:26:36 des Exp $ | 30 | * $FreeBSD: common.c,v 1.53 2007/12/19 00:26:36 des Exp $ | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | #if HAVE_CONFIG_H | 33 | #if HAVE_CONFIG_H | |
34 | #include "config.h" | 34 | #include "config.h" | |
35 | #endif | 35 | #endif | |
36 | #ifndef NETBSD | 36 | #ifndef NETBSD | |
37 | #include <nbcompat.h> | 37 | #include <nbcompat.h> | |
38 | #endif | 38 | #endif | |
39 | 39 | |||
40 | #ifdef __NetBSD__ | |||
41 | #include <sys/param.h> /* __NetBSD_Version__ */ | |||
42 | #endif | |||
43 | ||||
40 | #include <sys/types.h> | 44 | #include <sys/types.h> | |
41 | #include <sys/socket.h> | 45 | #include <sys/socket.h> | |
42 | #include <sys/time.h> | 46 | #include <sys/time.h> | |
43 | #include <sys/uio.h> | 47 | #include <sys/uio.h> | |
44 | #if HAVE_POLL_H | 48 | #if HAVE_POLL_H | |
45 | #include <poll.h> | 49 | #include <poll.h> | |
46 | #elif HAVE_SYS_POLL_H | 50 | #elif HAVE_SYS_POLL_H | |
47 | #include <sys/poll.h> | 51 | #include <sys/poll.h> | |
48 | #endif | 52 | #endif | |
49 | #include <netinet/in.h> | 53 | #include <netinet/in.h> | |
50 | #include <arpa/inet.h> | 54 | #include <arpa/inet.h> | |
51 | 55 | |||
52 | #include <ctype.h> | 56 | #include <ctype.h> | |
53 | #include <errno.h> | 57 | #include <errno.h> | |
54 | #if defined(HAVE_INTTYPES_H) || defined(NETBSD) | 58 | #if defined(HAVE_INTTYPES_H) || defined(NETBSD) | |
55 | #include <inttypes.h> | 59 | #include <inttypes.h> | |
56 | #endif | 60 | #endif | |
57 | #ifndef NETBSD | 61 | #ifndef NETBSD | |
58 | #include <nbcompat/netdb.h> | 62 | #include <nbcompat/netdb.h> | |
59 | #else | 63 | #else | |
60 | #include <netdb.h> | 64 | #include <netdb.h> | |
61 | #endif | 65 | #endif | |
62 | #include <pwd.h> | 66 | #include <pwd.h> | |
63 | #include <stdarg.h> | 67 | #include <stdarg.h> | |
64 | #include <stdlib.h> | 68 | #include <stdlib.h> | |
65 | #include <stdio.h> | 69 | #include <stdio.h> | |
66 | #include <string.h> | 70 | #include <string.h> | |
67 | #include <unistd.h> | 71 | #include <unistd.h> | |
68 | 72 | |||
69 | #ifndef MSG_NOSIGNAL | 73 | #ifndef MSG_NOSIGNAL | |
70 | #include <signal.h> | 74 | #include <signal.h> | |
71 | #endif | 75 | #endif | |
72 | 76 | |||
73 | #include "fetch.h" | 77 | #include "fetch.h" | |
74 | #include "common.h" | 78 | #include "common.h" | |
75 | 79 | |||
76 | /*** Local data **************************************************************/ | 80 | /*** Local data **************************************************************/ | |
77 | 81 | |||
78 | /* | 82 | /* | |
79 | * Error messages for resolver errors | 83 | * Error messages for resolver errors | |
80 | */ | 84 | */ | |
81 | static struct fetcherr netdb_errlist[] = { | 85 | static struct fetcherr netdb_errlist[] = { | |
82 | #ifdef EAI_NODATA | 86 | #ifdef EAI_NODATA | |
83 | { EAI_NODATA, FETCH_RESOLV, "Host not found" }, | 87 | { EAI_NODATA, FETCH_RESOLV, "Host not found" }, | |
84 | #endif | 88 | #endif | |
85 | { EAI_AGAIN, FETCH_TEMP, "Transient resolver failure" }, | 89 | { EAI_AGAIN, FETCH_TEMP, "Transient resolver failure" }, | |
86 | { EAI_FAIL, FETCH_RESOLV, "Non-recoverable resolver failure" }, | 90 | { EAI_FAIL, FETCH_RESOLV, "Non-recoverable resolver failure" }, | |
87 | { EAI_NONAME, FETCH_RESOLV, "No address record" }, | 91 | { EAI_NONAME, FETCH_RESOLV, "No address record" }, | |
88 | { -1, FETCH_UNKNOWN, "Unknown resolver error" } | 92 | { -1, FETCH_UNKNOWN, "Unknown resolver error" } | |
89 | }; | 93 | }; | |
90 | 94 | |||
91 | /*** Error-reporting functions ***********************************************/ | 95 | /*** Error-reporting functions ***********************************************/ | |
92 | 96 | |||
93 | /* | 97 | /* | |
94 | * Map error code to string | 98 | * Map error code to string | |
95 | */ | 99 | */ | |
96 | static struct fetcherr * | 100 | static struct fetcherr * | |
97 | fetch_finderr(struct fetcherr *p, int e) | 101 | fetch_finderr(struct fetcherr *p, int e) | |
98 | { | 102 | { | |
99 | while (p->num != -1 && p->num != e) | 103 | while (p->num != -1 && p->num != e) | |
100 | p++; | 104 | p++; | |
101 | return (p); | 105 | return (p); | |
102 | } | 106 | } | |
103 | 107 | |||
104 | /* | 108 | /* | |
105 | * Set error code | 109 | * Set error code | |
106 | */ | 110 | */ | |
107 | void | 111 | void | |
108 | fetch_seterr(struct fetcherr *p, int e) | 112 | fetch_seterr(struct fetcherr *p, int e) | |
109 | { | 113 | { | |
110 | p = fetch_finderr(p, e); | 114 | p = fetch_finderr(p, e); | |
111 | fetchLastErrCode = p->cat; | 115 | fetchLastErrCode = p->cat; | |
112 | snprintf(fetchLastErrString, MAXERRSTRING, "%s", p->string); | 116 | snprintf(fetchLastErrString, MAXERRSTRING, "%s", p->string); | |
113 | } | 117 | } | |
114 | 118 | |||
115 | /* | 119 | /* | |
116 | * Set error code according to errno | 120 | * Set error code according to errno | |
117 | */ | 121 | */ | |
118 | void | 122 | void | |
119 | fetch_syserr(void) | 123 | fetch_syserr(void) | |
120 | { | 124 | { | |
121 | switch (errno) { | 125 | switch (errno) { | |
122 | case 0: | 126 | case 0: | |
123 | fetchLastErrCode = FETCH_OK; | 127 | fetchLastErrCode = FETCH_OK; | |
124 | break; | 128 | break; | |
125 | case EPERM: | 129 | case EPERM: | |
126 | case EACCES: | 130 | case EACCES: | |
127 | case EROFS: | 131 | case EROFS: | |
128 | #ifdef EAUTH | 132 | #ifdef EAUTH | |
129 | case EAUTH: | 133 | case EAUTH: | |
130 | #endif | 134 | #endif | |
131 | #ifdef ENEEDAUTH | 135 | #ifdef ENEEDAUTH | |
132 | case ENEEDAUTH: | 136 | case ENEEDAUTH: | |
133 | #endif | 137 | #endif | |
134 | fetchLastErrCode = FETCH_AUTH; | 138 | fetchLastErrCode = FETCH_AUTH; | |
135 | break; | 139 | break; | |
136 | case ENOENT: | 140 | case ENOENT: | |
137 | case EISDIR: /* XXX */ | 141 | case EISDIR: /* XXX */ | |
138 | fetchLastErrCode = FETCH_UNAVAIL; | 142 | fetchLastErrCode = FETCH_UNAVAIL; | |
139 | break; | 143 | break; | |
140 | case ENOMEM: | 144 | case ENOMEM: | |
141 | fetchLastErrCode = FETCH_MEMORY; | 145 | fetchLastErrCode = FETCH_MEMORY; | |
142 | break; | 146 | break; | |
143 | case EBUSY: | 147 | case EBUSY: | |
144 | case EAGAIN: | 148 | case EAGAIN: | |
145 | fetchLastErrCode = FETCH_TEMP; | 149 | fetchLastErrCode = FETCH_TEMP; | |
146 | break; | 150 | break; | |
147 | case EEXIST: | 151 | case EEXIST: | |
148 | fetchLastErrCode = FETCH_EXISTS; | 152 | fetchLastErrCode = FETCH_EXISTS; | |
149 | break; | 153 | break; | |
150 | case ENOSPC: | 154 | case ENOSPC: | |
151 | fetchLastErrCode = FETCH_FULL; | 155 | fetchLastErrCode = FETCH_FULL; | |
152 | break; | 156 | break; | |
153 | case EADDRINUSE: | 157 | case EADDRINUSE: | |
154 | case EADDRNOTAVAIL: | 158 | case EADDRNOTAVAIL: | |
155 | case ENETDOWN: | 159 | case ENETDOWN: | |
156 | case ENETUNREACH: | 160 | case ENETUNREACH: | |
157 | case ENETRESET: | 161 | case ENETRESET: | |
158 | case EHOSTUNREACH: | 162 | case EHOSTUNREACH: | |
159 | fetchLastErrCode = FETCH_NETWORK; | 163 | fetchLastErrCode = FETCH_NETWORK; | |
160 | break; | 164 | break; | |
161 | case ECONNABORTED: | 165 | case ECONNABORTED: | |
162 | case ECONNRESET: | 166 | case ECONNRESET: | |
163 | fetchLastErrCode = FETCH_ABORT; | 167 | fetchLastErrCode = FETCH_ABORT; | |
164 | break; | 168 | break; | |
165 | case ETIMEDOUT: | 169 | case ETIMEDOUT: | |
166 | fetchLastErrCode = FETCH_TIMEOUT; | 170 | fetchLastErrCode = FETCH_TIMEOUT; | |
167 | break; | 171 | break; | |
168 | case ECONNREFUSED: | 172 | case ECONNREFUSED: | |
169 | case EHOSTDOWN: | 173 | case EHOSTDOWN: | |
170 | fetchLastErrCode = FETCH_DOWN; | 174 | fetchLastErrCode = FETCH_DOWN; | |
171 | break; | 175 | break; | |
172 | default: | 176 | default: | |
173 | fetchLastErrCode = FETCH_UNKNOWN; | 177 | fetchLastErrCode = FETCH_UNKNOWN; | |
174 | } | 178 | } | |
175 | snprintf(fetchLastErrString, MAXERRSTRING, "%s", strerror(errno)); | 179 | snprintf(fetchLastErrString, MAXERRSTRING, "%s", strerror(errno)); | |
176 | } | 180 | } | |
177 | 181 | |||
178 | 182 | |||
179 | /* | 183 | /* | |
180 | * Emit status message | 184 | * Emit status message | |
181 | */ | 185 | */ | |
182 | void | 186 | void | |
183 | fetch_info(const char *fmt, ...) | 187 | fetch_info(const char *fmt, ...) | |
184 | { | 188 | { | |
185 | va_list ap; | 189 | va_list ap; | |
186 | 190 | |||
187 | va_start(ap, fmt); | 191 | va_start(ap, fmt); | |
188 | vfprintf(stderr, fmt, ap); | 192 | vfprintf(stderr, fmt, ap); | |
189 | va_end(ap); | 193 | va_end(ap); | |
190 | fputc('\n', stderr); | 194 | fputc('\n', stderr); | |
191 | } | 195 | } | |
192 | 196 | |||
193 | 197 | |||
194 | /*** Network-related utility functions ***************************************/ | 198 | /*** Network-related utility functions ***************************************/ | |
195 | 199 | |||
196 | /* | 200 | /* | |
197 | * Return the default port for a scheme | 201 | * Return the default port for a scheme | |
198 | */ | 202 | */ | |
199 | int | 203 | int | |
200 | fetch_default_port(const char *scheme) | 204 | fetch_default_port(const char *scheme) | |
201 | { | 205 | { | |
202 | struct servent *se; | 206 | struct servent *se; | |
203 | 207 | |||
204 | if ((se = getservbyname(scheme, "tcp")) != NULL) | 208 | if ((se = getservbyname(scheme, "tcp")) != NULL) | |
205 | return (ntohs(se->s_port)); | 209 | return (ntohs(se->s_port)); | |
206 | if (strcasecmp(scheme, SCHEME_FTP) == 0) | 210 | if (strcasecmp(scheme, SCHEME_FTP) == 0) | |
207 | return (FTP_DEFAULT_PORT); | 211 | return (FTP_DEFAULT_PORT); | |
208 | if (strcasecmp(scheme, SCHEME_HTTP) == 0) | 212 | if (strcasecmp(scheme, SCHEME_HTTP) == 0) | |
209 | return (HTTP_DEFAULT_PORT); | 213 | return (HTTP_DEFAULT_PORT); | |
210 | return (0); | 214 | return (0); | |
211 | } | 215 | } | |
212 | 216 | |||
213 | /* | 217 | /* | |
214 | * Return the default proxy port for a scheme | 218 | * Return the default proxy port for a scheme | |
215 | */ | 219 | */ | |
216 | int | 220 | int | |
217 | fetch_default_proxy_port(const char *scheme) | 221 | fetch_default_proxy_port(const char *scheme) | |
218 | { | 222 | { | |
219 | if (strcasecmp(scheme, SCHEME_FTP) == 0) | 223 | if (strcasecmp(scheme, SCHEME_FTP) == 0) | |
220 | return (FTP_DEFAULT_PROXY_PORT); | 224 | return (FTP_DEFAULT_PROXY_PORT); | |
221 | if (strcasecmp(scheme, SCHEME_HTTP) == 0) | 225 | if (strcasecmp(scheme, SCHEME_HTTP) == 0) | |
222 | return (HTTP_DEFAULT_PROXY_PORT); | 226 | return (HTTP_DEFAULT_PROXY_PORT); | |
223 | return (0); | 227 | return (0); | |
224 | } | 228 | } | |
225 | 229 | |||
226 | 230 | |||
227 | /* | 231 | /* | |
228 | * Create a connection for an existing descriptor. | 232 | * Create a connection for an existing descriptor. | |
229 | */ | 233 | */ | |
230 | conn_t * | 234 | conn_t * | |
231 | fetch_reopen(int sd) | 235 | fetch_reopen(int sd) | |
232 | { | 236 | { | |
233 | conn_t *conn; | 237 | conn_t *conn; | |
234 | 238 | |||
235 | /* allocate and fill connection structure */ | 239 | /* allocate and fill connection structure */ | |
236 | if ((conn = calloc(1, sizeof(*conn))) == NULL) | 240 | if ((conn = calloc(1, sizeof(*conn))) == NULL) | |
237 | return (NULL); | 241 | return (NULL); | |
238 | conn->ftp_home = NULL; | 242 | conn->ftp_home = NULL; | |
239 | conn->cache_url = NULL; | 243 | conn->cache_url = NULL; | |
240 | conn->next_buf = NULL; | 244 | conn->next_buf = NULL; | |
241 | conn->next_len = 0; | 245 | conn->next_len = 0; | |
242 | conn->sd = sd; | 246 | conn->sd = sd; | |
243 | conn->buf_events = POLLIN; | 247 | conn->buf_events = POLLIN; | |
244 | return (conn); | 248 | return (conn); | |
245 | } | 249 | } | |
246 | 250 | |||
247 | 251 | |||
248 | /* | 252 | /* | |
249 | * Bind a socket to a specific local address | 253 | * Bind a socket to a specific local address | |
250 | */ | 254 | */ | |
251 | int | 255 | int | |
252 | fetch_bind(int sd, int af, const char *addr) | 256 | fetch_bind(int sd, int af, const char *addr) | |
253 | { | 257 | { | |
254 | struct addrinfo hints, *res, *res0; | 258 | struct addrinfo hints, *res, *res0; | |
255 | 259 | |||
256 | memset(&hints, 0, sizeof(hints)); | 260 | memset(&hints, 0, sizeof(hints)); | |
257 | hints.ai_family = af; | 261 | hints.ai_family = af; | |
258 | hints.ai_socktype = SOCK_STREAM; | 262 | hints.ai_socktype = SOCK_STREAM; | |
259 | hints.ai_protocol = 0; | 263 | hints.ai_protocol = 0; | |
260 | if (getaddrinfo(addr, NULL, &hints, &res0)) | 264 | if (getaddrinfo(addr, NULL, &hints, &res0)) | |
261 | return (-1); | 265 | return (-1); | |
262 | for (res = res0; res; res = res->ai_next) { | 266 | for (res = res0; res; res = res->ai_next) { | |
263 | if (bind(sd, res->ai_addr, res->ai_addrlen) == 0) | 267 | if (bind(sd, res->ai_addr, res->ai_addrlen) == 0) | |
264 | return (0); | 268 | return (0); | |
265 | } | 269 | } | |
266 | return (-1); | 270 | return (-1); | |
267 | } | 271 | } | |
268 | 272 | |||
269 | 273 | |||
270 | /* | 274 | /* | |
271 | * Establish a TCP connection to the specified port on the specified host. | 275 | * Establish a TCP connection to the specified port on the specified host. | |
272 | */ | 276 | */ | |
273 | conn_t * | 277 | conn_t * | |
274 | fetch_connect(struct url *url, int af, int verbose) | 278 | fetch_connect(struct url *url, int af, int verbose) | |
275 | { | 279 | { | |
276 | conn_t *conn; | 280 | conn_t *conn; | |
277 | char pbuf[10]; | 281 | char pbuf[10]; | |
278 | const char *bindaddr; | 282 | const char *bindaddr; | |
279 | struct addrinfo hints, *res, *res0; | 283 | struct addrinfo hints, *res, *res0; | |
280 | int sd, error; | 284 | int sd, error; | |
281 | 285 | |||
282 | if (verbose) | 286 | if (verbose) | |
283 | fetch_info("looking up %s", url->host); | 287 | fetch_info("looking up %s", url->host); | |
284 | 288 | |||
285 | /* look up host name and set up socket address structure */ | 289 | /* look up host name and set up socket address structure */ | |
286 | snprintf(pbuf, sizeof(pbuf), "%d", url->port); | 290 | snprintf(pbuf, sizeof(pbuf), "%d", url->port); | |
287 | memset(&hints, 0, sizeof(hints)); | 291 | memset(&hints, 0, sizeof(hints)); | |
288 | hints.ai_family = af; | 292 | hints.ai_family = af; | |
289 | hints.ai_socktype = SOCK_STREAM; | 293 | hints.ai_socktype = SOCK_STREAM; | |
290 | hints.ai_protocol = 0; | 294 | hints.ai_protocol = 0; | |
291 | if ((error = getaddrinfo(url->host, pbuf, &hints, &res0)) != 0) { | 295 | if ((error = getaddrinfo(url->host, pbuf, &hints, &res0)) != 0) { | |
292 | netdb_seterr(error); | 296 | netdb_seterr(error); | |
293 | return (NULL); | 297 | return (NULL); | |
294 | } | 298 | } | |
295 | bindaddr = getenv("FETCH_BIND_ADDRESS"); | 299 | bindaddr = getenv("FETCH_BIND_ADDRESS"); | |
296 | 300 | |||
297 | if (verbose) | 301 | if (verbose) | |
298 | fetch_info("connecting to %s:%d", url->host, url->port); | 302 | fetch_info("connecting to %s:%d", url->host, url->port); | |
299 | 303 | |||
300 | /* try to connect */ | 304 | /* try to connect */ | |
301 | for (sd = -1, res = res0; res; sd = -1, res = res->ai_next) { | 305 | for (sd = -1, res = res0; res; sd = -1, res = res->ai_next) { | |
302 | if ((sd = socket(res->ai_family, res->ai_socktype, | 306 | if ((sd = socket(res->ai_family, res->ai_socktype, | |
303 | res->ai_protocol)) == -1) | 307 | res->ai_protocol)) == -1) | |
304 | continue; | 308 | continue; | |
305 | if (bindaddr != NULL && *bindaddr != '\0' && | 309 | if (bindaddr != NULL && *bindaddr != '\0' && | |
306 | fetch_bind(sd, res->ai_family, bindaddr) != 0) { | 310 | fetch_bind(sd, res->ai_family, bindaddr) != 0) { | |
307 | fetch_info("failed to bind to '%s'", bindaddr); | 311 | fetch_info("failed to bind to '%s'", bindaddr); | |
308 | close(sd); | 312 | close(sd); | |
309 | continue; | 313 | continue; | |
310 | } | 314 | } | |
311 | if (connect(sd, res->ai_addr, res->ai_addrlen) == 0) | 315 | if (connect(sd, res->ai_addr, res->ai_addrlen) == 0) | |
312 | break; | 316 | break; | |
313 | close(sd); | 317 | close(sd); | |
314 | } | 318 | } | |
315 | freeaddrinfo(res0); | 319 | freeaddrinfo(res0); | |
316 | if (sd == -1) { | 320 | if (sd == -1) { | |
317 | fetch_syserr(); | 321 | fetch_syserr(); | |
318 | return (NULL); | 322 | return (NULL); | |
319 | } | 323 | } | |
320 | 324 | |||
321 | if ((conn = fetch_reopen(sd)) == NULL) { | 325 | if ((conn = fetch_reopen(sd)) == NULL) { | |
322 | fetch_syserr(); | 326 | fetch_syserr(); | |
323 | close(sd); | 327 | close(sd); | |
324 | return (NULL); | 328 | return (NULL); | |
325 | } | 329 | } | |
326 | conn->cache_url = fetchCopyURL(url); | 330 | conn->cache_url = fetchCopyURL(url); | |
327 | conn->cache_af = af; | 331 | conn->cache_af = af; | |
328 | return (conn); | 332 | return (conn); | |
329 | } | 333 | } | |
330 | 334 | |||
331 | static conn_t *connection_cache; | 335 | static conn_t *connection_cache; | |
332 | static int cache_global_limit = 0; | 336 | static int cache_global_limit = 0; | |
333 | static int cache_per_host_limit = 0; | 337 | static int cache_per_host_limit = 0; | |
334 | 338 | |||
335 | /* | 339 | /* | |
336 | * Initialise cache with the given limits. | 340 | * Initialise cache with the given limits. | |
337 | */ | 341 | */ | |
338 | void | 342 | void | |
339 | fetchConnectionCacheInit(int global_limit, int per_host_limit) | 343 | fetchConnectionCacheInit(int global_limit, int per_host_limit) | |
340 | { | 344 | { | |
341 | 345 | |||
342 | if (global_limit < 0) | 346 | if (global_limit < 0) | |
343 | cache_global_limit = INT_MAX; | 347 | cache_global_limit = INT_MAX; | |
344 | else if (per_host_limit > global_limit) | 348 | else if (per_host_limit > global_limit) | |
345 | cache_global_limit = per_host_limit; | 349 | cache_global_limit = per_host_limit; | |
346 | else | 350 | else | |
347 | cache_global_limit = global_limit; | 351 | cache_global_limit = global_limit; | |
348 | if (per_host_limit < 0) | 352 | if (per_host_limit < 0) | |
349 | cache_per_host_limit = INT_MAX; | 353 | cache_per_host_limit = INT_MAX; | |
350 | else | 354 | else | |
351 | cache_per_host_limit = per_host_limit; | 355 | cache_per_host_limit = per_host_limit; | |
352 | } | 356 | } | |
353 | 357 | |||
354 | /* | 358 | /* | |
355 | * Flush cache and free all associated resources. | 359 | * Flush cache and free all associated resources. | |
356 | */ | 360 | */ | |
357 | void | 361 | void | |
358 | fetchConnectionCacheClose(void) | 362 | fetchConnectionCacheClose(void) | |
359 | { | 363 | { | |
360 | conn_t *conn; | 364 | conn_t *conn; | |
361 | 365 | |||
362 | while ((conn = connection_cache) != NULL) { | 366 | while ((conn = connection_cache) != NULL) { | |
363 | connection_cache = conn->next_cached; | 367 | connection_cache = conn->next_cached; | |
364 | (*conn->cache_close)(conn); | 368 | (*conn->cache_close)(conn); | |
365 | } | 369 | } | |
366 | } | 370 | } | |
367 | 371 | |||
368 | /* | 372 | /* | |
369 | * Check connection cache for an existing entry matching | 373 | * Check connection cache for an existing entry matching | |
370 | * protocol/host/port/user/password/family. | 374 | * protocol/host/port/user/password/family. | |
371 | */ | 375 | */ | |
372 | conn_t * | 376 | conn_t * | |
373 | fetch_cache_get(const struct url *url, int af) | 377 | fetch_cache_get(const struct url *url, int af) | |
374 | { | 378 | { | |
375 | conn_t *conn, *last_conn = NULL; | 379 | conn_t *conn, *last_conn = NULL; | |
376 | 380 | |||
377 | for (conn = connection_cache; conn; conn = conn->next_cached) { | 381 | for (conn = connection_cache; conn; conn = conn->next_cached) { | |
378 | if (conn->cache_url->port == url->port && | 382 | if (conn->cache_url->port == url->port && | |
379 | strcmp(conn->cache_url->scheme, url->scheme) == 0 && | 383 | strcmp(conn->cache_url->scheme, url->scheme) == 0 && | |
380 | strcmp(conn->cache_url->host, url->host) == 0 && | 384 | strcmp(conn->cache_url->host, url->host) == 0 && | |
381 | strcmp(conn->cache_url->user, url->user) == 0 && | 385 | strcmp(conn->cache_url->user, url->user) == 0 && | |
382 | strcmp(conn->cache_url->pwd, url->pwd) == 0 && | 386 | strcmp(conn->cache_url->pwd, url->pwd) == 0 && | |
383 | (conn->cache_af == AF_UNSPEC || af == AF_UNSPEC || | 387 | (conn->cache_af == AF_UNSPEC || af == AF_UNSPEC || | |
384 | conn->cache_af == af)) { | 388 | conn->cache_af == af)) { | |
385 | if (last_conn != NULL) | 389 | if (last_conn != NULL) | |
386 | last_conn->next_cached = conn->next_cached; | 390 | last_conn->next_cached = conn->next_cached; | |
387 | else | 391 | else | |
388 | connection_cache = conn->next_cached; | 392 | connection_cache = conn->next_cached; | |
389 | return conn; | 393 | return conn; | |
390 | } | 394 | } | |
391 | } | 395 | } | |
392 | 396 | |||
393 | return NULL; | 397 | return NULL; | |
394 | } | 398 | } | |
395 | 399 | |||
396 | /* | 400 | /* | |
397 | * Put the connection back into the cache for reuse. | 401 | * Put the connection back into the cache for reuse. | |
398 | * If the connection is freed due to LRU or if the cache | 402 | * If the connection is freed due to LRU or if the cache | |
399 | * is explicitly closed, the given callback is called. | 403 | * is explicitly closed, the given callback is called. | |
400 | */ | 404 | */ | |
401 | void | 405 | void | |
402 | fetch_cache_put(conn_t *conn, int (*closecb)(conn_t *)) | 406 | fetch_cache_put(conn_t *conn, int (*closecb)(conn_t *)) | |
403 | { | 407 | { | |
404 | conn_t *iter, *last; | 408 | conn_t *iter, *last; | |
405 | int global_count, host_count; | 409 | int global_count, host_count; | |
406 | 410 | |||
407 | if (conn->cache_url == NULL || cache_global_limit == 0) { | 411 | if (conn->cache_url == NULL || cache_global_limit == 0) { | |
408 | (*closecb)(conn); | 412 | (*closecb)(conn); | |
409 | return; | 413 | return; | |
410 | } | 414 | } | |
411 | 415 | |||
412 | global_count = host_count = 0; | 416 | global_count = host_count = 0; | |
413 | last = NULL; | 417 | last = NULL; | |
414 | for (iter = connection_cache; iter; | 418 | for (iter = connection_cache; iter; | |
415 | last = iter, iter = iter->next_cached) { | 419 | last = iter, iter = iter->next_cached) { | |
416 | ++global_count; | 420 | ++global_count; | |
417 | if (strcmp(conn->cache_url->host, iter->cache_url->host) == 0) | 421 | if (strcmp(conn->cache_url->host, iter->cache_url->host) == 0) | |
418 | ++host_count; | 422 | ++host_count; | |
419 | if (global_count < cache_global_limit && | 423 | if (global_count < cache_global_limit && | |
420 | host_count < cache_per_host_limit) | 424 | host_count < cache_per_host_limit) | |
421 | continue; | 425 | continue; | |
422 | --global_count; | 426 | --global_count; | |
423 | if (last != NULL) | 427 | if (last != NULL) | |
424 | last->next_cached = iter->next_cached; | 428 | last->next_cached = iter->next_cached; | |
425 | else | 429 | else | |
426 | connection_cache = iter->next_cached; | 430 | connection_cache = iter->next_cached; | |
427 | (*iter->cache_close)(iter); | 431 | (*iter->cache_close)(iter); | |
428 | } | 432 | } | |
429 | 433 | |||
430 | conn->cache_close = closecb; | 434 | conn->cache_close = closecb; | |
431 | conn->next_cached = connection_cache; | 435 | conn->next_cached = connection_cache; | |
432 | connection_cache = conn; | 436 | connection_cache = conn; | |
433 | } | 437 | } | |
434 | 438 | |||
435 | /* | 439 | /* | |
436 | * Enable SSL on a connection. | 440 | * Enable SSL on a connection. | |
437 | */ | 441 | */ | |
438 | int | 442 | int | |
439 | fetch_ssl(conn_t *conn, const struct url *URL, int verbose) | 443 | fetch_ssl(conn_t *conn, const struct url *URL, int verbose) | |
440 | { | 444 | { | |
441 | 445 | |||
442 | #ifdef WITH_SSL | 446 | #ifdef WITH_SSL | |
443 | /* Init the SSL library and context */ | 447 | /* Init the SSL library and context */ | |
444 | if (!SSL_library_init()){ | 448 | if (!SSL_library_init()){ | |
445 | fprintf(stderr, "SSL library init failed\n"); | 449 | fprintf(stderr, "SSL library init failed\n"); | |
446 | return (-1); | 450 | return (-1); | |
447 | } | 451 | } | |
448 | 452 | |||
449 | SSL_load_error_strings(); | 453 | SSL_load_error_strings(); | |
450 | 454 | |||
451 | conn->ssl_meth = SSLv23_client_method(); | 455 | conn->ssl_meth = SSLv23_client_method(); | |
452 | conn->ssl_ctx = SSL_CTX_new(conn->ssl_meth); | 456 | conn->ssl_ctx = SSL_CTX_new(conn->ssl_meth); | |
453 | SSL_CTX_set_mode(conn->ssl_ctx, SSL_MODE_AUTO_RETRY); | 457 | SSL_CTX_set_mode(conn->ssl_ctx, SSL_MODE_AUTO_RETRY); | |
458 | #if defined(__NetBSD__) && __NetBSD_Version__ >= 1000000000 | |||
459 | if (getenv("SSL_NO_VERIFY_PEER") == NULL) { | |||
460 | SSL_CTX_set_default_verify_paths(conn->ssl_ctx); | |||
461 | SSL_CTX_set_verify(conn->ssl_ctx, SSL_VERIFY_PEER, NULL); | |||
462 | } | |||
463 | #endif | |||
454 | 464 | |||
455 | conn->ssl = SSL_new(conn->ssl_ctx); | 465 | conn->ssl = SSL_new(conn->ssl_ctx); | |
456 | if (conn->ssl == NULL){ | 466 | if (conn->ssl == NULL){ | |
457 | fprintf(stderr, "SSL context creation failed\n"); | 467 | fprintf(stderr, "SSL context creation failed\n"); | |
458 | return (-1); | 468 | return (-1); | |
459 | } | 469 | } | |
460 | conn->buf_events = 0; | 470 | conn->buf_events = 0; | |
461 | SSL_set_fd(conn->ssl, conn->sd); | 471 | SSL_set_fd(conn->ssl, conn->sd); | |
462 | #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) | 472 | #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) | |
463 | if (!SSL_set_tlsext_host_name(conn->ssl, (char *)(uintptr_t)URL->host)) { | 473 | if (!SSL_set_tlsext_host_name(conn->ssl, (char *)(uintptr_t)URL->host)) { | |
464 | fprintf(stderr, | 474 | fprintf(stderr, | |
465 | "TLS server name indication extension failed for host %s\n", | 475 | "TLS server name indication extension failed for host %s\n", | |
466 | URL->host); | 476 | URL->host); | |
467 | return (-1); | 477 | return (-1); | |
468 | } | 478 | } | |
469 | #endif | 479 | #endif | |
470 | if (SSL_connect(conn->ssl) == -1){ | 480 | if (SSL_connect(conn->ssl) == -1){ | |
471 | ERR_print_errors_fp(stderr); | 481 | ERR_print_errors_fp(stderr); | |
472 | return (-1); | 482 | return (-1); | |
473 | } | 483 | } | |
474 | 484 | |||
475 | if (verbose) { | 485 | if (verbose) { | |
476 | X509_NAME *name; | 486 | X509_NAME *name; | |
477 | char *str; | 487 | char *str; | |
478 | 488 | |||
479 | fprintf(stderr, "SSL connection established using %s\n", | 489 | fprintf(stderr, "SSL connection established using %s\n", | |
480 | SSL_get_cipher(conn->ssl)); | 490 | SSL_get_cipher(conn->ssl)); | |
481 | conn->ssl_cert = SSL_get_peer_certificate(conn->ssl); | 491 | conn->ssl_cert = SSL_get_peer_certificate(conn->ssl); | |
482 | name = X509_get_subject_name(conn->ssl_cert); | 492 | name = X509_get_subject_name(conn->ssl_cert); | |
483 | str = X509_NAME_oneline(name, 0, 0); | 493 | str = X509_NAME_oneline(name, 0, 0); | |
484 | printf("Certificate subject: %s\n", str); | 494 | printf("Certificate subject: %s\n", str); | |
485 | free(str); | 495 | free(str); | |
486 | name = X509_get_issuer_name(conn->ssl_cert); | 496 | name = X509_get_issuer_name(conn->ssl_cert); | |
487 | str = X509_NAME_oneline(name, 0, 0); | 497 | str = X509_NAME_oneline(name, 0, 0); | |
488 | printf("Certificate issuer: %s\n", str); | 498 | printf("Certificate issuer: %s\n", str); | |
489 | free(str); | 499 | free(str); | |
490 | } | 500 | } | |
491 | 501 | |||
492 | return (0); | 502 | return (0); | |
493 | #else | 503 | #else | |
494 | (void)conn; | 504 | (void)conn; | |
495 | (void)verbose; | 505 | (void)verbose; | |
496 | fprintf(stderr, "SSL support disabled\n"); | 506 | fprintf(stderr, "SSL support disabled\n"); | |
497 | return (-1); | 507 | return (-1); | |
498 | #endif | 508 | #endif | |
499 | } | 509 | } | |
500 | 510 | |||
501 | static int | 511 | static int | |
502 | compute_timeout(const struct timeval *tv) | 512 | compute_timeout(const struct timeval *tv) | |
503 | { | 513 | { | |
504 | struct timeval cur; | 514 | struct timeval cur; | |
505 | int timeout; | 515 | int timeout; | |
506 | 516 | |||
507 | gettimeofday(&cur, NULL); | 517 | gettimeofday(&cur, NULL); | |
508 | timeout = (tv->tv_sec - cur.tv_sec) * 1000 + (tv->tv_usec - cur.tv_usec) / 1000; | 518 | timeout = (tv->tv_sec - cur.tv_sec) * 1000 + (tv->tv_usec - cur.tv_usec) / 1000; | |
509 | return timeout; | 519 | return timeout; | |
510 | } | 520 | } | |
511 | 521 | |||
512 | /* | 522 | /* | |
513 | * Read a character from a connection w/ timeout | 523 | * Read a character from a connection w/ timeout | |
514 | */ | 524 | */ | |
515 | ssize_t | 525 | ssize_t | |
516 | fetch_read(conn_t *conn, char *buf, size_t len) | 526 | fetch_read(conn_t *conn, char *buf, size_t len) | |
517 | { | 527 | { | |
518 | struct timeval timeout_end; | 528 | struct timeval timeout_end; | |
519 | struct pollfd pfd; | 529 | struct pollfd pfd; | |
520 | int timeout_cur; | 530 | int timeout_cur; | |
521 | ssize_t rlen; | 531 | ssize_t rlen; | |
522 | int r; | 532 | int r; | |
523 | 533 | |||
524 | if (len == 0) | 534 | if (len == 0) | |
525 | return 0; | 535 | return 0; | |
526 | 536 | |||
527 | if (conn->next_len != 0) { | 537 | if (conn->next_len != 0) { | |
528 | if (conn->next_len < len) | 538 | if (conn->next_len < len) | |
529 | len = conn->next_len; | 539 | len = conn->next_len; | |
530 | memmove(buf, conn->next_buf, len); | 540 | memmove(buf, conn->next_buf, len); | |
531 | conn->next_len -= len; | 541 | conn->next_len -= len; | |
532 | conn->next_buf += len; | 542 | conn->next_buf += len; | |
533 | return len; | 543 | return len; | |
534 | } | 544 | } | |
535 | 545 | |||
536 | if (fetchTimeout) { | 546 | if (fetchTimeout) { | |
537 | gettimeofday(&timeout_end, NULL); | 547 | gettimeofday(&timeout_end, NULL); | |
538 | timeout_end.tv_sec += fetchTimeout; | 548 | timeout_end.tv_sec += fetchTimeout; | |
539 | } | 549 | } | |
540 | 550 | |||
541 | pfd.fd = conn->sd; | 551 | pfd.fd = conn->sd; | |
542 | for (;;) { | 552 | for (;;) { | |
543 | pfd.events = conn->buf_events; | 553 | pfd.events = conn->buf_events; | |
544 | if (fetchTimeout && pfd.events) { | 554 | if (fetchTimeout && pfd.events) { | |
545 | do { | 555 | do { | |
546 | timeout_cur = compute_timeout(&timeout_end); | 556 | timeout_cur = compute_timeout(&timeout_end); | |
547 | if (timeout_cur < 0) { | 557 | if (timeout_cur < 0) { | |
548 | errno = ETIMEDOUT; | 558 | errno = ETIMEDOUT; | |
549 | fetch_syserr(); | 559 | fetch_syserr(); | |
550 | return (-1); | 560 | return (-1); | |
551 | } | 561 | } | |
552 | errno = 0; | 562 | errno = 0; | |
553 | r = poll(&pfd, 1, timeout_cur); | 563 | r = poll(&pfd, 1, timeout_cur); | |
554 | if (r == -1) { | 564 | if (r == -1) { | |
555 | if (errno == EINTR && fetchRestartCalls) | 565 | if (errno == EINTR && fetchRestartCalls) | |
556 | continue; | 566 | continue; | |
557 | fetch_syserr(); | 567 | fetch_syserr(); | |
558 | return (-1); | 568 | return (-1); | |
559 | } | 569 | } | |
560 | } while (pfd.revents == 0); | 570 | } while (pfd.revents == 0); | |
561 | } | 571 | } | |
562 | #ifdef WITH_SSL | 572 | #ifdef WITH_SSL | |
563 | if (conn->ssl != NULL) { | 573 | if (conn->ssl != NULL) { | |
564 | rlen = SSL_read(conn->ssl, buf, len); | 574 | rlen = SSL_read(conn->ssl, buf, len); | |
565 | if (rlen == -1) { | 575 | if (rlen == -1) { | |
566 | switch (SSL_get_error(conn->ssl, rlen)) { | 576 | switch (SSL_get_error(conn->ssl, rlen)) { | |
567 | case SSL_ERROR_WANT_READ: | 577 | case SSL_ERROR_WANT_READ: | |
568 | conn->buf_events = POLLIN; | 578 | conn->buf_events = POLLIN; | |
569 | break; | 579 | break; | |
570 | case SSL_ERROR_WANT_WRITE: | 580 | case SSL_ERROR_WANT_WRITE: | |
571 | conn->buf_events = POLLOUT; | 581 | conn->buf_events = POLLOUT; | |
572 | break; | 582 | break; | |
573 | default: | 583 | default: | |
574 | errno = EIO; | 584 | errno = EIO; | |
575 | fetch_syserr(); | 585 | fetch_syserr(); | |
576 | return -1; | 586 | return -1; | |
577 | } | 587 | } | |
578 | } else { | 588 | } else { | |
579 | /* Assume buffering on the SSL layer. */ | 589 | /* Assume buffering on the SSL layer. */ | |
580 | conn->buf_events = 0; | 590 | conn->buf_events = 0; | |
581 | } | 591 | } | |
582 | } else | 592 | } else | |
583 | #endif | 593 | #endif | |
584 | rlen = read(conn->sd, buf, len); | 594 | rlen = read(conn->sd, buf, len); | |
585 | if (rlen >= 0) | 595 | if (rlen >= 0) | |
586 | break; | 596 | break; | |
587 | 597 | |||
588 | if (errno != EINTR || !fetchRestartCalls) | 598 | if (errno != EINTR || !fetchRestartCalls) | |
589 | return (-1); | 599 | return (-1); | |
590 | } | 600 | } | |
591 | return (rlen); | 601 | return (rlen); | |
592 | } | 602 | } | |
593 | 603 | |||
594 | 604 | |||
595 | /* | 605 | /* | |
596 | * Read a line of text from a connection w/ timeout | 606 | * Read a line of text from a connection w/ timeout | |
597 | */ | 607 | */ | |
598 | #define MIN_BUF_SIZE 1024 | 608 | #define MIN_BUF_SIZE 1024 | |
599 | 609 | |||
600 | int | 610 | int | |
601 | fetch_getln(conn_t *conn) | 611 | fetch_getln(conn_t *conn) | |
602 | { | 612 | { | |
603 | char *tmp, *next; | 613 | char *tmp, *next; | |
604 | size_t tmpsize; | 614 | size_t tmpsize; | |
605 | ssize_t len; | 615 | ssize_t len; | |
606 | 616 | |||
607 | if (conn->buf == NULL) { | 617 | if (conn->buf == NULL) { | |
608 | if ((conn->buf = malloc(MIN_BUF_SIZE)) == NULL) { | 618 | if ((conn->buf = malloc(MIN_BUF_SIZE)) == NULL) { | |
609 | errno = ENOMEM; | 619 | errno = ENOMEM; | |
610 | return (-1); | 620 | return (-1); | |
611 | } | 621 | } | |
612 | conn->bufsize = MIN_BUF_SIZE; | 622 | conn->bufsize = MIN_BUF_SIZE; | |
613 | } | 623 | } | |
614 | 624 | |||
615 | conn->buflen = 0; | 625 | conn->buflen = 0; | |
616 | next = NULL; | 626 | next = NULL; | |
617 | 627 | |||
618 | do { | 628 | do { | |
619 | /* | 629 | /* | |
620 | * conn->bufsize != conn->buflen at this point, | 630 | * conn->bufsize != conn->buflen at this point, | |
621 | * so the buffer can be NUL-terminated below for | 631 | * so the buffer can be NUL-terminated below for | |
622 | * the case of len == 0. | 632 | * the case of len == 0. | |
623 | */ | 633 | */ | |
624 | len = fetch_read(conn, conn->buf + conn->buflen, | 634 | len = fetch_read(conn, conn->buf + conn->buflen, | |
625 | conn->bufsize - conn->buflen); | 635 | conn->bufsize - conn->buflen); | |
626 | if (len == -1) | 636 | if (len == -1) | |
627 | return (-1); | 637 | return (-1); | |
628 | if (len == 0) | 638 | if (len == 0) | |
629 | break; | 639 | break; | |
630 | next = memchr(conn->buf + conn->buflen, '\n', len); | 640 | next = memchr(conn->buf + conn->buflen, '\n', len); | |
631 | conn->buflen += len; | 641 | conn->buflen += len; | |
632 | if (conn->buflen == conn->bufsize && next == NULL) { | 642 | if (conn->buflen == conn->bufsize && next == NULL) { | |
633 | tmp = conn->buf; | 643 | tmp = conn->buf; | |
634 | tmpsize = conn->bufsize * 2; | 644 | tmpsize = conn->bufsize * 2; | |
635 | if (tmpsize < conn->bufsize) { | 645 | if (tmpsize < conn->bufsize) { | |
636 | errno = ENOMEM; | 646 | errno = ENOMEM; | |
637 | return (-1); | 647 | return (-1); | |
638 | } | 648 | } | |
639 | if ((tmp = realloc(tmp, tmpsize)) == NULL) { | 649 | if ((tmp = realloc(tmp, tmpsize)) == NULL) { | |
640 | errno = ENOMEM; | 650 | errno = ENOMEM; | |
641 | return (-1); | 651 | return (-1); | |
642 | } | 652 | } | |
643 | conn->buf = tmp; | 653 | conn->buf = tmp; | |
644 | conn->bufsize = tmpsize; | 654 | conn->bufsize = tmpsize; | |
645 | } | 655 | } | |
646 | } while (next == NULL); | 656 | } while (next == NULL); | |
647 | 657 | |||
648 | if (next != NULL) { | 658 | if (next != NULL) { | |
649 | *next = '\0'; | 659 | *next = '\0'; | |
650 | conn->next_buf = next + 1; | 660 | conn->next_buf = next + 1; | |
651 | conn->next_len = conn->buflen - (conn->next_buf - conn->buf); | 661 | conn->next_len = conn->buflen - (conn->next_buf - conn->buf); | |
652 | conn->buflen = next - conn->buf; | 662 | conn->buflen = next - conn->buf; | |
653 | } else { | 663 | } else { | |
654 | conn->buf[conn->buflen] = '\0'; | 664 | conn->buf[conn->buflen] = '\0'; | |
655 | conn->next_len = 0; | 665 | conn->next_len = 0; | |
656 | } | 666 | } | |
657 | return (0); | 667 | return (0); | |
658 | } | 668 | } | |
659 | 669 | |||
660 | /* | 670 | /* | |
661 | * Write a vector to a connection w/ timeout | 671 | * Write a vector to a connection w/ timeout | |
662 | * Note: can modify the iovec. | 672 | * Note: can modify the iovec. | |
663 | */ | 673 | */ | |
664 | ssize_t | 674 | ssize_t | |
665 | fetch_write(conn_t *conn, const void *buf, size_t len) | 675 | fetch_write(conn_t *conn, const void *buf, size_t len) | |
666 | { | 676 | { | |
667 | struct timeval now, timeout, waittv; | 677 | struct timeval now, timeout, waittv; | |
668 | fd_set writefds; | 678 | fd_set writefds; | |
669 | ssize_t wlen, total; | 679 | ssize_t wlen, total; | |
670 | int r; | 680 | int r; | |
671 | #ifndef MSG_NOSIGNAL | 681 | #ifndef MSG_NOSIGNAL | |
672 | static int killed_sigpipe; | 682 | static int killed_sigpipe; | |
673 | #endif | 683 | #endif | |
674 | 684 | |||
675 | #ifndef MSG_NOSIGNAL | 685 | #ifndef MSG_NOSIGNAL | |
676 | if (!killed_sigpipe) { | 686 | if (!killed_sigpipe) { | |
677 | signal(SIGPIPE, SIG_IGN); | 687 | signal(SIGPIPE, SIG_IGN); | |
678 | killed_sigpipe = 1; | 688 | killed_sigpipe = 1; | |
679 | } | 689 | } | |
680 | #endif | 690 | #endif | |
681 | 691 | |||
682 | 692 | |||
683 | if (fetchTimeout) { | 693 | if (fetchTimeout) { | |
684 | FD_ZERO(&writefds); | 694 | FD_ZERO(&writefds); | |
685 | gettimeofday(&timeout, NULL); | 695 | gettimeofday(&timeout, NULL); | |
686 | timeout.tv_sec += fetchTimeout; | 696 | timeout.tv_sec += fetchTimeout; | |
687 | } | 697 | } | |
688 | 698 | |||
689 | total = 0; | 699 | total = 0; | |
690 | while (len) { | 700 | while (len) { | |
691 | while (fetchTimeout && !FD_ISSET(conn->sd, &writefds)) { | 701 | while (fetchTimeout && !FD_ISSET(conn->sd, &writefds)) { | |
692 | FD_SET(conn->sd, &writefds); | 702 | FD_SET(conn->sd, &writefds); | |
693 | gettimeofday(&now, NULL); | 703 | gettimeofday(&now, NULL); | |
694 | waittv.tv_sec = timeout.tv_sec - now.tv_sec; | 704 | waittv.tv_sec = timeout.tv_sec - now.tv_sec; | |
695 | waittv.tv_usec = timeout.tv_usec - now.tv_usec; | 705 | waittv.tv_usec = timeout.tv_usec - now.tv_usec; | |
696 | if (waittv.tv_usec < 0) { | 706 | if (waittv.tv_usec < 0) { | |
697 | waittv.tv_usec += 1000000; | 707 | waittv.tv_usec += 1000000; | |
698 | waittv.tv_sec--; | 708 | waittv.tv_sec--; | |
699 | } | 709 | } | |
700 | if (waittv.tv_sec < 0) { | 710 | if (waittv.tv_sec < 0) { | |
701 | errno = ETIMEDOUT; | 711 | errno = ETIMEDOUT; | |
702 | fetch_syserr(); | 712 | fetch_syserr(); | |
703 | return (-1); | 713 | return (-1); | |
704 | } | 714 | } | |
705 | errno = 0; | 715 | errno = 0; | |
706 | r = select(conn->sd + 1, NULL, &writefds, NULL, &waittv); | 716 | r = select(conn->sd + 1, NULL, &writefds, NULL, &waittv); | |
707 | if (r == -1) { | 717 | if (r == -1) { | |
708 | if (errno == EINTR && fetchRestartCalls) | 718 | if (errno == EINTR && fetchRestartCalls) | |
709 | continue; | 719 | continue; | |
710 | return (-1); | 720 | return (-1); | |
711 | } | 721 | } | |
712 | } | 722 | } | |
713 | errno = 0; | 723 | errno = 0; | |
714 | #ifdef WITH_SSL | 724 | #ifdef WITH_SSL | |
715 | if (conn->ssl != NULL) | 725 | if (conn->ssl != NULL) | |
716 | wlen = SSL_write(conn->ssl, buf, len); | 726 | wlen = SSL_write(conn->ssl, buf, len); | |
717 | else | 727 | else | |
718 | #endif | 728 | #endif | |
719 | #ifndef MSG_NOSIGNAL | 729 | #ifndef MSG_NOSIGNAL | |
720 | wlen = send(conn->sd, buf, len, 0); | 730 | wlen = send(conn->sd, buf, len, 0); | |
721 | #else | 731 | #else | |
722 | wlen = send(conn->sd, buf, len, MSG_NOSIGNAL); | 732 | wlen = send(conn->sd, buf, len, MSG_NOSIGNAL); | |
723 | #endif | 733 | #endif | |
724 | if (wlen == 0) { | 734 | if (wlen == 0) { | |
725 | /* we consider a short write a failure */ | 735 | /* we consider a short write a failure */ | |
726 | errno = EPIPE; | 736 | errno = EPIPE; | |
727 | fetch_syserr(); | 737 | fetch_syserr(); | |
728 | return (-1); | 738 | return (-1); | |
729 | } | 739 | } | |
730 | if (wlen < 0) { | 740 | if (wlen < 0) { | |
731 | if (errno == EINTR && fetchRestartCalls) | 741 | if (errno == EINTR && fetchRestartCalls) | |
732 | continue; | 742 | continue; | |
733 | return (-1); | 743 | return (-1); | |
734 | } | 744 | } | |
735 | total += wlen; | 745 | total += wlen; | |
736 | buf = (const char *)buf + wlen; | 746 | buf = (const char *)buf + wlen; | |
737 | len -= wlen; | 747 | len -= wlen; | |
738 | } | 748 | } | |
739 | return (total); | 749 | return (total); | |
740 | } | 750 | } | |
741 | 751 | |||
742 | 752 | |||
743 | /* | 753 | /* | |
744 | * Close connection | 754 | * Close connection | |
745 | */ | 755 | */ | |
746 | int | 756 | int | |
747 | fetch_close(conn_t *conn) | 757 | fetch_close(conn_t *conn) | |
748 | { | 758 | { | |
749 | int ret; | 759 | int ret; | |
750 | 760 | |||
751 | ret = close(conn->sd); | 761 | ret = close(conn->sd); | |
752 | if (conn->cache_url) | 762 | if (conn->cache_url) | |
753 | fetchFreeURL(conn->cache_url); | 763 | fetchFreeURL(conn->cache_url); | |
754 | free(conn->ftp_home); | 764 | free(conn->ftp_home); | |
755 | free(conn->buf); | 765 | free(conn->buf); | |
756 | free(conn); | 766 | free(conn); | |
757 | return (ret); | 767 | return (ret); | |
758 | } | 768 | } | |
759 | 769 | |||
760 | 770 | |||
761 | /*** Directory-related utility functions *************************************/ | 771 | /*** Directory-related utility functions *************************************/ | |
762 | 772 | |||
763 | int | 773 | int | |
764 | fetch_add_entry(struct url_list *ue, struct url *base, const char *name, | 774 | fetch_add_entry(struct url_list *ue, struct url *base, const char *name, | |
765 | int pre_quoted) | 775 | int pre_quoted) | |
766 | { | 776 | { | |
767 | struct url *tmp; | 777 | struct url *tmp; | |
768 | char *tmp_name; | 778 | char *tmp_name; | |
769 | size_t base_doc_len, name_len, i; | 779 | size_t base_doc_len, name_len, i; | |
770 | unsigned char c; | 780 | unsigned char c; | |
771 | 781 | |||
772 | if (strchr(name, '/') != NULL || | 782 | if (strchr(name, '/') != NULL || | |
773 | strcmp(name, "..") == 0 || | 783 | strcmp(name, "..") == 0 || | |
774 | strcmp(name, ".") == 0) | 784 | strcmp(name, ".") == 0) | |
775 | return 0; | 785 | return 0; | |
776 | 786 | |||
777 | if (strcmp(base->doc, "/") == 0) | 787 | if (strcmp(base->doc, "/") == 0) | |
778 | base_doc_len = 0; | 788 | base_doc_len = 0; | |
779 | else | 789 | else | |
780 | base_doc_len = strlen(base->doc); | 790 | base_doc_len = strlen(base->doc); | |
781 | 791 | |||
782 | name_len = 1; | 792 | name_len = 1; | |
783 | for (i = 0; name[i] != '\0'; ++i) { | 793 | for (i = 0; name[i] != '\0'; ++i) { | |
784 | if ((!pre_quoted && name[i] == '%') || | 794 | if ((!pre_quoted && name[i] == '%') || | |
785 | !fetch_urlpath_safe(name[i])) | 795 | !fetch_urlpath_safe(name[i])) | |
786 | name_len += 3; | 796 | name_len += 3; | |
787 | else | 797 | else | |
788 | ++name_len; | 798 | ++name_len; | |
789 | } | 799 | } | |
790 | 800 | |||
791 | tmp_name = malloc( base_doc_len + name_len + 1); | 801 | tmp_name = malloc( base_doc_len + name_len + 1); | |
792 | if (tmp_name == NULL) { | 802 | if (tmp_name == NULL) { | |
793 | errno = ENOMEM; | 803 | errno = ENOMEM; | |
794 | fetch_syserr(); | 804 | fetch_syserr(); | |
795 | return (-1); | 805 | return (-1); | |
796 | } | 806 | } | |
797 | 807 | |||
798 | if (ue->length + 1 >= ue->alloc_size) { | 808 | if (ue->length + 1 >= ue->alloc_size) { | |
799 | tmp = realloc(ue->urls, (ue->alloc_size * 2 + 1) * sizeof(*tmp)); | 809 | tmp = realloc(ue->urls, (ue->alloc_size * 2 + 1) * sizeof(*tmp)); | |
800 | if (tmp == NULL) { | 810 | if (tmp == NULL) { | |
801 | free(tmp_name); | 811 | free(tmp_name); | |
802 | errno = ENOMEM; | 812 | errno = ENOMEM; | |
803 | fetch_syserr(); | 813 | fetch_syserr(); | |
804 | return (-1); | 814 | return (-1); | |
805 | } | 815 | } | |
806 | ue->alloc_size = ue->alloc_size * 2 + 1; | 816 | ue->alloc_size = ue->alloc_size * 2 + 1; | |
807 | ue->urls = tmp; | 817 | ue->urls = tmp; | |
808 | } | 818 | } | |
809 | 819 | |||
810 | tmp = ue->urls + ue->length; | 820 | tmp = ue->urls + ue->length; | |
811 | strcpy(tmp->scheme, base->scheme); | 821 | strcpy(tmp->scheme, base->scheme); | |
812 | strcpy(tmp->user, base->user); | 822 | strcpy(tmp->user, base->user); | |
813 | strcpy(tmp->pwd, base->pwd); | 823 | strcpy(tmp->pwd, base->pwd); | |
814 | strcpy(tmp->host, base->host); | 824 | strcpy(tmp->host, base->host); | |
815 | tmp->port = base->port; | 825 | tmp->port = base->port; | |
816 | tmp->doc = tmp_name; | 826 | tmp->doc = tmp_name; | |
817 | memcpy(tmp->doc, base->doc, base_doc_len); | 827 | memcpy(tmp->doc, base->doc, base_doc_len); | |
818 | tmp->doc[base_doc_len] = '/'; | 828 | tmp->doc[base_doc_len] = '/'; | |
819 | 829 | |||
820 | for (i = base_doc_len + 1; *name != '\0'; ++name) { | 830 | for (i = base_doc_len + 1; *name != '\0'; ++name) { | |
821 | if ((!pre_quoted && *name == '%') || | 831 | if ((!pre_quoted && *name == '%') || | |
822 | !fetch_urlpath_safe(*name)) { | 832 | !fetch_urlpath_safe(*name)) { | |
823 | tmp->doc[i++] = '%'; | 833 | tmp->doc[i++] = '%'; | |
824 | c = (unsigned char)*name / 16; | 834 | c = (unsigned char)*name / 16; | |
825 | if (c < 10) | 835 | if (c < 10) | |
826 | tmp->doc[i++] = '0' + c; | 836 | tmp->doc[i++] = '0' + c; | |
827 | else | 837 | else | |
828 | tmp->doc[i++] = 'a' - 10 + c; | 838 | tmp->doc[i++] = 'a' - 10 + c; | |
829 | c = (unsigned char)*name % 16; | 839 | c = (unsigned char)*name % 16; | |
830 | if (c < 10) | 840 | if (c < 10) | |
831 | tmp->doc[i++] = '0' + c; | 841 | tmp->doc[i++] = '0' + c; | |
832 | else | 842 | else | |
833 | tmp->doc[i++] = 'a' - 10 + c; | 843 | tmp->doc[i++] = 'a' - 10 + c; | |
834 | } else { | 844 | } else { | |
835 | tmp->doc[i++] = *name; | 845 | tmp->doc[i++] = *name; | |
836 | } | 846 | } | |
837 | } | 847 | } | |
838 | tmp->doc[i] = '\0'; | 848 | tmp->doc[i] = '\0'; | |
839 | 849 | |||
840 | tmp->offset = 0; | 850 | tmp->offset = 0; | |
841 | tmp->length = 0; | 851 | tmp->length = 0; | |
842 | tmp->last_modified = -1; | 852 | tmp->last_modified = -1; | |
843 | 853 | |||
844 | ++ue->length; | 854 | ++ue->length; | |
845 | 855 | |||
846 | return (0); | 856 | return (0); | |
847 | } | 857 | } | |
848 | 858 | |||
849 | void | 859 | void | |
850 | fetchInitURLList(struct url_list *ue) | 860 | fetchInitURLList(struct url_list *ue) | |
851 | { | 861 | { | |
852 | ue->length = ue->alloc_size = 0; | 862 | ue->length = ue->alloc_size = 0; | |
853 | ue->urls = NULL; | 863 | ue->urls = NULL; | |
854 | } | 864 | } | |
855 | 865 | |||
856 | int | 866 | int | |
857 | fetchAppendURLList(struct url_list *dst, const struct url_list *src) | 867 | fetchAppendURLList(struct url_list *dst, const struct url_list *src) | |
858 | { | 868 | { | |
859 | size_t i, j, len; | 869 | size_t i, j, len; | |
860 | 870 | |||
861 | len = dst->length + src->length; | 871 | len = dst->length + src->length; | |
862 | if (len > dst->alloc_size) { | 872 | if (len > dst->alloc_size) { | |
863 | struct url *tmp; | 873 | struct url *tmp; | |
864 | 874 | |||
865 | tmp = realloc(dst->urls, len * sizeof(*tmp)); | 875 | tmp = realloc(dst->urls, len * sizeof(*tmp)); | |
866 | if (tmp == NULL) { | 876 | if (tmp == NULL) { | |
867 | errno = ENOMEM; | 877 | errno = ENOMEM; | |
868 | fetch_syserr(); | 878 | fetch_syserr(); | |
869 | return (-1); | 879 | return (-1); | |
870 | } | 880 | } | |
871 | dst->alloc_size = len; | 881 | dst->alloc_size = len; | |
872 | dst->urls = tmp; | 882 | dst->urls = tmp; | |
873 | } | 883 | } | |
874 | 884 | |||
875 | for (i = 0, j = dst->length; i < src->length; ++i, ++j) { | 885 | for (i = 0, j = dst->length; i < src->length; ++i, ++j) { | |
876 | dst->urls[j] = src->urls[i]; | 886 | dst->urls[j] = src->urls[i]; | |
877 | dst->urls[j].doc = strdup(src->urls[i].doc); | 887 | dst->urls[j].doc = strdup(src->urls[i].doc); | |
878 | if (dst->urls[j].doc == NULL) { | 888 | if (dst->urls[j].doc == NULL) { | |
879 | while (i-- > 0) | 889 | while (i-- > 0) | |
880 | free(dst->urls[j].doc); | 890 | free(dst->urls[j].doc); | |
881 | fetch_syserr(); | 891 | fetch_syserr(); | |
882 | return -1; | 892 | return -1; | |
883 | } | 893 | } | |
884 | } | 894 | } | |
885 | dst->length = len; | 895 | dst->length = len; | |
886 | 896 | |||
887 | return 0; | 897 | return 0; | |
888 | } | 898 | } | |
889 | 899 | |||
890 | void | 900 | void | |
891 | fetchFreeURLList(struct url_list *ue) | 901 | fetchFreeURLList(struct url_list *ue) | |
892 | { | 902 | { | |
893 | size_t i; | 903 | size_t i; | |
894 | 904 | |||
895 | for (i = 0; i < ue->length; ++i) | 905 | for (i = 0; i < ue->length; ++i) | |
896 | free(ue->urls[i].doc); | 906 | free(ue->urls[i].doc); | |
897 | free(ue->urls); | 907 | free(ue->urls); | |
898 | ue->length = ue->alloc_size = 0; | 908 | ue->length = ue->alloc_size = 0; | |
899 | } | 909 | } | |
900 | 910 | |||
901 | 911 | |||
902 | /*** Authentication-related utility functions ********************************/ | 912 | /*** Authentication-related utility functions ********************************/ | |
903 | 913 | |||
904 | static const char * | 914 | static const char * | |
905 | fetch_read_word(FILE *f) | 915 | fetch_read_word(FILE *f) | |
906 | { | 916 | { | |
907 | static char word[1024]; | 917 | static char word[1024]; | |
908 | 918 | |||
909 | if (fscanf(f, " %1023s ", word) != 1) | 919 | if (fscanf(f, " %1023s ", word) != 1) | |
910 | return (NULL); | 920 | return (NULL); | |
911 | return (word); | 921 | return (word); | |
912 | } | 922 | } | |
913 | 923 | |||
914 | /* | 924 | /* | |
915 | * Get authentication data for a URL from .netrc | 925 | * Get authentication data for a URL from .netrc | |
916 | */ | 926 | */ | |
917 | int | 927 | int | |
918 | fetch_netrc_auth(struct url *url) | 928 | fetch_netrc_auth(struct url *url) | |
919 | { | 929 | { | |
920 | char fn[PATH_MAX]; | 930 | char fn[PATH_MAX]; | |
921 | const char *word; | 931 | const char *word; | |
922 | char *p; | 932 | char *p; | |
923 | FILE *f; | 933 | FILE *f; | |
924 | 934 | |||
925 | if ((p = getenv("NETRC")) != NULL) { | 935 | if ((p = getenv("NETRC")) != NULL) { | |
926 | if (snprintf(fn, sizeof(fn), "%s", p) >= (int)sizeof(fn)) { | 936 | if (snprintf(fn, sizeof(fn), "%s", p) >= (int)sizeof(fn)) { | |
927 | fetch_info("$NETRC specifies a file name " | 937 | fetch_info("$NETRC specifies a file name " | |
928 | "longer than PATH_MAX"); | 938 | "longer than PATH_MAX"); | |
929 | return (-1); | 939 | return (-1); | |
930 | } | 940 | } | |
931 | } else { | 941 | } else { | |
932 | if ((p = getenv("HOME")) != NULL) { | 942 | if ((p = getenv("HOME")) != NULL) { | |
933 | struct passwd *pwd; | 943 | struct passwd *pwd; | |
934 | 944 | |||
935 | if ((pwd = getpwuid(getuid())) == NULL || | 945 | if ((pwd = getpwuid(getuid())) == NULL || | |
936 | (p = pwd->pw_dir) == NULL) | 946 | (p = pwd->pw_dir) == NULL) | |
937 | return (-1); | 947 | return (-1); | |
938 | } | 948 | } | |
939 | if (snprintf(fn, sizeof(fn), "%s/.netrc", p) >= (int)sizeof(fn)) | 949 | if (snprintf(fn, sizeof(fn), "%s/.netrc", p) >= (int)sizeof(fn)) | |
940 | return (-1); | 950 | return (-1); | |
941 | } | 951 | } | |
942 | 952 | |||
943 | if ((f = fopen(fn, "r")) == NULL) | 953 | if ((f = fopen(fn, "r")) == NULL) | |
944 | return (-1); | 954 | return (-1); | |
945 | while ((word = fetch_read_word(f)) != NULL) { | 955 | while ((word = fetch_read_word(f)) != NULL) { | |
946 | if (strcmp(word, "default") == 0) | 956 | if (strcmp(word, "default") == 0) | |
947 | break; | 957 | break; | |
948 | if (strcmp(word, "machine") == 0 && | 958 | if (strcmp(word, "machine") == 0 && | |
949 | (word = fetch_read_word(f)) != NULL && | 959 | (word = fetch_read_word(f)) != NULL && | |
950 | strcasecmp(word, url->host) == 0) { | 960 | strcasecmp(word, url->host) == 0) { | |
951 | break; | 961 | break; | |
952 | } | 962 | } | |
953 | } | 963 | } | |
954 | if (word == NULL) | 964 | if (word == NULL) | |
955 | goto ferr; | 965 | goto ferr; | |
956 | while ((word = fetch_read_word(f)) != NULL) { | 966 | while ((word = fetch_read_word(f)) != NULL) { | |
957 | if (strcmp(word, "login") == 0) { | 967 | if (strcmp(word, "login") == 0) { | |
958 | if ((word = fetch_read_word(f)) == NULL) | 968 | if ((word = fetch_read_word(f)) == NULL) | |
959 | goto ferr; | 969 | goto ferr; | |
960 | if (snprintf(url->user, sizeof(url->user), | 970 | if (snprintf(url->user, sizeof(url->user), | |
961 | "%s", word) > (int)sizeof(url->user)) { | 971 | "%s", word) > (int)sizeof(url->user)) { | |
962 | fetch_info("login name in .netrc is too long"); | 972 | fetch_info("login name in .netrc is too long"); | |
963 | url->user[0] = '\0'; | 973 | url->user[0] = '\0'; | |
964 | } | 974 | } | |
965 | } else if (strcmp(word, "password") == 0) { | 975 | } else if (strcmp(word, "password") == 0) { | |
966 | if ((word = fetch_read_word(f)) == NULL) | 976 | if ((word = fetch_read_word(f)) == NULL) | |
967 | goto ferr; | 977 | goto ferr; | |
968 | if (snprintf(url->pwd, sizeof(url->pwd), | 978 | if (snprintf(url->pwd, sizeof(url->pwd), | |
969 | "%s", word) > (int)sizeof(url->pwd)) { | 979 | "%s", word) > (int)sizeof(url->pwd)) { | |
970 | fetch_info("password in .netrc is too long"); | 980 | fetch_info("password in .netrc is too long"); | |
971 | url->pwd[0] = '\0'; | 981 | url->pwd[0] = '\0'; | |
972 | } | 982 | } | |
973 | } else if (strcmp(word, "account") == 0) { | 983 | } else if (strcmp(word, "account") == 0) { | |
974 | if ((word = fetch_read_word(f)) == NULL) | 984 | if ((word = fetch_read_word(f)) == NULL) | |
975 | goto ferr; | 985 | goto ferr; | |
976 | /* XXX not supported! */ | 986 | /* XXX not supported! */ | |
977 | } else { | 987 | } else { | |
978 | break; | 988 | break; | |
979 | } | 989 | } | |
980 | } | 990 | } | |
981 | fclose(f); | 991 | fclose(f); | |
982 | return (0); | 992 | return (0); | |
983 | ferr: | 993 | ferr: | |
984 | fclose(f); | 994 | fclose(f); | |
985 | return (-1); | 995 | return (-1); | |
986 | } | 996 | } | |
987 | 997 | |||
988 | /* | 998 | /* | |
989 | * The no_proxy environment variable specifies a set of domains for | 999 | * The no_proxy environment variable specifies a set of domains for | |
990 | * which the proxy should not be consulted; the contents is a comma-, | 1000 | * which the proxy should not be consulted; the contents is a comma-, | |
991 | * or space-separated list of domain names. A single asterisk will | 1001 | * or space-separated list of domain names. A single asterisk will | |
992 | * override all proxy variables and no transactions will be proxied | 1002 | * override all proxy variables and no transactions will be proxied | |
993 | * (for compatability with lynx and curl, see the discussion at | 1003 | * (for compatability with lynx and curl, see the discussion at | |
994 | * <http://curl.haxx.se/mail/archive_pre_oct_99/0009.html>). | 1004 | * <http://curl.haxx.se/mail/archive_pre_oct_99/0009.html>). | |
995 | */ | 1005 | */ | |
996 | int | 1006 | int | |
997 | fetch_no_proxy_match(const char *host) | 1007 | fetch_no_proxy_match(const char *host) | |
998 | { | 1008 | { | |
999 | const char *no_proxy, *p, *q; | 1009 | const char *no_proxy, *p, *q; | |
1000 | size_t h_len, d_len; | 1010 | size_t h_len, d_len; | |
1001 | 1011 | |||
1002 | if ((no_proxy = getenv("NO_PROXY")) == NULL && | 1012 | if ((no_proxy = getenv("NO_PROXY")) == NULL && | |
1003 | (no_proxy = getenv("no_proxy")) == NULL) | 1013 | (no_proxy = getenv("no_proxy")) == NULL) | |
1004 | return (0); | 1014 | return (0); | |
1005 | 1015 | |||
1006 | /* asterisk matches any hostname */ | 1016 | /* asterisk matches any hostname */ | |
1007 | if (strcmp(no_proxy, "*") == 0) | 1017 | if (strcmp(no_proxy, "*") == 0) | |
1008 | return (1); | 1018 | return (1); | |
1009 | 1019 | |||
1010 | h_len = strlen(host); | 1020 | h_len = strlen(host); | |
1011 | p = no_proxy; | 1021 | p = no_proxy; | |
1012 | do { | 1022 | do { | |
1013 | /* position p at the beginning of a domain suffix */ | 1023 | /* position p at the beginning of a domain suffix */ | |
1014 | while (*p == ',' || isspace((unsigned char)*p)) | 1024 | while (*p == ',' || isspace((unsigned char)*p)) | |
1015 | p++; | 1025 | p++; | |
1016 | 1026 | |||
1017 | /* position q at the first separator character */ | 1027 | /* position q at the first separator character */ | |
1018 | for (q = p; *q; ++q) | 1028 | for (q = p; *q; ++q) | |
1019 | if (*q == ',' || isspace((unsigned char)*q)) | 1029 | if (*q == ',' || isspace((unsigned char)*q)) | |
1020 | break; | 1030 | break; | |
1021 | 1031 | |||
1022 | d_len = q - p; | 1032 | d_len = q - p; | |
1023 | if (d_len > 0 && h_len > d_len && | 1033 | if (d_len > 0 && h_len > d_len && | |
1024 | strncasecmp(host + h_len - d_len, | 1034 | strncasecmp(host + h_len - d_len, | |
1025 | p, d_len) == 0) { | 1035 | p, d_len) == 0) { | |
1026 | /* domain name matches */ | 1036 | /* domain name matches */ | |
1027 | return (1); | 1037 | return (1); | |
1028 | } | 1038 | } | |
1029 | 1039 | |||
1030 | p = q + 1; | 1040 | p = q + 1; | |
1031 | } while (*q); | 1041 | } while (*q); | |
1032 | 1042 | |||
1033 | return (0); | 1043 | return (0); | |
1034 | } | 1044 | } | |
1035 | 1045 | |||
1036 | struct fetchIO { | 1046 | struct fetchIO { | |
1037 | void *io_cookie; | 1047 | void *io_cookie; | |
1038 | ssize_t (*io_read)(void *, void *, size_t); | 1048 | ssize_t (*io_read)(void *, void *, size_t); | |
1039 | ssize_t (*io_write)(void *, const void *, size_t); | 1049 | ssize_t (*io_write)(void *, const void *, size_t); | |
1040 | void (*io_close)(void *); | 1050 | void (*io_close)(void *); | |
1041 | }; | 1051 | }; | |
1042 | 1052 | |||
1043 | void | 1053 | void | |
1044 | fetchIO_close(fetchIO *f) | 1054 | fetchIO_close(fetchIO *f) | |
1045 | { | 1055 | { | |
1046 | if (f->io_close != NULL) | 1056 | if (f->io_close != NULL) | |
1047 | (*f->io_close)(f->io_cookie); | 1057 | (*f->io_close)(f->io_cookie); | |
1048 | 1058 | |||
1049 | free(f); | 1059 | free(f); | |
1050 | } | 1060 | } | |
1051 | 1061 | |||
1052 | fetchIO * | 1062 | fetchIO * | |
1053 | fetchIO_unopen(void *io_cookie, ssize_t (*io_read)(void *, void *, size_t), | 1063 | fetchIO_unopen(void *io_cookie, ssize_t (*io_read)(void *, void *, size_t), | |
1054 | ssize_t (*io_write)(void *, const void *, size_t), | 1064 | ssize_t (*io_write)(void *, const void *, size_t), | |
1055 | void (*io_close)(void *)) | 1065 | void (*io_close)(void *)) | |
1056 | { | 1066 | { | |
1057 | fetchIO *f; | 1067 | fetchIO *f; | |
1058 | 1068 | |||
1059 | f = malloc(sizeof(*f)); | 1069 | f = malloc(sizeof(*f)); | |
1060 | if (f == NULL) | 1070 | if (f == NULL) | |
1061 | return f; | 1071 | return f; | |
1062 | 1072 | |||
1063 | f->io_cookie = io_cookie; | 1073 | f->io_cookie = io_cookie; | |
1064 | f->io_read = io_read; | 1074 | f->io_read = io_read; | |
1065 | f->io_write = io_write; | 1075 | f->io_write = io_write; | |
1066 | f->io_close = io_close; | 1076 | f->io_close = io_close; | |
1067 | 1077 | |||
1068 | return f; | 1078 | return f; | |
1069 | } | 1079 | } | |
1070 | 1080 | |||
1071 | ssize_t | 1081 | ssize_t | |
1072 | fetchIO_read(fetchIO *f, void *buf, size_t len) | 1082 | fetchIO_read(fetchIO *f, void *buf, size_t len) | |
1073 | { | 1083 | { | |
1074 | if (f->io_read == NULL) | 1084 | if (f->io_read == NULL) | |
1075 | return EBADF; | 1085 | return EBADF; | |
1076 | return (*f->io_read)(f->io_cookie, buf, len); | 1086 | return (*f->io_read)(f->io_cookie, buf, len); | |
1077 | } | 1087 | } | |
1078 | 1088 | |||
1079 | ssize_t | 1089 | ssize_t | |
1080 | fetchIO_write(fetchIO *f, const void *buf, size_t len) | 1090 | fetchIO_write(fetchIO *f, const void *buf, size_t len) | |
1081 | { | 1091 | { | |
1082 | if (f->io_read == NULL) | 1092 | if (f->io_read == NULL) | |
1083 | return EBADF; | 1093 | return EBADF; | |
1084 | return (*f->io_write)(f->io_cookie, buf, len); | 1094 | return (*f->io_write)(f->io_cookie, buf, len); | |
1085 | } | 1095 | } |
@@ -1,781 +1,785 @@ | @@ -1,781 +1,785 @@ | |||
1 | .\"- | 1 | .\"- | |
2 | .\" Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav | 2 | .\" Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav | |
3 | .\" Copyright (c) 2010 Joerg Sonnenberger <joerg@NetBSD.org> | 3 | .\" Copyright (c) 2010 Joerg Sonnenberger <joerg@NetBSD.org> | |
4 | .\" All rights reserved. | 4 | .\" All rights reserved. | |
5 | .\" | 5 | .\" | |
6 | .\" Redistribution and use in source and binary forms, with or without | 6 | .\" Redistribution and use in source and binary forms, with or without | |
7 | .\" modification, are permitted provided that the following conditions | 7 | .\" modification, are permitted provided that the following conditions | |
8 | .\" are met: | 8 | .\" are met: | |
9 | .\" 1. Redistributions of source code must retain the above copyright | 9 | .\" 1. Redistributions of source code must retain the above copyright | |
10 | .\" notice, this list of conditions and the following disclaimer. | 10 | .\" notice, this list of conditions and the following disclaimer. | |
11 | .\" 2. Redistributions in binary form must reproduce the above copyright | 11 | .\" 2. Redistributions in binary form must reproduce the above copyright | |
12 | .\" notice, this list of conditions and the following disclaimer in the | 12 | .\" notice, this list of conditions and the following disclaimer in the | |
13 | .\" documentation and/or other materials provided with the distribution. | 13 | .\" documentation and/or other materials provided with the distribution. | |
14 | .\" | 14 | .\" | |
15 | .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | 15 | .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
16 | .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 16 | .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
17 | .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 17 | .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
18 | .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | 18 | .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
19 | .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 19 | .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
20 | .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 20 | .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
21 | .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 21 | .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
22 | .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 22 | .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
23 | .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 23 | .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
24 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 24 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
25 | .\" SUCH DAMAGE. | 25 | .\" SUCH DAMAGE. | |
26 | .\" | 26 | .\" | |
27 | .\" $FreeBSD: fetch.3,v 1.64 2007/12/18 11:03:26 des Exp $ | 27 | .\" $FreeBSD: fetch.3,v 1.64 2007/12/18 11:03:26 des Exp $ | |
28 | .\" $NetBSD: fetch.3,v 1.17 2016/05/31 18:02:36 abhinav Exp $ | 28 | .\" $NetBSD: fetch.3,v 1.17.62.1 2024/01/13 12:49:09 bsiegert Exp $ | |
29 | .\" | 29 | .\" | |
30 | .Dd January 22, 2010 | 30 | .Dd December 22, 2023 | |
31 | .Dt FETCH 3 | 31 | .Dt FETCH 3 | |
32 | .Os | 32 | .Os | |
33 | .Sh NAME | 33 | .Sh NAME | |
34 | .Nm fetchMakeURL , | 34 | .Nm fetchMakeURL , | |
35 | .Nm fetchParseURL , | 35 | .Nm fetchParseURL , | |
36 | .Nm fetchCopyURL , | 36 | .Nm fetchCopyURL , | |
37 | .Nm fetchFreeURL , | 37 | .Nm fetchFreeURL , | |
38 | .Nm fetchXGetURL , | 38 | .Nm fetchXGetURL , | |
39 | .Nm fetchGetURL , | 39 | .Nm fetchGetURL , | |
40 | .Nm fetchPutURL , | 40 | .Nm fetchPutURL , | |
41 | .Nm fetchStatURL , | 41 | .Nm fetchStatURL , | |
42 | .Nm fetchListURL , | 42 | .Nm fetchListURL , | |
43 | .Nm fetchXGet , | 43 | .Nm fetchXGet , | |
44 | .Nm fetchGet , | 44 | .Nm fetchGet , | |
45 | .Nm fetchPut , | 45 | .Nm fetchPut , | |
46 | .Nm fetchStat , | 46 | .Nm fetchStat , | |
47 | .Nm fetchList , | 47 | .Nm fetchList , | |
48 | .Nm fetchXGetFile , | 48 | .Nm fetchXGetFile , | |
49 | .Nm fetchGetFile , | 49 | .Nm fetchGetFile , | |
50 | .Nm fetchPutFile , | 50 | .Nm fetchPutFile , | |
51 | .Nm fetchStatFile , | 51 | .Nm fetchStatFile , | |
52 | .Nm fetchListFile , | 52 | .Nm fetchListFile , | |
53 | .Nm fetchXGetHTTP , | 53 | .Nm fetchXGetHTTP , | |
54 | .Nm fetchGetHTTP , | 54 | .Nm fetchGetHTTP , | |
55 | .Nm fetchPutHTTP , | 55 | .Nm fetchPutHTTP , | |
56 | .Nm fetchStatHTTP , | 56 | .Nm fetchStatHTTP , | |
57 | .Nm fetchListHTTP , | 57 | .Nm fetchListHTTP , | |
58 | .Nm fetchXGetFTP , | 58 | .Nm fetchXGetFTP , | |
59 | .Nm fetchGetFTP , | 59 | .Nm fetchGetFTP , | |
60 | .Nm fetchPutFTP , | 60 | .Nm fetchPutFTP , | |
61 | .Nm fetchStatFTP , | 61 | .Nm fetchStatFTP , | |
62 | .Nm fetchListFTP | 62 | .Nm fetchListFTP | |
63 | .Nm fetchInitURLList , | 63 | .Nm fetchInitURLList , | |
64 | .Nm fetchFreeURLList , | 64 | .Nm fetchFreeURLList , | |
65 | .Nm fetchUnquotePath , | 65 | .Nm fetchUnquotePath , | |
66 | .Nm fetchUnquoteFilename , | 66 | .Nm fetchUnquoteFilename , | |
67 | .Nm fetchStringifyURL , | 67 | .Nm fetchStringifyURL , | |
68 | .Nm fetchConnectionCacheInit , | 68 | .Nm fetchConnectionCacheInit , | |
69 | .Nm fetchConnectionCacheClose , | 69 | .Nm fetchConnectionCacheClose , | |
70 | .Nm fetch | 70 | .Nm fetch | |
71 | .Nd file transfer functions | 71 | .Nd file transfer functions | |
72 | .Sh LIBRARY | 72 | .Sh LIBRARY | |
73 | .Lb libfetch | 73 | .Lb libfetch | |
74 | .Sh SYNOPSIS | 74 | .Sh SYNOPSIS | |
75 | .In stdio.h | 75 | .In stdio.h | |
76 | .In fetch.h | 76 | .In fetch.h | |
77 | .Ft struct url * | 77 | .Ft struct url * | |
78 | .Fn fetchMakeURL "const char *scheme" "const char *host" "int port" "const char *doc" "const char *user" "const char *pwd" | 78 | .Fn fetchMakeURL "const char *scheme" "const char *host" "int port" "const char *doc" "const char *user" "const char *pwd" | |
79 | .Ft struct url * | 79 | .Ft struct url * | |
80 | .Fn fetchParseURL "const char *URL" | 80 | .Fn fetchParseURL "const char *URL" | |
81 | .Ft struct url * | 81 | .Ft struct url * | |
82 | .Fn fetchCopyURL "const struct url *u" | 82 | .Fn fetchCopyURL "const struct url *u" | |
83 | .Ft void | 83 | .Ft void | |
84 | .Fn fetchFreeURL "struct url *u" | 84 | .Fn fetchFreeURL "struct url *u" | |
85 | .Ft fetchIO * | 85 | .Ft fetchIO * | |
86 | .Fn fetchXGetURL "const char *URL" "struct url_stat *us" "const char *flags" | 86 | .Fn fetchXGetURL "const char *URL" "struct url_stat *us" "const char *flags" | |
87 | .Ft fetchIO * | 87 | .Ft fetchIO * | |
88 | .Fn fetchGetURL "const char *URL" "const char *flags" | 88 | .Fn fetchGetURL "const char *URL" "const char *flags" | |
89 | .Ft fetchIO * | 89 | .Ft fetchIO * | |
90 | .Fn fetchPutURL "const char *URL" "const char *flags" | 90 | .Fn fetchPutURL "const char *URL" "const char *flags" | |
91 | .Ft int | 91 | .Ft int | |
92 | .Fn fetchStatURL "const char *URL" "struct url_stat *us" "const char *flags" | 92 | .Fn fetchStatURL "const char *URL" "struct url_stat *us" "const char *flags" | |
93 | .Ft int | 93 | .Ft int | |
94 | .Fn fetchListURL "struct url_list *list" "const char *URL" "const char *pattern" "const char *flags" | 94 | .Fn fetchListURL "struct url_list *list" "const char *URL" "const char *pattern" "const char *flags" | |
95 | .Ft fetchIO * | 95 | .Ft fetchIO * | |
96 | .Fn fetchXGet "struct url *u" "struct url_stat *us" "const char *flags" | 96 | .Fn fetchXGet "struct url *u" "struct url_stat *us" "const char *flags" | |
97 | .Ft fetchIO * | 97 | .Ft fetchIO * | |
98 | .Fn fetchGet "struct url *u" "const char *flags" | 98 | .Fn fetchGet "struct url *u" "const char *flags" | |
99 | .Ft fetchIO * | 99 | .Ft fetchIO * | |
100 | .Fn fetchPut "struct url *u" "const char *flags" | 100 | .Fn fetchPut "struct url *u" "const char *flags" | |
101 | .Ft int | 101 | .Ft int | |
102 | .Fn fetchStat "struct url *u" "struct url_stat *us" "const char *flags" | 102 | .Fn fetchStat "struct url *u" "struct url_stat *us" "const char *flags" | |
103 | .Ft int | 103 | .Ft int | |
104 | .Fn fetchList "struct url_list *list" "struct url *u" "const char *pattern" "const char *flags" | 104 | .Fn fetchList "struct url_list *list" "struct url *u" "const char *pattern" "const char *flags" | |
105 | .Ft fetchIO * | 105 | .Ft fetchIO * | |
106 | .Fn fetchXGetFile "struct url *u" "struct url_stat *us" "const char *flags" | 106 | .Fn fetchXGetFile "struct url *u" "struct url_stat *us" "const char *flags" | |
107 | .Ft fetchIO * | 107 | .Ft fetchIO * | |
108 | .Fn fetchGetFile "struct url *u" "const char *flags" | 108 | .Fn fetchGetFile "struct url *u" "const char *flags" | |
109 | .Ft fetchIO * | 109 | .Ft fetchIO * | |
110 | .Fn fetchPutFile "struct url *u" "const char *flags" | 110 | .Fn fetchPutFile "struct url *u" "const char *flags" | |
111 | .Ft int | 111 | .Ft int | |
112 | .Fn fetchStatFile "struct url *u" "struct url_stat *us" "const char *flags" | 112 | .Fn fetchStatFile "struct url *u" "struct url_stat *us" "const char *flags" | |
113 | .Ft int | 113 | .Ft int | |
114 | .Fn fetchListFile "struct url_list *list" "struct url *u" "const char *pattern" "const char *flags" | 114 | .Fn fetchListFile "struct url_list *list" "struct url *u" "const char *pattern" "const char *flags" | |
115 | .Ft fetchIO * | 115 | .Ft fetchIO * | |
116 | .Fn fetchXGetHTTP "struct url *u" "struct url_stat *us" "const char *flags" | 116 | .Fn fetchXGetHTTP "struct url *u" "struct url_stat *us" "const char *flags" | |
117 | .Ft fetchIO * | 117 | .Ft fetchIO * | |
118 | .Fn fetchGetHTTP "struct url *u" "const char *flags" | 118 | .Fn fetchGetHTTP "struct url *u" "const char *flags" | |
119 | .Ft fetchIO * | 119 | .Ft fetchIO * | |
120 | .Fn fetchPutHTTP "struct url *u" "const char *flags" | 120 | .Fn fetchPutHTTP "struct url *u" "const char *flags" | |
121 | .Ft int | 121 | .Ft int | |
122 | .Fn fetchStatHTTP "struct url *u" "struct url_stat *us" "const char *flags" | 122 | .Fn fetchStatHTTP "struct url *u" "struct url_stat *us" "const char *flags" | |
123 | .Ft int | 123 | .Ft int | |
124 | .Fn fetchListHTTP "struct url_list *list" "struct url *u" "const char *pattern" "const char *flags" | 124 | .Fn fetchListHTTP "struct url_list *list" "struct url *u" "const char *pattern" "const char *flags" | |
125 | .Ft fetchIO * | 125 | .Ft fetchIO * | |
126 | .Fn fetchXGetFTP "struct url *u" "struct url_stat *us" "const char *flags" | 126 | .Fn fetchXGetFTP "struct url *u" "struct url_stat *us" "const char *flags" | |
127 | .Ft fetchIO * | 127 | .Ft fetchIO * | |
128 | .Fn fetchGetFTP "struct url *u" "const char *flags" | 128 | .Fn fetchGetFTP "struct url *u" "const char *flags" | |
129 | .Ft fetchIO * | 129 | .Ft fetchIO * | |
130 | .Fn fetchPutFTP "struct url *u" "const char *flags" | 130 | .Fn fetchPutFTP "struct url *u" "const char *flags" | |
131 | .Ft int | 131 | .Ft int | |
132 | .Fn fetchStatFTP "struct url *u" "struct url_stat *us" "const char *flags" | 132 | .Fn fetchStatFTP "struct url *u" "struct url_stat *us" "const char *flags" | |
133 | .Ft int | 133 | .Ft int | |
134 | .Fn fetchListFTP "struct url_list *list" "struct url *u" "const char *pattern" "const char *flags" | 134 | .Fn fetchListFTP "struct url_list *list" "struct url *u" "const char *pattern" "const char *flags" | |
135 | .Ft void | 135 | .Ft void | |
136 | .Fn fetchInitURLList "struct url_list *ul" | 136 | .Fn fetchInitURLList "struct url_list *ul" | |
137 | .Ft int | 137 | .Ft int | |
138 | .Fn fetchAppendURLList "struct url_list *dst" "const struct url_list *src" | 138 | .Fn fetchAppendURLList "struct url_list *dst" "const struct url_list *src" | |
139 | .Ft void | 139 | .Ft void | |
140 | .Fn fetchFreeURLList "struct url_list *ul" | 140 | .Fn fetchFreeURLList "struct url_list *ul" | |
141 | .Ft char * | 141 | .Ft char * | |
142 | .Fn fetchUnquotePath "struct url *u" | 142 | .Fn fetchUnquotePath "struct url *u" | |
143 | .Ft char * | 143 | .Ft char * | |
144 | .Fn fetchUnquoteFilename "struct url *u" | 144 | .Fn fetchUnquoteFilename "struct url *u" | |
145 | .Ft char * | 145 | .Ft char * | |
146 | .Fn fetchStringifyURL "const struct url *u" | 146 | .Fn fetchStringifyURL "const struct url *u" | |
147 | .Ft void | 147 | .Ft void | |
148 | .Fn fetchConnectionCacheInit "int global" "int per_host" | 148 | .Fn fetchConnectionCacheInit "int global" "int per_host" | |
149 | .Ft void | 149 | .Ft void | |
150 | .Fn fetchConnectionCacheClose "void" | 150 | .Fn fetchConnectionCacheClose "void" | |
151 | .Sh DESCRIPTION | 151 | .Sh DESCRIPTION | |
152 | These functions implement a high-level library for retrieving and | 152 | These functions implement a high-level library for retrieving and | |
153 | uploading files using Uniform Resource Locators (URLs). | 153 | uploading files using Uniform Resource Locators (URLs). | |
154 | .Pp | 154 | .Pp | |
155 | .Fn fetchParseURL | 155 | .Fn fetchParseURL | |
156 | takes a URL in the form of a null-terminated string and splits it into | 156 | takes a URL in the form of a null-terminated string and splits it into | |
157 | its components function according to the Common Internet Scheme Syntax | 157 | its components function according to the Common Internet Scheme Syntax | |
158 | detailed in RFC 1738. | 158 | detailed in RFC 1738. | |
159 | A regular expression which produces this syntax is: | 159 | A regular expression which produces this syntax is: | |
160 | .Bd -literal -offset indent | 160 | .Bd -literal -offset indent | |
161 | \*[Lt]scheme\*[Gt]:(//(\*[Lt]user\*[Gt](:\*[Lt]pwd\*[Gt])?@)?\*[Lt]host\*[Gt](:\*[Lt]port\*[Gt])?)?/(\*[Lt]doc\*[Gt])? | 161 | \*[Lt]scheme\*[Gt]:(//(\*[Lt]user\*[Gt](:\*[Lt]pwd\*[Gt])?@)?\*[Lt]host\*[Gt](:\*[Lt]port\*[Gt])?)?/(\*[Lt]doc\*[Gt])? | |
162 | .Ed | 162 | .Ed | |
163 | .Pp | 163 | .Pp | |
164 | If the URL does not seem to begin with a scheme name, it is assumed to be a local path. | 164 | If the URL does not seem to begin with a scheme name, it is assumed to be a local path. | |
165 | Only absolute path names are accepted. | 165 | Only absolute path names are accepted. | |
166 | .Pp | 166 | .Pp | |
167 | Note that some components of the URL are not necessarily relevant to | 167 | Note that some components of the URL are not necessarily relevant to | |
168 | all URL schemes. | 168 | all URL schemes. | |
169 | For instance, the file scheme only needs the | 169 | For instance, the file scheme only needs the | |
170 | .Aq scheme | 170 | .Aq scheme | |
171 | and | 171 | and | |
172 | .Aq doc | 172 | .Aq doc | |
173 | components. | 173 | components. | |
174 | .Fn fetchParseURL | 174 | .Fn fetchParseURL | |
175 | quotes any unsafe character in the URL automatically. | 175 | quotes any unsafe character in the URL automatically. | |
176 | This is not done by | 176 | This is not done by | |
177 | .Fn fetchMakeURL . | 177 | .Fn fetchMakeURL . | |
178 | .Fn fetchCopyURL | 178 | .Fn fetchCopyURL | |
179 | copies an existing | 179 | copies an existing | |
180 | .Vt url | 180 | .Vt url | |
181 | structure. | 181 | structure. | |
182 | .Pp | 182 | .Pp | |
183 | .Fn fetchMakeURL , | 183 | .Fn fetchMakeURL , | |
184 | .Fn fetchParseURL , | 184 | .Fn fetchParseURL , | |
185 | and | 185 | and | |
186 | .Fn fetchCopyURL | 186 | .Fn fetchCopyURL | |
187 | return a pointer to a | 187 | return a pointer to a | |
188 | .Vt url | 188 | .Vt url | |
189 | structure, which is defined as follows in | 189 | structure, which is defined as follows in | |
190 | .In fetch.h : | 190 | .In fetch.h : | |
191 | .Bd -literal | 191 | .Bd -literal | |
192 | #define URL_SCHEMELEN 16 | 192 | #define URL_SCHEMELEN 16 | |
193 | #define URL_USERLEN 256 | 193 | #define URL_USERLEN 256 | |
194 | #define URL_PWDLEN 256 | 194 | #define URL_PWDLEN 256 | |
195 | #define URL_HOSTLEN 255 | 195 | #define URL_HOSTLEN 255 | |
196 | 196 | |||
197 | struct url { | 197 | struct url { | |
198 | char scheme[URL_SCHEMELEN + 1]; | 198 | char scheme[URL_SCHEMELEN + 1]; | |
199 | char user[URL_USERLEN + 1]; | 199 | char user[URL_USERLEN + 1]; | |
200 | char pwd[URL_PWDLEN + 1]; | 200 | char pwd[URL_PWDLEN + 1]; | |
201 | char host[URL_HOSTLEN + 1]; | 201 | char host[URL_HOSTLEN + 1]; | |
202 | int port; | 202 | int port; | |
203 | char *doc; | 203 | char *doc; | |
204 | off_t offset; | 204 | off_t offset; | |
205 | size_t length; | 205 | size_t length; | |
206 | time_t last_modified; | 206 | time_t last_modified; | |
207 | }; | 207 | }; | |
208 | .Ed | 208 | .Ed | |
209 | .Pp | 209 | .Pp | |
210 | The pointer returned by | 210 | The pointer returned by | |
211 | .Fn fetchMakeURL , | 211 | .Fn fetchMakeURL , | |
212 | .Fn fetchCopyURL , | 212 | .Fn fetchCopyURL , | |
213 | and | 213 | and | |
214 | .Fn fetchParseURL | 214 | .Fn fetchParseURL | |
215 | should be freed using | 215 | should be freed using | |
216 | .Fn fetchFreeURL . | 216 | .Fn fetchFreeURL . | |
217 | The size of | 217 | The size of | |
218 | .Vt struct URL | 218 | .Vt struct URL | |
219 | is not part of the ABI. | 219 | is not part of the ABI. | |
220 | .Pp | 220 | .Pp | |
221 | .Fn fetchXGetURL , | 221 | .Fn fetchXGetURL , | |
222 | .Fn fetchGetURL , | 222 | .Fn fetchGetURL , | |
223 | and | 223 | and | |
224 | .Fn fetchPutURL | 224 | .Fn fetchPutURL | |
225 | constitute the recommended interface to the | 225 | constitute the recommended interface to the | |
226 | .Nm fetch | 226 | .Nm fetch | |
227 | library. | 227 | library. | |
228 | They examine the URL passed to them to determine the transfer | 228 | They examine the URL passed to them to determine the transfer | |
229 | method, and call the appropriate lower-level functions to perform the | 229 | method, and call the appropriate lower-level functions to perform the | |
230 | actual transfer. | 230 | actual transfer. | |
231 | .Fn fetchXGetURL | 231 | .Fn fetchXGetURL | |
232 | also returns the remote document's metadata in the | 232 | also returns the remote document's metadata in the | |
233 | .Vt url_stat | 233 | .Vt url_stat | |
234 | structure pointed to by the | 234 | structure pointed to by the | |
235 | .Fa us | 235 | .Fa us | |
236 | argument. | 236 | argument. | |
237 | .Pp | 237 | .Pp | |
238 | The | 238 | The | |
239 | .Fa flags | 239 | .Fa flags | |
240 | argument is a string of characters which specify transfer options. | 240 | argument is a string of characters which specify transfer options. | |
241 | The | 241 | The | |
242 | meaning of the individual flags is scheme-dependent, and is detailed | 242 | meaning of the individual flags is scheme-dependent, and is detailed | |
243 | in the appropriate section below. | 243 | in the appropriate section below. | |
244 | .Pp | 244 | .Pp | |
245 | .Fn fetchStatURL | 245 | .Fn fetchStatURL | |
246 | attempts to obtain the requested document's metadata and fill in the | 246 | attempts to obtain the requested document's metadata and fill in the | |
247 | structure pointed to by its second argument. | 247 | structure pointed to by its second argument. | |
248 | The | 248 | The | |
249 | .Vt url_stat | 249 | .Vt url_stat | |
250 | structure is defined as follows in | 250 | structure is defined as follows in | |
251 | .In fetch.h : | 251 | .In fetch.h : | |
252 | .Bd -literal | 252 | .Bd -literal | |
253 | struct url_stat { | 253 | struct url_stat { | |
254 | off_t size; | 254 | off_t size; | |
255 | time_t atime; | 255 | time_t atime; | |
256 | time_t mtime; | 256 | time_t mtime; | |
257 | }; | 257 | }; | |
258 | .Ed | 258 | .Ed | |
259 | .Pp | 259 | .Pp | |
260 | If the size could not be obtained from the server, the | 260 | If the size could not be obtained from the server, the | |
261 | .Fa size | 261 | .Fa size | |
262 | field is set to \-1. | 262 | field is set to \-1. | |
263 | If the modification time could not be obtained from the server, the | 263 | If the modification time could not be obtained from the server, the | |
264 | .Fa mtime | 264 | .Fa mtime | |
265 | field is set to the epoch. | 265 | field is set to the epoch. | |
266 | If the access time could not be obtained from the server, the | 266 | If the access time could not be obtained from the server, the | |
267 | .Fa atime | 267 | .Fa atime | |
268 | field is set to the modification time. | 268 | field is set to the modification time. | |
269 | .Pp | 269 | .Pp | |
270 | .Fn fetchListURL | 270 | .Fn fetchListURL | |
271 | attempts to list the contents of the directory pointed to by the URL provided. | 271 | attempts to list the contents of the directory pointed to by the URL provided. | |
272 | The pattern can be a simple glob-like expression as hint. | 272 | The pattern can be a simple glob-like expression as hint. | |
273 | Callers should not depend on the server to filter names. | 273 | Callers should not depend on the server to filter names. | |
274 | If successful, it appends the list of entries to the | 274 | If successful, it appends the list of entries to the | |
275 | .Vt url_list | 275 | .Vt url_list | |
276 | structure. | 276 | structure. | |
277 | The | 277 | The | |
278 | .Vt url_list | 278 | .Vt url_list | |
279 | structure is defined as follows in | 279 | structure is defined as follows in | |
280 | .In fetch.h : | 280 | .In fetch.h : | |
281 | .Bd -literal | 281 | .Bd -literal | |
282 | struct url_list { | 282 | struct url_list { | |
283 | size_t length; | 283 | size_t length; | |
284 | size_t alloc_size; | 284 | size_t alloc_size; | |
285 | struct url *urls; | 285 | struct url *urls; | |
286 | }; | 286 | }; | |
287 | .Ed | 287 | .Ed | |
288 | .Pp | 288 | .Pp | |
289 | The list should be initialized by calling | 289 | The list should be initialized by calling | |
290 | .Fn fetchInitURLList | 290 | .Fn fetchInitURLList | |
291 | and the entries be freed by calling | 291 | and the entries be freed by calling | |
292 | .Fn fetchFreeURLList . | 292 | .Fn fetchFreeURLList . | |
293 | The function | 293 | The function | |
294 | .Fn fetchAppendURLList | 294 | .Fn fetchAppendURLList | |
295 | can be used to append one URL lists to another. | 295 | can be used to append one URL lists to another. | |
296 | If the | 296 | If the | |
297 | .Ql c | 297 | .Ql c | |
298 | (cache result) flag is specified, the library is allowed to internally | 298 | (cache result) flag is specified, the library is allowed to internally | |
299 | cache the result. | 299 | cache the result. | |
300 | .Pp | 300 | .Pp | |
301 | .Fn fetchStringifyURL | 301 | .Fn fetchStringifyURL | |
302 | returns the URL as string. | 302 | returns the URL as string. | |
303 | .Fn fetchUnquotePath | 303 | .Fn fetchUnquotePath | |
304 | returns the path name part of the URL with any quoting undone. | 304 | returns the path name part of the URL with any quoting undone. | |
305 | Query arguments and fragment identifiers are not included. | 305 | Query arguments and fragment identifiers are not included. | |
306 | .Fn fetchUnquoteFilename | 306 | .Fn fetchUnquoteFilename | |
307 | returns the last component of the path name as returned by | 307 | returns the last component of the path name as returned by | |
308 | .Fn fetchUnquotePath . | 308 | .Fn fetchUnquotePath . | |
309 | .Fn fetchStringifyURL , | 309 | .Fn fetchStringifyURL , | |
310 | .Fn fetchUnquotePath , | 310 | .Fn fetchUnquotePath , | |
311 | and | 311 | and | |
312 | .Fn fetchUnquoteFilename | 312 | .Fn fetchUnquoteFilename | |
313 | return a string that should be deallocated with | 313 | return a string that should be deallocated with | |
314 | .Fn free | 314 | .Fn free | |
315 | after use. | 315 | after use. | |
316 | .Pp | 316 | .Pp | |
317 | .Fn fetchConnectionCacheInit | 317 | .Fn fetchConnectionCacheInit | |
318 | enables the connection cache. | 318 | enables the connection cache. | |
319 | The first argument specifies the global limit on cached connections. | 319 | The first argument specifies the global limit on cached connections. | |
320 | The second argument specifies the host limit. | 320 | The second argument specifies the host limit. | |
321 | Entries are considered to specify the same host, if the host name | 321 | Entries are considered to specify the same host, if the host name | |
322 | from the URL is identical, indepent of the address or address family. | 322 | from the URL is identical, indepent of the address or address family. | |
323 | .Fn fetchConnectionCacheClose | 323 | .Fn fetchConnectionCacheClose | |
324 | flushed the connection cache and closes all cached connections. | 324 | flushed the connection cache and closes all cached connections. | |
325 | .Pp | 325 | .Pp | |
326 | .Fn fetchXGet , | 326 | .Fn fetchXGet , | |
327 | .Fn fetchGet , | 327 | .Fn fetchGet , | |
328 | .Fn fetchPut , | 328 | .Fn fetchPut , | |
329 | and | 329 | and | |
330 | .Fn fetchStat | 330 | .Fn fetchStat | |
331 | are similar to | 331 | are similar to | |
332 | .Fn fetchXGetURL , | 332 | .Fn fetchXGetURL , | |
333 | .Fn fetchGetURL , | 333 | .Fn fetchGetURL , | |
334 | .Fn fetchPutURL , | 334 | .Fn fetchPutURL , | |
335 | and | 335 | and | |
336 | .Fn fetchStatURL , | 336 | .Fn fetchStatURL , | |
337 | except that they expect a pre-parsed URL in the form of a pointer to | 337 | except that they expect a pre-parsed URL in the form of a pointer to | |
338 | a | 338 | a | |
339 | .Vt struct url | 339 | .Vt struct url | |
340 | rather than a string. | 340 | rather than a string. | |
341 | .Pp | 341 | .Pp | |
342 | All of the | 342 | All of the | |
343 | .Fn fetchXGetXXX , | 343 | .Fn fetchXGetXXX , | |
344 | .Fn fetchGetXXX , | 344 | .Fn fetchGetXXX , | |
345 | and | 345 | and | |
346 | .Fn fetchPutXXX | 346 | .Fn fetchPutXXX | |
347 | functions return a pointer to a stream which can be used to read or | 347 | functions return a pointer to a stream which can be used to read or | |
348 | write data from or to the requested document, respectively. | 348 | write data from or to the requested document, respectively. | |
349 | Note that | 349 | Note that | |
350 | although the implementation details of the individual access methods | 350 | although the implementation details of the individual access methods | |
351 | vary, it can generally be assumed that a stream returned by one of the | 351 | vary, it can generally be assumed that a stream returned by one of the | |
352 | .Fn fetchXGetXXX | 352 | .Fn fetchXGetXXX | |
353 | or | 353 | or | |
354 | .Fn fetchGetXXX | 354 | .Fn fetchGetXXX | |
355 | functions is read-only, and that a stream returned by one of the | 355 | functions is read-only, and that a stream returned by one of the | |
356 | .Fn fetchPutXXX | 356 | .Fn fetchPutXXX | |
357 | functions is write-only. | 357 | functions is write-only. | |
358 | .Sh PROTOCOL INDEPENDENT FLAGS | 358 | .Sh PROTOCOL INDEPENDENT FLAGS | |
359 | If the | 359 | If the | |
360 | .Ql i | 360 | .Ql i | |
361 | (if-modified-since) flag is specified, the library will try to fetch | 361 | (if-modified-since) flag is specified, the library will try to fetch | |
362 | the content only if it is newer than | 362 | the content only if it is newer than | |
363 | .Va last_modified . | 363 | .Va last_modified . | |
364 | For HTTP an | 364 | For HTTP an | |
365 | .Li If-Modified-Since | 365 | .Li If-Modified-Since | |
366 | HTTP header is sent. | 366 | HTTP header is sent. | |
367 | For FTP a | 367 | For FTP a | |
368 | .Li MTDM | 368 | .Li MTDM | |
369 | command is sent first and compared locally. | 369 | command is sent first and compared locally. | |
370 | For FILE the source file is compared. | 370 | For FILE the source file is compared. | |
371 | .Sh FILE SCHEME | 371 | .Sh FILE SCHEME | |
372 | .Fn fetchXGetFile , | 372 | .Fn fetchXGetFile , | |
373 | .Fn fetchGetFile , | 373 | .Fn fetchGetFile , | |
374 | and | 374 | and | |
375 | .Fn fetchPutFile | 375 | .Fn fetchPutFile | |
376 | provide access to documents which are files in a locally mounted file | 376 | provide access to documents which are files in a locally mounted file | |
377 | system. | 377 | system. | |
378 | Only the | 378 | Only the | |
379 | .Aq document | 379 | .Aq document | |
380 | component of the URL is used. | 380 | component of the URL is used. | |
381 | .Pp | 381 | .Pp | |
382 | .Fn fetchXGetFile | 382 | .Fn fetchXGetFile | |
383 | and | 383 | and | |
384 | .Fn fetchGetFile | 384 | .Fn fetchGetFile | |
385 | do not accept any flags. | 385 | do not accept any flags. | |
386 | .Pp | 386 | .Pp | |
387 | .Fn fetchPutFile | 387 | .Fn fetchPutFile | |
388 | accepts the | 388 | accepts the | |
389 | .Ql a | 389 | .Ql a | |
390 | (append to file) flag. | 390 | (append to file) flag. | |
391 | If that flag is specified, the data written to | 391 | If that flag is specified, the data written to | |
392 | the stream returned by | 392 | the stream returned by | |
393 | .Fn fetchPutFile | 393 | .Fn fetchPutFile | |
394 | will be appended to the previous contents of the file, instead of | 394 | will be appended to the previous contents of the file, instead of | |
395 | replacing them. | 395 | replacing them. | |
396 | .Sh FTP SCHEME | 396 | .Sh FTP SCHEME | |
397 | .Fn fetchXGetFTP , | 397 | .Fn fetchXGetFTP , | |
398 | .Fn fetchGetFTP , | 398 | .Fn fetchGetFTP , | |
399 | and | 399 | and | |
400 | .Fn fetchPutFTP | 400 | .Fn fetchPutFTP | |
401 | implement the FTP protocol as described in RFC 959. | 401 | implement the FTP protocol as described in RFC 959. | |
402 | .Pp | 402 | .Pp | |
403 | By default | 403 | By default | |
404 | .Nm libfetch | 404 | .Nm libfetch | |
405 | will attempt to use passive mode first and only fallback to active mode | 405 | will attempt to use passive mode first and only fallback to active mode | |
406 | if the server reports a syntax error. | 406 | if the server reports a syntax error. | |
407 | If the | 407 | If the | |
408 | .Ql a | 408 | .Ql a | |
409 | (active) flag is specified, a passive connection is not tried and active mode | 409 | (active) flag is specified, a passive connection is not tried and active mode | |
410 | is used directly. | 410 | is used directly. | |
411 | .Pp | 411 | .Pp | |
412 | If the | 412 | If the | |
413 | .Ql l | 413 | .Ql l | |
414 | (low) flag is specified, data sockets will be allocated in the low (or | 414 | (low) flag is specified, data sockets will be allocated in the low (or | |
415 | default) port range instead of the high port range (see | 415 | default) port range instead of the high port range (see | |
416 | .Xr ip 4 ) . | 416 | .Xr ip 4 ) . | |
417 | .Pp | 417 | .Pp | |
418 | If the | 418 | If the | |
419 | .Ql d | 419 | .Ql d | |
420 | (direct) flag is specified, | 420 | (direct) flag is specified, | |
421 | .Fn fetchXGetFTP , | 421 | .Fn fetchXGetFTP , | |
422 | .Fn fetchGetFTP , | 422 | .Fn fetchGetFTP , | |
423 | and | 423 | and | |
424 | .Fn fetchPutFTP | 424 | .Fn fetchPutFTP | |
425 | will use a direct connection even if a proxy server is defined. | 425 | will use a direct connection even if a proxy server is defined. | |
426 | .Pp | 426 | .Pp | |
427 | If no user name or password is given, the | 427 | If no user name or password is given, the | |
428 | .Nm fetch | 428 | .Nm fetch | |
429 | library will attempt an anonymous login, with user name "anonymous" | 429 | library will attempt an anonymous login, with user name "anonymous" | |
430 | and password "anonymous@\*[Lt]hostname\*[Gt]". | 430 | and password "anonymous@\*[Lt]hostname\*[Gt]". | |
431 | .Sh HTTP SCHEME | 431 | .Sh HTTP SCHEME | |
432 | The | 432 | The | |
433 | .Fn fetchXGetHTTP , | 433 | .Fn fetchXGetHTTP , | |
434 | .Fn fetchGetHTTP , | 434 | .Fn fetchGetHTTP , | |
435 | and | 435 | and | |
436 | .Fn fetchPutHTTP | 436 | .Fn fetchPutHTTP | |
437 | functions implement the HTTP/1.1 protocol. | 437 | functions implement the HTTP/1.1 protocol. | |
438 | With a little luck, there is | 438 | With a little luck, there is | |
439 | even a chance that they comply with RFC 2616 and RFC 2617. | 439 | even a chance that they comply with RFC 2616 and RFC 2617. | |
440 | .Pp | 440 | .Pp | |
441 | If the | 441 | If the | |
442 | .Ql d | 442 | .Ql d | |
443 | (direct) flag is specified, | 443 | (direct) flag is specified, | |
444 | .Fn fetchXGetHTTP , | 444 | .Fn fetchXGetHTTP , | |
445 | .Fn fetchGetHTTP , | 445 | .Fn fetchGetHTTP , | |
446 | and | 446 | and | |
447 | .Fn fetchPutHTTP | 447 | .Fn fetchPutHTTP | |
448 | will use a direct connection even if a proxy server is defined. | 448 | will use a direct connection even if a proxy server is defined. | |
449 | .Pp | 449 | .Pp | |
450 | Since there seems to be no good way of implementing the HTTP PUT | 450 | Since there seems to be no good way of implementing the HTTP PUT | |
451 | method in a manner consistent with the rest of the | 451 | method in a manner consistent with the rest of the | |
452 | .Nm fetch | 452 | .Nm fetch | |
453 | library, | 453 | library, | |
454 | .Fn fetchPutHTTP | 454 | .Fn fetchPutHTTP | |
455 | is currently unimplemented. | 455 | is currently unimplemented. | |
456 | .Sh AUTHENTICATION | 456 | .Sh AUTHENTICATION | |
457 | Apart from setting the appropriate environment variables and | 457 | Apart from setting the appropriate environment variables and | |
458 | specifying the user name and password in the URL or the | 458 | specifying the user name and password in the URL or the | |
459 | .Vt struct url , | 459 | .Vt struct url , | |
460 | the calling program has the option of defining an authentication | 460 | the calling program has the option of defining an authentication | |
461 | function with the following prototype: | 461 | function with the following prototype: | |
462 | .Pp | 462 | .Pp | |
463 | .Ft int | 463 | .Ft int | |
464 | .Fn myAuthMethod "struct url *u" | 464 | .Fn myAuthMethod "struct url *u" | |
465 | .Pp | 465 | .Pp | |
466 | The callback function should fill in the | 466 | The callback function should fill in the | |
467 | .Fa user | 467 | .Fa user | |
468 | and | 468 | and | |
469 | .Fa pwd | 469 | .Fa pwd | |
470 | fields in the provided | 470 | fields in the provided | |
471 | .Vt struct url | 471 | .Vt struct url | |
472 | and return 0 on success, or any other value to indicate failure. | 472 | and return 0 on success, or any other value to indicate failure. | |
473 | .Pp | 473 | .Pp | |
474 | To register the authentication callback, simply set | 474 | To register the authentication callback, simply set | |
475 | .Va fetchAuthMethod | 475 | .Va fetchAuthMethod | |
476 | to point at it. | 476 | to point at it. | |
477 | The callback will be used whenever a site requires authentication and | 477 | The callback will be used whenever a site requires authentication and | |
478 | the appropriate environment variables are not set. | 478 | the appropriate environment variables are not set. | |
479 | .Pp | 479 | .Pp | |
480 | This interface is experimental and may be subject to change. | 480 | This interface is experimental and may be subject to change. | |
481 | .Sh RETURN VALUES | 481 | .Sh RETURN VALUES | |
482 | .Fn fetchParseURL | 482 | .Fn fetchParseURL | |
483 | returns a pointer to a | 483 | returns a pointer to a | |
484 | .Vt struct url | 484 | .Vt struct url | |
485 | containing the individual components of the URL. | 485 | containing the individual components of the URL. | |
486 | If it is | 486 | If it is | |
487 | unable to allocate memory, or the URL is syntactically incorrect, | 487 | unable to allocate memory, or the URL is syntactically incorrect, | |
488 | .Fn fetchParseURL | 488 | .Fn fetchParseURL | |
489 | returns a | 489 | returns a | |
490 | .Dv NULL | 490 | .Dv NULL | |
491 | pointer. | 491 | pointer. | |
492 | .Pp | 492 | .Pp | |
493 | The | 493 | The | |
494 | .Fn fetchStat | 494 | .Fn fetchStat | |
495 | functions return 0 on success and \-1 on failure. | 495 | functions return 0 on success and \-1 on failure. | |
496 | .Pp | 496 | .Pp | |
497 | All other functions return a stream pointer which may be used to | 497 | All other functions return a stream pointer which may be used to | |
498 | access the requested document, or | 498 | access the requested document, or | |
499 | .Dv NULL | 499 | .Dv NULL | |
500 | if an error occurred. | 500 | if an error occurred. | |
501 | .Pp | 501 | .Pp | |
502 | The following error codes are defined in | 502 | The following error codes are defined in | |
503 | .In fetch.h : | 503 | .In fetch.h : | |
504 | .Bl -tag -width 18n | 504 | .Bl -tag -width 18n | |
505 | .It Bq Er FETCH_ABORT | 505 | .It Bq Er FETCH_ABORT | |
506 | Operation aborted | 506 | Operation aborted | |
507 | .It Bq Er FETCH_AUTH | 507 | .It Bq Er FETCH_AUTH | |
508 | Authentication failed | 508 | Authentication failed | |
509 | .It Bq Er FETCH_DOWN | 509 | .It Bq Er FETCH_DOWN | |
510 | Service unavailable | 510 | Service unavailable | |
511 | .It Bq Er FETCH_EXISTS | 511 | .It Bq Er FETCH_EXISTS | |
512 | File exists | 512 | File exists | |
513 | .It Bq Er FETCH_FULL | 513 | .It Bq Er FETCH_FULL | |
514 | File system full | 514 | File system full | |
515 | .It Bq Er FETCH_INFO | 515 | .It Bq Er FETCH_INFO | |
516 | Informational response | 516 | Informational response | |
517 | .It Bq Er FETCH_MEMORY | 517 | .It Bq Er FETCH_MEMORY | |
518 | Insufficient memory | 518 | Insufficient memory | |
519 | .It Bq Er FETCH_MOVED | 519 | .It Bq Er FETCH_MOVED | |
520 | File has moved | 520 | File has moved | |
521 | .It Bq Er FETCH_NETWORK | 521 | .It Bq Er FETCH_NETWORK | |
522 | Network error | 522 | Network error | |
523 | .It Bq Er FETCH_OK | 523 | .It Bq Er FETCH_OK | |
524 | No error | 524 | No error | |
525 | .It Bq Er FETCH_PROTO | 525 | .It Bq Er FETCH_PROTO | |
526 | Protocol error | 526 | Protocol error | |
527 | .It Bq Er FETCH_RESOLV | 527 | .It Bq Er FETCH_RESOLV | |
528 | Resolver error | 528 | Resolver error | |
529 | .It Bq Er FETCH_SERVER | 529 | .It Bq Er FETCH_SERVER | |
530 | Server error | 530 | Server error | |
531 | .It Bq Er FETCH_TEMP | 531 | .It Bq Er FETCH_TEMP | |
532 | Temporary error | 532 | Temporary error | |
533 | .It Bq Er FETCH_TIMEOUT | 533 | .It Bq Er FETCH_TIMEOUT | |
534 | Operation timed out | 534 | Operation timed out | |
535 | .It Bq Er FETCH_UNAVAIL | 535 | .It Bq Er FETCH_UNAVAIL | |
536 | File is not available | 536 | File is not available | |
537 | .It Bq Er FETCH_UNKNOWN | 537 | .It Bq Er FETCH_UNKNOWN | |
538 | Unknown error | 538 | Unknown error | |
539 | .It Bq Er FETCH_URL | 539 | .It Bq Er FETCH_URL | |
540 | Invalid URL | 540 | Invalid URL | |
541 | .El | 541 | .El | |
542 | .Pp | 542 | .Pp | |
543 | The accompanying error message includes a protocol-specific error code | 543 | The accompanying error message includes a protocol-specific error code | |
544 | and message, e.g.\& "File is not available (404 Not Found)" | 544 | and message, e.g.\& "File is not available (404 Not Found)" | |
545 | .Sh ENVIRONMENT | 545 | .Sh ENVIRONMENT | |
546 | .Bl -tag -width ".Ev FETCH_BIND_ADDRESS" | 546 | .Bl -tag -width ".Ev FETCH_BIND_ADDRESS" | |
547 | .It Ev FETCH_BIND_ADDRESS | 547 | .It Ev FETCH_BIND_ADDRESS | |
548 | Specifies a host name or IP address to which sockets used for outgoing | 548 | Specifies a host name or IP address to which sockets used for outgoing | |
549 | connections will be bound. | 549 | connections will be bound. | |
550 | .It Ev FTP_LOGIN | 550 | .It Ev FTP_LOGIN | |
551 | Default FTP login if none was provided in the URL. | 551 | Default FTP login if none was provided in the URL. | |
552 | .It Ev FTP_PASSIVE_MODE | 552 | .It Ev FTP_PASSIVE_MODE | |
553 | If set to anything but | 553 | If set to anything but | |
554 | .Ql no , | 554 | .Ql no , | |
555 | forces the FTP code to use passive mode. | 555 | forces the FTP code to use passive mode. | |
556 | .It Ev FTP_PASSWORD | 556 | .It Ev FTP_PASSWORD | |
557 | Default FTP password if the remote server requests one and none was | 557 | Default FTP password if the remote server requests one and none was | |
558 | provided in the URL. | 558 | provided in the URL. | |
559 | .It Ev FTP_PROXY | 559 | .It Ev FTP_PROXY | |
560 | URL of the proxy to use for FTP requests. | 560 | URL of the proxy to use for FTP requests. | |
561 | The document part is ignored. | 561 | The document part is ignored. | |
562 | FTP and HTTP proxies are supported; if no scheme is specified, FTP is | 562 | FTP and HTTP proxies are supported; if no scheme is specified, FTP is | |
563 | assumed. | 563 | assumed. | |
564 | If the proxy is an FTP proxy, | 564 | If the proxy is an FTP proxy, | |
565 | .Nm libfetch | 565 | .Nm libfetch | |
566 | will send | 566 | will send | |
567 | .Ql user@host | 567 | .Ql user@host | |
568 | as user name to the proxy, where | 568 | as user name to the proxy, where | |
569 | .Ql user | 569 | .Ql user | |
570 | is the real user name, and | 570 | is the real user name, and | |
571 | .Ql host | 571 | .Ql host | |
572 | is the name of the FTP server. | 572 | is the name of the FTP server. | |
573 | .Pp | 573 | .Pp | |
574 | If this variable is set to an empty string, no proxy will be used for | 574 | If this variable is set to an empty string, no proxy will be used for | |
575 | FTP requests, even if the | 575 | FTP requests, even if the | |
576 | .Ev HTTP_PROXY | 576 | .Ev HTTP_PROXY | |
577 | variable is set. | 577 | variable is set. | |
578 | .It Ev ftp_proxy | 578 | .It Ev ftp_proxy | |
579 | Same as | 579 | Same as | |
580 | .Ev FTP_PROXY , | 580 | .Ev FTP_PROXY , | |
581 | for compatibility. | 581 | for compatibility. | |
582 | .It Ev HTTP_AUTH | 582 | .It Ev HTTP_AUTH | |
583 | Specifies HTTP authorization parameters as a colon-separated list of | 583 | Specifies HTTP authorization parameters as a colon-separated list of | |
584 | items. | 584 | items. | |
585 | The first and second item are the authorization scheme and realm | 585 | The first and second item are the authorization scheme and realm | |
586 | respectively; further items are scheme-dependent. | 586 | respectively; further items are scheme-dependent. | |
587 | Currently, only basic authorization is supported. | 587 | Currently, only basic authorization is supported. | |
588 | .Pp | 588 | .Pp | |
589 | Basic authorization requires two parameters: the user name and | 589 | Basic authorization requires two parameters: the user name and | |
590 | password, in that order. | 590 | password, in that order. | |
591 | .Pp | 591 | .Pp | |
592 | This variable is only used if the server requires authorization and | 592 | This variable is only used if the server requires authorization and | |
593 | no user name or password was specified in the URL. | 593 | no user name or password was specified in the URL. | |
594 | .It Ev HTTP_PROXY | 594 | .It Ev HTTP_PROXY | |
595 | URL of the proxy to use for HTTP requests. | 595 | URL of the proxy to use for HTTP requests. | |
596 | The document part is ignored. | 596 | The document part is ignored. | |
597 | Only HTTP proxies are supported for HTTP requests. | 597 | Only HTTP proxies are supported for HTTP requests. | |
598 | If no port number is specified, the default is 3128. | 598 | If no port number is specified, the default is 3128. | |
599 | .Pp | 599 | .Pp | |
600 | Note that this proxy will also be used for FTP documents, unless the | 600 | Note that this proxy will also be used for FTP documents, unless the | |
601 | .Ev FTP_PROXY | 601 | .Ev FTP_PROXY | |
602 | variable is set. | 602 | variable is set. | |
603 | .It Ev http_proxy | 603 | .It Ev http_proxy | |
604 | Same as | 604 | Same as | |
605 | .Ev HTTP_PROXY , | 605 | .Ev HTTP_PROXY , | |
606 | for compatibility. | 606 | for compatibility. | |
607 | .It Ev HTTP_PROXY_AUTH | 607 | .It Ev HTTP_PROXY_AUTH | |
608 | Specifies authorization parameters for the HTTP proxy in the same | 608 | Specifies authorization parameters for the HTTP proxy in the same | |
609 | format as the | 609 | format as the | |
610 | .Ev HTTP_AUTH | 610 | .Ev HTTP_AUTH | |
611 | variable. | 611 | variable. | |
612 | .Pp | 612 | .Pp | |
613 | This variable is used if and only if connected to an HTTP proxy, and | 613 | This variable is used if and only if connected to an HTTP proxy, and | |
614 | is ignored if a user and/or a password were specified in the proxy | 614 | is ignored if a user and/or a password were specified in the proxy | |
615 | URL. | 615 | URL. | |
616 | .It Ev HTTP_REFERER | 616 | .It Ev HTTP_REFERER | |
617 | Specifies the referrer URL to use for HTTP requests. | 617 | Specifies the referrer URL to use for HTTP requests. | |
618 | If set to | 618 | If set to | |
619 | .Dq auto , | 619 | .Dq auto , | |
620 | the document URL will be used as referrer URL. | 620 | the document URL will be used as referrer URL. | |
621 | .It Ev HTTP_USER_AGENT | 621 | .It Ev HTTP_USER_AGENT | |
622 | Specifies the User-Agent string to use for HTTP requests. | 622 | Specifies the User-Agent string to use for HTTP requests. | |
623 | This can be useful when working with HTTP origin or proxy servers that | 623 | This can be useful when working with HTTP origin or proxy servers that | |
624 | differentiate between user agents. | 624 | differentiate between user agents. | |
625 | .It Ev NETRC | 625 | .It Ev NETRC | |
626 | Specifies a file to use instead of | 626 | Specifies a file to use instead of | |
627 | .Pa ~/.netrc | 627 | .Pa ~/.netrc | |
628 | to look up login names and passwords for FTP sites. | 628 | to look up login names and passwords for FTP sites. | |
629 | See | 629 | See | |
630 | .Xr ftp 1 | 630 | .Xr ftp 1 | |
631 | for a description of the file format. | 631 | for a description of the file format. | |
632 | This feature is experimental. | 632 | This feature is experimental. | |
633 | .It Ev NO_PROXY | 633 | .It Ev NO_PROXY | |
634 | Either a single asterisk, which disables the use of proxies | 634 | Either a single asterisk, which disables the use of proxies | |
635 | altogether, or a comma- or whitespace-separated list of hosts for | 635 | altogether, or a comma- or whitespace-separated list of hosts for | |
636 | which proxies should not be used. | 636 | which proxies should not be used. | |
637 | .It Ev no_proxy | 637 | .It Ev no_proxy | |
638 | Same as | 638 | Same as | |
639 | .Ev NO_PROXY , | 639 | .Ev NO_PROXY , | |
640 | for compatibility. | 640 | for compatibility. | |
641 | .It Ev SSL_NO_VERIFY_PEER | |||
642 | If defined, | |||
643 | .Nm | |||
644 | will skip validating certificates when fetching HTTPS URLs. | |||
641 | .El | 645 | .El | |
642 | .Sh EXAMPLES | 646 | .Sh EXAMPLES | |
643 | To access a proxy server on | 647 | To access a proxy server on | |
644 | .Pa proxy.example.com | 648 | .Pa proxy.example.com | |
645 | port 8080, set the | 649 | port 8080, set the | |
646 | .Ev HTTP_PROXY | 650 | .Ev HTTP_PROXY | |
647 | environment variable in a manner similar to this: | 651 | environment variable in a manner similar to this: | |
648 | .Pp | 652 | .Pp | |
649 | .Dl HTTP_PROXY=http://proxy.example.com:8080 | 653 | .Dl HTTP_PROXY=http://proxy.example.com:8080 | |
650 | .Pp | 654 | .Pp | |
651 | If the proxy server requires authentication, there are | 655 | If the proxy server requires authentication, there are | |
652 | two options available for passing the authentication data. | 656 | two options available for passing the authentication data. | |
653 | The first method is by using the proxy URL: | 657 | The first method is by using the proxy URL: | |
654 | .Pp | 658 | .Pp | |
655 | .Dl HTTP_PROXY=http://\*[Lt]user\*[Gt]:\*[Lt]pwd\*[Gt]@proxy.example.com:8080 | 659 | .Dl HTTP_PROXY=http://\*[Lt]user\*[Gt]:\*[Lt]pwd\*[Gt]@proxy.example.com:8080 | |
656 | .Pp | 660 | .Pp | |
657 | The second method is by using the | 661 | The second method is by using the | |
658 | .Ev HTTP_PROXY_AUTH | 662 | .Ev HTTP_PROXY_AUTH | |
659 | environment variable: | 663 | environment variable: | |
660 | .Bd -literal -offset indent | 664 | .Bd -literal -offset indent | |
661 | HTTP_PROXY=http://proxy.example.com:8080 | 665 | HTTP_PROXY=http://proxy.example.com:8080 | |
662 | HTTP_PROXY_AUTH=basic:*:\*[Lt]user\*[Gt]:\*[Lt]pwd\*[Gt] | 666 | HTTP_PROXY_AUTH=basic:*:\*[Lt]user\*[Gt]:\*[Lt]pwd\*[Gt] | |
663 | .Ed | 667 | .Ed | |
664 | .Pp | 668 | .Pp | |
665 | To disable the use of a proxy for an HTTP server running on the local | 669 | To disable the use of a proxy for an HTTP server running on the local | |
666 | host, define | 670 | host, define | |
667 | .Ev NO_PROXY | 671 | .Ev NO_PROXY | |
668 | as follows: | 672 | as follows: | |
669 | .Bd -literal -offset indent | 673 | .Bd -literal -offset indent | |
670 | NO_PROXY=localhost,127.0.0.1 | 674 | NO_PROXY=localhost,127.0.0.1 | |
671 | .Ed | 675 | .Ed | |
672 | .Sh SEE ALSO | 676 | .Sh SEE ALSO | |
673 | .\" .Xr fetch 1 , | 677 | .\" .Xr fetch 1 , | |
674 | .\" .Xr ftpio 3 , | 678 | .\" .Xr ftpio 3 , | |
675 | .Xr ftp 1 , | 679 | .Xr ftp 1 , | |
676 | .Xr ip 4 | 680 | .Xr ip 4 | |
677 | .Rs | 681 | .Rs | |
678 | .%A J. Postel | 682 | .%A J. Postel | |
679 | .%A J. K. Reynolds | 683 | .%A J. K. Reynolds | |
680 | .%D October 1985 | 684 | .%D October 1985 | |
681 | .%B File Transfer Protocol | 685 | .%B File Transfer Protocol | |
682 | .%O RFC 959 | 686 | .%O RFC 959 | |
683 | .Re | 687 | .Re | |
684 | .Rs | 688 | .Rs | |
685 | .%A P. Deutsch | 689 | .%A P. Deutsch | |
686 | .%A A. Emtage | 690 | .%A A. Emtage | |
687 | .%A A. Marine | 691 | .%A A. Marine | |
688 | .%D May 1994 | 692 | .%D May 1994 | |
689 | .%T How to Use Anonymous FTP | 693 | .%T How to Use Anonymous FTP | |
690 | .%O RFC 1635 | 694 | .%O RFC 1635 | |
691 | .Re | 695 | .Re | |
692 | .Rs | 696 | .Rs | |
693 | .%A T. Berners-Lee | 697 | .%A T. Berners-Lee | |
694 | .%A L. Masinter | 698 | .%A L. Masinter | |
695 | .%A M. McCahill | 699 | .%A M. McCahill | |
696 | .%D December 1994 | 700 | .%D December 1994 | |
697 | .%T Uniform Resource Locators (URL) | 701 | .%T Uniform Resource Locators (URL) | |
698 | .%O RFC 1738 | 702 | .%O RFC 1738 | |
699 | .Re | 703 | .Re | |
700 | .Rs | 704 | .Rs | |
701 | .%A R. Fielding | 705 | .%A R. Fielding | |
702 | .%A J. Gettys | 706 | .%A J. Gettys | |
703 | .%A J. Mogul | 707 | .%A J. Mogul | |
704 | .%A H. Frystyk | 708 | .%A H. Frystyk | |
705 | .%A L. Masinter | 709 | .%A L. Masinter | |
706 | .%A P. Leach | 710 | .%A P. Leach | |
707 | .%A T. Berners-Lee | 711 | .%A T. Berners-Lee | |
708 | .%D January 1999 | 712 | .%D January 1999 | |
709 | .%B Hypertext Transfer Protocol -- HTTP/1.1 | 713 | .%B Hypertext Transfer Protocol -- HTTP/1.1 | |
710 | .%O RFC 2616 | 714 | .%O RFC 2616 | |
711 | .Re | 715 | .Re | |
712 | .Rs | 716 | .Rs | |
713 | .%A J. Franks | 717 | .%A J. Franks | |
714 | .%A P. Hallam-Baker | 718 | .%A P. Hallam-Baker | |
715 | .%A J. Hostetler | 719 | .%A J. Hostetler | |
716 | .%A S. Lawrence | 720 | .%A S. Lawrence | |
717 | .%A P. Leach | 721 | .%A P. Leach | |
718 | .%A A. Luotonen | 722 | .%A A. Luotonen | |
719 | .%A L. Stewart | 723 | .%A L. Stewart | |
720 | .%D June 1999 | 724 | .%D June 1999 | |
721 | .%B HTTP Authentication: Basic and Digest Access Authentication | 725 | .%B HTTP Authentication: Basic and Digest Access Authentication | |
722 | .%O RFC 2617 | 726 | .%O RFC 2617 | |
723 | .Re | 727 | .Re | |
724 | .Sh HISTORY | 728 | .Sh HISTORY | |
725 | The | 729 | The | |
726 | .Nm fetch | 730 | .Nm fetch | |
727 | library first appeared in | 731 | library first appeared in | |
728 | .Fx 3.0 . | 732 | .Fx 3.0 . | |
729 | .Sh AUTHORS | 733 | .Sh AUTHORS | |
730 | .An -nosplit | 734 | .An -nosplit | |
731 | The | 735 | The | |
732 | .Nm fetch | 736 | .Nm fetch | |
733 | library was mostly written by | 737 | library was mostly written by | |
734 | .An Dag-Erling Sm\(/orgrav Aq Mt des@FreeBSD.org | 738 | .An Dag-Erling Sm\(/orgrav Aq Mt des@FreeBSD.org | |
735 | with numerous suggestions from | 739 | with numerous suggestions from | |
736 | .An Jordan K. Hubbard Aq Mt jkh@FreeBSD.org , | 740 | .An Jordan K. Hubbard Aq Mt jkh@FreeBSD.org , | |
737 | .An Eugene Skepner Aq Mt eu@qub.com | 741 | .An Eugene Skepner Aq Mt eu@qub.com | |
738 | and other | 742 | and other | |
739 | .Fx | 743 | .Fx | |
740 | developers. | 744 | developers. | |
741 | It replaces the older | 745 | It replaces the older | |
742 | .Nm ftpio | 746 | .Nm ftpio | |
743 | library written by | 747 | library written by | |
744 | .An Poul-Henning Kamp Aq Mt phk@FreeBSD.org | 748 | .An Poul-Henning Kamp Aq Mt phk@FreeBSD.org | |
745 | and | 749 | and | |
746 | .An Jordan K. Hubbard Aq Mt jkh@FreeBSD.org . | 750 | .An Jordan K. Hubbard Aq Mt jkh@FreeBSD.org . | |
747 | .Pp | 751 | .Pp | |
748 | This manual page was written by | 752 | This manual page was written by | |
749 | .An Dag-Erling Sm\(/orgrav Aq Mt des@FreeBSD.org . | 753 | .An Dag-Erling Sm\(/orgrav Aq Mt des@FreeBSD.org . | |
750 | .Sh BUGS | 754 | .Sh BUGS | |
751 | Some parts of the library are not yet implemented. | 755 | Some parts of the library are not yet implemented. | |
752 | The most notable | 756 | The most notable | |
753 | examples of this are | 757 | examples of this are | |
754 | .Fn fetchPutHTTP | 758 | .Fn fetchPutHTTP | |
755 | and FTP proxy support. | 759 | and FTP proxy support. | |
756 | .Pp | 760 | .Pp | |
757 | There is no way to select a proxy at run-time other than setting the | 761 | There is no way to select a proxy at run-time other than setting the | |
758 | .Ev HTTP_PROXY | 762 | .Ev HTTP_PROXY | |
759 | or | 763 | or | |
760 | .Ev FTP_PROXY | 764 | .Ev FTP_PROXY | |
761 | environment variables as appropriate. | 765 | environment variables as appropriate. | |
762 | .Pp | 766 | .Pp | |
763 | .Nm libfetch | 767 | .Nm libfetch | |
764 | does not understand or obey 305 (Use Proxy) replies. | 768 | does not understand or obey 305 (Use Proxy) replies. | |
765 | .Pp | 769 | .Pp | |
766 | Error numbers are unique only within a certain context; the error | 770 | Error numbers are unique only within a certain context; the error | |
767 | codes used for FTP and HTTP overlap, as do those used for resolver and | 771 | codes used for FTP and HTTP overlap, as do those used for resolver and | |
768 | system errors. | 772 | system errors. | |
769 | For instance, error code 202 means "Command not | 773 | For instance, error code 202 means "Command not | |
770 | implemented, superfluous at this site" in an FTP context and | 774 | implemented, superfluous at this site" in an FTP context and | |
771 | "Accepted" in an HTTP context. | 775 | "Accepted" in an HTTP context. | |
772 | .Pp | 776 | .Pp | |
773 | .Fn fetchStatFTP | 777 | .Fn fetchStatFTP | |
774 | does not check that the result of an MDTM command is a valid date. | 778 | does not check that the result of an MDTM command is a valid date. | |
775 | .Pp | 779 | .Pp | |
776 | The man page is incomplete, poorly written and produces badly | 780 | The man page is incomplete, poorly written and produces badly | |
777 | formatted text. | 781 | formatted text. | |
778 | .Pp | 782 | .Pp | |
779 | The error reporting mechanism is unsatisfactory. | 783 | The error reporting mechanism is unsatisfactory. | |
780 | .Pp | 784 | .Pp | |
781 | Some parts of the code are not fully reentrant. | 785 | Some parts of the code are not fully reentrant. |
@@ -1,236 +1,236 @@ | @@ -1,236 +1,236 @@ | |||
1 | # $NetBSD: Makefile,v 1.237 2023/10/24 22:10:40 wiz Exp $ | 1 | # $NetBSD: Makefile,v 1.237.2.1 2024/01/13 12:49:09 bsiegert Exp $ | |
2 | 2 | |||
3 | # Notes to package maintainers: | 3 | # Notes to package maintainers: | |
4 | # | 4 | # | |
5 | # Updating this package does not automatically necessitate bumping | 5 | # Updating this package does not automatically necessitate bumping | |
6 | # PKGTOOLS_REQD in bsd.pkg.mk. Do so if and only if there is a critical | 6 | # PKGTOOLS_REQD in bsd.pkg.mk. Do so if and only if there is a critical | |
7 | # change in the pkg_* tools that pkgsrc relies on for proper operation. | 7 | # change in the pkg_* tools that pkgsrc relies on for proper operation. | |
8 | 8 | |||
9 | PKGNAME= pkg_install-${VERSION} | 9 | PKGNAME= pkg_install-${VERSION} | |
10 | PKGREVISION= 1 | 10 | PKGREVISION= 2 | |
11 | CATEGORIES= pkgtools | 11 | CATEGORIES= pkgtools | |
12 | 12 | |||
13 | MAINTAINER= agc@NetBSD.org | 13 | MAINTAINER= agc@NetBSD.org | |
14 | HOMEPAGE= https://www.pkgsrc.org/ | 14 | HOMEPAGE= https://www.pkgsrc.org/ | |
15 | COMMENT= Package management and administration tools for pkgsrc | 15 | COMMENT= Package management and administration tools for pkgsrc | |
16 | LICENSE= modified-bsd | 16 | LICENSE= modified-bsd | |
17 | 17 | |||
18 | BOOTSTRAP_PKG= yes | 18 | BOOTSTRAP_PKG= yes | |
19 | SKIP_LICENSE_CHECK= yes | 19 | SKIP_LICENSE_CHECK= yes | |
20 | 20 | |||
21 | CONFLICTS+= audit-packages-[0-9]* | 21 | CONFLICTS+= audit-packages-[0-9]* | |
22 | 22 | |||
23 | GNU_CONFIGURE= yes | 23 | GNU_CONFIGURE= yes | |
24 | CONFIGURE_ARGS+= --sysconfdir=${PKG_SYSCONFDIR} | 24 | CONFIGURE_ARGS+= --sysconfdir=${PKG_SYSCONFDIR} | |
25 | CONFIGURE_ARGS+= --with-pkgdbdir=${PKG_DBDIR} | 25 | CONFIGURE_ARGS+= --with-pkgdbdir=${PKG_DBDIR} | |
26 | 26 | |||
27 | USE_FEATURES= nbcompat | 27 | USE_FEATURES= nbcompat | |
28 | 28 | |||
29 | NBCOMPAT_CONFIGURE_ARGS+= --enable-bsd-getopt --enable-db | 29 | NBCOMPAT_CONFIGURE_ARGS+= --enable-bsd-getopt --enable-db | |
30 | 30 | |||
31 | SKIP_AUDIT_PACKAGES= yes | 31 | SKIP_AUDIT_PACKAGES= yes | |
32 | NO_PKGTOOLS_REQD_CHECK= yes | 32 | NO_PKGTOOLS_REQD_CHECK= yes | |
33 | PKG_PRESERVE= yes | 33 | PKG_PRESERVE= yes | |
34 | CHECK_PERMS_SKIP= * | 34 | CHECK_PERMS_SKIP= * | |
35 | 35 | |||
36 | # These are needed to solve a chicken-and-egg problem where pkgsrc uses | 36 | # These are needed to solve a chicken-and-egg problem where pkgsrc uses | |
37 | # newer features of pkg_install, but older NetBSD installations won't | 37 | # newer features of pkg_install, but older NetBSD installations won't | |
38 | # support them. In this case, we explicitly use the native GCC | 38 | # support them. In this case, we explicitly use the native GCC | |
39 | # compiler to avoid problems with depending on pkgsrc GCC for building | 39 | # compiler to avoid problems with depending on pkgsrc GCC for building | |
40 | # pkg_install. | 40 | # pkg_install. | |
41 | # | 41 | # | |
42 | # We also use the newly built pkg_{add,create,delete} since upgrading | 42 | # We also use the newly built pkg_{add,create,delete} since upgrading | |
43 | # from an older pkg_install might required features of the new | 43 | # from an older pkg_install might required features of the new | |
44 | # program, provided that we are not cross-compiling. (XXX If we are | 44 | # program, provided that we are not cross-compiling. (XXX If we are | |
45 | # cross-compiling, we should maybe have a host build dependency on | 45 | # cross-compiling, we should maybe have a host build dependency on | |
46 | # ourselves...) | 46 | # ourselves...) | |
47 | # | 47 | # | |
48 | # Note that the definitions are only overriden for the phases that are | 48 | # Note that the definitions are only overriden for the phases that are | |
49 | # supposed to use them. pkg_admin pmatch might be used when looking for | 49 | # supposed to use them. pkg_admin pmatch might be used when looking for | |
50 | # dependencies. If that is ever changed in a incompatible way, this has to | 50 | # dependencies. If that is ever changed in a incompatible way, this has to | |
51 | # be rethought. | 51 | # be rethought. | |
52 | USE_NATIVE_GCC= yes | 52 | USE_NATIVE_GCC= yes | |
53 | 53 | |||
54 | .include "../../mk/bsd.prefs.mk" | 54 | .include "../../mk/bsd.prefs.mk" | |
55 | 55 | |||
56 | .if ${OS_VARIANT} == "SCOOSR5" | 56 | .if ${OS_VARIANT} == "SCOOSR5" | |
57 | # SCO OpenServer 5.0.7/3.2's strings.h defines strcasecmp with | 57 | # SCO OpenServer 5.0.7/3.2's strings.h defines strcasecmp with | |
58 | # "unsigned size_t". We cannot use -Werror for net/libfetch. | 58 | # "unsigned size_t". We cannot use -Werror for net/libfetch. | |
59 | MAKE_FLAGS+= NOGCCERROR=yes | 59 | MAKE_FLAGS+= NOGCCERROR=yes | |
60 | .endif | 60 | .endif | |
61 | 61 | |||
62 | .if defined(_PKGSRC_BARRIER) && empty(USE_CROSS_COMPILE:M[yY][eE][sS]) | 62 | .if defined(_PKGSRC_BARRIER) && empty(USE_CROSS_COMPILE:M[yY][eE][sS]) | |
63 | PKG_ADD_CMD= ${WRKSRC}/add/pkg_add | 63 | PKG_ADD_CMD= ${WRKSRC}/add/pkg_add | |
64 | PKG_CREATE_CMD= ${WRKSRC}/create/pkg_create | 64 | PKG_CREATE_CMD= ${WRKSRC}/create/pkg_create | |
65 | PKG_DELETE_CMD= ${WRKSRC}/delete/pkg_delete | 65 | PKG_DELETE_CMD= ${WRKSRC}/delete/pkg_delete | |
66 | # | 66 | # | |
67 | # Special case for dependency checking in 'non-bootstrap' builds: | 67 | # Special case for dependency checking in 'non-bootstrap' builds: | |
68 | # don't redefine 'pkg_info' if it already exists. | 68 | # don't redefine 'pkg_info' if it already exists. | |
69 | # | 69 | # | |
70 | . if defined(PKG_INFO_CMD) && !exists(${PKG_INFO_CMD}) | 70 | . if defined(PKG_INFO_CMD) && !exists(${PKG_INFO_CMD}) | |
71 | PKG_INFO_CMD= ${WRKSRC}/info/pkg_info | 71 | PKG_INFO_CMD= ${WRKSRC}/info/pkg_info | |
72 | . endif | 72 | . endif | |
73 | .endif | 73 | .endif | |
74 | 74 | |||
75 | CPPFLAGS+= -D_LARGEFILE_SOURCE -D_LARGE_FILES | 75 | CPPFLAGS+= -D_LARGEFILE_SOURCE -D_LARGE_FILES | |
76 | CPPFLAGS+= -D_FILE_OFFSET_BITS=64 | 76 | CPPFLAGS+= -D_FILE_OFFSET_BITS=64 | |
77 | 77 | |||
78 | CPPFLAGS+= -DDEF_UMASK=${DEF_UMASK} | 78 | CPPFLAGS+= -DDEF_UMASK=${DEF_UMASK} | |
79 | 79 | |||
80 | MAKE_ENV+= PKGSRC_MACHINE_ARCH=${MACHINE_ARCH} | 80 | MAKE_ENV+= PKGSRC_MACHINE_ARCH=${MACHINE_ARCH} | |
81 | MAKE_ENV+= OPSYS=${OPSYS} | 81 | MAKE_ENV+= OPSYS=${OPSYS} | |
82 | MAKE_ENV+= CATMAN_SECTION_SUFFIX=${CATMAN_SECTION_SUFFIX:Q} | 82 | MAKE_ENV+= CATMAN_SECTION_SUFFIX=${CATMAN_SECTION_SUFFIX:Q} | |
83 | MAKE_ENV+= MANINSTALL=${MANINSTALL:Q} | 83 | MAKE_ENV+= MANINSTALL=${MANINSTALL:Q} | |
84 | 84 | |||
85 | PKG_DBDIR?= ${PREFIX}/pkgdb | 85 | PKG_DBDIR?= ${PREFIX}/pkgdb | |
86 | EGDIR= ${PREFIX}/share/examples/pkg_install | 86 | EGDIR= ${PREFIX}/share/examples/pkg_install | |
87 | 87 | |||
88 | PLIST_SUBST+= PKG_DBDIR=${PKG_DBDIR} | 88 | PLIST_SUBST+= PKG_DBDIR=${PKG_DBDIR} | |
89 | 89 | |||
90 | DEINSTALL_SRC= ${PKGDIR}/DEINSTALL | 90 | DEINSTALL_SRC= ${PKGDIR}/DEINSTALL | |
91 | INSTALL_SRC= ${PKGDIR}/INSTALL | 91 | INSTALL_SRC= ${PKGDIR}/INSTALL | |
92 | FILES_SUBST+= PKG_DBDIR=${PKG_DBDIR} \ | 92 | FILES_SUBST+= PKG_DBDIR=${PKG_DBDIR} \ | |
93 | PKG_TOOLS_BIN=${PKG_TOOLS_BIN:Q} \ | 93 | PKG_TOOLS_BIN=${PKG_TOOLS_BIN:Q} \ | |
94 | MKDIR=${MKDIR:Q} | 94 | MKDIR=${MKDIR:Q} | |
95 | 95 | |||
96 | .include "../../mk/compiler.mk" | 96 | .include "../../mk/compiler.mk" | |
97 | 97 | |||
98 | .if !empty(CC_VERSION:Mclang*) | 98 | .if !empty(CC_VERSION:Mclang*) | |
99 | MAKE_FLAGS+= ACTIVE_CC=clang | 99 | MAKE_FLAGS+= ACTIVE_CC=clang | |
100 | .endif | 100 | .endif | |
101 | 101 | |||
102 | VERSION!= ${AWK} '/PKGTOOLS_VERSION/ {print $$3}' \ | 102 | VERSION!= ${AWK} '/PKGTOOLS_VERSION/ {print $$3}' \ | |
103 | ${FILESDIR}/lib/version.h | 103 | ${FILESDIR}/lib/version.h | |
104 | 104 | |||
105 | # Requires 3.x filter API and bugfixes. | 105 | # Requires 3.x filter API and bugfixes. | |
106 | BUILDLINK_API_DEPENDS.libarchive+= libarchive>=3.3.1 | 106 | BUILDLINK_API_DEPENDS.libarchive+= libarchive>=3.3.1 | |
107 | 107 | |||
108 | .include "../../archivers/bzip2/builtin.mk" | 108 | .include "../../archivers/bzip2/builtin.mk" | |
109 | .include "../../archivers/xz/builtin.mk" | 109 | .include "../../archivers/xz/builtin.mk" | |
110 | .include "../../archivers/libarchive/builtin.mk" | 110 | .include "../../archivers/libarchive/builtin.mk" | |
111 | .include "../../devel/zlib/builtin.mk" | 111 | .include "../../devel/zlib/builtin.mk" | |
112 | .include "../../security/openssl/builtin.mk" | 112 | .include "../../security/openssl/builtin.mk" | |
113 | 113 | |||
114 | .include "options.mk" | 114 | .include "options.mk" | |
115 | 115 | |||
116 | .if empty(USE_BUILTIN.bzip2:M[yY][eE][sS]) || \ | 116 | .if empty(USE_BUILTIN.bzip2:M[yY][eE][sS]) || \ | |
117 | empty(USE_BUILTIN.zlib:M[yY][eE][sS]) | 117 | empty(USE_BUILTIN.zlib:M[yY][eE][sS]) | |
118 | USE_BUILTIN.libarchive= no | 118 | USE_BUILTIN.libarchive= no | |
119 | .endif | 119 | .endif | |
120 | 120 | |||
121 | FILESDIR.bzip2?= ${.CURDIR}/../../archivers/bzip2/files | 121 | FILESDIR.bzip2?= ${.CURDIR}/../../archivers/bzip2/files | |
122 | FILESDIR.libarchive?= ${.CURDIR}/../../archivers/libarchive/files | 122 | FILESDIR.libarchive?= ${.CURDIR}/../../archivers/libarchive/files | |
123 | FILESDIR.zlib?= ${.CURDIR}/../../devel/zlib/files | 123 | FILESDIR.zlib?= ${.CURDIR}/../../devel/zlib/files | |
124 | FILESDIR.libfetch?= ${.CURDIR}/../../net/libfetch/files | 124 | FILESDIR.libfetch?= ${.CURDIR}/../../net/libfetch/files | |
125 | FILESDIR.netpgpverify?= ${.CURDIR}/../../security/netpgpverify/files | 125 | FILESDIR.netpgpverify?= ${.CURDIR}/../../security/netpgpverify/files | |
126 | 126 | |||
127 | .if empty(USE_BUILTIN.bzip2:M[yY][eE][sS]) | 127 | .if empty(USE_BUILTIN.bzip2:M[yY][eE][sS]) | |
128 | CPPFLAGS+= -I${WRKDIR}/bzip2 | 128 | CPPFLAGS+= -I${WRKDIR}/bzip2 | |
129 | LDFLAGS+= -L${WRKDIR}/bzip2 | 129 | LDFLAGS+= -L${WRKDIR}/bzip2 | |
130 | .endif | 130 | .endif | |
131 | .if empty(USE_BUILTIN.zlib:M[yY][eE][sS]) | 131 | .if empty(USE_BUILTIN.zlib:M[yY][eE][sS]) | |
132 | CPPFLAGS+= -I${WRKDIR}/zlib | 132 | CPPFLAGS+= -I${WRKDIR}/zlib | |
133 | LDFLAGS+= -L${WRKDIR}/zlib | 133 | LDFLAGS+= -L${WRKDIR}/zlib | |
134 | .endif | 134 | .endif | |
135 | .if empty(USE_BUILTIN.libarchive:M[yY][eE][sS]) | 135 | .if empty(USE_BUILTIN.libarchive:M[yY][eE][sS]) | |
136 | CPPFLAGS+= -I${WRKDIR}/libarchive/libarchive | 136 | CPPFLAGS+= -I${WRKDIR}/libarchive/libarchive | |
137 | LDFLAGS+= -L${WRKDIR}/libarchive/.libs | 137 | LDFLAGS+= -L${WRKDIR}/libarchive/.libs | |
138 | 138 | |||
139 | # Only use XZ if we actually have builtin support for it. Some systems | 139 | # Only use XZ if we actually have builtin support for it. Some systems | |
140 | # install the header, but without usable library or prefer to not use | 140 | # install the header, but without usable library or prefer to not use | |
141 | # the system version, so give them some control. | 141 | # the system version, so give them some control. | |
142 | . if empty(USE_BUILTIN.xz:M[Yy][Ee][Ss]) | 142 | . if empty(USE_BUILTIN.xz:M[Yy][Ee][Ss]) | |
143 | LIBARCHIVE_CONFIGURE_ARGS+= --without-lzma | 143 | LIBARCHIVE_CONFIGURE_ARGS+= --without-lzma | |
144 | . endif | 144 | . endif | |
145 | 145 | |||
146 | LIBARCHIVE_LIBS= ${SED} -n -e 's/^Libs.private://p' \ | 146 | LIBARCHIVE_LIBS= ${SED} -n -e 's/^Libs.private://p' \ | |
147 | ${WRKDIR}/libarchive/build/pkgconfig/libarchive.pc 2>/dev/null || echo | 147 | ${WRKDIR}/libarchive/build/pkgconfig/libarchive.pc 2>/dev/null || echo | |
148 | LIBS+= ${LIBARCHIVE_LIBS:sh} | 148 | LIBS+= ${LIBARCHIVE_LIBS:sh} | |
149 | 149 | |||
150 | CONFIG_GUESS_OVERRIDE+= ${WRKDIR}/libarchive/build/autoconf/config.guess \ | 150 | CONFIG_GUESS_OVERRIDE+= ${WRKDIR}/libarchive/build/autoconf/config.guess \ | |
151 | ${WRKSRC}/config.guess | 151 | ${WRKSRC}/config.guess | |
152 | CONFIG_SUB_OVERRIDE+= ${WRKDIR}/libarchive/build/autoconf/config.sub \ | 152 | CONFIG_SUB_OVERRIDE+= ${WRKDIR}/libarchive/build/autoconf/config.sub \ | |
153 | ${WRKSRC}/config.sub | 153 | ${WRKSRC}/config.sub | |
154 | 154 | |||
155 | CPPFLAGS.Cygwin+= -DLIBARCHIVE_STATIC | 155 | CPPFLAGS.Cygwin+= -DLIBARCHIVE_STATIC | |
156 | 156 | |||
157 | # Make sure that the linker used our static library instead of the | 157 | # Make sure that the linker used our static library instead of the | |
158 | # (outdated) dynamic library "/usr/lib/libarchive.dylib". | 158 | # (outdated) dynamic library "/usr/lib/libarchive.dylib". | |
159 | LDFLAGS.Darwin+= -Wl,-search_paths_first | 159 | LDFLAGS.Darwin+= -Wl,-search_paths_first | |
160 | 160 | |||
161 | # workaround for pkg/45491 | 161 | # workaround for pkg/45491 | |
162 | CONFIGURE_ENV.SunOS+= ac_cv_header_ext2fs_ext2_fs_h=no | 162 | CONFIGURE_ENV.SunOS+= ac_cv_header_ext2fs_ext2_fs_h=no | |
163 | 163 | |||
164 | # Hack to make sure that the libarchive version is replaced | 164 | # Hack to make sure that the libarchive version is replaced | |
165 | pre-configure: config-guess-override config-sub-override | 165 | pre-configure: config-guess-override config-sub-override | |
166 | .endif | 166 | .endif | |
167 | CPPFLAGS+= -I${WRKDIR}/libfetch | 167 | CPPFLAGS+= -I${WRKDIR}/libfetch | |
168 | LDFLAGS+= -L${WRKDIR}/libfetch | 168 | LDFLAGS+= -L${WRKDIR}/libfetch | |
169 | # Avoid duplicate and conflicting headers, pull in any we need | 169 | # Avoid duplicate and conflicting headers, pull in any we need | |
170 | # directly with <netpgpg/*.h> | 170 | # directly with <netpgpg/*.h> | |
171 | CPPFLAGS+= -I${WRKDIR} | 171 | CPPFLAGS+= -I${WRKDIR} | |
172 | LDFLAGS+= -L${WRKDIR}/netpgp | 172 | LDFLAGS+= -L${WRKDIR}/netpgp | |
173 | 173 | |||
174 | CONFIGURE_ENV+= LIBS=${LIBS:Q} | 174 | CONFIGURE_ENV+= LIBS=${LIBS:Q} | |
175 | 175 | |||
176 | do-extract: | 176 | do-extract: | |
177 | @${CP} -R ${FILESDIR} ${WRKSRC} | 177 | @${CP} -R ${FILESDIR} ${WRKSRC} | |
178 | .if empty(USE_BUILTIN.bzip2:M[yY][eE][sS]) | 178 | .if empty(USE_BUILTIN.bzip2:M[yY][eE][sS]) | |
179 | @${CP} -R ${FILESDIR.bzip2} ${WRKDIR}/bzip2 | 179 | @${CP} -R ${FILESDIR.bzip2} ${WRKDIR}/bzip2 | |
180 | .endif | 180 | .endif | |
181 | .if empty(USE_BUILTIN.zlib:M[yY][eE][sS]) | 181 | .if empty(USE_BUILTIN.zlib:M[yY][eE][sS]) | |
182 | @${CP} -R ${FILESDIR.zlib} ${WRKDIR}/zlib | 182 | @${CP} -R ${FILESDIR.zlib} ${WRKDIR}/zlib | |
183 | .endif | 183 | .endif | |
184 | .if empty(USE_BUILTIN.libarchive:M[yY][eE][sS]) | 184 | .if empty(USE_BUILTIN.libarchive:M[yY][eE][sS]) | |
185 | @${CP} -R ${FILESDIR.libarchive} ${WRKDIR}/libarchive | 185 | @${CP} -R ${FILESDIR.libarchive} ${WRKDIR}/libarchive | |
186 | .endif | 186 | .endif | |
187 | @${CP} -R ${FILESDIR.libfetch} ${WRKDIR}/libfetch | 187 | @${CP} -R ${FILESDIR.libfetch} ${WRKDIR}/libfetch | |
188 | @${CP} -R ${FILESDIR.netpgpverify} ${WRKDIR}/netpgp | 188 | @${CP} -R ${FILESDIR.netpgpverify} ${WRKDIR}/netpgp | |
189 | 189 | |||
190 | pre-configure: | 190 | pre-configure: | |
191 | .if empty(USE_BUILTIN.bzip2:M[yY][eE][sS]) | 191 | .if empty(USE_BUILTIN.bzip2:M[yY][eE][sS]) | |
192 | cd ${WRKDIR}/bzip2 && ${BUILD_MAKE_CMD} libbz2.a | 192 | cd ${WRKDIR}/bzip2 && ${BUILD_MAKE_CMD} libbz2.a | |
193 | .endif | 193 | .endif | |
194 | .if empty(USE_BUILTIN.zlib:M[yY][eE][sS]) | 194 | .if empty(USE_BUILTIN.zlib:M[yY][eE][sS]) | |
195 | cd ${WRKDIR}/zlib && ${BUILD_MAKE_CMD} libz.a | 195 | cd ${WRKDIR}/zlib && ${BUILD_MAKE_CMD} libz.a | |
196 | .endif | 196 | .endif | |
197 | .if empty(USE_BUILTIN.libarchive:M[yY][eE][sS]) | 197 | .if empty(USE_BUILTIN.libarchive:M[yY][eE][sS]) | |
198 | cd ${WRKDIR}/libarchive && ${SETENV} ${_CONFIGURE_SCRIPT_ENV} \ | 198 | cd ${WRKDIR}/libarchive && ${SETENV} ${_CONFIGURE_SCRIPT_ENV} \ | |
199 | ${CONFIG_SHELL} ${CONFIG_SHELL_FLAGS} ./configure \ | 199 | ${CONFIG_SHELL} ${CONFIG_SHELL_FLAGS} ./configure \ | |
200 | --disable-bsdcpio --disable-bsdtar --disable-shared \ | 200 | --disable-bsdcpio --disable-bsdtar --disable-shared \ | |
201 | --disable-dependency-tracking --without-expat \ | 201 | --disable-dependency-tracking --without-expat \ | |
202 | --disable-maintainer-mode \ | 202 | --disable-maintainer-mode \ | |
203 | --without-iconv --without-lzo2 --without-nettle \ | 203 | --without-iconv --without-lzo2 --without-nettle \ | |
204 | --without-xml2 --without-lz4 --without-zstd \ | 204 | --without-xml2 --without-lz4 --without-zstd \ | |
205 | ${LIBARCHIVE_CONFIGURE_ARGS} | 205 | ${LIBARCHIVE_CONFIGURE_ARGS} | |
206 | cd ${WRKDIR}/libarchive && ${BUILD_MAKE_CMD} | 206 | cd ${WRKDIR}/libarchive && ${BUILD_MAKE_CMD} | |
207 | .endif | 207 | .endif | |
208 | cd ${WRKDIR}/libfetch && ${TOUCH} fetch.cat3 && \ | 208 | cd ${WRKDIR}/libfetch && ${TOUCH} fetch.cat3 && \ | |
209 | ${SETENV} ${MAKE_ENV} ${BSD_MAKE_ENV} \ | 209 | ${SETENV} ${MAKE_ENV} ${BSD_MAKE_ENV} \ | |
210 | ${MAKE_PROGRAM} ${MAKE_FLAGS} ${BUILD_MAKE_FLAGS} \ | 210 | ${MAKE_PROGRAM} ${MAKE_FLAGS} ${BUILD_MAKE_FLAGS} \ | |
211 | -f ${MAKE_FILE} depend all | 211 | -f ${MAKE_FILE} depend all | |
212 | cd ${WRKDIR}/netpgp && ${CP} Makefile.lib.in Makefile.in && \ | 212 | cd ${WRKDIR}/netpgp && ${CP} Makefile.lib.in Makefile.in && \ | |
213 | ${CONFIG_SHELL} ${CONFIG_SHELL_FLAGS} ./configure && \ | 213 | ${CONFIG_SHELL} ${CONFIG_SHELL_FLAGS} ./configure && \ | |
214 | ${SETENV} ${MAKE_ENV} ${BSD_MAKE_ENV} ${MAKE_PROGRAM} \ | 214 | ${SETENV} ${MAKE_ENV} ${BSD_MAKE_ENV} ${MAKE_PROGRAM} \ | |
215 | ${MAKE_FLAGS} ${BUILD_MAKE_FLAGS} -f ${MAKE_FILE} all | 215 | ${MAKE_FLAGS} ${BUILD_MAKE_FLAGS} -f ${MAKE_FILE} all | |
216 | 216 | |||
217 | # XXX Reverse the order that update does things since | 217 | # XXX Reverse the order that update does things since | |
218 | # XXX we need pkg_delete built before we can deinstall. | 218 | # XXX we need pkg_delete built before we can deinstall. | |
219 | # XXX This should probably be the default order for all packages. | 219 | # XXX This should probably be the default order for all packages. | |
220 | update: | 220 | update: | |
221 | ${MAKE} | 221 | ${MAKE} | |
222 | ${MAKE} deinstall _UPDATE_RUNNING=YES | 222 | ${MAKE} deinstall _UPDATE_RUNNING=YES | |
223 | ${MAKE} ${UPDATE_TARGET} | 223 | ${MAKE} ${UPDATE_TARGET} | |
224 | ${MAKE} clean | 224 | ${MAKE} clean | |
225 | 225 | |||
226 | update-catpages: | 226 | update-catpages: | |
227 | for f in lib/pkgsrc.7 add/pkg_add.1 admin/pkg_admin.1 \ | 227 | for f in lib/pkgsrc.7 add/pkg_add.1 admin/pkg_admin.1 \ | |
228 | create/pkg_create.1 delete/pkg_delete.1 info/pkg_info.1 \ | 228 | create/pkg_create.1 delete/pkg_delete.1 info/pkg_info.1 \ | |
229 | lib/pkg_summary.5 lib/pkgsrc.7; do \ | 229 | lib/pkg_summary.5 lib/pkgsrc.7; do \ | |
230 | mandoc -I os=pkgsrc -Tascii ${FILESDIR}/$$f > \ | 230 | mandoc -I os=pkgsrc -Tascii ${FILESDIR}/$$f > \ | |
231 | ${FILESDIR}/$${f%%.[157]}.cat; \ | 231 | ${FILESDIR}/$${f%%.[157]}.cat; \ | |
232 | done | 232 | done | |
233 | mandoc -I os=pkgsrc -Tascii ${FILESDIR}/lib/pkg_install.conf.5.in > \ | 233 | mandoc -I os=pkgsrc -Tascii ${FILESDIR}/lib/pkg_install.conf.5.in > \ | |
234 | ${FILESDIR}/lib/pkg_install.conf.cat.in | 234 | ${FILESDIR}/lib/pkg_install.conf.cat.in | |
235 | 235 | |||
236 | .include "../../mk/bsd.pkg.mk" | 236 | .include "../../mk/bsd.pkg.mk" |
@@ -1,73 +1,73 @@ | @@ -1,73 +1,73 @@ | |||
1 | # $NetBSD: Makefile,v 1.128 2023/11/08 13:20:39 wiz Exp $ | 1 | # $NetBSD: Makefile,v 1.128.2.1 2024/01/13 12:49:09 bsiegert Exp $ | |
2 | 2 | |||
3 | DISTNAME= pkgin-23.8.1 | 3 | DISTNAME= pkgin-23.8.1 | |
4 | PKGREVISION= 2 | 4 | PKGREVISION= 3 | |
5 | CATEGORIES= pkgtools | 5 | CATEGORIES= pkgtools | |
6 | MASTER_SITES= ${MASTER_SITE_GITHUB:=NetBSDfr/} | 6 | MASTER_SITES= ${MASTER_SITE_GITHUB:=NetBSDfr/} | |
7 | GITHUB_TAG= v${PKGVERSION_NOREV} | 7 | GITHUB_TAG= v${PKGVERSION_NOREV} | |
8 | 8 | |||
9 | MAINTAINER= jperkin@pkgsrc.org | 9 | MAINTAINER= jperkin@pkgsrc.org | |
10 | HOMEPAGE= http://pkgin.net/ | 10 | HOMEPAGE= http://pkgin.net/ | |
11 | COMMENT= Apt / yum like tool for managing pkgsrc binary packages | 11 | COMMENT= Apt / yum like tool for managing pkgsrc binary packages | |
12 | LICENSE= modified-bsd | 12 | LICENSE= modified-bsd | |
13 | 13 | |||
14 | EGDIR= ${PREFIX}/share/examples/${PKGBASE} | 14 | EGDIR= ${PREFIX}/share/examples/${PKGBASE} | |
15 | CONF_FILES= ${EGDIR}/repositories.conf.example \ | 15 | CONF_FILES= ${EGDIR}/repositories.conf.example \ | |
16 | ${PKG_SYSCONFDIR}/${PKGBASE}/repositories.conf | 16 | ${PKG_SYSCONFDIR}/${PKGBASE}/repositories.conf | |
17 | 17 | |||
18 | OWN_DIRS+= ${PKG_SYSCONFDIR}/${PKGBASE} | 18 | OWN_DIRS+= ${PKG_SYSCONFDIR}/${PKGBASE} | |
19 | OWN_DIRS+= ${VARBASE}/db/pkgin | 19 | OWN_DIRS+= ${VARBASE}/db/pkgin | |
20 | 20 | |||
21 | INSTALLATION_DIRS+= bin ${PKGMANDIR}/man1 ${EGDIR} | 21 | INSTALLATION_DIRS+= bin ${PKGMANDIR}/man1 ${EGDIR} | |
22 | 22 | |||
23 | BUILD_DEFS+= PKGIN_REPOSITORY_URL | 23 | BUILD_DEFS+= PKGIN_REPOSITORY_URL | |
24 | BUILD_DEFS+= VARBASE | 24 | BUILD_DEFS+= VARBASE | |
25 | 25 | |||
26 | GNU_CONFIGURE= yes | 26 | GNU_CONFIGURE= yes | |
27 | CONFIGURE_ARGS+= --disable-maintainer-mode | 27 | CONFIGURE_ARGS+= --disable-maintainer-mode | |
28 | CONFIGURE_ARGS+= --sysconfdir=${PKG_SYSCONFDIR} | 28 | CONFIGURE_ARGS+= --sysconfdir=${PKG_SYSCONFDIR} | |
29 | CONFIGURE_ARGS+= --with-dbdir=${VARBASE}/db/pkgin | 29 | CONFIGURE_ARGS+= --with-dbdir=${VARBASE}/db/pkgin | |
30 | CONFIGURE_ARGS+= --with-machine-arch=${MACHINE_ARCH} | 30 | CONFIGURE_ARGS+= --with-machine-arch=${MACHINE_ARCH} | |
31 | CONFIGURE_ARGS+= --with-pkg-install=${PKG_TOOLS_BIN} | 31 | CONFIGURE_ARGS+= --with-pkg-install=${PKG_TOOLS_BIN} | |
32 | CONFIGURE_ARGS+= --with-libarchive=${BUILDLINK_PREFIX.libarchive} | 32 | CONFIGURE_ARGS+= --with-libarchive=${BUILDLINK_PREFIX.libarchive} | |
33 | CONFIGURE_ARGS+= --with-libfetch=${BUILDLINK_PREFIX.libfetch} | 33 | CONFIGURE_ARGS+= --with-libfetch=${BUILDLINK_PREFIX.libfetch} | |
34 | CONFIGURE_ARGS+= --with-openssl=${BUILDLINK_PREFIX.openssl} | 34 | CONFIGURE_ARGS+= --with-openssl=${BUILDLINK_PREFIX.openssl} | |
35 | CONFIGURE_ARGS+= --with-sqlite3=${BUILDLINK_PREFIX.sqlite3} | 35 | CONFIGURE_ARGS+= --with-sqlite3=${BUILDLINK_PREFIX.sqlite3} | |
36 | 36 | |||
37 | USE_FEATURES= nbcompat | 37 | USE_FEATURES= nbcompat | |
38 | 38 | |||
39 | .include "../../mk/bsd.prefs.mk" | 39 | .include "../../mk/bsd.prefs.mk" | |
40 | 40 | |||
41 | SUBST_CLASSES.NetBSD+= osrel | 41 | SUBST_CLASSES.NetBSD+= osrel | |
42 | SUBST_STAGE.osrel= pre-configure | 42 | SUBST_STAGE.osrel= pre-configure | |
43 | SUBST_MESSAGE.osrel= Adjusting repository OS release | 43 | SUBST_MESSAGE.osrel= Adjusting repository OS release | |
44 | SUBST_FILES.osrel= REPOSITORIES | 44 | SUBST_FILES.osrel= REPOSITORIES | |
45 | SUBST_SED.osrel= -e "s|@OSREL@|${OS_VERSION:C/_.*//}|" | 45 | SUBST_SED.osrel= -e "s|@OSREL@|${OS_VERSION:C/_.*//}|" | |
46 | 46 | |||
47 | CFLAGS.SunOS+= -D_FILE_OFFSET_BITS=64 | 47 | CFLAGS.SunOS+= -D_FILE_OFFSET_BITS=64 | |
48 | 48 | |||
49 | DEPENDS+= pkg_install>=20200701:../../pkgtools/pkg_install | 49 | DEPENDS+= pkg_install>=20200701:../../pkgtools/pkg_install | |
50 | 50 | |||
51 | .include "options.mk" | 51 | .include "options.mk" | |
52 | 52 | |||
53 | # those have official repositories | 53 | # those have official repositories | |
54 | .if !empty(PKGIN_REPOSITORY_URL) | 54 | .if !empty(PKGIN_REPOSITORY_URL) | |
55 | pre-install: | 55 | pre-install: | |
56 | ${ECHO} ${PKGIN_REPOSITORY_URL} >> ${WRKSRC}/repositories.conf | 56 | ${ECHO} ${PKGIN_REPOSITORY_URL} >> ${WRKSRC}/repositories.conf | |
57 | .elif ${OPSYS} == "NetBSD" || ${OPSYS} == "DragonFly" || ${OPSYS} == "Minix" | 57 | .elif ${OPSYS} == "NetBSD" || ${OPSYS} == "DragonFly" || ${OPSYS} == "Minix" | |
58 | pre-install: | 58 | pre-install: | |
59 | ${GREP} -i ${OPSYS} ${WRKSRC}/REPOSITORIES >> \ | 59 | ${GREP} -i ${OPSYS} ${WRKSRC}/REPOSITORIES >> \ | |
60 | ${WRKSRC}/repositories.conf | 60 | ${WRKSRC}/repositories.conf | |
61 | .endif | 61 | .endif | |
62 | 62 | |||
63 | post-install: | 63 | post-install: | |
64 | ${INSTALL_DATA} ${WRKSRC}/repositories.conf \ | 64 | ${INSTALL_DATA} ${WRKSRC}/repositories.conf \ | |
65 | ${DESTDIR}${EGDIR}/repositories.conf.example | 65 | ${DESTDIR}${EGDIR}/repositories.conf.example | |
66 | ${INSTALL_DATA} ${WRKSRC}/preferred.conf \ | 66 | ${INSTALL_DATA} ${WRKSRC}/preferred.conf \ | |
67 | ${DESTDIR}${EGDIR}/preferred.conf.example | 67 | ${DESTDIR}${EGDIR}/preferred.conf.example | |
68 | 68 | |||
69 | .include "../../archivers/libarchive/buildlink3.mk" | 69 | .include "../../archivers/libarchive/buildlink3.mk" | |
70 | .include "../../databases/sqlite3/buildlink3.mk" | 70 | .include "../../databases/sqlite3/buildlink3.mk" | |
71 | .include "../../net/libfetch/buildlink3.mk" | 71 | .include "../../net/libfetch/buildlink3.mk" | |
72 | .include "../../security/openssl/buildlink3.mk" | 72 | .include "../../security/openssl/buildlink3.mk" | |
73 | .include "../../mk/bsd.pkg.mk" | 73 | .include "../../mk/bsd.pkg.mk" |