=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/misc.c,v retrieving revision 1.179 retrieving revision 1.180 diff -u -r1.179 -r1.180 --- src/usr.bin/ssh/misc.c 2022/12/15 18:20:39 1.179 +++ src/usr.bin/ssh/misc.c 2023/01/06 02:37:04 1.180 @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.179 2022/12/15 18:20:39 deraadt Exp $ */ +/* $OpenBSD: misc.c,v 1.180 2023/01/06 02:37:04 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2005-2020 Damien Miller. All rights reserved. @@ -2723,4 +2723,93 @@ ret = lookup_env_in_list(name, envs, nenvs); free(name); return ret; +} + +/* + * Helpers for managing poll(2)/ppoll(2) timeouts + * Will remember the earliest deadline and return it for use in poll/ppoll. + */ + +/* Initialise a poll/ppoll timeout with an indefinite deadline */ +void +ptimeout_init(struct timespec *pt) +{ + /* + * Deliberately invalid for ppoll(2). + * Will be converted to NULL in ptimeout_get_tspec() later. + */ + pt->tv_sec = -1; + pt->tv_nsec = 0; +} + +/* Specify a poll/ppoll deadline of at most 'sec' seconds */ +void +ptimeout_deadline_sec(struct timespec *pt, long sec) +{ + if (pt->tv_sec == -1 || pt->tv_sec >= sec) { + pt->tv_sec = sec; + pt->tv_nsec = 0; + } +} + +/* Specify a poll/ppoll deadline of at most 'p' (timespec) */ +static void +ptimeout_deadline_tsp(struct timespec *pt, struct timespec *p) +{ + if (pt->tv_sec == -1 || timespeccmp(pt, p, >=)) + *pt = *p; +} + +/* Specify a poll/ppoll deadline of at most 'ms' milliseconds */ +void +ptimeout_deadline_ms(struct timespec *pt, long ms) +{ + struct timespec p; + + p.tv_sec = ms / 1000; + p.tv_nsec = (ms % 1000) * 1000000; + ptimeout_deadline_tsp(pt, &p); +} + +/* Specify a poll/ppoll deadline at wall clock monotime 'when' */ +void +ptimeout_deadline_monotime(struct timespec *pt, time_t when) +{ + struct timespec now, t; + + t.tv_sec = when; + t.tv_nsec = 0; + monotime_ts(&now); + + if (timespeccmp(&now, &t, >=)) + ptimeout_deadline_sec(pt, 0); + else { + timespecsub(&t, &now, &t); + ptimeout_deadline_tsp(pt, &t); + } +} + +/* Get a poll(2) timeout value in milliseconds */ +int +ptimeout_get_ms(struct timespec *pt) +{ + if (pt->tv_sec == -1) + return -1; + if (pt->tv_sec >= (INT_MAX - (pt->tv_nsec / 1000000)) / 1000) + return INT_MAX; + return (pt->tv_sec * 1000) + (pt->tv_nsec / 1000000); +} + +/* Get a ppoll(2) timeout value as a timespec pointer */ +struct timespec * +ptimeout_get_tsp(struct timespec *pt) +{ + return pt->tv_sec == -1 ? NULL : pt; +} + +/* Returns non-zero if a timeout has been set (i.e. is not indefinite) */ +int +ptimeout_isset(struct timespec *pt) +{ + return pt->tv_sec != -1; }