Sat Jan 13 12:49:10 2024 UTC (154d)
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.)


(bsiegert)
diff -r1.64 -r1.64.2.1 pkgsrc/net/libfetch/Makefile
diff -r1.31 -r1.31.58.1 pkgsrc/net/libfetch/files/common.c
diff -r1.17 -r1.17.62.1 pkgsrc/net/libfetch/files/fetch.3
diff -r1.237 -r1.237.2.1 pkgsrc/pkgtools/pkg_install/Makefile
diff -r1.128 -r1.128.2.1 pkgsrc/pkgtools/pkgin/Makefile

cvs diff -r1.64 -r1.64.2.1 pkgsrc/net/libfetch/Makefile (switch to unified diff)

--- pkgsrc/net/libfetch/Makefile 2023/10/24 22:10:22 1.64
+++ pkgsrc/net/libfetch/Makefile 2024/01/13 12:49:09 1.64.2.1
@@ -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
3DISTNAME= libfetch-2.39 3DISTNAME= libfetch-2.39
4PKGREVISION= 2 4PKGREVISION= 3
5CATEGORIES= net 5CATEGORIES= net
6MASTER_SITES= # empty 6MASTER_SITES= # empty
7DISTFILES= # empty 7DISTFILES= # empty
8 8
9MAINTAINER= pkgsrc-users@NetBSD.org 9MAINTAINER= pkgsrc-users@NetBSD.org
10HOMEPAGE= https://www.FreeBSD.org/ 10HOMEPAGE= https://www.FreeBSD.org/
11COMMENT= Library to access HTTP/FTP server 11COMMENT= Library to access HTTP/FTP server
12LICENSE= modified-bsd 12LICENSE= modified-bsd
13 13
14USE_FEATURES= nbcompat 14USE_FEATURES= nbcompat
15 15
16USE_BSD_MAKEFILE= yes 16USE_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)
20CHECK_PERMS= no 20CHECK_PERMS= no
21.endif 21.endif
22 22
23INSTALLATION_DIRS= include lib ${PKGMANDIR}/cat3 ${PKGMANDIR}/man3 23INSTALLATION_DIRS= include lib ${PKGMANDIR}/cat3 ${PKGMANDIR}/man3
24 24
25BUILD_TARGET= depend all 25BUILD_TARGET= depend all
26INSTALL_TARGET= install includes 26INSTALL_TARGET= install includes
27 27
28do-extract: 28do-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"

cvs diff -r1.31 -r1.31.58.1 pkgsrc/net/libfetch/files/common.c (switch to unified diff)

