summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2018-01-14 17:54:42 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2018-01-14 17:54:42 +0000
commit4984158b95c5a0c3922cd34940c393652d080f99 (patch)
treebd110462519e041679dc0332088b43132214fe45 /src
parentc5e7afbd8d62f3217687f21c0691a02797dc0df5 (diff)
downloadmdevd-4984158b95c5a0c3922cd34940c393652d080f99.tar.xz
New mdevd model, prepare for 0.1.0.0
- mdevd-netlink removed - mdevd listens to the netlink itself - mdevd-coldplug writes nothing to stdout, but triggers the kernel to create uevents
Diffstat (limited to 'src')
-rw-r--r--src/mdevd/deps-exe/mdevd-netlink1
-rw-r--r--src/mdevd/mdevd-coldplug.c152
-rw-r--r--src/mdevd/mdevd-netlink.c177
-rw-r--r--src/mdevd/mdevd.c219
-rw-r--r--src/mdevd/mdevd.h8
5 files changed, 223 insertions, 334 deletions
diff --git a/src/mdevd/deps-exe/mdevd-netlink b/src/mdevd/deps-exe/mdevd-netlink
deleted file mode 100644
index e7187fe..0000000
--- a/src/mdevd/deps-exe/mdevd-netlink
+++ /dev/null
@@ -1 +0,0 @@
--lskarnet
diff --git a/src/mdevd/mdevd-coldplug.c b/src/mdevd/mdevd-coldplug.c
index dabd678..0d64007 100644
--- a/src/mdevd/mdevd-coldplug.c
+++ b/src/mdevd/mdevd-coldplug.c
@@ -3,70 +3,83 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
-#include <limits.h>
#include <unistd.h>
#include <errno.h>
-#include <skalibs/allreadwrite.h>
-#include <skalibs/buffer.h>
#include <skalibs/sgetopt.h>
#include <skalibs/strerr2.h>
#include <skalibs/direntry.h>
-#include "mdevd.h"
#define USAGE "mdevd-coldplug [ -s slashsys ]"
#define dieusage() strerr_dieusage(100, USAGE)
-#define die1() strerr_diefu1sys(111, "write to stdout")
-static inline void create_event (int fddir, char const *sysdev, char const *sub, char const *name)
+static void scan_subdir (int fdat, char const *pathat, char const *list)
{
- if (faccessat(fddir, "dev", R_OK, AT_EACCESS) < 0)
+ DIR *dir ;
+ int fdlist = openat(fdat, list, O_RDONLY | O_DIRECTORY) ;
+ if (fdlist < 0) strerr_diefu4sys(111, "open ", pathat, "/", list) ;
+ dir = fdopendir(fdlist) ;
+ if (!dir) strerr_diefu4sys(111, "fdopendir ", pathat, "/", list) ;
+ for (;;)
{
- if (errno == ENOENT) return ;
- strerr_diefu6sys(111, "access dev in ", sysdev, "/", sub, "/", name) ;
- }
- if (buffer_put(buffer_1, "add@/", 5) < 0
- || buffer_puts(buffer_1, sub) < 0
- || buffer_put(buffer_1, "/", 1) < 0
- || buffer_puts(buffer_1, name) < 0
- || buffer_put(buffer_1, "\0ACTION=add\0DEVPATH=/dev/", sizeof("\0ACTION=add\0DEVPATH=/dev/") - 1) < 0
- || buffer_puts(buffer_1, sub) < 0
- || buffer_put(buffer_1, "/", 1) < 0
- || buffer_puts(buffer_1, name) < 0
- || buffer_put(buffer_1, "\0SUBSYSTEM=", sizeof("\0SUBSYSTEM=") - 1) < 0)
- die1() ;
-
- {
- char *p ;
- ssize_t r ;
- char buf[PATH_MAX] ;
- r = readlinkat(fddir, "subsystem", buf, PATH_MAX - 1) ;
- if (r < 0) strerr_diefu6sys(111, "readlink subsystem in ", sysdev, "/", sub, "/", name) ;
- buf[r] = 0 ;
- p = strrchr(buf, '/') ;
- if (p && buffer_put(buffer_1, p+1, strlen(p)) < 0) die1() ;
+ direntry *d ;
+ errno = 0 ;
+ d = readdir(dir) ;
+ if (!d) break ;
+ if (d->d_name[0] == '.') continue ;
+ {
+ int fd ;
+ size_t dlen = strlen(d->d_name) ;
+ char fn[dlen + 8] ;
+ memcpy(fn, d->d_name, dlen) ;
+ memcpy(fn + dlen, "/uevent", 8) ;
+ fd = openat(fdlist, fn, O_WRONLY) ;
+ if (fd < 0)
+ {
+ strerr_warnwu6sys("open ", pathat, "/", list, "/", fn) ;
+ continue ;
+ }
+ if (write(fd, "add\n", 4) < 4)
+ strerr_warnwu6sys("write to ", pathat, "/", list, "/", fn) ;
+ close(fd) ;
+ }
}
+ if (errno) strerr_diefu4sys(111, "readdir ", pathat, "/", list) ;
+ dir_close(dir) ;
+}
+static int scan_dir (char const *path, int add_devices)
+{
+ DIR *dir ;
+ int fdpath = open(path, O_RDONLY | O_DIRECTORY) ;
+ if (fdpath < 0) return 0 ;
+ dir = fdopendir(fdpath) ;
+ if (!dir) strerr_diefu2sys(111, "fdopendir ", path) ;
+ for (;;)
{
- size_t len ;
- size_t i = 0 ;
- char buf[UEVENT_MAX_SIZE] ;
- int fd = openat(fddir, "uevent", O_RDONLY) ;
- if (fd < 0)
- strerr_diefu6sys(111, "open uevent in ", sysdev, "/", sub, "/", name) ;
- len = allread(fd, buf, UEVENT_MAX_SIZE) ;
- if (!len) strerr_diefu6sys(111, "read uevent in ", sysdev, "/", sub, "/", name) ;
- close(fd) ;
- for (; i < len ; i++) if (buf[i] == '\n') buf[i] = 0 ;
- if (buffer_put(buffer_1, buf, len) < 0) die1() ;
+ direntry *d ;
+ errno = 0 ;
+ d = readdir(dir) ;
+ if (!d) break ;
+ if (d->d_name[0] == '.') continue ;
+ if (add_devices)
+ {
+ size_t dlen = strlen(d->d_name) ;
+ char fn[dlen + 9] ;
+ memcpy(fn, d->d_name, dlen) ;
+ memcpy(fn + dlen, "/devices", 9) ;
+ scan_subdir(fdpath, path, fn) ;
+ }
+ else scan_subdir(fdpath, path, d->d_name) ;
}
-
- if (buffer_put(buffer_1, "", 1) < 1) die1() ;
+ if (errno) strerr_diefu2sys(111, "readdir ", path) ;
+ dir_close(dir) ;
+ return 1 ;
}
+
int main (int argc, char const *const *argv, char const *const *envp)
{
char const *slashsys = "/sys" ;
- size_t slashsyslen ;
PROG = "mdevd-coldplug" ;
{
subgetopt_t l = SUBGETOPT_ZERO ;
@@ -83,51 +96,18 @@ int main (int argc, char const *const *argv, char const *const *envp)
argc -= l.ind ; argv += l.ind ;
}
- slashsyslen = strlen(slashsys) ;
{
- int fdsysdev ;
- DIR *dirsysdev ;
- char sysdev[slashsyslen + 5] ;
- memcpy(sysdev, slashsys, slashsyslen) ;
- memcpy(sysdev + slashsyslen, "/dev", 5) ;
- fdsysdev = open(sysdev, O_RDONLY | O_DIRECTORY) ;
- if (fdsysdev < 0) strerr_diefu2sys(111, "open ", sysdev) ;
- dirsysdev = fdopendir(fdsysdev) ;
- if (!dirsysdev) strerr_diefu2sys(111, "fdopendir ", sysdev) ;
- for (;;)
+ size_t slashsyslen = strlen(slashsys) ;
+ char fn[slashsyslen + 11] ;
+ memcpy(fn, slashsys, slashsyslen) ;
+ memcpy(fn + slashsyslen, "/subsystem", 11) ;
+ if (!scan_dir(fn, 1))
{
- direntry *d ;
- int fdsub ;
- DIR *dirsub ;
- errno = 0 ;
- d = readdir(dirsysdev) ;
- if (!d) break ;
- if (d->d_name[0] == '.') continue ;
- fdsub = openat(fdsysdev, d->d_name, O_RDONLY | O_DIRECTORY) ;
- if (fdsub < 0) strerr_diefu4sys(111, "open ", sysdev, "/", d->d_name) ;
- dirsub = fdopendir(fdsub) ;
- if (!dirsub) strerr_diefu4sys(111, "fdopendir ", sysdev, "/", d->d_name) ;
- for (;;)
- {
- direntry *dd ;
- int fddevice ;
- errno = 0 ;
- dd = readdir(dirsub) ;
- if (!dd) break ;
- if (dd->d_name[0] == '.') continue ;
- fddevice = openat(fdsub, dd->d_name, O_RDONLY | O_DIRECTORY) ;
- if (fddevice < 0) strerr_diefu6sys(111, "open ", sysdev, "/", d->d_name, "/", dd->d_name) ;
- create_event(fddevice, sysdev, d->d_name, dd->d_name) ;
- close(fddevice) ;
- }
- if (errno) strerr_diefu4sys(111, "readdir ", sysdev, "/", d->d_name) ;
- dir_close(dirsub) ;
- close(fdsub) ;
+ memcpy(fn + slashsyslen + 1, "class", 6) ;
+ if (!scan_dir(fn, 0)) strerr_diefu2sys(111, "open ", fn) ;
+ memcpy(fn + slashsyslen + 1, "bus", 4) ;
+ if (!scan_dir(fn, 1)) strerr_diefu2sys(111, "open ", fn) ;
}
- if (errno) strerr_diefu2sys(111, "readdir ", sysdev) ;
- dir_close(dirsysdev) ;
- close(fdsysdev) ;
}
- if (!buffer_flush(buffer_1)) die1() ;
return 0 ;
}
diff --git a/src/mdevd/mdevd-netlink.c b/src/mdevd/mdevd-netlink.c
deleted file mode 100644
index 3f55f23..0000000
--- a/src/mdevd/mdevd-netlink.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/* ISC license. */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include <sys/socket.h>
-#include <linux/netlink.h>
-#include <skalibs/types.h>
-#include <skalibs/allreadwrite.h>
-#include <skalibs/siovec.h>
-#include <skalibs/buffer.h>
-#include <skalibs/sgetopt.h>
-#include <skalibs/error.h>
-#include <skalibs/strerr2.h>
-#include <skalibs/iopause.h>
-#include <skalibs/djbunix.h>
-#include <skalibs/sig.h>
-#include <skalibs/selfpipe.h>
-#include "mdevd.h"
-
-#define USAGE "mdevd-netlink [ -d notification-fd ] [ -v verbosity ] [ -b kbufsz ]"
-#define dieusage() strerr_dieusage(100, USAGE)
-#define dienomem() strerr_diefu1sys(111, "build string") ;
-
-static unsigned int cont = 1, verbosity = 1 ;
-
-static inline ssize_t fd_recvmsg (int fd, struct msghdr *hdr)
-{
- ssize_t r ;
- do r = recvmsg(fd, hdr, MSG_DONTWAIT) ;
- while ((r == -1) && (errno == EINTR)) ;
- return r ;
-}
-
-static inline int netlink_init_stdin (unsigned int kbufsz)
-{
- struct sockaddr_nl nl = { .nl_family = AF_NETLINK, .nl_pad = 0, .nl_groups = 1, .nl_pid = 0 } ;
- close(0) ;
- if (socket_internal(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT, DJBUNIX_FLAG_NB|DJBUNIX_FLAG_COE) < 0
- || bind(0, (struct sockaddr *)&nl, sizeof(struct sockaddr_nl)) < 0)
- return 0 ;
-
- if (setsockopt(0, SOL_SOCKET, SO_RCVBUFFORCE, &kbufsz, sizeof(unsigned int)) < 0
- && errno == EPERM
- && setsockopt(0, SOL_SOCKET, SO_RCVBUF, &kbufsz, sizeof(unsigned int)) < 0)
- return 0 ;
- return 1 ;
-}
-
-static inline void handle_signals (void)
-{
- for (;;)
- {
- int c = selfpipe_read() ;
- switch (c)
- {
- case -1 : strerr_diefu1sys(111, "selfpipe_read") ;
- case 0 : return ;
- case SIGTERM :
- cont = 0 ;
- fd_close(0) ;
- break ;
- default :
- strerr_dief1x(101, "internal error: inconsistent signal state. Please submit a bug-report.") ;
- }
- }
-}
-
-static inline void handle_stdout (void)
-{
- if (!buffer_flush(buffer_1) && !error_isagain(errno))
- strerr_diefu1sys(111, "flush stdout") ;
-}
-
-static inline void handle_netlink (void)
-{
- struct sockaddr_nl nl;
- struct iovec v[2] ;
- struct msghdr msg =
- {
- .msg_name = &nl,
- .msg_namelen = sizeof(struct sockaddr_nl),
- .msg_iov = v,
- .msg_iovlen = 2,
- .msg_control = 0,
- .msg_controllen = 0,
- .msg_flags = 0
- } ;
- ssize_t r ;
- buffer_wpeek(buffer_1, v) ;
- siovec_trunc(v, 2, siovec_len(v, 2) - 1) ;
- r = sanitize_read(fd_recvmsg(0, &msg)) ;
- if (r < 0)
- {
- if (errno == EPIPE)
- {
- if (verbosity >= 2) strerr_warnw1x("received EOF on netlink") ;
- cont = 0 ;
- fd_close(0) ;
- return ;
- }
- else strerr_diefu1sys(111, "receive netlink message") ;
- }
- if (!r) return ;
- if (msg.msg_flags & MSG_TRUNC)
- strerr_diefu2x(111, "buffer too small for ", "netlink message") ;
- if (nl.nl_pid)
- {
- if (verbosity >= 3)
- {
- char fmt[PID_FMT] ;
- fmt[pid_fmt(fmt, nl.nl_pid)] = 0 ;
- strerr_warnw3x("netlink message", " from userspace process ", fmt) ;
- }
- return ;
- }
- buffer_wseek(buffer_1, r) ;
- buffer_putnoflush(buffer_1, "", 1) ;
-}
-
-
-int main (int argc, char const *const *argv, char const *const *envp)
-{
- iopause_fd x[3] = { { .events = IOPAUSE_READ }, { .fd = 1 }, { .fd = 0 } } ;
- unsigned int notif = 0 ;
- PROG = "mdevd-netlink" ;
- {
- unsigned int kbufsz = 65536 ;
- subgetopt_t l = SUBGETOPT_ZERO ;
- for (;;)
- {
- int opt = subgetopt_r(argc, argv, "d:v:b:", &l) ;
- if (opt == -1) break ;
- switch (opt)
- {
- case 'd' : if (!uint0_scan(l.arg, &notif) || notif < 3) dieusage() ; break ;
- case 'v' : if (!uint0_scan(l.arg, &verbosity)) dieusage() ; break ;
- case 'b' : if (!uint0_scan(l.arg, &kbufsz)) dieusage() ; break ;
- default : dieusage() ;
- }
- }
- argc -= l.ind ; argv += l.ind ;
- if (!netlink_init_stdin(kbufsz)) strerr_diefu1sys(111, "init netlink") ;
- }
-
- x[0].fd = selfpipe_init() ;
- if (x[0].fd < 0) strerr_diefu1sys(111, "init selfpipe") ;
- if (selfpipe_trap(SIGTERM) < 0) strerr_diefu1sys(111, "trap SIGTERM") ;
-
- if (verbosity >= 2) strerr_warni1x("starting") ;
- if (notif)
- {
- fd_write(notif, "\n", 1) ;
- fd_close(notif) ;
- }
-
- while (cont || buffer_len(buffer_1))
- {
- int r ;
- x[1].events = buffer_len(buffer_1) ? IOPAUSE_WRITE : 0 ;
- x[2].events = buffer_available(buffer_1) >= UEVENT_MAX_SIZE + 1 ? IOPAUSE_READ : 0 ;
- r = iopause(x, 2 + cont, 0, 0) ;
- if (r < 0) strerr_diefu1sys(111, "iopause") ;
- if (!r) continue ;
- if (x[1].revents & IOPAUSE_EXCEPT) break ;
- if (x[1].revents & IOPAUSE_WRITE) handle_stdout() ;
- if (x[0].revents & (IOPAUSE_READ | IOPAUSE_EXCEPT)) handle_signals() ;
- if (cont && x[2].events & IOPAUSE_READ && x[2].revents & (IOPAUSE_READ | IOPAUSE_EXCEPT))
- handle_netlink() ;
- }
- if (verbosity >= 2) strerr_warni1x("exiting") ;
- return 0 ;
-}
diff --git a/src/mdevd/mdevd.c b/src/mdevd/mdevd.c
index 7fafea0..ca1e070 100644
--- a/src/mdevd/mdevd.c
+++ b/src/mdevd/mdevd.c
@@ -1,7 +1,11 @@
/* ISC license. */
-#include <sys/sysmacros.h> /* makedev, major, minor */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
#include <sys/types.h>
+#include <sys/sysmacros.h> /* makedev, major, minor */
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
@@ -15,10 +19,12 @@
#include <regex.h>
#include <libgen.h> /* basename */
#include <stdio.h> /* rename */
+#include <sys/socket.h>
+#include <linux/netlink.h>
+
#include <skalibs/types.h>
#include <skalibs/allreadwrite.h>
#include <skalibs/bytestr.h>
-#include <skalibs/buffer.h>
#include <skalibs/strerr2.h>
#include <skalibs/sgetopt.h>
#include <skalibs/sig.h>
@@ -28,16 +34,17 @@
#include <skalibs/env.h>
#include <skalibs/djbunix.h>
#include <skalibs/iopause.h>
+#include <skalibs/socket.h>
#include <skalibs/skamisc.h>
#include <skalibs/surf.h>
#include <skalibs/random.h>
-#include "mdevd.h"
-#define USAGE "mdevd [ -v verbosity ] [ -f conffile ] [ -n ] [ -s slashsys ] [ -d slashdev ]"
+#define USAGE "mdevd [ -v verbosity ] [ -1 ] [ -b kbufsz ] [ -f conffile ] [ -n ] [ -s slashsys ] [ -d slashdev ]"
#define dieusage() strerr_dieusage(100, USAGE)
-#define BUFSIZE 8192
+#define CONFBUFSIZE 8192
#define UEVENT_MAX_VARS 63
+#define UEVENT_MAX_SIZE 4096
#define ACTION_NONE 0x0
#define ACTION_ADD 0x1
@@ -177,6 +184,103 @@ static int makesubdirs (char *path)
}
+ /* Netlink isolation layer */
+
+static inline ssize_t fd_recvmsg (int fd, struct msghdr *hdr)
+{
+ ssize_t r ;
+ do r = recvmsg(fd, hdr, MSG_DONTWAIT) ;
+ while ((r == -1) && (errno == EINTR)) ;
+ return r ;
+}
+
+static inline int netlink_init (unsigned int kbufsz)
+{
+ struct sockaddr_nl nl = { .nl_family = AF_NETLINK, .nl_pad = 0, .nl_groups = 1, .nl_pid = 0 } ;
+ int fd = socket_internal(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT, DJBUNIX_FLAG_NB|DJBUNIX_FLAG_COE) ;
+ if (fd < 0) return -1 ;
+ if (bind(fd, (struct sockaddr *)&nl, sizeof(struct sockaddr_nl)) < 0
+ || (setsockopt(0, SOL_SOCKET, SO_RCVBUFFORCE, &kbufsz, sizeof(unsigned int)) < 0
+ && errno == EPERM
+ && setsockopt(0, SOL_SOCKET, SO_RCVBUF, &kbufsz, sizeof(unsigned int)) < 0))
+ {
+ fd_close(fd) ;
+ return -1 ;
+ }
+ return fd ;
+}
+
+static inline size_t netlink_read (char *s)
+{
+ struct sockaddr_nl nl;
+ struct iovec v = { .iov_base = s, .iov_len = UEVENT_MAX_SIZE } ;
+ struct msghdr msg =
+ {
+ .msg_name = &nl,
+ .msg_namelen = sizeof(struct sockaddr_nl),
+ .msg_iov = &v,
+ .msg_iovlen = 1,
+ .msg_control = 0,
+ .msg_controllen = 0,
+ .msg_flags = 0
+ } ;
+ ssize_t r = sanitize_read(fd_recvmsg(0, &msg)) ;
+ if (r < 0)
+ {
+ if (errno == EPIPE)
+ {
+ if (verbosity >= 2) strerr_warnw1x("received EOF on netlink") ;
+ cont = 0 ;
+ return 0 ;
+ }
+ else strerr_diefu1sys(111, "receive netlink message") ;
+ }
+ if (!r) return 0 ;
+ if (msg.msg_flags & MSG_TRUNC)
+ strerr_diefu1x(111, "buffer too small for netlink message") ;
+ if (nl.nl_pid)
+ {
+ if (verbosity >= 3)
+ {
+ char fmt[PID_FMT] ;
+ fmt[pid_fmt(fmt, nl.nl_pid)] = 0 ;
+ strerr_warnw2x("received netlink message from userspace process ", fmt) ;
+ }
+ return 0 ;
+ }
+ if (s[r-1])
+ {
+ if (verbosity) strerr_warnw2x("received invalid event: ", "improperly terminated") ;
+ return 0 ;
+ }
+ if (!strstr(s, "@/"))
+ {
+ if (verbosity) strerr_warnw2x("received invalid event: ", "bad initial summary") ;
+ return 0 ;
+ }
+ return r ;
+}
+
+static inline int uevent_read (struct uevent_s *event)
+{
+ unsigned short len = 0 ;
+ event->len = netlink_read(event->buf) ;
+ if (!event->len) return 0 ;
+ event->varn = 0 ;
+ while (len < event->len)
+ {
+ if (event->varn >= UEVENT_MAX_VARS)
+ {
+ if (verbosity) strerr_warnw2x("received invalid event: ", "too many variables") ;
+ return 0 ;
+ }
+ event->vars[event->varn++] = len ;
+ len += strlen(event->buf + len) + 1 ;
+ }
+ return 1 ;
+}
+
+
/* mdev.conf parsing. See PARSING.txt for details. */
/* The first pass is simple. The goal is just to compute scriptlen and envmatchlen. */
@@ -840,7 +944,7 @@ static inline void on_event (struct uevent_s *event, scriptelem const *script, u
/* Tying it all together */
-static inline int handle_signals (void)
+static inline void handle_signals (void)
{
for (;;)
{
@@ -848,8 +952,9 @@ static inline int handle_signals (void)
switch (c)
{
case -1 : strerr_diefu1sys(111, "selfpipe_read") ;
- case 0 : return 0 ;
- case SIGHUP : return 1 ;
+ case SIGTERM :
+ case SIGHUP : cont = c == SIGHUP ;
+ case 0 : return ;
case SIGCHLD :
if (!pid) wait_reap() ;
else
@@ -869,54 +974,37 @@ static inline int handle_signals (void)
}
}
-static void handle_stdin (struct uevent_s *event, scriptelem const *script, unsigned short scriptlen, char const *storage, struct envmatch_s const *envmatch, size_t *w)
+static inline void handle_event (scriptelem const *script, unsigned short scriptlen, char const *storage, struct envmatch_s const *envmatch)
{
- while (!pid)
- {
- ssize_t r ;
- if (event->len >= UEVENT_MAX_SIZE)
- strerr_dief2x(1, "received invalid event: ", "too long") ;
- r = sanitize_read(getlnmax(buffer_0, event->buf + event->len, UEVENT_MAX_SIZE - event->len, w, '\0')) ;
- if (r < 0)
- {
- cont = 0 ;
- if (errno != EPIPE && verbosity) strerr_warnwu1sys("read from stdin") ;
- if (event->len) strerr_dief1x(1, "received incomplete event") ;
- }
- if (r <= 0) break ;
- if (*w > 1)
- {
- if (event->varn >= UEVENT_MAX_VARS)
- strerr_dief2x(1, "received invalid event: ", "too many variables") ;
- event->vars[event->varn++] = event->len ;
- event->len += *w ;
- }
- else
- {
- if (event->varn > 1) on_event(event, script, scriptlen, storage, envmatch) ;
- event->len = 0 ;
- event->varn = 0 ;
- }
- *w = 0 ;
- }
+ struct uevent_s event = UEVENT_ZERO ;
+ if (uevent_read(&event) && event.varn > 1)
+ on_event(&event, script, scriptlen, storage, envmatch) ;
}
int main (int argc, char const *const *argv)
{
char const *configfile = "/etc/mdev.conf" ;
- iopause_fd x[2] = { { .events = IOPAUSE_READ }, { .fd = 0 } } ;
+ iopause_fd x[2] = { { .events = IOPAUSE_READ }, { .events = IOPAUSE_READ } } ;
+ unsigned int notif = 0 ;
+ unsigned int kbufsz = 65536 ;
+ char const *slashdev = "/dev" ;
PROG = "mdevd" ;
{
- char const *slashdev = "/dev" ;
subgetopt_t l = SUBGETOPT_ZERO ;
for (;;)
{
- int opt = subgetopt_r(argc, argv, "nv:f:s:d:F:", &l) ;
+ int opt = subgetopt_r(argc, argv, "nv:D:b:f:s:d:F:", &l) ;
if (opt == -1) break ;
switch (opt)
{
case 'n' : dryrun = 1 ; break ;
case 'v' : if (!uint0_scan(l.arg, &verbosity)) dieusage() ; break ;
+ case 'D' :
+ if (!uint0_scan(l.arg, &notif)) dieusage() ;
+ if (notif < 3) strerr_dief1x(100, "notification fd must be 3 or more") ;
+ if (fcntl(notif, F_GETFD) < 0) strerr_dief1sys(100, "invalid notification fd") ;
+ break ;
+ case 'b' : if (!uint0_scan(l.arg, &kbufsz)) dieusage() ; break ;
case 'f' : configfile = l.arg ; break ;
case 's' : slashsys = l.arg ; break ;
case 'd' : slashdev = l.arg ; break ;
@@ -925,13 +1013,13 @@ int main (int argc, char const *const *argv)
}
}
argc -= l.ind ; argv += l.ind ;
- if (configfile[0] != '/') strerr_dief2x(100, configfile, " is not an absolute path") ;
- if (slashsys[0] != '/') strerr_dief2x(100, slashsys, " is not an absolute path") ;
- if (slashdev[0] != '/') strerr_dief2x(100, slashdev, " is not an absolute path") ;
- if (fwbase[0] != '/') strerr_dief2x(100, fwbase, " is not an absolute path") ;
- if (chdir(slashdev) < 0) strerr_diefu2sys(111, "chdir to ", slashdev) ;
}
+ if (configfile[0] != '/') strerr_dief2x(100, configfile, " is not an absolute path") ;
+ if (slashsys[0] != '/') strerr_dief2x(100, slashsys, " is not an absolute path") ;
+ if (slashdev[0] != '/') strerr_dief2x(100, slashdev, " is not an absolute path") ;
+ if (fwbase[0] != '/') strerr_dief2x(100, fwbase, " is not an absolute path") ;
+ if (chdir(slashdev) < 0) strerr_diefu2sys(111, "chdir to ", slashdev) ;
if (strlen(slashsys) >= PATH_MAX - 1) strerr_dief1x(100, "paths too long") ;
if (!fd_sanitize()) strerr_diefu1sys(111, "sanitize standard fds") ;
@@ -942,13 +1030,16 @@ int main (int argc, char const *const *argv)
root_min = minor(st.st_dev) ;
}
- if (ndelay_on(0) < 0) strerr_diefu1sys(111, "set stdin nonblocking") ;
+ x[1].fd = netlink_init(kbufsz) ;
+ if (x[1].fd < 0) strerr_diefu1sys(111, "init netlink") ;
+
x[0].fd = selfpipe_init() ;
if (x[0].fd < 0) strerr_diefu1sys(111, "init selfpipe") ;
if (sig_ignore(SIGPIPE) < 0) strerr_diefu1sys(111, "ignore SIGPIPE") ;
{
sigset_t set ;
sigemptyset(&set) ;
+ sigaddset(&set, SIGTERM) ;
sigaddset(&set, SIGCHLD) ;
sigaddset(&set, SIGHUP) ;
if (selfpipe_trapset(&set) < 0)
@@ -957,43 +1048,47 @@ int main (int argc, char const *const *argv)
mdevd_random_init() ;
umask(0) ;
+ if (notif)
+ {
+ fd_write(notif, "\n", 1) ;
+ fd_close(notif) ;
+ }
+
while (cont)
{
ssize_t len ;
unsigned short scriptlen = 0 ;
unsigned short envmatchlen = 0 ;
- char buf[BUFSIZE] ;
- len = openreadnclose(configfile, buf, BUFSIZE - 1) ;
+ char storage[CONFBUFSIZE] ;
+ len = openreadnclose(configfile, storage, CONFBUFSIZE - 1) ;
if (len < 0)
{
if (errno != ENOENT) strerr_diefu2sys(111, "read ", configfile) ;
if (verbosity) strerr_warnwu2sys("read ", configfile) ;
len = 0 ;
}
- buf[len++] = 0 ;
- script_firstpass(buf, &scriptlen, &envmatchlen) ;
+ storage[len++] = 0 ;
+ script_firstpass(storage, &scriptlen, &envmatchlen) ;
{
- size_t w = 0 ;
- int reload = 0 ;
- struct uevent_s event = UEVENT_ZERO ;
struct envmatch_s envmatch[envmatchlen ? envmatchlen : 1] ;
scriptelem script[scriptlen + 1] ;
memset(script, 0, scriptlen * sizeof(scriptelem)) ;
script[scriptlen++] = scriptelem_catchall ;
- script_secondpass(buf, script, envmatch) ;
- while (pid || (cont && (!reload || buffer_len(buffer_0))))
+ script_secondpass(storage, script, envmatch) ;
+ cont = 2 ;
+
+ while (pid || cont == 2)
{
- if (buffer_len(buffer_0)) handle_stdin(&event, script, scriptlen, buf, envmatch, &w) ;
- x[1].events = pid ? 0 : IOPAUSE_READ ;
- if (iopause(x, 1 + cont, 0, 0) < 0) strerr_diefu1sys(111, "iopause") ;
- if (x[0].revents & IOPAUSE_READ && handle_signals()) reload = 1 ;
- if (cont && !pid && x[1].revents & IOPAUSE_READ)
- handle_stdin(&event, script, scriptlen, buf, envmatch, &w) ;
+ if (iopause(x, 1 + (!pid && cont == 2), 0, 0) < 0) strerr_diefu1sys(111, "iopause") ;
+ if (x[0].revents & IOPAUSE_READ)
+ handle_signals() ;
+ if (!pid && cont == 2 && x[1].revents & IOPAUSE_READ)
+ handle_event(script, scriptlen, storage, envmatch) ;
}
+
script_free(script, scriptlen, envmatch, envmatchlen) ;
}
}
- ndelay_off(0) ;
return 0 ;
}
diff --git a/src/mdevd/mdevd.h b/src/mdevd/mdevd.h
deleted file mode 100644
index a99f692..0000000
--- a/src/mdevd/mdevd.h
+++ /dev/null
@@ -1,8 +0,0 @@
- /* ISC license. */
-
-#ifndef MDEVD_H
-#define MDEVD_H
-
-#define UEVENT_MAX_SIZE 4096
-
-#endif