diff --git a/sbin/devd/devd.cc b/sbin/devd/devd.cc --- a/sbin/devd/devd.cc +++ b/sbin/devd/devd.cc @@ -70,6 +70,7 @@ #include #include #include +#include #include #include @@ -88,6 +89,7 @@ #include #include #include +#include #include #include @@ -95,6 +97,7 @@ #include #include #include +#include #include "devd.h" /* C compatible definitions */ #include "devd.hh" /* C++ class definitions */ @@ -846,71 +849,87 @@ static void process_event(char *buffer) { + // TODO + // 1. Create "newerthan" syntax element for devd.conf + // 2. Make custom exception for redundant events + char type; char *sp; struct timeval tv; char *timestr; + struct stat file_info; + + gettimeofday(&tv, NULL); sp = buffer + 1; - devdlog(LOG_INFO, "Processing event '%s'\n", buffer); type = *buffer++; - cfg.push_var_table(); - // $* is the entire line - cfg.set_variable("*", buffer - 1); - // $_ is the entire line without the initial character - cfg.set_variable("_", buffer); - - // Save the time this happened (as approximated by when we got - // around to processing it). - gettimeofday(&tv, NULL); - asprintf(×tr, "%jd.%06ld", (uintmax_t)tv.tv_sec, tv.tv_usec); - cfg.set_variable("timestamp", timestr); - free(timestr); - // Match doesn't have a device, and the format is a little - // different, so handle it separately. - switch (type) { - case notify: - //! (k=v)* - sp = cfg.set_vars(sp); - break; - case nomatch: - //? at location pnp-info on bus - sp = strchr(sp, ' '); - if (sp == NULL) - return; /* Can't happen? */ - *sp++ = '\0'; - while (isspace(*sp)) - sp++; - if (strncmp(sp, "at ", 3) == 0) - sp += 3; - sp = cfg.set_vars(sp); - while (isspace(*sp)) - sp++; - if (strncmp(sp, "on ", 3) == 0) - cfg.set_variable("bus", sp + 3); - break; - case attach: /*FALLTHROUGH*/ - case detach: - sp = strchr(sp, ' '); - if (sp == NULL) - return; /* Can't happen? */ - *sp++ = '\0'; - cfg.set_variable("device-name", buffer); - while (isspace(*sp)) - sp++; - if (strncmp(sp, "at ", 3) == 0) - sp += 3; - sp = cfg.set_vars(sp); - while (isspace(*sp)) - sp++; - if (strncmp(sp, "on ", 3) == 0) - cfg.set_variable("bus", sp + 3); - break; + const char* devmatch_ran = "/var/run/devmatch_ran"; + stat(devmatch_ran, &file_info); // Retrieves last modification timestamp of file + + if ((tv.tv_sec < file_info.st_mtim.tv_sec || tv.tv_usec < file_info.st_mtim.tv_nsec / 1000) && type==nomatch) { // Checks if event is older than devmatch_ran + throw std::exception(); } + else { + devdlog(LOG_INFO, "Processing event '%s'\n", buffer); + + cfg.push_var_table(); + // $* is the entire line + cfg.set_variable("*", buffer - 1); + // $_ is the entire line without the initial character + cfg.set_variable("_", buffer); + + // Save the time this happened (as approximated by when we got + // around to processing it). + asprintf(×tr, "%jd.%06ld", (uintmax_t)tv.tv_sec, tv.tv_usec); + cfg.set_variable("timestamp", timestr); + free(timestr); + + // Match doesn't have a device, and the format is a little + // different, so handle it separately. + switch (type) { + case notify: + //! (k=v)* + sp = cfg.set_vars(sp); + break; + case nomatch: + //? at location pnp-info on bus + sp = strchr(sp, ' '); + if (sp == NULL) + return; /* Can't happen? */ + *sp++ = '\0'; + while (isspace(*sp)) + sp++; + if (strncmp(sp, "at ", 3) == 0) + sp += 3; + sp = cfg.set_vars(sp); + while (isspace(*sp)) + sp++; + if (strncmp(sp, "on ", 3) == 0) + cfg.set_variable("bus", sp + 3); + break; + case attach: /*FALLTHROUGH*/ + case detach: + sp = strchr(sp, ' '); + if (sp == NULL) + return; /* Can't happen? */ + *sp++ = '\0'; + cfg.set_variable("device-name", buffer); + while (isspace(*sp)) + sp++; + if (strncmp(sp, "at ", 3) == 0) + sp += 3; + sp = cfg.set_vars(sp); + while (isspace(*sp)) + sp++; + if (strncmp(sp, "on ", 3) == 0) + cfg.set_variable("bus", sp + 3); + break; + } - cfg.find_and_execute(type); - cfg.pop_var_table(); + cfg.find_and_execute(type); + cfg.pop_var_table(); + } } static int @@ -1032,6 +1051,7 @@ static void event_loop(void) { + int rv; int fd; char buffer[DEVCTL_MAXBUF]; @@ -1121,12 +1141,18 @@ while (buffer[--rv] == '\n') buffer[rv] = '\0'; try { + process_event(buffer); } + // Include a second catch statement for late timestamps, so make process_event throw an exception catch (const std::length_error& e) { devdlog(LOG_ERR, "Dropping event %s " "due to low memory", buffer); } + catch (const std::exception& e) { + devdlog(LOG_ERR, "Event %s is redundant", buffer); + + } } else if (rv < 0) { if (errno != EINTR) break;