diff options
Diffstat (limited to 'misc.c')
-rw-r--r-- | misc.c | 93 |
1 files changed, 87 insertions, 6 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: misc.c,v 1.133 2018/10/05 14:26:09 naddy Exp $ */ | 1 | /* $OpenBSD: misc.c,v 1.137 2019/01/23 21:50:56 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2005,2006 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2005,2006 Damien Miller. All rights reserved. |
@@ -38,6 +38,7 @@ | |||
38 | #ifdef HAVE_LIBGEN_H | 38 | #ifdef HAVE_LIBGEN_H |
39 | # include <libgen.h> | 39 | # include <libgen.h> |
40 | #endif | 40 | #endif |
41 | #include <poll.h> | ||
41 | #include <signal.h> | 42 | #include <signal.h> |
42 | #include <stdarg.h> | 43 | #include <stdarg.h> |
43 | #include <stdio.h> | 44 | #include <stdio.h> |
@@ -234,6 +235,80 @@ set_rdomain(int fd, const char *name) | |||
234 | #endif | 235 | #endif |
235 | } | 236 | } |
236 | 237 | ||
238 | /* | ||
239 | * Wait up to *timeoutp milliseconds for fd to be readable. Updates | ||
240 | * *timeoutp with time remaining. | ||
241 | * Returns 0 if fd ready or -1 on timeout or error (see errno). | ||
242 | */ | ||
243 | int | ||
244 | waitrfd(int fd, int *timeoutp) | ||
245 | { | ||
246 | struct pollfd pfd; | ||
247 | struct timeval t_start; | ||
248 | int oerrno, r; | ||
249 | |||
250 | monotime_tv(&t_start); | ||
251 | pfd.fd = fd; | ||
252 | pfd.events = POLLIN; | ||
253 | for (; *timeoutp >= 0;) { | ||
254 | r = poll(&pfd, 1, *timeoutp); | ||
255 | oerrno = errno; | ||
256 | ms_subtract_diff(&t_start, timeoutp); | ||
257 | errno = oerrno; | ||
258 | if (r > 0) | ||
259 | return 0; | ||
260 | else if (r == -1 && errno != EAGAIN) | ||
261 | return -1; | ||
262 | else if (r == 0) | ||
263 | break; | ||
264 | } | ||
265 | /* timeout */ | ||
266 | errno = ETIMEDOUT; | ||
267 | return -1; | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | * Attempt a non-blocking connect(2) to the specified address, waiting up to | ||
272 | * *timeoutp milliseconds for the connection to complete. If the timeout is | ||
273 | * <=0, then wait indefinitely. | ||
274 | * | ||
275 | * Returns 0 on success or -1 on failure. | ||
276 | */ | ||
277 | int | ||
278 | timeout_connect(int sockfd, const struct sockaddr *serv_addr, | ||
279 | socklen_t addrlen, int *timeoutp) | ||
280 | { | ||
281 | int optval = 0; | ||
282 | socklen_t optlen = sizeof(optval); | ||
283 | |||
284 | /* No timeout: just do a blocking connect() */ | ||
285 | if (timeoutp == NULL || *timeoutp <= 0) | ||
286 | return connect(sockfd, serv_addr, addrlen); | ||
287 | |||
288 | set_nonblock(sockfd); | ||
289 | if (connect(sockfd, serv_addr, addrlen) == 0) { | ||
290 | /* Succeeded already? */ | ||
291 | unset_nonblock(sockfd); | ||
292 | return 0; | ||
293 | } else if (errno != EINPROGRESS) | ||
294 | return -1; | ||
295 | |||
296 | if (waitrfd(sockfd, timeoutp) == -1) | ||
297 | return -1; | ||
298 | |||
299 | /* Completed or failed */ | ||
300 | if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) { | ||
301 | debug("getsockopt: %s", strerror(errno)); | ||
302 | return -1; | ||
303 | } | ||
304 | if (optval != 0) { | ||
305 | errno = optval; | ||
306 | return -1; | ||
307 | } | ||
308 | unset_nonblock(sockfd); | ||
309 | return 0; | ||
310 | } | ||
311 | |||
237 | /* Characters considered whitespace in strsep calls. */ | 312 | /* Characters considered whitespace in strsep calls. */ |
238 | #define WHITESPACE " \t\r\n" | 313 | #define WHITESPACE " \t\r\n" |
239 | #define QUOTE "\"" | 314 | #define QUOTE "\"" |
@@ -489,7 +564,7 @@ put_host_port(const char *host, u_short port) | |||
489 | * The delimiter char, if present, is stored in delim. | 564 | * The delimiter char, if present, is stored in delim. |
490 | * If this is the last field, *cp is set to NULL. | 565 | * If this is the last field, *cp is set to NULL. |
491 | */ | 566 | */ |
492 | static char * | 567 | char * |
493 | hpdelim2(char **cp, char *delim) | 568 | hpdelim2(char **cp, char *delim) |
494 | { | 569 | { |
495 | char *s, *old; | 570 | char *s, *old; |
@@ -1335,11 +1410,11 @@ bandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen) | |||
1335 | { | 1410 | { |
1336 | bw->buflen = buflen; | 1411 | bw->buflen = buflen; |
1337 | bw->rate = kbps; | 1412 | bw->rate = kbps; |
1338 | bw->thresh = bw->rate; | 1413 | bw->thresh = buflen; |
1339 | bw->lamt = 0; | 1414 | bw->lamt = 0; |
1340 | timerclear(&bw->bwstart); | 1415 | timerclear(&bw->bwstart); |
1341 | timerclear(&bw->bwend); | 1416 | timerclear(&bw->bwend); |
1342 | } | 1417 | } |
1343 | 1418 | ||
1344 | /* Callback from read/write loop to insert bandwidth-limiting delays */ | 1419 | /* Callback from read/write loop to insert bandwidth-limiting delays */ |
1345 | void | 1420 | void |
@@ -1348,12 +1423,11 @@ bandwidth_limit(struct bwlimit *bw, size_t read_len) | |||
1348 | u_int64_t waitlen; | 1423 | u_int64_t waitlen; |
1349 | struct timespec ts, rm; | 1424 | struct timespec ts, rm; |
1350 | 1425 | ||
1426 | bw->lamt += read_len; | ||
1351 | if (!timerisset(&bw->bwstart)) { | 1427 | if (!timerisset(&bw->bwstart)) { |
1352 | monotime_tv(&bw->bwstart); | 1428 | monotime_tv(&bw->bwstart); |
1353 | return; | 1429 | return; |
1354 | } | 1430 | } |
1355 | |||
1356 | bw->lamt += read_len; | ||
1357 | if (bw->lamt < bw->thresh) | 1431 | if (bw->lamt < bw->thresh) |
1358 | return; | 1432 | return; |
1359 | 1433 | ||
@@ -2037,3 +2111,10 @@ format_absolute_time(uint64_t t, char *buf, size_t len) | |||
2037 | localtime_r(&tt, &tm); | 2111 | localtime_r(&tt, &tm); |
2038 | strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm); | 2112 | strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm); |
2039 | } | 2113 | } |
2114 | |||
2115 | /* check if path is absolute */ | ||
2116 | int | ||
2117 | path_absolute(const char *path) | ||
2118 | { | ||
2119 | return (*path == '/') ? 1 : 0; | ||
2120 | } | ||