From: John Crispin Date: Thu, 9 May 2013 18:14:27 +0000 (+0200) Subject: add a rcS helper X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fprocd.git;a=commitdiff_plain;h=0c116c65f9bc4132fa0dfc99e875f57e9ee29af1 add a rcS helper Signed-off-by: John Crispin --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 62e309a..0d3a989 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ IF(APPLE) LINK_DIRECTORIES(/opt/local/lib) ENDIF() -SET(SOURCES main.c ubus.c service.c instance.c utils.c md5.c hotplug.c state.c mkdev.c early.c inittab.c preinit.c coldplug.c syslog.c log.c watchdog.c signal.c system.c debug.c) +SET(SOURCES main.c ubus.c service.c instance.c utils.c md5.c hotplug.c state.c mkdev.c early.c inittab.c preinit.c coldplug.c syslog.c log.c watchdog.c signal.c system.c debug.c rcS.c) find_library(json NAMES json-c json) SET(LIBS ubox ubus ${json} blobmsg_json json_script) diff --git a/inittab.c b/inittab.c index 32be11f..2ed1395 100644 --- a/inittab.c +++ b/inittab.c @@ -25,6 +25,7 @@ #include #include "procd.h" +#include "rcS.h" #define TAG_ID 0 #define TAG_RUNLVL 1 @@ -39,7 +40,7 @@ const char *console; struct init_handler { const char *name; void (*cb) (struct init_action *a); - int atomic; + int multi; }; struct init_action { @@ -52,7 +53,6 @@ struct init_action { struct init_handler *handler; struct uloop_process proc; - int pending; int respawn; struct uloop_timeout tout; }; @@ -60,11 +60,9 @@ struct init_action { static const char *tab = "/etc/inittab"; static char *ask = "/sbin/askfirst"; -static struct init_action *pending; - static LIST_HEAD(actions); -static void fork_script(struct init_action *a) +static void fork_worker(struct init_action *a) { a->proc.pid = fork(); if (!a->proc.pid) { @@ -86,25 +84,27 @@ static void child_exit(struct uloop_process *proc, int ret) struct init_action *a = container_of(proc, struct init_action, proc); DEBUG(2, "pid:%d\n", proc->pid); - if (a->tout.cb) { - uloop_timeout_set(&a->tout, a->respawn); - } else { - a->pending = 0; - pending = NULL; - procd_state_next(); - } + uloop_timeout_set(&a->tout, a->respawn); } static void respawn(struct uloop_timeout *tout) { struct init_action *a = container_of(tout, struct init_action, tout); - fork_script(a); + fork_worker(a); } -static void runscript(struct init_action *a) +static void rcdone(struct runqueue *q) { - a->proc.cb = child_exit; - fork_script(a); + procd_state_next(); +} + +static void runrc(struct init_action *a) +{ + if (!a->argv[1] || !a->argv[2]) { + ERROR("valid format is rcS \n"); + return; + } + rcS(a->argv[1], a->argv[2], rcdone); } static void askfirst(struct init_action *a) @@ -128,7 +128,7 @@ static void askfirst(struct init_action *a) a->respawn = 500; a->proc.cb = child_exit; - fork_script(a); + fork_worker(a); } static void askconsole(struct init_action *a) @@ -169,7 +169,8 @@ static void askconsole(struct init_action *a) a->respawn = 500; a->proc.cb = child_exit; - fork_script(a); + fork_worker(a); + err_out: regfree(&pat_cmdline); } @@ -177,18 +178,18 @@ err_out: static struct init_handler handlers[] = { { .name = "sysinit", - .cb = runscript, + .cb = runrc, }, { .name = "shutdown", - .cb = runscript, + .cb = runrc, }, { .name = "askfirst", .cb = askfirst, - .atomic = 1, + .multi = 1, }, { .name = "askconsole", .cb = askconsole, - .atomic = 1, + .multi = 1, } }; @@ -212,15 +213,12 @@ void procd_inittab_run(const char *handler) list_for_each_entry(a, &actions, list) if (!strcmp(a->handler->name, handler)) { - if (a->handler->atomic) { + if (a->handler->multi) { a->handler->cb(a); continue; } - if (pending || a->pending) - break; - a->pending = 1; - pending = a; a->handler->cb(a); + break; } } diff --git a/procd.h b/procd.h index 8c2892d..7f6c7cb 100644 --- a/procd.h +++ b/procd.h @@ -31,6 +31,10 @@ fprintf(stderr, "procd: %s(%d): " fmt, __func__, __LINE__, ## __VA_ARGS__); \ } while (0) +#define SYSLOG(p, fmt, ...) do { \ + syslog(p, fmt, ## __VA_ARGS__); \ + } while (0) + #define LOG(fmt, ...) do { \ syslog(LOG_INFO, fmt, ## __VA_ARGS__); \ fprintf(stderr, "procd: "fmt, ## __VA_ARGS__); \ diff --git a/rcS.c b/rcS.c new file mode 100644 index 0000000..58f195b --- /dev/null +++ b/rcS.c @@ -0,0 +1,143 @@ +/* + * runqueue-example.c + * + * Copyright (C) 2013 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "procd.h" +#include "rcS.h" + +static struct runqueue q; + +struct initd { + struct ustream_fd fd; + struct runqueue_process proc; + char *file; + char *param; +}; + +static void pipe_cb(struct ustream *s, int bytes) +{ + struct ustream_buf *buf = s->r.head; + char *newline, *str; + int len; + + do { + str = ustream_get_read_buf(s, NULL); + if (!str) + break; + newline = strchr(buf->data, '\n'); + if (!newline) + break; + *newline = 0; + len = newline + 1 - str; + SYSLOG(6, buf->data); + ustream_consume(s, len); + } while (1); +} + +static void q_initd_run(struct runqueue *q, struct runqueue_task *t) +{ + struct initd *s = container_of(t, struct initd, proc.task); + int pipefd[2]; + pid_t pid; + + DEBUG(1, "start %s %s \n", s->file, s->param); + if (pipe(pipefd) == -1) { + ERROR("Failed to create pipe\n"); + return; + } + + pid = fork(); + if (pid < 0) + return; + + if (pid) { + close(pipefd[1]); + s->fd.stream.string_data = true, + s->fd.stream.notify_read = pipe_cb, + runqueue_process_add(q, &s->proc, pid); + ustream_fd_init(&s->fd, pipefd[0]); + return; + } + close(pipefd[0]); + dup2(pipefd[1], STDOUT_FILENO); + dup2(pipefd[1], STDERR_FILENO); + + execlp(s->file, s->file, s->param, NULL); + exit(1); +} + +static void q_initd_complete(struct runqueue *q, struct runqueue_process *p, int ret) +{ + struct initd *s = container_of(p, struct initd, proc); + + DEBUG(1, "stop %s %s \n", s->file, s->param); + ustream_free(&s->fd.stream); + close(s->fd.fd.fd); + free(s); +} + +static void add_initd(char *file, char *param) +{ + static const struct runqueue_task_type initd_type = { + .run = q_initd_run, + .cancel = runqueue_process_cancel_cb, + .kill = runqueue_process_kill_cb, + }; + struct initd *s; + + s = calloc(1, sizeof(*s)); + s->proc.task.type = &initd_type; + s->proc.complete = q_initd_complete; + s->param = param; + s->file = file; + runqueue_task_add(&q, &s->proc.task, false); +} + +int rcS(char *pattern, char *param, void (*q_empty)(struct runqueue *)) +{ + char dir[16]; + glob_t gl; + int j; + + runqueue_init(&q); + q.empty_cb = q_empty; + q.max_running_tasks = 1; + + DEBUG(1, "running /etc/rc.d/%s %s\n", pattern, param); + snprintf(dir, sizeof(dir), "/etc/rc.d/%s*", pattern); + if (glob(dir, GLOB_NOESCAPE | GLOB_MARK, NULL, &gl)) { + printf("glob failed on %s\n", dir); + return -1; + } + + for (j = 0; j < gl.gl_pathc; j++) + add_initd(gl.gl_pathv[j], param); + + return 0; +} diff --git a/rcS.h b/rcS.h new file mode 100644 index 0000000..233b7aa --- /dev/null +++ b/rcS.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2013 Felix Fietkau + * Copyright (C) 2013 John Crispin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * This program 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. + */ + +#ifndef __PROCD_RCS_H +#define __PROCD_RCS_H + +#include + +extern int rcS(char *pattern, char *param, void (*q_empty)(struct runqueue *)); + +#endif diff --git a/syslog.c b/syslog.c index fa4a9b3..01b6e7e 100644 --- a/syslog.c +++ b/syslog.c @@ -274,7 +274,7 @@ void log_init(void) syslog_open(); klog_open(); - openlog("procd", LOG_PID, LOG_DAEMON); + openlog("sysinit", LOG_CONS, LOG_DAEMON); } void log_shutdown(void)