Kaynağa Gözat

ncd: modules: sys_start_process: implement process startup options like in runonce() in daemon()

ambrop7 13 yıl önce
ebeveyn
işleme
aefe4561c5
1 değiştirilmiş dosya ile 45 ekleme ve 7 silme
  1. 45 7
      ncd/modules/sys_start_process.c

+ 45 - 7
ncd/modules/sys_start_process.c

@@ -29,7 +29,16 @@
  * @section DESCRIPTION
  * 
  * Synopsis:
- *   sys.start_process(list command, string mode)
+ *   sys.start_process(list command, string mode [, map options])
+ * 
+ * Options:
+ *   "keep_stdout":"true" - Start the program with the same stdout as the NCD process.
+ *     Must not be present if the process is being opened for reading.
+ *   "keep_stderr":true" - Start the program with the same stderr as the NCD process.
+ *   "do_setsid":"true" - Call setsid() in the child before exec. This is needed to
+ *     start the 'agetty' program.
+ *   "username":username_string - Start the process under the permissions of the
+ *       specified user. 
  * 
  * Variables:
  *   is_error - "true" if there was an error starting the process, "false" if the process
@@ -132,6 +141,7 @@
 #include <ncd/extra/NCDBuf.h>
 #include <ncd/extra/value_utils.h>
 #include <ncd/extra/build_cmdline.h>
+#include <ncd/extra/NCDBProcessOpts.h>
 
 #include <generated/blog_channel_ncd_sys_start_process.h>
 
@@ -292,7 +302,10 @@ static void process_func_new (void *vo, NCDModuleInst *i, const struct NCDModule
     // check arguments
     NCDValRef command_arg;
     NCDValRef mode_arg;
-    if (!NCDVal_ListRead(params->args, 2, &command_arg, &mode_arg)) {
+    NCDValRef options_arg = NCDVal_NewInvalid();
+    if (!NCDVal_ListRead(params->args, 2, &command_arg, &mode_arg) &&
+        !NCDVal_ListRead(params->args, 3, &command_arg, &mode_arg, &options_arg)
+    ) {
         ModuleLog(i, BLOG_ERROR, "wrong arity");
         goto fail0;
     }
@@ -304,10 +317,27 @@ static void process_func_new (void *vo, NCDModuleInst *i, const struct NCDModule
         goto fail0;
     }
     
+    // parse options
+    NCDBProcessOpts opts;
+    int keep_stdout;
+    int keep_stderr;
+    if (!NCDBProcessOpts_Init2(&opts, options_arg, NULL, NULL, i, BLOG_CURRENT_CHANNEL, &keep_stdout, &keep_stderr)) {
+        goto fail0;
+    }
+    
+    // keep-stdout option and read mode are not compatible
+    if (keep_stdout && is_read) {
+        ModuleLog(i, BLOG_ERROR, "keep-stdout and read mode are not compatible");
+        goto fail1;
+    }
+    
     // prepare for creating pipes
-    int fds[3];
-    int fds_map[2];
-    int num_fds = 0;
+    int fds[4];
+    int fds_map[3];
+    int start_num_fds = opts.nfds;
+    int num_fds = start_num_fds;
+    memcpy(fds, opts.fds, num_fds * sizeof(int));
+    memcpy(fds_map, opts.fds_map, num_fds * sizeof(int));
     int read_fd = -1;
     int write_fd = -1;
     
@@ -342,6 +372,8 @@ static void process_func_new (void *vo, NCDModuleInst *i, const struct NCDModule
     struct BProcess_params p_params = {};
     p_params.fds = fds;
     p_params.fds_map = fds_map;
+    p_params.do_setsid = opts.do_setsid;
+    p_params.username = opts.username;
     
     // build command line
     char *exec;
@@ -360,12 +392,15 @@ static void process_func_new (void *vo, NCDModuleInst *i, const struct NCDModule
     }
     
     // close child fds
-    while (num_fds-- > 0) {
+    while (num_fds-- > start_num_fds) {
         if (close(fds[num_fds]) < 0) {
             ModuleLog(i, BLOG_ERROR, "close failed");
         }
     }
     
+    // free opts
+    NCDBProcessOpts_Free(&opts);
+    
     // init waits list
     LinkedList0_Init(&o->waits_list);
     
@@ -380,6 +415,8 @@ static void process_func_new (void *vo, NCDModuleInst *i, const struct NCDModule
     NCDModuleInst_Backend_Up(i);
     return;
     
+fail1:
+    NCDBProcessOpts_Free(&opts);
 fail0:
     NCDModuleInst_Backend_DeadError(i);
     return;
@@ -395,11 +432,12 @@ error1:
             ModuleLog(i, BLOG_ERROR, "close failed");
         }
     }
-    while (num_fds-- > 0) {
+    while (num_fds-- > start_num_fds) {
         if (close(fds[num_fds]) < 0) {
             ModuleLog(i, BLOG_ERROR, "close failed");
         }
     }
+    NCDBProcessOpts_Free(&opts);
     
     o->read_fd = -1;
     o->write_fd = -1;