add a rcS helper
authorJohn Crispin <blogic@openwrt.org>
Thu, 9 May 2013 18:14:27 +0000 (20:14 +0200)
committerJohn Crispin <blogic@openwrt.org>
Thu, 9 May 2013 20:35:17 +0000 (22:35 +0200)
Signed-off-by: John Crispin <blogic@openwrt.org>
CMakeLists.txt
inittab.c
procd.h
rcS.c [new file with mode: 0644]
rcS.h [new file with mode: 0644]
syslog.c

index 62e309a..0d3a989 100644 (file)
@@ -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)
index 32be11f..2ed1395 100644 (file)
--- a/inittab.c
+++ b/inittab.c
@@ -25,6 +25,7 @@
 #include <libubox/list.h>
 
 #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 <S|K> <param>\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 (file)
--- a/procd.h
+++ b/procd.h
                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 (file)
index 0000000..58f195b
--- /dev/null
+++ b/rcS.c
@@ -0,0 +1,143 @@
+/*
+ * runqueue-example.c
+ *
+ * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
+ *
+ * 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 <libubox/uloop.h>
+#include <libubox/runqueue.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <glob.h>
+
+#include <libubox/ustream.h>
+
+#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 (file)
index 0000000..233b7aa
--- /dev/null
+++ b/rcS.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ *
+ * 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 <libubox/runqueue.h>
+
+extern int rcS(char *pattern, char *param, void (*q_empty)(struct runqueue *));
+
+#endif
index fa4a9b3..01b6e7e 100644 (file)
--- 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)