ambrop7 пре 15 година
родитељ
комит
c50899fc1f

+ 1 - 0
blog_channels.txt

@@ -10,6 +10,7 @@ ncd_concat 4
 ncd_if 4
 ncd_strcmp 4
 ncd_ip_in_network 4
+ncd_run 4
 ncd_net_backend_physical 4
 ncd_net_backend_badvpn 4
 ncd_net_dns 4

+ 4 - 0
generated/blog_channel_ncd_run.h

@@ -0,0 +1,4 @@
+#ifdef BLOG_CURRENT_CHANNEL
+#undef BLOG_CURRENT_CHANNEL
+#endif
+#define BLOG_CURRENT_CHANNEL BLOG_CHANNEL_ncd_run

+ 25 - 24
generated/blog_channels_defines.h

@@ -10,27 +10,28 @@
 #define BLOG_CHANNEL_ncd_if 9
 #define BLOG_CHANNEL_ncd_strcmp 10
 #define BLOG_CHANNEL_ncd_ip_in_network 11
-#define BLOG_CHANNEL_ncd_net_backend_physical 12
-#define BLOG_CHANNEL_ncd_net_backend_badvpn 13
-#define BLOG_CHANNEL_ncd_net_dns 14
-#define BLOG_CHANNEL_ncd_net_iptables 15
-#define BLOG_CHANNEL_ncd_net_ipv4_addr 16
-#define BLOG_CHANNEL_ncd_net_ipv4_dhcp 17
-#define BLOG_CHANNEL_ncd_net_ipv4_route 18
-#define BLOG_CHANNEL_StreamPeerIO 19
-#define BLOG_CHANNEL_DatagramPeerIO 20
-#define BLOG_CHANNEL_BReactor 21
-#define BLOG_CHANNEL_BSignal 22
-#define BLOG_CHANNEL_FragmentProtoAssembler 23
-#define BLOG_CHANNEL_BPredicate 24
-#define BLOG_CHANNEL_ServerConnection 25
-#define BLOG_CHANNEL_Listener 26
-#define BLOG_CHANNEL_DataProto 27
-#define BLOG_CHANNEL_FrameDecider 28
-#define BLOG_CHANNEL_BSocksClient 29
-#define BLOG_CHANNEL_BDHCPClientCore 30
-#define BLOG_CHANNEL_BDHCPClient 31
-#define BLOG_CHANNEL_NCDIfConfig 32
-#define BLOG_CHANNEL_BUnixSignal 33
-#define BLOG_CHANNEL_BProcess 34
-#define BLOG_NUM_CHANNELS 35
+#define BLOG_CHANNEL_ncd_run 12
+#define BLOG_CHANNEL_ncd_net_backend_physical 13
+#define BLOG_CHANNEL_ncd_net_backend_badvpn 14
+#define BLOG_CHANNEL_ncd_net_dns 15
+#define BLOG_CHANNEL_ncd_net_iptables 16
+#define BLOG_CHANNEL_ncd_net_ipv4_addr 17
+#define BLOG_CHANNEL_ncd_net_ipv4_dhcp 18
+#define BLOG_CHANNEL_ncd_net_ipv4_route 19
+#define BLOG_CHANNEL_StreamPeerIO 20
+#define BLOG_CHANNEL_DatagramPeerIO 21
+#define BLOG_CHANNEL_BReactor 22
+#define BLOG_CHANNEL_BSignal 23
+#define BLOG_CHANNEL_FragmentProtoAssembler 24
+#define BLOG_CHANNEL_BPredicate 25
+#define BLOG_CHANNEL_ServerConnection 26
+#define BLOG_CHANNEL_Listener 27
+#define BLOG_CHANNEL_DataProto 28
+#define BLOG_CHANNEL_FrameDecider 29
+#define BLOG_CHANNEL_BSocksClient 30
+#define BLOG_CHANNEL_BDHCPClientCore 31
+#define BLOG_CHANNEL_BDHCPClient 32
+#define BLOG_CHANNEL_NCDIfConfig 33
+#define BLOG_CHANNEL_BUnixSignal 34
+#define BLOG_CHANNEL_BProcess 35
+#define BLOG_NUM_CHANNELS 36

+ 1 - 0
generated/blog_channels_list.h

@@ -10,6 +10,7 @@
 {.name = "ncd_if", .loglevel = 4},
 {.name = "ncd_strcmp", .loglevel = 4},
 {.name = "ncd_ip_in_network", .loglevel = 4},
+{.name = "ncd_run", .loglevel = 4},
 {.name = "ncd_net_backend_physical", .loglevel = 4},
 {.name = "ncd_net_backend_badvpn", .loglevel = 4},
 {.name = "ncd_net_dns", .loglevel = 4},

+ 1 - 0
ncd/CMakeLists.txt

