add ptimeout API for keeping track of poll/ppoll timeouts;
authordjm <djm@openbsd.org>
Fri, 6 Jan 2023 02:37:04 +0000 (02:37 +0000)
committerdjm <djm@openbsd.org>
Fri, 6 Jan 2023 02:37:04 +0000 (02:37 +0000)
ok dtucker markus

usr.bin/ssh/misc.c
usr.bin/ssh/misc.h

index 2d65927..536efe5 100644 (file)
@@ -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.
@@ -2724,3 +2724,92 @@ lookup_setenv_in_list(const char *env, char * const *envs, size_t 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;
+}
index 5ca5dde..7d1454e 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.h,v 1.100 2022/06/03 04:30:47 djm Exp $ */
+/* $OpenBSD: misc.h,v 1.101 2023/01/06 02:37:04 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -206,6 +206,15 @@ void       opt_array_append2(const char *file, const int line,
            const char *directive, char ***array, int **iarray, u_int *lp,
            const char *s, int i);
 
+struct timespec;
+void ptimeout_init(struct timespec *pt);
+void ptimeout_deadline_sec(struct timespec *pt, long sec);
+void ptimeout_deadline_ms(struct timespec *pt, long ms);
+void ptimeout_deadline_monotime(struct timespec *pt, time_t when);
+int ptimeout_get_ms(struct timespec *pt);
+struct timespec *ptimeout_get_tsp(struct timespec *pt);
+int ptimeout_isset(struct timespec *pt);
+
 /* readpass.c */
 
 #define RP_ECHO                        0x0001