326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering/***
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering This file is part of systemd.
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering Copyright 2014 Lennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering systemd is free software; you can redistribute it and/or modify it
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering under the terms of the GNU Lesser General Public License as published by
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering (at your option) any later version.
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering systemd is distributed in the hope that it will be useful, but
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering Lesser General Public License for more details.
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering You should have received a copy of the GNU Lesser General Public License
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering***/
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "alloc-util.h"
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering#include "mkdir.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include "parse-util.h"
4e731273edfe852a3eee2949cd20f49fd5b4f6d7Lennart Poettering#include "proc-cmdline.h"
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin#include "special.h"
4e731273edfe852a3eee2949cd20f49fd5b4f6d7Lennart Poettering#include "string-util.h"
4e731273edfe852a3eee2949cd20f49fd5b4f6d7Lennart Poettering#include "strv.h"
4e731273edfe852a3eee2949cd20f49fd5b4f6d7Lennart Poettering#include "unit-name.h"
4e731273edfe852a3eee2949cd20f49fd5b4f6d7Lennart Poettering#include "util.h"
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchaginstatic char *arg_default_unit = NULL;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poetteringstatic const char *arg_dest = "/tmp";
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poetteringstatic char **arg_mask = NULL;
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poetteringstatic char **arg_wants = NULL;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poetteringstatic bool arg_debug_shell = false;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poetteringstatic int parse_proc_cmdline_item(const char *key, const char *value) {
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering int r;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering assert(key);
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering if (streq(key, "systemd.mask")) {
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering if (!value)
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering log_error("Missing argument for systemd.mask= kernel command line parameter.");
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering else {
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering char *n;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering r = unit_name_mangle(value, UNIT_NAME_NOGLOB, &n);
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering if (r < 0)
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering return log_error_errno(r, "Failed to glob unit name: %m");
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering r = strv_consume(&arg_mask, n);
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering if (r < 0)
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering return log_oom();
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering }
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering } else if (streq(key, "systemd.wants")) {
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering if (!value)
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering log_error("Missing argument for systemd.want= kernel command line parameter.");
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering else {
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering char *n;
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering r = unit_name_mangle(value, UNIT_NAME_NOGLOB, &n);
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering if (r < 0)
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering return log_error_errno(r, "Failed to glob unit name: %m");
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering r = strv_consume(&arg_wants, n);
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering if (r < 0)
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering return log_oom();
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering }
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering } else if (streq(key, "systemd.debug-shell")) {
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering if (value) {
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering r = parse_boolean(value);
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering if (r < 0)
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering log_error("Failed to parse systemd.debug-shell= argument '%s', ignoring.", value);
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering else
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering arg_debug_shell = r;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering } else
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering arg_debug_shell = true;
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin } else if (streq(key, "systemd.unit")) {
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin if (!value)
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin log_error("Missing argument for systemd.unit= kernel command line parameter.");
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin else {
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin r = free_and_strdup(&arg_default_unit, value);
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin if (r < 0)
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin return log_error_errno(r, "Failed to set default unit %s: %m", value);
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin }
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin } else if (!value) {
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin const char *target;
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin target = runlevel_to_target(key);
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin if (target) {
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin r = free_and_strdup(&arg_default_unit, target);
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin if (r < 0)
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin return log_error_errno(r, "Failed to set default unit %s: %m", target);
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin }
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering }
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering return 0;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering}
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poetteringstatic int generate_mask_symlinks(void) {
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering char **u;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering int r = 0;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering if (strv_isempty(arg_mask))
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering return 0;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering STRV_FOREACH(u, arg_mask) {
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering _cleanup_free_ char *p = NULL;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering p = strjoin(arg_dest, "/", *u, NULL);
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering if (!p)
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering return log_oom();
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
1f6b411372076426c0faf0bb350437fb4d82931fLennart Poettering if (symlink("/dev/null", p) < 0)
94c156cd452424ea59931920df2454d9da7cb774Lennart Poettering r = log_error_errno(errno,
94c156cd452424ea59931920df2454d9da7cb774Lennart Poettering "Failed to create mask symlink %s: %m",
94c156cd452424ea59931920df2454d9da7cb774Lennart Poettering p);
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering }
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering return r;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering}
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poetteringstatic int generate_wants_symlinks(void) {
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering char **u;
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering int r = 0;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering if (strv_isempty(arg_wants))
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering return 0;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering STRV_FOREACH(u, arg_wants) {
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering _cleanup_free_ char *p = NULL, *f = NULL;
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin p = strjoin(arg_dest, "/", arg_default_unit, ".wants/", *u, NULL);
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering if (!p)
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering return log_oom();
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering f = strappend(SYSTEM_DATA_UNIT_PATH "/", *u);
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering if (!f)
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering return log_oom();
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering mkdir_parents_label(p, 0755);
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
1f6b411372076426c0faf0bb350437fb4d82931fLennart Poettering if (symlink(f, p) < 0)
94c156cd452424ea59931920df2454d9da7cb774Lennart Poettering r = log_error_errno(errno,
94c156cd452424ea59931920df2454d9da7cb774Lennart Poettering "Failed to create wants symlink %s: %m",
94c156cd452424ea59931920df2454d9da7cb774Lennart Poettering p);
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering }
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering return r;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering}
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poetteringint main(int argc, char *argv[]) {
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering int r, q;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering if (argc > 1 && argc != 4) {
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering log_error("This program takes three or no arguments.");
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering return EXIT_FAILURE;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering }
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering if (argc > 1)
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering arg_dest = argv[2];
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering log_set_target(LOG_TARGET_SAFE);
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering log_parse_environment();
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering log_open();
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering umask(0022);
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin r = free_and_strdup(&arg_default_unit, SPECIAL_DEFAULT_TARGET);
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin if (r < 0) {
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin log_error_errno(r, "Failed to set default unit %s: %m", SPECIAL_DEFAULT_TARGET);
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin goto finish;
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin }
7dcc56715d150ff7e8b5459877879430cff790f7Evgeny Vereshchagin
b5884878a2874447b2a9f07f324a7cd909d96d48Lennart Poettering r = parse_proc_cmdline(parse_proc_cmdline_item);
b5884878a2874447b2a9f07f324a7cd909d96d48Lennart Poettering if (r < 0)
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering if (arg_debug_shell) {
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering r = strv_extend(&arg_wants, "debug-shell.service");
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering if (r < 0) {
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering r = log_oom();
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering goto finish;
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering }
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering }
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering r = generate_mask_symlinks();
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poettering q = generate_wants_symlinks();
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering if (q < 0)
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering r = q;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
3c5a87a879e3eb66c9c159a26051d940ff2db7a1Lennart Poetteringfinish:
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering
326bb68c40ff2a7119c344b9ab7a7473f9fcdf3cLennart Poettering}