Implement additional checks for reload
authorDavin McCall <davmac@davmac.org>
Mon, 2 Dec 2019 11:13:32 +0000 (21:13 +1000)
committerDavin McCall <davmac@davmac.org>
Mon, 2 Dec 2019 11:13:32 +0000 (21:13 +1000)
The settings/flags inittab-id, inittab-line, shares-console,
runs-on-console, and pid-file cannot be changed for a running service.

src/includes/proc-service.h
src/includes/service.h
src/load-service.cc

index 99aad596b03dbae0a52ab4eb9761608726b434d4..7056a6db8b2ce8871afdd09eba1afe46fe7e68e0 100644 (file)
@@ -434,6 +434,21 @@ class process_service : public base_process_service
         strncpy(inittab_line, line, sizeof(inittab_line));
     }
 
+    // Get the utmp (inittab) id, may not be nul terminated if maximum length!
+    const char *get_utmp_id()
+    {
+        return inittab_id;
+    }
+
+    // Get the utmp (inittab) line, may not be nul terminated if maximum length!
+    const char *get_utmp_line()
+    {
+        return inittab_line;
+    }
+
+    constexpr size_t get_utmp_id_size() { return sizeof(inittab_id); }
+    constexpr size_t get_utmp_line_size() { return sizeof(inittab_line); }
+
 #endif
 
     ~process_service() noexcept
@@ -454,7 +469,9 @@ class bgproc_service : public base_process_service
         TERMINATED   // read pid successfully, but the process already terminated
     };
 
-    // Read the pid-file, return false on failure
+    string pid_file;
+
+    // Read the pid-file contents
     pid_result_t read_pid_file(bp_sys::exit_status *exit_status) noexcept;
 
     public:
@@ -469,6 +486,16 @@ class bgproc_service : public base_process_service
     ~bgproc_service() noexcept
     {
     }
+
+    void set_pid_file(string &&pid_file) noexcept
+    {
+        this->pid_file = std::move(pid_file);
+    }
+
+    const std::string &get_pid_file() noexcept
+    {
+        return pid_file;
+    }
 };
 
 // Service which is started and stopped via separate commands
index 5ebb8b92c1d57537ee7ea44b05c43336921ca2f7..c4f8dcf5b5eb6f189a5cae3cfd8c12b5edf902e5 100644 (file)
@@ -196,8 +196,6 @@ class service_record
     service_state_t desired_state = service_state_t::STOPPED;
 
     protected:
-    string pid_file;
-    
     service_flags_t onstart_flags;
 
     string logfile;           // log file name, empty string specifies /dev/null
@@ -481,11 +479,11 @@ class service_record
         this->onstart_flags = flags;
     }
 
-    void set_pid_file(string &&pid_file) noexcept
+    service_flags_t get_flags() noexcept
     {
-        this->pid_file = std::move(pid_file);
+        return onstart_flags;
     }
-    
+
     void set_socket_details(string &&socket_path, int socket_perms, uid_t socket_uid, uid_t socket_gid)
             noexcept
     {
index f5f01fdb7d22c85598f2a0429c90800c8770cc64..08c7fee6a389c05ae3a6c8d8f73e3d9c04127a4a 100644 (file)
@@ -488,9 +488,36 @@ service_record * dirload_service_set::reload_service(service_record * service)
                 }
             }
 
-            //    XXX cannot change pid_file
-            //    XXX cannot change service flags: runs_on_console, shares_console
-            //    XXX cannot change inittab_id/inittab_line
+            // Cannot change certain flags
+            auto current_flags = service->get_flags();
+            if (current_flags.starts_on_console != settings.onstart_flags.starts_on_console
+                    || current_flags.shares_console != settings.onstart_flags.shares_console) {
+                throw service_description_exc(name, "Cannot change starts_on_console/"
+                        "shares_console flags for a running service.");
+            }
+
+            // Cannot change pid file
+            if (service->get_type() == service_type_t::BGPROCESS) {
+                auto *bgp_service = static_cast<bgproc_service *>(service);
+                if (bgp_service->get_pid_file() != settings.pid_file) {
+                    throw service_description_exc(name, "Cannot change pid_file for running service.");
+                }
+            }
+
+            // Cannot change inittab_id/inittab_line
+            #if USE_UTMPX
+                if (service->get_type() == service_type_t::PROCESS) {
+                    auto *proc_service = static_cast<process_service *>(service);
+                    auto *svc_utmp_id = proc_service->get_utmp_id();
+                    auto *svc_utmp_ln = proc_service->get_utmp_line();
+                    if (strncmp(svc_utmp_id, settings.inittab_id, proc_service->get_utmp_id_size()) != 0
+                            || strncmp(svc_utmp_ln, settings.inittab_line,
+                                    proc_service->get_utmp_line_size()) != 0) {
+                        throw service_description_exc(name, "Cannot change inittab-id or inittab-line "
+                                "settings for running service.");
+                    }
+                }
+            #endif
 
             // Already started; we must replace settings on existing service record
             create_new_record = false;