Daemon to print kernel uevents
Jun 8, 2013 14:57:17 GMT 1
Post by barryk on Jun 8, 2013 14:57:17 GMT 1
I have a C program that waits for Linux kernel uevents and prints them. Uevents are messages that the kernel generates whenever something happens such as a USB stick plugged in or removed. The udevd daemon in the udev (now in systemd) package reads these messages.
Converting the C program to BaCon has been a very interesting exercise. I ran into a bug with RECORD, that Peter fixed:
basic-converter.proboards.com/index.cgi?board=bugs&action=display&thread=498
So, BaCon 2.1.7 is required to compile my program.
I ran into more problems with RECORD, that I reported here:
basic-converter.proboards.com/index.cgi?board=bugs&action=display&thread=500
...however, I was able to work around those, and my program works fine.
I was using IMPORT, until I read bigbass's excellent posts about PROTO:
basic-converter.proboards.com/index.cgi?board=doc&action=display&thread=497
...that is superb!
The "thinness" of BaCon above C, lazy translation, sure does make it easy to convert from C to BaCon. I experimented and found that putting in C syntax here and there gets through OK.
Anyway, here is my program:
After compiling, all you have to do is run it in a terminal, then plug in a USB stick. CTRL-C to kill it.
After stripping, it is 34KB, which is bigger than I expected.
Converting the C program to BaCon has been a very interesting exercise. I ran into a bug with RECORD, that Peter fixed:
basic-converter.proboards.com/index.cgi?board=bugs&action=display&thread=498
So, BaCon 2.1.7 is required to compile my program.
I ran into more problems with RECORD, that I reported here:
basic-converter.proboards.com/index.cgi?board=bugs&action=display&thread=500
...however, I was able to work around those, and my program works fine.
I was using IMPORT, until I read bigbass's excellent posts about PROTO:
basic-converter.proboards.com/index.cgi?board=doc&action=display&thread=497
...that is superb!
The "thinness" of BaCon above C, lazy translation, sure does make it easy to convert from C to BaCon. I experimented and found that putting in C syntax here and there gets through OK.
Anyway, here is my program:
REM (c) Copyright Barry Kauler, June 2013, bkhome.org
REM License GPL3 (refer: /usr/share/doc/legal)
REM libc ref: http://www.gnu.org/software/libc/manual/html_node/Function-Index.html#Function-Index
REM this little daemon reads kernel uevents.
REM from linux/netlink.h...
CONST NETLINK_KOBJECT_UEVENT=15
REM linux/poll.h, only includes asm/poll.h, which only includes asm-generic/poll.h...
CONST POLLIN=1
REM C functions, in libc.so. note, I originally used IMPORT, but PROTO is simpler...
PROTO getpid, socket, bind, poll, recv
REM struct sockaddr_nl, defined in linux/netlink.h...
RECORD nls
LOCAL nl_family TYPE unsigned short
LOCAL nl_pad TYPE unsigned short
LOCAL nl_pid TYPE unsigned int
LOCAL nl_groups TYPE unsigned int
END RECORD
REM struct pollfd, defined in asm-generic/poll.h...
RECORD pfd
LOCAL fd TYPE int
LOCAL events TYPE short
LOCAL revents TYPE short
END RECORD
DECLARE buf TYPE char ARRAY 512
DECLARE eventstatus TYPE int
size_char=SIZEOF(char)
size_buf=size_char*512
size_us=SIZEOF(unsigned short)
size_ui=SIZEOF(unsigned int)
size_nls=(2*size_us)+(2*size_ui)
REM initialise the nls structure...
nls.nl_family = AF_NETLINK
nls.nl_pad = 0
nls.nl_pid = getpid()
nls.nl_groups = -1
REM Open hotplug event netlink socket...
pfd.events = POLLIN
pfd.fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)
IF pfd.fd == -1 THEN END 1
REM listen to netlink socket...
retval=bind(pfd.fd, (void *)&nls.nl_family, size_nls)
IF retval==-1 THEN END 2
WHILE TRUE DO
REM 2 second timeout... note, -1 is wait indefinitely.
eventstatus=poll(&pfd.fd, 1, 2000)
IF eventstatus==-1 THEN END 3
IF eventstatus==0 THEN
PRINT "Two second timeout"
CONTINUE
END IF
REM get the uevent...
len = recv(pfd.fd, buf, size_buf, MSG_DONTWAIT)
IF len==-1 THEN END 4
REM process the uevent...
REM only respond to add@ and remove@ uevents...
IF (buf[0]!='a' & buf[0]!='r') THEN CONTINUE
IF (buf[1]!='d' & buf[1]!='e') THEN CONTINUE
IF (buf[2]!='d' & buf[2]!='m') THEN CONTINUE
PRINT "Next uevent..."
buf[size_buf]=0
str$=buf
PRINT str$
WEND
After compiling, all you have to do is run it in a terminal, then plug in a USB stick. CTRL-C to kill it.
After stripping, it is 34KB, which is bigger than I expected.