init: add FEATURE_KILL_REMOVED (Eugene Bordenkircher <eugebo@gmail.com>)
authorDenis Vlasenko <vda.linux@googlemail.com>
Tue, 25 Dec 2007 01:08:58 +0000 (01:08 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Tue, 25 Dec 2007 01:08:58 +0000 (01:08 -0000)
init: slight size optimization

init/Config.in
init/init.c

index 318f523a0dca436a4681fd8688fc3f583e689b05..1084de9055b607375e0c62744669d546476686c9 100644 (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
index baa5a50009470f6476ae0908f011bd186b4963c9..e6581880c18ecd381056b029027dd86bb97d0478 100644 (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;
-               }
-
-               /* 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 */
+               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;
+
+               *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]) {
-                       /* Choke on an unknown action */
-                       message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);
-               }
+               *command = ':';
+               /* Choke on an unknown action */
+ bad_entry:
+               message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", id);
+ next_line: ;
        }
        fclose(file);
 #endif /* FEATURE_USE_INITTAB */
@@ -860,12 +834,29 @@ static void reload_signal(int sig ATTRIBUTE_UNUSED)
        message(L_LOG, "reloading /etc/inittab");
 
        /* disable old entrys */
-       for (a = init_action_list; a; a = a->next ) {
+       for (a = init_action_list; a; a = a->next) {
                a->action = ONCE;
        }
 
        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;