Isaac Dunham <ibid...@gmail.com> writes: > Or you can do it with mount, sudo, sh, and nlmon (http://git.r-36.net/nlmon).
Using poll to wait for a message followed by recvmsg for reading it offers (in absence of a timeout) no advantages over just doing a blocking recv. Since this code neither uses control messages nor looks at the returned flags, it can use recvfrom instead of the (more complicated) recvmsg. Considering that it checks for message buffer overflow via len >= sizeof(buf), the MSG_TRUNC flag should probably be used to make the kernel return the real size in case a datagram was truncated. Lastly, the message doesn't have to be copied to a 2nd buffer just to turn the 0-terminated name=value pairs into \n-terminated ones. NB: I admit that I mainly did this because it looked like a nice, simple programming task. ------------ diff --git a/nlmon.c b/nlmon.c index 7339f74..8e965fe 100644 --- a/nlmon.c +++ b/nlmon.c @@ -53,15 +53,50 @@ usage(void) die("usage: %s [-h] [-kl] [-f subsystem]\n", argv0); } +void +print_event_if(char *subsys, char *p, int len) +{ + char *s, *e, *sep; + char *start; + + start = p; + e = p + len; + + /* find start of name=value pairs */ + while (++p < e && *p != '=') + if (!*p) start = s = p + 1; + if (p == e) return; + + do { + sep = p; + + /* skip to end of parameter */ + do ++p; while (p < e && *p); + if (p == e) return; + + if (subsys && strncmp("SUBSYSTEM", s, sep - s) == 0) { + if (strcmp(sep + 1, subsys) != 0) return; + subsys = NULL; + } + + *p = '\n'; + + /* find next = */ + s = ++p; + while (p < e && *p != '=') ++p; + } while (p < e); + + *p++ = '\n'; + write(1, start, p - start); +} + int main(int argc, char *argv[]) { struct sockaddr_nl nls, cnls; - struct pollfd fds; - struct msghdr hdr; - struct iovec iov; - char buf[4097], obuf[4098], *subsystem; - int i, len, olen, slen, showudev, showkernel; + socklen_t cnlslen; + char buf[4097], *subsystem; + int len, showudev, showkernel, sk; showkernel = 1; showudev = 1; @@ -93,9 +128,8 @@ main(int argc, char *argv[]) * messages in userspace. */ - fds.events = POLLIN; - fds.fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); - if (fds.fd < 0) + sk = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); + if (sk < 0) edie("socket"); /* @@ -104,20 +138,15 @@ main(int argc, char *argv[]) * enough buffer. */ - if (bind(fds.fd, (void *)&nls, sizeof(nls))) + if (bind(sk, (void *)&nls, sizeof(nls))) edie("bind"); - buf[sizeof(buf)-1] = '\0'; - while (poll(&fds, 1, -1) > -1) { - iov.iov_base = &buf; - iov.iov_len = sizeof(buf); - memset(&hdr, 0, sizeof(hdr)); - hdr.msg_iov = &iov; - hdr.msg_iovlen = 1; - hdr.msg_name = &cnls; - hdr.msg_namelen = sizeof(cnls); - - len = recvmsg(fds.fd, &hdr, 0); + while (1) { + buf[sizeof(buf)-1] = '\0'; + cnlslen = sizeof(cnls); + len = recvfrom(sk, buf, sizeof(buf), MSG_TRUNC, + (struct sockaddr *)&cnls, &cnlslen); + if (len < 0) { if (errno == EINTR) continue; @@ -126,40 +155,10 @@ main(int argc, char *argv[]) if (len < 32 || len >= sizeof(buf)) continue; - if (!memcmp(buf, "libudev", 8)) { - if (!showudev) - continue; - } else { - if (!showkernel) - continue; - - /* - * Kernel messages should be from root. - */ - if (cnls.nl_pid > 0) - continue; - } - - for (i = 0, olen = 0; i < len; i += slen + 1) { - slen = strlen(buf+i); - if (!slen || !strchr(buf+i, '=')) - continue; - if (subsystem && !strncmp(buf+i, "SUBSYSTEM=", 10) - && !strstr(buf+i+10, subsystem)) { - olen = 0; - break; - } - - snprintf(obuf+olen, sizeof(obuf)-olen-2, - "%s\n", buf+i); - olen += slen + 1; - } - if (olen > 0) { - obuf[olen] = '\n'; - write(1, obuf, olen+1); - } + if ((showudev && memcmp(buf, "libudev", 8) == 0) + || (showkernel && cnls.nl_pid < 1)) + print_event_if(subsystem, buf, len); } return 0; } - _______________________________________________ Dng mailing list Dng@lists.dyne.org https://mailinglists.dyne.org/cgi-bin/mailman/listinfo/dng