commit cb0a601f08208245331447ec00db5de4b447ce50
parent 3e475d9f0d2322e6a31dd70f4c1416e79a41aa76
Author: Christoph Lohmann <20h@r-36.net>
Date: Sat, 26 Feb 2011 21:31:38 +0100
Initial commit of rfkilld.
Diffstat:
11 files changed, 359 insertions(+), 118 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,29 +1,55 @@
-# rfkilld - rfkill daemon
+# rfkilld - rfkill daemon
# See LICENSE file for copyright and license details.
include config.mk
-dist:
+SRC = ${NAME}.c
+OBJ = ${SRC:.c=.o}
+
+all: options ${NAME}
+
+options:
+ @echo ${NAME} build options:
+ @echo "CFLAGS = ${CFLAGS}"
+ @echo "LDFLAGS = ${LDFLAGS}"
+ @echo "CC = ${CC}"
+
+.c.o:
+ @echo CC $<
+ @${CC} -c ${CFLAGS} $<
+
+${OBJ}: config.mk
+
+${NAME}: ${OBJ}
+ @echo CC -o $@
+ @${CC} -o $@ ${OBJ} ${LDFLAGS}
+
+clean:
+ @echo cleaning
+ @rm -f ${NAME} ${OBJ} ${NAME}-${VERSION}.tar.gz
+
+dist: clean
@echo creating dist tarball
- @mkdir -p rfkilld-${VERSION}
- @cp -R LICENSE README.md Makefile config.mk \
- bin etc rfkilld-${VERSION}
- @tar -cf rfkilld-${VERSION}.tar rfkilld-${VERSION}
- @gzip rfkilld-${VERSION}.tar
- @rm -rf rfkilld-${VERSION}
-
-install:
- @echo installing rfkilld script to ${DESTDIR}${PREFIX}/bin
- @cp bin/rfkilld ${DESTDIR}${PREFIX}/bin
- @chmod 755 ${DESTDIR}${PREFIX}/bin/rfkilld
- @echo installing etc files into ${DESTDIR}/etc/rfkilld
- @mkdir -p ${DESTDIR}/etc/rfkilld
- @cp -R etc/rfkilld ${DESTDIR}/etc/rfkilld
+ @mkdir -p ${NAME}-${VERSION}
+ @cp -R LICENSE Makefile README.md config.mk \
+ etc ${SRC} *.h ${NAME}-${VERSION}
+ @tar -cf ${NAME}-${VERSION}.tar ${NAME}-${VERSION}
+ @gzip ${NAME}-${VERSION}.tar
+ @rm -rf ${NAME}-${VERSION}
+
+install: all
+ @echo installing executable file to ${DESTDIR}${PREFIX}/bin
+ @mkdir -p ${DESTDIR}${PREFIX}/bin
+ @cp -f ${NAME} ${DESTDIR}${PREFIX}/bin
+ @chmod 755 ${DESTDIR}${PREFIX}/bin/${NAME}
+ @echo installing etc files into ${DESTDIR}/etc/${NAME}
+ @mkdir -p ${DESTDIR}/etc/${NAME}
+ @cp -R etc/${NAME} ${DESTDIR}/etc/${NAME}
uninstall:
- @echo removing rfkilld script from ${DESTDIR}${PREFIX}/bin
- @rm -f ${DESTDIR}${PREFIX}/bin/rfkilld
- @echo removing etc files from ${DESTDIR}/etc/rfkilld
- @rm -rf ${DESTDIR}/etc/rfkilld
+ @echo removing executable file from ${DESTDIR}${PREFIX}/bin
+ @rm -f ${DESTDIR}${PREFIX}/bin/${NAME}
+ @echo removing etc files from ${DESTDIR}/etc/${NAME}
+ @rm -rf ${DESTDIR}/etc/${NAME}
-.PHONY: dist install uninstall
+.PHONY: all options clean dist install uninstall
diff --git a/README.md b/README.md
@@ -0,0 +1,20 @@
+# rfkilld - a rfkill daemon
+
+This daemon listens for rfkill events from the kernel, over a netlink,
+for the »rfkill« subsystem. When an event occurs, the specific proper-
+ties (NAME, TYPE, STATE) are taken and the files
+
+ /etc/rfkilld/$name $state $type
+ /etc/rfkilld/$type $state $name
+
+are run using the shown arguments.
+
+Included are rc.d and conf.d files for being used in Archlinux.
+
+It is recommended to run this in conjunction with conn [0].
+
+
+Have fun!
+
+[0] http://git.r-36.net/conn/
+
diff --git a/arg.h b/arg.h
@@ -0,0 +1,19 @@
+#ifndef ARG_H
+#define ARG_H
+
+#define USED(x) ((void)(x))
+
+extern char *argv0;
+
+#define ARGBEGIN for(argv0 = *argv, argv++, argc--;\
+ argv[0] && argv[0][0]=='-' && argv[0][1];\
+ argc--, argv++) {\
+ char _argc;\
+ _argc = argv[0][1];\
+ switch(_argc)
+#define ARGEND USED(_argc);} USED(argv);USED(argc);
+#define EARGF(x) ((argv[1] == NULL)? ((x), abort(), (char *)0) :\
+ (argc--, argv++, argv[0]))
+
+#endif
+
diff --git a/bin/rfkilld b/bin/rfkilld
@@ -1,96 +0,0 @@
-#!/bin/sh
-
-usage() {
- echo "usage: `basename $1` [-hbl] [-p pidfile] [-e etcdir] [-b]"
-}
-
-UDEVMONITORCMD="/usr/bin/nlmon -p -k"
-ETCDIR="/etc/rfkilld"
-PIDFILE="/var/run/rfkilld.pid"
-dobackground=0
-dodebug=0
-dolog=0
-
-while getopts "ldp:e:" opt;
-do
- case $opt in
- d)
- dodebug=1
- ;;
- p)
- PIDFILE="$OPTARG"
- ;;
- e)
- ETCDIR="$OPTARG"
- ;;
- l)
- dolog=1
- ;;
- *)
- usage $0
- exit 1
- ;;
- esac
-done
-shift $(($OPTIND - 1))
-
-debugcmd=""
-if [ $dodebug -eq 1 ];
-then
- debugcmd="-d"
- set -x
-fi
-
-echo $$ > $PIDFILE 2>&1 >/dev/null
-trap "[ -e $PIDFILE ] && rm $PIDFILE; exit 0;" 2 3 6 9 15
-
-name=
-type=
-state=
-
-$UDEVMONITORCMD | \
-while read status
-do
- [[ "$status" =~ ^RFKILL_NAME=(.*)$ ]] \
- && name="${BASH_REMATCH[1]}"
- [[ "$status" =~ ^RFKILL_TYPE=(.*)$ ]] \
- && type="${BASH_REMATCH[1]}"
- [[ "$status" =~ ^RFKILL_STATE=(.*)$ ]] \
- && state="${BASH_REMATCH[1]}"
-
- if [ "$status" == "" ];
- then
- if [ "$name" == "" ] || [ "$type" == "" ] \
- || [ "$state" == "" ];
- then
- continue
- fi
-
- [ $dodebug -eq 1 ] \
- && logger -t rfkilld "req $name $type $state"
-
- if [ -x $ETCDIR/$name.sh ];
- then
- $ETCDIR/$name.sh $state 2>&1 >/dev/null &
-
- [ $dolog -eq 1 ] \
- && logger -t rfkilld "ran $name.sh $state"
- fi
-
- if [ -x $ETCDIR/$type.sh ];
- then
- $ETCDIR/$type.sh $state $name 2>&1 >/dev/null &
-
- [ $dolog -eq 1 ] \
- && logger -t rfkilld \
- "ran $type.sh $state $name"
- fi
-
- name=
- type=
- state=
- fi
-done
-
-exit 0
-
diff --git a/config.mk b/config.mk
@@ -1,4 +1,5 @@
-# rfkilld version
+# rfkilld metadata
+NAME = rfkilld
VERSION = 0.2
# Customize below to fit your system
@@ -7,3 +8,16 @@ VERSION = 0.2
PREFIX = /usr
MANPREFIX = ${PREFIX}/share/man
+# includes and libs
+INCS = -I. -I/usr/include
+LIBS = -L/usr/lib -lc -ludev
+
+# flags
+CPPFLAGS = -DVERSION=\"${VERSION}\"
+CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
+LDFLAGS = -g ${LIBS}
+#LDFLAGS = -s ${LIBS}
+
+# compiler and linker
+CC = cc
+
diff --git a/etc/conf.d/rfkilld b/etc/conf.d/rfkilld
@@ -0,0 +1,5 @@
+#
+# Parameters to be passed to rfkilld.
+#
+RFKILLD_ARGS="-l -b"
+
diff --git a/etc/rc.d/rfkilld b/etc/rc.d/rfkilld
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+. /etc/rc.conf
+. /etc/rc.d/functions
+. /etc/conf.d/rfkilld
+
+PID=`pidof -o %PPID /usr/bin/rfkilld`
+case "$1" in
+ start)
+ stat_busy "Starting rfkilld"
+ [ -z "$PID" ] && /usr/bin/rfkilld $RFKILLD_ARGS 2>&1
+ if [ $? -gt 0 ]; then
+ stat_fail
+ else
+ PID=`pidof -o %PPID /usr/bin/rfkilld`
+ add_daemon rfkilld
+ stat_done
+ fi
+ ;;
+ stop)
+ stat_busy "Stopping rfkilld"
+ [ ! -z "$PID" ] && kill -KILL $PID &>/dev/null
+ if [ $? -gt 0 ]; then
+ stat_fail
+ else
+ rm_daemon rfkilld
+ stat_done
+ fi
+ ;;
+ restart)
+ $0 stop
+ $0 start
+ ;;
+ *)
+ echo "usage: $0 {start|stop|restart}"
+esac
+exit 0
diff --git a/etc/rfkilld/bluetooth.sh b/etc/rfkilld/bluetooth.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+case $1 in
+ 0)
+ ;;
+ 1)
+ rfkill block bluetooth
+ ;;
+ *)
+ exit 1
+ ;;
+esac
+
+exit 0
+
diff --git a/etc/rfkilld/wlan.sh b/etc/rfkilld/wlan.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+case $1 in
+ 0)
+ conn -k wifi
+ ;;
+ 1)
+ conn -s wifi
+ ;;
+ *)
+ exit 1
+ ;;
+esac
+
+exit 0
+
diff --git a/etc/rfkilld/wwan.sh b/etc/rfkilld/wwan.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+case $1 in
+ 0)
+ ;;
+ 1|2)
+ # conn -s wwan
+ ;;
+ *)
+ exit 1
+ ;;
+esac
+
+exit 0
+
diff --git a/rfkilld.c b/rfkilld.c
@@ -0,0 +1,170 @@
+/*
+ * Copy me if you can.
+ * by 20h
+ */
+
+#define _XOPEN_SOURCE
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <libudev.h>
+#include <poll.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdarg.h>
+#include <syslog.h>
+#include <signal.h>
+#include <strings.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "arg.h"
+
+char *argv0;
+char *etcdir = "/etc/rfkilld";
+int running = 1;
+int dolog = 0;
+
+void
+runifexecutable(char *file, char *oname, char *ostate)
+{
+ char cmd[512], name[64], state[16];
+ int pid;
+
+ strncpy(name, oname, sizeof(name));
+ strncpy(state, ostate, sizeof(state));
+
+ snprintf(cmd, sizeof(cmd), "%s/%s.sh", etcdir, file);
+ if (!access(cmd, X_OK)) {
+ if (!(pid = fork())) {
+ if (!fork())
+ if(execl(cmd, name, state, NULL) < 0)
+ perror("execl");
+ exit(EXIT_SUCCESS);
+ }
+ waitpid(pid, NULL, 0);
+ }
+}
+
+void
+runscripts(struct udev_device *dev)
+{
+ struct udev_list_entry *props;
+ char *type, *name, *state;
+
+ props = udev_device_get_properties_list_entry(dev);
+ type = (char *)udev_device_get_property_value(dev, "RFKILL_NAME");
+ name = (char *)udev_device_get_property_value(dev, "RFKILL_TYPE");
+ state = (char *)udev_device_get_property_value(dev, "RFKILL_STATE");
+
+ if (dolog)
+ syslog(LOG_NOTICE, "name: %s; type: %s; state: %s;\n",
+ name, type, state);
+
+ runifexecutable(name, type, state);
+ runifexecutable(type, name, state);
+}
+
+void
+sighandler(int sig)
+{
+ switch(sig) {
+ case SIGCHLD:
+ while(waitpid(-1, NULL, WNOHANG) > 0);
+ break;
+ case SIGHUP:
+ case SIGINT:
+ case SIGQUIT:
+ case SIGABRT:
+ case SIGTERM:
+ closelog();
+ running = 0;
+ break;
+ default:
+ break;
+ }
+}
+
+void
+initsignals(void)
+{
+ signal(SIGCHLD, sighandler);
+ signal(SIGHUP, sighandler);
+ signal(SIGINT, sighandler);
+ signal(SIGQUIT, sighandler);
+ signal(SIGABRT, sighandler);
+ signal(SIGTERM, sighandler);
+ signal(SIGKILL, sighandler);
+}
+
+void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-hbl] [-e etcdir]\n", argv0);
+ fflush(stderr);
+ exit(EXIT_FAILURE);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct udev *udev;
+ struct udev_monitor *mon;
+ struct udev_device *dev;
+ struct pollfd fds[1];
+ int ret, dodaemonize;
+
+ dodaemonize = 0;
+
+ ARGBEGIN {
+ case 'b':
+ dodaemonize = 1;
+ break;
+ case 'l':
+ dolog = 1;
+ break;
+ case 'e':
+ etcdir = EARGF(usage());
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if(dodaemonize)
+ daemon(0, 0);
+
+ if(dolog)
+ openlog("rfkilld", 0, LOG_DAEMON);
+
+ initsignals();
+
+ udev = udev_new();
+ if (!udev) {
+ perror("udev_new");
+ exit(EXIT_FAILURE);
+ }
+
+ mon = udev_monitor_new_from_netlink(udev, "kernel");
+ udev_monitor_filter_add_match_subsystem_devtype(mon, "rfkill", NULL);
+ udev_monitor_enable_receiving(mon);
+
+ fds[0].fd = udev_monitor_get_fd(mon);
+ fds[0].events = POLLIN|POLLPRI;
+ while(running) {
+ ret = poll(fds, 1, 500);
+ if (ret > 0) {
+ if ((fds[0].revents & POLLIN) \
+ || (fds[0].revents & POLLPRI)) {
+ dev = udev_monitor_receive_device(mon);
+ if (dev) {
+ runscripts(dev);
+ udev_device_unref(dev);
+ }
+ }
+ }
+ }
+
+ exit(EXIT_SUCCESS);
+}
+