Browse Source

Add $XDG_CONFIG_HOME/dinit.d/ to default user service directories. Fixes #222

Void 4 months ago
parent
commit
de7b3be464

+ 1 - 0
.gitignore

@@ -14,6 +14,7 @@
 /src/tests/cptests/corpus
 /src/tests/cptests/fuzz
 /src/igr-tests/igr-runner
+!/src/igr-tests/xdg-config/config/dinit.d/
 /mconfig
 
 /build/includes/*.h

+ 1 - 0
CONTRIBUTORS

@@ -13,3 +13,4 @@ The following people (in alphabetical order) have contributed:
  * Fabien Poussin - Code, services, documentation.
  * James Knippes - Code
  * Mobin Aydinfar - Code, documentation, CI
+ * Oliver Amann - Code, testing, documentation

+ 1 - 1
doc/manpages/dinit-service.5.m4

@@ -6,7 +6,7 @@ Dinit service description files
 .SH SYNOPSIS
 .\"
 .ft CR
-/etc/dinit.d/\fIservice-name\fR, $HOME/.config/dinit.d/\fIservice-name\fR
+/etc/dinit.d/\fIservice-name\fR, $XDG_CONFIG_HOME/dinit.d/\fIservice-name\fR
 .ft
 .\"
 .SH DESCRIPTION

+ 9 - 9
doc/manpages/dinit.8.m4

@@ -31,8 +31,8 @@ See \fBRUNNING AS SYSTEM MANAGER / PRIMARY INIT\fR.
 .LP
 Dinit reads service descriptions from files located in a service
 description directory, normally one of \fI/etc/dinit.d\fR, \fI/run/dinit.d\fR,
-\fI/usr/local/lib/dinit.d\fR or \fI/lib/dinit.d\fR for the system instance
-or just \fI$HOME/.config/dinit.d\fR when run as a user process.
+\fI/usr/local/lib/dinit.d\fR and \fI/lib/dinit.d\fR for the system instance
+or \fI$XDG_CONFIG_HOME/dinit.d\fR and \fI$HOME/.config/dinit.d\fR when run as a user process.
 See \fBSERVICE DESCRIPTION FILES\fR for details of the service description format.
 .\"
 .SH OPTIONS
@@ -42,9 +42,9 @@ Specifies \fIdir\fP as the directory containing service definition files.
 This can be specified multiple times for multiple service directories.
 The default directories are not searched for services when this option is provided.
 .sp
-If not specified, the default is \fI$HOME/.config/dinit.d\fR or, for the
-system service manager, each of \fI/etc/dinit.d\fR, \fI/run/dinit.d/\fR,
-\fI/usr/local/lib/dinit.d\fR, and \fI/lib/dinit.d\fR (searched in that order).
+If not specified, the default for the user instance is \fI$XDG_CONFIG_HOME/dinit.d\fR
+and \fI$HOME/.config/dinit.d\fR or, for the system instance, each of \fI/etc/dinit.d\fR,
+\fI/run/dinit.d/\fR, \fI/usr/local/lib/dinit.d\fR, and \fI/lib/dinit.d\fR (searched in that order).
 .TP
 \fB\-e\fR \fIfile\fP, \fB\-\-env\-file\fR \fIfile\fP
 Read initial environment from \fIfile\fP.
@@ -142,8 +142,8 @@ Use a level of \fBnone\fR to suppress all messages.
 .\"
 Service description files specify the parameters of each service.
 They are named for the service they describe, and are found in one of several directories
-(including \fI/etc/dinit.d\fR) for a system instance or \fI$HOME/.config/dinit.d\fR for a user instance
-(see also \fB\-\-services\-dir\fR option).
+(including \fI/etc/dinit.d\fR) for a system instance or \fI$XDG_CONFIG_HOME/dinit.d\fR and
+\fI$HOME/.config/dinit.d\fR for a user instance (see also \fB\-\-services\-dir\fR option).
 .LP
 Service description files are read by Dinit on an "as needed" basis.
 Once loaded, a service description is never automatically unloaded (even if the service
@@ -278,8 +278,8 @@ value set previously as well as the effect of previous \fB!unset\fR and \fB!clea
 \fI/etc/dinit.d\fR, \fI/run/dinit.d\fR, \fI/usr/local/lib/dinit.d\fR, \fI/lib/dinit.d\fR
 Default locations for service description files. The directories are searched in the order listed.
 .TP
-\fI$HOME/.config/dinit.d\fR
-Default location for service description files for user instances. 
+\fI$XDG_CONFIG_HOME/dinit.d\fR, \fI$HOME/.config/dinit.d\fR
+Default location for service description files for user instances. The directories are searched in the order listed.
 .\"
 .SH SIGNALS
 .LP

+ 3 - 3
doc/manpages/dinitcheck.8.m4

@@ -39,9 +39,9 @@ Specifies \fIdir\fP as the directory containing service description files (can
 be given multiple times to specify multiple service directories).
 Default directories are not searched for services when this option is provided.
 .sp
-If not specified, the default is \fI$HOME/.config/dinit.d\fR or, for the
-system service manager, each of \fI/etc/dinit.d/fR, \fI/run/dinit.d\fR,
-\fI/usr/local/lib/dinit.d\fR, and \fI/lib/dinit.d\fR (searched in that order).
+If not specified, the default for the user instance is \fI$XDG_CONFIG_HOME/dinit.d\fR
+and \fI$HOME/.config/dinit.d\fR or, for the system instance, each of \fI/etc/dinit.d\fR,
+\fI/run/dinit.d/\fR, \fI/usr/local/lib/dinit.d\fR, and \fI/lib/dinit.d\fR (searched in that order).
 .TP
 \fB\-\-help\fR
 Display brief help text and then exit.

+ 1 - 1
src/igr-tests/igr-runner.cc

@@ -15,7 +15,7 @@ int main(int argc, char **argv)
     const char * const test_dirs[] = { "basic", "environ", "environ2", "ps-environ", "chain-to", "force-stop",
             "restart", "check-basic", "check-cycle", "check-cycle2", "check-lint", "reload1", "reload2",
             "no-command-error", "add-rm-dep", "var-subst", "svc-start-fail", "dep-not-found", "pseudo-cycle",
-            "before-after", "before-after2", "log-via-pipe", "catlog", "offline-enable" };
+            "before-after", "before-after2", "log-via-pipe", "catlog", "offline-enable", "xdg-config" };
     constexpr int num_tests = sizeof(test_dirs) / sizeof(test_dirs[0]);
 
     int passed = 0;

+ 4 - 0
src/igr-tests/xdg-config/basic.sh

@@ -0,0 +1,4 @@
+#!/bin/sh
+# basic test; record our run
+
+echo "ran" > "$IGR_OUTPUT"/basic-ran

+ 3 - 0
src/igr-tests/xdg-config/config/dinit.d/basic

@@ -0,0 +1,3 @@
+type = process
+command = ../../basic.sh
+restart = false

+ 18 - 0
src/igr-tests/xdg-config/run-test.sh

@@ -0,0 +1,18 @@
+#!/bin/sh
+
+set -eu
+cd "$(dirname "$0")"
+. ../igr_functions.sh
+
+rm -f "$IGR_OUTPUT"/basic-ran
+
+export XDG_CONFIG_HOME="$PWD/config/"
+
+find_dinit
+"$DINIT" $QUIET -u -p "$SOCKET" -l /dev/null basic
+
+if ! compare_text "$IGR_OUTPUT"/basic-ran "ran"; then
+    error "$IGR_OUTPUT/basic-ran didn't contain expected result!"
+fi
+
+exit 0

+ 14 - 0
src/options-processing.cc

@@ -32,6 +32,20 @@ void service_dir_opt::build_paths(bool am_system_init)
 
         /* service directory name */
         if (!am_system_init) {
+            const char * xdg_config_home = getenv("XDG_CONFIG_HOME");
+            if (xdg_config_home != nullptr && strlen(xdg_config_home) != 0) {
+                size_t xdg_config_home_len = strlen(xdg_config_home);
+                size_t dinit_d_len = strlen("/dinit.d");
+                size_t full_len = xdg_config_home_len + dinit_d_len + 1;
+                char *service_dir_w = new char[full_len];
+                std::memcpy(service_dir_w, xdg_config_home, xdg_config_home_len);
+                std::memcpy(service_dir_w + xdg_config_home_len, "/dinit.d", dinit_d_len);
+                service_dir_w[full_len - 1] = 0;
+
+                service_dir_paths.emplace_back(service_dir_w, /*dyn_allocd=*/true);
+                home_service_dir_set = true;
+            }
+
             const char * user_home = get_user_home();
             if (user_home != nullptr) {
                 size_t user_home_len = strlen(user_home);