Implement "env-file" service setting for service-specific environment.
authorDavin McCall <davmac@davmac.org>
Sat, 6 Jul 2019 00:05:09 +0000 (01:05 +0100)
committerDavin McCall <davmac@davmac.org>
Sat, 6 Jul 2019 04:06:17 +0000 (14:06 +1000)
src/baseproc-service.cc
src/dinit.cc
src/includes/dinit.h
src/includes/proc-service.h
src/load-service.cc
src/run-child-proc.cc
src/tests/test-includes/dinit.h

index 0bc9414f1d0f09b26f3445a03bafe775aa60f206..157b7ae6a5b13051e5866bfde35718df784b3917 100644 (file)
@@ -162,6 +162,7 @@ bool base_process_service::start_ps_process(const std::vector<const char *> &cmd
         run_params.notify_fd = notify_pipe[1];
         run_params.force_notify_fd = force_notification_fd;
         run_params.notify_var = notification_var.c_str();
+        run_params.env_file = env_file.c_str();
         run_child_proc(run_params);
     }
     else {
index 5e87cccf16d90e47699b8434d20f9f28d44cda1d..c997201d0b9f6ee3e31144861e7dcfec33974f5d 100644 (file)
@@ -59,7 +59,6 @@ static void sigterm_cb(eventloop_t &eloop) noexcept;
 static void open_control_socket(bool report_ro_failure = true) noexcept;
 static void close_control_socket() noexcept;
 static void confirm_restart_boot() noexcept;
-static void read_env_file(const char *);
 
 static void control_socket_cb(eventloop_t *loop, int fd);
 
@@ -558,8 +557,8 @@ static void log_bad_env(int linenum)
     log(loglevel_t::ERROR, "invalid environment variable setting in environment file (line ", linenum, ")");
 }
 
-// Read and set environment variables from a file.
-static void read_env_file(const char *env_file_path)
+// Read and set environment variables from a file. May throw std::bad_alloc, std::system_error.
+void read_env_file(const char *env_file_path)
 {
     // Note that we can't use the log in this function; it hasn't been initialised yet.
 
index fc20ee34efcf09136f48366862dd967e049e3488..180a5fdb8ec4dc18a5521d8985f69bdcb66c410c 100644 (file)
@@ -15,6 +15,7 @@ using time_val = dasynq::time_val;
 
 void rootfs_is_rw() noexcept;
 void setup_external_log() noexcept;
+void read_env_file(const char *);
 
 extern eventloop_t event_loop;
 
index f3af5413f022afbe73829d036d3f7b199bf339fe..b77113de6f244ed1e16de9722d488b49107a2cd9 100644 (file)
@@ -31,6 +31,7 @@ struct run_proc_params
     const char * const *args; // program arguments including executable (args[0])
     const char *working_dir;  // working directory
     const char *logfile;      // log file or nullptr (stdout/stderr); must be valid if !on_console
+    const char *env_file;      // file with environment settings (or nullptr)
     bool on_console;          // whether to run on console
     int wpipefd;              // pipe to which error status will be sent (if error occurs)
     int csfd;                 // control socket fd (or -1); may be moved
@@ -44,9 +45,9 @@ struct run_proc_params
 
     run_proc_params(const char * const *args, const char *working_dir, const char *logfile, int wpipefd,
             uid_t uid, gid_t gid, const std::vector<service_rlimits> &rlimits)
-            : args(args), working_dir(working_dir), logfile(logfile), on_console(false), wpipefd(wpipefd),
-              csfd(-1), socket_fd(-1), notify_fd(-1), force_notify_fd(-1), notify_var(nullptr), uid(uid),
-              gid(gid), rlimits(rlimits)
+            : args(args), working_dir(working_dir), logfile(logfile), env_file(nullptr), on_console(false),
+              wpipefd(wpipefd), csfd(-1), socket_fd(-1), notify_fd(-1), force_notify_fd(-1), notify_var(nullptr),
+              uid(uid), gid(gid), rlimits(rlimits)
     { }
 };
 
