blob: b840d4f215d8241c9df405c4cefce6723acdf86d [file] [log] [blame] [raw]
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2014 Canonical
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 <errno.h>
#include <stdbool.h>
#include <unistd.h>
#include "alloc-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "log.h"
#include "mkdir.h"
#include "string-util.h"
#include "util.h"
/*
* Ensure that the started display-manager is matching
* /etc/X11/default-display-manager if present, otherwise
* let display-manager.service symlinks pick the preferred one
* if any.
*/
static const char *dm_service_unit = SYSTEM_CONFIG_UNIT_PATH "/display-manager.service";
static const char *default_dm_file = "/etc/X11/default-display-manager";
static const char *dest = NULL;
static int generate_display_manager_alias(void) {
_cleanup_free_ char *default_dm_path = NULL, *enabled_dm_unit = NULL;
const char *default_dm = NULL, *in_mem_symlink = NULL, *target_unit_path = NULL;
bool dm_service_exists = true;
int r;
r = read_full_file(default_dm_file, &default_dm_path, NULL);
if (r < 0) {
log_debug("No %s file, nothing to generate", default_dm_file);
return 0;
}
default_dm = strstrip(basename(default_dm_path));
r = readlink_value(dm_service_unit, &enabled_dm_unit);
if (r < 0) {
enabled_dm_unit = strdup("");
dm_service_exists = false;
}
/* all is fine if the info matches */
if (streq(strjoina(default_dm, ".service"), enabled_dm_unit))
return 0;
target_unit_path = strjoina(SYSTEM_DATA_UNIT_PATH, "/", default_dm, ".service");
/* we only create the alias symlink for non sysvinit services */
if (access(target_unit_path, F_OK) < 0 && (errno == ENOENT)) {
/* if the dm service was already disabled, nothing to be done */
if (!dm_service_exists) {
log_debug("No %s file, nothing to mask", dm_service_unit);
return 0;
}
log_warning("%s is not a systemd unit, we disable the systemd enabled display manager", target_unit_path);
target_unit_path = "/dev/null";
} else {
log_warning("%s points at %s while the default systemd unit is %s. Reconfiguring %s as default.",
default_dm_file, default_dm, enabled_dm_unit, default_dm);
}
in_mem_symlink = strjoina(dest, "/display-manager.service");
mkdir_parents_label(in_mem_symlink, 0755);
if (symlink(target_unit_path, in_mem_symlink) < 0) {
log_error("Failed to create symlink %s: %m", in_mem_symlink);
return -errno;
}
return 0;
}
int main(int argc, char *argv[]) {
int r;
if (argc != 4) {
log_error("This program takes three arguments.");
return EXIT_FAILURE;
}
dest = argv[2];
log_set_target(LOG_TARGET_SAFE);
log_parse_environment();
log_open();
umask(0022);
r = generate_display_manager_alias();
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}