--- pkgsrc/net/libfetch/files/common.c 2016/10/20 21:25:57 1.31
+++ pkgsrc/net/libfetch/files/common.c 2024/01/13 12:49:09 1.31.58.1
@@ -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 */
81static struct fetcherr netdb_errlist[] = { 85static 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 */
96static struct fetcherr * 100static struct fetcherr *
97fetch_finderr(struct fetcherr *p, int e) 101fetch_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 */
107void 111void
108fetch_seterr(struct fetcherr *p, int e) 112fetch_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 */
118void 122void
119fetch_syserr(void) 123fetch_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;
172default: 176default:
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 */
182void 186void
183fetch_info(const char *fmt, ...) 187fetch_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 */
199int 203int
200fetch_default_port(const char *scheme) 204fetch_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 */
216int 220int
217fetch_default_proxy_port(const char *scheme) 221fetch_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 */
230conn_t * 234conn_t *
231fetch_reopen(int sd) 235fetch_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 */
251int 255int
252fetch_bind(int sd, int af, const char *addr) 256fetch_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 */
273conn_t * 277conn_t *
274fetch_connect(struct url *url, int af, int verbose) 278fetch_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
331static conn_t *connection_cache; 335static conn_t *connection_cache;
332static int cache_global_limit = 0; 336static int cache_global_limit = 0;
333static int cache_per_host_limit = 0; 337static 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 */
338void 342void
339fetchConnectionCacheInit(int global_limit, int per_host_limit) 343fetchConnectionCacheInit(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 */
357void 361void
358fetchConnectionCacheClose(void) 362fetchConnectionCacheClose(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 */
372conn_t * 376conn_t *
373fetch_cache_get(const struct url *url, int af) 377fetch_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 */
401void 405void
402fetch_cache_put(conn_t *conn, int (*closecb)(conn_t *)) 406fetch_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 */
438int 442int
439fetch_ssl(conn_t *conn, const struct url *URL, int verbose) 443fetch_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
501static int 511static int
502compute_timeout(const struct timeval *tv) 512compute_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 */
515ssize_t 525ssize_t
516fetch_read(conn_t *conn, char *buf, size_t len) 526fetch_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
600int 610int
601fetch_getln(conn_t *conn) 611fetch_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 */
664ssize_t 674ssize_t
665fetch_write(conn_t *conn, const void *buf, size_t len) 675fetch_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 */
746int 756int
747fetch_close(conn_t *conn) 757fetch_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
763int 773int
764fetch_add_entry(struct url_list *ue, struct url *base, const char *name, 774fetch_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
849void 859void
850fetchInitURLList(struct url_list *ue) 860fetchInitURLList(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
856int 866int
857fetchAppendURLList(struct url_list *dst, const struct url_list *src) 867fetchAppendURLList(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
890void 900void
891fetchFreeURLList(struct url_list *ue) 901fetchFreeURLList(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
904static const char * 914static const char *
905fetch_read_word(FILE *f) 915fetch_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 */
917int 927int
918fetch_netrc_auth(struct url *url) 928fetch_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 */
996int 1006int
997fetch_no_proxy_match(const char *host) 1007fetch_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
1036struct fetchIO { 1046struct 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
1043void 1053void
1044fetchIO_close(fetchIO *f) 1054fetchIO_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
1052fetchIO * 1062fetchIO *
1053fetchIO_unopen(void *io_cookie, ssize_t (*io_read)(void *, void *, size_t), 1063fetchIO_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
1071ssize_t 1081ssize_t
1072fetchIO_read(fetchIO *f, void *buf, size_t len) 1082fetchIO_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
1079ssize_t 1089ssize_t
1080fetchIO_write(fetchIO *f, const void *buf, size_t len) 1090fetchIO_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}

cvs diff -r1.17 -r1.17.62.1 pkgsrc/net/libfetch/files/fetch.3 (switch to unified diff)

--- pkgsrc/net/libfetch/files/fetch.3 2016/05/31 18:02:36 1.17
+++ pkgsrc/net/libfetch/files/fetch.3 2024/01/13 12:49:09 1.17.62.1
@@ -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
152These functions implement a high-level library for retrieving and 152These functions implement a high-level library for retrieving and
153uploading files using Uniform Resource Locators (URLs). 153uploading files using Uniform Resource Locators (URLs).
154.Pp 154.Pp
155.Fn fetchParseURL 155.Fn fetchParseURL
156takes a URL in the form of a null-terminated string and splits it into 156takes a URL in the form of a null-terminated string and splits it into
157its components function according to the Common Internet Scheme Syntax 157its components function according to the Common Internet Scheme Syntax
158detailed in RFC 1738. 158detailed in RFC 1738.
159A regular expression which produces this syntax is: 159A 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
164If the URL does not seem to begin with a scheme name, it is assumed to be a local path. 164If the URL does not seem to begin with a scheme name, it is assumed to be a local path.
165Only absolute path names are accepted. 165Only absolute path names are accepted.
166.Pp 166.Pp
167Note that some components of the URL are not necessarily relevant to 167Note that some components of the URL are not necessarily relevant to
168all URL schemes. 168all URL schemes.
169For instance, the file scheme only needs the 169For instance, the file scheme only needs the
170.Aq scheme 170.Aq scheme
171and 171and
172.Aq doc 172.Aq doc
173components. 173components.
174.Fn fetchParseURL 174.Fn fetchParseURL
175quotes any unsafe character in the URL automatically. 175quotes any unsafe character in the URL automatically.
176This is not done by 176This is not done by
177.Fn fetchMakeURL . 177.Fn fetchMakeURL .
178.Fn fetchCopyURL 178.Fn fetchCopyURL
179copies an existing 179copies an existing
180.Vt url 180.Vt url
181structure. 181structure.
182.Pp 182.Pp
183.Fn fetchMakeURL , 183.Fn fetchMakeURL ,
184.Fn fetchParseURL , 184.Fn fetchParseURL ,
185and 185and
186.Fn fetchCopyURL 186.Fn fetchCopyURL
187return a pointer to a 187return a pointer to a
188.Vt url 188.Vt url
189structure, which is defined as follows in 189structure, 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
197struct url { 197struct 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
210The pointer returned by 210The pointer returned by
211.Fn fetchMakeURL , 211.Fn fetchMakeURL ,
212.Fn fetchCopyURL , 212.Fn fetchCopyURL ,
213and 213and
214.Fn fetchParseURL 214.Fn fetchParseURL
215should be freed using 215should be freed using
216.Fn fetchFreeURL . 216.Fn fetchFreeURL .
217The size of 217The size of
218.Vt struct URL 218.Vt struct URL
219is not part of the ABI. 219is not part of the ABI.
220.Pp 220.Pp
221.Fn fetchXGetURL , 221.Fn fetchXGetURL ,
222.Fn fetchGetURL , 222.Fn fetchGetURL ,
223and 223and
224.Fn fetchPutURL 224.Fn fetchPutURL
225constitute the recommended interface to the 225constitute the recommended interface to the
226.Nm fetch 226.Nm fetch
227library. 227library.
228They examine the URL passed to them to determine the transfer 228They examine the URL passed to them to determine the transfer
229method, and call the appropriate lower-level functions to perform the 229method, and call the appropriate lower-level functions to perform the
230actual transfer. 230actual transfer.
231.Fn fetchXGetURL 231.Fn fetchXGetURL
232also returns the remote document's metadata in the 232also returns the remote document's metadata in the
233.Vt url_stat 233.Vt url_stat
234structure pointed to by the 234structure pointed to by the
235.Fa us 235.Fa us
236argument. 236argument.
237.Pp 237.Pp
238The 238The
239.Fa flags 239.Fa flags
240argument is a string of characters which specify transfer options. 240argument is a string of characters which specify transfer options.
241The 241The
242meaning of the individual flags is scheme-dependent, and is detailed 242meaning of the individual flags is scheme-dependent, and is detailed
243in the appropriate section below. 243in the appropriate section below.
244.Pp 244.Pp
245.Fn fetchStatURL 245.Fn fetchStatURL
246attempts to obtain the requested document's metadata and fill in the 246attempts to obtain the requested document's metadata and fill in the
247structure pointed to by its second argument. 247structure pointed to by its second argument.
248The 248The
249.Vt url_stat 249.Vt url_stat
250structure is defined as follows in 250structure is defined as follows in
251.In fetch.h : 251.In fetch.h :
252.Bd -literal 252.Bd -literal
253struct url_stat { 253struct 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
260If the size could not be obtained from the server, the 260If the size could not be obtained from the server, the
261.Fa size 261.Fa size
262field is set to \-1. 262field is set to \-1.
263If the modification time could not be obtained from the server, the 263If the modification time could not be obtained from the server, the
264.Fa mtime 264.Fa mtime
265field is set to the epoch. 265field is set to the epoch.
266If the access time could not be obtained from the server, the 266If the access time could not be obtained from the server, the
267.Fa atime 267.Fa atime
268field is set to the modification time. 268field is set to the modification time.
269.Pp 269.Pp
270.Fn fetchListURL 270.Fn fetchListURL
271attempts to list the contents of the directory pointed to by the URL provided. 271attempts to list the contents of the directory pointed to by the URL provided.
272The pattern can be a simple glob-like expression as hint. 272The pattern can be a simple glob-like expression as hint.
273Callers should not depend on the server to filter names. 273Callers should not depend on the server to filter names.
274If successful, it appends the list of entries to the 274If successful, it appends the list of entries to the
275.Vt url_list 275.Vt url_list
276structure. 276structure.
277The 277The
278.Vt url_list 278.Vt url_list
279structure is defined as follows in 279structure is defined as follows in
280.In fetch.h : 280.In fetch.h :
281.Bd -literal 281.Bd -literal
282struct url_list { 282struct 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
289The list should be initialized by calling 289The list should be initialized by calling
290.Fn fetchInitURLList 290.Fn fetchInitURLList
291and the entries be freed by calling 291and the entries be freed by calling
292.Fn fetchFreeURLList . 292.Fn fetchFreeURLList .
293The function 293The function
294.Fn fetchAppendURLList 294.Fn fetchAppendURLList
295can be used to append one URL lists to another. 295can be used to append one URL lists to another.
296If the 296If 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
299cache the result. 299cache the result.
300.Pp 300.Pp
301.Fn fetchStringifyURL 301.Fn fetchStringifyURL
302returns the URL as string. 302returns the URL as string.
303.Fn fetchUnquotePath 303.Fn fetchUnquotePath
304returns the path name part of the URL with any quoting undone. 304returns the path name part of the URL with any quoting undone.
305Query arguments and fragment identifiers are not included. 305Query arguments and fragment identifiers are not included.
306.Fn fetchUnquoteFilename 306.Fn fetchUnquoteFilename
307returns the last component of the path name as returned by 307returns 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 ,
311and 311and
312.Fn fetchUnquoteFilename 312.Fn fetchUnquoteFilename
313return a string that should be deallocated with 313return a string that should be deallocated with
314.Fn free 314.Fn free
315after use. 315after use.
316.Pp 316.Pp
317.Fn fetchConnectionCacheInit 317.Fn fetchConnectionCacheInit
318enables the connection cache. 318enables the connection cache.
319The first argument specifies the global limit on cached connections. 319The first argument specifies the global limit on cached connections.
320The second argument specifies the host limit. 320The second argument specifies the host limit.
321Entries are considered to specify the same host, if the host name 321Entries are considered to specify the same host, if the host name
322from the URL is identical, indepent of the address or address family. 322from the URL is identical, indepent of the address or address family.
323.Fn fetchConnectionCacheClose 323.Fn fetchConnectionCacheClose
324flushed the connection cache and closes all cached connections. 324flushed 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 ,
329and 329and
330.Fn fetchStat 330.Fn fetchStat
331are similar to 331are similar to
332.Fn fetchXGetURL , 332.Fn fetchXGetURL ,
333.Fn fetchGetURL , 333.Fn fetchGetURL ,
334.Fn fetchPutURL , 334.Fn fetchPutURL ,
335and 335and
336.Fn fetchStatURL , 336.Fn fetchStatURL ,
337except that they expect a pre-parsed URL in the form of a pointer to 337except that they expect a pre-parsed URL in the form of a pointer to
338a 338a
339.Vt struct url 339.Vt struct url
340rather than a string. 340rather than a string.
341.Pp 341.Pp
342All of the 342All of the
343.Fn fetchXGetXXX , 343.Fn fetchXGetXXX ,
344.Fn fetchGetXXX , 344.Fn fetchGetXXX ,
345and 345and
346.Fn fetchPutXXX 346.Fn fetchPutXXX
347functions return a pointer to a stream which can be used to read or 347functions return a pointer to a stream which can be used to read or
348write data from or to the requested document, respectively. 348write data from or to the requested document, respectively.
349Note that 349Note that
350although the implementation details of the individual access methods 350although the implementation details of the individual access methods
351vary, it can generally be assumed that a stream returned by one of the 351vary, it can generally be assumed that a stream returned by one of the
352.Fn fetchXGetXXX 352.Fn fetchXGetXXX
353or 353or
354.Fn fetchGetXXX 354.Fn fetchGetXXX
355functions is read-only, and that a stream returned by one of the 355functions is read-only, and that a stream returned by one of the
356.Fn fetchPutXXX 356.Fn fetchPutXXX
357functions is write-only. 357functions is write-only.
358.Sh PROTOCOL INDEPENDENT FLAGS 358.Sh PROTOCOL INDEPENDENT FLAGS
359If the 359If 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
362the content only if it is newer than 362the content only if it is newer than
363.Va last_modified . 363.Va last_modified .
364For HTTP an 364For HTTP an
365.Li If-Modified-Since 365.Li If-Modified-Since
366HTTP header is sent. 366HTTP header is sent.
367For FTP a 367For FTP a
368.Li MTDM 368.Li MTDM
369command is sent first and compared locally. 369command is sent first and compared locally.
370For FILE the source file is compared. 370For 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 ,
374and 374and
375.Fn fetchPutFile 375.Fn fetchPutFile
376provide access to documents which are files in a locally mounted file 376provide access to documents which are files in a locally mounted file
377system. 377system.
378Only the 378Only the
379.Aq document 379.Aq document
380component of the URL is used. 380component of the URL is used.
381.Pp 381.Pp
382.Fn fetchXGetFile 382.Fn fetchXGetFile
383and 383and
384.Fn fetchGetFile 384.Fn fetchGetFile
385do not accept any flags. 385do not accept any flags.
386.Pp 386.Pp
387.Fn fetchPutFile 387.Fn fetchPutFile
388accepts the 388accepts the
389.Ql a 389.Ql a
390(append to file) flag. 390(append to file) flag.
391If that flag is specified, the data written to 391If that flag is specified, the data written to
392the stream returned by 392the stream returned by
393.Fn fetchPutFile 393.Fn fetchPutFile
394will be appended to the previous contents of the file, instead of 394will be appended to the previous contents of the file, instead of
395replacing them. 395replacing them.
396.Sh FTP SCHEME 396.Sh FTP SCHEME
397.Fn fetchXGetFTP , 397.Fn fetchXGetFTP ,
398.Fn fetchGetFTP , 398.Fn fetchGetFTP ,
399and 399and
400.Fn fetchPutFTP 400.Fn fetchPutFTP
401implement the FTP protocol as described in RFC 959. 401implement the FTP protocol as described in RFC 959.
402.Pp 402.Pp
403By default 403By default
404.Nm libfetch 404.Nm libfetch
405will attempt to use passive mode first and only fallback to active mode 405will attempt to use passive mode first and only fallback to active mode
406if the server reports a syntax error. 406if the server reports a syntax error.
407If the 407If 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
410is used directly. 410is used directly.
411.Pp 411.Pp
412If the 412If 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
415default) port range instead of the high port range (see 415default) port range instead of the high port range (see
416.Xr ip 4 ) . 416.Xr ip 4 ) .
417.Pp 417.Pp
418If the 418If 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 ,
423and 423and
424.Fn fetchPutFTP 424.Fn fetchPutFTP
425will use a direct connection even if a proxy server is defined. 425will use a direct connection even if a proxy server is defined.
426.Pp 426.Pp
427If no user name or password is given, the 427If no user name or password is given, the
428.Nm fetch 428.Nm fetch
429library will attempt an anonymous login, with user name "anonymous" 429library will attempt an anonymous login, with user name "anonymous"
430and password "anonymous@\*[Lt]hostname\*[Gt]". 430and password "anonymous@\*[Lt]hostname\*[Gt]".
431.Sh HTTP SCHEME 431.Sh HTTP SCHEME
432The 432The
433.Fn fetchXGetHTTP , 433.Fn fetchXGetHTTP ,
434.Fn fetchGetHTTP , 434.Fn fetchGetHTTP ,
435and 435and
436.Fn fetchPutHTTP 436.Fn fetchPutHTTP
437functions implement the HTTP/1.1 protocol. 437functions implement the HTTP/1.1 protocol.
438With a little luck, there is 438With a little luck, there is
439even a chance that they comply with RFC 2616 and RFC 2617. 439even a chance that they comply with RFC 2616 and RFC 2617.
440.Pp 440.Pp
441If the 441If 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 ,
446and 446and
447.Fn fetchPutHTTP 447.Fn fetchPutHTTP
448will use a direct connection even if a proxy server is defined. 448will use a direct connection even if a proxy server is defined.
449.Pp 449.Pp
450Since there seems to be no good way of implementing the HTTP PUT 450Since there seems to be no good way of implementing the HTTP PUT
451method in a manner consistent with the rest of the 451method in a manner consistent with the rest of the
452.Nm fetch 452.Nm fetch
453library, 453library,
454.Fn fetchPutHTTP 454.Fn fetchPutHTTP
455is currently unimplemented. 455is currently unimplemented.
456.Sh AUTHENTICATION 456.Sh AUTHENTICATION
457Apart from setting the appropriate environment variables and 457Apart from setting the appropriate environment variables and
458specifying the user name and password in the URL or the 458specifying the user name and password in the URL or the
459.Vt struct url , 459.Vt struct url ,
460the calling program has the option of defining an authentication 460the calling program has the option of defining an authentication
461function with the following prototype: 461function 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
466The callback function should fill in the 466The callback function should fill in the
467.Fa user 467.Fa user
468and 468and
469.Fa pwd 469.Fa pwd
470fields in the provided 470fields in the provided
471.Vt struct url 471.Vt struct url
472and return 0 on success, or any other value to indicate failure. 472and return 0 on success, or any other value to indicate failure.
473.Pp 473.Pp
474To register the authentication callback, simply set 474To register the authentication callback, simply set
475.Va fetchAuthMethod 475.Va fetchAuthMethod
476to point at it. 476to point at it.
477The callback will be used whenever a site requires authentication and 477The callback will be used whenever a site requires authentication and
478the appropriate environment variables are not set. 478the appropriate environment variables are not set.
479.Pp 479.Pp
480This interface is experimental and may be subject to change. 480This interface is experimental and may be subject to change.
481.Sh RETURN VALUES 481.Sh RETURN VALUES
482.Fn fetchParseURL 482.Fn fetchParseURL
483returns a pointer to a 483returns a pointer to a
484.Vt struct url 484.Vt struct url
485containing the individual components of the URL. 485containing the individual components of the URL.
486If it is 486If it is
487unable to allocate memory, or the URL is syntactically incorrect, 487unable to allocate memory, or the URL is syntactically incorrect,
488.Fn fetchParseURL 488.Fn fetchParseURL
489returns a 489returns a
490.Dv NULL 490.Dv NULL
491pointer. 491pointer.
492.Pp 492.Pp
493The 493The
494.Fn fetchStat 494.Fn fetchStat
495functions return 0 on success and \-1 on failure. 495functions return 0 on success and \-1 on failure.
496.Pp 496.Pp
497All other functions return a stream pointer which may be used to 497All other functions return a stream pointer which may be used to
498access the requested document, or 498access the requested document, or
499.Dv NULL 499.Dv NULL
500if an error occurred. 500if an error occurred.
501.Pp 501.Pp
502The following error codes are defined in 502The 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
506Operation aborted 506Operation aborted
507.It Bq Er FETCH_AUTH 507.It Bq Er FETCH_AUTH
508Authentication failed 508Authentication failed
509.It Bq Er FETCH_DOWN 509.It Bq Er FETCH_DOWN
510Service unavailable 510Service unavailable
511.It Bq Er FETCH_EXISTS 511.It Bq Er FETCH_EXISTS
512File exists 512File exists
513.It Bq Er FETCH_FULL 513.It Bq Er FETCH_FULL
514File system full 514File system full
515.It Bq Er FETCH_INFO 515.It Bq Er FETCH_INFO
516Informational response 516Informational response
517.It Bq Er FETCH_MEMORY 517.It Bq Er FETCH_MEMORY
518Insufficient memory 518Insufficient memory
519.It Bq Er FETCH_MOVED 519.It Bq Er FETCH_MOVED
520File has moved 520File has moved
521.It Bq Er FETCH_NETWORK 521.It Bq Er FETCH_NETWORK
522Network error 522Network error
523.It Bq Er FETCH_OK 523.It Bq Er FETCH_OK
524No error 524No error
525.It Bq Er FETCH_PROTO 525.It Bq Er FETCH_PROTO
526Protocol error 526Protocol error
527.It Bq Er FETCH_RESOLV 527.It Bq Er FETCH_RESOLV
528Resolver error 528Resolver error
529.It Bq Er FETCH_SERVER 529.It Bq Er FETCH_SERVER
530Server error 530Server error
531.It Bq Er FETCH_TEMP 531.It Bq Er FETCH_TEMP
532Temporary error 532Temporary error
533.It Bq Er FETCH_TIMEOUT 533.It Bq Er FETCH_TIMEOUT
534Operation timed out 534Operation timed out
535.It Bq Er FETCH_UNAVAIL 535.It Bq Er FETCH_UNAVAIL
536File is not available 536File is not available
537.It Bq Er FETCH_UNKNOWN 537.It Bq Er FETCH_UNKNOWN
538Unknown error 538Unknown error
539.It Bq Er FETCH_URL 539.It Bq Er FETCH_URL
540Invalid URL 540Invalid URL
541.El 541.El
542.Pp 542.Pp
543The accompanying error message includes a protocol-specific error code 543The accompanying error message includes a protocol-specific error code
544and message, e.g.\& "File is not available (404 Not Found)" 544and 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
548Specifies a host name or IP address to which sockets used for outgoing 548Specifies a host name or IP address to which sockets used for outgoing
549connections will be bound. 549connections will be bound.
550.It Ev FTP_LOGIN 550.It Ev FTP_LOGIN
551Default FTP login if none was provided in the URL. 551Default FTP login if none was provided in the URL.
552.It Ev FTP_PASSIVE_MODE 552.It Ev FTP_PASSIVE_MODE
553If set to anything but 553If set to anything but
554.Ql no , 554.Ql no ,
555forces the FTP code to use passive mode. 555forces the FTP code to use passive mode.
556.It Ev FTP_PASSWORD 556.It Ev FTP_PASSWORD
557Default FTP password if the remote server requests one and none was 557Default FTP password if the remote server requests one and none was
558provided in the URL. 558provided in the URL.
559.It Ev FTP_PROXY 559.It Ev FTP_PROXY
560URL of the proxy to use for FTP requests. 560URL of the proxy to use for FTP requests.
561The document part is ignored. 561The document part is ignored.
562FTP and HTTP proxies are supported; if no scheme is specified, FTP is 562FTP and HTTP proxies are supported; if no scheme is specified, FTP is
563assumed. 563assumed.
564If the proxy is an FTP proxy, 564If the proxy is an FTP proxy,
565.Nm libfetch 565.Nm libfetch
566will send 566will send
567.Ql user@host 567.Ql user@host
568as user name to the proxy, where 568as user name to the proxy, where
569.Ql user 569.Ql user
570is the real user name, and 570is the real user name, and
571.Ql host 571.Ql host
572is the name of the FTP server. 572is the name of the FTP server.
573.Pp 573.Pp
574If this variable is set to an empty string, no proxy will be used for 574If this variable is set to an empty string, no proxy will be used for
575FTP requests, even if the 575FTP requests, even if the
576.Ev HTTP_PROXY 576.Ev HTTP_PROXY
577variable is set. 577variable is set.
578.It Ev ftp_proxy 578.It Ev ftp_proxy
579Same as 579Same as
580.Ev FTP_PROXY , 580.Ev FTP_PROXY ,
581for compatibility. 581for compatibility.
582.It Ev HTTP_AUTH 582.It Ev HTTP_AUTH
583Specifies HTTP authorization parameters as a colon-separated list of 583Specifies HTTP authorization parameters as a colon-separated list of
584items. 584items.
585The first and second item are the authorization scheme and realm 585The first and second item are the authorization scheme and realm
586respectively; further items are scheme-dependent. 586respectively; further items are scheme-dependent.
587Currently, only basic authorization is supported. 587Currently, only basic authorization is supported.
588.Pp 588.Pp
589Basic authorization requires two parameters: the user name and 589Basic authorization requires two parameters: the user name and
590password, in that order. 590password, in that order.
591.Pp 591.Pp
592This variable is only used if the server requires authorization and 592This variable is only used if the server requires authorization and
593no user name or password was specified in the URL. 593no user name or password was specified in the URL.
594.It Ev HTTP_PROXY 594.It Ev HTTP_PROXY
595URL of the proxy to use for HTTP requests. 595URL of the proxy to use for HTTP requests.
596The document part is ignored. 596The document part is ignored.
597Only HTTP proxies are supported for HTTP requests. 597Only HTTP proxies are supported for HTTP requests.
598If no port number is specified, the default is 3128. 598If no port number is specified, the default is 3128.
599.Pp 599.Pp
600Note that this proxy will also be used for FTP documents, unless the 600Note that this proxy will also be used for FTP documents, unless the
601.Ev FTP_PROXY 601.Ev FTP_PROXY
602variable is set. 602variable is set.
603.It Ev http_proxy 603.It Ev http_proxy
604Same as 604Same as
605.Ev HTTP_PROXY , 605.Ev HTTP_PROXY ,
606for compatibility. 606for compatibility.
607.It Ev HTTP_PROXY_AUTH 607.It Ev HTTP_PROXY_AUTH
608Specifies authorization parameters for the HTTP proxy in the same 608Specifies authorization parameters for the HTTP proxy in the same
609format as the 609format as the
610.Ev HTTP_AUTH 610.Ev HTTP_AUTH
611variable. 611variable.
612.Pp 612.Pp
613This variable is used if and only if connected to an HTTP proxy, and 613This variable is used if and only if connected to an HTTP proxy, and
614is ignored if a user and/or a password were specified in the proxy 614is ignored if a user and/or a password were specified in the proxy
615URL. 615URL.
616.It Ev HTTP_REFERER 616.It Ev HTTP_REFERER
617Specifies the referrer URL to use for HTTP requests. 617Specifies the referrer URL to use for HTTP requests.
618If set to 618If set to
619.Dq auto , 619.Dq auto ,
620the document URL will be used as referrer URL. 620the document URL will be used as referrer URL.
621.It Ev HTTP_USER_AGENT 621.It Ev HTTP_USER_AGENT
622Specifies the User-Agent string to use for HTTP requests. 622Specifies the User-Agent string to use for HTTP requests.
623This can be useful when working with HTTP origin or proxy servers that 623This can be useful when working with HTTP origin or proxy servers that
624differentiate between user agents. 624differentiate between user agents.
625.It Ev NETRC 625.It Ev NETRC
626Specifies a file to use instead of 626Specifies a file to use instead of
627.Pa ~/.netrc 627.Pa ~/.netrc
628to look up login names and passwords for FTP sites. 628to look up login names and passwords for FTP sites.
629See 629See
630.Xr ftp 1 630.Xr ftp 1
631for a description of the file format. 631for a description of the file format.
632This feature is experimental. 632This feature is experimental.
633.It Ev NO_PROXY 633.It Ev NO_PROXY
634Either a single asterisk, which disables the use of proxies 634Either a single asterisk, which disables the use of proxies
635altogether, or a comma- or whitespace-separated list of hosts for 635altogether, or a comma- or whitespace-separated list of hosts for
636which proxies should not be used. 636which proxies should not be used.
637.It Ev no_proxy 637.It Ev no_proxy
638Same as 638Same as
639.Ev NO_PROXY , 639.Ev NO_PROXY ,
640for compatibility. 640for compatibility.
 641.It Ev SSL_NO_VERIFY_PEER
 642If defined,
 643.Nm
 644will skip validating certificates when fetching HTTPS URLs.
641.El 645.El
642.Sh EXAMPLES 646.Sh EXAMPLES
643To access a proxy server on 647To access a proxy server on
644.Pa proxy.example.com 648.Pa proxy.example.com
645port 8080, set the 649port 8080, set the
646.Ev HTTP_PROXY 650.Ev HTTP_PROXY
647environment variable in a manner similar to this: 651environment 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
651If the proxy server requires authentication, there are 655If the proxy server requires authentication, there are
652two options available for passing the authentication data. 656two options available for passing the authentication data.
653The first method is by using the proxy URL: 657The 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
657The second method is by using the 661The second method is by using the
658.Ev HTTP_PROXY_AUTH 662.Ev HTTP_PROXY_AUTH
659environment variable: 663environment variable:
660.Bd -literal -offset indent 664.Bd -literal -offset indent
661HTTP_PROXY=http://proxy.example.com:8080 665HTTP_PROXY=http://proxy.example.com:8080
662HTTP_PROXY_AUTH=basic:*:\*[Lt]user\*[Gt]:\*[Lt]pwd\*[Gt] 666HTTP_PROXY_AUTH=basic:*:\*[Lt]user\*[Gt]:\*[Lt]pwd\*[Gt]
663.Ed 667.Ed
664.Pp 668.Pp
665To disable the use of a proxy for an HTTP server running on the local 669To disable the use of a proxy for an HTTP server running on the local
666host, define 670host, define
667.Ev NO_PROXY 671.Ev NO_PROXY
668as follows: 672as follows:
669.Bd -literal -offset indent 673.Bd -literal -offset indent
670NO_PROXY=localhost,127.0.0.1 674NO_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
725The 729The
726.Nm fetch 730.Nm fetch
727library first appeared in 731library first appeared in
728.Fx 3.0 . 732.Fx 3.0 .
729.Sh AUTHORS 733.Sh AUTHORS
730.An -nosplit 734.An -nosplit
731The 735The
732.Nm fetch 736.Nm fetch
733library was mostly written by 737library 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
735with numerous suggestions from 739with 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
738and other 742and other
739.Fx 743.Fx
740developers. 744developers.
741It replaces the older 745It replaces the older
742.Nm ftpio 746.Nm ftpio
743library written by 747library written by
744.An Poul-Henning Kamp Aq Mt phk@FreeBSD.org 748.An Poul-Henning Kamp Aq Mt phk@FreeBSD.org
745and 749and
746.An Jordan K. Hubbard Aq Mt jkh@FreeBSD.org . 750.An Jordan K. Hubbard Aq Mt jkh@FreeBSD.org .
747.Pp 751.Pp
748This manual page was written by 752This 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
751Some parts of the library are not yet implemented. 755Some parts of the library are not yet implemented.
752The most notable 756The most notable
753examples of this are 757examples of this are
754.Fn fetchPutHTTP 758.Fn fetchPutHTTP
755and FTP proxy support. 759and FTP proxy support.
756.Pp 760.Pp
757There is no way to select a proxy at run-time other than setting the 761There is no way to select a proxy at run-time other than setting the
758.Ev HTTP_PROXY 762.Ev HTTP_PROXY
759or 763or
760.Ev FTP_PROXY 764.Ev FTP_PROXY
761environment variables as appropriate. 765environment variables as appropriate.
762.Pp 766.Pp
763.Nm libfetch 767.Nm libfetch
764does not understand or obey 305 (Use Proxy) replies. 768does not understand or obey 305 (Use Proxy) replies.
765.Pp 769.Pp
766Error numbers are unique only within a certain context; the error 770Error numbers are unique only within a certain context; the error
767codes used for FTP and HTTP overlap, as do those used for resolver and 771codes used for FTP and HTTP overlap, as do those used for resolver and
768system errors. 772system errors.
769For instance, error code 202 means "Command not 773For instance, error code 202 means "Command not
770implemented, superfluous at this site" in an FTP context and 774implemented, 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
774does not check that the result of an MDTM command is a valid date. 778does not check that the result of an MDTM command is a valid date.
775.Pp 779.Pp
776The man page is incomplete, poorly written and produces badly 780The man page is incomplete, poorly written and produces badly
777formatted text. 781formatted text.
778.Pp 782.Pp
779The error reporting mechanism is unsatisfactory. 783The error reporting mechanism is unsatisfactory.
780.Pp 784.Pp
781Some parts of the code are not fully reentrant. 785Some parts of the code are not fully reentrant.

cvs diff -r1.237 -r1.237.2.1 pkgsrc/pkgtools/pkg_install/Makefile (switch to unified diff)

--- pkgsrc/pkgtools/pkg_install/Makefile 2023/10/24 22:10:40 1.237
+++ pkgsrc/pkgtools/pkg_install/Makefile 2024/01/13 12:49:09 1.237.2.1
@@ -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
9PKGNAME= pkg_install-${VERSION} 9PKGNAME= pkg_install-${VERSION}
10PKGREVISION= 1 10PKGREVISION= 2
11CATEGORIES= pkgtools 11CATEGORIES= pkgtools
12 12
13MAINTAINER= agc@NetBSD.org 13MAINTAINER= agc@NetBSD.org
14HOMEPAGE= https://www.pkgsrc.org/ 14HOMEPAGE= https://www.pkgsrc.org/
15COMMENT= Package management and administration tools for pkgsrc 15COMMENT= Package management and administration tools for pkgsrc
16LICENSE= modified-bsd 16LICENSE= modified-bsd
17 17
18BOOTSTRAP_PKG= yes 18BOOTSTRAP_PKG= yes
19SKIP_LICENSE_CHECK= yes 19SKIP_LICENSE_CHECK= yes
20 20
21CONFLICTS+= audit-packages-[0-9]* 21CONFLICTS+= audit-packages-[0-9]*
22 22
23GNU_CONFIGURE= yes 23GNU_CONFIGURE= yes
24CONFIGURE_ARGS+= --sysconfdir=${PKG_SYSCONFDIR} 24CONFIGURE_ARGS+= --sysconfdir=${PKG_SYSCONFDIR}
25CONFIGURE_ARGS+= --with-pkgdbdir=${PKG_DBDIR} 25CONFIGURE_ARGS+= --with-pkgdbdir=${PKG_DBDIR}
26 26
27USE_FEATURES= nbcompat 27USE_FEATURES= nbcompat
28 28
29NBCOMPAT_CONFIGURE_ARGS+= --enable-bsd-getopt --enable-db 29NBCOMPAT_CONFIGURE_ARGS+= --enable-bsd-getopt --enable-db
30 30
31SKIP_AUDIT_PACKAGES= yes 31SKIP_AUDIT_PACKAGES= yes
32NO_PKGTOOLS_REQD_CHECK= yes 32NO_PKGTOOLS_REQD_CHECK= yes
33PKG_PRESERVE= yes 33PKG_PRESERVE= yes
34CHECK_PERMS_SKIP= * 34CHECK_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.
52USE_NATIVE_GCC= yes 52USE_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.
59MAKE_FLAGS+= NOGCCERROR=yes 59MAKE_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])
63PKG_ADD_CMD= ${WRKSRC}/add/pkg_add 63PKG_ADD_CMD= ${WRKSRC}/add/pkg_add
64PKG_CREATE_CMD= ${WRKSRC}/create/pkg_create 64PKG_CREATE_CMD= ${WRKSRC}/create/pkg_create
65PKG_DELETE_CMD= ${WRKSRC}/delete/pkg_delete 65PKG_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})
71PKG_INFO_CMD= ${WRKSRC}/info/pkg_info 71PKG_INFO_CMD= ${WRKSRC}/info/pkg_info
72. endif 72. endif
73.endif 73.endif
74 74
75CPPFLAGS+= -D_LARGEFILE_SOURCE -D_LARGE_FILES 75CPPFLAGS+= -D_LARGEFILE_SOURCE -D_LARGE_FILES
76CPPFLAGS+= -D_FILE_OFFSET_BITS=64 76CPPFLAGS+= -D_FILE_OFFSET_BITS=64
77 77
78CPPFLAGS+= -DDEF_UMASK=${DEF_UMASK} 78CPPFLAGS+= -DDEF_UMASK=${DEF_UMASK}
79 79
80MAKE_ENV+= PKGSRC_MACHINE_ARCH=${MACHINE_ARCH} 80MAKE_ENV+= PKGSRC_MACHINE_ARCH=${MACHINE_ARCH}
81MAKE_ENV+= OPSYS=${OPSYS} 81MAKE_ENV+= OPSYS=${OPSYS}
82MAKE_ENV+= CATMAN_SECTION_SUFFIX=${CATMAN_SECTION_SUFFIX:Q} 82MAKE_ENV+= CATMAN_SECTION_SUFFIX=${CATMAN_SECTION_SUFFIX:Q}
83MAKE_ENV+= MANINSTALL=${MANINSTALL:Q} 83MAKE_ENV+= MANINSTALL=${MANINSTALL:Q}
84 84
85PKG_DBDIR?= ${PREFIX}/pkgdb 85PKG_DBDIR?= ${PREFIX}/pkgdb
86EGDIR= ${PREFIX}/share/examples/pkg_install 86EGDIR= ${PREFIX}/share/examples/pkg_install
87 87
88PLIST_SUBST+= PKG_DBDIR=${PKG_DBDIR} 88PLIST_SUBST+= PKG_DBDIR=${PKG_DBDIR}
89 89
90DEINSTALL_SRC= ${PKGDIR}/DEINSTALL 90DEINSTALL_SRC= ${PKGDIR}/DEINSTALL
91INSTALL_SRC= ${PKGDIR}/INSTALL 91INSTALL_SRC= ${PKGDIR}/INSTALL
92FILES_SUBST+= PKG_DBDIR=${PKG_DBDIR} \ 92FILES_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*)
99MAKE_FLAGS+= ACTIVE_CC=clang 99MAKE_FLAGS+= ACTIVE_CC=clang
100.endif 100.endif
101 101
102VERSION!= ${AWK} '/PKGTOOLS_VERSION/ {print $$3}' \ 102VERSION!= ${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.
106BUILDLINK_API_DEPENDS.libarchive+= libarchive>=3.3.1 106BUILDLINK_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])
118USE_BUILTIN.libarchive= no 118USE_BUILTIN.libarchive= no
119.endif 119.endif
120 120
121FILESDIR.bzip2?= ${.CURDIR}/../../archivers/bzip2/files 121FILESDIR.bzip2?= ${.CURDIR}/../../archivers/bzip2/files
122FILESDIR.libarchive?= ${.CURDIR}/../../archivers/libarchive/files 122FILESDIR.libarchive?= ${.CURDIR}/../../archivers/libarchive/files
123FILESDIR.zlib?= ${.CURDIR}/../../devel/zlib/files 123FILESDIR.zlib?= ${.CURDIR}/../../devel/zlib/files
124FILESDIR.libfetch?= ${.CURDIR}/../../net/libfetch/files 124FILESDIR.libfetch?= ${.CURDIR}/../../net/libfetch/files
125FILESDIR.netpgpverify?= ${.CURDIR}/../../security/netpgpverify/files 125FILESDIR.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])
128CPPFLAGS+= -I${WRKDIR}/bzip2 128CPPFLAGS+= -I${WRKDIR}/bzip2
129LDFLAGS+= -L${WRKDIR}/bzip2 129LDFLAGS+= -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])
132CPPFLAGS+= -I${WRKDIR}/zlib 132CPPFLAGS+= -I${WRKDIR}/zlib
133LDFLAGS+= -L${WRKDIR}/zlib 133LDFLAGS+= -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])
136CPPFLAGS+= -I${WRKDIR}/libarchive/libarchive 136CPPFLAGS+= -I${WRKDIR}/libarchive/libarchive
137LDFLAGS+= -L${WRKDIR}/libarchive/.libs 137LDFLAGS+= -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])
143LIBARCHIVE_CONFIGURE_ARGS+= --without-lzma 143LIBARCHIVE_CONFIGURE_ARGS+= --without-lzma
144. endif 144. endif
145 145
146LIBARCHIVE_LIBS= ${SED} -n -e 's/^Libs.private://p' \ 146LIBARCHIVE_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
148LIBS+= ${LIBARCHIVE_LIBS:sh} 148LIBS+= ${LIBARCHIVE_LIBS:sh}
149 149
150CONFIG_GUESS_OVERRIDE+= ${WRKDIR}/libarchive/build/autoconf/config.guess \ 150CONFIG_GUESS_OVERRIDE+= ${WRKDIR}/libarchive/build/autoconf/config.guess \
151 ${WRKSRC}/config.guess 151 ${WRKSRC}/config.guess
152CONFIG_SUB_OVERRIDE+= ${WRKDIR}/libarchive/build/autoconf/config.sub \ 152CONFIG_SUB_OVERRIDE+= ${WRKDIR}/libarchive/build/autoconf/config.sub \
153 ${WRKSRC}/config.sub 153 ${WRKSRC}/config.sub
154 154
155CPPFLAGS.Cygwin+= -DLIBARCHIVE_STATIC 155CPPFLAGS.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".
159LDFLAGS.Darwin+= -Wl,-search_paths_first 159LDFLAGS.Darwin+= -Wl,-search_paths_first
160 160
161# workaround for pkg/45491 161# workaround for pkg/45491
162CONFIGURE_ENV.SunOS+= ac_cv_header_ext2fs_ext2_fs_h=no 162CONFIGURE_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
165pre-configure: config-guess-override config-sub-override 165pre-configure: config-guess-override config-sub-override
166.endif 166.endif
167CPPFLAGS+= -I${WRKDIR}/libfetch 167CPPFLAGS+= -I${WRKDIR}/libfetch
168LDFLAGS+= -L${WRKDIR}/libfetch 168LDFLAGS+= -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>
171CPPFLAGS+= -I${WRKDIR} 171CPPFLAGS+= -I${WRKDIR}
172LDFLAGS+= -L${WRKDIR}/netpgp 172LDFLAGS+= -L${WRKDIR}/netpgp
173 173
174CONFIGURE_ENV+= LIBS=${LIBS:Q} 174CONFIGURE_ENV+= LIBS=${LIBS:Q}
175 175
176do-extract: 176do-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
190pre-configure: 190pre-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.
220update: 220update:
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
226update-catpages: 226update-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"

