summaryrefslogtreecommitdiffstats
path: root/sbin/devd/devd.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/devd/devd.cc')
-rw-r--r--sbin/devd/devd.cc146
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);
}
OpenPOWER on IntegriCloud