Просмотр исходного кода

ncd: modules: run: allow empty command

ambrop7 14 лет назад
Родитель
Сommit
5d0897e700
3 измененных файлов с 111 добавлено и 62 удалено
  1. 100 57
      ncd/modules/command_template.c
  2. 4 0
      ncd/modules/command_template.h
  3. 7 5
      ncd/modules/run.c

+ 100 - 57
ncd/modules/command_template.c

@@ -31,58 +31,47 @@
 #define STATE_DELETING_LOCK 5
 #define STATE_DELETING 6
 
-static int start_process (command_template_instance *o, int remove);
+static void lock_handler (command_template_instance *o);
 static void process_handler (command_template_instance *o, int normally, uint8_t normally_exit_status);
 static void free_template (command_template_instance *o, int is_error);
 
-int start_process (command_template_instance *o, int remove)
-{
-    int ret = 0;
-    
-    // build command line
-    char *exec;
-    CmdLine cl;
-    if (!(o->build_cmdline(o->i, remove, &exec, &cl))) {
-        NCDModuleInst_Backend_Log(o->i, o->blog_channel, BLOG_ERROR, "build_cmdline callback failed");
-        goto fail0;
-    }
-    
-    // start process
-    if (!BProcess_Init(&o->process, o->i->manager, (BProcess_handler)process_handler, o, exec, CmdLine_Get(&cl), NULL)) {
-        NCDModuleInst_Backend_Log(o->i, o->blog_channel, BLOG_ERROR, "BProcess_Init failed");
-        goto fail1;
-    }
-    
-    ret = 1;
-    
-fail1:
-    CmdLine_Free(&cl);
-    free(exec);
-fail0:
-    return ret;
-}
-
 static void lock_handler (command_template_instance *o)
 {
     ASSERT(o->state == STATE_ADDING_LOCK || o->state == STATE_DELETING_LOCK)
     ASSERT(!o->have_process)
-    
-    int remove = (o->state == STATE_DELETING_LOCK);
-    
-    // start process
-    if (!start_process(o, remove)) {
-        free_template(o, 1);
-        return;
+    ASSERT(!(o->state == STATE_ADDING_LOCK) || o->do_exec)
+    ASSERT(!(o->state == STATE_DELETING_LOCK) || o->undo_exec)
+    
+    if (o->state == STATE_ADDING_LOCK) {
+        // start process
+        if (!BProcess_Init(&o->process, o->i->manager, (BProcess_handler)process_handler, o, o->do_exec, CmdLine_Get(&o->do_cmdline), NULL)) {
+            NCDModuleInst_Backend_Log(o->i, o->blog_channel, BLOG_ERROR, "BProcess_Init failed");
+            free_template(o, 1);
+            return;
+        }
+        
+        // set have process
+        o->have_process = 1;
+        
+        // set state
+        o->state = STATE_ADDING;
+    } else {
+        // start process
+        if (!BProcess_Init(&o->process, o->i->manager, (BProcess_handler)process_handler, o, o->undo_exec, CmdLine_Get(&o->undo_cmdline), NULL)) {
+            NCDModuleInst_Backend_Log(o->i, o->blog_channel, BLOG_ERROR, "BProcess_Init failed");
+            free_template(o, 1);
+            return;
+        }
+        
+        // set have process
+        o->have_process = 1;
+        
+        // set state
+        o->state = STATE_DELETING;
     }
-    
-    // set have process
-    o->have_process = 1;
-    
-    // set state
-    o->state = (remove ? STATE_DELETING : STATE_ADDING);
 }
 
-void process_handler (command_template_instance *o, int normally, uint8_t normally_exit_status)
+static void process_handler (command_template_instance *o, int normally, uint8_t normally_exit_status)
 {
     ASSERT(o->have_process)
     ASSERT(o->state == STATE_ADDING || o->state == STATE_ADDING_NEED_DELETE || o->state == STATE_DELETING)
@@ -105,6 +94,7 @@ void process_handler (command_template_instance *o, int normally, uint8_t normal
     
     switch (o->state) {
         case STATE_ADDING: {
+            // set state
             o->state = STATE_DONE;
             
             // signal up
@@ -112,11 +102,16 @@ void process_handler (command_template_instance *o, int normally, uint8_t normal
         } break;
         
         case STATE_ADDING_NEED_DELETE: {
-            // wait for lock
-            BEventLockJob_Wait(&o->elock_job);
-            
-            // set state
-            o->state = STATE_DELETING_LOCK;
+            if (o->undo_exec) {
+                // wait for lock
+                BEventLockJob_Wait(&o->elock_job);
+                
+                // set state
+                o->state = STATE_DELETING_LOCK;
+            } else {
+                free_template(o, 0);
+                return;
+            }
         } break;
         
         case STATE_DELETING: {
@@ -136,26 +131,68 @@ void command_template_new (command_template_instance *o, NCDModuleInst *i, comma
     o->user = user;
     o->blog_channel = blog_channel;
     
+    // build do command
+    if (!o->build_cmdline(o->i, 0, &o->do_exec, &o->do_cmdline)) {
+        NCDModuleInst_Backend_Log(o->i, o->blog_channel, BLOG_ERROR, "build_cmdline do callback failed");
+        goto fail0;
+    }
+    
+    // build undo command
+    if (!o->build_cmdline(o->i, 1, &o->undo_exec, &o->undo_cmdline)) {
+        NCDModuleInst_Backend_Log(o->i, o->blog_channel, BLOG_ERROR, "build_cmdline undo callback failed");
+        goto fail1;
+    }
+    
     // init lock job
     BEventLockJob_Init(&o->elock_job, elock, (BEventLock_handler)lock_handler, o);
     
     // set have no process
     o->have_process = 0;
     
-    // wait for lock
-    BEventLockJob_Wait(&o->elock_job);
+    if (o->do_exec) {
+        // wait for lock
+        BEventLockJob_Wait(&o->elock_job);
+        
+        // set state
+        o->state = STATE_ADDING_LOCK;
+    } else {
+        // set state
+        o->state = STATE_DONE;
+        
+        // signal up
+        NCDModuleInst_Backend_Event(o->i, NCDMODULE_EVENT_UP);
+    }
+    
+    return;
     
-    // set state
-    o->state = STATE_ADDING_LOCK;
+fail1:
+    if (o->do_exec) {
+        free(o->do_exec);
+        CmdLine_Free(&o->do_cmdline);
+    }
+fail0:
+    o->free_func(o->user, 1);
 }
 
-void free_template (command_template_instance *o, int is_error)
+static void free_template (command_template_instance *o, int is_error)
 {
     ASSERT(!o->have_process)
     
     // free lock job
     BEventLockJob_Free(&o->elock_job);
     
+    // free undo command
+    if (o->undo_exec) {
+        free(o->undo_exec);
+        CmdLine_Free(&o->undo_cmdline);
+    }
+    
+    // free do command
+    if (o->do_exec) {
+        free(o->do_exec);
+        CmdLine_Free(&o->do_cmdline);
+    }
+    
     // call free function
     o->free_func(o->user, is_error);
 }
@@ -175,17 +212,23 @@ void command_template_die (command_template_instance *o)
         case STATE_ADDING: {
             ASSERT(o->have_process)
             
+            // set state
             o->state = STATE_ADDING_NEED_DELETE;
         } break;
         
         case STATE_DONE: {
             ASSERT(!o->have_process)
             
-            // wait for lock
-            BEventLockJob_Wait(&o->elock_job);
-            
-            // set state
-            o->state = STATE_DELETING_LOCK;
+            if (o->undo_exec) {
+                // wait for lock
+                BEventLockJob_Wait(&o->elock_job);
+                
+                // set state
+                o->state = STATE_DELETING_LOCK;
+            } else {
+                free_template(o, 0);
+                return;
+            }
         } break;
     }
 }

+ 4 - 0
ncd/modules/command_template.h

@@ -43,6 +43,10 @@ typedef struct {
     command_template_free_func free_func;
     void *user;
     int blog_channel;
+    char *do_exec;
+    CmdLine do_cmdline;
+    char *undo_exec;
+    CmdLine undo_cmdline;
     BEventLockJob elock_job;
     int state;
     int have_process;

+ 7 - 5
ncd/modules/run.c

@@ -29,7 +29,7 @@
  * Arguments:
  *   list do_cmd - Command run on startup. The first element is the full path
  *     to the executable, other elements are command line arguments (excluding
- *     the zeroth argument).
+ *     the zeroth argument). An empty list is interpreted as no operation.
  *   list undo_cmd - Command run on shutdown, like do_cmd.
  */
 
@@ -66,12 +66,14 @@ static int build_cmdline (NCDModuleInst *i, int remove, char **exec, CmdLine *cl
     
     NCDValue *list = (remove ? undo_cmd_arg : do_cmd_arg);
     
+    // check if there is no command
+    if (!NCDValue_ListFirst(list)) {
+        *exec = NULL;
+        return 1;
+    }
+    
     // read exec
     NCDValue *exec_arg = NCDValue_ListFirst(list);
-    if (!exec_arg) {
-        ModuleLog(i, BLOG_ERROR, "missing executable name");
-        goto fail0;
-    }
     if (NCDValue_Type(exec_arg) != NCDVALUE_STRING) {
         ModuleLog(i, BLOG_ERROR, "wrong type");
         goto fail0;