summaryrefslogtreecommitdiffstats
path: root/sbin/devd
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2004-07-01 07:24:18 +0000
committerimp <imp@FreeBSD.org>2004-07-01 07:24:18 +0000
commit3c5c35a72b44c745361adcdc5002abdd00233ca6 (patch)
tree5af47f1fd0d7b6af8009828331d3a7d6e3af4e1b /sbin/devd
parentf39553c75a79c7f7fcd1a4be31aeb04aa6359d05 (diff)
downloadFreeBSD-src-3c5c35a72b44c745361adcdc5002abdd00233ca6.zip
FreeBSD-src-3c5c35a72b44c745361adcdc5002abdd00233ca6.tar.gz
Create a unix domain socket and write to it all the events that come
in over the socket.
Diffstat (limited to 'sbin/devd')
-rw-r--r--sbin/devd/devd.85
-rw-r--r--sbin/devd/devd.cc100
2 files changed, 91 insertions, 14 deletions
diff --git a/sbin/devd/devd.8 b/sbin/devd/devd.8
index e8fecfe..97cc104 100644
--- a/sbin/devd/devd.8
+++ b/sbin/devd/devd.8
@@ -109,6 +109,11 @@ wish to hook into the
.Nm
system without modifying the user's other
config files.
+.Pp
+All messages that
+.Nm
+receives are forwarded to the unix domain socket at
+.Pa /var/run/devd.pipe .
.Sh SEE ALSO
.Xr devctl 4 ,
.Xr devd.conf 5
diff --git a/sbin/devd/devd.cc b/sbin/devd/devd.cc
index 71a0f29..75b22c3 100644
--- a/sbin/devd/devd.cc
+++ b/sbin/devd/devd.cc
@@ -30,15 +30,18 @@
// TODO list:
// o devd.conf and devd man pages need a lot of help:
-// - devd.conf needs to lose the warning about zone files.
+// - devd needs to document the unix domain socket
// - devd.conf needs more details on the supported statements.
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
#include <sys/sysctl.h>
+#include <sys/types.h>
+#include <sys/un.h>
#include <ctype.h>
#include <dirent.h>
@@ -54,11 +57,13 @@ __FBSDID("$FreeBSD$");
#include <algorithm>
#include <map>
#include <string>
+#include <list>
#include <vector>
#include "devd.h" /* C compatible definitions */
#include "devd.hh" /* C++ class definitions */
+#define PIPE "/var/run/devd.pipe"
#define CF "/etc/devd.conf"
#define SYSCTL "hw.bus.devctl_disable"
@@ -585,6 +590,56 @@ process_event(char *buffer)
cfg.pop_var_table();
}
+int
+create_socket(const char *name)
+{
+ int fd, slen;
+ struct sockaddr_un sun;
+
+ if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0)
+ err(1, "socket");
+ bzero(&sun, sizeof(sun));
+ sun.sun_family = AF_UNIX;
+ strlcpy(sun.sun_path, name, sizeof(sun.sun_path));
+ slen = SUN_LEN(&sun);
+ unlink(name);
+ if (bind(fd, (struct sockaddr *) & sun, slen) < 0)
+ err(1, "bind");
+ listen(fd, 4);
+ fchown(fd, 0, 0); /* XXX - root.wheel */
+ fchmod(fd, 0660);
+ return (fd);
+}
+
+list<int> clients;
+
+void
+notify_clients(const char *data, int len)
+{
+ list<int> bad;
+ list<int>::const_iterator i;
+
+ for (i = clients.begin(); i != clients.end(); i++) {
+ if (write(*i, data, len) <= 0) {
+ bad.push_back(*i);
+ close(*i);
+ }
+ }
+
+ for (i = bad.begin(); i != bad.end(); i++)
+ clients.erase(find(clients.begin(), clients.end(), *i));
+}
+
+void
+new_client(int fd)
+{
+ int s;
+
+ s = accept(fd, NULL, NULL);
+ if (s != -1)
+ clients.push_back(s);
+}
+
static void
event_loop(void)
{
@@ -592,14 +647,17 @@ event_loop(void)
int fd;
char buffer[DEVCTL_MAXBUF];
int once = 0;
+ int server_fd, max_fd;
timeval tv;
fd_set fds;
fd = open(PATH_DEVCTL, O_RDONLY);
if (fd == -1)
- err(1, "Can't open devctl");
+ err(1, "Can't open devctl device %s", PATH_DEVCTL);
if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0)
- err(1, "Can't set close-on-exec flag");
+ err(1, "Can't set close-on-exec flag on devctl");
+ server_fd = create_socket(PIPE);
+ max_fd = max(fd, server_fd) + 1;
while (1) {
if (romeo_must_die)
break;
@@ -619,19 +677,33 @@ event_loop(void)
once++;
}
}
- rv = read(fd, buffer, sizeof(buffer) - 1);
- if (rv > 0) {
- buffer[rv] = '\0';
- while (buffer[--rv] == '\n')
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+ FD_SET(server_fd, &fds);
+ rv = select(max_fd, &fds, NULL, NULL, NULL);
+ if (rv == -1) {
+ if (errno == EINTR)
+ continue;
+ err(1, "select");
+ }
+ if (FD_ISSET(fd, &fds)) {
+ rv = read(fd, buffer, sizeof(buffer) - 1);
+ if (rv > 0) {
+ notify_clients(buffer, rv);
buffer[rv] = '\0';
- process_event(buffer);
- } else if (rv < 0) {
- if (errno != EINTR)
+ while (buffer[--rv] == '\n')
+ buffer[rv] = '\0';
+ process_event(buffer);
+ } else if (rv < 0) {
+ if (errno != EINTR)
+ break;
+ } else {
+ /* EOF */
break;
- } else {
- /* EOF */
- break;
+ }
}
+ if (FD_ISSET(server_fd, &fds))
+ new_client(server_fd);
}
close(fd);
}
OpenPOWER on IntegriCloud