Create a unix domain socket and write to it all the events that come

in over the socket.
This commit is contained in:
Warner Losh 2004-07-01 07:24:18 +00:00
parent ee2a403c97
commit 251bedd15b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=131397
2 changed files with 93 additions and 16 deletions

View File

@ -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

View File

@ -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')
buffer[rv] = '\0';
process_event(buffer);
} else if (rv < 0) {
if (errno != EINTR)
break;
} else {
/* EOF */
break;
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';
while (buffer[--rv] == '\n')
buffer[rv] = '\0';
process_event(buffer);
} else if (rv < 0) {
if (errno != EINTR)
break;
} else {
/* EOF */
break;
}
}
if (FD_ISSET(server_fd, &fds))
new_client(server_fd);
}
close(fd);
}