cvs diff -r1.128 -r1.128.2.1 pkgsrc/pkgtools/pkgin/Makefile (switch to unified diff)

--- pkgsrc/pkgtools/pkgin/Makefile 2023/11/08 13:20:39 1.128
+++ pkgsrc/pkgtools/pkgin/Makefile 2024/01/13 12:49:09 1.128.2.1
@@ -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
3DISTNAME= pkgin-23.8.1 3DISTNAME= pkgin-23.8.1
4PKGREVISION= 2 4PKGREVISION= 3
5CATEGORIES= pkgtools 5CATEGORIES= pkgtools
6MASTER_SITES= ${MASTER_SITE_GITHUB:=NetBSDfr/} 6MASTER_SITES= ${MASTER_SITE_GITHUB:=NetBSDfr/}
7GITHUB_TAG= v${PKGVERSION_NOREV} 7GITHUB_TAG= v${PKGVERSION_NOREV}
8 8
9MAINTAINER= jperkin@pkgsrc.org 9MAINTAINER= jperkin@pkgsrc.org
10HOMEPAGE= http://pkgin.net/ 10HOMEPAGE= http://pkgin.net/
11COMMENT= Apt / yum like tool for managing pkgsrc binary packages 11COMMENT= Apt / yum like tool for managing pkgsrc binary packages
12LICENSE= modified-bsd 12LICENSE= modified-bsd
13 13
14EGDIR= ${PREFIX}/share/examples/${PKGBASE} 14EGDIR= ${PREFIX}/share/examples/${PKGBASE}
15CONF_FILES= ${EGDIR}/repositories.conf.example \ 15CONF_FILES= ${EGDIR}/repositories.conf.example \
16 ${PKG_SYSCONFDIR}/${PKGBASE}/repositories.conf 16 ${PKG_SYSCONFDIR}/${PKGBASE}/repositories.conf
17 17
18OWN_DIRS+= ${PKG_SYSCONFDIR}/${PKGBASE} 18OWN_DIRS+= ${PKG_SYSCONFDIR}/${PKGBASE}
19OWN_DIRS+= ${VARBASE}/db/pkgin 19OWN_DIRS+= ${VARBASE}/db/pkgin
20 20
21INSTALLATION_DIRS+= bin ${PKGMANDIR}/man1 ${EGDIR} 21INSTALLATION_DIRS+= bin ${PKGMANDIR}/man1 ${EGDIR}
22 22
23BUILD_DEFS+= PKGIN_REPOSITORY_URL 23BUILD_DEFS+= PKGIN_REPOSITORY_URL
24BUILD_DEFS+= VARBASE 24BUILD_DEFS+= VARBASE
25 25
26GNU_CONFIGURE= yes 26GNU_CONFIGURE= yes
27CONFIGURE_ARGS+= --disable-maintainer-mode 27CONFIGURE_ARGS+= --disable-maintainer-mode
28CONFIGURE_ARGS+= --sysconfdir=${PKG_SYSCONFDIR} 28CONFIGURE_ARGS+= --sysconfdir=${PKG_SYSCONFDIR}
29CONFIGURE_ARGS+= --with-dbdir=${VARBASE}/db/pkgin 29CONFIGURE_ARGS+= --with-dbdir=${VARBASE}/db/pkgin
30CONFIGURE_ARGS+= --with-machine-arch=${MACHINE_ARCH} 30CONFIGURE_ARGS+= --with-machine-arch=${MACHINE_ARCH}
31CONFIGURE_ARGS+= --with-pkg-install=${PKG_TOOLS_BIN} 31CONFIGURE_ARGS+= --with-pkg-install=${PKG_TOOLS_BIN}
32CONFIGURE_ARGS+= --with-libarchive=${BUILDLINK_PREFIX.libarchive} 32CONFIGURE_ARGS+= --with-libarchive=${BUILDLINK_PREFIX.libarchive}
33CONFIGURE_ARGS+= --with-libfetch=${BUILDLINK_PREFIX.libfetch} 33CONFIGURE_ARGS+= --with-libfetch=${BUILDLINK_PREFIX.libfetch}
34CONFIGURE_ARGS+= --with-openssl=${BUILDLINK_PREFIX.openssl} 34CONFIGURE_ARGS+= --with-openssl=${BUILDLINK_PREFIX.openssl}
35CONFIGURE_ARGS+= --with-sqlite3=${BUILDLINK_PREFIX.sqlite3} 35CONFIGURE_ARGS+= --with-sqlite3=${BUILDLINK_PREFIX.sqlite3}
36 36
37USE_FEATURES= nbcompat 37USE_FEATURES= nbcompat
38 38
39.include "../../mk/bsd.prefs.mk" 39.include "../../mk/bsd.prefs.mk"
40 40
41SUBST_CLASSES.NetBSD+= osrel 41SUBST_CLASSES.NetBSD+= osrel
42SUBST_STAGE.osrel= pre-configure 42SUBST_STAGE.osrel= pre-configure
43SUBST_MESSAGE.osrel= Adjusting repository OS release 43SUBST_MESSAGE.osrel= Adjusting repository OS release
44SUBST_FILES.osrel= REPOSITORIES 44SUBST_FILES.osrel= REPOSITORIES
45SUBST_SED.osrel= -e "s|@OSREL@|${OS_VERSION:C/_.*//}|" 45SUBST_SED.osrel= -e "s|@OSREL@|${OS_VERSION:C/_.*//}|"
46 46
47CFLAGS.SunOS+= -D_FILE_OFFSET_BITS=64 47CFLAGS.SunOS+= -D_FILE_OFFSET_BITS=64
48 48
49DEPENDS+= pkg_install>=20200701:../../pkgtools/pkg_install 49DEPENDS+= 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)
55pre-install: 55pre-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"
58pre-install: 58pre-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
63post-install: 63post-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"