|
|
@ -47,31 +47,22 @@
|
|
|
|
#define SHUTDOWN 0x040
|
|
|
|
#define SHUTDOWN 0x040
|
|
|
|
#define RESTART 0x080
|
|
|
|
#define RESTART 0x080
|
|
|
|
|
|
|
|
|
|
|
|
/* A mapping between "inittab" action name strings and action type codes. */
|
|
|
|
#define STR_SYSINIT "\x01"
|
|
|
|
struct init_action_type {
|
|
|
|
#define STR_RESPAWN "\x02"
|
|
|
|
const char *name;
|
|
|
|
#define STR_ASKFIRST "\x04"
|
|
|
|
int action;
|
|
|
|
#define STR_WAIT "\x08"
|
|
|
|
};
|
|
|
|
#define STR_ONCE "\x10"
|
|
|
|
|
|
|
|
#define STR_CTRLALTDEL "\x20"
|
|
|
|
static const struct init_action_type actions[] = {
|
|
|
|
#define STR_SHUTDOWN "\x40"
|
|
|
|
{"sysinit", SYSINIT},
|
|
|
|
#define STR_RESTART "\x80"
|
|
|
|
{"respawn", RESPAWN},
|
|
|
|
|
|
|
|
{"askfirst", ASKFIRST},
|
|
|
|
|
|
|
|
{"wait", WAIT},
|
|
|
|
|
|
|
|
{"once", ONCE},
|
|
|
|
|
|
|
|
{"ctrlaltdel", CTRLALTDEL},
|
|
|
|
|
|
|
|
{"shutdown", SHUTDOWN},
|
|
|
|
|
|
|
|
{"restart", RESTART},
|
|
|
|
|
|
|
|
{0, 0}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Set up a linked list of init_actions, to be read from inittab */
|
|
|
|
/* Set up a linked list of init_actions, to be read from inittab */
|
|
|
|
struct init_action {
|
|
|
|
struct init_action {
|
|
|
|
struct init_action *next;
|
|
|
|
struct init_action *next;
|
|
|
|
int action;
|
|
|
|
|
|
|
|
pid_t pid;
|
|
|
|
pid_t pid;
|
|
|
|
char command[INIT_BUFFS_SIZE];
|
|
|
|
uint8_t action;
|
|
|
|
char terminal[CONSOLE_NAME_SIZE];
|
|
|
|
char terminal[CONSOLE_NAME_SIZE];
|
|
|
|
|
|
|
|
char command[INIT_BUFFS_SIZE];
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* Static variables */
|
|
|
|
/* Static variables */
|
|
|
@ -113,7 +104,7 @@ static const char *const environment[] = {
|
|
|
|
|
|
|
|
|
|
|
|
/* Function prototypes */
|
|
|
|
/* Function prototypes */
|
|
|
|
static void delete_init_action(struct init_action *a);
|
|
|
|
static void delete_init_action(struct init_action *a);
|
|
|
|
static int waitfor(const struct init_action *a, pid_t pid);
|
|
|
|
static int waitfor(pid_t pid);
|
|
|
|
#if !ENABLE_DEBUG_INIT
|
|
|
|
#if !ENABLE_DEBUG_INIT
|
|
|
|
static void shutdown_signal(int sig);
|
|
|
|
static void shutdown_signal(int sig);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
@ -193,43 +184,6 @@ static void message(int device, const char *fmt, ...)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Set terminal settings to reasonable defaults */
|
|
|
|
|
|
|
|
static void set_sane_term(void)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
struct termios tty;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tcgetattr(STDIN_FILENO, &tty);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* set control chars */
|
|
|
|
|
|
|
|
tty.c_cc[VINTR] = 3; /* C-c */
|
|
|
|
|
|
|
|
tty.c_cc[VQUIT] = 28; /* C-\ */
|
|
|
|
|
|
|
|
tty.c_cc[VERASE] = 127; /* C-? */
|
|
|
|
|
|
|
|
tty.c_cc[VKILL] = 21; /* C-u */
|
|
|
|
|
|
|
|
tty.c_cc[VEOF] = 4; /* C-d */
|
|
|
|
|
|
|
|
tty.c_cc[VSTART] = 17; /* C-q */
|
|
|
|
|
|
|
|
tty.c_cc[VSTOP] = 19; /* C-s */
|
|
|
|
|
|
|
|
tty.c_cc[VSUSP] = 26; /* C-z */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* use line dicipline 0 */
|
|
|
|
|
|
|
|
tty.c_line = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Make it be sane */
|
|
|
|
|
|
|
|
tty.c_cflag &= CBAUD | CBAUDEX | CSIZE | CSTOPB | PARENB | PARODD;
|
|
|
|
|
|
|
|
tty.c_cflag |= CREAD | HUPCL | CLOCAL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* input modes */
|
|
|
|
|
|
|
|
tty.c_iflag = ICRNL | IXON | IXOFF;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* output modes */
|
|
|
|
|
|
|
|
tty.c_oflag = OPOST | ONLCR;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* local modes */
|
|
|
|
|
|
|
|
tty.c_lflag =
|
|
|
|
|
|
|
|
ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tcsetattr(STDIN_FILENO, TCSANOW, &tty);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* From <linux/serial.h> */
|
|
|
|
/* From <linux/serial.h> */
|
|
|
|
struct serial_struct {
|
|
|
|
struct serial_struct {
|
|
|
|
int type;
|
|
|
|
int type;
|
|
|
@ -277,7 +231,7 @@ static void console_init(void)
|
|
|
|
|
|
|
|
|
|
|
|
s = getenv("TERM");
|
|
|
|
s = getenv("TERM");
|
|
|
|
if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
|
|
|
|
if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
|
|
|
|
/* Force the TERM setting to vt102 for serial console --
|
|
|
|
/* Force the TERM setting to vt102 for serial console
|
|
|
|
* if TERM is set to linux (the default) */
|
|
|
|
* if TERM is set to linux (the default) */
|
|
|
|
if (!s || strcmp(s, "linux") == 0)
|
|
|
|
if (!s || strcmp(s, "linux") == 0)
|
|
|
|
putenv((char*)"TERM=vt102");
|
|
|
|
putenv((char*)"TERM=vt102");
|
|
|
@ -288,14 +242,41 @@ static void console_init(void)
|
|
|
|
putenv((char*)"TERM=linux");
|
|
|
|
putenv((char*)"TERM=linux");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void fixup_argv(char **argv)
|
|
|
|
/* Set terminal settings to reasonable defaults */
|
|
|
|
|
|
|
|
static void set_sane_term(void)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/* Fix up argv[0] to be certain we claim to be init */
|
|
|
|
struct termios tty;
|
|
|
|
strncpy(argv[0], "init", strlen(argv[0]));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Wipe argv[1]-argv[N] so they don't clutter the ps listing */
|
|
|
|
tcgetattr(STDIN_FILENO, &tty);
|
|
|
|
while (*++argv)
|
|
|
|
|
|
|
|
memset(*argv, 0, strlen(*argv));
|
|
|
|
/* set control chars */
|
|
|
|
|
|
|
|
tty.c_cc[VINTR] = 3; /* C-c */
|
|
|
|
|
|
|
|
tty.c_cc[VQUIT] = 28; /* C-\ */
|
|
|
|
|
|
|
|
tty.c_cc[VERASE] = 127; /* C-? */
|
|
|
|
|
|
|
|
tty.c_cc[VKILL] = 21; /* C-u */
|
|
|
|
|
|
|
|
tty.c_cc[VEOF] = 4; /* C-d */
|
|
|
|
|
|
|
|
tty.c_cc[VSTART] = 17; /* C-q */
|
|
|
|
|
|
|
|
tty.c_cc[VSTOP] = 19; /* C-s */
|
|
|
|
|
|
|
|
tty.c_cc[VSUSP] = 26; /* C-z */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* use line dicipline 0 */
|
|
|
|
|
|
|
|
tty.c_line = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Make it be sane */
|
|
|
|
|
|
|
|
tty.c_cflag &= CBAUD | CBAUDEX | CSIZE | CSTOPB | PARENB | PARODD;
|
|
|
|
|
|
|
|
tty.c_cflag |= CREAD | HUPCL | CLOCAL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* input modes */
|
|
|
|
|
|
|
|
tty.c_iflag = ICRNL | IXON | IXOFF;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* output modes */
|
|
|
|
|
|
|
|
tty.c_oflag = OPOST | ONLCR;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* local modes */
|
|
|
|
|
|
|
|
tty.c_lflag =
|
|
|
|
|
|
|
|
ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tcsetattr(STDIN_FILENO, TCSANOW, &tty);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Open the new terminal device */
|
|
|
|
/* Open the new terminal device */
|
|
|
@ -324,6 +305,7 @@ static void open_stdio_to_tty(const char* tty_name, int fail)
|
|
|
|
set_sane_term();
|
|
|
|
set_sane_term();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Used only by run_actions */
|
|
|
|
static pid_t run(const struct init_action *a)
|
|
|
|
static pid_t run(const struct init_action *a)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int i;
|
|
|
@ -333,16 +315,20 @@ static pid_t run(const struct init_action *a)
|
|
|
|
char buf[INIT_BUFFS_SIZE + 6]; /* INIT_BUFFS_SIZE+strlen("exec ")+1 */
|
|
|
|
char buf[INIT_BUFFS_SIZE + 6]; /* INIT_BUFFS_SIZE+strlen("exec ")+1 */
|
|
|
|
sigset_t nmask, omask;
|
|
|
|
sigset_t nmask, omask;
|
|
|
|
|
|
|
|
|
|
|
|
/* Block sigchild while forking. */
|
|
|
|
/* Block sigchild while forking (why?) */
|
|
|
|
sigemptyset(&nmask);
|
|
|
|
sigemptyset(&nmask);
|
|
|
|
sigaddset(&nmask, SIGCHLD);
|
|
|
|
sigaddset(&nmask, SIGCHLD);
|
|
|
|
sigprocmask(SIG_BLOCK, &nmask, &omask);
|
|
|
|
sigprocmask(SIG_BLOCK, &nmask, &omask);
|
|
|
|
pid = fork();
|
|
|
|
pid = fork();
|
|
|
|
sigprocmask(SIG_SETMASK, &omask, NULL);
|
|
|
|
sigprocmask(SIG_SETMASK, &omask, NULL);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (pid < 0)
|
|
|
|
|
|
|
|
message(L_LOG | L_CONSOLE, "Can't fork");
|
|
|
|
if (pid)
|
|
|
|
if (pid)
|
|
|
|
return pid;
|
|
|
|
return pid;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Child */
|
|
|
|
|
|
|
|
|
|
|
|
/* Reset signal handlers that were set by the parent process */
|
|
|
|
/* Reset signal handlers that were set by the parent process */
|
|
|
|
signal(SIGUSR1, SIG_DFL);
|
|
|
|
signal(SIGUSR1, SIG_DFL);
|
|
|
|
signal(SIGUSR2, SIG_DFL);
|
|
|
|
signal(SIGUSR2, SIG_DFL);
|
|
|
@ -359,8 +345,9 @@ static pid_t run(const struct init_action *a)
|
|
|
|
setsid();
|
|
|
|
setsid();
|
|
|
|
|
|
|
|
|
|
|
|
/* Open the new terminal device */
|
|
|
|
/* Open the new terminal device */
|
|
|
|
open_stdio_to_tty(a->terminal, 1);
|
|
|
|
open_stdio_to_tty(a->terminal, 1 /* - exit if open fails*/);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef BUT_RUN_ACTIONS_ALREADY_DOES_WAITING
|
|
|
|
/* If the init Action requires us to wait, then force the
|
|
|
|
/* If the init Action requires us to wait, then force the
|
|
|
|
* supplied terminal to be the controlling tty. */
|
|
|
|
* supplied terminal to be the controlling tty. */
|
|
|
|
if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
|
|
|
|
if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
|
|
|
@ -373,13 +360,13 @@ static pid_t run(const struct init_action *a)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (pid > 0) {
|
|
|
|
if (pid > 0) {
|
|
|
|
/* We are the parent -- wait till the child is done */
|
|
|
|
/* Parent - wait till the child is done */
|
|
|
|
signal(SIGINT, SIG_IGN);
|
|
|
|
signal(SIGINT, SIG_IGN);
|
|
|
|
signal(SIGTSTP, SIG_IGN);
|
|
|
|
signal(SIGTSTP, SIG_IGN);
|
|
|
|
signal(SIGQUIT, SIG_IGN);
|
|
|
|
signal(SIGQUIT, SIG_IGN);
|
|
|
|
signal(SIGCHLD, SIG_DFL);
|
|
|
|
signal(SIGCHLD, SIG_DFL);
|
|
|
|
|
|
|
|
|
|
|
|
waitfor(NULL, pid);
|
|
|
|
waitfor(pid);
|
|
|
|
/* See if stealing the controlling tty back is necessary */
|
|
|
|
/* See if stealing the controlling tty back is necessary */
|
|
|
|
if (tcgetpgrp(0) != getpid())
|
|
|
|
if (tcgetpgrp(0) != getpid())
|
|
|
|
_exit(0);
|
|
|
|
_exit(0);
|
|
|
@ -395,12 +382,13 @@ static pid_t run(const struct init_action *a)
|
|
|
|
ioctl(0, TIOCSCTTY, 1);
|
|
|
|
ioctl(0, TIOCSCTTY, 1);
|
|
|
|
_exit(0);
|
|
|
|
_exit(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
waitfor(NULL, pid);
|
|
|
|
waitfor(pid);
|
|
|
|
_exit(0);
|
|
|
|
_exit(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Now fall though to actually execute things */
|
|
|
|
/* Child - fall though to actually execute things */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/* See if any special /bin/sh requiring characters are present */
|
|
|
|
/* See if any special /bin/sh requiring characters are present */
|
|
|
|
if (strpbrk(a->command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {
|
|
|
|
if (strpbrk(a->command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {
|
|
|
@ -433,9 +421,9 @@ static pid_t run(const struct init_action *a)
|
|
|
|
/* skip over the dash */
|
|
|
|
/* skip over the dash */
|
|
|
|
++cmdpath;
|
|
|
|
++cmdpath;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef WHY_WE_DO_THIS_SHELL_MUST_HANDLE_THIS_ITSELF
|
|
|
|
/* find the last component in the command pathname */
|
|
|
|
/* find the last component in the command pathname */
|
|
|
|
s = bb_get_last_path_component_nostrip(cmdpath);
|
|
|
|
s = bb_get_last_path_component_nostrip(cmdpath);
|
|
|
|
|
|
|
|
|
|
|
|
/* make a new argv[0] */
|
|
|
|
/* make a new argv[0] */
|
|
|
|
cmd[0] = malloc(strlen(s) + 2);
|
|
|
|
cmd[0] = malloc(strlen(s) + 2);
|
|
|
|
if (cmd[0] == NULL) {
|
|
|
|
if (cmd[0] == NULL) {
|
|
|
@ -445,16 +433,16 @@ static pid_t run(const struct init_action *a)
|
|
|
|
cmd[0][0] = '-';
|
|
|
|
cmd[0][0] = '-';
|
|
|
|
strcpy(cmd[0] + 1, s);
|
|
|
|
strcpy(cmd[0] + 1, s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#if ENABLE_FEATURE_INIT_SCTTY
|
|
|
|
#if ENABLE_FEATURE_INIT_SCTTY
|
|
|
|
/* Establish this process as session leader and
|
|
|
|
/* Establish this process as session leader and
|
|
|
|
* (attempt) to make the tty (if any) a controlling tty.
|
|
|
|
* _attempt_ to make stdin a controlling tty.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
setsid();
|
|
|
|
ioctl(0, TIOCSCTTY, 0 /*only try, don't steal*/);
|
|
|
|
ioctl(0, TIOCSCTTY, 0 /*don't steal it*/);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__)
|
|
|
|
|
|
|
|
if (a->action & ASKFIRST) {
|
|
|
|
if (a->action & ASKFIRST) {
|
|
|
|
static const char press_enter[] ALIGN1 =
|
|
|
|
static const char press_enter[] ALIGN1 =
|
|
|
|
#ifdef CUSTOMIZED_BANNER
|
|
|
|
#ifdef CUSTOMIZED_BANNER
|
|
|
@ -474,10 +462,10 @@ static pid_t run(const struct init_action *a)
|
|
|
|
"(pid %d, tty '%s')\n",
|
|
|
|
"(pid %d, tty '%s')\n",
|
|
|
|
cmdpath, getpid(), a->terminal);
|
|
|
|
cmdpath, getpid(), a->terminal);
|
|
|
|
full_write(1, press_enter, sizeof(press_enter) - 1);
|
|
|
|
full_write(1, press_enter, sizeof(press_enter) - 1);
|
|
|
|
while (read(0, &c, 1) == 1 && c != '\n')
|
|
|
|
while (safe_read(0, &c, 1) == 1 && c != '\n')
|
|
|
|
;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Log the process name and args */
|
|
|
|
/* Log the process name and args */
|
|
|
|
message(L_LOG, "starting pid %d, tty '%s': '%s'",
|
|
|
|
message(L_LOG, "starting pid %d, tty '%s': '%s'",
|
|
|
|
getpid(), a->terminal, cmdpath);
|
|
|
|
getpid(), a->terminal, cmdpath);
|
|
|
@ -504,22 +492,15 @@ static pid_t run(const struct init_action *a)
|
|
|
|
_exit(-1);
|
|
|
|
_exit(-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int waitfor(const struct init_action *a, pid_t pid)
|
|
|
|
static int waitfor(pid_t runpid)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int runpid;
|
|
|
|
|
|
|
|
int status, wpid;
|
|
|
|
int status, wpid;
|
|
|
|
|
|
|
|
|
|
|
|
runpid = (NULL == a)? pid : run(a);
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
while (1) {
|
|
|
|
wpid = waitpid(runpid, &status, 0);
|
|
|
|
wpid = waitpid(runpid, &status, 0);
|
|
|
|
if (wpid == runpid)
|
|
|
|
if (wpid == -1 && errno == EINTR)
|
|
|
|
break;
|
|
|
|
continue;
|
|
|
|
if (wpid == -1 && errno == ECHILD) {
|
|
|
|
break;
|
|
|
|
/* we missed its termination */
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME other errors should maybe trigger an error, but allow
|
|
|
|
|
|
|
|
* the program to continue */
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return wpid;
|
|
|
|
return wpid;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -534,9 +515,10 @@ static void run_actions(int action)
|
|
|
|
if (a->action == action) {
|
|
|
|
if (a->action == action) {
|
|
|
|
/* a->terminal of "" means "init's console" */
|
|
|
|
/* a->terminal of "" means "init's console" */
|
|
|
|
if (a->terminal[0] && access(a->terminal, R_OK | W_OK)) {
|
|
|
|
if (a->terminal[0] && access(a->terminal, R_OK | W_OK)) {
|
|
|
|
|
|
|
|
//message(L_LOG | L_CONSOLE, "Device %s cannot be opened in RW mode", a->terminal /*, strerror(errno)*/);
|
|
|
|
delete_init_action(a);
|
|
|
|
delete_init_action(a);
|
|
|
|
} else if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
|
|
|
|
} else if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
|
|
|
|
waitfor(a, 0);
|
|
|
|
waitfor(run(a));
|
|
|
|
delete_init_action(a);
|
|
|
|
delete_init_action(a);
|
|
|
|
} else if (a->action & ONCE) {
|
|
|
|
} else if (a->action & ONCE) {
|
|
|
|
run(a);
|
|
|
|
run(a);
|
|
|
@ -607,6 +589,29 @@ static void shutdown_system(void)
|
|
|
|
sleep(1);
|
|
|
|
sleep(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void shutdown_signal(int sig)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
const char *m;
|
|
|
|
|
|
|
|
int rb;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
shutdown_system();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m = "halt";
|
|
|
|
|
|
|
|
rb = RB_HALT_SYSTEM;
|
|
|
|
|
|
|
|
if (sig == SIGTERM) {
|
|
|
|
|
|
|
|
m = "reboot";
|
|
|
|
|
|
|
|
rb = RB_AUTOBOOT;
|
|
|
|
|
|
|
|
} else if (sig == SIGUSR2) {
|
|
|
|
|
|
|
|
m = "poweroff";
|
|
|
|
|
|
|
|
rb = RB_POWER_OFF;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
message(L_CONSOLE | L_LOG, "Requesting system %s", m);
|
|
|
|
|
|
|
|
/* allow time for last message to reach serial console */
|
|
|
|
|
|
|
|
sleep(2);
|
|
|
|
|
|
|
|
init_reboot(rb);
|
|
|
|
|
|
|
|
loop_forever();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void exec_signal(int sig ATTRIBUTE_UNUSED)
|
|
|
|
static void exec_signal(int sig ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct init_action *a, *tmp;
|
|
|
|
struct init_action *a, *tmp;
|
|
|
@ -632,7 +637,7 @@ static void exec_signal(int sig ATTRIBUTE_UNUSED)
|
|
|
|
sigprocmask(SIG_UNBLOCK, &unblock_signals, NULL);
|
|
|
|
sigprocmask(SIG_UNBLOCK, &unblock_signals, NULL);
|
|
|
|
|
|
|
|
|
|
|
|
/* Open the new terminal device */
|
|
|
|
/* Open the new terminal device */
|
|
|
|
open_stdio_to_tty(a->terminal, 0);
|
|
|
|
open_stdio_to_tty(a->terminal, 0 /* - shutdown_signal(SIGUSR1) [halt] if open fails */);
|
|
|
|
|
|
|
|
|
|
|
|
messageD(L_CONSOLE | L_LOG, "Trying to re-exec %s", a->command);
|
|
|
|
messageD(L_CONSOLE | L_LOG, "Trying to re-exec %s", a->command);
|
|
|
|
BB_EXECLP(a->command, a->command, NULL);
|
|
|
|
BB_EXECLP(a->command, a->command, NULL);
|
|
|
@ -646,29 +651,6 @@ static void exec_signal(int sig ATTRIBUTE_UNUSED)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void shutdown_signal(int sig)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
const char *m;
|
|
|
|
|
|
|
|
int rb;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
shutdown_system();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m = "halt";
|
|
|
|
|
|
|
|
rb = RB_HALT_SYSTEM;
|
|
|
|
|
|
|
|
if (sig == SIGTERM) {
|
|
|
|
|
|
|
|
m = "reboot";
|
|
|
|
|
|
|
|
rb = RB_AUTOBOOT;
|
|
|
|
|
|
|
|
} else if (sig == SIGUSR2) {
|
|
|
|
|
|
|
|
m = "poweroff";
|
|
|
|
|
|
|
|
rb = RB_POWER_OFF;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
message(L_CONSOLE | L_LOG, "Requesting system %s", m);
|
|
|
|
|
|
|
|
/* allow time for last message to reach serial console */
|
|
|
|
|
|
|
|
sleep(2);
|
|
|
|
|
|
|
|
init_reboot(rb);
|
|
|
|
|
|
|
|
loop_forever();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void ctrlaltdel_signal(int sig ATTRIBUTE_UNUSED)
|
|
|
|
static void ctrlaltdel_signal(int sig ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
run_actions(CTRLALTDEL);
|
|
|
|
run_actions(CTRLALTDEL);
|
|
|
@ -682,7 +664,7 @@ static void stop_handler(int sig ATTRIBUTE_UNUSED)
|
|
|
|
got_cont = 0;
|
|
|
|
got_cont = 0;
|
|
|
|
while (!got_cont)
|
|
|
|
while (!got_cont)
|
|
|
|
pause();
|
|
|
|
pause();
|
|
|
|
got_cont = 0;
|
|
|
|
|
|
|
|
errno = saved_errno;
|
|
|
|
errno = saved_errno;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -694,7 +676,7 @@ static void cont_handler(int sig ATTRIBUTE_UNUSED)
|
|
|
|
|
|
|
|
|
|
|
|
#endif /* !ENABLE_DEBUG_INIT */
|
|
|
|
#endif /* !ENABLE_DEBUG_INIT */
|
|
|
|
|
|
|
|
|
|
|
|
static void new_init_action(int action, const char *command, const char *cons)
|
|
|
|
static void new_init_action(uint8_t action, const char *command, const char *cons)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct init_action *new_action, *a, *last;
|
|
|
|
struct init_action *new_action, *a, *last;
|
|
|
|
|
|
|
|
|
|
|
@ -754,11 +736,21 @@ static void delete_init_action(struct init_action *action)
|
|
|
|
static void parse_inittab(void)
|
|
|
|
static void parse_inittab(void)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
#if ENABLE_FEATURE_USE_INITTAB
|
|
|
|
#if ENABLE_FEATURE_USE_INITTAB
|
|
|
|
|
|
|
|
static const char actions[] =
|
|
|
|
|
|
|
|
STR_SYSINIT "sysinit\0"
|
|
|
|
|
|
|
|
STR_RESPAWN "respawn\0"
|
|
|
|
|
|
|
|
STR_ASKFIRST "askfirst\0"
|
|
|
|
|
|
|
|
STR_WAIT "wait\0"
|
|
|
|
|
|
|
|
STR_ONCE "once\0"
|
|
|
|
|
|
|
|
STR_CTRLALTDEL "ctrlaltdel\0"
|
|
|
|
|
|
|
|
STR_SHUTDOWN "shutdown\0"
|
|
|
|
|
|
|
|
STR_RESTART "restart\0"
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
|
|
FILE *file;
|
|
|
|
FILE *file;
|
|
|
|
char buf[INIT_BUFFS_SIZE], lineAsRead[INIT_BUFFS_SIZE];
|
|
|
|
char buf[INIT_BUFFS_SIZE], lineAsRead[INIT_BUFFS_SIZE];
|
|
|
|
char tmpConsole[CONSOLE_NAME_SIZE];
|
|
|
|
char tmpConsole[CONSOLE_NAME_SIZE];
|
|
|
|
char *id, *runlev, *action, *command, *eol;
|
|
|
|
char *id, *runlev, *action, *command, *eol;
|
|
|
|
const struct init_action_type *a = actions;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
file = fopen(INITTAB, "r");
|
|
|
|
file = fopen(INITTAB, "r");
|
|
|
|
if (file == NULL) {
|
|
|
|
if (file == NULL) {
|
|
|
@ -769,7 +761,8 @@ static void parse_inittab(void)
|
|
|
|
/* Umount all filesystems on halt/reboot */
|
|
|
|
/* Umount all filesystems on halt/reboot */
|
|
|
|
new_init_action(SHUTDOWN, "umount -a -r", "");
|
|
|
|
new_init_action(SHUTDOWN, "umount -a -r", "");
|
|
|
|
/* Swapoff on halt/reboot */
|
|
|
|
/* Swapoff on halt/reboot */
|
|
|
|
if (ENABLE_SWAPONOFF) new_init_action(SHUTDOWN, "swapoff -a", "");
|
|
|
|
if (ENABLE_SWAPONOFF)
|
|
|
|
|
|
|
|
new_init_action(SHUTDOWN, "swapoff -a", "");
|
|
|
|
/* Prepare to restart init when a HUP is received */
|
|
|
|
/* Prepare to restart init when a HUP is received */
|
|
|
|
new_init_action(RESTART, "init", "");
|
|
|
|
new_init_action(RESTART, "init", "");
|
|
|
|
/* Askfirst shell on tty1-4 */
|
|
|
|
/* Askfirst shell on tty1-4 */
|
|
|
@ -785,6 +778,8 @@ static void parse_inittab(void)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
while (fgets(buf, INIT_BUFFS_SIZE, file) != NULL) {
|
|
|
|
while (fgets(buf, INIT_BUFFS_SIZE, file) != NULL) {
|
|
|
|
|
|
|
|
const char *a;
|
|
|
|
|
|
|
|
|
|
|
|
/* Skip leading spaces */
|
|
|
|
/* Skip leading spaces */
|
|
|
|
for (id = buf; *id == ' ' || *id == '\t'; id++);
|
|
|
|
for (id = buf; *id == ' ' || *id == '\t'; id++);
|
|
|
|
|
|
|
|
|
|
|
@ -832,8 +827,8 @@ static void parse_inittab(void)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Ok, now process it */
|
|
|
|
/* Ok, now process it */
|
|
|
|
for (a = actions; a->name != 0; a++) {
|
|
|
|
for (a = actions; a[0]; a += strlen(a) + 1) {
|
|
|
|
if (strcmp(a->name, action) == 0) {
|
|
|
|
if (strcmp(a + 1, action) == 0) {
|
|
|
|
if (*id != '\0') {
|
|
|
|
if (*id != '\0') {
|
|
|
|
if (strncmp(id, "/dev/", 5) == 0)
|
|
|
|
if (strncmp(id, "/dev/", 5) == 0)
|
|
|
|
id += 5;
|
|
|
|
id += 5;
|
|
|
@ -842,11 +837,11 @@ static void parse_inittab(void)
|
|
|
|
sizeof(tmpConsole) - 5);
|
|
|
|
sizeof(tmpConsole) - 5);
|
|
|
|
id = tmpConsole;
|
|
|
|
id = tmpConsole;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
new_init_action(a->action, command, id);
|
|
|
|
new_init_action((uint8_t)a[0], command, id);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (a->name == 0) {
|
|
|
|
if (!a[0]) {
|
|
|
|
/* Choke on an unknown action */
|
|
|
|
/* Choke on an unknown action */
|
|
|
|
message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);
|
|
|
|
message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -981,8 +976,11 @@ int init_main(int argc, char **argv)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_SELINUX */
|
|
|
|
#endif /* CONFIG_SELINUX */
|
|
|
|
|
|
|
|
|
|
|
|
/* Make the command line just say "init" -- thats all, nothing else */
|
|
|
|
/* Make the command line just say "init" - thats all, nothing else */
|
|
|
|
fixup_argv(argv);
|
|
|
|
strncpy(argv[0], "init", strlen(argv[0]));
|
|
|
|
|
|
|
|
/* Wipe argv[1]-argv[N] so they don't clutter the ps listing */
|
|
|
|
|
|
|
|
while (*++argv)
|
|
|
|
|
|
|
|
memset(*argv, 0, strlen(*argv));
|
|
|
|
|
|
|
|
|
|
|
|
/* Now run everything that needs to be run */
|
|
|
|
/* Now run everything that needs to be run */
|
|
|
|
|
|
|
|
|
|
|
|