"Fossies" - the Fresh Open Source Software Archive

Member "sysvinit-2.99/src/init.c" (21 Feb 2021, 71044 Bytes) of package /linux/misc/sysvinit-2.99.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "init.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.98_vs_2.99.

    1 /*
    2  * Init     A System-V Init Clone.
    3  *
    4  * Usage:   /sbin/init
    5  *           init [0123456SsQqAaBbCc]
    6  *        telinit [0123456SsQqAaBbCc]
    7  *
    8  * Version: @(#)init.c  2.86  30-Jul-2004  miquels@cistron.nl
    9  * Version:     init.c 2.90 18-Jun-2018 jsmith@resonatingmedia.com
   10  */
   11 
   12 /*
   13 Version information is not placed in the top-level Makefile by default
   14 */
   15 #ifndef VERSION
   16 #define VERSION "2.94"
   17 #endif
   18 /*
   19  *      This file is part of the sysvinit suite,
   20  *      Copyright (C) 1991-2004 Miquel van Smoorenburg.
   21  *      Copyright (C) 2017-2019 Jesse Smith
   22  *
   23  *      This program is free software; you can redistribute it and/or modify
   24  *      it under the terms of the GNU General Public License as published by
   25  *      the Free Software Foundation; either version 2 of the License, or
   26  *      (at your option) any later version.
   27  *
   28  *      This program is distributed in the hope that it will be useful,
   29  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
   30  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   31  *      GNU General Public License for more details.
   32  *
   33  *      You should have received a copy of the GNU General Public License
   34  *      along with this program; if not, write to the Free Software
   35  *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   36  *
   37  */
   38 
   39 #include <sys/types.h>
   40 #include <sys/stat.h>
   41 #include <sys/ioctl.h>
   42 #include <sys/wait.h>
   43 #ifdef __linux__
   44 #include <sys/kd.h>
   45 #endif
   46 #include <sys/resource.h>
   47 #include <stdlib.h>
   48 #include <unistd.h>
   49 #include <errno.h>
   50 #include <stdio.h>
   51 #include <time.h>
   52 #include <fcntl.h>
   53 #include <string.h>
   54 #include <signal.h>
   55 #include <termios.h>
   56 #ifdef __FreeBSD__
   57 #include <utmpx.h>
   58 #else
   59 #include <utmp.h>
   60 #endif
   61 #include <ctype.h>
   62 #include <stdarg.h>
   63 #include <sys/ttydefaults.h>
   64 #include <sys/syslog.h>
   65 #include <sys/time.h>
   66 /*
   67  * inittab.d
   68  */
   69 #include <sys/types.h>
   70 #include <dirent.h>
   71 
   72 #ifdef WITH_SELINUX
   73 #  include <selinux/selinux.h>
   74 #endif
   75 #ifdef __FreeBSD__
   76 extern char **environ;
   77 #endif
   78 
   79 #ifdef __i386__
   80 #  ifdef __GLIBC__
   81      /* GNU libc 2.x */
   82 #    define STACK_DEBUG 1
   83 #    if (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
   84        /* Only glibc 2.0 needs this */
   85 #      include <sigcontext.h>
   86 #    elif ( __GLIBC__ > 2) && ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1))
   87 #      include <bits/sigcontext.h>
   88 #    endif
   89 #  endif
   90 #endif
   91 
   92 #include "init.h"
   93 #include "initreq.h"
   94 #include "paths.h"
   95 #include "reboot.h"
   96 #include "runlevellog.h"
   97 #include "set.h"
   98 
   99 #ifndef SIGPWR
  100 #  define SIGPWR SIGUSR2
  101 #endif
  102 
  103 #ifndef CBAUD
  104 #  define CBAUD     0
  105 #endif
  106 #ifndef CBAUDEX
  107 #  define CBAUDEX   0
  108 #endif
  109 
  110 /* Set a signal handler. */
  111 #define SETSIG(sa, sig, fun, flags) \
  112         do { \
  113             memset(&sa, 0, sizeof(sa)); \
  114             sa.sa_handler = fun; \
  115             sa.sa_flags = flags; \
  116             sigemptyset(&sa.sa_mask); \
  117             sigaction(sig, &sa, NULL); \
  118         } while(0)
  119 
  120 /* Version information */
  121 char *Version = "@(#) init " VERSION " miquels@cistron.nl";
  122 char *bootmsg = "version " VERSION " %s";
  123 #define E_VERSION "INIT_VERSION=sysvinit-" VERSION
  124 
  125 CHILD *family = NULL;       /* The linked list of all entries */
  126 CHILD *newFamily = NULL;    /* The list after inittab re-read */
  127 
  128 CHILD ch_emerg = {      /* Emergency shell */
  129     WAITING, 0, 0, 0, 0,
  130     "~~",
  131     "S",
  132     3,
  133     "/sbin/sulogin",
  134     NULL,
  135     NULL
  136 };
  137 
  138 char runlevel = 'S';        /* The current run level */
  139 char thislevel = 'S';       /* The current runlevel */
  140 char prevlevel = 'N';       /* Previous runlevel */
  141 int dfl_level = 0;      /* Default runlevel */
  142 sig_atomic_t got_cont = 0;  /* Set if we received the SIGCONT signal */
  143 sig_atomic_t got_signals;   /* Set if we received a signal. */
  144 int emerg_shell = 0;        /* Start emergency shell? */
  145 int wrote_wtmp_reboot = 1;  /* Set when we wrote the reboot record */
  146 int wrote_utmp_reboot = 1;  /* Set when we wrote the reboot record */
  147 int wrote_wtmp_rlevel = 1;  /* Set when we wrote the runlevel record */
  148 int wrote_utmp_rlevel = 1;  /* Set when we wrote the runlevel record */
  149 int sleep_time = WAIT_BETWEEN_SIGNALS;    /* Sleep time between TERM and KILL */
  150 char *argv0;            /* First arguments; show up in ps listing */
  151 int maxproclen;         /* Maximal length of argv[0] with \0 */
  152 struct utmp utproto;        /* Only used for sizeof(utproto.ut_id) */
  153 char *console_dev;      /* Console device. */
  154 int pipe_fd = -1;       /* /run/initctl */
  155 int did_boot = 0;       /* Did we already do BOOT* stuff? */
  156 int main(int, char **);
  157 
  158 /*  Used by re-exec part */
  159 int reload = 0;         /* Should we do initialization stuff? */
  160 char *myname=INIT;      /* What should we exec */
  161 int oops_error;         /* Used by some of the re-exec code. */
  162 const char *Signature = "12567362"; /* Signature for re-exec fd */
  163 
  164 /* Macro to see if this is a special action */
  165 #define ISPOWER(i) ((i) == POWERWAIT || (i) == POWERFAIL || \
  166             (i) == POWEROKWAIT || (i) == POWERFAILNOW || \
  167             (i) == CTRLALTDEL)
  168 
  169 /* ascii values for the `action' field. */
  170 struct actions {
  171   char *name;
  172   int act;
  173 } actions[] = {
  174   { "respawn",     RESPAWN  },
  175   { "wait",    WAIT     },
  176   { "once",    ONCE     },
  177   { "boot",    BOOT     },
  178   { "bootwait",    BOOTWAIT },
  179   { "powerfail",   POWERFAIL    },
  180   { "powerfailnow",POWERFAILNOW },
  181   { "powerwait",   POWERWAIT    },
  182   { "powerokwait", POWEROKWAIT  },
  183   { "ctrlaltdel",  CTRLALTDEL   },
  184   { "off",     OFF      },
  185   { "ondemand",    ONDEMAND },
  186   { "initdefault", INITDEFAULT  },
  187   { "sysinit",     SYSINIT  },
  188   { "kbrequest",   KBREQUEST    },
  189   { NULL,      0        },
  190 };
  191 
  192 /*
  193  *  State parser token table (see receive_state)
  194  */
  195 struct {
  196   char name[4]; 
  197   int cmd;
  198 } cmds[] = {
  199   { "VER",     C_VER    },
  200   { "END",     C_END    },
  201   { "REC",     C_REC    },
  202   { "EOR",     C_EOR    },
  203   { "LEV",     C_LEV    },
  204   { "FL ",     C_FLAG   },
  205   { "AC ",     C_ACTION },
  206   { "CMD",     C_PROCESS    },
  207   { "PID",     C_PID    },
  208   { "EXS",     C_EXS    },
  209   { "-RL",     D_RUNLEVEL   },
  210   { "-TL",     D_THISLEVEL  },
  211   { "-PL",     D_PREVLEVEL  },
  212   { "-SI",     D_GOTSIGN    },
  213   { "-WR",     D_WROTE_WTMP_REBOOT},
  214   { "-WU",     D_WROTE_UTMP_REBOOT},
  215   { "-ST",     D_SLTIME },
  216   { "-DB",     D_DIDBOOT    },
  217   { "-LW",     D_WROTE_WTMP_RLEVEL},
  218   { "-LU",     D_WROTE_UTMP_RLEVEL},
  219   { "",        0        }
  220 };
  221 struct {
  222     char *name;
  223     int mask;
  224 } flags[]={
  225     {"RU",RUNNING},
  226     {"DE",DEMAND},
  227     {"XD",XECUTED},
  228     {"WT",WAITING},
  229     {NULL,0}
  230 };
  231 
  232 #define NR_EXTRA_ENV    16
  233 char *extra_env[NR_EXTRA_ENV];
  234 
  235 #define MINI_SLEEP 10      /* ten milliseconds */
  236 #define SHORT_SLEEP 5000   /* five seconds */
  237 #define LONG_SLEEP 30000   /* 30 seconds sleep to deal with memory issues*/
  238 
  239 /*
  240  *  Sleep a number of milliseconds.
  241  *
  242  *  This only works correctly because Linux select updates
  243  *  the elapsed time in the struct timeval passed to select!
  244  */
  245 static
  246 void do_msleep(int msec)
  247 {
  248     struct timeval tv;
  249 
  250     tv.tv_sec = msec / 1000;
  251     tv.tv_usec = (msec % 1000) * 1000;
  252 
  253     while(select(0, NULL, NULL, NULL, &tv) < 0 && errno == EINTR)
  254         ;
  255 }
  256 
  257 
  258 /*
  259  *  Non-failing allocation routines (init cannot fail).
  260  */
  261 static
  262 void *imalloc(size_t size)
  263 {
  264     void    *m;
  265 
  266     while ((m = malloc(size)) == NULL) {
  267         initlog(L_VB, "out of memory");
  268         do_msleep(SHORT_SLEEP);
  269     }
  270     memset(m, 0, size);
  271     return m;
  272 }
  273 
  274 static
  275 char *istrdup(const char *s)
  276 {
  277     char    *m;
  278     int l;
  279 
  280     l = strlen(s) + 1;
  281     m = imalloc(l);
  282     memcpy(m, s, l);
  283     return m;
  284 }
  285 
  286 
  287 /*
  288  *  Send the state info of the previous running init to
  289  *  the new one, in a version-independant way.
  290  */
  291 static
  292 void send_state(int fd)
  293 {
  294     FILE    *fp;
  295     CHILD   *p;
  296     int i,val;
  297 
  298     fp = fdopen(fd,"w");
  299 
  300     fprintf(fp, "VER%s\n", Version);
  301     fprintf(fp, "-RL%c\n", runlevel);
  302     fprintf(fp, "-TL%c\n", thislevel);
  303     fprintf(fp, "-PL%c\n", prevlevel);
  304     fprintf(fp, "-SI%u\n", got_signals);
  305     fprintf(fp, "-WR%d\n", wrote_wtmp_reboot);
  306     fprintf(fp, "-WU%d\n", wrote_utmp_reboot);
  307     fprintf(fp, "-ST%d\n", sleep_time);
  308     fprintf(fp, "-DB%d\n", did_boot);
  309 
  310     for (p = family; p; p = p->next) {
  311         fprintf(fp, "REC%s\n", p->id);
  312         fprintf(fp, "LEV%s\n", p->rlevel);
  313         for (i = 0, val = p->flags; flags[i].mask; i++)
  314             if (val & flags[i].mask) {
  315                 val &= ~flags[i].mask;
  316                 fprintf(fp, "FL %s\n",flags[i].name);
  317             }
  318         fprintf(fp, "PID%d\n",p->pid);
  319         fprintf(fp, "EXS%u\n",p->exstat);
  320         for(i = 0; actions[i].act; i++)
  321             if (actions[i].act == p->action) {
  322                 fprintf(fp, "AC %s\n", actions[i].name);
  323                 break;
  324             }
  325         fprintf(fp, "CMD%s\n", p->process);
  326         fprintf(fp, "EOR\n");
  327     }
  328     fprintf(fp, "END\n");
  329     fclose(fp);
  330 }
  331 
  332 /*
  333  *  Read a string from a file descriptor.
  334  *  Q: why not use fgets() ?
  335  *      A: Answer: looked into this. Turns out after all the checks
  336  *      required in the fgets() approach (removing newline, read errors, etc)
  337  *      the function is longer and takes approximately the same amount of
  338  *      time to do one big fgets and checks as it does to do a pile of getcs.
  339  *      We don't benefit from switching.
  340  *      - Jesse
  341  */
  342 static int get_string(char *p, int size, FILE *f)
  343 {
  344     int c;
  345 
  346     while ((c = getc(f)) != EOF && c != '\n') {
  347         if (--size > 0)
  348             *p++ = c;
  349     }
  350     *p = '\0';
  351     return (c != EOF) && (size > 0);
  352 }
  353 
  354 /*
  355  *  Read trailing data from the state pipe until we see a newline.
  356  */
  357 static int get_void(FILE *f)
  358 {
  359     int c;
  360 
  361     while ((c = getc(f)) != EOF && c != '\n')
  362         ;
  363 
  364     return (c != EOF);
  365 }
  366 
  367 /*
  368  *  Read the next "command" from the state pipe.
  369  */
  370 static int get_cmd(FILE *f)
  371 {
  372     char    cmd[4] = "   ";
  373     int i;
  374 
  375     if (fread(cmd, 1, sizeof(cmd) - 1, f) != sizeof(cmd) - 1)
  376         return C_EOF;
  377 
  378     for(i = 0; cmds[i].cmd && strcmp(cmds[i].name, cmd) != 0; i++)
  379         ;
  380     return cmds[i].cmd;
  381 }
  382 
  383 /*
  384  *  Read a CHILD * from the state pipe.
  385  */
  386 static CHILD *get_record(FILE *f)
  387 {
  388     int cmd;
  389     char    s[32];
  390     int i;
  391     CHILD   *p;
  392 
  393     do {
  394         errno = 0;
  395         switch (cmd = get_cmd(f)) {
  396             case C_END:
  397                 get_void(f);
  398                 return NULL;
  399             case 0:
  400                 get_void(f);
  401                 break;
  402             case C_REC:
  403                 break;
  404             case D_RUNLEVEL:
  405                 if (fscanf(f, "%c\n", &runlevel) == EOF && errno != 0) {
  406                     fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
  407                 }
  408                 break;
  409             case D_THISLEVEL:
  410                 if (fscanf(f, "%c\n", &thislevel) == EOF && errno != 0) {
  411                     fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
  412                 }
  413                 break;
  414             case D_PREVLEVEL:
  415                 if (fscanf(f, "%c\n", &prevlevel) == EOF && errno != 0) {
  416                     fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
  417                 }
  418                 break;
  419             case D_GOTSIGN:
  420                 if (fscanf(f, "%u\n", &got_signals) == EOF && errno != 0) {
  421                     fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
  422                 }
  423                 break;
  424             case D_WROTE_WTMP_REBOOT:
  425                 if (fscanf(f, "%d\n", &wrote_wtmp_reboot) == EOF && errno != 0) {
  426                     fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
  427                 }
  428                 break;
  429             case D_WROTE_UTMP_REBOOT:
  430                 if (fscanf(f, "%d\n", &wrote_utmp_reboot) == EOF && errno != 0) {
  431                     fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
  432                 }
  433                 break;
  434             case D_SLTIME:
  435                 if (fscanf(f, "%d\n", &sleep_time) == EOF && errno != 0) {
  436                     fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
  437                 }
  438                 break;
  439             case D_DIDBOOT:
  440                 if (fscanf(f, "%d\n", &did_boot) == EOF && errno != 0) {
  441                     fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
  442                 }
  443                 break;
  444             case D_WROTE_WTMP_RLEVEL:
  445                 if (fscanf(f, "%d\n", &wrote_wtmp_rlevel) == EOF && errno != 0) {
  446                     fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
  447                 }
  448                 break;
  449             case D_WROTE_UTMP_RLEVEL:
  450                 if (fscanf(f, "%d\n", &wrote_utmp_rlevel) == EOF && errno != 0) {
  451                     fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
  452                 }
  453                 break;
  454             default:
  455                 if (cmd > 0 || cmd == C_EOF) {
  456                     oops_error = -1;
  457                     return NULL;
  458                 }
  459         }
  460     } while (cmd != C_REC);
  461 
  462     p = imalloc(sizeof(CHILD));
  463     get_string(p->id, sizeof(p->id), f);
  464 
  465     do switch(cmd = get_cmd(f)) {
  466         case 0:
  467         case C_EOR:
  468             get_void(f);
  469             break;
  470         case C_PID:
  471             if (fscanf(f, "%d\n", &(p->pid)) == EOF && errno != 0) {
  472                 fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
  473             }
  474             break;
  475         case C_EXS:
  476             if (fscanf(f, "%u\n", &(p->exstat)) == EOF && errno != 0) {
  477                 fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno));
  478             }
  479             break;
  480         case C_LEV:
  481             get_string(p->rlevel, sizeof(p->rlevel), f);
  482             break;
  483         case C_PROCESS:
  484             get_string(p->process, sizeof(p->process), f);
  485             break;
  486         case C_FLAG:
  487             get_string(s, sizeof(s), f);
  488             for(i = 0; flags[i].name; i++) {
  489                 if (strcmp(flags[i].name,s) == 0)
  490                     break;
  491             }
  492             p->flags |= flags[i].mask;
  493             break;
  494         case C_ACTION:
  495             get_string(s, sizeof(s), f);
  496             for(i = 0; actions[i].name; i++) {
  497                 if (strcmp(actions[i].name, s) == 0)
  498                     break;
  499             }
  500             p->action = actions[i].act ? actions[i].act : OFF;
  501             break;
  502         default:
  503             free(p);
  504             oops_error = -1;
  505             return NULL;
  506     } while( cmd != C_EOR);
  507 
  508     return p;
  509 }
  510 
  511 /*
  512  *  Read the complete state info from the state pipe.
  513  *  Returns 0 on success
  514  */
  515 static
  516 int receive_state(int fd)
  517 {
  518     FILE    *f;
  519     char    old_version[256];
  520     CHILD   **pp;
  521 
  522     f = fdopen(fd, "r");
  523 
  524     if (get_cmd(f) != C_VER) {
  525         fclose(f);
  526         return -1;
  527     }
  528     get_string(old_version, sizeof(old_version), f);
  529     oops_error = 0;
  530     for (pp = &family; (*pp = get_record(f)) != NULL; pp = &((*pp)->next))
  531         ;
  532     fclose(f);
  533     return oops_error;
  534 }
  535 
  536 /*
  537  *  Set the process title.
  538  */
  539 #ifdef __GNUC__
  540 #ifndef __FreeBSD__
  541 __attribute__ ((format (printf, 1, 2)))
  542 #endif
  543 #endif
  544 /* This function already exists on FreeBSD. No need to declare it. */
  545 #ifndef __FreeBSD__
  546 static int setproctitle(char *fmt, ...)
  547 {
  548     va_list ap;
  549     int len;
  550     char buf[256];
  551 
  552     buf[0] = 0;
  553 
  554     va_start(ap, fmt);
  555     len = vsnprintf(buf, sizeof(buf), fmt, ap);
  556     va_end(ap);
  557 
  558     if (maxproclen > 1) {
  559         memset(argv0, 0, maxproclen);
  560         strncpy(argv0, buf, maxproclen - 1);
  561     }
  562 
  563     return len;
  564 }
  565 #endif
  566 
  567 /*
  568  *  Set console_dev to a working console.
  569  */
  570 static
  571 void console_init(void)
  572 {
  573     int fd;
  574     int tried_devcons = 0;
  575     int tried_vtmaster = 0;
  576     char *s;
  577 
  578     if ((s = getenv("CONSOLE")) != NULL)
  579         console_dev = s;
  580     else {
  581         console_dev = CONSOLE;
  582         tried_devcons++;
  583     }
  584 
  585     while ((fd = open(console_dev, O_RDONLY|O_NONBLOCK)) < 0) {
  586         if (!tried_devcons) {
  587             tried_devcons++;
  588             console_dev = CONSOLE;
  589             continue;
  590         }
  591         if (!tried_vtmaster) {
  592             tried_vtmaster++;
  593             console_dev = VT_MASTER;
  594             continue;
  595         }
  596         break;
  597     }
  598     if (fd < 0)
  599         console_dev = "/dev/null";
  600     else
  601         close(fd);
  602 }
  603 
  604 
  605 /*
  606  *  Open the console with retries.
  607  */
  608 static
  609 int console_open(int mode)
  610 {
  611     int f, fd = -1;
  612     int m;
  613 
  614     /*
  615      *  Open device in nonblocking mode.
  616      */
  617     m = mode | O_NONBLOCK;
  618 
  619     /*
  620      *  Retry the open five times.
  621      */
  622     for(f = 0; f < 5; f++) {
  623         if ((fd = open(console_dev, m)) >= 0) break;
  624         usleep(10000);
  625     }
  626 
  627     if (fd < 0) return fd;
  628 
  629     /*
  630      *  Set original flags.
  631      */
  632     if (m != mode)
  633         fcntl(fd, F_SETFL, mode);
  634     return fd;
  635 }
  636 
  637 /*
  638  *  We got a signal (HUP PWR WINCH ALRM INT)
  639  */
  640 static
  641 void signal_handler(int sig)
  642 {
  643     ADDSET(got_signals, sig);
  644 }
  645 
  646 /*
  647  *  SIGCHLD: one of our children has died.
  648  */
  649 static
  650 # ifdef __GNUC__
  651 void chld_handler(int sig __attribute__((unused)))
  652 # else
  653 void chld_handler(int sig)
  654 # endif
  655 {
  656     CHILD       *ch;
  657     int     pid, st;
  658     int     saved_errno = errno;
  659 
  660     /*
  661      *  Find out which process(es) this was (were)
  662      */
  663     while((pid = waitpid(-1, &st, WNOHANG)) != 0) {
  664         if (errno == ECHILD) break;
  665         for( ch = family; ch; ch = ch->next )
  666             if ( ch->pid == pid && (ch->flags & RUNNING) ) {
  667                 INITDBG(L_VB,
  668                     "chld_handler: marked %d as zombie",
  669                     ch->pid);
  670                 ADDSET(got_signals, SIGCHLD);
  671                 ch->exstat = st;
  672                 ch->flags |= ZOMBIE;
  673                 if (ch->new) {
  674                     ch->new->exstat = st;
  675                     ch->new->flags |= ZOMBIE;
  676                 }
  677                 break;
  678             }
  679         if (ch == NULL) {
  680             INITDBG(L_VB, "chld_handler: unknown child %d exited.",
  681                 pid);
  682         }
  683     }
  684     errno = saved_errno;
  685 }
  686 
  687 /*
  688  *  Linux ignores all signals sent to init when the
  689  *  SIG_DFL handler is installed. Therefore we must catch SIGTSTP
  690  *  and SIGCONT, or else they won't work....
  691  *
  692  *  The SIGCONT handler
  693  */
  694 static
  695 # ifdef __GNUC__
  696 void cont_handler(int sig __attribute__((unused)))
  697 # else
  698 void cont_handler(int sig)
  699 # endif
  700 {
  701     got_cont = 1;
  702 }
  703 
  704 /*
  705  *  Fork and dump core in /.
  706  */
  707 static
  708 void coredump(void)
  709 {
  710     static int      dumped = 0;
  711     struct rlimit       rlim;
  712     sigset_t        mask;
  713 
  714     if (dumped) return;
  715     dumped = 1;
  716 
  717     if (fork() != 0) return;
  718 
  719     sigfillset(&mask);
  720     sigprocmask(SIG_SETMASK, &mask, NULL);
  721 
  722     rlim.rlim_cur = RLIM_INFINITY;
  723     rlim.rlim_max = RLIM_INFINITY;
  724     setrlimit(RLIMIT_CORE, &rlim);
  725     if (0 != chdir("/"))
  726         initlog(L_VB, "unable to chdir to /: %s",
  727             strerror(errno));
  728 
  729     signal(SIGSEGV, SIG_DFL);
  730     raise(SIGSEGV);
  731     sigdelset(&mask, SIGSEGV);
  732     sigprocmask(SIG_SETMASK, &mask, NULL);
  733 
  734     do_msleep(SHORT_SLEEP);
  735     exit(0);
  736 }
  737 
  738 /*
  739  *  OOPS: segmentation violation!
  740  *  If we have the info, print where it occurred.
  741  *  Then sleep 30 seconds and try to continue.
  742  */
  743 static
  744 #if defined(STACK_DEBUG) && defined(__linux__)
  745 # ifdef __GNUC__
  746 void segv_handler(int sig __attribute__((unused)), struct sigcontext ctx)
  747 # else
  748 void segv_handler(int sig, struct sigcontext ctx)
  749 # endif
  750 {
  751     char    *p = "";
  752     int saved_errno = errno;
  753 
  754     if ((void *)ctx.eip >= (void *)do_msleep &&
  755         (void *)ctx.eip < (void *)main)
  756         p = " (code)";
  757     initlog(L_VB, "PANIC: segmentation violation at %p%s! "
  758           "sleeping for 30 seconds.", (void *)ctx.eip, p);
  759     coredump();
  760     do_msleep(LONG_SLEEP);
  761     errno = saved_errno;
  762 }
  763 #else
  764 # ifdef __GNUC__
  765 void segv_handler(int sig __attribute__((unused)))
  766 # else
  767 void segv_handler(int sig)
  768 # endif
  769 {
  770     int saved_errno = errno;
  771 
  772     initlog(L_VB,
  773         "PANIC: segmentation violation! sleeping for 30 seconds.");
  774     coredump();
  775     do_msleep(LONG_SLEEP);
  776     errno = saved_errno;
  777 }
  778 #endif
  779 
  780 /*
  781  *  The SIGSTOP & SIGTSTP handler
  782  */
  783 static
  784 # ifdef __GNUC__
  785 void stop_handler(int sig __attribute__((unused)))
  786 # else
  787 void stop_handler(int sig)
  788 # endif
  789 {
  790     int saved_errno = errno;
  791 
  792     got_cont = 0;
  793     while(!got_cont) pause();
  794     got_cont = 0;
  795     errno = saved_errno;
  796 }
  797 
  798 /*
  799  *  Set terminal settings to reasonable defaults
  800  */
  801 static
  802 void console_stty(void)
  803 {
  804     struct termios tty;
  805     int fd;
  806 
  807     if ((fd = console_open(O_RDWR|O_NOCTTY)) < 0) {
  808         initlog(L_VB, "can't open %s", console_dev);
  809         return;
  810     }
  811 
  812 #ifdef __FreeBSD_kernel__
  813     /*
  814      * The kernel of FreeBSD expects userland to set TERM.  Usually, we want
  815      * "xterm".  Later, gettys might disagree on this (i.e. we're not using
  816      * syscons) but some boot scripts, like /etc/init.d/xserver-xorg, still
  817      * need a non-dumb terminal.
  818      */
  819     putenv ("TERM=xterm");
  820 #endif
  821 
  822     (void) tcgetattr(fd, &tty);
  823 
  824     tty.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD;
  825     tty.c_cflag |= HUPCL|CLOCAL|CREAD;
  826 
  827     tty.c_cc[VINTR]     = CINTR;
  828     tty.c_cc[VQUIT]     = CQUIT;
  829     tty.c_cc[VERASE]    = CERASE; /* ASCII DEL (0177) */
  830     tty.c_cc[VKILL]     = CKILL;
  831     tty.c_cc[VEOF]      = CEOF;
  832     tty.c_cc[VTIME]     = 0;
  833     tty.c_cc[VMIN]      = 1;
  834 #ifdef VSWTC /* not defined on FreeBSD */
  835     tty.c_cc[VSWTC]     = _POSIX_VDISABLE;
  836 #endif /* VSWTC */
  837     tty.c_cc[VSTART]    = CSTART;
  838     tty.c_cc[VSTOP]     = CSTOP;
  839     tty.c_cc[VSUSP]     = CSUSP;
  840     tty.c_cc[VEOL]      = _POSIX_VDISABLE;
  841     tty.c_cc[VREPRINT]  = CREPRINT;
  842     tty.c_cc[VDISCARD]  = CDISCARD;
  843     tty.c_cc[VWERASE]   = CWERASE;
  844     tty.c_cc[VLNEXT]    = CLNEXT;
  845     tty.c_cc[VEOL2]     = _POSIX_VDISABLE;
  846 
  847     /*
  848      *  Set pre and post processing
  849      */
  850     tty.c_iflag = IGNPAR|ICRNL|IXON|IXANY
  851 #ifdef IUTF8    /* Not defined on FreeBSD */
  852             | (tty.c_iflag & IUTF8)
  853 #endif /* IUTF8 */
  854         ;
  855     tty.c_oflag = OPOST|ONLCR;
  856     tty.c_lflag = ISIG|ICANON|ECHO|ECHOCTL|ECHOE|ECHOKE;
  857 
  858 #if defined(SANE_TIO) && (SANE_TIO == 1)
  859     /*
  860      *  Disable flow control (-ixon), ignore break (ignbrk),
  861      *  and make nl/cr more usable (sane).
  862      */
  863     tty.c_iflag |=  IGNBRK;
  864     tty.c_iflag &= ~(BRKINT|INLCR|IGNCR|IXON);
  865     tty.c_oflag &= ~(OCRNL|ONLRET);
  866 #endif
  867     /*
  868      *  Now set the terminal line.
  869      *  We don't care about non-transmitted output data
  870      *  and non-read input data.
  871      */
  872     (void) tcsetattr(fd, TCSANOW, &tty);
  873     (void) tcflush(fd, TCIOFLUSH);
  874     (void) close(fd);
  875 }
  876 
  877 static  ssize_t
  878 safe_write(int fd, const char *buffer, size_t count)
  879 {
  880     ssize_t offset = 0;
  881 
  882     while (count > 0) {
  883         ssize_t block = write(fd, &buffer[offset], count);
  884 
  885         if (block < 0 && errno == EINTR)
  886             continue;
  887         if (block <= 0)
  888             return offset ? offset : block;
  889         offset += block;
  890         count -= block;
  891     }
  892     return offset;
  893 }
  894 
  895 /*
  896  *  Print to the system console
  897  */
  898 void print(char *s)
  899 {
  900     int fd;
  901 
  902     if ((fd = console_open(O_WRONLY|O_NOCTTY|O_NDELAY)) >= 0) {
  903         safe_write(fd, s, strlen(s));
  904         close(fd);
  905     }
  906 }
  907 
  908 /*
  909  *  Log something to a logfile and the console.
  910  */
  911 #ifdef __GNUC__
  912 __attribute__ ((format (printf, 2, 3)))
  913 #endif
  914 void initlog(int loglevel, char *s, ...)
  915 {
  916     va_list va_alist;
  917     char buf[256];
  918     sigset_t nmask, omask;
  919 
  920     va_start(va_alist, s);
  921     vsnprintf(buf, sizeof(buf), s, va_alist);
  922     va_end(va_alist);
  923 
  924     if (loglevel & L_SY) {
  925         /*
  926          *  Re-establish connection with syslogd every time.
  927          *  Block signals while talking to syslog.
  928          */
  929         sigfillset(&nmask);
  930         sigprocmask(SIG_BLOCK, &nmask, &omask);
  931         openlog("init", 0, LOG_DAEMON);
  932         syslog(LOG_INFO, "%s", buf);
  933         closelog();
  934         sigprocmask(SIG_SETMASK, &omask, NULL);
  935     }
  936 
  937     /*
  938      *  And log to the console.
  939      */
  940     if (loglevel & L_CO) {
  941         print("\rINIT: ");
  942         print(buf);
  943         print("\r\n");
  944     }
  945 }
  946 
  947 /*
  948  *  Add or replace specific environment value
  949  */
  950 int addnewenv(const char *new, char **curr, int n)
  951 {
  952     size_t nlen = strcspn(new, "=");
  953     int i;
  954     for (i = 0; i < n; i++) {
  955         if (nlen != strcspn(curr[i], "="))
  956             continue;
  957         if (strncmp (new, curr[i], nlen) == 0)
  958             break;
  959     }
  960     if (i >= n)
  961         curr[n++] = istrdup(new);
  962     else {
  963         free(curr[i]);
  964         curr[i] = istrdup(new);
  965     }
  966     return n;
  967 }
  968 
  969 /*
  970  *  Build a new environment for execve().
  971  */
  972 char **init_buildenv(int child)
  973 {
  974     char        i_lvl[] = "RUNLEVEL=x";
  975     char        i_prev[] = "PREVLEVEL=x";
  976     char        i_cons[128];
  977     char        i_shell[] = "SHELL=" SHELL;
  978     char        **e;
  979     int     n, i;
  980 
  981     for (n = 0; environ[n]; n++)
  982         ;
  983     n += NR_EXTRA_ENV + 1;      /* Also room for last NULL */
  984     if (child)
  985         n += 8;
  986 
  987     while ((e = (char**)calloc(n, sizeof(char *))) == NULL) {
  988         initlog(L_VB, "out of memory");
  989         do_msleep(SHORT_SLEEP);
  990     }
  991 
  992     for (n = 0; environ[n]; n++)
  993         e[n] = istrdup(environ[n]);
  994 
  995     for (i = 0; i < NR_EXTRA_ENV; i++) {
  996         if (extra_env[i] == NULL || *extra_env[i] == '\0')
  997             continue;
  998         n = addnewenv(extra_env[i], e, n);
  999     }
 1000 
 1001     if (child) {
 1002         snprintf(i_cons, sizeof(i_cons), "CONSOLE=%s", console_dev);
 1003         i_lvl[9]   = thislevel;
 1004         i_prev[10] = prevlevel;
 1005         n = addnewenv(i_shell, e, n);
 1006         n = addnewenv(i_lvl, e, n);
 1007         n = addnewenv(i_prev, e, n);
 1008         n = addnewenv(i_cons, e, n);
 1009         n = addnewenv(E_VERSION, e, n);
 1010     }
 1011 
 1012     e[n++] = NULL;
 1013 
 1014     return e;
 1015 }
 1016 
 1017 
 1018 void init_freeenv(char **e)
 1019 {
 1020     int     n;
 1021 
 1022     for (n = 0; e[n]; n++)
 1023         free(e[n]);
 1024     free(e);
 1025 }
 1026 
 1027 
 1028 /*
 1029  *  Fork and execute.
 1030  *
 1031  *  This function is too long and indents too deep.
 1032  *
 1033  */
 1034 static
 1035 pid_t spawn(CHILD *ch, int *res)
 1036 {
 1037   char *args[16];       /* Argv array */
 1038   char buf[136];        /* Line buffer */
 1039   int f, st;            /* Scratch variables */
 1040   char *ptr;            /* Ditto */
 1041   time_t t;         /* System time */
 1042   int oldAlarm;         /* Previous alarm value */
 1043   char *proc = ch->process; /* Command line */
 1044   pid_t pid, pgrp;      /* child, console process group. */
 1045   sigset_t nmask, omask;    /* For blocking SIGCHLD */
 1046   struct sigaction sa;
 1047 
 1048   *res = -1;
 1049   buf[sizeof(buf) - 1] = 0;
 1050 
 1051   /* Skip '+' if it's there */
 1052   if (proc[0] == '+') proc++;
 1053 
 1054   ch->flags |= XECUTED;
 1055 
 1056   if (ch->action == RESPAWN || ch->action == ONDEMAND) {
 1057     /* Is the date stamp from less than 2 minutes ago? */
 1058     time(&t);
 1059     if (ch->tm + TESTTIME > t) {
 1060         ch->count++;
 1061     } else {
 1062         ch->count = 0;
 1063         ch->tm = t;
 1064     }
 1065 
 1066     /* Do we try to respawn too fast? */
 1067     if (ch->count >= MAXSPAWN) {
 1068 
 1069       initlog(L_VB,
 1070         "Id \"%s\" respawning too fast: disabled for %d minutes",
 1071         ch->id, SLEEPTIME / 60);
 1072       ch->flags &= ~RUNNING;
 1073       ch->flags |= FAILING;
 1074 
 1075       /* Remember the time we stopped */
 1076       ch->tm = t;
 1077 
 1078       /* Try again in 5 minutes */
 1079       oldAlarm = alarm(0);
 1080       if (oldAlarm > SLEEPTIME || oldAlarm <= 0) oldAlarm = SLEEPTIME;
 1081       alarm(oldAlarm);
 1082       return(-1);
 1083     }
 1084   }
 1085 
 1086   /* See if there is an "initscript" (except in single user mode). */
 1087   if (access(INITSCRIPT, R_OK) == 0 && runlevel != 'S') {
 1088     /* Build command line using "initscript" */
 1089     args[1] = SHELL;
 1090     args[2] = INITSCRIPT;
 1091     args[3] = ch->id;
 1092     args[4] = ch->rlevel;
 1093     args[5] = "unknown";
 1094     for(f = 0; actions[f].name; f++) {
 1095         if (ch->action == actions[f].act) {
 1096             args[5] = actions[f].name;
 1097             break;
 1098         }
 1099     }
 1100     args[6] = proc;
 1101     args[7] = NULL;
 1102   } else if (strpbrk(proc, "~`!$^&*()=|\\{}[];\"'<>?")) {
 1103   /* See if we need to fire off a shell for this command */
 1104     /* Give command line to shell */
 1105     args[1] = SHELL;
 1106     args[2] = "-c";
 1107     strcpy(buf, "exec ");
 1108     strncat(buf, proc, sizeof(buf) - strlen(buf) - 1);
 1109     args[3] = buf;
 1110     args[4] = NULL;
 1111   } else {
 1112     /* Split up command line arguments */
 1113     buf[0] = 0;
 1114     strncat(buf, proc, sizeof(buf) - 1);
 1115     ptr = buf;
 1116     for(f = 1; f < 15; f++) {
 1117         /* Skip white space */
 1118         while(*ptr == ' ' || *ptr == '\t') ptr++;
 1119         args[f] = ptr;
 1120         
 1121         /* May be trailing space.. */
 1122         if (*ptr == 0) break;
 1123 
 1124         /* Skip this `word' */
 1125         while(*ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '#')
 1126             ptr++;
 1127         
 1128         /* If end-of-line, break */ 
 1129         if (*ptr == '#' || *ptr == 0) {
 1130             f++;
 1131             *ptr = 0;
 1132             break;
 1133         }
 1134         /* End word with \0 and continue */
 1135         *ptr++ = 0;
 1136     }
 1137     args[f] = NULL;
 1138   }
 1139   args[0] = args[1];
 1140   while(1) {
 1141     /*
 1142      *  Block sigchild while forking.
 1143      */
 1144     sigemptyset(&nmask);
 1145     sigaddset(&nmask, SIGCHLD);
 1146     sigprocmask(SIG_BLOCK, &nmask, &omask);
 1147 
 1148     if ((pid = fork()) == 0) {
 1149 
 1150         close(0);
 1151         close(1);
 1152         close(2);
 1153         if (pipe_fd >= 0)
 1154                 {
 1155                     close(pipe_fd);
 1156                     pipe_fd = -1;
 1157                 }
 1158 
 1159         sigprocmask(SIG_SETMASK, &omask, NULL);
 1160 
 1161         /*
 1162          *  In sysinit, boot, bootwait or single user mode:
 1163          *  for any wait-type subprocess we _force_ the console
 1164          *  to be its controlling tty.
 1165          */
 1166         if (strchr("*#sS", runlevel) && ch->flags & WAITING) {
 1167             int ftty;   /* Handler for tty controlling */
 1168             /*
 1169              *  We fork once extra. This is so that we can
 1170              *  wait and change the process group and session
 1171              *  of the console after exit of the leader.
 1172              */
 1173             setsid();
 1174             if ((ftty = console_open(O_RDWR|O_NOCTTY)) >= 0) {
 1175                 /* Take over controlling tty by force */
 1176                 (void)ioctl(ftty, TIOCSCTTY, 1);
 1177 
 1178                 if(dup(ftty) < 0){
 1179                         initlog(L_VB, "cannot duplicate console fd");
 1180                 }
 1181                 
 1182                 if(dup(ftty) < 0){
 1183                         initlog(L_VB, "cannot duplicate console fd");
 1184                 }
 1185 
 1186             }
 1187 
 1188             /*
 1189              * 4 Sep 2001, Andrea Arcangeli:
 1190              * Fix a race in spawn() that is used to deadlock init in a
 1191              * waitpid() loop: must set the childhandler as default before forking
 1192              * off the child or the chld_handler could run before the waitpid loop
 1193              * has a chance to find its zombie-child.
 1194              */
 1195             SETSIG(sa, SIGCHLD, SIG_DFL, SA_RESTART);
 1196             if ((pid = fork()) < 0) {
 1197                 initlog(L_VB, "cannot fork: %s",
 1198                     strerror(errno));
 1199                 exit(1);
 1200             }
 1201             if (pid > 0) {
 1202                 pid_t rc;
 1203                 /*
 1204                  *  Ignore keyboard signals etc.
 1205                  *  Then wait for child to exit.
 1206                  */
 1207                 SETSIG(sa, SIGINT, SIG_IGN, SA_RESTART);
 1208                 SETSIG(sa, SIGTSTP, SIG_IGN, SA_RESTART);
 1209                 SETSIG(sa, SIGQUIT, SIG_IGN, SA_RESTART);
 1210 
 1211                 while ((rc = waitpid(pid, &st, 0)) != pid)
 1212                     if (rc < 0 && errno == ECHILD)
 1213                         break;
 1214 
 1215                 /*
 1216                  *  Small optimization. See if stealing
 1217                  *  controlling tty back is needed.
 1218                  */
 1219                 pgrp = tcgetpgrp(ftty);
 1220                 if (pgrp != getpid())
 1221                     exit(0);
 1222 
 1223                 /*
 1224                  *  Steal controlling tty away. We do
 1225                  *  this with a temporary process.
 1226                  */
 1227                 if ((pid = fork()) < 0) {
 1228                     initlog(L_VB, "cannot fork: %s",
 1229                         strerror(errno));
 1230                     exit(1);
 1231                 }
 1232                 if (pid == 0) {
 1233                     setsid();
 1234                     (void)ioctl(ftty, TIOCSCTTY, 1);
 1235                     exit(0);
 1236                 }
 1237                 while((rc = waitpid(pid, &st, 0)) != pid)
 1238                     if (rc < 0 && errno == ECHILD)
 1239                         break;
 1240                 exit(0);
 1241             }
 1242 
 1243             /* Set ioctl settings to default ones */
 1244             console_stty();
 1245 
 1246         } else { /* parent */
 1247             int fd;
 1248             setsid();
 1249             if ((fd = console_open(O_RDWR|O_NOCTTY)) < 0) {
 1250                 initlog(L_VB, "open(%s): %s", console_dev,
 1251                     strerror(errno));
 1252                 fd = open("/dev/null", O_RDWR);
 1253             }
 1254 
 1255             if(dup(fd) < 0) {
 1256                 initlog(L_VB, "cannot duplicate /dev/null fd");
 1257             }
 1258             
 1259             if(dup(fd) < 0) {
 1260                 initlog(L_VB, "cannot duplicate /dev/null fd");
 1261             }
 1262 
 1263         }
 1264 
 1265         /*
 1266          * Update utmp/wtmp file prior to starting
 1267          * any child.  This MUST be done right here in
 1268          * the child process in order to prevent a race
 1269          * condition that occurs when the child
 1270          * process' time slice executes before the
 1271          * parent (can and does happen in a uniprocessor
 1272          * environment).  If the child is a getty and
 1273          * the race condition happens, then init's utmp
 1274          * update will happen AFTER the getty runs
 1275          * and expects utmp to be updated already!
 1276          *
 1277          * Do NOT log if process field starts with '+'
 1278          * This is for compatibility with *very*
 1279          * old getties - probably it can be taken out.
 1280          */
 1281         if (ch->process[0] != '+')
 1282             write_utmp_wtmp("", ch->id, getpid(), INIT_PROCESS, "");
 1283 
 1284         /* Reset all the signals, set up environment */
 1285         for(f = 1; f < NSIG; f++) SETSIG(sa, f, SIG_DFL, SA_RESTART);
 1286         environ = init_buildenv(1);
 1287 
 1288         /*
 1289          *  Execute prog. In case of ENOEXEC try again
 1290          *  as a shell script.
 1291          */
 1292         execvp(args[1], args + 1);
 1293         if (errno == ENOEXEC) {
 1294             args[1] = SHELL;
 1295             args[2] = "-c";
 1296             strcpy(buf, "exec ");
 1297             strncat(buf, proc, sizeof(buf) - strlen(buf) - 1);
 1298             args[3] = buf;
 1299             args[4] = NULL;
 1300             execvp(args[1], args + 1);
 1301         }
 1302         initlog(L_VB, "cannot execute \"%s\"", args[1]);
 1303 
 1304         if (ch->process[0] != '+')
 1305             write_utmp_wtmp("", ch->id, getpid(), DEAD_PROCESS, NULL);
 1306         exit(1);
 1307     }
 1308     *res = pid;
 1309     sigprocmask(SIG_SETMASK, &omask, NULL);
 1310 
 1311     INITDBG(L_VB, "Started id %s (pid %d)", ch->id, pid);
 1312 
 1313     if (pid == -1) {
 1314         initlog(L_VB, "cannot fork, retry..");
 1315         do_msleep(SHORT_SLEEP);
 1316         continue;
 1317     }
 1318     return(pid);
 1319   }
 1320 }
 1321 
 1322 /*
 1323  *  Start a child running!
 1324  */
 1325 static
 1326 void startup(CHILD *ch)
 1327 {
 1328     /*
 1329      *  See if it's disabled
 1330      */
 1331     if (ch->flags & FAILING) return;
 1332 
 1333     switch(ch->action) {
 1334 
 1335         case SYSINIT:
 1336         case BOOTWAIT:
 1337         case WAIT:
 1338         case POWERWAIT:
 1339         case POWERFAILNOW:
 1340         case POWEROKWAIT:
 1341         case CTRLALTDEL:
 1342             if (!(ch->flags & XECUTED)) ch->flags |= WAITING;
 1343             /* Fall through */
 1344         case KBREQUEST:
 1345         case BOOT:
 1346         case POWERFAIL:
 1347         case ONCE:
 1348             if (ch->flags & XECUTED) break;
 1349                         /* Fall through */
 1350         case ONDEMAND:
 1351         case RESPAWN:
 1352             ch->flags |= RUNNING;
 1353             (void)spawn(ch, &(ch->pid));
 1354             break;
 1355     }
 1356 }
 1357 
 1358 #ifdef __linux__
 1359 static
 1360 void check_kernel_console()
 1361 {
 1362     FILE* fp;
 1363     char buf[4096];
 1364     if ((fp = fopen("/proc/cmdline", "r")) == 0) {    
 1365         return;
 1366     }    
 1367     if (fgets(buf, sizeof(buf), fp)) {    
 1368         char* p = buf;
 1369            if ( strstr(p, "init.autocon=1") )
 1370            {
 1371         while ((p = strstr(p, "console="))) {    
 1372             char* e;
 1373             p += strlen("console=");
 1374             for (e = p; *e; ++e) {
 1375                 switch (*e) {
 1376                     case '-' ... '9':
 1377                     case 'A' ... 'Z':
 1378                     case '_':
 1379                     case 'a' ... 'z':
 1380                         continue;
 1381                 }
 1382                 break;
 1383             }
 1384             if (p != e) {
 1385                 CHILD* old;
 1386                 int dup = 0;
 1387                 char id[8] = {0};
 1388                 char dev[32] = {0};
 1389                 strncpy(dev, p, MIN(sizeof(dev), (unsigned)(e-p)));
 1390                 if (!strncmp(dev, "tty", 3))
 1391                     strncpy(id, dev+3, sizeof(id));
 1392                 else
 1393                     strncpy(id, dev, sizeof(id));
 1394 
 1395                 for(old = newFamily; old; old = old->next) {
 1396                     if (!strcmp(old->id, id)) {
 1397                         dup = 1;
 1398                     }
 1399                 }
 1400                 if (!dup) {
 1401                     CHILD* ch = imalloc(sizeof(CHILD));
 1402                     ch->action = RESPAWN;
 1403                     strcpy(ch->id, id);
 1404                     strcpy(ch->rlevel, "2345");
 1405                     sprintf(ch->process, "/sbin/agetty -L -s 115200,38400,9600 %s vt102", dev);
 1406                     ch->next = NULL;
 1407                     for(old = family; old; old = old->next) {
 1408                         if (strcmp(old->id, ch->id) == 0) {
 1409                             old->new = ch;
 1410                             break;
 1411                         }
 1412                     }
 1413                     /* add to end */
 1414                     for(old = newFamily; old; old = old->next) {
 1415                         if (!old->next) {
 1416                             old->next = ch;
 1417                             break;
 1418                         }
 1419                     }
 1420 
 1421                     initlog(L_VB, "added agetty on %s with id %s", dev, id);
 1422                 }
 1423             }
 1424         }
 1425             } 
 1426     }    
 1427     fclose(fp);
 1428     return;
 1429 }
 1430 #endif
 1431 
 1432 /*
 1433  *  Read the inittab file.
 1434  */
 1435 static
 1436 void read_inittab(void)
 1437 {
 1438   FILE      *fp;            /* The INITTAB file */
 1439   FILE      *fp_tab;        /* The INITTABD files */
 1440   CHILD     *ch, *old, *i;      /* Pointers to CHILD structure */
 1441   CHILD     *head = NULL;       /* Head of linked list */
 1442 #ifdef INITLVL
 1443   struct stat   st;         /* To stat INITLVL */
 1444 #endif
 1445   sigset_t  nmask, omask;       /* For blocking SIGCHLD. */
 1446   char      buf[256];       /* Line buffer */
 1447   char      err[64];        /* Error message. */
 1448   char      *id, *rlevel,
 1449         *action, *process;  /* Fields of a line */
 1450   char      *p;
 1451   int       lineNo = 0;     /* Line number in INITTAB file */
 1452   int       actionNo;       /* Decoded action field */
 1453   int       f;          /* Counter */
 1454   int       round;          /* round 0 for SIGTERM, 1 for SIGKILL */
 1455   int       foundOne = 0;       /* No killing no sleep */
 1456   int       talk;           /* Talk to the user */
 1457   int       done = -1;      /* Ready yet? , 2 level : -1 nothing done, 0 inittab done, 1 inittab and inittab.d done */
 1458   DIR       *tabdir=NULL;       /* the INITTAB.D dir */
 1459   struct dirent *file_entry;        /* inittab.d entry */
 1460   char      f_name[272];        /* size d_name + strlen /etc/inittad.d/ */
 1461 
 1462 #if DEBUG
 1463   if (newFamily != NULL) {
 1464     INITDBG(L_VB, "PANIC newFamily != NULL");
 1465     exit(1);
 1466   }
 1467   INITDBG(L_VB, "Reading inittab");
 1468 #endif
 1469 
 1470   /*
 1471    *    Open INITTAB and read line by line.
 1472    */
 1473   if ((fp = fopen(INITTAB, "r")) == NULL)
 1474     initlog(L_VB, "No inittab file found");
 1475 
 1476   /*
 1477    *  Open INITTAB.D directory 
 1478    */
 1479   if( (tabdir = opendir(INITTABD))==NULL)
 1480       initlog(L_VB, "No inittab.d directory found");
 1481 
 1482   while(done!=1) {
 1483     /*
 1484      *  Add single user shell entry at the end.
 1485      */
 1486     if(done == -1) {
 1487         if (fp == NULL || fgets(buf, sizeof(buf), fp) == NULL) {
 1488             done = 0;
 1489             /*
 1490              *  See if we have a single user entry.
 1491              */
 1492             for(old = newFamily; old; old = old->next)
 1493                 if (strpbrk(old->rlevel, "S"))  break;
 1494             if (old == NULL)
 1495                 snprintf(buf, sizeof(buf), "~~:S:wait:%s\n", SULOGIN);
 1496             else
 1497                 continue;
 1498         }
 1499     } /* end if( done==-1) */
 1500     else if ( done == 0 ){
 1501         /* parse /etc/inittab.d and read all .tab files */
 1502         if(tabdir!=NULL){
 1503             if( (file_entry = readdir(tabdir))!=NULL){
 1504                 /* ignore files not like *.tab */
 1505                 if (!strcmp(file_entry->d_name, ".") || !strcmp(file_entry->d_name, ".."))
 1506                     continue;
 1507                 if (strlen(file_entry->d_name) < 5 || strcmp(file_entry->d_name + strlen(file_entry->d_name) - 4, ".tab"))
 1508                     continue;
 1509                 /*
 1510                  * initialize filename
 1511                  */
 1512                 memset(f_name,0,sizeof(char)*272);
 1513                 snprintf(f_name,272,"/etc/inittab.d/%s",file_entry->d_name);
 1514                 initlog(L_VB, "Reading: %s",f_name);
 1515                 /*
 1516                  * read file in inittab.d only one entry per file
 1517                  */
 1518                 if ((fp_tab = fopen(f_name, "r")) == NULL)
 1519                     continue;
 1520                 /* read the file while the line contain comment */
 1521                 while( fgets(buf, sizeof(buf), fp_tab) != NULL) {
 1522                     for(p = buf; *p == ' ' || *p == '\t'; p++);
 1523                     if (*p != '#' && *p != '\n')
 1524                         break;
 1525                 }
 1526                 fclose(fp_tab);
 1527                 /* do some checks */
 1528                 if( buf == NULL ) 
 1529                     continue;
 1530                 if( strlen( p  ) == 0 )
 1531                     continue;
 1532             } /* end of readdir, all is done */
 1533             else { 
 1534                 done = 1;
 1535                 continue;
 1536             }
 1537         } /* end of if(tabdir!=NULL) */
 1538         else {
 1539             done = 1;
 1540             continue;
 1541         }
 1542     } /* end of if ( done == 0 ) */
 1543     lineNo++;
 1544     /*
 1545      *  Skip comments and empty lines
 1546      */
 1547     for(p = buf; *p == ' ' || *p == '\t'; p++)
 1548         ;
 1549     if (*p == '#' || *p == '\n') continue;
 1550 
 1551     /*
 1552      *  Decode the fields
 1553      */
 1554     id =      strsep(&p, ":");
 1555     rlevel =  strsep(&p, ":");
 1556     action =  strsep(&p, ":");
 1557     process = strsep(&p, "\n");
 1558 
 1559     /*
 1560      *  Check if syntax is OK. Be very verbose here, to
 1561      *  avoid newbie postings on comp.os.linux.setup :)
 1562      */
 1563     err[0] = 0;
 1564     if (!id || !*id) strcpy(err, "missing id field");
 1565     if (!rlevel)     strcpy(err, "missing runlevel field");
 1566     if (!process)    strcpy(err, "missing process field");
 1567     if (!action || !*action)
 1568             strcpy(err, "missing action field");
 1569     if (id && strlen(id) > sizeof(utproto.ut_id))
 1570         sprintf(err, "id field too long (max %d characters)",
 1571             (int)sizeof(utproto.ut_id));
 1572     if (rlevel && strlen(rlevel) > 11)
 1573         strcpy(err, "rlevel field too long (max 11 characters)");
 1574     if (process && strlen(process) > 127)
 1575         strcpy(err, "process field too long (max 127 characters)");
 1576     if (action && strlen(action) > 32)
 1577         strcpy(err, "action field too long");
 1578     if (err[0] != 0) {
 1579         initlog(L_VB, "%s[%d]: %s", INITTAB, lineNo, err);
 1580         INITDBG(L_VB, "%s:%s:%s:%s", id, rlevel, action, process);
 1581         continue;
 1582     }
 1583   
 1584     /*
 1585      *  Decode the "action" field
 1586      */
 1587     actionNo = -1;
 1588     for(f = 0; actions[f].name; f++)
 1589         if (strcasecmp(action, actions[f].name) == 0) {
 1590             actionNo = actions[f].act;
 1591             break;
 1592         }
 1593     if (actionNo == -1) {
 1594         initlog(L_VB, "%s[%d]: %s: unknown action field",
 1595             INITTAB, lineNo, action);
 1596         continue;
 1597     }
 1598 
 1599     /*
 1600      *  See if the id field is unique
 1601      */
 1602     for(old = newFamily; old; old = old->next) {
 1603         if(strcmp(old->id, id) == 0 && strcmp(id, "~~")) {
 1604             initlog(L_VB, "%s[%d]: duplicate ID field \"%s\"",
 1605                 INITTAB, lineNo, id);
 1606             break;
 1607         }
 1608     }
 1609     if (old) continue;
 1610 
 1611     /*
 1612      *  Allocate a CHILD structure
 1613      */
 1614     ch = imalloc(sizeof(CHILD));
 1615 
 1616     /*
 1617      *  And fill it in.
 1618      */
 1619     ch->action = actionNo;
 1620     strncpy(ch->id, id, sizeof(utproto.ut_id) + 1); /* Hack for different libs. */
 1621     strncpy(ch->process, process, sizeof(ch->process) - 1);
 1622     if (rlevel[0]) {
 1623         for(f = 0; f < (int)sizeof(rlevel) - 1 && rlevel[f]; f++) {
 1624             ch->rlevel[f] = rlevel[f];
 1625             if (ch->rlevel[f] == 's') ch->rlevel[f] = 'S';
 1626         }
 1627         strncpy(ch->rlevel, rlevel, sizeof(ch->rlevel) - 1);
 1628     } else {
 1629         strcpy(ch->rlevel, "0123456789");
 1630         if (ISPOWER(ch->action))
 1631             strcpy(ch->rlevel, "S0123456789");
 1632     }
 1633     /*
 1634      *  We have the fake runlevel '#' for SYSINIT  and
 1635      *  '*' for BOOT and BOOTWAIT.
 1636      */
 1637     if (ch->action == SYSINIT) strcpy(ch->rlevel, "#");
 1638     if (ch->action == BOOT || ch->action == BOOTWAIT)
 1639         strcpy(ch->rlevel, "*");
 1640 
 1641     /*
 1642      *  Now add it to the linked list. Special for powerfail.
 1643      */
 1644     if (ISPOWER(ch->action)) {
 1645 
 1646         /*
 1647          *  Disable by default
 1648          */
 1649         ch->flags |= XECUTED;
 1650 
 1651         /*
 1652          *  Tricky: insert at the front of the list..
 1653          */
 1654         old = NULL;
 1655         for(i = newFamily; i; i = i->next) {
 1656             if (!ISPOWER(i->action)) break;
 1657             old = i;
 1658         }
 1659         /*
 1660          *  Now add after entry "old"
 1661          */
 1662         if (old) {
 1663             ch->next = i;
 1664             old->next = ch;
 1665             if (i == NULL) head = ch;
 1666         } else {
 1667             ch->next = newFamily;
 1668             newFamily = ch;
 1669             if (ch->next == NULL) head = ch;
 1670         }
 1671     } else {
 1672         /*
 1673          *  Just add at end of the list
 1674          */
 1675         if (ch->action == KBREQUEST) ch->flags |= XECUTED;
 1676         ch->next = NULL;
 1677         if (head)
 1678             head->next = ch;
 1679         else
 1680             newFamily = ch;
 1681         head = ch;
 1682     }
 1683 
 1684     /*
 1685      *  Walk through the old list comparing id fields
 1686      */
 1687     for(old = family; old; old = old->next)
 1688         if (strcmp(old->id, ch->id) == 0) {
 1689             old->new = ch;
 1690             break;
 1691         }
 1692   }
 1693 
 1694   /*
 1695    *    We're done.
 1696    */
 1697   if (fp) fclose(fp);
 1698   if(tabdir) closedir(tabdir);
 1699 
 1700 #ifdef __linux__
 1701   check_kernel_console();
 1702 #endif
 1703 
 1704   /*
 1705    *    Loop through the list of children, and see if they need to
 1706    *    be killed. 
 1707    */
 1708 
 1709   INITDBG(L_VB, "Checking for children to kill");
 1710   for(round = 0; round < 2; round++) {
 1711     talk = 1;
 1712     for(ch = family; ch; ch = ch->next) {
 1713     ch->flags &= ~KILLME;
 1714 
 1715     /*
 1716      *  Is this line deleted?
 1717      */
 1718     if (ch->new == NULL) ch->flags |= KILLME;
 1719 
 1720     /*
 1721      *  If the entry has changed, kill it anyway. Note that
 1722      *  we do not check ch->process, only the "action" field.
 1723      *  This way, you can turn an entry "off" immediately, but
 1724      *  changes in the command line will only become effective
 1725      *  after the running version has exited.
 1726      */
 1727     if (ch->new && ch->action != ch->new->action) ch->flags |= KILLME;
 1728 
 1729     /*
 1730      *  Only BOOT processes may live in all levels
 1731      */
 1732     if (ch->action != BOOT &&
 1733         strchr(ch->rlevel, runlevel) == NULL) {
 1734         /*
 1735          *  Ondemand procedures live always,
 1736          *  except in single user
 1737          */
 1738         if (runlevel == 'S' || !(ch->flags & DEMAND))
 1739             ch->flags |= KILLME;
 1740     }
 1741 
 1742     /*
 1743      *  Now, if this process may live note so in the new list
 1744      */
 1745     if ((ch->flags & KILLME) == 0) {
 1746         ch->new->flags  = ch->flags;
 1747         ch->new->pid    = ch->pid;
 1748         ch->new->exstat = ch->exstat;
 1749         continue;
 1750     }
 1751 
 1752 
 1753     /*
 1754      *  Is this process still around?
 1755      */
 1756     if ((ch->flags & RUNNING) == 0) {
 1757         ch->flags &= ~KILLME;
 1758         continue;
 1759     }
 1760     INITDBG(L_VB, "Killing \"%s\"", ch->process);
 1761     switch(round) {
 1762         case 0: /* Send TERM signal */
 1763             if (talk)
 1764                 initlog(L_CO,
 1765                     "Sending processes configured via /etc/inittab the TERM signal");
 1766             kill(-(ch->pid), SIGTERM);
 1767             foundOne = 1;
 1768             break;
 1769         case 1: /* Send KILL signal and collect status */
 1770             if (talk)
 1771                 initlog(L_CO,
 1772                     "Sending processes configured via /etc/inittab the KILL signal");
 1773             kill(-(ch->pid), SIGKILL);
 1774             break;
 1775     }
 1776     talk = 0;
 1777     
 1778     }
 1779     /*
 1780      *  See if we have to wait sleep_time seconds
 1781      */
 1782     if (foundOne && round == 0) {
 1783     /*
 1784      *  Yup, but check every 10 milliseconds if we still have children.
 1785          *      The f < 100 * sleep_time refers to sleep time in 10 millisecond chunks.
 1786      */
 1787     for(f = 0; f < 100 * sleep_time; f++) {
 1788         for(ch = family; ch; ch = ch->next) {
 1789             if (!(ch->flags & KILLME)) continue;
 1790             if ((ch->flags & RUNNING) && !(ch->flags & ZOMBIE))
 1791                 break;
 1792         }
 1793         if (ch == NULL) {
 1794             /*
 1795              *  No running children, skip SIGKILL
 1796              */
 1797             round = 1;
 1798             foundOne = 0; /* Skip the sleep below. */
 1799             break;
 1800         }
 1801         do_msleep(MINI_SLEEP);
 1802     }
 1803     }
 1804   }
 1805 
 1806   /*
 1807    *    Now give all processes the chance to die and collect exit statuses.
 1808    */
 1809   if (foundOne) do_msleep(MINI_SLEEP);
 1810   for(ch = family; ch; ch = ch->next)
 1811     if (ch->flags & KILLME) {
 1812         if (!(ch->flags & ZOMBIE))
 1813             initlog(L_CO, "Pid %d [id %s] seems to hang", ch->pid,
 1814                 ch->id);
 1815         else {
 1816             INITDBG(L_VB, "Updating utmp for pid %d [id %s]",
 1817                 ch->pid, ch->id);
 1818             ch->flags &= ~RUNNING;
 1819             if (ch->process[0] != '+')
 1820                 write_utmp_wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL);
 1821         }
 1822     }
 1823 
 1824   /*
 1825    *    Both rounds done; clean up the list.
 1826    */
 1827   sigemptyset(&nmask);
 1828   sigaddset(&nmask, SIGCHLD);
 1829   sigprocmask(SIG_BLOCK, &nmask, &omask);
 1830   for(ch = family; ch; ch = old) {
 1831     old = ch->next;
 1832     free(ch);
 1833   }
 1834   family = newFamily;
 1835   for(ch = family; ch; ch = ch->next) ch->new = NULL;
 1836   newFamily = NULL;
 1837   sigprocmask(SIG_SETMASK, &omask, NULL);
 1838 
 1839 #ifdef INITLVL
 1840   /*
 1841    *    Dispose of INITLVL file.
 1842    */
 1843   if (lstat(INITLVL, &st) >= 0 && S_ISLNK(st.st_mode)) {
 1844     /*
 1845      *  INITLVL is a symbolic link, so just truncate the file.
 1846      */
 1847     close(open(INITLVL, O_WRONLY|O_TRUNC));
 1848   } else {
 1849     /*
 1850      *  Delete INITLVL file.
 1851      */
 1852     unlink(INITLVL);
 1853   }
 1854 #endif
 1855 #ifdef INITLVL2
 1856   /*
 1857    *    Dispose of INITLVL2 file.
 1858    */
 1859   if (lstat(INITLVL2, &st) >= 0 && S_ISLNK(st.st_mode)) {
 1860     /*
 1861      *  INITLVL2 is a symbolic link, so just truncate the file.
 1862      */
 1863     close(open(INITLVL2, O_WRONLY|O_TRUNC));
 1864   } else {
 1865     /*
 1866      *  Delete INITLVL2 file.
 1867      */
 1868     unlink(INITLVL2);
 1869   }
 1870 #endif
 1871 }
 1872 
 1873 /*
 1874  *  Walk through the family list and start up children.
 1875  *  The entries that do not belong here at all are removed
 1876  *  from the list.
 1877  */
 1878 static
 1879 void start_if_needed(void)
 1880 {
 1881     CHILD *ch;      /* Pointer to child */
 1882     int delete;     /* Delete this entry from list? */
 1883 
 1884     INITDBG(L_VB, "Checking for children to start");
 1885 
 1886     for(ch = family; ch; ch = ch->next) {
 1887 
 1888 #if DEBUG
 1889         if (ch->rlevel[0] == 'C') {
 1890             INITDBG(L_VB, "%s: flags %d", ch->process, ch->flags);
 1891         }
 1892 #endif
 1893 
 1894         /* Are we waiting for this process? Then quit here. */
 1895         if (ch->flags & WAITING) break;
 1896 
 1897         /* Already running? OK, don't touch it */
 1898         if (ch->flags & RUNNING) continue;
 1899 
 1900         /* See if we have to start it up */
 1901         delete = 1;
 1902         if (strchr(ch->rlevel, runlevel) ||
 1903             ((ch->flags & DEMAND) && !strchr("#*Ss", runlevel))) {
 1904             startup(ch);
 1905             delete = 0;
 1906         }
 1907 
 1908         if (delete) {
 1909             /* is this OK? */
 1910             ch->flags &= ~(RUNNING|WAITING);
 1911             if (!ISPOWER(ch->action) && ch->action != KBREQUEST)
 1912                 ch->flags &= ~XECUTED;
 1913             ch->pid = 0;
 1914         } else
 1915             /* Do we have to wait for this process? */
 1916             if (ch->flags & WAITING) break;
 1917     }
 1918     /* Done. */
 1919 }
 1920 
 1921 /*
 1922  *  Ask the user on the console for a runlevel
 1923  */
 1924 static
 1925 int ask_runlevel(void)
 1926 {
 1927     const char  prompt[] = "\nEnter runlevel: ";
 1928     char        buf[8];
 1929     int     lvl = -1;
 1930     int     fd;
 1931 
 1932     console_stty();
 1933     fd = console_open(O_RDWR|O_NOCTTY);
 1934 
 1935     if (fd < 0) return('S');
 1936 
 1937     while(!strchr("0123456789S", lvl)) {
 1938         safe_write(fd, prompt, sizeof(prompt) - 1);
 1939         if (read(fd, buf, sizeof(buf)) <= 0)
 1940             buf[0] = 0;
 1941         if (buf[0] != 0 && (buf[1] == '\r' || buf[1] == '\n'))
 1942             lvl = buf[0];
 1943         if (islower(lvl)) lvl = toupper(lvl);
 1944     }
 1945     close(fd);
 1946     return lvl;
 1947 }
 1948 
 1949 /*
 1950  *  Search the INITTAB file for the 'initdefault' field, with the default
 1951  *  runlevel. If this fails, ask the user to supply a runlevel.
 1952  */
 1953 static
 1954 int get_init_default(void)
 1955 {
 1956     CHILD *ch;
 1957     int lvl = -1;
 1958     char *p;
 1959 
 1960     /*
 1961      *  Look for initdefault.
 1962      */
 1963     for(ch = family; ch; ch = ch->next)
 1964         if (ch->action == INITDEFAULT) {
 1965             p = ch->rlevel;
 1966             while(*p) {
 1967                 if (*p > lvl) lvl = *p;
 1968                 p++;
 1969             }
 1970             break;
 1971         }
 1972     /*
 1973      *  See if level is valid
 1974      */
 1975     if (lvl > 0) {
 1976         if (islower(lvl)) lvl = toupper(lvl);
 1977         if (strchr("0123456789S", lvl) == NULL) {
 1978             initlog(L_VB,
 1979                 "Initdefault level '%c' is invalid", lvl);
 1980             lvl = 0;
 1981         }
 1982     }
 1983     /*
 1984      *  Ask for runlevel on console if needed.
 1985      */
 1986     if (lvl <= 0) lvl = ask_runlevel();
 1987 
 1988     /*
 1989      *  Log the fact that we have a runlevel now.
 1990      */
 1991         Write_Runlevel_Log(lvl);
 1992     return lvl;
 1993 }
 1994 
 1995 
 1996 /*
 1997  *  We got signaled.
 1998  *
 1999  *  Do actions for the new level. If we are compatible with
 2000  *  the "old" INITLVL and arg == 0, try to read the new
 2001  *  runlevel from that file first.
 2002  */
 2003 static
 2004 int read_level(int arg)
 2005 {
 2006     CHILD       *ch;            /* Walk through list */
 2007     unsigned char   foo = 'X';      /* Contents of INITLVL */
 2008     int     ok = 1;
 2009 #ifdef INITLVL
 2010     FILE        *fp;
 2011     struct stat stt;
 2012     int     st;
 2013 #endif
 2014 
 2015     if (arg) foo = arg;
 2016 
 2017 #ifdef INITLVL
 2018     ok = 0;
 2019 
 2020     if (arg == 0) {
 2021         fp = NULL;
 2022         if (stat(INITLVL, &stt) != 0 || stt.st_size != 0L)
 2023             fp = fopen(INITLVL, "r");
 2024 #ifdef INITLVL2
 2025         if (fp == NULL &&
 2026             (stat(INITLVL2, &stt) != 0 || stt.st_size != 0L))
 2027             fp = fopen(INITLVL2, "r");
 2028 #endif
 2029         if (fp == NULL) {
 2030             /* INITLVL file empty or not there - act as 'init q' */
 2031             initlog(L_SY, "Re-reading inittab");
 2032             return(runlevel);
 2033         }
 2034         ok = fscanf(fp, "%c %d", &foo, &st);
 2035         fclose(fp);
 2036     } else {
 2037         /* We go to the new runlevel passed as an argument. */
 2038         foo = arg;
 2039         ok = 1;
 2040     }
 2041     if (ok == 2) sleep_time = st;
 2042 
 2043 #endif /* INITLVL */
 2044 
 2045     if (islower(foo)) foo = toupper(foo);
 2046     if (ok < 1 || ok > 2 || strchr("QS0123456789ABCU", foo) == NULL) {
 2047         initlog(L_VB, "bad runlevel: %c", foo);
 2048         return runlevel;
 2049     }
 2050 
 2051     /* Log this action */
 2052     switch(foo) {
 2053         case 'S':
 2054             initlog(L_VB, "Going single user");
 2055             break;
 2056         case 'Q':
 2057             initlog(L_SY, "Re-reading inittab");
 2058             break;
 2059         case 'A':
 2060         case 'B':
 2061         case 'C':
 2062             initlog(L_SY,
 2063                 "Activating demand-procedures for '%c'", foo);
 2064             break;
 2065         case 'U':
 2066             initlog(L_SY, "Trying to re-exec init");
 2067             return 'U';
 2068         default:
 2069             initlog(L_VB, "Switching to runlevel: %c", foo);
 2070     }
 2071 
 2072     if (foo == 'Q') {
 2073 #if defined(SIGINT_ONLYONCE) && (SIGINT_ONLYONCE == 1)
 2074         /* Re-enable signal from keyboard */
 2075         struct sigaction sa;
 2076         SETSIG(sa, SIGINT, signal_handler, 0);
 2077 #endif
 2078         return runlevel;
 2079     }
 2080 
 2081     /* Check if this is a runlevel a, b or c */
 2082     if (strchr("ABC", foo)) {
 2083         if (runlevel == 'S') return(runlevel);
 2084 
 2085         /* Read inittab again first! */
 2086         read_inittab();
 2087 
 2088         /* Mark those special tasks */
 2089         for(ch = family; ch; ch = ch->next)
 2090             if (strchr(ch->rlevel, foo) != NULL ||
 2091                 strchr(ch->rlevel, tolower(foo)) != NULL) {
 2092                 ch->flags |= DEMAND;
 2093                 ch->flags &= ~XECUTED;
 2094                 INITDBG(L_VB,
 2095                     "Marking (%s) as ondemand, flags %d",
 2096                     ch->id, ch->flags);
 2097             }
 2098         return runlevel;
 2099     }
 2100 
 2101     /* Store both the old and the new runlevel. */
 2102     wrote_utmp_rlevel = 0;
 2103     wrote_wtmp_rlevel = 0;
 2104     write_utmp_wtmp("runlevel", "~~", foo + 256*runlevel, RUN_LVL, "~");
 2105     thislevel = foo;
 2106     prevlevel = runlevel;
 2107         Write_Runlevel_Log(runlevel);
 2108     return foo;
 2109 }
 2110 
 2111 
 2112 /*
 2113  *  This procedure is called after every signal (SIGHUP, SIGALRM..)
 2114  *
 2115  *  Only clear the 'failing' flag if the process is sleeping
 2116  *  longer than 5 minutes, or inittab was read again due
 2117  *  to user interaction.
 2118  */
 2119 static
 2120 void fail_check(void)
 2121 {
 2122     CHILD   *ch;            /* Pointer to child structure */
 2123     time_t  t;          /* System time */
 2124     time_t  next_alarm = 0;     /* When to set next alarm */
 2125 
 2126     time(&t);
 2127 
 2128     for(ch = family; ch; ch = ch->next) {
 2129 
 2130         if (ch->flags & FAILING) {
 2131             /* Can we free this sucker? */
 2132             if (ch->tm + SLEEPTIME < t) {
 2133                 ch->flags &= ~FAILING;
 2134                 ch->count = 0;
 2135                 ch->tm = 0;
 2136             } else {
 2137                 /* No, we'll look again later */
 2138                 if (next_alarm == 0 ||
 2139                     ch->tm + SLEEPTIME > next_alarm)
 2140                     next_alarm = ch->tm + SLEEPTIME;
 2141             }
 2142         }
 2143     }
 2144     if (next_alarm) {
 2145         next_alarm -= t;
 2146         if (next_alarm < 1) next_alarm = 1;
 2147         alarm(next_alarm);
 2148     }
 2149 }
 2150 
 2151 /* Set all 'Fail' timers to 0 */
 2152 static
 2153 void fail_cancel(void)
 2154 {
 2155     CHILD *ch;
 2156 
 2157     for(ch = family; ch; ch = ch->next) {
 2158         ch->count = 0;
 2159         ch->tm = 0;
 2160         ch->flags &= ~FAILING;
 2161     }
 2162 }
 2163 
 2164 /*
 2165  *  Start up powerfail entries.
 2166  */
 2167 static
 2168 void do_power_fail(int pwrstat)
 2169 {
 2170     CHILD *ch;
 2171 
 2172     /*
 2173      *  Tell powerwait & powerfail entries to start up
 2174      */
 2175     for (ch = family; ch; ch = ch->next) {
 2176         if (pwrstat == 'O') {
 2177             /*
 2178              *  The power is OK again.
 2179              */
 2180             if (ch->action == POWEROKWAIT)
 2181                 ch->flags &= ~XECUTED;
 2182         } else if (pwrstat == 'L') {
 2183             /*
 2184              *  Low battery, shut down now.
 2185              */
 2186             if (ch->action == POWERFAILNOW)
 2187                 ch->flags &= ~XECUTED;
 2188         } else {
 2189             /*
 2190              *  Power is failing, shutdown imminent
 2191              */
 2192             if (ch->action == POWERFAIL || ch->action == POWERWAIT)
 2193                 ch->flags &= ~XECUTED;
 2194         }
 2195     }
 2196 }
 2197 
 2198 /*
 2199  *  Check for state-pipe presence
 2200  */
 2201 static
 2202 int check_pipe(int fd)
 2203 {
 2204     struct timeval  t;
 2205     fd_set      s;
 2206     char        signature[8];
 2207 
 2208     FD_ZERO(&s);
 2209     FD_SET(fd, &s);
 2210     t.tv_sec = t.tv_usec = 0;
 2211 
 2212     if (select(fd+1, &s, NULL, NULL, &t) != 1)
 2213         return 0;
 2214     if (read(fd, signature, 8) != 8)
 2215          return 0;
 2216     return strncmp(Signature, signature, 8) == 0;
 2217 }
 2218 
 2219 /*
 2220  *   Make a state-pipe.
 2221  */
 2222 static
 2223 int make_pipe(int fd)
 2224 {
 2225     int fds[2];
 2226 
 2227     if (pipe(fds)) {
 2228         initlog(L_VB, "pipe: %m");
 2229         return -1;
 2230     }
 2231     dup2(fds[0], fd);
 2232     close(fds[0]);
 2233     fcntl(fds[1], F_SETFD, 1);
 2234     fcntl(fd, F_SETFD, 0);
 2235     safe_write(fds[1], Signature, 8);
 2236 
 2237     return fds[1];
 2238 }
 2239 
 2240 /*
 2241  *  Attempt to re-exec.
 2242  *      Renaming to my_re_exec since re_exec is now a common function name
 2243  *      which conflicts.
 2244  */
 2245 static
 2246 void my_re_exec(void)
 2247 {
 2248     CHILD       *ch;
 2249     sigset_t    mask, oldset;
 2250     pid_t       pid;
 2251     char        **env;
 2252     int     fd;
 2253 
 2254     if (strchr("S0123456",runlevel) == NULL)
 2255         return;
 2256 
 2257     /*
 2258      *  Reset the alarm, and block all signals.
 2259      */
 2260     alarm(0);
 2261     sigfillset(&mask);
 2262     sigprocmask(SIG_BLOCK, &mask, &oldset);
 2263 
 2264     /*
 2265      *  construct a pipe fd --> STATE_PIPE and write a signature
 2266      */
 2267     if ((fd = make_pipe(STATE_PIPE)) < 0) {
 2268         sigprocmask(SIG_SETMASK, &oldset, NULL);
 2269         initlog(L_CO, "Attempt to re-exec failed");
 2270     }
 2271 
 2272     fail_cancel();
 2273     if (pipe_fd >= 0) 
 2274           close(pipe_fd);
 2275     pipe_fd = -1;
 2276     DELSET(got_signals, SIGCHLD);
 2277     DELSET(got_signals, SIGHUP);
 2278     DELSET(got_signals, SIGUSR1);
 2279     DELSET(got_signals, SIGUSR2);
 2280 
 2281     /*
 2282      *  That should be cleaned.
 2283      */
 2284     for(ch = family; ch; ch = ch->next)
 2285         if (ch->flags & ZOMBIE) {
 2286         INITDBG(L_VB, "Child died, PID= %d", ch->pid);
 2287         ch->flags &= ~(RUNNING|ZOMBIE|WAITING);
 2288         if (ch->process[0] != '+')
 2289             write_utmp_wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL);
 2290         }
 2291 
 2292     if ((pid = fork()) == 0) {
 2293         /*
 2294          *  Child sends state information to the parent.
 2295          */
 2296         send_state(fd);
 2297         exit(0);
 2298     }
 2299 
 2300     /*
 2301      *  The existing init process execs a new init binary.
 2302      */
 2303     env = init_buildenv(0);
 2304     execle(myname, myname, "--init", NULL, env);
 2305 
 2306     /*
 2307      *  We shouldn't be here, something failed. 
 2308      *  Close the state pipe, unblock signals and return.
 2309      */
 2310     init_freeenv(env);
 2311     close(fd);
 2312     close(STATE_PIPE);
 2313     sigprocmask(SIG_SETMASK, &oldset, NULL);
 2314     initlog(L_CO, "Attempt to re-exec failed");
 2315 }
 2316 
 2317 /*
 2318  *  Redo utmp/wtmp entries if required or requested
 2319  *  Check for written records and size of utmp
 2320  */
 2321 static
 2322 void redo_utmp_wtmp(void)
 2323 {
 2324     struct stat ustat;
 2325     const int ret = stat(UTMP_FILE, &ustat);
 2326 
 2327     if ((ret < 0) || (ustat.st_size == 0))
 2328         wrote_utmp_rlevel = wrote_utmp_reboot = 0;
 2329 
 2330     if ((wrote_wtmp_reboot == 0) || (wrote_utmp_reboot == 0))
 2331         write_utmp_wtmp("reboot", "~~", 0, BOOT_TIME, "~");
 2332 
 2333     if ((wrote_wtmp_rlevel == 0) || (wrote_utmp_rlevel == 0))
 2334         write_utmp_wtmp("runlevel", "~~", thislevel + 256 * prevlevel, RUN_LVL, "~");
 2335 }
 2336 
 2337 /*
 2338  *  We got a change runlevel request through the
 2339  *  init.fifo. Process it.
 2340  */
 2341 static
 2342 void fifo_new_level(int level)
 2343 {
 2344 #if CHANGE_WAIT
 2345     CHILD   *ch;
 2346 #endif
 2347     int oldlevel;
 2348 
 2349     if (level == runlevel) return;
 2350 
 2351 #if CHANGE_WAIT
 2352     /* Are we waiting for a child? */
 2353     for(ch = family; ch; ch = ch->next)
 2354         if (ch->flags & WAITING) break;
 2355     if (ch == NULL)
 2356 #endif
 2357     {
 2358         /* We need to go into a new runlevel */
 2359         oldlevel = runlevel;
 2360         runlevel = read_level(level);
 2361         if (runlevel == 'U') {
 2362             runlevel = oldlevel;
 2363             my_re_exec();
 2364         } else {
 2365             if (oldlevel != 'S' && runlevel == 'S') console_stty();
 2366             if (runlevel == '6' || runlevel == '0' ||
 2367                 runlevel == '1') console_stty();
 2368             if (runlevel  > '1' && runlevel  < '6') redo_utmp_wtmp();
 2369             read_inittab();
 2370             fail_cancel();
 2371             setproctitle("init [%c]", (int)runlevel);
 2372         }
 2373     }
 2374         Write_Runlevel_Log(runlevel);
 2375 }
 2376 
 2377 
 2378 /*
 2379  *  Set/unset environment variables. The variables are
 2380  *  encoded as KEY=VAL\0KEY=VAL\0\0. With "=VAL" it means
 2381  *  setenv, without it means unsetenv.
 2382  */
 2383 static
 2384 void initcmd_setenv(char *data, int size)
 2385 {
 2386     char        *env, *p, *e;
 2387     size_t      sz;
 2388     int     i, eq;
 2389 
 2390     e = data + size;
 2391 
 2392     while (*data && data < e) {
 2393         for (p = data; *p && p < e; p++)
 2394             ;
 2395         if (*p) break;
 2396         env = data;
 2397         data = ++p;
 2398 
 2399         /*
 2400          *  We only allow INIT_* to be set.
 2401          */
 2402         if (strncmp(env, "INIT_", 5) != 0)
 2403             continue;
 2404 
 2405         sz = strcspn(env, "=");
 2406         eq = (env[sz] == '=');
 2407 
 2408         /*initlog(L_SY, "init_setenv: %s, %d, %d", env, eq, sz);*/
 2409 
 2410         /* Free existing vars. */
 2411         for (i = 0; i < NR_EXTRA_ENV; i++) {
 2412             if (extra_env[i] == NULL)
 2413                 continue;
 2414             if (sz != strcspn(extra_env[i], "="))
 2415                 continue;
 2416             if (strncmp(extra_env[i], env, sz) == 0) {
 2417                 free(extra_env[i]);
 2418                 extra_env[i] = NULL;
 2419             }
 2420         }
 2421 
 2422         if (eq == 0)
 2423             continue;
 2424 
 2425         /* Set new vars if needed. */
 2426         for (i = 0; i < NR_EXTRA_ENV; i++) {
 2427             if (extra_env[i] == NULL) {
 2428                 extra_env[i] = istrdup(env);
 2429                 break;
 2430             }
 2431         }
 2432     }
 2433 }
 2434 
 2435 
 2436 /*
 2437  *  Read from the init FIFO. Processes like telnetd and rlogind can
 2438  *  ask us to create login processes on their behalf.
 2439  */
 2440 static
 2441 void check_init_fifo(void)
 2442 {
 2443   struct init_request   request;
 2444   struct timeval    tv;
 2445   struct stat       st, st2;
 2446   fd_set        fds;
 2447   int           n;
 2448   int           quit = 0;
 2449 
 2450   /*
 2451    *    First, try to create /run/initctl if not present.
 2452    */
 2453   if (stat(INIT_FIFO, &st2) < 0 && errno == ENOENT)
 2454     (void)mkfifo(INIT_FIFO, 0600);
 2455 
 2456   /*
 2457    *    If /run/initctl is open, stat the file to see if it
 2458    *    is still the _same_ inode.
 2459    */
 2460   if (pipe_fd >= 0) {
 2461     fstat(pipe_fd, &st);
 2462     if (stat(INIT_FIFO, &st2) < 0 ||
 2463         st.st_dev != st2.st_dev ||
 2464         st.st_ino != st2.st_ino) {
 2465         close(pipe_fd);
 2466         pipe_fd = -1;
 2467     }
 2468   }
 2469 
 2470   /*
 2471    *    Now finally try to open /run/initctl if pipe_fd is -1
 2472    *    if it is -2, then we leave it closed
 2473    */
 2474   if (pipe_fd == -1) {
 2475     if ((pipe_fd = open(INIT_FIFO, O_RDWR|O_NONBLOCK)) >= 0) {
 2476         fstat(pipe_fd, &st);
 2477         if (!S_ISFIFO(st.st_mode)) {
 2478             initlog(L_VB, "%s is not a fifo", INIT_FIFO);
 2479             close(pipe_fd);
 2480             pipe_fd = -1;
 2481         }
 2482     }
 2483     if (pipe_fd >= 0) {
 2484         /*
 2485          *  Don't use fd's 0, 1 or 2.
 2486          */
 2487         (void) dup2(pipe_fd, PIPE_FD);
 2488         close(pipe_fd);
 2489         pipe_fd = PIPE_FD;
 2490 
 2491         /*
 2492          *  Return to caller - we'll be back later.
 2493          */
 2494     }
 2495   }
 2496 
 2497   /* Wait for data to appear, _if_ the pipe was opened. */
 2498   if (pipe_fd >= 0) { 
 2499      while(!quit) {
 2500 
 2501     /* Do select, return on EINTR. */
 2502     FD_ZERO(&fds);
 2503     FD_SET(pipe_fd, &fds);
 2504     tv.tv_sec = 5;
 2505     tv.tv_usec = 0;
 2506     n = select(pipe_fd + 1, &fds, NULL, NULL, &tv);
 2507     if (n <= 0) {
 2508         if (n == 0 || errno == EINTR) return;
 2509         continue;
 2510     }
 2511 
 2512     /* Read the data, return on EINTR. */
 2513     n = read(pipe_fd, &request, sizeof(request));
 2514     if (n == 0) {
 2515         /*
 2516          *  End of file. This can't happen under Linux (because
 2517          *  the pipe is opened O_RDWR - see select() in the
 2518          *  kernel) but you never know...
 2519          */
 2520         close(pipe_fd);
 2521         pipe_fd = -1;
 2522         return;
 2523     }
 2524     if (n <= 0) {
 2525         if (errno == EINTR) return;
 2526         initlog(L_VB, "error reading initrequest");
 2527         continue;
 2528     }
 2529 
 2530     /*
 2531      *  This is a convenient point to also try to
 2532      *  find the console device or check if it changed.
 2533      */
 2534     console_init();
 2535 
 2536     /*
 2537      *  Process request.
 2538      */
 2539     if (request.magic != INIT_MAGIC || n != sizeof(request)) {
 2540         initlog(L_VB, "got bogus initrequest");
 2541         continue;
 2542     }
 2543     switch(request.cmd) {
 2544         case INIT_CMD_RUNLVL:
 2545             sleep_time = request.sleeptime;
 2546             fifo_new_level(request.runlevel);
 2547             quit = 1;
 2548             break;
 2549         case INIT_CMD_POWERFAIL:
 2550             sleep_time = request.sleeptime;
 2551             do_power_fail('F');
 2552             quit = 1;
 2553             break;
 2554         case INIT_CMD_POWERFAILNOW:
 2555             sleep_time = request.sleeptime;
 2556             do_power_fail('L');
 2557             quit = 1;
 2558             break;
 2559         case INIT_CMD_POWEROK:
 2560             sleep_time = request.sleeptime;
 2561             do_power_fail('O');
 2562             quit = 1;
 2563             break;
 2564         case INIT_CMD_SETENV:
 2565             initcmd_setenv(request.i.data, sizeof(request.i.data));
 2566             break;
 2567         default:
 2568             initlog(L_VB, "got unimplemented initrequest.");
 2569             break;
 2570     }   /* end of switch */
 2571     }       /* end of while loop not quitting */
 2572   }         /* end of if the pipe is open */
 2573   /*
 2574    *    We come here if the pipe couldn't be opened.
 2575    */
 2576   if (pipe_fd == -1) pause();
 2577 
 2578 }
 2579 
 2580 
 2581 /*
 2582  *  This function is used in the transition
 2583  *  sysinit (-> single user) boot -> multi-user.
 2584  */
 2585 static
 2586 void boot_transitions()
 2587 {
 2588   CHILD     *ch;
 2589   static int    newlevel = 0;
 2590   static int    warn = 1;
 2591   int       loglevel;
 2592   int       oldlevel;
 2593 
 2594   /* Check if there is something to wait for! */
 2595   for( ch = family; ch; ch = ch->next )
 2596     if ((ch->flags & RUNNING) && ch->action != BOOT) break;
 2597      
 2598   if (ch == NULL) {
 2599     /* No processes left in this level, proceed to next level. */
 2600     loglevel = -1;
 2601     oldlevel = 'N';
 2602     switch(runlevel) {
 2603         case '#': /* SYSINIT -> BOOT */
 2604             INITDBG(L_VB, "SYSINIT -> BOOT");
 2605 
 2606             /* Write a boot record. */
 2607             wrote_utmp_reboot = 0;
 2608             wrote_wtmp_reboot = 0;
 2609             write_utmp_wtmp("reboot", "~~", 0, BOOT_TIME, "~");
 2610 
 2611             /* Get our run level */
 2612             newlevel = dfl_level ? dfl_level : get_init_default();
 2613             if (newlevel == 'S') {
 2614                 runlevel = newlevel;
 2615                 /* Not really 'S' but show anyway. */
 2616                 setproctitle("init [S]");
 2617             } else
 2618                 runlevel = '*';
 2619             break;
 2620         case '*': /* BOOT -> NORMAL */
 2621             INITDBG(L_VB, "BOOT -> NORMAL");
 2622             if (runlevel != newlevel)
 2623                 loglevel = newlevel;
 2624             runlevel = newlevel;
 2625             did_boot = 1;
 2626             warn = 1;
 2627             break;
 2628         case 'S': /* Ended SU mode */
 2629         case 's':
 2630             INITDBG(L_VB, "END SU MODE");
 2631             newlevel = get_init_default();
 2632             if (!did_boot && newlevel != 'S')
 2633                 runlevel = '*';
 2634             else {
 2635                 if (runlevel != newlevel)
 2636                     loglevel = newlevel;
 2637                 runlevel = newlevel;
 2638                 oldlevel = 'S';
 2639             }
 2640             warn = 1;
 2641             for(ch = family; ch; ch = ch->next)
 2642                 if (strcmp(ch->rlevel, "S") == 0)
 2643                 ch->flags &= ~(FAILING|WAITING|XECUTED);
 2644             break;
 2645         default:
 2646             if (warn)
 2647               initlog(L_VB,
 2648                 "no more processes left in this runlevel");
 2649             warn = 0;
 2650             loglevel = -1;
 2651             if (got_signals == 0)
 2652                 check_init_fifo();
 2653             break;
 2654     }
 2655     if (loglevel > 0) {
 2656         initlog(L_VB, "Entering runlevel: %c", runlevel);
 2657         wrote_utmp_rlevel = 0;
 2658         wrote_wtmp_rlevel = 0;
 2659         write_utmp_wtmp("runlevel", "~~", runlevel + 256 * oldlevel, RUN_LVL, "~");
 2660         thislevel = runlevel;
 2661         prevlevel = oldlevel;
 2662         setproctitle("init [%c]", (int)runlevel);
 2663     }
 2664         Write_Runlevel_Log(runlevel);
 2665   }
 2666 }
 2667 
 2668 /*
 2669  *  Init got hit by a signal. See which signal it is,
 2670  *  and act accordingly.
 2671  */
 2672 static
 2673 void process_signals()
 2674 {
 2675   CHILD     *ch;
 2676   int       pwrstat;
 2677   int       oldlevel;
 2678   int       fd;
 2679   char      c;
 2680 
 2681   if (ISMEMBER(got_signals, SIGPWR)) {
 2682     INITDBG(L_VB, "got SIGPWR");
 2683     /* See _what_ kind of SIGPWR this is. */
 2684     pwrstat = 0;
 2685     if ((fd = open(PWRSTAT, O_RDONLY)) >= 0) {
 2686         if (read(fd, &c, 1) != 1)
 2687             c = 0;
 2688         pwrstat = c;
 2689         close(fd);
 2690         unlink(PWRSTAT);
 2691     } else if ((fd = open(PWRSTAT_OLD, O_RDONLY)) >= 0) {
 2692         /* Path changed 2010-03-20.  Look for the old path for a while. */
 2693         initlog(L_VB, "warning: found obsolete path %s, use %s instead",
 2694             PWRSTAT_OLD, PWRSTAT);
 2695         if (read(fd, &c, 1) != 1)
 2696             c = 0;
 2697         pwrstat = c;
 2698         close(fd);
 2699         unlink(PWRSTAT_OLD);
 2700         }
 2701     do_power_fail(pwrstat);
 2702     DELSET(got_signals, SIGPWR);
 2703   }
 2704 
 2705   if (ISMEMBER(got_signals, SIGINT)) {
 2706 #if defined(SIGINT_ONLYONCE) && (SIGINT_ONLYONCE == 1)
 2707     /* Ignore any further signal from keyboard */
 2708     struct sigaction sa;
 2709     SETSIG(sa, SIGINT, SIG_IGN, SA_RESTART);
 2710 #endif
 2711     INITDBG(L_VB, "got SIGINT");
 2712     /* Tell ctrlaltdel entry to start up */
 2713     for(ch = family; ch; ch = ch->next)
 2714         if (ch->action == CTRLALTDEL)
 2715             ch->flags &= ~XECUTED;
 2716     DELSET(got_signals, SIGINT);
 2717   }
 2718 
 2719   if (ISMEMBER(got_signals, SIGWINCH)) {
 2720     INITDBG(L_VB, "got SIGWINCH");
 2721     /* Tell kbrequest entry to start up */
 2722     for(ch = family; ch; ch = ch->next)
 2723         if (ch->action == KBREQUEST)
 2724             ch->flags &= ~XECUTED;
 2725     DELSET(got_signals, SIGWINCH);
 2726   }
 2727 
 2728   if (ISMEMBER(got_signals, SIGALRM)) {
 2729     INITDBG(L_VB, "got SIGALRM");
 2730     /* The timer went off: check it out */
 2731     DELSET(got_signals, SIGALRM);
 2732   }
 2733 
 2734   if (ISMEMBER(got_signals, SIGCHLD)) {
 2735     INITDBG(L_VB, "got SIGCHLD");
 2736     /* First set flag to 0 */
 2737     DELSET(got_signals, SIGCHLD);
 2738 
 2739     /* See which child this was */
 2740     for(ch = family; ch; ch = ch->next)
 2741         if (ch->flags & ZOMBIE) {
 2742         INITDBG(L_VB, "Child died, PID= %d", ch->pid);
 2743         ch->flags &= ~(RUNNING|ZOMBIE|WAITING);
 2744         if (ch->process[0] != '+')
 2745             write_utmp_wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL);
 2746         }
 2747 
 2748   }
 2749 
 2750   if (ISMEMBER(got_signals, SIGHUP)) {
 2751     INITDBG(L_VB, "got SIGHUP");
 2752 #if CHANGE_WAIT
 2753     /* Are we waiting for a child? */
 2754     for(ch = family; ch; ch = ch->next)
 2755         if (ch->flags & WAITING) break;
 2756     if (ch == NULL)
 2757 #endif
 2758     {
 2759         /* We need to go into a new runlevel */
 2760         oldlevel = runlevel;
 2761 #ifdef INITLVL
 2762         runlevel = read_level(0);
 2763 #endif
 2764         if (runlevel == 'U') {
 2765             runlevel = oldlevel;
 2766             my_re_exec();
 2767         } else {
 2768             if (oldlevel != 'S' && runlevel == 'S') console_stty();
 2769             if (runlevel == '6' || runlevel == '0' ||
 2770                 runlevel == '1') console_stty();
 2771             read_inittab();
 2772             fail_cancel();
 2773             setproctitle("init [%c]", (int)runlevel);
 2774             DELSET(got_signals, SIGHUP);
 2775         }
 2776                 Write_Runlevel_Log(runlevel);
 2777     }
 2778   }
 2779   if (ISMEMBER(got_signals, SIGUSR1)) {
 2780     /*
 2781      *  SIGUSR1 means close and reopen /run/initctl
 2782      */
 2783     INITDBG(L_VB, "got SIGUSR1");
 2784     if (pipe_fd)
 2785            close(pipe_fd);
 2786     pipe_fd = -1;
 2787     DELSET(got_signals, SIGUSR1);
 2788   }
 2789   else if (ISMEMBER(got_signals, SIGUSR2)) {
 2790        /* SIGUSR1 mean close the pipe and leave it closed */
 2791        INITDBG(L_VB, "got SIGUSR2");
 2792        if (pipe_fd)
 2793            close(pipe_fd);
 2794        pipe_fd = -2;
 2795        DELSET(got_signals, SIGUSR2);
 2796   }
 2797 }
 2798 
 2799 /*
 2800  *  The main loop
 2801  */ 
 2802 static
 2803 void init_main(void)
 2804 {
 2805   CHILD         *ch;
 2806   struct sigaction  sa;
 2807   sigset_t      sgt;
 2808   int           f, st;
 2809 
 2810   if (!reload) {
 2811   
 2812 #if INITDEBUG
 2813     /*
 2814      * Fork so we can debug the init process.
 2815      */
 2816     if ((f = fork()) > 0) {
 2817         static const char killmsg[] = "PRNT: init killed.\r\n";
 2818         pid_t rc;
 2819 
 2820         while((rc = wait(&st)) != f)
 2821             if (rc < 0 && errno == ECHILD)
 2822                 break;
 2823         safe_write(1, killmsg, sizeof(killmsg) - 1);
 2824         while(1) pause();
 2825     }
 2826 #endif
 2827 
 2828 #ifdef __linux__
 2829     /*
 2830      *  Tell the kernel to send us SIGINT when CTRL-ALT-DEL
 2831      *  is pressed, and that we want to handle keyboard signals.
 2832      */
 2833     init_reboot(BMAGIC_SOFT);
 2834     if ((f = open(VT_MASTER, O_RDWR | O_NOCTTY)) >= 0) {
 2835         (void) ioctl(f, KDSIGACCEPT, SIGWINCH);
 2836         close(f);
 2837     } else
 2838         (void) ioctl(0, KDSIGACCEPT, SIGWINCH);
 2839 #endif
 2840 
 2841     /*
 2842      *  Ignore all signals.
 2843      */
 2844     for(f = 1; f <= NSIG; f++)
 2845         SETSIG(sa, f, SIG_IGN, SA_RESTART);
 2846   }
 2847 
 2848   SETSIG(sa, SIGALRM,  signal_handler, 0);
 2849   SETSIG(sa, SIGHUP,   signal_handler, 0);
 2850   SETSIG(sa, SIGINT,   signal_handler, 0);
 2851   SETSIG(sa, SIGCHLD,  chld_handler, SA_RESTART);
 2852   SETSIG(sa, SIGPWR,   signal_handler, 0);
 2853   SETSIG(sa, SIGWINCH, signal_handler, 0);
 2854   SETSIG(sa, SIGUSR1,  signal_handler, 0);
 2855   SETSIG(sa, SIGUSR2,  signal_handler, 0);
 2856   SETSIG(sa, SIGSTOP,  stop_handler, SA_RESTART);
 2857   SETSIG(sa, SIGTSTP,  stop_handler, SA_RESTART);
 2858   SETSIG(sa, SIGCONT,  cont_handler, SA_RESTART);
 2859   SETSIG(sa, SIGSEGV,  (void (*)(int))segv_handler, SA_RESTART);
 2860 
 2861   console_init();
 2862 
 2863   if (!reload) {
 2864     int fd;
 2865 
 2866     /* Close whatever files are open, and reset the console. */
 2867     close(0);
 2868     close(1);
 2869     close(2);
 2870     console_stty();
 2871     setsid();
 2872 
 2873     /*
 2874      *  Set default PATH variable.
 2875      */
 2876     setenv("PATH", PATH_DEFAULT, 1 /* Overwrite */);
 2877 
 2878     /*
 2879      *  Initialize /var/run/utmp (only works if /var is on
 2880      *  root and mounted rw)
 2881      */
 2882     if ((fd = open(UTMP_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0644)) >= 0)
 2883         close(fd);
 2884 
 2885     /*
 2886      *  Say hello to the world
 2887      */
 2888     initlog(L_CO, bootmsg, "booting");
 2889 
 2890     /*
 2891      *  See if we have to start an emergency shell.
 2892      */
 2893     if (emerg_shell) {
 2894         pid_t rc;
 2895         SETSIG(sa, SIGCHLD, SIG_DFL, SA_RESTART);
 2896         if (spawn(&ch_emerg, &f) > 0) {
 2897             while((rc = wait(&st)) != f)
 2898                 if (rc < 0 && errno == ECHILD)
 2899                     break;
 2900         }
 2901         SETSIG(sa, SIGCHLD,  chld_handler, SA_RESTART);
 2902     }
 2903 
 2904     /*
 2905      *  Start normal boot procedure.
 2906      */
 2907     runlevel = '#';
 2908     read_inittab();
 2909   
 2910   } else {
 2911     /*
 2912      *  Restart: unblock signals and let the show go on
 2913      */
 2914     initlog(L_CO, bootmsg, "reloading");
 2915     sigfillset(&sgt);
 2916     sigprocmask(SIG_UNBLOCK, &sgt, NULL);
 2917 
 2918     /*
 2919      *  Set default PATH variable.
 2920      */
 2921     setenv("PATH", PATH_DEFAULT, 0 /* Don't overwrite */);
 2922   }
 2923   start_if_needed();
 2924 
 2925   while(1) {
 2926 
 2927      /* See if we need to make the boot transitions. */
 2928      boot_transitions();
 2929      INITDBG(L_VB, "init_main: waiting..");
 2930 
 2931      /* Check if there are processes to be waited on. */
 2932      for(ch = family; ch; ch = ch->next)
 2933     if ((ch->flags & RUNNING) && ch->action != BOOT) break;
 2934 
 2935 #if CHANGE_WAIT
 2936      /* Wait until we get hit by some signal. */
 2937      while (ch != NULL && got_signals == 0) {
 2938     if (ISMEMBER(got_signals, SIGHUP)) {
 2939         /* See if there are processes to be waited on. */
 2940         for(ch = family; ch; ch = ch->next)
 2941             if (ch->flags & WAITING) break;
 2942     }
 2943     if (ch != NULL) check_init_fifo();
 2944      }
 2945 #else /* CHANGE_WAIT */
 2946      if (ch != NULL && got_signals == 0) check_init_fifo();
 2947 #endif /* CHANGE_WAIT */
 2948 
 2949      /* Check the 'failing' flags */
 2950      fail_check();
 2951 
 2952      /* Process any signals. */
 2953      process_signals();
 2954 
 2955      /* See what we need to start up (again) */
 2956      start_if_needed();
 2957   }
 2958   /*NOTREACHED*/
 2959 }
 2960 
 2961 /*
 2962  * Tell the user about the syntax we expect.
 2963  */
 2964 static
 2965 void usage(char *s)
 2966 {
 2967     fprintf(stderr, "Usage: %s {-e VAR[=VAL] | [-t SECONDS] {0|1|2|3|4|5|6|S|s|Q|q|A|a|B|b|C|c|U|u}}\n", s);
 2968     exit(1);
 2969 }
 2970 
 2971 static
 2972 int telinit(char *progname, int argc, char **argv)
 2973 {
 2974 #ifdef TELINIT_USES_INITLVL
 2975     FILE            *fp;
 2976 #endif
 2977     struct init_request request;
 2978     struct sigaction    sa;
 2979     int         f, fd, l;
 2980     char            *env = NULL;
 2981 
 2982     memset(&request, 0, sizeof(request));
 2983     request.magic     = INIT_MAGIC;
 2984 
 2985     while ((f = getopt(argc, argv, "t:e:")) != EOF) switch(f) {
 2986         case 't':
 2987             sleep_time = atoi(optarg);
 2988             break;
 2989         case 'e':
 2990             if (env == NULL)
 2991                 env = request.i.data;
 2992             l = strlen(optarg);
 2993             if (env + l + 2 > request.i.data + sizeof(request.i.data)) {
 2994                 fprintf(stderr, "%s: -e option data "
 2995                     "too large\n", progname);
 2996                 exit(1);
 2997             }
 2998             memcpy(env, optarg, l);
 2999             env += l;
 3000             *env++ = 0;
 3001             break;
 3002         default:
 3003             usage(progname);
 3004             break;
 3005     }
 3006 
 3007     if (env) *env++ = 0;
 3008 
 3009     if (env) {
 3010         if (argc != optind)
 3011             usage(progname);
 3012         request.cmd = INIT_CMD_SETENV;
 3013     } else {
 3014         if (argc - optind != 1 || strlen(argv[optind]) != 1)
 3015             usage(progname);
 3016         if (!strchr("0123456789SsQqAaBbCcUu", argv[optind][0]))
 3017             usage(progname);
 3018         request.cmd = INIT_CMD_RUNLVL;
 3019         request.runlevel  = argv[optind][0];
 3020         request.sleeptime = sleep_time;
 3021     }
 3022 
 3023     /* Change to the root directory. */
 3024     if (0 != chdir("/"))
 3025         initlog(L_VB, "unable to chdir to /: %s",
 3026             strerror(errno));
 3027 
 3028     /* Open the fifo and write a command. */
 3029     /* Make sure we don't hang on opening /run/initctl */
 3030     SETSIG(sa, SIGALRM, signal_handler, 0);
 3031     alarm(3);
 3032     if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0) {
 3033         ssize_t p = 0;
 3034         size_t s  = sizeof(request);
 3035         void *ptr = &request;
 3036 
 3037         while (s > 0) {
 3038             p = write(fd, ptr, s);
 3039             if (p < 0) {
 3040                 if (errno == EINTR || errno == EAGAIN)
 3041                     continue;
 3042                 break;
 3043             }
 3044             ptr += p;
 3045             s -= p;
 3046         }
 3047         close(fd);
 3048         alarm(0);
 3049         return 0;
 3050     }
 3051 
 3052 #ifdef TELINIT_USES_INITLVL
 3053     if (request.cmd == INIT_CMD_RUNLVL) {
 3054         /* Fallthrough to the old method. */
 3055 
 3056         /* Now write the new runlevel. */
 3057         if ((fp = fopen(INITLVL, "w")) == NULL) {
 3058             fprintf(stderr, "%s: cannot create %s\n",
 3059                 progname, INITLVL);
 3060             exit(1);
 3061         }
 3062         fprintf(fp, "%s %d", argv[optind], sleep_time);
 3063         fclose(fp);
 3064 
 3065         /* And tell init about the pending runlevel change. */
 3066         if (kill(INITPID, SIGHUP) < 0) perror(progname);
 3067 
 3068         return 0;
 3069     }
 3070 #endif
 3071 
 3072     fprintf(stderr, "%s: ", progname);
 3073     if (ISMEMBER(got_signals, SIGALRM)) {
 3074         fprintf(stderr, "timeout opening/writing control channel %s\n",
 3075             INIT_FIFO);
 3076     } else {
 3077         perror(INIT_FIFO);
 3078     }
 3079     return 1;
 3080 }
 3081 
 3082 /*
 3083  * Main entry for init and telinit.
 3084  */
 3085 int main(int argc, char **argv)
 3086 {
 3087     char            *p;
 3088     int         f;
 3089     int         isinit;
 3090 #ifdef WITH_SELINUX
 3091     int         enforce = 0;
 3092 #endif
 3093 
 3094     /* Get my own name */
 3095     if ((p = strrchr(argv[0], '/')) != NULL)
 3096         p++;
 3097     else
 3098         p = argv[0];
 3099 
 3100         if ( (argc == 2) && (! strcmp(argv[1], "--version") ) )
 3101         {
 3102            printf("SysV init version: %s\n\n", VERSION);
 3103            exit(0);
 3104         }
 3105 
 3106     /* Common umask */
 3107     umask(umask(077) | 022);
 3108 
 3109     /* Quick check */
 3110     if (geteuid() != 0) {
 3111         fprintf(stderr, "%s: must be superuser.\n", p);
 3112         exit(1);
 3113     }
 3114 
 3115     /*
 3116      *  Is this telinit or init ?
 3117      */
 3118     isinit = (getpid() == 1);
 3119     for (f = 1; f < argc; f++) {
 3120         if (!strcmp(argv[f], "-i") || !strcmp(argv[f], "--init")) {
 3121             isinit = 1;
 3122             break;
 3123         }
 3124     }
 3125     if (!isinit) exit(telinit(p, argc, argv));
 3126 
 3127     /*
 3128      *  Check for re-exec
 3129      */     
 3130     if (check_pipe(STATE_PIPE)) {
 3131 
 3132         receive_state(STATE_PIPE);
 3133 
 3134         myname = istrdup(argv[0]);
 3135         argv0 = argv[0];
 3136         maxproclen = 0;
 3137         for (f = 0; f < argc; f++)
 3138             maxproclen += strlen(argv[f]) + 1;
 3139         reload = 1;
 3140         setproctitle("init [%c]", (int)runlevel);
 3141 
 3142         init_main();
 3143     }
 3144 
 3145     /* Check command line arguments */
 3146     maxproclen = strlen(argv[0]) + 1;
 3147     for(f = 1; f < argc; f++) {
 3148         if (!strcmp(argv[f], "single") || !strcmp(argv[f], "-s"))
 3149             dfl_level = 'S';
 3150         else if (!strcmp(argv[f], "-a") || !strcmp(argv[f], "auto"))
 3151             putenv("AUTOBOOT=YES");
 3152         else if (!strcmp(argv[f], "-b") || !strcmp(argv[f],"emergency"))
 3153             emerg_shell = 1;
 3154         else if (!strcmp(argv[f], "-z")) {
 3155             /* Ignore -z xxx */
 3156             if (argv[f + 1]) f++;
 3157         } else if (strchr("0123456789sS", argv[f][0])
 3158             && strlen(argv[f]) == 1)
 3159             dfl_level = argv[f][0];
 3160         /* "init u" in the very beginning makes no sense */
 3161         if (dfl_level == 's') dfl_level = 'S';
 3162         maxproclen += strlen(argv[f]) + 1;
 3163     }
 3164 
 3165 #ifdef WITH_SELINUX
 3166     if (getenv("SELINUX_INIT") == NULL) {
 3167          if (is_selinux_enabled() != 1) {
 3168         if (selinux_init_load_policy(&enforce) == 0) {
 3169              putenv("SELINUX_INIT=YES");
 3170           execv(myname, argv);
 3171         } else {
 3172           if (enforce > 0) {
 3173         /* SELinux in enforcing mode but load_policy failed */
 3174         /* At this point, we probably can't open /dev/console, so log() won't work */
 3175         fprintf(stderr,"Unable to load SELinux Policy. Machine is in enforcing mode. Halting now.\n");
 3176         exit(1);
 3177           }
 3178         }
 3179       }
 3180     }
 3181 #endif  
 3182     /* Start booting. */
 3183     argv0 = argv[0];
 3184     argv[1] = NULL;
 3185     setproctitle("init boot");
 3186     init_main();
 3187 
 3188     /*NOTREACHED*/
 3189     return 0;
 3190 }