diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2018-01-14 17:54:42 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2018-01-14 17:54:42 +0000 |
commit | 4984158b95c5a0c3922cd34940c393652d080f99 (patch) | |
tree | bd110462519e041679dc0332088b43132214fe45 /src | |
parent | c5e7afbd8d62f3217687f21c0691a02797dc0df5 (diff) | |
download | mdevd-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-netlink | 1 | ||||
-rw-r--r-- | src/mdevd/mdevd-coldplug.c | 152 | ||||
-rw-r--r-- | src/mdevd/mdevd-netlink.c | 177 | ||||
-rw-r--r-- | src/mdevd/mdevd.c | 219 | ||||
-rw-r--r-- | src/mdevd/mdevd.h | 8 |
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, ¬if) || 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, ¬if)) 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 |