summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2013-10-14 04:31:49 +0200
committerLennart Poettering <lennart@poettering.net>2013-10-14 04:31:49 +0200
commit3990f247652c3bd41e4ea074e6302277eb9c7aa3 (patch)
treea374a06aa0c19ef135bf93f47cfc50c76b476c17
parent0f4ba83c397e807939a4eb0b2cbd04ad4ab548cc (diff)
rfkill: add new rfkill tool to save/restore rfkill state across reboots
This works analogous to the existing backlight and random seed services
-rw-r--r--.gitignore1
-rw-r--r--Makefile-man.am11
-rw-r--r--Makefile.am20
-rw-r--r--configure.ac9
-rw-r--r--man/systemd-backlight@.service.xml6
-rw-r--r--man/systemd-rfkill@.service.xml71
-rw-r--r--rules/99-systemd.rules.in4
l---------src/rfkill/Makefile1
-rw-r--r--src/rfkill/rfkill.c146
-rw-r--r--units/.gitignore1
-rw-r--r--units/systemd-rfkill@.service.in21
11 files changed, 287 insertions, 4 deletions
diff --git a/.gitignore b/.gitignore
index 40015debaf..587b6d07ef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -69,6 +69,7 @@
/systemd-remount-api-vfs
/systemd-remount-fs
/systemd-reply-password
+/systemd-rfkill
/systemd-run
/systemd-shutdown
/systemd-shutdownd
diff --git a/Makefile-man.am b/Makefile-man.am
index c8a4342396..6c9b790989 100644
--- a/Makefile-man.am
+++ b/Makefile-man.am
@@ -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 \
diff --git a/Makefile.am b/Makefile.am
index 7b6df1b608..66012441c0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3434,6 +3434,26 @@ 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 += \
systemd-cryptsetup
diff --git a/configure.ac b/configure.ac
index 00ee9bb92d..6cda8f967f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -705,6 +705,14 @@ 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]))
if test "x$enable_logind" != "xno"; then
@@ -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}
diff --git a/man/systemd-backlight@.service.xml b/man/systemd-backlight@.service.xml
index 4318964dca..6d26d4b2ed 100644
--- a/man/systemd-backlight@.service.xml
+++ b/man/systemd-backlight@.service.xml
@@ -56,11 +56,9 @@
<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
index 0000000000..b274cb818b
--- /dev/null
+++ b/man/systemd-rfkill@.service.xml
@@ -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>
diff --git a/rules/99-systemd.rules.in b/rules/99-systemd.rules.in
index 498e89c3d8..2ffe744413 100644
--- a/rules/99-systemd.rules.in
+++ b/rules/99-systemd.rules.in
@@ -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
index 0000000000..d0b0e8e008
--- /dev/null
+++ b/src/rfkill/Makefile
@@ -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
index 0000000000..91536523b0
--- /dev/null
+++ b/src/rfkill/rfkill.c
@@ -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;
+}
diff --git a/units/.gitignore b/units/.gitignore
index 9c65075c0a..6a67f3f608 100644
--- a/units/.gitignore
+++ b/units/.gitignore
@@ -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
index 0000000000..9d264a2bca
--- /dev/null
+++ b/units/systemd-rfkill@.service.in
@@ -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