mirror of
https://github.com/sheumann/hush.git
synced 2025-01-02 09:31:26 +00:00
init: remove superfluous forks and messing up with argv[0]
cttyhack: add stealing of ctty
This commit is contained in:
parent
191836845e
commit
2afabe8b83
@ -18,7 +18,8 @@ HOSTCFLAGS_usage.o = -I$(srctree)/include
|
|||||||
|
|
||||||
applets/applets.o: include/usage_compressed.h include/applet_tables.h
|
applets/applets.o: include/usage_compressed.h include/applet_tables.h
|
||||||
|
|
||||||
applets/usage: .config $(srctree)/applets/usage_compressed
|
applets/usage: .config $(srctree)/applets/usage_compressed
|
||||||
|
applets/applet_tables: .config
|
||||||
|
|
||||||
quiet_cmd_gen_usage_compressed = GEN include/usage_compressed.h
|
quiet_cmd_gen_usage_compressed = GEN include/usage_compressed.h
|
||||||
cmd_gen_usage_compressed = $(srctree)/applets/usage_compressed include/usage_compressed.h applets
|
cmd_gen_usage_compressed = $(srctree)/applets/usage_compressed include/usage_compressed.h applets
|
||||||
|
@ -365,7 +365,7 @@ this is a great mystery.
|
|||||||
becomes its controlling tty.
|
becomes its controlling tty.
|
||||||
</p><p>The BSD approach is that one has to explicitly call
|
</p><p>The BSD approach is that one has to explicitly call
|
||||||
</p><blockquote>
|
</p><blockquote>
|
||||||
<pre>ioctl(fd, TIOCSCTTY, ...);
|
<pre>ioctl(fd, TIOCSCTTY, 0/1);
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
@ -378,6 +378,8 @@ and (ii) it does not yet have a controlling tty, and
|
|||||||
(iii) maybe the tty should not already control some other session;
|
(iii) maybe the tty should not already control some other session;
|
||||||
if it does it is an error if we aren't root, or we steal the tty
|
if it does it is an error if we aren't root, or we steal the tty
|
||||||
if we are all-powerful.
|
if we are all-powerful.
|
||||||
|
[vda: correction: third parameter controls this: if 1, we steal tty from
|
||||||
|
any such session, if 0, we don't steal]
|
||||||
</p><p>Opening some terminal will give us a controlling tty,
|
</p><p>Opening some terminal will give us a controlling tty,
|
||||||
provided that (i) the current process is a session leader, and
|
provided that (i) the current process is a session leader, and
|
||||||
(ii) it does not yet have a controlling tty, and
|
(ii) it does not yet have a controlling tty, and
|
||||||
|
@ -37,6 +37,7 @@ config FEATURE_INIT_SCTTY
|
|||||||
controlling tty (TIOCSCTTY). This is not the traditional init
|
controlling tty (TIOCSCTTY). This is not the traditional init
|
||||||
behavour, but is often what you want in an embedded system where
|
behavour, but is often what you want in an embedded system where
|
||||||
the console is only accessed during development or for maintenance.
|
the console is only accessed during development or for maintenance.
|
||||||
|
NB: using cttyhack applet may work better.
|
||||||
|
|
||||||
config FEATURE_INIT_SYSLOG
|
config FEATURE_INIT_SYSLOG
|
||||||
bool "Enable init to write to syslog"
|
bool "Enable init to write to syslog"
|
||||||
|
246
init/init.c
246
init/init.c
@ -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 */
|
||||||
|
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
/* This code is adapted from busybox project
|
/* vi: set sw=4 ts=4: */
|
||||||
*
|
/*
|
||||||
* Licensed under GPLv2
|
* Licensed under GPLv2
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007 Denys Vlasenko <vda.linux@googlemail.com>
|
||||||
*/
|
*/
|
||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
|
|
||||||
/* From <linux/vt.h> */
|
/* From <linux/vt.h> */
|
||||||
struct vt_stat {
|
struct vt_stat {
|
||||||
unsigned short v_active; /* active vt */
|
unsigned short v_active; /* active vt */
|
||||||
unsigned short v_signal; /* signal to send */
|
unsigned short v_signal; /* signal to send */
|
||||||
unsigned short v_state; /* vt bitmask */
|
unsigned short v_state; /* vt bitmask */
|
||||||
};
|
};
|
||||||
enum { VT_GETSTATE = 0x5603 }; /* get global vt state info */
|
enum { VT_GETSTATE = 0x5603 }; /* get global vt state info */
|
||||||
|
|
||||||
/* From <linux/serial.h> */
|
/* From <linux/serial.h> */
|
||||||
struct serial_struct {
|
struct serial_struct {
|
||||||
@ -26,8 +28,8 @@ struct serial_struct {
|
|||||||
char io_type;
|
char io_type;
|
||||||
char reserved_char[1];
|
char reserved_char[1];
|
||||||
int hub6;
|
int hub6;
|
||||||
unsigned short closing_wait; /* time to wait before closing */
|
unsigned short closing_wait; /* time to wait before closing */
|
||||||
unsigned short closing_wait2; /* no longer used... */
|
unsigned short closing_wait2; /* no longer used... */
|
||||||
unsigned char *iomem_base;
|
unsigned char *iomem_base;
|
||||||
unsigned short iomem_reg_shift;
|
unsigned short iomem_reg_shift;
|
||||||
unsigned int port_high;
|
unsigned int port_high;
|
||||||
@ -66,8 +68,10 @@ int cttyhack_main(int argc, char **argv)
|
|||||||
dup2(fd, 1);
|
dup2(fd, 1);
|
||||||
dup2(fd, 2);
|
dup2(fd, 2);
|
||||||
while (fd > 2) close(fd--);
|
while (fd > 2) close(fd--);
|
||||||
|
/* Some other session may have it as ctty. Steal it from them */
|
||||||
|
ioctl(0, TIOCSCTTY, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
execvp(argv[0], argv);
|
BB_EXECVP(argv[0], argv);
|
||||||
bb_perror_msg_and_die("cannot exec '%s'", argv[0]);
|
bb_perror_msg_and_die("cannot exec '%s'", argv[0]);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user