@@ -12,6 +12,7 @@ add_executable(badvpn-ncd
     modules/if.c
     modules/strcmp.c
     modules/ip_in_network.c
+    modules/run.c
     modules/net_backend_physical.c
     modules/net_backend_badvpn.c
     modules/net_dns.c

+ 2 - 0
ncd/modules/modules.h

@@ -34,6 +34,7 @@ extern const struct NCDModuleGroup ncdmodule_concat;
 extern const struct NCDModuleGroup ncdmodule_if;
 extern const struct NCDModuleGroup ncdmodule_strcmp;
 extern const struct NCDModuleGroup ncdmodule_ip_in_network;
+extern const struct NCDModuleGroup ncdmodule_run;
 extern const struct NCDModuleGroup ncdmodule_net_backend_physical;
 extern const struct NCDModuleGroup ncdmodule_net_backend_badvpn;
 extern const struct NCDModuleGroup ncdmodule_net_dns;
@@ -50,6 +51,7 @@ static const struct NCDModuleGroup *ncd_modules[] = {
     &ncdmodule_if,
     &ncdmodule_strcmp,
     &ncdmodule_ip_in_network,
+    &ncdmodule_run,
     &ncdmodule_net_backend_physical,
     &ncdmodule_net_backend_badvpn,
     &ncdmodule_net_dns,

+ 177 - 0
ncd/modules/run.c

@@ -0,0 +1,177 @@
+/**
+ * @file run.c
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * This file is part of BadVPN.
+ * 
+ * BadVPN is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ * 
+ * BadVPN is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * @section DESCRIPTION
+ * 
+ * Module for running arbitrary programs.
+ * NOTE: There is no locking - the program may run in parallel with other
+ * NCD processes and their programs.
+ * 
+ * Synopsis: run(list do_cmd, list undo_cmd)
+ * 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).
+ *   list undo_cmd - Command run on shutdown, like do_cmd.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <ncd/modules/command_template.h>
+
+#include <generated/blog_channel_ncd_run.h>
+
+#define ModuleLog(i, ...) NCDModuleInst_Backend_Log((i), BLOG_CURRENT_CHANNEL, __VA_ARGS__)
+
+struct instance {
+    BEventLock lock;
+    command_template_instance cti;
+};
+
+static int build_cmdline (NCDModuleInst *i, int remove, char **exec, CmdLine *cl)
+{
+    // read arguments
+    NCDValue *do_cmd_arg;
+    NCDValue *undo_cmd_arg;
+    if (!NCDValue_ListRead(i->args, 2, &do_cmd_arg, &undo_cmd_arg)) {
+        ModuleLog(i, BLOG_ERROR, "wrong arity");
+        goto fail0;
+    }
+    if (NCDValue_Type(do_cmd_arg) != NCDVALUE_LIST || NCDValue_Type(undo_cmd_arg) != NCDVALUE_LIST) {
+        ModuleLog(i, BLOG_ERROR, "wrong type");
+        goto fail0;
+    }
+    
+    NCDValue *list = (remove ? undo_cmd_arg : do_cmd_arg);
+    
+    // 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;
+    }
+    if (!(*exec = strdup(NCDValue_StringValue(exec_arg)))) {
+        ModuleLog(i, BLOG_ERROR, "strdup failed");
+        goto fail0;
+    }
+    
+    // start cmdline
+    if (!CmdLine_Init(cl)) {
+        ModuleLog(i, BLOG_ERROR, "CmdLine_Init failed");
+        goto fail1;
+    }
+    
+    // add header
+    if (!CmdLine_Append(cl, *exec)) {
+        ModuleLog(i, BLOG_ERROR, "CmdLine_Append failed");
+        goto fail2;
+    }
+    
+    // add additional arguments
+    NCDValue *arg = exec_arg;
+    while (arg = NCDValue_ListNext(list, arg)) {
+        if (NCDValue_Type(arg) != NCDVALUE_STRING) {
+            ModuleLog(i, BLOG_ERROR, "wrong type");
+            goto fail2;
+        }
+        
+        if (!CmdLine_Append(cl, NCDValue_StringValue(arg))) {
+            ModuleLog(i, BLOG_ERROR, "CmdLine_Append failed");
+            goto fail2;
+        }
+    }
+    
+    // finish
+    if (!CmdLine_Finish(cl)) {
+        ModuleLog(i, BLOG_ERROR, "CmdLine_Finish failed");
+        goto fail2;
+    }
+    
+    return 1;
+    
+fail2:
+    CmdLine_Free(cl);
+fail1:
+    free(*exec);
+fail0:
+    return 0;
+}
+
+static void * func_new (NCDModuleInst *i)
+{
+    struct instance *o = malloc(sizeof(*o));
+    if (!o) {
+        BLog(BLOG_ERROR, "malloc failed");
+        goto fail0;
+    }
+    
+    BEventLock_Init(&o->lock, BReactor_PendingGroup(i->reactor));
+    
+    if (!command_template_new(&o->cti, i, build_cmdline, BLOG_CURRENT_CHANNEL, &o->lock)) {
+        goto fail1;
+    }
+    
+    return o;
+    
+fail1:
+    BEventLock_Free(&o->lock);
+    free(o);
+fail0:
+    return NULL;
+}
+
+static void func_free (void *vo)
+{
+    struct instance *o = vo;
+    
+    command_template_free(&o->cti);
+    
+    BEventLock_Free(&o->lock);
+    
+    free(o);
+}
+
+static void func_die (void *vo)
+{
+    struct instance *o = vo;
+    
+    command_template_die(&o->cti);
+}
+
+static const struct NCDModule modules[] = {
+    {
+        .type = "run",
+        .func_new = func_new,
+        .func_free = func_free,
+        .func_die = func_die
+    }, {
+        .type = NULL
+    }
+};
+
+const struct NCDModuleGroup ncdmodule_run= {
+    .modules = modules
+};