1 /* 2 * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org> 3 * Copyright (C) 2013 John Crispin <blogic@openwrt.org> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU Lesser General Public License version 2.1 7 * as published by the Free Software Foundation 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 */ 14 #define _GNU_SOURCE 15 16 #include <sys/stat.h> 17 #include <sys/types.h> 18 #include <sys/mount.h> 19 #include <fcntl.h> 20 21 #include <libubox/uloop.h> 22 #include <libubox/utils.h> 23 #include <libubus.h> 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <unistd.h> 28 29 #include "init.h" 30 #include "../watchdog.h" 31 #include "../sysupgrade.h" 32 33 static struct uloop_process preinit_proc; 34 static struct uloop_process plugd_proc; 35 36 static void 37 check_dbglvl(void) 38 { 39 FILE *fp = fopen("/tmp/debug_level", "r"); 40 int lvl = 0; 41 42 if (!fp) 43 return; 44 if (fscanf(fp, "%d", &lvl) == EOF) 45 ERROR("failed to read debug level: %m\n"); 46 fclose(fp); 47 unlink("/tmp/debug_level"); 48 49 if (lvl > 0 && lvl < 5) 50 debug = lvl; 51 } 52 53 static void 54 check_sysupgrade(void) 55 { 56 char *prefix = NULL, *path = NULL, *command = NULL; 57 size_t n; 58 59 if (chdir("/")) 60 return; 61 62 FILE *sysupgrade = fopen("/tmp/sysupgrade", "r"); 63 if (!sysupgrade) 64 return; 65 66 n = 0; 67 if (getdelim(&prefix, &n, 0, sysupgrade) < 0) 68 goto fail; 69 n = 0; 70 if (getdelim(&path, &n, 0, sysupgrade) < 0) 71 goto fail; 72 n = 0; 73 if (getdelim(&command, &n, 0, sysupgrade) < 0) 74 goto fail; 75 76 fclose(sysupgrade); 77 78 sysupgrade_exec_upgraded(prefix, path, NULL, command, NULL); 79 80 while (true) 81 sleep(1); 82 83 fail: 84 fclose(sysupgrade); 85 free(prefix); 86 free(path); 87 free(command); 88 } 89 90 static void 91 spawn_procd(struct uloop_process *proc, int ret) 92 { 93 char *wdt_fd = watchdog_fd(); 94 char *argv[] = { "/sbin/procd", NULL}; 95 char dbg[2]; 96 97 if (plugd_proc.pid > 0) 98 kill(plugd_proc.pid, SIGKILL); 99 100 unsetenv("PREINIT"); 101 unlink("/tmp/.preinit"); 102 103 check_sysupgrade(); 104 105 DEBUG(2, "Exec to real procd now\n"); 106 if (wdt_fd) 107 setenv("WDTFD", wdt_fd, 1); 108 check_dbglvl(); 109 if (debug > 0) { 110 snprintf(dbg, 2, "%d", debug); 111 setenv("DBGLVL", dbg, 1); 112 } 113 114 execvp(argv[0], argv); 115 } 116 117 static void 118 plugd_proc_cb(struct uloop_process *proc, int ret) 119 { 120 proc->pid = 0; 121 } 122 123 void 124 preinit(void) 125 { 126 char *init[] = { "/bin/sh", "/etc/preinit", NULL }; 127 char *plug[] = { "/sbin/procd", "-h", "/etc/hotplug-preinit.json", NULL }; 128 int fd; 129 130 LOG("- preinit -\n"); 131 132 plugd_proc.cb = plugd_proc_cb; 133 plugd_proc.pid = fork(); 134 if (!plugd_proc.pid) { 135 execvp(plug[0], plug); 136 ERROR("Failed to start plugd: %m\n"); 137 exit(EXIT_FAILURE); 138 } 139 if (plugd_proc.pid <= 0) { 140 ERROR("Failed to start new plugd instance: %m\n"); 141 return; 142 } 143 uloop_process_add(&plugd_proc); 144 145 setenv("PREINIT", "1", 1); 146 147 fd = creat("/tmp/.preinit", 0600); 148 149 if (fd < 0) 150 ERROR("Failed to create sentinel file: %m\n"); 151 else 152 close(fd); 153 154 preinit_proc.cb = spawn_procd; 155 preinit_proc.pid = fork(); 156 if (!preinit_proc.pid) { 157 execvp(init[0], init); 158 ERROR("Failed to start preinit: %m\n"); 159 exit(EXIT_FAILURE); 160 } 161 if (preinit_proc.pid <= 0) { 162 ERROR("Failed to start new preinit instance: %m\n"); 163 return; 164 } 165 uloop_process_add(&preinit_proc); 166 167 DEBUG(4, "Launched preinit instance, pid=%d\n", (int) preinit_proc.pid); 168 } 169
This page was automatically generated by LXR 0.3.1. • OpenWrt