X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fprocd.git;a=blobdiff_plain;f=inittab.c;h=21172f7c065cdc9474ca037398757e9b78b026a8;hp=32be11fc194586bf06f5fd72d4bc5b1cb92314f3;hb=8d720b2c2e569885c6e1e7eab68d36f31818ed84;hpb=271e7eca16ed6074f66026c7bd9383c060098af4;ds=sidebyside diff --git a/inittab.c b/inittab.c index 32be11f..21172f7 100644 --- a/inittab.c +++ b/inittab.c @@ -12,19 +12,28 @@ * GNU General Public License for more details. */ +#define _GNU_SOURCE #include #include +#include #include #include #include #include #include +#include #include #include +#include "utils/utils.h" #include "procd.h" +#include "rcS.h" + +#ifndef O_PATH +#define O_PATH 010000000 +#endif #define TAG_ID 0 #define TAG_RUNLVL 1 @@ -34,12 +43,12 @@ #define MAX_ARGS 8 struct init_action; -const char *console; +char *console = NULL; struct init_handler { const char *name; void (*cb) (struct init_action *a); - int atomic; + int multi; }; struct init_action { @@ -52,7 +61,6 @@ struct init_action { struct init_handler *handler; struct uloop_process proc; - int pending; int respawn; struct uloop_timeout tout; }; @@ -60,21 +68,48 @@ 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 int dev_exist(const char *dev) +{ + int dfd, fd; + + dfd = open("/dev", O_PATH|O_DIRECTORY); + + if (dfd < 0) + return 0; + + fd = openat(dfd, dev, O_RDONLY); + close(dfd); + + if (fd < 0) + return 0; + + close(fd); + return 1; +} + +static void fork_worker(struct init_action *a) { + pid_t p; + a->proc.pid = fork(); if (!a->proc.pid) { + p = setsid(); + + if (patch_stdio(a->id)) + ERROR("Failed to setup i/o redirection\n"); + + ioctl(STDIN_FILENO, TIOCSCTTY, 1); + tcsetpgrp(STDIN_FILENO, p); + execvp(a->argv[0], a->argv); ERROR("Failed to execute %s\n", a->argv[0]); exit(-1); } if (a->proc.pid > 0) { - DEBUG(2, "Launched new %s action, pid=%d\n", + DEBUG(4, "Launched new %s action, pid=%d\n", a->handler->name, (int) a->proc.pid); uloop_process_add(&a->proc); @@ -85,110 +120,122 @@ 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(); - } + DEBUG(4, "pid:%d\n", proc->pid); + 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; + } + + /* proceed even if no init or shutdown scripts run */ + if (rcS(a->argv[1], a->argv[2], rcdone)) + rcdone(NULL); } static void askfirst(struct init_action *a) { - struct stat s; int i; - chdir("/dev"); - i = stat(a->id, &s); - chdir("/"); - if (i || (console && !strcmp(console, a->id))) { - DEBUG(2, "Skipping %s\n", a->id); + if (!dev_exist(a->id) || (console && !strcmp(console, a->id))) { + DEBUG(4, "Skipping %s\n", a->id); return; } a->tout.cb = respawn; - for (i = MAX_ARGS - 2; i >= 2; i--) - a->argv[i] = a->argv[i - 2]; + for (i = MAX_ARGS - 1; i >= 1; i--) + a->argv[i] = a->argv[i - 1]; a->argv[0] = ask; - a->argv[1] = a->id; a->respawn = 500; a->proc.cb = child_exit; - fork_script(a); + fork_worker(a); } static void askconsole(struct init_action *a) { - struct stat s; - char line[256], *tty; - int i, r, fd = open("/proc/cmdline", O_RDONLY); - regex_t pat_cmdline; - regmatch_t matches[2]; + char line[256], *tty, *split; + int i; - if (!fd) - return; + tty = get_cmdline_val("console", line, sizeof(line)); + if (tty != NULL) { + split = strchr(tty, ','); + if (split != NULL) + *split = '\0'; - r = read(fd, line, sizeof(line) - 1); - line[r] = '\0'; - close(fd); + if (!dev_exist(tty)) { + DEBUG(4, "skipping %s\n", tty); + return; + } - regcomp(&pat_cmdline, "console=([a-zA-Z0-9]*)", REG_EXTENDED); - if (regexec(&pat_cmdline, line, 2, matches, 0)) - goto err_out; - line[matches[1].rm_eo] = '\0'; - tty = &line[matches[1].rm_so]; - - chdir("/dev"); - i = stat(tty, &s); - chdir("/"); - if (i) { - DEBUG(2, "skipping %s\n", tty); - goto err_out; + console = strdup(tty); + a->id = strdup(tty); + } + else { + console = NULL; + a->id = NULL; } - console = strdup(tty); a->tout.cb = respawn; - for (i = MAX_ARGS - 2; i >= 2; i--) - a->argv[i] = a->argv[i - 2]; + for (i = MAX_ARGS - 1; i >= 1; i--) + a->argv[i] = a->argv[i - 1]; a->argv[0] = ask; - a->argv[1] = strdup(tty); a->respawn = 500; a->proc.cb = child_exit; - fork_script(a); -err_out: - regfree(&pat_cmdline); + fork_worker(a); +} + +static void rcrespawn(struct init_action *a) +{ + a->tout.cb = respawn; + a->respawn = 500; + + a->proc.cb = child_exit; + fork_worker(a); } 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, + }, { + .name = "respawn", + .cb = rcrespawn, + .multi = 1, + }, { + .name = "askconsolelate", + .cb = askconsole, + .multi = 1, + }, { + .name = "respawnlate", + .cb = rcrespawn, + .multi = 1, } }; @@ -212,15 +259,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; } } @@ -238,7 +282,7 @@ void procd_inittab(void) return; } - regcomp(&pat_inittab, "([a-zA-Z0-9]*):([a-zA-Z0-9]*):([a-zA-Z0-9]*):([a-zA-Z0-9/[.-.]. ]*)", REG_EXTENDED); + regcomp(&pat_inittab, "([a-zA-Z0-9]*):([a-zA-Z0-9]*):([a-zA-Z0-9]*):(.*)", REG_EXTENDED); line = malloc(LINE_LEN); a = malloc(sizeof(struct init_action)); memset(a, 0, sizeof(struct init_action)); @@ -247,6 +291,11 @@ void procd_inittab(void) char *tags[TAG_PROCESS + 1]; char *tok; int i; + int len = strlen(line); + + while (isspace(line[len - 1])) + len--; + line[len] = 0; if (*line == '#') continue; @@ -254,7 +303,7 @@ void procd_inittab(void) if (regexec(&pat_inittab, line, 5, matches, 0)) continue; - DEBUG(2, "Parsing inittab - %s", line); + DEBUG(4, "Parsing inittab - %s\n", line); for (i = TAG_ID; i <= TAG_PROCESS; i++) { line[matches[i].rm_eo] = '\0'; @@ -262,7 +311,7 @@ void procd_inittab(void) }; tok = strtok(tags[TAG_PROCESS], " "); - for (i = 0; i < (MAX_ARGS - i - 1) && tok; i++) { + for (i = 0; i < (MAX_ARGS - 1) && tok; i++) { a->argv[i] = tok; tok = strtok(NULL, " "); }