path-lookup.c revision 7ad94c716d6403233d04c4d37cb14df958c9b65d
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers/***
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers This file is part of systemd.
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers Copyright 2010 Lennart Poettering
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers systemd is free software; you can redistribute it and/or modify it
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers under the terms of the GNU Lesser General Public License as published by
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers the Free Software Foundation; either version 2.1 of the License, or
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers (at your option) any later version.
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers systemd is distributed in the hope that it will be useful, but
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers WITHOUT ANY WARRANTY; without even the implied warranty of
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers Lesser General Public License for more details.
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers You should have received a copy of the GNU Lesser General Public License
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers along with systemd; If not, see <http://www.gnu.org/licenses/>.
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers***/
ad37f393fa97f4274cc3bf97a0d8c388a429037eKay Sievers
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers#include <assert.h>
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers#include <stdlib.h>
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers#include <stdio.h>
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers#include <string.h>
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers#include <unistd.h>
ad37f393fa97f4274cc3bf97a0d8c388a429037eKay Sievers#include <errno.h>
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers#include "util.h"
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers#include "mkdir.h"
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers#include "strv.h"
ad37f393fa97f4274cc3bf97a0d8c388a429037eKay Sievers#include "path-util.h"
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers#include "path-lookup.h"
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sieversstatic const char* const systemd_running_as_table[_SYSTEMD_RUNNING_AS_MAX] = {
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers [SYSTEMD_SYSTEM] = "system",
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers [SYSTEMD_USER] = "user"
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers};
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers
ad37f393fa97f4274cc3bf97a0d8c388a429037eKay SieversDEFINE_STRING_TABLE_LOOKUP(systemd_running_as, SystemdRunningAs);
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sieversint user_config_home(char **config_home) {
0d6ce9236f61cb991d7e8f2359d818e41ead0cf5Kay Sievers const char *e;
0d6ce9236f61cb991d7e8f2359d818e41ead0cf5Kay Sievers
0d6ce9236f61cb991d7e8f2359d818e41ead0cf5Kay Sievers e = getenv("XDG_CONFIG_HOME");
0d6ce9236f61cb991d7e8f2359d818e41ead0cf5Kay Sievers if (e) {
ad37f393fa97f4274cc3bf97a0d8c388a429037eKay Sievers if (asprintf(config_home, "%s/systemd/user", e) < 0)
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers return -ENOMEM;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers return 1;
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers } else {
ad37f393fa97f4274cc3bf97a0d8c388a429037eKay Sievers const char *home;
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers home = getenv("HOME");
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers if (home) {
de892aea1c486b59e04884268b612081d1660514Kay Sievers if (asprintf(config_home, "%s/.config/systemd/user", home) < 0)
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers return -ENOMEM;
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers return 1;
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers }
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers }
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers return 0;
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers}
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers
f610d6de38119b372b377ec41b2a6089872d3294Kay Sieversstatic char** user_dirs(
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers const char *generator,
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers const char *generator_early,
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers const char *generator_late) {
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers const char * const config_unit_paths[] = {
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers USER_CONFIG_UNIT_PATH,
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers "/etc/systemd/user",
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers "/run/systemd/user",
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers NULL
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers };
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers const char * const data_unit_paths[] = {
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers "/usr/local/lib/systemd/user",
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers "/usr/local/share/systemd/user",
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers USER_DATA_UNIT_PATH,
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers "/usr/lib/systemd/user",
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers "/usr/share/systemd/user",
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers NULL
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers };
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers const char *home, *e;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers char *config_home = NULL, *data_home = NULL;
de892aea1c486b59e04884268b612081d1660514Kay Sievers char **config_dirs = NULL, **data_dirs = NULL;
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers char **r = NULL, **t;
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers /* Implement the mechanisms defined in
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers *
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * We look in both the config and the data dirs because we
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * want to encourage that distributors ship their unit files
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * as data, and allow overriding as configuration.
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers */
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (user_config_home(&config_home) < 0)
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers goto fail;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers home = getenv("HOME");
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers e = getenv("XDG_CONFIG_DIRS");
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (e) {
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers config_dirs = strv_split(e, ":");
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (!config_dirs)
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers goto fail;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers }
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers /* We don't treat /etc/xdg/systemd here as the spec
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * suggests because we assume that that is a link to
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers * /etc/systemd/ anyway. */
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers e = getenv("XDG_DATA_HOME");
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers if (e) {
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers if (asprintf(&data_home, "%s/systemd/user", e) < 0)
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers goto fail;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
01d183ddae6fb3445c4519cf1d90c6575f17292eKay Sievers } else if (home) {
01d183ddae6fb3445c4519cf1d90c6575f17292eKay Sievers if (asprintf(&data_home, "%s/.local/share/systemd/user", home) < 0)
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers goto fail;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers /* There is really no need for two unit dirs in $HOME,
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers * except to be fully compliant with the XDG spec. We
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers * now try to link the two dirs, so that we can
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers * minimize disk seeks a little. Further down we'll
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * then filter out this link, if it is actually is
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers * one. */
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers mkdir_parents_label(data_home, 0777);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers (void) symlink("../../../.config/systemd/user", data_home);
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers }
137661d87525a3c339afd2804e577532d58d3fbcKay Sievers
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers e = getenv("XDG_DATA_DIRS");
de892aea1c486b59e04884268b612081d1660514Kay Sievers if (e)
de892aea1c486b59e04884268b612081d1660514Kay Sievers data_dirs = strv_split(e, ":");
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers else
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers data_dirs = strv_new("/usr/local/share",
de892aea1c486b59e04884268b612081d1660514Kay Sievers "/usr/share",
de892aea1c486b59e04884268b612081d1660514Kay Sievers NULL);
de892aea1c486b59e04884268b612081d1660514Kay Sievers if (!data_dirs)
de892aea1c486b59e04884268b612081d1660514Kay Sievers goto fail;
de892aea1c486b59e04884268b612081d1660514Kay Sievers
de892aea1c486b59e04884268b612081d1660514Kay Sievers /* Now merge everything we found. */
de892aea1c486b59e04884268b612081d1660514Kay Sievers if (generator_early) {
de892aea1c486b59e04884268b612081d1660514Kay Sievers t = strv_append(r, generator_early);
de892aea1c486b59e04884268b612081d1660514Kay Sievers if (!t)
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers goto fail;
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers strv_free(r);
de892aea1c486b59e04884268b612081d1660514Kay Sievers r = t;
de892aea1c486b59e04884268b612081d1660514Kay Sievers }
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers
de892aea1c486b59e04884268b612081d1660514Kay Sievers if (config_home) {
de892aea1c486b59e04884268b612081d1660514Kay Sievers t = strv_append(r, config_home);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (!t)
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers goto fail;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers strv_free(r);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers r = t;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers }
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers if (!strv_isempty(config_dirs)) {
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers t = strv_merge_concat(r, config_dirs, "/systemd/user");
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers if (!t)
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers goto finish;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers strv_free(r);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers r = t;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers }
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers t = strv_merge(r, (char**) config_unit_paths);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers if (!t)
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers goto fail;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers strv_free(r);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers r = t;
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers if (generator) {
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers t = strv_append(r, generator);
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers if (!t)
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers goto fail;
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers strv_free(r);
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers r = t;
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers }
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers if (data_home) {
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers t = strv_append(r, data_home);
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers if (!t)
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers goto fail;
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers strv_free(r);
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers r = t;
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers }
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers if (!strv_isempty(data_dirs)) {
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers t = strv_merge_concat(r, data_dirs, "/systemd/user");
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers if (!t)
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers goto fail;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers strv_free(r);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers r = t;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers }
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers t = strv_merge(r, (char**) data_unit_paths);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers if (!t)
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers goto fail;
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers strv_free(r);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers r = t;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers if (generator_late) {
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers t = strv_append(r, generator_late);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers if (!t)
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers goto fail;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers strv_free(r);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers r = t;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers }
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers if (!path_strv_make_absolute_cwd(r))
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers goto fail;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sieversfinish:
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers free(config_home);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers strv_free(config_dirs);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers free(data_home);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers strv_free(data_dirs);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers return r;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sieversfail:
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers strv_free(r);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers r = NULL;
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers goto finish;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers}
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sieversint lookup_paths_init(
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers LookupPaths *p,
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers SystemdRunningAs running_as,
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers bool personal,
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers const char *generator,
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers const char *generator_early,
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers const char *generator_late) {
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers const char *e;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers assert(p);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers /* First priority is whatever has been passed to us via env
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * vars */
5b8180d3f6598a1b2f296645690de41d726fd5abKay Sievers e = getenv("SYSTEMD_UNIT_PATH");
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers if (e) {
5b8180d3f6598a1b2f296645690de41d726fd5abKay Sievers p->unit_path = path_split_and_make_absolute(e);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (!p->unit_path)
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers return -ENOMEM;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers } else
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers p->unit_path = NULL;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (strv_isempty(p->unit_path)) {
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers /* Nothing is set, so let's figure something out. */
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers strv_free(p->unit_path);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers /* For the user units we include share/ in the search
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * path in order to comply with the XDG basedir
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * spec. For the system stuff we avoid such
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * nonsense. OTOH we include /lib in the search path
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * for the system stuff but avoid it for user
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * stuff. */
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (running_as == SYSTEMD_USER) {
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (personal)
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers p->unit_path = user_dirs(generator, generator_early, generator_late);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers else
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers p->unit_path = strv_new(
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers /* If you modify this you also want to modify
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * systemduserunitpath= in systemd.pc.in, and
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * the arrays in user_dirs() above! */
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers STRV_IFNOTNULL(generator_early),
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers USER_CONFIG_UNIT_PATH,
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers "/etc/systemd/user",
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers "/run/systemd/user",
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers STRV_IFNOTNULL(generator),
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers "/usr/local/lib/systemd/user",
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers "/usr/local/share/systemd/user",
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers USER_DATA_UNIT_PATH,
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers "/usr/lib/systemd/user",
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers "/usr/share/systemd/user",
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers STRV_IFNOTNULL(generator_late),
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers NULL);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (!p->unit_path)
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers return -ENOMEM;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers } else {
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers p->unit_path = strv_new(
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers /* If you modify this you also want to modify
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers * systemdsystemunitpath= in systemd.pc.in! */
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers STRV_IFNOTNULL(generator_early),
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers SYSTEM_CONFIG_UNIT_PATH,
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers "/etc/systemd/system",
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers "/run/systemd/system",
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers STRV_IFNOTNULL(generator),
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers "/usr/local/lib/systemd/system",
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers SYSTEM_DATA_UNIT_PATH,
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers "/usr/lib/systemd/system",
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers#ifdef HAVE_SPLIT_USR
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers "/lib/systemd/system",
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers#endif
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers STRV_IFNOTNULL(generator_late),
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers NULL);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (!p->unit_path)
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers return -ENOMEM;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers }
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers }
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (!path_strv_canonicalize(p->unit_path))
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers return -ENOMEM;
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers strv_uniq(p->unit_path);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers if (!strv_isempty(p->unit_path)) {
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers char _cleanup_free_ *t = strv_join(p->unit_path, "\n\t");
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers if (!t)
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers return -ENOMEM;
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers log_info("Looking for unit files in (higher priority first):\n\t%s", t);
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers } else {
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers log_info("Ignoring unit files.");
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers strv_free(p->unit_path);
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers p->unit_path = NULL;
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers }
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers if (running_as == SYSTEMD_SYSTEM) {
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers#ifdef HAVE_SYSV_COMPAT
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers /* /etc/init.d/ compatibility does not matter to users */
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers e = getenv("SYSTEMD_SYSVINIT_PATH");
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers if (e) {
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers p->sysvinit_path = path_split_and_make_absolute(e);
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers if (!p->sysvinit_path)
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers return -ENOMEM;
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers } else
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers p->sysvinit_path = NULL;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (strv_isempty(p->sysvinit_path)) {
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers strv_free(p->sysvinit_path);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers p->sysvinit_path = strv_new(
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers SYSTEM_SYSVINIT_PATH, /* /etc/init.d/ */
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers NULL);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (!p->sysvinit_path)
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers return -ENOMEM;
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers }
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers e = getenv("SYSTEMD_SYSVRCND_PATH");
971e7fb62548f2c9c4e32684bb13409e6579dc6aKay Sievers if (e) {
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers p->sysvrcnd_path = path_split_and_make_absolute(e);
971e7fb62548f2c9c4e32684bb13409e6579dc6aKay Sievers if (!p->sysvrcnd_path)
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers return -ENOMEM;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers } else
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers p->sysvrcnd_path = NULL;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (strv_isempty(p->sysvrcnd_path)) {
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers strv_free(p->sysvrcnd_path);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers p->sysvrcnd_path = strv_new(
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers SYSTEM_SYSVRCND_PATH, /* /etc/rcN.d/ */
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers NULL);
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers if (!p->sysvrcnd_path)
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers return -ENOMEM;
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers }
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers if (!path_strv_canonicalize(p->sysvinit_path))
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers return -ENOMEM;
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (!path_strv_canonicalize(p->sysvrcnd_path))
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers return -ENOMEM;
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers strv_uniq(p->sysvinit_path);
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers strv_uniq(p->sysvrcnd_path);
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers if (!strv_isempty(p->sysvinit_path)) {
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers char _cleanup_free_ *t = strv_join(p->sysvinit_path, "\n\t");
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers if (!t)
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers return -ENOMEM;
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers log_info("Looking for SysV init scripts in:\n\t%s", t);
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers } else {
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers log_info("Ignoring SysV init scripts.");
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers strv_free(p->sysvinit_path);
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers p->sysvinit_path = NULL;
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers }
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers if (!strv_isempty(p->sysvrcnd_path)) {
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers char _cleanup_free_ *t =
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers strv_join(p->sysvrcnd_path, "\n\t");
72bc96f07868d532596477604b6fb41633ebd124Kay Sievers if (!t)
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers return -ENOMEM;
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers log_debug("Looking for SysV rcN.d links in:\n\t%s", t);
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers } else {
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers log_debug("Ignoring SysV rcN.d links.");
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers strv_free(p->sysvrcnd_path);
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers p->sysvrcnd_path = NULL;
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers }
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers#else
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers log_info("SysV init scripts and rcN.d links support disabled");
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers#endif
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers }
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers return 0;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers}
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sieversvoid lookup_paths_free(LookupPaths *p) {
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers assert(p);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers strv_free(p->unit_path);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers p->unit_path = NULL;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers#ifdef HAVE_SYSV_COMPAT
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers strv_free(p->sysvinit_path);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers strv_free(p->sysvrcnd_path);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers p->sysvinit_path = p->sysvrcnd_path = NULL;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers#endif
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers}
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers