X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fprocd.git;a=blobdiff_plain;f=inittab.c;h=011d7a67e644841ed5ed7cb95e4f88c385b6cceb;hp=2d9a1e08d25faaddbfdd6297b560a85f2e3530ad;hb=961dc692aff7457f874bce61f8e766514edcf794;hpb=174777181850705df7c6dbe234bd7e93d352666a diff --git a/inittab.c b/inittab.c index 2d9a1e0..011d7a6 100644 --- a/inittab.c +++ b/inittab.c @@ -12,8 +12,10 @@ * GNU General Public License for more details. */ +#define _GNU_SOURCE #include #include +#include #include #include @@ -29,6 +31,10 @@ #include "procd.h" #include "rcS.h" +#ifndef O_PATH +#define O_PATH 010000000 +#endif + #define TAG_ID 0 #define TAG_RUNLVL 1 #define TAG_ACTION 2 @@ -37,7 +43,7 @@ #define MAX_ARGS 8 struct init_action; -const char *console; +char *console = NULL; struct init_handler { const char *name; @@ -64,10 +70,39 @@ static char *ask = "/sbin/askfirst"; static LIST_HEAD(actions); +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); @@ -106,27 +141,25 @@ static void runrc(struct init_action *a) ERROR("valid format is rcS \n"); return; } - rcS(a->argv[1], a->argv[2], rcdone); + + /* 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))) { + 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; @@ -135,29 +168,32 @@ static void askfirst(struct init_action *a) static void askconsole(struct init_action *a) { - struct stat s; char line[256], *tty, *split; int i; tty = get_cmdline_val("console", line, sizeof(line)); - split=strchr(tty, ','); - if (split != NULL) - split = '\0'; - - chdir("/dev"); - i = stat(tty, &s); - chdir("/"); - if (i) { - DEBUG(4, "skipping %s\n", tty); - return; + if (tty != NULL) { + split = strchr(tty, ','); + if (split != NULL) + *split = '\0'; + + if (!dev_exist(tty)) { + DEBUG(4, "skipping %s\n", tty); + return; + } + + 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; @@ -192,6 +228,14 @@ static struct init_handler handlers[] = { .name = "respawn", .cb = rcrespawn, .multi = 1, + }, { + .name = "askconsolelate", + .cb = askconsole, + .multi = 1, + }, { + .name = "respawnlate", + .cb = rcrespawn, + .multi = 1, } };