X-Git-Url: https://roy.marples.name/git diff --git a/src/dhcpcd-online/dhcpcd-online.c b/src/dhcpcd-online/dhcpcd-online.c index 334960c..6596220 100644 --- a/src/dhcpcd-online/dhcpcd-online.c +++ b/src/dhcpcd-online/dhcpcd-online.c @@ -1,6 +1,6 @@ /* * dhcpcd-online - * Copyright 2014 Roy Marples + * Copyright 2014-2015 Roy Marples * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -53,22 +53,57 @@ # endif #endif +#ifndef timespeccmp +#define timespeccmp(tsp, usp, cmp) \ + (((tsp)->tv_sec == (usp)->tv_sec) ? \ + ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \ + ((tsp)->tv_sec cmp (usp)->tv_sec)) +#endif +#ifndef timespecsub +#define timespecsub(tsp, usp, vsp) \ + do { \ + (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \ + (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \ + if ((vsp)->tv_nsec < 0) { \ + (vsp)->tv_sec--; \ + (vsp)->tv_nsec += 1000000000L; \ + } \ + } while (/* CONSTCOND */ 0) +#endif + +/* Incase we need to pass anything else in context to status cb */ +struct ctx { + struct pollfd pollfd; +}; + static void __dead do_exit(DHCPCD_CONNECTION *con, int code) { + /* Unregister the status callback so that close doesn't spam. */ + dhcpcd_set_status_callback(con, NULL, NULL); + dhcpcd_close(con); dhcpcd_free(con); exit(code); } static void -do_status_cb(DHCPCD_CONNECTION *con, const char *status, void __unused *arg) +status_cb(DHCPCD_CONNECTION *con, + unsigned int status, const char *status_msg, void *arg) { + struct ctx *ctx; - syslog(LOG_INFO, "%s", status); - if (strcmp(status, "connected") == 0) + syslog(LOG_INFO, "%s", status_msg); + switch (status) { + case DHC_CONNECTED: do_exit(con, EXIT_SUCCESS); + /* NOT REACHED */ + case DHC_DOWN: + ctx = arg; + ctx->pollfd.fd = -1; + break; + } } int @@ -77,7 +112,7 @@ main(int argc, char **argv) DHCPCD_CONNECTION *con; bool xflag; struct timespec now, end, t; - struct pollfd pfd; + struct ctx ctx; int timeout, n, lerrno; long lnum; char *lend; @@ -86,6 +121,9 @@ main(int argc, char **argv) timeout = 30; xflag = false; + ctx.pollfd.fd = -1; + ctx.pollfd.events = POLLIN; + ctx.pollfd.revents = 0; openlog("dhcpcd-online", LOG_PERROR, 0); setlogmask(LOG_UPTO(LOG_INFO)); @@ -121,18 +159,15 @@ main(int argc, char **argv) syslog(LOG_ERR, "dhcpcd_new: %m"); return EXIT_FAILURE; } + dhcpcd_set_status_callback(con, status_cb, &ctx); - dhcpcd_set_status_callback(con, do_status_cb, NULL); - - if ((pfd.fd = dhcpcd_open(con)) == -1) { + if ((ctx.pollfd.fd = dhcpcd_open(con, false)) == -1) { lerrno = errno; syslog(LOG_WARNING, "dhcpcd_open: %m"); if (xflag) do_exit(con, EXIT_FAILURE); } else lerrno = 0; - pfd.events = POLLIN; - pfd.revents = 0; /* Work out our timeout time */ if (clock_gettime(CLOCK_MONOTONIC, &end) == -1) { @@ -150,7 +185,7 @@ main(int argc, char **argv) syslog(LOG_ERR, "timed out"); do_exit(con, EXIT_FAILURE); } - if (pfd.fd == -1) { + if (ctx.pollfd.fd == -1) { n = poll(NULL, 0, DHCPCD_RETRYOPEN); } else { /* poll(2) should really take a timespec */ @@ -160,23 +195,23 @@ main(int argc, char **argv) (t.tv_nsec + 999999) / 1000000 > INT_MAX % 1000000)) timeout = INT_MAX; else - timeout = (int)t.tv_sec * 1000 + - (t.tv_nsec + 999999) / 1000000; - n = poll(&pfd, 1, timeout); + timeout = (int)(t.tv_sec * 1000 + + (t.tv_nsec + 999999) / 1000000); + n = poll(&ctx.pollfd, 1, timeout); } if (n == -1) { syslog(LOG_ERR, "poll: %m"); do_exit(con, EXIT_FAILURE); } - if (pfd.fd == -1) { - if ((pfd.fd = dhcpcd_open(con)) == -1) { + if (ctx.pollfd.fd == -1) { + if ((ctx.pollfd.fd = dhcpcd_open(con, false)) == -1) { if (lerrno != errno) { lerrno = errno; syslog(LOG_WARNING, "dhcpcd_open: %m"); } } } else { - if (n > 0 && pfd.revents) + if (n > 0 && ctx.pollfd.revents) dhcpcd_dispatch(con); } }