Merge korg/donut into korg/master
diff --git a/init/init.c b/init/init.c
index 1630155..dfc858a 100644
--- a/init/init.c
+++ b/init/init.c
@@ -156,7 +156,7 @@
     fcntl(fd, F_SETFD, 0);
 }
 
-void service_start(struct service *svc)
+void service_start(struct service *svc, const char *dynamic_args)
 {
     struct stat s;
     pid_t pid;
@@ -192,6 +192,13 @@
         return;
     }
 
+    if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) {
+        ERROR("service '%s' must be one-shot to use dynamic args, disabling\n",
+               svc->args[0]);
+        svc->flags |= SVC_DISABLED;
+        return;
+    }
+
     NOTICE("starting '%s'\n", svc->name);
 
     pid = fork();
@@ -248,8 +255,27 @@
             setuid(svc->uid);
         }
 
-        if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) {
-            ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
+        if (!dynamic_args)
+            if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0)
+                ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
+        else {
+            char *arg_ptrs[SVC_MAXARGS+1];
+            int arg_idx = svc->nargs;
+            char *tmp = strdup(dynamic_args);
+            char *next = tmp;
+            char *bword;
+
+            /* Copy the static arguments */
+            memcpy(arg_ptrs, svc->args, (svc->nargs * sizeof(char *)));
+
+            while((bword = strsep(&next, " "))) {
+                arg_ptrs[arg_idx++] = bword;
+                if (arg_idx == SVC_MAXARGS)
+                    break;
+            }
+            arg_ptrs[arg_idx] = '\0';
+            if (execve(svc->args[0], (char**) arg_ptrs, (char**) ENV) < 0)
+                ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
         }
         _exit(127);
     }
@@ -381,7 +407,7 @@
 
     if (next_start_time <= gettime()) {
         svc->flags &= (~SVC_RESTARTING);
-        service_start(svc);
+        service_start(svc, NULL);
         return;
     }
 
@@ -407,13 +433,28 @@
 
 static void msg_start(const char *name)
 {
-    struct service *svc = service_find_by_name(name);
+    struct service *svc;
+    char *tmp = NULL;
+    char *args = NULL;
+
+    if (!strchr(name, ':'))
+        svc = service_find_by_name(name);
+    else {
+        tmp = strdup(name);
+        args = strchr(tmp, ':');
+        *args = '\0';
+        args++;
+
+        svc = service_find_by_name(tmp);
+    }
     
     if (svc) {
-        service_start(svc);
+        service_start(svc, args);
     } else {
         ERROR("no such service '%s'\n", name);
     }
+    if (tmp)
+        free(tmp);
 }
 
 static void msg_stop(const char *name)
@@ -423,7 +464,7 @@
     if (svc) {
         service_stop(svc);
     } else {
-        ERROR("no such service '%s'\n");
+        ERROR("no such service '%s'\n", name);
     }
 }
 
@@ -739,7 +780,7 @@
     svc = service_find_by_keychord(id);
     if (svc) {
         INFO("starting service %s from keychord\n", svc->name);
-        service_start(svc);   
+        service_start(svc, NULL);
     } else {
         ERROR("service for keychord %d not found\n", id);
     }