Look in multiple directories for service descriptions.
authorDavin McCall <davmac@davmac.org>
Mon, 14 May 2018 20:22:43 +0000 (21:22 +0100)
committerDavin McCall <davmac@davmac.org>
Mon, 14 May 2018 20:22:43 +0000 (21:22 +0100)
Previously we checked only /etc/dinit.d; now, check /etc/dinit.d,
/usr/local/lib/dinit.d, and /lib/dinit.d, in that order.

README
TODO
doc/manpages/dinit-service.5
doc/manpages/dinit.8
src/dinit.cc

diff --git a/README b/README
index 69df41e06a50476c506fd2f01b8521b03d5de7e9..c7c8cacc9e9e2a74525df4f4d2f45536ecb6d399 100644 (file)
--- a/README
+++ b/README
@@ -117,9 +117,10 @@ Service Description files
 =-=-=-=-=-=-=-=-=-=-=-=-=
 
 Dinit discovers services by reading _service description files_. These files
-reside in a directory (/etc/dinit.d is the default "system" location) and
-their name matches the name of the service. Service descriptions are loaded
-lazily, as needed by Dinit.
+reside in a directory (/etc/dinit.d is the default "system" location, with
+"/usr/local/lib/dinit.d" and "/lib/dinit.d" also searched) and their name
+matches the name of the service. Service descriptions are loaded lazily, as
+needed by Dinit.
 
 A service description file consists of a number of parameter settings.
 Settings in the SDF are denoted as a parameter name followed by either an
diff --git a/TODO b/TODO
index 653604f69e27740d84a17ab3d3b6abcf43f53959..864e08805bdbdbcc44eaa7168fade5fe52bbf081 100644 (file)
--- a/TODO
+++ b/TODO
@@ -19,7 +19,11 @@ For version 1.0:
 * Think about detecting runs-on-console dependency conflicts (i.e. if A runs-on-console and
   B depends on A and runs-on-consle then B can never start).
 * Documentation must be complete (see section below).
-  
+* Package-manager-friendly way to enable/disable services.
+  Perhaps a service can specify a dependency file (with dependency type) where
+  the file contains a list of service names, or if it is a directory, each
+  filename within corresponds to a service that is a dependency.
+* Be able to boot and shutdown Linux and FreeBSD.
 
 For later:
 ----------
index ed80605212062f51481ac62e36fe2e7588b6b069..c3b4c26e013c0ab0a829983d4fae631600536f50 100644 (file)
@@ -16,8 +16,9 @@ of the file corresponds to the name of the service it describes.
 Service description files specify the various attributes of a service. A
 service description file is named after the service it represents, and is
 a plain-text file with simple key-value format. The description files are
-located in the service description directory (which defaults to
-\fI/etc/dinit.d\fR for the system process).
+located in a service description directory; by default, the system process
+searches \fI/etc/dinit.d\fR, \fI/usr/local/lib/dinit.d\fR and
+\fI/lib/dinit.d\fR, while a user process searches \fI$HOME/dinit.d\fR.
 .LP
 All services have a \fItype\fR and a set of \fIdependencies\fR. Service
 types are discussed in the following subsection. If a service depends on
index 753714f48f7615f6869180d5f085ad7d0d773fa2..3f0e48e3911068e85f2b8080d425454a0a30b92a 100644 (file)
@@ -20,15 +20,18 @@ specified via command line parameter) or as a user instance. This affects
 the default paths used to locate certain files, and the reaction to various
 signals.
 
-Dinit reads service descriptions from files located in the service
-description directory, normally \fI/etc/dinit.d\fR for the system instance
-or \fI$HOME/dinit.d\fR when run as a user process. See \fBSERVICE
-DESCRIPTION FILES\fR for details.
+Dinit reads service descriptions from files located in a service
+description directory, normally one of \fI/etc/dinit.d\fR,
+\fI/usr/local/lib/dinit.d/fR or \fI/lib/dinit.d\fR for the system instance
+or just \fI$HOME/dinit.d\fR when run as a user process. See \fBSERVICE
+DESCRIPTION FILES\fR for details of the service description format.
 .\"
 .SH OPTIONS
 .TP
 \fB\-d\fR \fIdir\fP, \fB\-\-services\-dir\fR \fIdir\fP
 Specifies \fIdir\fP as the directory containing service definition files.
+The directory specified will be the only directory searched for service
+definitions.
 .TP
 \fB\-e\fR \fIfile\fP, \fB\-\-env\-file\fR \fIfile\fP
 Read initial environment from \fIfile\fP. For the system init process, the
index 06445dcfd6d122ae12e32357a565b70928294a33..7297f9895fcace4408323d313015be3c23797a82 100644 (file)
@@ -165,6 +165,7 @@ int dinit_main(int argc, char **argv)
     
     am_system_init = (getpid() == 1);
     const char * service_dir = nullptr;
+    bool service_dir_dynamic = false; // service_dir dynamically allocated?
     const char * env_file = nullptr;
     string service_dir_str; // to hold storage for above if necessary
     bool control_socket_path_set = false;
@@ -306,16 +307,20 @@ int dinit_main(int argc, char **argv)
     if (service_dir == nullptr && ! am_system_init) {
         const char * userhome = get_user_home();
         if (userhome != nullptr) {
-            service_dir_str = get_user_home();
-            service_dir_str += "/dinit.d";
-            service_dir = service_dir_str.c_str();
+            const char * user_home = get_user_home();
+            size_t user_home_len = strlen(user_home);
+            size_t dinit_d_len = strlen("/dinit.d");
+            size_t full_len = user_home_len + dinit_d_len + 1;
+            char *service_dir_w = new char[full_len];
+            std::memcpy(service_dir_w, user_home, user_home_len);
+            std::memcpy(service_dir_w + user_home_len, "/dinit.d", dinit_d_len);
+            service_dir_w[full_len - 1] = 0;
+
+            service_dir = service_dir_w;
+            service_dir_dynamic = true;
         }
     }
     
-    if (service_dir == nullptr) {
-        service_dir = "/etc/dinit.d";
-    }
-    
     if (services_to_start.empty()) {
         services_to_start.push_back("boot");
     }
@@ -369,8 +374,18 @@ int dinit_main(int argc, char **argv)
     
     log_flush_timer.add_timer(event_loop, dasynq::clock_type::MONOTONIC);
 
+    bool add_all_service_dirs = false;
+    if (service_dir == nullptr) {
+        service_dir = "/etc/dinit.d";
+        add_all_service_dirs = true;
+    }
+
     /* start requested services */
-    services = new dirload_service_set(service_dir);
+    services = new dirload_service_set(service_dir, service_dir_dynamic);
+    if (add_all_service_dirs) {
+        services->add_service_dir("/usr/local/lib/dinit.d", false);
+        services->add_service_dir("/lib/dinit.d", false);
+    }
     
     init_log(services);
     if (am_system_init) {