X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fprocd.git;a=blobdiff_plain;f=initd%2Fpreinit.c;h=fbb36df9e5adb2e668f0b033bbc2fda0f1e20ee0;hp=eeadbeb3ae8cc36691e216926e101d5a00ccf615;hb=c3faabeb635ce515b831afb2e87d9bb241991907;hpb=916f95cb58604038695347ee41a430d8ca1f0556 diff --git a/initd/preinit.c b/initd/preinit.c index eeadbeb..fbb36df 100644 --- a/initd/preinit.c +++ b/initd/preinit.c @@ -11,10 +11,12 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ +#define _GNU_SOURCE #include #include #include +#include #include #include @@ -26,29 +28,90 @@ #include "init.h" #include "../watchdog.h" +#include "../sysupgrade.h" static struct uloop_process preinit_proc; static struct uloop_process plugd_proc; static void +check_dbglvl(void) +{ + FILE *fp = fopen("/tmp/debug_level", "r"); + int lvl = 0; + + if (!fp) + return; + if (fscanf(fp, "%d", &lvl) == EOF) + ERROR("failed to read debug level: %m\n"); + fclose(fp); + unlink("/tmp/debug_level"); + + if (lvl > 0 && lvl < 5) + debug = lvl; +} + +static void +check_sysupgrade(void) +{ + char *prefix = NULL, *path = NULL, *command = NULL; + size_t n; + + if (chdir("/")) + return; + + FILE *sysupgrade = fopen("/tmp/sysupgrade", "r"); + if (!sysupgrade) + return; + + n = 0; + if (getdelim(&prefix, &n, 0, sysupgrade) < 0) + goto fail; + n = 0; + if (getdelim(&path, &n, 0, sysupgrade) < 0) + goto fail; + n = 0; + if (getdelim(&command, &n, 0, sysupgrade) < 0) + goto fail; + + fclose(sysupgrade); + + sysupgrade_exec_upgraded(prefix, path, command); + + while (true) + sleep(1); + +fail: + fclose(sysupgrade); + free(prefix); + free(path); + free(command); +} + +static void spawn_procd(struct uloop_process *proc, int ret) { char *wdt_fd = watchdog_fd(); - char *argv[] = { "/sbin/procd", NULL }; - struct stat s; + char *argv[] = { "/sbin/procd", NULL}; + char dbg[2]; if (plugd_proc.pid > 0) kill(plugd_proc.pid, SIGKILL); - if (!stat("/tmp/sysupgrade", &s)) - while (true) - sleep(1); - unsetenv("INITRAMFS"); unsetenv("PREINIT"); + unlink("/tmp/.preinit"); + + check_sysupgrade(); + DEBUG(2, "Exec to real procd now\n"); if (wdt_fd) setenv("WDTFD", wdt_fd, 1); + check_dbglvl(); + if (debug > 0) { + snprintf(dbg, 2, "%d", debug); + setenv("DBGLVL", dbg, 1); + } + execvp(argv[0], argv); } @@ -63,6 +126,7 @@ preinit(void) { char *init[] = { "/bin/sh", "/etc/preinit", NULL }; char *plug[] = { "/sbin/procd", "-h", "/etc/hotplug-preinit.json", NULL }; + int fd; LOG("- preinit -\n"); @@ -70,26 +134,33 @@ preinit(void) plugd_proc.pid = fork(); if (!plugd_proc.pid) { execvp(plug[0], plug); - ERROR("Failed to start plugd\n"); + ERROR("Failed to start plugd: %m\n"); exit(-1); } if (plugd_proc.pid <= 0) { - ERROR("Failed to start new plugd instance\n"); + ERROR("Failed to start new plugd instance: %m\n"); return; } uloop_process_add(&plugd_proc); setenv("PREINIT", "1", 1); + fd = creat("/tmp/.preinit", 0600); + + if (fd < 0) + ERROR("Failed to create sentinel file: %m\n"); + else + close(fd); + preinit_proc.cb = spawn_procd; preinit_proc.pid = fork(); if (!preinit_proc.pid) { execvp(init[0], init); - ERROR("Failed to start preinit\n"); + ERROR("Failed to start preinit: %m\n"); exit(-1); } if (preinit_proc.pid <= 0) { - ERROR("Failed to start new preinit instance\n"); + ERROR("Failed to start new preinit instance: %m\n"); return; } uloop_process_add(&preinit_proc);