Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/init/init.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/init/init.c
r821 r1770 10 10 */ 11 11 12 #include "busybox.h" 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <errno.h> 12 #include "libbb.h" 16 13 #include <paths.h> 17 #include <signal.h> 18 #include <stdarg.h> 19 #include <string.h> 20 #include <termios.h> 21 #include <unistd.h> 22 #include <limits.h> 23 #include <fcntl.h> 24 #include <sys/ioctl.h> 25 #include <sys/types.h> 26 #include <sys/wait.h> 14 //#include <signal.h> 15 //#include <sys/ioctl.h> 16 //#include <sys/wait.h> 27 17 #include <sys/reboot.h> 28 18 29 #include "init_shared.h" 30 31 32 #ifdef CONFIG_SYSLOGD 19 #if ENABLE_FEATURE_INIT_SYSLOG 33 20 # include <sys/syslog.h> 34 21 #endif 35 22 36 37 #ifdef CONFIG_SELINUX38 # include <selinux/selinux.h>39 #endif /* CONFIG_SELINUX */40 41 42 23 #define INIT_BUFFS_SIZE 256 43 44 /* From <linux/vt.h> */ 45 struct vt_stat { 46 unsigned short v_active; /* active vt */ 47 unsigned short v_signal; /* signal to send */ 48 unsigned short v_state; /* vt bitmask */ 24 #define CONSOLE_NAME_SIZE 32 25 #define MAXENV 16 /* Number of env. vars */ 26 27 #if ENABLE_FEATURE_INIT_COREDUMPS 28 /* 29 * When a file named CORE_ENABLE_FLAG_FILE exists, setrlimit is called 30 * before processes are spawned to set core file size as unlimited. 31 * This is for debugging only. Don't use this is production, unless 32 * you want core dumps lying about.... 33 */ 34 #define CORE_ENABLE_FLAG_FILE "/.init_enable_core" 35 #include <sys/resource.h> 36 #endif 37 38 #define INITTAB "/etc/inittab" /* inittab file location */ 39 #ifndef INIT_SCRIPT 40 #define INIT_SCRIPT "/etc/init.d/rcS" /* Default sysinit script. */ 41 #endif 42 43 /* Allowed init action types */ 44 #define SYSINIT 0x001 45 #define RESPAWN 0x002 46 #define ASKFIRST 0x004 47 #define WAIT 0x008 48 #define ONCE 0x010 49 #define CTRLALTDEL 0x020 50 #define SHUTDOWN 0x040 51 #define RESTART 0x080 52 53 /* A mapping between "inittab" action name strings and action type codes. */ 54 struct init_action_type { 55 const char *name; 56 int action; 49 57 }; 50 enum { VT_GETSTATE = 0x5603 }; /* get global vt state info */ 58 59 static const struct init_action_type actions[] = { 60 {"sysinit", SYSINIT}, 61 {"respawn", RESPAWN}, 62 {"askfirst", ASKFIRST}, 63 {"wait", WAIT}, 64 {"once", ONCE}, 65 {"ctrlaltdel", CTRLALTDEL}, 66 {"shutdown", SHUTDOWN}, 67 {"restart", RESTART}, 68 {0, 0} 69 }; 70 71 /* Set up a linked list of init_actions, to be read from inittab */ 72 struct init_action { 73 struct init_action *next; 74 int action; 75 pid_t pid; 76 char command[INIT_BUFFS_SIZE]; 77 char terminal[CONSOLE_NAME_SIZE]; 78 }; 79 80 /* Static variables */ 81 static struct init_action *init_action_list = NULL; 82 83 #if !ENABLE_FEATURE_INIT_SYSLOG 84 static const char *log_console = VC_5; 85 #endif 86 #if !ENABLE_DEBUG_INIT 87 static sig_atomic_t got_cont = 0; 88 #endif 89 90 enum { 91 L_LOG = 0x1, 92 L_CONSOLE = 0x2, 93 94 #if ENABLE_FEATURE_EXTRA_QUIET 95 MAYBE_CONSOLE = 0x0, 96 #else 97 MAYBE_CONSOLE = L_CONSOLE, 98 #endif 99 100 #ifndef RB_HALT_SYSTEM 101 RB_HALT_SYSTEM = 0xcdef0123, /* FIXME: this overflows enum */ 102 RB_ENABLE_CAD = 0x89abcdef, 103 RB_DISABLE_CAD = 0, 104 RB_POWER_OFF = 0x4321fedc, 105 RB_AUTOBOOT = 0x01234567, 106 #endif 107 }; 108 109 static const char *const environment[] = { 110 "HOME=/", 111 bb_PATH_root_path, 112 "SHELL=/bin/sh", 113 "USER=root", 114 NULL 115 }; 116 117 /* Function prototypes */ 118 static void delete_init_action(struct init_action *a); 119 static int waitfor(const struct init_action *a, pid_t pid); 120 #if !ENABLE_DEBUG_INIT 121 static void shutdown_signal(int sig); 122 #endif 123 124 #if !ENABLE_DEBUG_INIT 125 static void loop_forever(void) 126 { 127 while (1) 128 sleep(1); 129 } 130 #endif 131 132 /* Print a message to the specified device. 133 * Device may be bitwise-or'd from L_LOG | L_CONSOLE */ 134 #if ENABLE_DEBUG_INIT 135 #define messageD message 136 #else 137 #define messageD(...) do {} while (0) 138 #endif 139 static void message(int device, const char *fmt, ...) 140 __attribute__ ((format(printf, 2, 3))); 141 static void message(int device, const char *fmt, ...) 142 { 143 #if !ENABLE_FEATURE_INIT_SYSLOG 144 static int log_fd = -1; 145 #endif 146 147 va_list arguments; 148 int l; 149 char msg[128]; 150 151 msg[0] = '\r'; 152 va_start(arguments, fmt); 153 vsnprintf(msg + 1, sizeof(msg) - 2, fmt, arguments); 154 va_end(arguments); 155 msg[sizeof(msg) - 2] = '\0'; 156 l = strlen(msg); 157 158 #if ENABLE_FEATURE_INIT_SYSLOG 159 /* Log the message to syslogd */ 160 if (device & L_LOG) { 161 /* don't out "\r" */ 162 openlog(applet_name, 0, LOG_DAEMON); 163 syslog(LOG_INFO, "init: %s", msg + 1); 164 closelog(); 165 } 166 msg[l++] = '\n'; 167 msg[l] = '\0'; 168 #else 169 msg[l++] = '\n'; 170 msg[l] = '\0'; 171 /* Take full control of the log tty, and never close it. 172 * It's mine, all mine! Muhahahaha! */ 173 if (log_fd < 0) { 174 if (!log_console) { 175 log_fd = 2; 176 } else { 177 log_fd = device_open(log_console, O_WRONLY | O_NONBLOCK | O_NOCTTY); 178 if (log_fd < 0) { 179 bb_error_msg("can't log to %s", log_console); 180 device = L_CONSOLE; 181 } else { 182 fcntl(log_fd, F_SETFD, FD_CLOEXEC); 183 } 184 } 185 } 186 if (device & L_LOG) { 187 full_write(log_fd, msg, l); 188 if (log_fd == 2) 189 return; /* don't print dup messages */ 190 } 191 #endif 192 193 if (device & L_CONSOLE) { 194 /* Send console messages to console so people will see them. */ 195 full_write(2, msg, l); 196 } 197 } 198 199 /* Set terminal settings to reasonable defaults */ 200 static void set_sane_term(void) 201 { 202 struct termios tty; 203 204 tcgetattr(STDIN_FILENO, &tty); 205 206 /* set control chars */ 207 tty.c_cc[VINTR] = 3; /* C-c */ 208 tty.c_cc[VQUIT] = 28; /* C-\ */ 209 tty.c_cc[VERASE] = 127; /* C-? */ 210 tty.c_cc[VKILL] = 21; /* C-u */ 211 tty.c_cc[VEOF] = 4; /* C-d */ 212 tty.c_cc[VSTART] = 17; /* C-q */ 213 tty.c_cc[VSTOP] = 19; /* C-s */ 214 tty.c_cc[VSUSP] = 26; /* C-z */ 215 216 /* use line dicipline 0 */ 217 tty.c_line = 0; 218 219 /* Make it be sane */ 220 tty.c_cflag &= CBAUD | CBAUDEX | CSIZE | CSTOPB | PARENB | PARODD; 221 tty.c_cflag |= CREAD | HUPCL | CLOCAL; 222 223 /* input modes */ 224 tty.c_iflag = ICRNL | IXON | IXOFF; 225 226 /* output modes */ 227 tty.c_oflag = OPOST | ONLCR; 228 229 /* local modes */ 230 tty.c_lflag = 231 ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN; 232 233 tcsetattr(STDIN_FILENO, TCSANOW, &tty); 234 } 51 235 52 236 /* From <linux/serial.h> */ … … 71 255 unsigned long iomap_base; /* cookie passed into ioremap */ 72 256 int reserved[1]; 257 /* Paranoia (imagine 64bit kernel overwriting 32bit userspace stack) */ 258 uint32_t bbox_reserved[16]; 73 259 }; 74 75 76 #ifndef _PATH_STDPATH77 #define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin"78 #endif79 80 #if defined CONFIG_FEATURE_INIT_COREDUMPS81 /*82 * When a file named CORE_ENABLE_FLAG_FILE exists, setrlimit is called83 * before processes are spawned to set core file size as unlimited.84 * This is for debugging only. Don't use this is production, unless85 * you want core dumps lying about....86 */87 #define CORE_ENABLE_FLAG_FILE "/.init_enable_core"88 #include <sys/resource.h>89 #endif90 91 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))92 93 #define INITTAB "/etc/inittab" /* inittab file location */94 #ifndef INIT_SCRIPT95 #define INIT_SCRIPT "/etc/init.d/rcS" /* Default sysinit script. */96 #endif97 98 #define MAXENV 16 /* Number of env. vars */99 100 #define CONSOLE_BUFF_SIZE 32101 102 /* Allowed init action types */103 #define SYSINIT 0x001104 #define RESPAWN 0x002105 #define ASKFIRST 0x004106 #define WAIT 0x008107 #define ONCE 0x010108 #define CTRLALTDEL 0x020109 #define SHUTDOWN 0x040110 #define RESTART 0x080111 112 /* A mapping between "inittab" action name strings and action type codes. */113 struct init_action_type {114 const char *name;115 int action;116 };117 118 static const struct init_action_type actions[] = {119 {"sysinit", SYSINIT},120 {"respawn", RESPAWN},121 {"askfirst", ASKFIRST},122 {"wait", WAIT},123 {"once", ONCE},124 {"ctrlaltdel", CTRLALTDEL},125 {"shutdown", SHUTDOWN},126 {"restart", RESTART},127 {0, 0}128 };129 130 /* Set up a linked list of init_actions, to be read from inittab */131 struct init_action {132 pid_t pid;133 char command[INIT_BUFFS_SIZE];134 char terminal[CONSOLE_BUFF_SIZE];135 struct init_action *next;136 int action;137 };138 139 /* Static variables */140 static struct init_action *init_action_list = NULL;141 static char console[CONSOLE_BUFF_SIZE] = CONSOLE_DEV;142 143 #ifndef CONFIG_SYSLOGD144 static char *log_console = VC_5;145 #endif146 #if !ENABLE_DEBUG_INIT147 static sig_atomic_t got_cont = 0;148 #endif149 150 enum {151 LOG = 0x1,152 CONSOLE = 0x2,153 154 #if defined CONFIG_FEATURE_EXTRA_QUIET155 MAYBE_CONSOLE = 0x0,156 #else157 MAYBE_CONSOLE = CONSOLE,158 #endif159 160 #ifndef RB_HALT_SYSTEM161 RB_HALT_SYSTEM = 0xcdef0123, /* FIXME: this overflows enum */162 RB_ENABLE_CAD = 0x89abcdef,163 RB_DISABLE_CAD = 0,164 RB_POWER_OFF = 0x4321fedc,165 RB_AUTOBOOT = 0x01234567,166 #endif167 };168 169 static const char * const environment[] = {170 "HOME=/",171 "PATH=" _PATH_STDPATH,172 "SHELL=/bin/sh",173 "USER=root",174 NULL175 };176 177 /* Function prototypes */178 static void delete_init_action(struct init_action *a);179 static int waitfor(const struct init_action *a, pid_t pid);180 #if !ENABLE_DEBUG_INIT181 static void shutdown_signal(int sig);182 #endif183 184 static void loop_forever(void)185 {186 while (1)187 sleep(1);188 }189 190 /* Print a message to the specified device.191 * Device may be bitwise-or'd from LOG | CONSOLE */192 #if ENABLE_DEBUG_INIT193 #define messageD message194 #else195 static inline void messageD(int ATTRIBUTE_UNUSED device,196 const char ATTRIBUTE_UNUSED *fmt, ...)197 {198 }199 #endif200 static void message(int device, const char *fmt, ...)201 __attribute__ ((format(printf, 2, 3)));202 static void message(int device, const char *fmt, ...)203 {204 va_list arguments;205 int l;206 RESERVE_CONFIG_BUFFER(msg, 1024);207 #ifndef CONFIG_SYSLOGD208 static int log_fd = -1;209 #endif210 211 msg[0] = '\r';212 va_start(arguments, fmt);213 l = vsnprintf(msg + 1, 1024 - 2, fmt, arguments) + 1;214 va_end(arguments);215 216 #ifdef CONFIG_SYSLOGD217 /* Log the message to syslogd */218 if (device & LOG) {219 /* don`t out "\r\n" */220 openlog(bb_applet_name, 0, LOG_DAEMON);221 syslog(LOG_INFO, "%s", msg + 1);222 closelog();223 }224 225 msg[l++] = '\n';226 msg[l] = 0;227 #else228 229 msg[l++] = '\n';230 msg[l] = 0;231 /* Take full control of the log tty, and never close it.232 * It's mine, all mine! Muhahahaha! */233 if (log_fd < 0) {234 if ((log_fd = device_open(log_console, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {235 log_fd = -2;236 bb_error_msg("Bummer, can't write to log on %s!", log_console);237 device = CONSOLE;238 } else {239 fcntl(log_fd, F_SETFD, FD_CLOEXEC);240 }241 }242 if ((device & LOG) && (log_fd >= 0)) {243 bb_full_write(log_fd, msg, l);244 }245 #endif246 247 if (device & CONSOLE) {248 int fd = device_open(CONSOLE_DEV,249 O_WRONLY | O_NOCTTY | O_NONBLOCK);250 /* Always send console messages to /dev/console so people will see them. */251 if (fd >= 0) {252 bb_full_write(fd, msg, l);253 close(fd);254 #if ENABLE_DEBUG_INIT255 /* all descriptors may be closed */256 } else {257 bb_error_msg("Bummer, can't print: ");258 va_start(arguments, fmt);259 vfprintf(stderr, fmt, arguments);260 va_end(arguments);261 #endif262 }263 }264 RELEASE_CONFIG_BUFFER(msg);265 }266 267 /* Set terminal settings to reasonable defaults */268 static void set_term(void)269 {270 struct termios tty;271 272 tcgetattr(STDIN_FILENO, &tty);273 274 /* set control chars */275 tty.c_cc[VINTR] = 3; /* C-c */276 tty.c_cc[VQUIT] = 28; /* C-\ */277 tty.c_cc[VERASE] = 127; /* C-? */278 tty.c_cc[VKILL] = 21; /* C-u */279 tty.c_cc[VEOF] = 4; /* C-d */280 tty.c_cc[VSTART] = 17; /* C-q */281 tty.c_cc[VSTOP] = 19; /* C-s */282 tty.c_cc[VSUSP] = 26; /* C-z */283 284 /* use line dicipline 0 */285 tty.c_line = 0;286 287 /* Make it be sane */288 tty.c_cflag &= CBAUD | CBAUDEX | CSIZE | CSTOPB | PARENB | PARODD;289 tty.c_cflag |= CREAD | HUPCL | CLOCAL;290 291 292 /* input modes */293 tty.c_iflag = ICRNL | IXON | IXOFF;294 295 /* output modes */296 tty.c_oflag = OPOST | ONLCR;297 298 /* local modes */299 tty.c_lflag =300 ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;301 302 tcsetattr(STDIN_FILENO, TCSANOW, &tty);303 }304 305 260 static void console_init(void) 306 261 { 307 int fd;308 int tried = 0;309 struct vt_stat vt;310 262 struct serial_struct sr; 311 263 char *s; 312 264 313 if ((s = getenv("CONSOLE")) != NULL || (s = getenv("console")) != NULL) {314 safe_strncpy(console, s, sizeof(console));315 #if 0 /* #cpu(sparc) */ 316 /* sparc kernel supports console=tty[ab] parameter which is also317 * passed to init, so catch it here */318 /* remap tty[ab] to /dev/ttyS[01] */319 if (strcmp(s, "ttya") == 0)320 safe_strncpy(console, SC_0, sizeof(console));321 else if (strcmp(s, "ttyb") == 0)322 safe_strncpy(console, SC_1, sizeof(console));323 #endif 265 s = getenv("CONSOLE"); 266 if (!s) s = getenv("console"); 267 if (s) { 268 int fd = open(s, O_RDWR | O_NONBLOCK | O_NOCTTY); 269 if (fd >= 0) { 270 dup2(fd, 0); 271 dup2(fd, 1); 272 dup2(fd, 2); 273 while (fd > 2) close(fd--); 274 } 275 messageD(L_LOG, "console='%s'", s); 324 276 } else { 325 /* 2.2 kernels: identify the real console backend and try to use it */ 326 if (ioctl(0, TIOCGSERIAL, &sr) == 0) { 327 /* this is a serial console */ 328 snprintf(console, sizeof(console) - 1, SC_FORMAT, sr.line); 329 } else if (ioctl(0, VT_GETSTATE, &vt) == 0) { 330 /* this is linux virtual tty */ 331 snprintf(console, sizeof(console) - 1, VC_FORMAT, vt.v_active); 277 /* Make sure fd 0,1,2 are not closed */ 278 bb_sanitize_stdio(); 279 } 280 281 s = getenv("TERM"); 282 if (ioctl(0, TIOCGSERIAL, &sr) == 0) { 283 /* Force the TERM setting to vt102 for serial console -- 284 * if TERM is set to linux (the default) */ 285 if (!s || strcmp(s, "linux") == 0) 286 putenv((char*)"TERM=vt102"); 287 #if !ENABLE_FEATURE_INIT_SYSLOG 288 log_console = NULL; 289 #endif 290 } else if (!s) 291 putenv((char*)"TERM=linux"); 292 } 293 294 static void fixup_argv(char **argv) 295 { 296 /* Fix up argv[0] to be certain we claim to be init */ 297 strncpy(argv[0], "init", strlen(argv[0])); 298 299 /* Wipe argv[1]-argv[N] so they don't clutter the ps listing */ 300 while (*++argv) 301 memset(*argv, 0, strlen(*argv)); 302 } 303 304 /* Open the new terminal device */ 305 static void open_stdio_to_tty(const char* tty_name, int fail) 306 { 307 /* empty tty_name means "use init's tty", else... */ 308 if (tty_name[0]) { 309 int fd = device_open(tty_name, O_RDWR); 310 if (fd < 0) { 311 message(L_LOG | L_CONSOLE, "Can't open %s: %s", 312 tty_name, strerror(errno)); 313 if (fail) 314 _exit(1); 315 #if !ENABLE_DEBUG_INIT 316 shutdown_signal(SIGUSR1); 317 #else 318 _exit(2); 319 #endif 332 320 } else { 333 safe_strncpy(console, CONSOLE_DEV, sizeof(console)); 334 tried++; 335 } 336 } 337 338 while ((fd = open(console, O_RDONLY | O_NONBLOCK)) < 0 && tried < 2) { 339 /* Can't open selected console -- try 340 logical system console and VT_MASTER */ 341 safe_strncpy(console, (tried == 0 ? CONSOLE_DEV : CURRENT_VC), 342 sizeof(console)); 343 tried++; 344 } 345 if (fd < 0) { 346 /* Perhaps we should panic here? */ 347 #ifndef CONFIG_SYSLOGD 348 log_console = 349 #endif 350 safe_strncpy(console, bb_dev_null, sizeof(console)); 351 } else { 352 s = getenv("TERM"); 353 /* check for serial console */ 354 if (ioctl(fd, TIOCGSERIAL, &sr) == 0) { 355 /* Force the TERM setting to vt102 for serial console -- 356 * if TERM is set to linux (the default) */ 357 if (s == NULL || strcmp(s, "linux") == 0) 358 putenv("TERM=vt102"); 359 #ifndef CONFIG_SYSLOGD 360 log_console = console; 361 #endif 362 } else { 363 if (s == NULL) 364 putenv("TERM=linux"); 365 } 366 close(fd); 367 } 368 messageD(LOG, "console=%s", console); 369 } 370 371 static void fixup_argv(int argc, char **argv, char *new_argv0) 372 { 373 int len; 374 375 /* Fix up argv[0] to be certain we claim to be init */ 376 len = strlen(argv[0]); 377 memset(argv[0], 0, len); 378 safe_strncpy(argv[0], new_argv0, len + 1); 379 380 /* Wipe argv[1]-argv[N] so they don't clutter the ps listing */ 381 len = 1; 382 while (argc > len) { 383 memset(argv[len], 0, strlen(argv[len])); 384 len++; 385 } 386 } 387 388 /* Open the new terminal device */ 389 static void open_new_terminal(const char * const device, const int fail) { 390 struct stat sb; 391 392 if ((device_open(device, O_RDWR)) < 0) { 393 if (stat(device, &sb) != 0) { 394 message(LOG | CONSOLE, "device '%s' does not exist.", device); 395 } else { 396 message(LOG | CONSOLE, "Bummer, can't open %s", device); 397 } 398 if (fail) 399 _exit(1); 400 /* else */ 401 #if !ENABLE_DEBUG_INIT 402 shutdown_signal(SIGUSR1); 403 #else 404 _exit(2); 405 #endif 406 } 321 dup2(fd, 0); 322 dup2(fd, 1); 323 dup2(fd, 2); 324 if (fd > 2) close(fd); 325 } 326 } 327 set_sane_term(); 407 328 } 408 329 … … 411 332 int i; 412 333 pid_t pid; 413 char *s, *tmpCmd, *cmd[INIT_BUFFS_SIZE], *cmdpath; 334 char *s, *tmpCmd, *cmdpath; 335 char *cmd[INIT_BUFFS_SIZE]; 414 336 char buf[INIT_BUFFS_SIZE + 6]; /* INIT_BUFFS_SIZE+strlen("exec ")+1 */ 415 337 sigset_t nmask, omask; 416 static const char press_enter[] =417 #ifdef CUSTOMIZED_BANNER418 #include CUSTOMIZED_BANNER419 #endif420 "\nPlease press Enter to activate this console. ";421 338 422 339 /* Block sigchild while forking. */ … … 424 341 sigaddset(&nmask, SIGCHLD); 425 342 sigprocmask(SIG_BLOCK, &nmask, &omask); 426 427 if ((pid = fork()) == 0) { 428 429 /* Clean up */ 430 close(0); 431 close(1); 432 close(2); 433 sigprocmask(SIG_SETMASK, &omask, NULL); 434 435 /* Reset signal handlers that were set by the parent process */ 436 signal(SIGUSR1, SIG_DFL); 437 signal(SIGUSR2, SIG_DFL); 438 signal(SIGINT, SIG_DFL); 439 signal(SIGTERM, SIG_DFL); 440 signal(SIGHUP, SIG_DFL); 441 signal(SIGQUIT, SIG_DFL); 442 signal(SIGCONT, SIG_DFL); 443 signal(SIGSTOP, SIG_DFL); 444 signal(SIGTSTP, SIG_DFL); 445 446 /* Create a new session and make ourself the process 447 * group leader */ 448 setsid(); 449 450 /* Open the new terminal device */ 451 open_new_terminal(a->terminal, 1); 452 453 /* Make sure the terminal will act fairly normal for us */ 454 set_term(); 455 /* Setup stdout, stderr for the new process so 456 * they point to the supplied terminal */ 457 dup(0); 458 dup(0); 459 460 /* If the init Action requires us to wait, then force the 461 * supplied terminal to be the controlling tty. */ 462 if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) { 463 464 /* Now fork off another process to just hang around */ 343 pid = fork(); 344 sigprocmask(SIG_SETMASK, &omask, NULL); 345 346 if (pid) 347 return pid; 348 349 /* Reset signal handlers that were set by the parent process */ 350 signal(SIGUSR1, SIG_DFL); 351 signal(SIGUSR2, SIG_DFL); 352 signal(SIGINT, SIG_DFL); 353 signal(SIGTERM, SIG_DFL); 354 signal(SIGHUP, SIG_DFL); 355 signal(SIGQUIT, SIG_DFL); 356 signal(SIGCONT, SIG_DFL); 357 signal(SIGSTOP, SIG_DFL); 358 signal(SIGTSTP, SIG_DFL); 359 360 /* Create a new session and make ourself the process 361 * group leader */ 362 setsid(); 363 364 /* Open the new terminal device */ 365 open_stdio_to_tty(a->terminal, 1); 366 367 /* If the init Action requires us to wait, then force the 368 * supplied terminal to be the controlling tty. */ 369 if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) { 370 371 /* Now fork off another process to just hang around */ 372 if ((pid = fork()) < 0) { 373 message(L_LOG | L_CONSOLE, "Can't fork"); 374 _exit(1); 375 } 376 377 if (pid > 0) { 378 379 /* We are the parent -- wait till the child is done */ 380 signal(SIGINT, SIG_IGN); 381 signal(SIGTSTP, SIG_IGN); 382 signal(SIGQUIT, SIG_IGN); 383 signal(SIGCHLD, SIG_DFL); 384 385 waitfor(NULL, pid); 386 /* See if stealing the controlling tty back is necessary */ 387 if (tcgetpgrp(0) != getpid()) 388 _exit(0); 389 390 /* Use a temporary process to steal the controlling tty. */ 465 391 if ((pid = fork()) < 0) { 466 message(L OG | CONSOLE, "Can't fork!");392 message(L_LOG | L_CONSOLE, "Can't fork"); 467 393 _exit(1); 468 394 } 469 470 if (pid > 0) { 471 472 /* We are the parent -- wait till the child is done */ 473 signal(SIGINT, SIG_IGN); 474 signal(SIGTSTP, SIG_IGN); 475 signal(SIGQUIT, SIG_IGN); 476 signal(SIGCHLD, SIG_DFL); 477 478 waitfor(NULL, pid); 479 /* See if stealing the controlling tty back is necessary */ 480 if (tcgetpgrp(0) != getpid()) 481 _exit(0); 482 483 /* Use a temporary process to steal the controlling tty. */ 484 if ((pid = fork()) < 0) { 485 message(LOG | CONSOLE, "Can't fork!"); 486 _exit(1); 487 } 488 if (pid == 0) { 489 setsid(); 490 ioctl(0, TIOCSCTTY, 1); 491 _exit(0); 492 } 493 waitfor(NULL, pid); 395 if (pid == 0) { 396 setsid(); 397 ioctl(0, TIOCSCTTY, 1); 494 398 _exit(0); 495 399 } 496 497 /* Now fall though to actually execute things */ 498 } 499 500 /* See if any special /bin/sh requiring characters are present */ 501 if (strpbrk(a->command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) { 502 cmd[0] = (char *)DEFAULT_SHELL; 503 cmd[1] = "-c"; 504 cmd[2] = strcat(strcpy(buf, "exec "), a->command); 505 cmd[3] = NULL; 400 waitfor(NULL, pid); 401 _exit(0); 402 } 403 404 /* Now fall though to actually execute things */ 405 } 406 407 /* See if any special /bin/sh requiring characters are present */ 408 if (strpbrk(a->command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) { 409 cmd[0] = (char*)DEFAULT_SHELL; 410 cmd[1] = (char*)"-c"; 411 cmd[2] = strcat(strcpy(buf, "exec "), a->command); 412 cmd[3] = NULL; 413 } else { 414 /* Convert command (char*) into cmd (char**, one word per string) */ 415 strcpy(buf, a->command); 416 s = buf; 417 for (tmpCmd = buf, i = 0; (tmpCmd = strsep(&s, " \t")) != NULL;) { 418 if (*tmpCmd != '\0') { 419 cmd[i] = tmpCmd; 420 i++; 421 } 422 } 423 cmd[i] = NULL; 424 } 425 426 cmdpath = cmd[0]; 427 428 /* 429 * Interactive shells want to see a dash in argv[0]. This 430 * typically is handled by login, argv will be setup this 431 * way if a dash appears at the front of the command path 432 * (like "-/bin/sh"). 433 */ 434 if (*cmdpath == '-') { 435 /* skip over the dash */ 436 ++cmdpath; 437 438 /* find the last component in the command pathname */ 439 s = bb_get_last_path_component(cmdpath); 440 441 /* make a new argv[0] */ 442 if ((cmd[0] = malloc(strlen(s) + 2)) == NULL) { 443 message(L_LOG | L_CONSOLE, bb_msg_memory_exhausted); 444 cmd[0] = cmdpath; 506 445 } else { 507 /* Convert command (char*) into cmd (char**, one word per string) */ 508 strcpy(buf, a->command); 509 s = buf; 510 for (tmpCmd = buf, i = 0; (tmpCmd = strsep(&s, " \t")) != NULL;) { 511 if (*tmpCmd != '\0') { 512 cmd[i] = tmpCmd; 513 i++; 514 } 515 } 516 cmd[i] = NULL; 517 } 518 519 cmdpath = cmd[0]; 520 446 cmd[0][0] = '-'; 447 strcpy(cmd[0] + 1, s); 448 } 449 #if ENABLE_FEATURE_INIT_SCTTY 450 /* Establish this process as session leader and 451 * (attempt) to make the tty (if any) a controlling tty. 452 */ 453 setsid(); 454 ioctl(0, TIOCSCTTY, 0 /*don't steal it*/); 455 #endif 456 } 457 458 #if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__) 459 if (a->action & ASKFIRST) { 460 static const char press_enter[] ALIGN1 = 461 #ifdef CUSTOMIZED_BANNER 462 #include CUSTOMIZED_BANNER 463 #endif 464 "\nPlease press Enter to activate this console. "; 465 char c; 521 466 /* 522 Interactive shells want to see a dash in argv[0]. This 523 typically is handled by login, argv will be setup this 524 way if a dash appears at the front of the command path 525 (like "-/bin/sh"). 467 * Save memory by not exec-ing anything large (like a shell) 468 * before the user wants it. This is critical if swap is not 469 * enabled and the system has low memory. Generally this will 470 * be run on the second virtual console, and the first will 471 * be allowed to start a shell or whatever an init script 472 * specifies. 526 473 */ 527 528 if (*cmdpath == '-') { 529 530 /* skip over the dash */ 531 ++cmdpath; 532 533 /* find the last component in the command pathname */ 534 s = bb_get_last_path_component(cmdpath); 535 536 /* make a new argv[0] */ 537 if ((cmd[0] = malloc(strlen(s) + 2)) == NULL) { 538 message(LOG | CONSOLE, bb_msg_memory_exhausted); 539 cmd[0] = cmdpath; 540 } else { 541 cmd[0][0] = '-'; 542 strcpy(cmd[0] + 1, s); 543 } 544 #ifdef CONFIG_FEATURE_INIT_SCTTY 545 /* Establish this process as session leader and 546 * (attempt) to make the tty (if any) a controlling tty. 547 */ 548 (void) setsid(); 549 (void) ioctl(0, TIOCSCTTY, 0/*don't steal it*/); 550 #endif 551 } 552 553 #if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__) 554 if (a->action & ASKFIRST) { 555 char c; 556 /* 557 * Save memory by not exec-ing anything large (like a shell) 558 * before the user wants it. This is critical if swap is not 559 * enabled and the system has low memory. Generally this will 560 * be run on the second virtual console, and the first will 561 * be allowed to start a shell or whatever an init script 562 * specifies. 563 */ 564 messageD(LOG, "Waiting for enter to start '%s'" 565 "(pid %d, terminal %s)\n", 566 cmdpath, getpid(), a->terminal); 567 bb_full_write(1, press_enter, sizeof(press_enter) - 1); 568 while(read(0, &c, 1) == 1 && c != '\n') 569 ; 570 } 571 #endif 572 573 /* Log the process name and args */ 574 message(LOG, "Starting pid %d, console %s: '%s'", 575 getpid(), a->terminal, cmdpath); 576 577 #if defined CONFIG_FEATURE_INIT_COREDUMPS 578 { 579 struct stat sb; 580 if (stat(CORE_ENABLE_FLAG_FILE, &sb) == 0) { 581 struct rlimit limit; 582 583 limit.rlim_cur = RLIM_INFINITY; 584 limit.rlim_max = RLIM_INFINITY; 585 setrlimit(RLIMIT_CORE, &limit); 586 } 587 } 588 #endif 589 590 /* Now run it. The new program will take over this PID, 591 * so nothing further in init.c should be run. */ 592 execv(cmdpath, cmd); 593 594 /* We're still here? Some error happened. */ 595 message(LOG | CONSOLE, "Bummer, could not run '%s': %m", cmdpath); 596 _exit(-1); 597 } 598 sigprocmask(SIG_SETMASK, &omask, NULL); 599 return pid; 474 messageD(L_LOG, "waiting for enter to start '%s'" 475 "(pid %d, tty '%s')\n", 476 cmdpath, getpid(), a->terminal); 477 full_write(1, press_enter, sizeof(press_enter) - 1); 478 while (read(0, &c, 1) == 1 && c != '\n') 479 ; 480 } 481 #endif 482 /* Log the process name and args */ 483 message(L_LOG, "starting pid %d, tty '%s': '%s'", 484 getpid(), a->terminal, cmdpath); 485 486 #if ENABLE_FEATURE_INIT_COREDUMPS 487 { 488 struct stat sb; 489 if (stat(CORE_ENABLE_FLAG_FILE, &sb) == 0) { 490 struct rlimit limit; 491 492 limit.rlim_cur = RLIM_INFINITY; 493 limit.rlim_max = RLIM_INFINITY; 494 setrlimit(RLIMIT_CORE, &limit); 495 } 496 } 497 #endif 498 /* Now run it. The new program will take over this PID, 499 * so nothing further in init.c should be run. */ 500 BB_EXECVP(cmdpath, cmd); 501 502 /* We're still here? Some error happened. */ 503 message(L_LOG | L_CONSOLE, "Cannot run '%s': %s", 504 cmdpath, strerror(errno)); 505 _exit(-1); 600 506 } 601 507 … … 607 513 runpid = (NULL == a)? pid : run(a); 608 514 while (1) { 609 wpid = waitpid(runpid, &status,0);515 wpid = waitpid(runpid, &status, 0); 610 516 if (wpid == runpid) 611 517 break; … … 628 534 tmp = a->next; 629 535 if (a->action == action) { 630 if (access(a->terminal, R_OK | W_OK)) { 536 /* a->terminal of "" means "init's console" */ 537 if (a->terminal[0] && access(a->terminal, R_OK | W_OK)) { 631 538 delete_init_action(a); 632 539 } else if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) { … … 654 561 * linux/kernel/sys.c, which can cause the machine to panic when 655 562 * the init process is killed.... */ 656 if ((pid = fork()) == 0) { 563 pid = vfork(); 564 if (pid == 0) { /* child */ 657 565 reboot(magic); 658 566 _exit(0); 659 567 } 660 waitpid 568 waitpid(pid, NULL, 0); 661 569 } 662 570 … … 684 592 sigprocmask(SIG_BLOCK, &block_signals, NULL); 685 593 594 message(L_CONSOLE | L_LOG, "The system is going down NOW!"); 595 686 596 /* Allow Ctrl-Alt-Del to reboot system. */ 687 597 init_reboot(RB_ENABLE_CAD); 688 598 689 message(CONSOLE | LOG, "The system is going down NOW !!"); 599 /* Send signals to every process _except_ pid 1 */ 600 message(L_CONSOLE | L_LOG, "Sending SIG%s to all processes", "TERM"); 601 kill(-1, SIGTERM); 690 602 sync(); 691 692 /* Send signals to every process _except_ pid 1 */693 message(CONSOLE | LOG, init_sending_format, "TERM");694 kill(-1, SIGTERM);695 603 sleep(1); 604 605 message(L_CONSOLE | L_LOG, "Sending SIG%s to all processes", "KILL"); 606 kill(-1, SIGKILL); 696 607 sync(); 697 698 message(CONSOLE | LOG, init_sending_format, "KILL");699 kill(-1, SIGKILL);700 608 sleep(1); 701 702 sync();703 609 } 704 610 … … 727 633 sigprocmask(SIG_UNBLOCK, &unblock_signals, NULL); 728 634 729 /* Close whatever files are open. */730 close(0);731 close(1);732 close(2);733 734 635 /* Open the new terminal device */ 735 open_new_terminal(a->terminal, 0); 736 737 /* Make sure the terminal will act fairly normal for us */ 738 set_term(); 739 /* Setup stdout, stderr on the supplied terminal */ 740 dup(0); 741 dup(0); 742 743 messageD(CONSOLE | LOG, "Trying to re-exec %s", a->command); 744 execl(a->command, a->command, NULL); 745 746 message(CONSOLE | LOG, "exec of '%s' failed: %m", 747 a->command); 748 sync(); 636 open_stdio_to_tty(a->terminal, 0); 637 638 messageD(L_CONSOLE | L_LOG, "Trying to re-exec %s", a->command); 639 BB_EXECLP(a->command, a->command, NULL); 640 641 message(L_CONSOLE | L_LOG, "Cannot run '%s': %s", 642 a->command, strerror(errno)); 749 643 sleep(2); 750 644 init_reboot(RB_HALT_SYSTEM); … … 756 650 static void shutdown_signal(int sig) 757 651 { 758 c har *m;652 const char *m; 759 653 int rb; 760 654 761 655 shutdown_system(); 762 656 657 m = "halt"; 658 rb = RB_HALT_SYSTEM; 763 659 if (sig == SIGTERM) { 764 660 m = "reboot"; … … 767 663 m = "poweroff"; 768 664 rb = RB_POWER_OFF; 769 } else { 770 m = "halt"; 771 rb = RB_HALT_SYSTEM; 772 } 773 message(CONSOLE | LOG, "Requesting system %s.", m); 774 sync(); 775 665 } 666 message(L_CONSOLE | L_LOG, "Requesting system %s", m); 776 667 /* allow time for last message to reach serial console */ 777 668 sleep(2); 778 779 669 init_reboot(rb); 780 781 670 loop_forever(); 782 671 } … … 805 694 } 806 695 807 #endif /* !ENABLE_DEBUG_INIT */696 #endif /* !ENABLE_DEBUG_INIT */ 808 697 809 698 static void new_init_action(int action, const char *command, const char *cons) 810 699 { 811 700 struct init_action *new_action, *a, *last; 812 813 if (*cons == '\0')814 cons = console;815 701 816 702 if (strcmp(cons, bb_dev_null) == 0 && (action & ASKFIRST)) 817 703 return; 818 819 new_action = calloc((size_t) (1), sizeof(struct init_action));820 if (!new_action) {821 message(LOG | CONSOLE, "Memory allocation failure");822 loop_forever();823 }824 704 825 705 /* Append to the end of the list */ … … 827 707 /* don't enter action if it's already in the list, 828 708 * but do overwrite existing actions */ 829 if ((strcmp(a->command, command) == 0) && 830 (strcmp(a->terminal, cons) ==0)) { 709 if ((strcmp(a->command, command) == 0) 710 && (strcmp(a->terminal, cons) == 0) 711 ) { 831 712 a->action = action; 832 free(new_action);833 713 return; 834 714 } 835 715 last = a; 836 716 } 717 718 new_action = xzalloc(sizeof(struct init_action)); 837 719 if (last) { 838 720 last->next = new_action; … … 843 725 new_action->action = action; 844 726 strcpy(new_action->terminal, cons); 845 #if 0 /* calloc zeroed always */ 846 new_action->pid = 0; 847 #endif 848 messageD(LOG|CONSOLE, "command='%s' action='%d' terminal='%s'\n", 727 messageD(L_LOG | L_CONSOLE, "command='%s' action=%d tty='%s'\n", 849 728 new_action->command, new_action->action, new_action->terminal); 850 729 } … … 876 755 static void parse_inittab(void) 877 756 { 878 #if def CONFIG_FEATURE_USE_INITTAB757 #if ENABLE_FEATURE_USE_INITTAB 879 758 FILE *file; 880 759 char buf[INIT_BUFFS_SIZE], lineAsRead[INIT_BUFFS_SIZE]; 881 char tmpConsole[CONSOLE_ BUFF_SIZE];760 char tmpConsole[CONSOLE_NAME_SIZE]; 882 761 char *id, *runlev, *action, *command, *eol; 883 762 const struct init_action_type *a = actions; 884 885 763 886 764 file = fopen(INITTAB, "r"); … … 889 767 #endif 890 768 /* Reboot on Ctrl-Alt-Del */ 891 new_init_action(CTRLALTDEL, " /sbin/reboot", "");769 new_init_action(CTRLALTDEL, "reboot", ""); 892 770 /* Umount all filesystems on halt/reboot */ 893 new_init_action(SHUTDOWN, " /bin/umount -a -r", "");771 new_init_action(SHUTDOWN, "umount -a -r", ""); 894 772 /* Swapoff on halt/reboot */ 895 if (ENABLE_SWAPONOFF) new_init_action(SHUTDOWN, "/sbin/swapoff -a", "");773 if (ENABLE_SWAPONOFF) new_init_action(SHUTDOWN, "swapoff -a", ""); 896 774 /* Prepare to restart init when a HUP is received */ 897 new_init_action(RESTART, " /sbin/init", "");775 new_init_action(RESTART, "init", ""); 898 776 /* Askfirst shell on tty1-4 */ 899 777 new_init_action(ASKFIRST, bb_default_login_shell, ""); … … 905 783 906 784 return; 907 #if def CONFIG_FEATURE_USE_INITTAB785 #if ENABLE_FEATURE_USE_INITTAB 908 786 } 909 787 … … 917 795 918 796 /* Trim the trailing \n */ 797 //XXX: chomp() ? 919 798 eol = strrchr(id, '\n'); 920 799 if (eol != NULL) … … 927 806 runlev = strchr(id, ':'); 928 807 if (runlev == NULL || *(runlev + 1) == '\0') { 929 message(L OG |CONSOLE, "Bad inittab entry: %s", lineAsRead);808 message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead); 930 809 continue; 931 810 } else { … … 937 816 action = strchr(runlev, ':'); 938 817 if (action == NULL || *(action + 1) == '\0') { 939 message(L OG |CONSOLE, "Bad inittab entry: %s", lineAsRead);818 message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead); 940 819 continue; 941 820 } else { … … 947 826 command = strchr(action, ':'); 948 827 if (command == NULL || *(command + 1) == '\0') { 949 message(L OG |CONSOLE, "Bad inittab entry: %s", lineAsRead);828 message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead); 950 829 continue; 951 830 } else { … … 958 837 if (strcmp(a->name, action) == 0) { 959 838 if (*id != '\0') { 960 if (strncmp(id, "/dev/", 5) == 0)839 if (strncmp(id, "/dev/", 5) == 0) 961 840 id += 5; 962 841 strcpy(tmpConsole, "/dev/"); 963 842 safe_strncpy(tmpConsole + 5, id, 964 CONSOLE_BUFF_SIZE- 5);843 sizeof(tmpConsole) - 5); 965 844 id = tmpConsole; 966 845 } … … 971 850 if (a->name == 0) { 972 851 /* Choke on an unknown action */ 973 message(L OG |CONSOLE, "Bad inittab entry: %s", lineAsRead);852 message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead); 974 853 } 975 854 } 976 855 fclose(file); 977 return; 978 #endif /* CONFIG_FEATURE_USE_INITTAB */ 979 } 980 981 #ifdef CONFIG_FEATURE_USE_INITTAB 856 #endif /* FEATURE_USE_INITTAB */ 857 } 858 859 #if ENABLE_FEATURE_USE_INITTAB 982 860 static void reload_signal(int sig ATTRIBUTE_UNUSED) 983 861 { 984 862 struct init_action *a, *tmp; 985 863 986 message(L OG, "Reloading /etc/inittab");864 message(L_LOG, "reloading /etc/inittab"); 987 865 988 866 /* disable old entrys */ … … 996 874 for (a = init_action_list; a; a = tmp) { 997 875 tmp = a->next; 998 if (a->action & (ONCE | SYSINIT | WAIT ) && 999 a->pid == 0 ) { 876 if ((a->action & (ONCE | SYSINIT | WAIT)) && a->pid == 0) { 1000 877 delete_init_action(a); 1001 878 } 1002 879 } 1003 880 run_actions(RESPAWN); 1004 return; 1005 } 1006 #endif /* CONFIG_FEATURE_USE_INITTAB */ 1007 881 } 882 #endif /* FEATURE_USE_INITTAB */ 883 884 int init_main(int argc, char **argv); 1008 885 int init_main(int argc, char **argv) 1009 886 { … … 1011 888 pid_t wpid; 1012 889 890 die_sleep = 30 * 24*60*60; /* if xmalloc will ever die... */ 891 1013 892 if (argc > 1 && !strcmp(argv[1], "-q")) { 1014 return kill(1, SIGHUP);893 return kill(1, SIGHUP); 1015 894 } 1016 895 #if !ENABLE_DEBUG_INIT 1017 896 /* Expect to be invoked as init with PID=1 or be invoked as linuxrc */ 1018 if (getpid() != 1 &&1019 (!ENABLE_FEATURE_INITRD || !strstr(bb_applet_name, "linuxrc")))1020 {897 if (getpid() != 1 898 && (!ENABLE_FEATURE_INITRD || !strstr(applet_name, "linuxrc")) 899 ) { 1021 900 bb_show_usage(); 1022 901 } … … 1038 917 #endif 1039 918 919 1040 920 /* Figure out where the default console should be */ 1041 921 console_init(); 1042 1043 /* Close whatever files are open, and reset the console. */ 1044 close(0); 1045 close(1); 1046 close(2); 1047 1048 if (device_open(console, O_RDWR | O_NOCTTY) == 0) { 1049 set_term(); 1050 close(0); 1051 } 1052 922 set_sane_term(); 1053 923 chdir("/"); 1054 924 setsid(); 1055 925 { 1056 const char * 926 const char *const *e; 1057 927 /* Make sure environs is set to something sane */ 1058 for (e = environment; *e; e++)928 for (e = environment; *e; e++) 1059 929 putenv((char *) *e); 1060 930 } 931 932 if (argc > 1) setenv("RUNLEVEL", argv[1], 1); 933 1061 934 /* Hello world */ 1062 message(MAYBE_CONSOLE | L OG, "init started: %s", bb_msg_full_version);935 message(MAYBE_CONSOLE | L_LOG, "init started: %s", bb_banner); 1063 936 1064 937 /* Make sure there is enough memory to do something useful. */ … … 1067 940 1068 941 if (!sysinfo(&info) && 1069 (info.mem_unit ? : 1) * (long long)info.totalram < MEGABYTE)942 (info.mem_unit ? : 1) * (long long)info.totalram < 1024*1024) 1070 943 { 1071 message( CONSOLE,"Low memory: forcing swapon.");944 message(L_CONSOLE, "Low memory, forcing swapon"); 1072 945 /* swapon -a requires /proc typically */ 1073 new_init_action(SYSINIT, " /bin/mount -t proc proc /proc", "");946 new_init_action(SYSINIT, "mount -t proc proc /proc", ""); 1074 947 /* Try to turn on swap */ 1075 new_init_action(SYSINIT, " /sbin/swapon -a", "");948 new_init_action(SYSINIT, "swapon -a", ""); 1076 949 run_actions(SYSINIT); /* wait and removing */ 1077 950 } … … 1079 952 1080 953 /* Check if we are supposed to be in single user mode */ 1081 if (argc > 1 && (!strcmp(argv[1], "single") || 1082 !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) { 954 if (argc > 1 955 && (!strcmp(argv[1], "single") || !strcmp(argv[1], "-s") || LONE_CHAR(argv[1], '1')) 956 ) { 1083 957 /* Start a shell on console */ 1084 958 new_init_action(RESPAWN, bb_default_login_shell, ""); … … 1093 967 } 1094 968 1095 #if def CONFIG_SELINUX969 #if ENABLE_SELINUX 1096 970 if (getenv("SELINUX_INIT") == NULL) { 1097 971 int enforce = 0; 1098 972 1099 putenv( "SELINUX_INIT=YES");973 putenv((char*)"SELINUX_INIT=YES"); 1100 974 if (selinux_init_load_policy(&enforce) == 0) { 1101 execv(argv[0], argv);975 BB_EXECVP(argv[0], argv); 1102 976 } else if (enforce > 0) { 1103 977 /* SELinux in enforcing mode but load_policy failed */ 1104 978 /* At this point, we probably can't open /dev/console, so log() won't work */ 1105 message(CONSOLE,"Unable to load SELinux Policy. Machine is in enforcing mode. Halting now."); 979 message(L_CONSOLE, "Cannot load SELinux Policy. " 980 "Machine is in enforcing mode. Halting now."); 1106 981 exit(1); 1107 982 } … … 1110 985 1111 986 /* Make the command line just say "init" -- thats all, nothing else */ 1112 fixup_argv(arg c, argv, "init");987 fixup_argv(argv); 1113 988 1114 989 /* Now run everything that needs to be run */ … … 1123 998 run_actions(ONCE); 1124 999 1125 #if def CONFIG_FEATURE_USE_INITTAB1000 #if ENABLE_FEATURE_USE_INITTAB 1126 1001 /* Redefine SIGHUP to reread /etc/inittab */ 1127 1002 signal(SIGHUP, reload_signal); 1128 1003 #else 1129 1004 signal(SIGHUP, SIG_IGN); 1130 #endif /* CONFIG_FEATURE_USE_INITTAB */ 1131 1005 #endif /* FEATURE_USE_INITTAB */ 1132 1006 1133 1007 /* Now run the looping stuff for the rest of forever */ … … 1151 1025 * restarted by run_actions() */ 1152 1026 a->pid = 0; 1153 message(L OG, "Process '%s' (pid %d) exited."1027 message(L_LOG, "process '%s' (pid %d) exited. " 1154 1028 "Scheduling it for restart.", 1155 1029 a->command, wpid); … … 1157 1031 } 1158 1032 /* see if anyone else is waiting to be reaped */ 1159 wpid = waitpid 1160 } 1161 } 1162 } 1033 wpid = waitpid(-1, NULL, WNOHANG); 1034 } 1035 } 1036 }
Note:
See TracChangeset
for help on using the changeset viewer.