diff options
Diffstat (limited to 'init/init.c')
| -rw-r--r-- | init/init.c | 57 |
1 files changed, 49 insertions, 8 deletions
diff --git a/init/init.c b/init/init.c index 16301555..dfc858a4 100644 --- a/init/init.c +++ b/init/init.c @@ -156,7 +156,7 @@ static void publish_socket(const char *name, int fd) 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 @@ void service_start(struct service *svc) 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 @@ void service_start(struct service *svc) 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 @@ static void restart_service_if_needed(struct service *svc) if (next_start_time <= gettime()) { svc->flags &= (~SVC_RESTARTING); - service_start(svc); + service_start(svc, NULL); return; } @@ -407,13 +433,28 @@ static void sigchld_handler(int s) 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 @@ static void msg_stop(const char *name) if (svc) { service_stop(svc); } else { - ERROR("no such service '%s'\n"); + ERROR("no such service '%s'\n", name); } } @@ -739,7 +780,7 @@ void handle_keychord(int fd) 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); } |
