From 7093c38978e86b462071e120f1dbd0414aab3eb6 Mon Sep 17 00:00:00 2001 From: 0scar Date: Tue, 11 Feb 2025 08:57:17 +0100 Subject: Remove clib/gnu time functions --- status.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 26 deletions(-) diff --git a/status.c b/status.c index 260ea6b..6bdcbc7 100644 --- a/status.c +++ b/status.c @@ -30,8 +30,8 @@ typedef void (*element_function)(char*); /* Data structures */ struct element { const element_function f; - const struct timeval fire_interval; - struct timeval fire_previous; + const struct timespec fire_interval; + struct timespec fire_previous; char buf[ELEMENT_STRBUF_SZ]; }; @@ -82,15 +82,17 @@ static char* battery_level_icon[] = { "", /* "\uf578" */ }; +// Converts milliseconds to nanoseconds +#define MSEC(msec) (msec * 1000 * 1000) static struct element statusbar[] = { /* Add status elements here */ - /*{element_function, {seconds, microseconds}, {0}, {0}},*/ + /*{element_function, {seconds, nanoseconds}, {0}, {0}},*/ {get_net_link_status, {15, 0}, {0}, {0}}, {get_battery0_status, {60, 0}, {0}, {0}}, {get_battery1_status, {60, 0}, {0}, {0}}, { get_all_bat_status, {60, 0}, {0}, {0}}, - { date, {7, 500000}, {0}, {0}}, + { date, {7, MSEC(500)}, {0}, {0}}, }; struct interface_status interfaces[8]; // surely noone has more than 8 interfaces. @@ -226,8 +228,7 @@ get_essid(char* if_name, char* dst) { dst[0] = '\0'; } - close(sock); - + close(sock); } void @@ -243,10 +244,11 @@ get_net_link_status(char* buf) { } for (struct ifaddrs* ifa = if_addr; ifa != NULL; ifa = ifa->ifa_next) { - int i = 0; + size_t i = 0; const char* name = ifa->ifa_name; - while (i < c && strcmp(name, interfaces[i].name)) i++; + while (i < c && strcmp(name, interfaces[i].name)) + i++; //if (i != c) { //printf("found %s in %d\n", name, i); @@ -286,7 +288,7 @@ get_net_link_status(char* buf) { struct interface_status s; // = &status[c]; memset(&s, 0, sizeof(struct interface_status)); - s = interfaces[i]; + s = interfaces[i]; if (ifa->ifa_addr != NULL) { const int family = ifa->ifa_addr->sa_family; @@ -326,12 +328,11 @@ get_net_link_status(char* buf) { } memcpy(&interfaces[i], &s, sizeof(struct interface_status)); - } freeifaddrs(if_addr); memset(buf, 0, ELEMENT_STRBUF_SZ); - for (int i = 0; i < c; i++) { + for (size_t i = 0; i < c; i++) { // int i = 0; { struct interface_status* s = &interfaces[i]; // Write the status string to the output buffer @@ -372,30 +373,69 @@ get_net_link_status(char* buf) { } } +static struct timespec +time_add(struct timespec a, struct timespec b) { + struct timespec dst; + dst.tv_sec = a.tv_sec + b.tv_sec; + dst.tv_nsec = a.tv_nsec + b.tv_nsec; + + /* larger than 1 second in μsec */ + if (dst.tv_nsec >= 1000000) { + dst.tv_nsec -= 1000000 * 1000; + dst.tv_sec++; + } + + return dst; +} + +/* Assume that time_t and time64_t are signed (they are on my machine) */ +static struct timespec +time_sub(struct timespec a, struct timespec b) { + struct timespec dst; + + dst.tv_sec = a.tv_sec + b.tv_sec; + dst.tv_nsec = a.tv_nsec + b.tv_nsec; + + if (dst.tv_nsec < 0) { + dst.tv_nsec += 1000000 * 1000; + dst.tv_sec--; + } + + return dst; +} + +static bool +time_lt(struct timespec a, struct timespec b) { + if (a.tv_sec == b.tv_sec) { + return a.tv_nsec < b.tv_nsec; + } + + return a.tv_sec < b.tv_sec; +} + int main(void) { const int num_elems = sizeof(statusbar) / sizeof(statusbar[0]); - struct timeval now; - const struct timeval one_minute = {60, 0}; + struct timespec now; + const struct timespec one_minute = {60, 0}; memset(interfaces, 0, sizeof(struct interface_status[8])); while (true) { - gettimeofday(&now, NULL); + clock_gettime(CLOCK_REALTIME, &now); unsigned i; /* Stall updating for at most 1 minute */ - struct timeval next_update; - timeradd(&now, &one_minute, &next_update); + struct timespec next_update = {0}; + now = time_add(one_minute, next_update); for (i = 0; i < num_elems; i++) { - struct timeval next_fire; - timeradd(&statusbar[i].fire_previous, &statusbar[i].fire_interval, - &next_fire); + struct timespec next_fire = {0}; + statusbar[i].fire_previous = time_add(statusbar[i].fire_interval, next_fire); - if (timercmp(&next_fire, &now, >)) { + if (time_lt(now, next_fire)) { /* Check if this is the next to-be-updated element */ - if (timercmp(&next_fire, &next_update, <)) { + if (time_lt(next_fire, next_update)) { next_update = next_fire; } continue; @@ -407,9 +447,9 @@ main(void) { statusbar[i].fire_previous = now; /* Check if this element needs to be refreshed next, again */ - timeradd(&statusbar[i].fire_previous, &statusbar[i].fire_interval, - &next_fire); - if (timercmp(&next_fire, &next_update, <)) { + statusbar[i].fire_previous = time_add(statusbar[i].fire_interval, next_fire); + + if (time_lt(next_fire, next_update)) { next_update = next_fire; } @@ -436,8 +476,11 @@ main(void) { puts(buf); fflush(stdout); - timersub(&next_update, &now, &next_update); - usleep(next_update.tv_sec * 1000 * 1000 + next_update.tv_usec); + next_update = time_sub(now, next_update); + + /* Replace NULL to get "remaining time", in case we got + * interrupted / signaled */ + nanosleep(&next_update, NULL); } return 0; -- cgit v1.3