init: add FEATURE_KILL_REMOVED (Eugene Bordenkircher <eugebo@gmail.com>)

init: slight size optimization
This commit is contained in:
Denis Vlasenko 2007-12-25 01:08:58 +00:00
parent 7b55c7f97d
commit ec5631b6d6
2 changed files with 73 additions and 62 deletions

View File

@ -27,6 +27,26 @@ config FEATURE_USE_INITTAB
help
Allow init to read an inittab file when the system boot.
config FEATURE_KILL_REMOVED
bool "Support killing processes that have been removed from inittab"
default y
depends on FEATURE_USE_INITTAB
help
When respawn entries are removed from inittab and a SIGHUP is
sent to init, this feature will kill the processes that have
been removed.
config FEATURE_KILL_DELAY
int "How long to wait between TERM and KILL (0 - send TERM only)"
range 0 1024
default 0
depends on FEATURE_KILL_REMOVED
help
With nonzero setting, init sends TERM, forks, child waits N
seconds, sends KILL and exits. Setting it too high is unwise
(child will hang around for too long and can actually kill
wrong process!)
config FEATURE_INIT_SCTTY
bool "Support running commands with a controlling-tty"
default n

View File

@ -738,21 +738,8 @@ static void delete_init_action(struct init_action *action)
static void parse_inittab(void)
{
#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;
char buf[INIT_BUFFS_SIZE], lineAsRead[INIT_BUFFS_SIZE];
char tmpConsole[CONSOLE_NAME_SIZE];
char *id, *runlev, *action, *command, *eol;
char buf[INIT_BUFFS_SIZE];
file = fopen(INITTAB, "r");
if (file == NULL) {
@ -780,57 +767,43 @@ static void parse_inittab(void)
}
while (fgets(buf, INIT_BUFFS_SIZE, file) != NULL) {
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"
;
char tmpConsole[CONSOLE_NAME_SIZE];
char *id, *runlev, *action, *command;
const char *a;
/* Skip leading spaces */
for (id = buf; *id == ' ' || *id == '\t'; id++);
id = skip_whitespace(buf);
/* Skip the line if it's a comment */
if (*id == '#' || *id == '\n')
continue;
/* Trim the trailing '\n' */
*strchrnul(id, '\n') = '\0';
/* Trim the trailing \n */
//XXX: chomp() ?
eol = strrchr(id, '\n');
if (eol != NULL)
*eol = '\0';
/* Keep a copy around for posterity's sake (and error msgs) */
strcpy(lineAsRead, buf);
/* Separate the ID field from the runlevels */
/* Line is: "id:runlevel_ignored:action:command" */
runlev = strchr(id, ':');
if (runlev == NULL || *(runlev + 1) == '\0') {
message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);
continue;
} else {
*runlev = '\0';
++runlev;
}
if (runlev == NULL /*|| runlev[1] == '\0' - not needed */)
goto bad_entry;
action = strchr(runlev + 1, ':');
if (action == NULL /*|| action[1] == '\0' - not needed */)
goto bad_entry;
command = strchr(action + 1, ':');
if (command == NULL || command[1] == '\0')
goto bad_entry;
/* Separate the runlevels from the action */
action = strchr(runlev, ':');
if (action == NULL || *(action + 1) == '\0') {
message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);
continue;
} else {
*action = '\0';
++action;
}
/* Separate the action from the command */
command = strchr(action, ':');
if (command == NULL || *(command + 1) == '\0') {
message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);
continue;
} else {
*command = '\0';
++command;
}
/* Ok, now process it */
*command = '\0'; /* action => ":action\0" now */
for (a = actions; a[0]; a += strlen(a) + 1) {
if (strcmp(a + 1, action) == 0) {
if (strcmp(a + 1, action + 1) == 0) {
*runlev = '\0';
if (*id != '\0') {
if (strncmp(id, "/dev/", 5) == 0)
id += 5;
@ -839,14 +812,15 @@ static void parse_inittab(void)
sizeof(tmpConsole) - 5);
id = tmpConsole;
}
new_init_action((uint8_t)a[0], command, id);
break;
new_init_action((uint8_t)a[0], command + 1, id);
goto next_line;
}
}
if (!a[0]) {
*command = ':';
/* Choke on an unknown action */
message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);
}
bad_entry:
message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", id);
next_line: ;
}
fclose(file);
#endif /* FEATURE_USE_INITTAB */
@ -866,6 +840,23 @@ static void reload_signal(int sig ATTRIBUTE_UNUSED)
parse_inittab();
#if ENABLE_FEATURE_KILL_REMOVED
for (a = init_action_list; a; a = a->next) {
pid_t pid = a->pid;
if ((a->action & ONCE) && pid != 0) {
/* Be nice and send SIGTERM first */
kill(pid, SIGTERM);
#if CONFIG_FEATURE_KILL_DELAY
if (fork() == 0) { /* child */
sleep(CONFIG_FEATURE_KILL_DELAY);
kill(pid, SIGKILL);
_exit(0);
}
#endif
}
}
#endif /* FEATURE_KILL_REMOVED */
/* remove unused entrys */
for (a = init_action_list; a; a = tmp) {
tmp = a->next;