diff options
Diffstat (limited to 'sbin/devd/devd.cc')
-rw-r--r-- | sbin/devd/devd.cc | 146 |
1 files changed, 96 insertions, 50 deletions
diff --git a/sbin/devd/devd.cc b/sbin/devd/devd.cc index b227589..0f11a83 100644 --- a/sbin/devd/devd.cc +++ b/sbin/devd/devd.cc @@ -79,6 +79,7 @@ __FBSDID("$FreeBSD$"); #include <cstdio> #include <csignal> #include <cstring> +#include <cstdarg> #include <dirent.h> #include <err.h> @@ -87,6 +88,7 @@ __FBSDID("$FreeBSD$"); #include <paths.h> #include <poll.h> #include <regex.h> +#include <syslog.h> #include <unistd.h> #include <algorithm> @@ -114,13 +116,15 @@ static const char detach = '-'; static struct pidfh *pfh; -int Dflag; int dflag; int nflag; +static unsigned total_events = 0; +static volatile sig_atomic_t got_siginfo = 0; static volatile sig_atomic_t romeo_must_die = 0; static const char *configfile = CF; +static void devdlog(int priority, const char* message, ...); static void event_loop(void); static void usage(void); @@ -167,7 +171,7 @@ bool event_proc::run(config &c) const { vector<eps *>::const_iterator i; - + for (i = _epsvec.begin(); i != _epsvec.end(); ++i) if (!(*i)->do_action(c)) return (false); @@ -175,7 +179,7 @@ event_proc::run(config &c) const } action::action(const char *cmd) - : _cmd(cmd) + : _cmd(cmd) { // nothing } @@ -194,7 +198,7 @@ my_system(const char *command) sigset_t newsigblock, oldsigblock; if (!command) /* just checking... */ - return(1); + return (1); /* * Ignore SIGINT and SIGQUIT, block SIGCHLD. Remember to save @@ -243,8 +247,7 @@ bool action::do_action(config &c) { string s = c.expand_string(_cmd.c_str()); - if (Dflag) - fprintf(stderr, "Executing '%s'\n", s.c_str()); + devdlog(LOG_NOTICE, "Executing '%s'\n", s.c_str()); my_system(s.c_str()); return (true); } @@ -268,15 +271,22 @@ match::do_match(config &c) const string &value = c.get_variable(_var); bool retval; - if (Dflag) - fprintf(stderr, "Testing %s=%s against %s, invert=%d\n", + /* + * This function gets called WAY too often to justify calling syslog() + * each time, even at LOG_DEBUG. Because if syslogd isn't running, it + * can consume excessive amounts of systime inside of connect(). Only + * log when we're in -d mode. + */ + if (dflag) { + devdlog(LOG_DEBUG, "Testing %s=%s against %s, invert=%d\n", _var.c_str(), value.c_str(), _re.c_str(), _inv); + } retval = (regexec(&_regex, value.c_str(), 0, NULL, 0) == 0); if (_inv == 1) retval = (retval == 0) ? 1 : 0; - return retval; + return (retval); } #include <sys/sockio.h> @@ -322,8 +332,7 @@ media::do_match(config &c) value = c.get_variable("device-name"); if (value.empty()) value = c.get_variable("subsystem"); - if (Dflag) - fprintf(stderr, "Testing media type of %s against 0x%x\n", + devdlog(LOG_DEBUG, "Testing media type of %s against 0x%x\n", value.c_str(), _type); retval = false; @@ -335,20 +344,18 @@ media::do_match(config &c) if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0 && ifmr.ifm_status & IFM_AVALID) { - if (Dflag) - fprintf(stderr, "%s has media type 0x%x\n", + devdlog(LOG_DEBUG, "%s has media type 0x%x\n", value.c_str(), IFM_TYPE(ifmr.ifm_active)); retval = (IFM_TYPE(ifmr.ifm_active) == _type); } else if (_type == -1) { - if (Dflag) - fprintf(stderr, "%s has unknown media type\n", + devdlog(LOG_DEBUG, "%s has unknown media type\n", value.c_str()); retval = true; } close(s); } - return retval; + return (retval); } const string var_list::bogus = "_$_$_$_$_B_O_G_U_S_$_$_$_$_"; @@ -374,8 +381,14 @@ var_list::is_set(const string &var) const void var_list::set_variable(const string &var, const string &val) { - if (Dflag) - fprintf(stderr, "setting %s=%s\n", var.c_str(), val.c_str()); + /* + * This function gets called WAY too often to justify calling syslog() + * each time, even at LOG_DEBUG. Because if syslogd isn't running, it + * can consume excessive amounts of systime inside of connect(). Only + * log when we're in -d mode. + */ + if (dflag) + devdlog(LOG_DEBUG, "setting %s=%s\n", var.c_str(), val.c_str()); _vars[var] = val; } @@ -393,8 +406,7 @@ config::reset(void) void config::parse_one_file(const char *fn) { - if (Dflag) - fprintf(stderr, "Parsing %s\n", fn); + devdlog(LOG_DEBUG, "Parsing %s\n", fn); yyin = fopen(fn, "r"); if (yyin == NULL) err(1, "Cannot open config file %s", fn); @@ -411,8 +423,7 @@ config::parse_files_in_dir(const char *dirname) struct dirent *dp; char path[PATH_MAX]; - if (Dflag) - fprintf(stderr, "Parsing files in %s\n", dirname); + devdlog(LOG_DEBUG, "Parsing files in %s\n", dirname); dirp = opendir(dirname); if (dirp == NULL) return; @@ -460,7 +471,7 @@ void config::open_pidfile() { pid_t otherpid; - + if (_pidfile.empty()) return; pfh = pidfile_open(_pidfile.c_str(), 0600, &otherpid); @@ -474,21 +485,21 @@ config::open_pidfile() void config::write_pidfile() { - + pidfile_write(pfh); } void config::close_pidfile() { - + pidfile_close(pfh); } void config::remove_pidfile() { - + pidfile_remove(pfh); } @@ -536,11 +547,10 @@ void config::push_var_table() { var_list *vl; - + vl = new var_list(); _var_list_table.push_back(vl); - if (Dflag) - fprintf(stderr, "Pushing table\n"); + devdlog(LOG_DEBUG, "Pushing table\n"); } void @@ -548,8 +558,7 @@ config::pop_var_table() { delete _var_list_table.back(); _var_list_table.pop_back(); - if (Dflag) - fprintf(stderr, "Popping table\n"); + devdlog(LOG_DEBUG, "Popping table\n"); } void @@ -573,7 +582,7 @@ config::get_variable(const string &var) bool config::is_id_char(char ch) const { - return (ch != '\0' && (isalpha(ch) || isdigit(ch) || ch == '_' || + return (ch != '\0' && (isalpha(ch) || isdigit(ch) || ch == '_' || ch == '-')); } @@ -589,7 +598,7 @@ config::expand_one(const char *&src, string &dst) dst += *src++; return; } - + // $(foo) -> $(foo) // Not sure if I want to support this or not, so for now we just pass // it through. @@ -606,7 +615,7 @@ config::expand_one(const char *&src, string &dst) } return; } - + // $[^A-Za-z] -> $\1 if (!isalpha(*src)) { dst += '$'; @@ -657,7 +666,7 @@ bool config::chop_var(char *&buffer, char *&lhs, char *&rhs) const { char *walker; - + if (*buffer == '\0') return (false); walker = lhs = buffer; @@ -731,8 +740,7 @@ config::find_and_execute(char type) s = "detach"; break; } - if (Dflag) - fprintf(stderr, "Processing %s event\n", s); + devdlog(LOG_DEBUG, "Processing %s event\n", s); for (i = l->begin(); i != l->end(); ++i) { if ((*i)->matches(*this)) { (*i)->run(*this); @@ -742,7 +750,7 @@ config::find_and_execute(char type) } - + static void process_event(char *buffer) { @@ -750,8 +758,7 @@ process_event(char *buffer) char *sp; sp = buffer + 1; - if (Dflag) - fprintf(stderr, "Processing event '%s'\n", buffer); + devdlog(LOG_DEBUG, "Processing event '%s'\n", buffer); type = *buffer++; cfg.push_var_table(); // No match doesn't have a device, and the format is a little @@ -794,7 +801,7 @@ process_event(char *buffer) cfg.set_variable("bus", sp + 3); break; } - + cfg.find_and_execute(type); cfg.pop_var_table(); } @@ -843,6 +850,8 @@ notify_clients(const char *data, int len) --num_clients; close(*i); i = clients.erase(i); + devdlog(LOG_WARNING, "notify_clients: write() failed; " + "dropping unresponsive client\n"); } else ++i; } @@ -871,6 +880,8 @@ check_clients(void) --num_clients; close(*i); i = clients.erase(i); + devdlog(LOG_NOTICE, "check_clients: " + "dropping disconnected client\n"); } else ++i; } @@ -923,8 +934,7 @@ event_loop(void) rv = select(fd + 1, &fds, &fds, &fds, &tv); // No events -> we've processed all pending events if (rv == 0) { - if (Dflag) - fprintf(stderr, "Calling daemon\n"); + devdlog(LOG_DEBUG, "Calling daemon\n"); cfg.remove_pidfile(); cfg.open_pidfile(); daemon(0, 0); @@ -958,6 +968,11 @@ event_loop(void) tv.tv_usec = 0; } rv = select(max_fd, &fds, NULL, NULL, &tv); + if (got_siginfo) { + devdlog(LOG_INFO, "Events received so far=%ld\n", + total_events); + got_siginfo = 0; + } if (rv == -1) { if (errno == EINTR) continue; @@ -967,6 +982,12 @@ event_loop(void) if (FD_ISSET(fd, &fds)) { rv = read(fd, buffer, sizeof(buffer) - 1); if (rv > 0) { + total_events++; + if (rv == sizeof(buffer) - 1) { + devdlog(LOG_WARNING, "Warning: " + "available event data exceeded " + "buffer space\n"); + } notify_clients(buffer, rv); buffer[rv] = '\0'; while (buffer[--rv] == '\n') @@ -985,7 +1006,7 @@ event_loop(void) } close(fd); } - + /* * functions that the parser uses. */ @@ -1070,7 +1091,7 @@ set_variable(const char *var, const char *val) free(const_cast<char *>(val)); } - + static void gensighand(int) @@ -1078,10 +1099,37 @@ gensighand(int) romeo_must_die = 1; } +/* + * SIGINFO handler. Will print useful statistics to the syslog or stderr + * as appropriate + */ +static void +siginfohand(int) +{ + got_siginfo = 1; +} + +/* + * Local logging function. Prints to syslog if we're daemonized; syslog + * otherwise. + */ +static void +devdlog(int priority, const char* fmt, ...) +{ + va_list argp; + + va_start(argp, fmt); + if (dflag) + vfprintf(stderr, fmt, argp); + else + vsyslog(priority, fmt, argp); + va_end(argp); +} + static void usage() { - fprintf(stderr, "usage: %s [-Ddn] [-l connlimit] [-f file]\n", + fprintf(stderr, "usage: %s [-dn] [-l connlimit] [-f file]\n", getprogname()); exit(1); } @@ -1111,11 +1159,8 @@ main(int argc, char **argv) int ch; check_devd_enabled(); - while ((ch = getopt(argc, argv, "Ddf:l:n")) != -1) { + while ((ch = getopt(argc, argv, "df:l:n")) != -1) { switch (ch) { - case 'D': - Dflag++; - break; case 'd': dflag++; break; @@ -1143,6 +1188,7 @@ main(int argc, char **argv) signal(SIGHUP, gensighand); signal(SIGINT, gensighand); signal(SIGTERM, gensighand); + signal(SIGINFO, siginfohand); event_loop(); return (0); } |