chiark / gitweb /
rfkill: add new rfkill tool to save/restore rfkill state across reboots
authorLennart Poettering <lennart@poettering.net>
Mon, 14 Oct 2013 02:31:49 +0000 (04:31 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 14 Oct 2013 02:31:49 +0000 (04:31 +0200)
This works analogous to the existing backlight and random seed services

.gitignore
Makefile-man.am
Makefile.am
configure.ac
man/systemd-backlight@.service.xml
man/systemd-rfkill@.service.xml [new file with mode: 0644]
rules/99-systemd.rules.in
src/rfkill/Makefile [new symlink]
src/rfkill/rfkill.c [new file with mode: 0644]
units/.gitignore
units/systemd-rfkill@.service.in [new file with mode: 0644]

index 40015debaf0d16118944774ecb23d6c1e0d8ba65..587b6d07eff54dd264170a6380b7b12fecb719c1 100644 (file)
@@ -69,6 +69,7 @@
 /systemd-remount-api-vfs
 /systemd-remount-fs
 /systemd-reply-password
+/systemd-rfkill
 /systemd-run
 /systemd-shutdown
 /systemd-shutdownd
index c8a43423961aee697d8e7cf39109c1442895bbfd..6c9b790989a90eaecfc2b0c01e11aec292dfee7e 100644 (file)
@@ -744,6 +744,17 @@ man/systemd-readahead.html: man/systemd-readahead-replay.service.html
 
 endif
 
+if ENABLE_RFKILL
+MANPAGES += \
+       man/systemd-rfkill@.service.8
+MANPAGES_ALIAS += \
+       man/systemd-rfkill.8
+man/systemd-rfkill.8: man/systemd-rfkill@.service.8
+man/systemd-rfkill.html: man/systemd-rfkill@.service.html
+       $(html-alias)
+
+endif
+
 if ENABLE_TIMEDATED
 MANPAGES += \
        man/systemd-timedated.service.8 \
index 7b6df1b608b4ba83e8827a27d188db7fd8230a8c..66012441c08f398a78ebd3902b0c6bec47568710 100644 (file)
@@ -3433,6 +3433,26 @@ endif
 EXTRA_DIST += \
        units/systemd-backlight@.service.in
 
+# ------------------------------------------------------------------------------
+if ENABLE_RFKILL
+rootlibexec_PROGRAMS += \
+       systemd-rfkill
+
+nodist_systemunit_DATA += \
+       units/systemd-rfkill@.service
+
+systemd_rfkill_SOURCES = \
+       src/rfkill/rfkill.c
+
+systemd_rfkill_LDADD = \
+       libsystemd-label.la \
+       libsystemd-shared.la \
+       libudev-private.la
+endif
+
+EXTRA_DIST += \
+       units/systemd-rfkill@.service.in
+
 # ------------------------------------------------------------------------------
 if HAVE_LIBCRYPTSETUP
 rootlibexec_PROGRAMS += \
index 00ee9bb92d78d11639c9918eb49ce0072b1ac86e..6cda8f967f77aaee2bd1989aaf7aab16551c7ff9 100644 (file)
@@ -704,6 +704,14 @@ if test "x$enable_backlight" != "xno"; then
 fi
 AM_CONDITIONAL(ENABLE_BACKLIGHT, [test "$have_backlight" = "yes"])
 
+# ------------------------------------------------------------------------------
+have_rfkill=no
+AC_ARG_ENABLE(rfkill, AS_HELP_STRING([--disable-rfkill], [disable rfkill tools]))
+if test "x$enable_rfkill" != "xno"; then
+        have_rfkill=yes
+fi
+AM_CONDITIONAL(ENABLE_RFKILL, [test "$have_rfkill" = "yes"])
+
 # ------------------------------------------------------------------------------
 have_logind=no
 AC_ARG_ENABLE(logind, AS_HELP_STRING([--disable-logind], [disable login daemon]))
@@ -1042,6 +1050,7 @@ AC_MSG_RESULT([
         tmpfiles:                ${have_tmpfiles}
         randomseed:              ${have_randomseed}
         backlight:               ${have_backlight}
+        rfkill:                  ${have_rfkill}
         logind:                  ${have_logind}
         machined:                ${have_machined}
         hostnamed:               ${have_hostnamed}
index 4318964dcaf9ff39f2eb93cb7e597432cf8c5afa..6d26d4b2edda2a0b19999b854ae8bb9e1d3b70b8 100644 (file)
 
                 <para><filename>systemd-backlight@.service</filename>
                 is a service that restores the display backlight
-                brightness at early-boot and saves it at shutdown. On
+                brightness at early boot and saves it at shutdown. On
                 disk, the backlight brightness is stored in
-                <filename>/var/lib/systemd/backlight/</filename>. Note that by
-                default, only firmware backlight devices are
-                saved/restored.</para>
+                <filename>/var/lib/systemd/backlight/</filename>.</para>
         </refsect1>
 
         <refsect1>
diff --git a/man/systemd-rfkill@.service.xml b/man/systemd-rfkill@.service.xml
new file mode 100644 (file)
index 0000000..b274cb8
--- /dev/null
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<!--
+  This file is part of systemd.
+
+  Copyright 2013 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+<refentry id="systemd-rfkill@.service" conditional='ENABLE_RFKILL'>
+
+        <refentryinfo>
+                <title>systemd-rfkill@.service</title>
+                <productname>systemd</productname>
+
+                <authorgroup>
+                        <author>
+                                <contrib>Developer</contrib>
+                                <firstname>Lennart</firstname>
+                                <surname>Poettering</surname>
+                                <email>lennart@poettering.net</email>
+                        </author>
+                </authorgroup>
+        </refentryinfo>
+
+        <refmeta>
+                <refentrytitle>systemd-rfkill@.service</refentrytitle>
+                <manvolnum>8</manvolnum>
+        </refmeta>
+
+        <refnamediv>
+                <refname>systemd-rfkill@.service</refname>
+                <refname>systemd-rfkill</refname>
+                <refpurpose>Load and save the RF kill switch state at boot and shutdown</refpurpose>
+        </refnamediv>
+
+        <refsynopsisdiv>
+                <para><filename>systemd-rfkill@.service</filename></para>
+                <para><filename>/usr/lib/systemd/systemd-rfkill</filename></para>
+        </refsynopsisdiv>
+
+        <refsect1>
+                <title>Description</title>
+
+                <para><filename>systemd-rfkill@.service</filename> is
+                a service that restores the RF kill switch state at
+                early boot and saves it at shutdown. On disk, the RF
+                kill switch state is stored in
+                <filename>/var/lib/systemd/rfkill/</filename>.</para>
+        </refsect1>
+
+        <refsect1>
+                <title>See Also</title>
+                <para>
+                        <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+                </para>
+        </refsect1>
+
+</refentry>
index 498e89c3d8c72f47f318d477529db23aa5fa0ff2..2ffe744413043026d29b26519861d7e210223bba 100644 (file)
@@ -57,6 +57,10 @@ ACTION=="add", SUBSYSTEM=="net", KERNEL!="lo", RUN+="@rootlibexecdir@/systemd-sy
 ACTION=="add", SUBSYSTEM=="backlight", TAG+="systemd", ENV{SYSTEMD_WANTS}+="systemd-backlight@backlight:$name.service"
 ACTION=="add", SUBSYSTEM=="leds", KERNEL=="*kbd_backlight", TAG+="systemd", ENV{SYSTEMD_WANTS}+="systemd-backlight@leds:$name.service"
 
+# Pull in rfkill save/restore for all rfkill devices
+
+ACTION=="add", SUBSYSTEM=="rfkill", TAG+="systemd", ENV{SYSTEMD_WANTS}+="systemd-rfkill@rfkill:$name.service"
+
 # Asynchronously mount file systems implemented by these modules as
 # soon as they are loaded.
 
diff --git a/src/rfkill/Makefile b/src/rfkill/Makefile
new file mode 120000 (symlink)
index 0000000..d0b0e8e
--- /dev/null
@@ -0,0 +1 @@
+../Makefile
\ No newline at end of file
diff --git a/src/rfkill/rfkill.c b/src/rfkill/rfkill.c
new file mode 100644 (file)
index 0000000..9153652
--- /dev/null
@@ -0,0 +1,146 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "util.h"
+#include "mkdir.h"
+#include "fileio.h"
+#include "libudev.h"
+#include "udev-util.h"
+
+int main(int argc, char *argv[]) {
+        _cleanup_udev_unref_ struct udev *udev = NULL;
+        _cleanup_udev_device_unref_ struct udev_device *device = NULL;
+        _cleanup_free_ char *saved = NULL, *ss = NULL, *escaped_name = NULL;
+        const char *sysname, *name;
+        int r;
+
+        if (argc != 3) {
+                log_error("This program requires two arguments.");
+                return EXIT_FAILURE;
+        }
+
+        log_set_target(LOG_TARGET_AUTO);
+        log_parse_environment();
+        log_open();
+
+        umask(0022);
+
+        r = mkdir_p("/var/lib/systemd/rfkill", 0755);
+        if (r < 0) {
+                log_error("Failed to create rfkill directory: %s", strerror(-r));
+                return EXIT_FAILURE;
+        }
+
+        udev = udev_new();
+        if (!udev) {
+                log_oom();
+                return EXIT_FAILURE;
+        }
+
+        sysname = strchr(argv[2], ':');
+        if (!sysname) {
+                log_error("Requires pair of subsystem and sysname for specifying rfkill device.");
+                return EXIT_FAILURE;
+        }
+
+        ss = strndup(argv[2], sysname - argv[2]);
+        if (!ss) {
+                log_oom();
+                return EXIT_FAILURE;
+        }
+
+        sysname++;
+
+        if (!streq(ss, "rfkill")) {
+                log_error("Not a rfkill device: '%s:%s'", ss, sysname);
+                return EXIT_FAILURE;
+        }
+
+        errno = 0;
+        device = udev_device_new_from_subsystem_sysname(udev, ss, sysname);
+        if (!device) {
+                if (errno != 0)
+                        log_error("Failed to get rfkill device '%s:%s': %m", ss, sysname);
+                else
+                        log_oom();
+
+                return EXIT_FAILURE;
+        }
+
+        name = udev_device_get_sysattr_value(device, "name");
+        if (!name) {
+                log_error("rfkill device has no name?");
+                return EXIT_FAILURE;
+        }
+
+        escaped_name = cescape(name);
+        if (!escaped_name) {
+                log_oom();
+                return EXIT_FAILURE;
+        }
+
+        saved = strjoin("/var/lib/systemd/rfkill/", escaped_name, NULL);
+        if (!saved) {
+                log_oom();
+                return EXIT_FAILURE;
+        }
+
+        if (streq(argv[1], "load")) {
+                _cleanup_free_ char *value = NULL;
+
+                r = read_one_line_file(saved, &value);
+                if (r < 0) {
+
+                        if (r == -ENOENT)
+                                return EXIT_SUCCESS;
+
+                        log_error("Failed to read %s: %s", saved, strerror(-r));
+                        return EXIT_FAILURE;
+                }
+
+                r = udev_device_set_sysattr_value(device, "soft", value);
+                if (r < 0) {
+                        log_error("Failed to write system attribute: %s", strerror(-r));
+                        return EXIT_FAILURE;
+                }
+
+        } else if (streq(argv[1], "save")) {
+                const char *value;
+
+                value = udev_device_get_sysattr_value(device, "soft");
+                if (!value) {
+                        log_error("Failed to read system attribute: %s", strerror(-r));
+                        return EXIT_FAILURE;
+                }
+
+                r = write_string_file(saved, value);
+                if (r < 0) {
+                        log_error("Failed to write %s: %s", saved, strerror(-r));
+                        return EXIT_FAILURE;
+                }
+
+        } else {
+                log_error("Unknown verb %s.", argv[1]);
+                return EXIT_FAILURE;
+        }
+
+        return EXIT_SUCCESS;
+}
index 9c65075c0a1cf424db6b39886fa2aacc0bfe0498..6a67f3f60887aa7759d1a132f9568fb97748cac8 100644 (file)
@@ -1,4 +1,5 @@
 /systemd-backlight@.service
+/systemd-rfkill@.service
 /halt-local.service
 /rc-local.service
 /systemd-hybrid-sleep.service
diff --git a/units/systemd-rfkill@.service.in b/units/systemd-rfkill@.service.in
new file mode 100644 (file)
index 0000000..9d264a2
--- /dev/null
@@ -0,0 +1,21 @@
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=Load/Save RF Kill Switch Status of %I
+Documentation=man:systemd-rfkill@.service(8)
+DefaultDependencies=no
+RequiresMountsFor=/var/lib/systemd/rfkill
+Conflicts=shutdown.target
+After=systemd-readahead-collect.service systemd-readahead-replay.service systemd-remount-fs.service
+Before=sysinit.target shutdown.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=@rootlibexecdir@/systemd-rfkill load %I
+ExecStop=@rootlibexecdir@/systemd-rfkill save %I