rfkill.c revision 3990f247652c3bd41e4ea074e6302277eb9c7aa3
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering/***
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering This file is part of systemd.
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering Copyright 2013 Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering systemd is free software; you can redistribute it and/or modify it
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering under the terms of the GNU Lesser General Public License as published by
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering (at your option) any later version.
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering systemd is distributed in the hope that it will be useful, but
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering Lesser General Public License for more details.
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering You should have received a copy of the GNU Lesser General Public License
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering***/
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering#include "util.h"
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering#include "mkdir.h"
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering#include "fileio.h"
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering#include "libudev.h"
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering#include "udev-util.h"
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poetteringint main(int argc, char *argv[]) {
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering _cleanup_udev_unref_ struct udev *udev = NULL;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering _cleanup_udev_device_unref_ struct udev_device *device = NULL;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering _cleanup_free_ char *saved = NULL, *ss = NULL, *escaped_name = NULL;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering const char *sysname, *name;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering int r;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering if (argc != 3) {
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering log_error("This program requires two arguments.");
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering return EXIT_FAILURE;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering }
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering log_set_target(LOG_TARGET_AUTO);
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering log_parse_environment();
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering log_open();
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering umask(0022);
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering r = mkdir_p("/var/lib/systemd/rfkill", 0755);
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering if (r < 0) {
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering log_error("Failed to create rfkill directory: %s", strerror(-r));
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering return EXIT_FAILURE;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering }
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering udev = udev_new();
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering if (!udev) {
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering log_oom();
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering return EXIT_FAILURE;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering }
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering sysname = strchr(argv[2], ':');
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering if (!sysname) {
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering log_error("Requires pair of subsystem and sysname for specifying rfkill device.");
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering return EXIT_FAILURE;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering }
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering ss = strndup(argv[2], sysname - argv[2]);
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering if (!ss) {
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering log_oom();
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering return EXIT_FAILURE;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering }
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering sysname++;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering if (!streq(ss, "rfkill")) {
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering log_error("Not a rfkill device: '%s:%s'", ss, sysname);
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering return EXIT_FAILURE;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering }
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering errno = 0;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering device = udev_device_new_from_subsystem_sysname(udev, ss, sysname);
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering if (!device) {
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering if (errno != 0)
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering log_error("Failed to get rfkill device '%s:%s': %m", ss, sysname);
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering else
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering log_oom();
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering return EXIT_FAILURE;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering }
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering name = udev_device_get_sysattr_value(device, "name");
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering if (!name) {
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering log_error("rfkill device has no name?");
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering return EXIT_FAILURE;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering }
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering escaped_name = cescape(name);
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering if (!escaped_name) {
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering log_oom();
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering return EXIT_FAILURE;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering }
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering saved = strjoin("/var/lib/systemd/rfkill/", escaped_name, NULL);
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering if (!saved) {
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering log_oom();
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering return EXIT_FAILURE;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering }
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering if (streq(argv[1], "load")) {
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering _cleanup_free_ char *value = NULL;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering r = read_one_line_file(saved, &value);
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering if (r < 0) {
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering if (r == -ENOENT)
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering return EXIT_SUCCESS;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering log_error("Failed to read %s: %s", saved, strerror(-r));
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering return EXIT_FAILURE;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering }
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering r = udev_device_set_sysattr_value(device, "soft", value);
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering if (r < 0) {
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering log_error("Failed to write system attribute: %s", strerror(-r));
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering return EXIT_FAILURE;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering }
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering } else if (streq(argv[1], "save")) {
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering const char *value;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering value = udev_device_get_sysattr_value(device, "soft");
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering if (!value) {
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering log_error("Failed to read system attribute: %s", strerror(-r));
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering return EXIT_FAILURE;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering }
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering r = write_string_file(saved, value);
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering if (r < 0) {
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering log_error("Failed to write %s: %s", saved, strerror(-r));
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering return EXIT_FAILURE;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering }
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering } else {
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering log_error("Unknown verb %s.", argv[1]);
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering return EXIT_FAILURE;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering }
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering return EXIT_SUCCESS;
3990f247652c3bd41e4ea074e6302277eb9c7aa3Lennart Poettering}