@@ -128,6 +129,7 @@ class base_process_service : public service_record
     std::vector<const char *> stop_arg_parts;
 
     string working_dir;       // working directory (or empty)
+    string env_file;          // file with environment settings for this service
 
     std::vector<service_rlimits> rlimits; // resource limits
 
@@ -256,6 +258,11 @@ class base_process_service : public service_record
         stop_arg_parts = separate_args(stop_command, stop_command_offsets);
     }
 
+    void set_env_file(const std::string &env_file_p)
+    {
+        env_file = env_file_p;
+    }
+
     void set_rlimits(std::vector<service_rlimits> &&rlimits_p)
     {
         rlimits = std::move(rlimits_p);
index f4b4af27fbf15a9a7607d270de8aefabb98cef07..3040cf34bfe346cd2b431dbe575109d94f80f58f 100644 (file)
@@ -436,6 +436,7 @@ service_record * dirload_service_set::load_service(const char * name)
     list<pair<unsigned,unsigned>> stop_command_offsets;
     string working_dir;
     string pid_file;
+    string env_file;
 
     bool do_sub_vars = false;
 
@@ -493,6 +494,9 @@ service_record * dirload_service_set::load_service(const char * name)
             else if (setting == "working-dir") {
                 working_dir = read_setting_value(i, end, nullptr);
             }
+            else if (setting == "env-file") {
+                env_file = read_setting_value(i, end, nullptr);
+            }
             else if (setting == "socket-listen") {
                 socket_path = read_setting_value(i, end, nullptr);
             }
@@ -757,6 +761,7 @@ service_record * dirload_service_set::load_service(const char * name)
                     auto rvalps = new process_service(this, string(name), std::move(command),
                             command_offsets, depends);
                     rvalps->set_working_dir(working_dir);
+                    rvalps->set_env_file(env_file);
                     rvalps->set_rlimits(std::move(rlimits));
                     rvalps->set_restart_interval(restart_interval, max_restarts);
                     rvalps->set_restart_delay(restart_delay);
@@ -777,6 +782,7 @@ service_record * dirload_service_set::load_service(const char * name)
                     auto rvalps = new bgproc_service(this, string(name), std::move(command),
                             command_offsets, depends);
                     rvalps->set_working_dir(working_dir);
+                    rvalps->set_env_file(env_file);
                     rvalps->set_rlimits(std::move(rlimits));
                     rvalps->set_pid_file(std::move(pid_file));
                     rvalps->set_restart_interval(restart_interval, max_restarts);
@@ -794,6 +800,7 @@ service_record * dirload_service_set::load_service(const char * name)
                             command_offsets, depends);
                     rvalps->set_stop_command(stop_command, stop_command_offsets);
                     rvalps->set_working_dir(working_dir);
+                    rvalps->set_env_file(env_file);
                     rvalps->set_rlimits(std::move(rlimits));
                     rvalps->set_stop_timeout(stop_timeout);
                     rvalps->set_start_timeout(start_timeout);
index 837a2c9ee2181abfcd90531133423064fa337d22..d3a8326811519a64247ff7a44c29247dd035ae6b 100644 (file)
@@ -129,6 +129,19 @@ void base_process_service::run_child_proc(run_proc_params params) noexcept
         if (notify_fd == -1) goto failure_out;
     }
 
+    // Read environment from file
+    if (params.env_file != nullptr) {
+        try {
+            read_env_file(params.env_file);
+        }
+        catch (std::system_error &sys_err) {
+            errno = sys_err.code().value();
+        }
+        catch (std::bad_alloc &alloc_err) {
+            errno = ENOMEM; goto failure_out;
+        }
+    }
+
     // Set up notify-fd variable:
     if (notify_var != nullptr && *notify_var != 0) {
         // We need to do an allocation: the variable name length, '=', and space for the value,
index e3cef621d72395f9c325db9c3d582ea47df5c1e8..59013467e87b53209bdcc89a525ebaf39e399b81 100644 (file)
@@ -215,6 +215,10 @@ inline void setup_external_log() noexcept
 {
 }
 
+inline void read_env_file(const char *env_file_path)
+{
+}
+
 extern eventloop_t event_loop;
 
 #endif