Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/init/init.c


Ignore:
Timestamp:
Nov 6, 2007, 11:01:53 AM (16 years ago)
Author:
Bruno Cornec
Message:
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/stable/mindi-busybox/init/init.c

    r821 r1770  
    1010 */
    1111
    12 #include "busybox.h"
    13 #include <stdio.h>
    14 #include <stdlib.h>
    15 #include <errno.h>
     12#include "libbb.h"
    1613#include <paths.h>
    17 #include <signal.h>
    18 #include <stdarg.h>
    19 #include <string.h>
    20 #include <termios.h>
    21 #include <unistd.h>
    22 #include <limits.h>
    23 #include <fcntl.h>
    24 #include <sys/ioctl.h>
    25 #include <sys/types.h>
    26 #include <sys/wait.h>
     14//#include <signal.h>
     15//#include <sys/ioctl.h>
     16//#include <sys/wait.h>
    2717#include <sys/reboot.h>
    2818
    29 #include "init_shared.h"
    30 
    31 
    32 #ifdef CONFIG_SYSLOGD
     19#if ENABLE_FEATURE_INIT_SYSLOG
    3320# include <sys/syslog.h>
    3421#endif
    3522
    36 
    37 #ifdef CONFIG_SELINUX
    38 # include <selinux/selinux.h>
    39 #endif /* CONFIG_SELINUX */
    40 
    41 
    4223#define INIT_BUFFS_SIZE 256
    43 
    44 /* From <linux/vt.h> */
    45 struct vt_stat {
    46     unsigned short v_active;    /* active vt */
    47     unsigned short v_signal;    /* signal to send */
    48     unsigned short v_state; /* vt bitmask */
     24#define CONSOLE_NAME_SIZE 32
     25#define MAXENV  16      /* Number of env. vars */
     26
     27#if ENABLE_FEATURE_INIT_COREDUMPS
     28/*
     29 * When a file named CORE_ENABLE_FLAG_FILE exists, setrlimit is called
     30 * before processes are spawned to set core file size as unlimited.
     31 * This is for debugging only.  Don't use this is production, unless
     32 * you want core dumps lying about....
     33 */
     34#define CORE_ENABLE_FLAG_FILE "/.init_enable_core"
     35#include <sys/resource.h>
     36#endif
     37
     38#define INITTAB      "/etc/inittab" /* inittab file location */
     39#ifndef INIT_SCRIPT
     40#define INIT_SCRIPT  "/etc/init.d/rcS"  /* Default sysinit script. */
     41#endif
     42
     43/* Allowed init action types */
     44#define SYSINIT     0x001
     45#define RESPAWN     0x002
     46#define ASKFIRST    0x004
     47#define WAIT        0x008
     48#define ONCE        0x010
     49#define CTRLALTDEL  0x020
     50#define SHUTDOWN    0x040
     51#define RESTART     0x080
     52
     53/* A mapping between "inittab" action name strings and action type codes. */
     54struct init_action_type {
     55    const char *name;
     56    int action;
    4957};
    50 enum { VT_GETSTATE = 0x5603 };  /* get global vt state info */
     58
     59static const struct init_action_type actions[] = {
     60    {"sysinit", SYSINIT},
     61    {"respawn", RESPAWN},
     62    {"askfirst", ASKFIRST},
     63    {"wait", WAIT},
     64    {"once", ONCE},
     65    {"ctrlaltdel", CTRLALTDEL},
     66    {"shutdown", SHUTDOWN},
     67    {"restart", RESTART},
     68    {0, 0}
     69};
     70
     71/* Set up a linked list of init_actions, to be read from inittab */
     72struct init_action {
     73    struct init_action *next;
     74    int action;
     75    pid_t pid;
     76    char command[INIT_BUFFS_SIZE];
     77    char terminal[CONSOLE_NAME_SIZE];
     78};
     79
     80/* Static variables */
     81static struct init_action *init_action_list = NULL;
     82
     83#if !ENABLE_FEATURE_INIT_SYSLOG
     84static const char *log_console = VC_5;
     85#endif
     86#if !ENABLE_DEBUG_INIT
     87static sig_atomic_t got_cont = 0;
     88#endif
     89
     90enum {
     91    L_LOG = 0x1,
     92    L_CONSOLE = 0x2,
     93
     94#if ENABLE_FEATURE_EXTRA_QUIET
     95    MAYBE_CONSOLE = 0x0,
     96#else
     97    MAYBE_CONSOLE = L_CONSOLE,
     98#endif
     99
     100#ifndef RB_HALT_SYSTEM
     101    RB_HALT_SYSTEM = 0xcdef0123, /* FIXME: this overflows enum */
     102    RB_ENABLE_CAD = 0x89abcdef,
     103    RB_DISABLE_CAD = 0,
     104    RB_POWER_OFF = 0x4321fedc,
     105    RB_AUTOBOOT = 0x01234567,
     106#endif
     107};
     108
     109static const char *const environment[] = {
     110    "HOME=/",
     111    bb_PATH_root_path,
     112    "SHELL=/bin/sh",
     113    "USER=root",
     114    NULL
     115};
     116
     117/* Function prototypes */
     118static void delete_init_action(struct init_action *a);
     119static int waitfor(const struct init_action *a, pid_t pid);
     120#if !ENABLE_DEBUG_INIT
     121static void shutdown_signal(int sig);
     122#endif
     123
     124#if !ENABLE_DEBUG_INIT
     125static void loop_forever(void)
     126{
     127    while (1)
     128        sleep(1);
     129}
     130#endif
     131
     132/* Print a message to the specified device.
     133 * Device may be bitwise-or'd from L_LOG | L_CONSOLE */
     134#if ENABLE_DEBUG_INIT
     135#define messageD message
     136#else
     137#define messageD(...)  do {} while (0)
     138#endif
     139static void message(int device, const char *fmt, ...)
     140    __attribute__ ((format(printf, 2, 3)));
     141static void message(int device, const char *fmt, ...)
     142{
     143#if !ENABLE_FEATURE_INIT_SYSLOG
     144    static int log_fd = -1;
     145#endif
     146
     147    va_list arguments;
     148    int l;
     149    char msg[128];
     150
     151    msg[0] = '\r';
     152    va_start(arguments, fmt);
     153    vsnprintf(msg + 1, sizeof(msg) - 2, fmt, arguments);
     154    va_end(arguments);
     155    msg[sizeof(msg) - 2] = '\0';
     156    l = strlen(msg);
     157
     158#if ENABLE_FEATURE_INIT_SYSLOG
     159    /* Log the message to syslogd */
     160    if (device & L_LOG) {
     161        /* don't out "\r" */
     162        openlog(applet_name, 0, LOG_DAEMON);
     163        syslog(LOG_INFO, "init: %s", msg + 1);
     164        closelog();
     165    }
     166    msg[l++] = '\n';
     167    msg[l] = '\0';
     168#else
     169    msg[l++] = '\n';
     170    msg[l] = '\0';
     171    /* Take full control of the log tty, and never close it.
     172     * It's mine, all mine!  Muhahahaha! */
     173    if (log_fd < 0) {
     174        if (!log_console) {
     175            log_fd = 2;
     176        } else {
     177            log_fd = device_open(log_console, O_WRONLY | O_NONBLOCK | O_NOCTTY);
     178            if (log_fd < 0) {
     179                bb_error_msg("can't log to %s", log_console);
     180                device = L_CONSOLE;
     181            } else {
     182                fcntl(log_fd, F_SETFD, FD_CLOEXEC);
     183            }
     184        }
     185    }
     186    if (device & L_LOG) {
     187        full_write(log_fd, msg, l);
     188        if (log_fd == 2)
     189            return; /* don't print dup messages */
     190    }
     191#endif
     192
     193    if (device & L_CONSOLE) {
     194        /* Send console messages to console so people will see them. */
     195        full_write(2, msg, l);
     196    }
     197}
     198
     199/* Set terminal settings to reasonable defaults */
     200static void set_sane_term(void)
     201{
     202    struct termios tty;
     203
     204    tcgetattr(STDIN_FILENO, &tty);
     205
     206    /* set control chars */
     207    tty.c_cc[VINTR] = 3;    /* C-c */
     208    tty.c_cc[VQUIT] = 28;   /* C-\ */
     209    tty.c_cc[VERASE] = 127; /* C-? */
     210    tty.c_cc[VKILL] = 21;   /* C-u */
     211    tty.c_cc[VEOF] = 4; /* C-d */
     212    tty.c_cc[VSTART] = 17;  /* C-q */
     213    tty.c_cc[VSTOP] = 19;   /* C-s */
     214    tty.c_cc[VSUSP] = 26;   /* C-z */
     215
     216    /* use line dicipline 0 */
     217    tty.c_line = 0;
     218
     219    /* Make it be sane */
     220    tty.c_cflag &= CBAUD | CBAUDEX | CSIZE | CSTOPB | PARENB | PARODD;
     221    tty.c_cflag |= CREAD | HUPCL | CLOCAL;
     222
     223    /* input modes */
     224    tty.c_iflag = ICRNL | IXON | IXOFF;
     225
     226    /* output modes */
     227    tty.c_oflag = OPOST | ONLCR;
     228
     229    /* local modes */
     230    tty.c_lflag =
     231        ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
     232
     233    tcsetattr(STDIN_FILENO, TCSANOW, &tty);
     234}
    51235
    52236/* From <linux/serial.h> */
     
    71255    unsigned long   iomap_base; /* cookie passed into ioremap */
    72256    int reserved[1];
     257    /* Paranoia (imagine 64bit kernel overwriting 32bit userspace stack) */
     258    uint32_t bbox_reserved[16];
    73259};
    74 
    75 
    76 #ifndef _PATH_STDPATH
    77 #define _PATH_STDPATH   "/usr/bin:/bin:/usr/sbin:/sbin"
    78 #endif
    79 
    80 #if defined CONFIG_FEATURE_INIT_COREDUMPS
    81 /*
    82  * When a file named CORE_ENABLE_FLAG_FILE exists, setrlimit is called
    83  * before processes are spawned to set core file size as unlimited.
    84  * This is for debugging only.  Don't use this is production, unless
    85  * you want core dumps lying about....
    86  */
    87 #define CORE_ENABLE_FLAG_FILE "/.init_enable_core"
    88 #include <sys/resource.h>
    89 #endif
    90 
    91 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
    92 
    93 #define INITTAB      "/etc/inittab" /* inittab file location */
    94 #ifndef INIT_SCRIPT
    95 #define INIT_SCRIPT  "/etc/init.d/rcS"  /* Default sysinit script. */
    96 #endif
    97 
    98 #define MAXENV  16      /* Number of env. vars */
    99 
    100 #define CONSOLE_BUFF_SIZE 32
    101 
    102 /* Allowed init action types */
    103 #define SYSINIT     0x001
    104 #define RESPAWN     0x002
    105 #define ASKFIRST    0x004
    106 #define WAIT        0x008
    107 #define ONCE        0x010
    108 #define CTRLALTDEL  0x020
    109 #define SHUTDOWN    0x040
    110 #define RESTART     0x080
    111 
    112 /* A mapping between "inittab" action name strings and action type codes. */
    113 struct init_action_type {
    114     const char *name;
    115     int action;
    116 };
    117 
    118 static const struct init_action_type actions[] = {
    119     {"sysinit", SYSINIT},
    120     {"respawn", RESPAWN},
    121     {"askfirst", ASKFIRST},
    122     {"wait", WAIT},
    123     {"once", ONCE},
    124     {"ctrlaltdel", CTRLALTDEL},
    125     {"shutdown", SHUTDOWN},
    126     {"restart", RESTART},
    127     {0, 0}
    128 };
    129 
    130 /* Set up a linked list of init_actions, to be read from inittab */
    131 struct init_action {
    132     pid_t pid;
    133     char command[INIT_BUFFS_SIZE];
    134     char terminal[CONSOLE_BUFF_SIZE];
    135     struct init_action *next;
    136     int action;
    137 };
    138 
    139 /* Static variables */
    140 static struct init_action *init_action_list = NULL;
    141 static char console[CONSOLE_BUFF_SIZE] = CONSOLE_DEV;
    142 
    143 #ifndef CONFIG_SYSLOGD
    144 static char *log_console = VC_5;
    145 #endif
    146 #if !ENABLE_DEBUG_INIT
    147 static sig_atomic_t got_cont = 0;
    148 #endif
    149 
    150 enum {
    151     LOG = 0x1,
    152     CONSOLE = 0x2,
    153 
    154 #if defined CONFIG_FEATURE_EXTRA_QUIET
    155     MAYBE_CONSOLE = 0x0,
    156 #else
    157     MAYBE_CONSOLE = CONSOLE,
    158 #endif
    159 
    160 #ifndef RB_HALT_SYSTEM
    161     RB_HALT_SYSTEM = 0xcdef0123, /* FIXME: this overflows enum */
    162     RB_ENABLE_CAD = 0x89abcdef,
    163     RB_DISABLE_CAD = 0,
    164     RB_POWER_OFF = 0x4321fedc,
    165     RB_AUTOBOOT = 0x01234567,
    166 #endif
    167 };
    168 
    169 static const char * const environment[] = {
    170     "HOME=/",
    171     "PATH=" _PATH_STDPATH,
    172     "SHELL=/bin/sh",
    173     "USER=root",
    174     NULL
    175 };
    176 
    177 /* Function prototypes */
    178 static void delete_init_action(struct init_action *a);
    179 static int waitfor(const struct init_action *a, pid_t pid);
    180 #if !ENABLE_DEBUG_INIT
    181 static void shutdown_signal(int sig);
    182 #endif
    183 
    184 static void loop_forever(void)
    185 {
    186     while (1)
    187         sleep(1);
    188 }
    189 
    190 /* Print a message to the specified device.
    191  * Device may be bitwise-or'd from LOG | CONSOLE */
    192 #if ENABLE_DEBUG_INIT
    193 #define messageD message
    194 #else
    195 static inline void messageD(int ATTRIBUTE_UNUSED device,
    196                 const char ATTRIBUTE_UNUSED *fmt, ...)
    197 {
    198 }
    199 #endif
    200 static void message(int device, const char *fmt, ...)
    201     __attribute__ ((format(printf, 2, 3)));
    202 static void message(int device, const char *fmt, ...)
    203 {
    204     va_list arguments;
    205     int l;
    206     RESERVE_CONFIG_BUFFER(msg, 1024);
    207 #ifndef CONFIG_SYSLOGD
    208     static int log_fd = -1;
    209 #endif
    210 
    211     msg[0] = '\r';
    212         va_start(arguments, fmt);
    213     l = vsnprintf(msg + 1, 1024 - 2, fmt, arguments) + 1;
    214         va_end(arguments);
    215 
    216 #ifdef CONFIG_SYSLOGD
    217     /* Log the message to syslogd */
    218     if (device & LOG) {
    219         /* don`t out "\r\n" */
    220         openlog(bb_applet_name, 0, LOG_DAEMON);
    221         syslog(LOG_INFO, "%s", msg + 1);
    222         closelog();
    223     }
    224 
    225     msg[l++] = '\n';
    226     msg[l] = 0;
    227 #else
    228 
    229     msg[l++] = '\n';
    230     msg[l] = 0;
    231     /* Take full control of the log tty, and never close it.
    232      * It's mine, all mine!  Muhahahaha! */
    233     if (log_fd < 0) {
    234         if ((log_fd = device_open(log_console, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
    235             log_fd = -2;
    236             bb_error_msg("Bummer, can't write to log on %s!", log_console);
    237             device = CONSOLE;
    238         } else {
    239             fcntl(log_fd, F_SETFD, FD_CLOEXEC);
    240         }
    241     }
    242     if ((device & LOG) && (log_fd >= 0)) {
    243         bb_full_write(log_fd, msg, l);
    244     }
    245 #endif
    246 
    247     if (device & CONSOLE) {
    248         int fd = device_open(CONSOLE_DEV,
    249                     O_WRONLY | O_NOCTTY | O_NONBLOCK);
    250         /* Always send console messages to /dev/console so people will see them. */
    251         if (fd >= 0) {
    252             bb_full_write(fd, msg, l);
    253             close(fd);
    254 #if ENABLE_DEBUG_INIT
    255         /* all descriptors may be closed */
    256         } else {
    257             bb_error_msg("Bummer, can't print: ");
    258             va_start(arguments, fmt);
    259             vfprintf(stderr, fmt, arguments);
    260             va_end(arguments);
    261 #endif
    262         }
    263     }
    264     RELEASE_CONFIG_BUFFER(msg);
    265 }
    266 
    267 /* Set terminal settings to reasonable defaults */
    268 static void set_term(void)
    269 {
    270     struct termios tty;
    271 
    272     tcgetattr(STDIN_FILENO, &tty);
    273 
    274     /* set control chars */
    275     tty.c_cc[VINTR] = 3;    /* C-c */
    276     tty.c_cc[VQUIT] = 28;   /* C-\ */
    277     tty.c_cc[VERASE] = 127; /* C-? */
    278     tty.c_cc[VKILL] = 21;   /* C-u */
    279     tty.c_cc[VEOF] = 4; /* C-d */
    280     tty.c_cc[VSTART] = 17;  /* C-q */
    281     tty.c_cc[VSTOP] = 19;   /* C-s */
    282     tty.c_cc[VSUSP] = 26;   /* C-z */
    283 
    284     /* use line dicipline 0 */
    285     tty.c_line = 0;
    286 
    287     /* Make it be sane */
    288     tty.c_cflag &= CBAUD | CBAUDEX | CSIZE | CSTOPB | PARENB | PARODD;
    289     tty.c_cflag |= CREAD | HUPCL | CLOCAL;
    290 
    291 
    292     /* input modes */
    293     tty.c_iflag = ICRNL | IXON | IXOFF;
    294 
    295     /* output modes */
    296     tty.c_oflag = OPOST | ONLCR;
    297 
    298     /* local modes */
    299     tty.c_lflag =
    300         ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
    301 
    302     tcsetattr(STDIN_FILENO, TCSANOW, &tty);
    303 }
    304 
    305260static void console_init(void)
    306261{
    307     int fd;
    308     int tried = 0;
    309     struct vt_stat vt;
    310262    struct serial_struct sr;
    311263    char *s;
    312264
    313     if ((s = getenv("CONSOLE")) != NULL || (s = getenv("console")) != NULL) {
    314         safe_strncpy(console, s, sizeof(console));
    315 #if 0 /* #cpu(sparc) */
    316     /* sparc kernel supports console=tty[ab] parameter which is also
    317      * passed to init, so catch it here */
    318         /* remap tty[ab] to /dev/ttyS[01] */
    319         if (strcmp(s, "ttya") == 0)
    320             safe_strncpy(console, SC_0, sizeof(console));
    321         else if (strcmp(s, "ttyb") == 0)
    322             safe_strncpy(console, SC_1, sizeof(console));
    323 #endif
     265    s = getenv("CONSOLE");
     266    if (!s) s = getenv("console");
     267    if (s) {
     268        int fd = open(s, O_RDWR | O_NONBLOCK | O_NOCTTY);
     269        if (fd >= 0) {
     270            dup2(fd, 0);
     271            dup2(fd, 1);
     272            dup2(fd, 2);
     273            while (fd > 2) close(fd--);
     274        }
     275        messageD(L_LOG, "console='%s'", s);
    324276    } else {
    325         /* 2.2 kernels: identify the real console backend and try to use it */
    326         if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
    327             /* this is a serial console */
    328             snprintf(console, sizeof(console) - 1, SC_FORMAT, sr.line);
    329         } else if (ioctl(0, VT_GETSTATE, &vt) == 0) {
    330             /* this is linux virtual tty */
    331             snprintf(console, sizeof(console) - 1, VC_FORMAT, vt.v_active);
     277        /* Make sure fd 0,1,2 are not closed */
     278        bb_sanitize_stdio();
     279    }
     280
     281    s = getenv("TERM");
     282    if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
     283        /* Force the TERM setting to vt102 for serial console --
     284         * if TERM is set to linux (the default) */
     285        if (!s || strcmp(s, "linux") == 0)
     286            putenv((char*)"TERM=vt102");
     287#if !ENABLE_FEATURE_INIT_SYSLOG
     288        log_console = NULL;
     289#endif
     290    } else if (!s)
     291        putenv((char*)"TERM=linux");
     292}
     293
     294static void fixup_argv(char **argv)
     295{
     296    /* Fix up argv[0] to be certain we claim to be init */
     297    strncpy(argv[0], "init", strlen(argv[0]));
     298
     299    /* Wipe argv[1]-argv[N] so they don't clutter the ps listing */
     300    while (*++argv)
     301        memset(*argv, 0, strlen(*argv));
     302}
     303
     304/* Open the new terminal device */
     305static void open_stdio_to_tty(const char* tty_name, int fail)
     306{
     307    /* empty tty_name means "use init's tty", else... */
     308    if (tty_name[0]) {
     309        int fd = device_open(tty_name, O_RDWR);
     310        if (fd < 0) {
     311            message(L_LOG | L_CONSOLE, "Can't open %s: %s",
     312                tty_name, strerror(errno));
     313            if (fail)
     314                _exit(1);
     315#if !ENABLE_DEBUG_INIT
     316            shutdown_signal(SIGUSR1);
     317#else
     318            _exit(2);
     319#endif
    332320        } else {
    333             safe_strncpy(console, CONSOLE_DEV, sizeof(console));
    334             tried++;
    335         }
    336     }
    337 
    338     while ((fd = open(console, O_RDONLY | O_NONBLOCK)) < 0 && tried < 2) {
    339         /* Can't open selected console -- try
    340             logical system console and VT_MASTER */
    341         safe_strncpy(console, (tried == 0 ? CONSOLE_DEV : CURRENT_VC),
    342                             sizeof(console));
    343         tried++;
    344     }
    345     if (fd < 0) {
    346         /* Perhaps we should panic here? */
    347 #ifndef CONFIG_SYSLOGD
    348         log_console =
    349 #endif
    350         safe_strncpy(console, bb_dev_null, sizeof(console));
    351     } else {
    352         s = getenv("TERM");
    353         /* check for serial console */
    354         if (ioctl(fd, TIOCGSERIAL, &sr) == 0) {
    355             /* Force the TERM setting to vt102 for serial console --
    356              * if TERM is set to linux (the default) */
    357             if (s == NULL || strcmp(s, "linux") == 0)
    358                 putenv("TERM=vt102");
    359 #ifndef CONFIG_SYSLOGD
    360             log_console = console;
    361 #endif
    362         } else {
    363             if (s == NULL)
    364                 putenv("TERM=linux");
    365         }
    366         close(fd);
    367     }
    368     messageD(LOG, "console=%s", console);
    369 }
    370 
    371 static void fixup_argv(int argc, char **argv, char *new_argv0)
    372 {
    373     int len;
    374 
    375     /* Fix up argv[0] to be certain we claim to be init */
    376     len = strlen(argv[0]);
    377     memset(argv[0], 0, len);
    378     safe_strncpy(argv[0], new_argv0, len + 1);
    379 
    380     /* Wipe argv[1]-argv[N] so they don't clutter the ps listing */
    381     len = 1;
    382     while (argc > len) {
    383         memset(argv[len], 0, strlen(argv[len]));
    384         len++;
    385     }
    386 }
    387 
    388 /* Open the new terminal device */
    389 static void open_new_terminal(const char * const device, const int fail) {
    390     struct stat sb;
    391 
    392     if ((device_open(device, O_RDWR)) < 0) {
    393         if (stat(device, &sb) != 0) {
    394             message(LOG | CONSOLE, "device '%s' does not exist.", device);
    395         } else {
    396             message(LOG | CONSOLE, "Bummer, can't open %s", device);
    397         }
    398         if (fail)
    399             _exit(1);
    400         /* else */
    401 #if !ENABLE_DEBUG_INIT
    402         shutdown_signal(SIGUSR1);
    403 #else
    404         _exit(2);
    405 #endif
    406     }
     321            dup2(fd, 0);
     322            dup2(fd, 1);
     323            dup2(fd, 2);
     324            if (fd > 2) close(fd);
     325        }
     326    }
     327    set_sane_term();
    407328}
    408329
     
    411332    int i;
    412333    pid_t pid;
    413     char *s, *tmpCmd, *cmd[INIT_BUFFS_SIZE], *cmdpath;
     334    char *s, *tmpCmd, *cmdpath;
     335    char *cmd[INIT_BUFFS_SIZE];
    414336    char buf[INIT_BUFFS_SIZE + 6];  /* INIT_BUFFS_SIZE+strlen("exec ")+1 */
    415337    sigset_t nmask, omask;
    416     static const char press_enter[] =
    417 #ifdef CUSTOMIZED_BANNER
    418 #include CUSTOMIZED_BANNER
    419 #endif
    420         "\nPlease press Enter to activate this console. ";
    421338
    422339    /* Block sigchild while forking.  */
     
    424341    sigaddset(&nmask, SIGCHLD);
    425342    sigprocmask(SIG_BLOCK, &nmask, &omask);
    426 
    427     if ((pid = fork()) == 0) {
    428 
    429         /* Clean up */
    430         close(0);
    431         close(1);
    432         close(2);
    433         sigprocmask(SIG_SETMASK, &omask, NULL);
    434 
    435         /* Reset signal handlers that were set by the parent process */
    436         signal(SIGUSR1, SIG_DFL);
    437         signal(SIGUSR2, SIG_DFL);
    438         signal(SIGINT, SIG_DFL);
    439         signal(SIGTERM, SIG_DFL);
    440         signal(SIGHUP, SIG_DFL);
    441         signal(SIGQUIT, SIG_DFL);
    442         signal(SIGCONT, SIG_DFL);
    443         signal(SIGSTOP, SIG_DFL);
    444         signal(SIGTSTP, SIG_DFL);
    445 
    446         /* Create a new session and make ourself the process
    447          * group leader */
    448         setsid();
    449 
    450         /* Open the new terminal device */
    451         open_new_terminal(a->terminal, 1);
    452 
    453         /* Make sure the terminal will act fairly normal for us */
    454         set_term();
    455         /* Setup stdout, stderr for the new process so
    456          * they point to the supplied terminal */
    457         dup(0);
    458         dup(0);
    459 
    460         /* If the init Action requires us to wait, then force the
    461          * supplied terminal to be the controlling tty. */
    462         if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
    463 
    464             /* Now fork off another process to just hang around */
     343    pid = fork();
     344    sigprocmask(SIG_SETMASK, &omask, NULL);
     345
     346    if (pid)
     347        return pid;
     348
     349    /* Reset signal handlers that were set by the parent process */
     350    signal(SIGUSR1, SIG_DFL);
     351    signal(SIGUSR2, SIG_DFL);
     352    signal(SIGINT, SIG_DFL);
     353    signal(SIGTERM, SIG_DFL);
     354    signal(SIGHUP, SIG_DFL);
     355    signal(SIGQUIT, SIG_DFL);
     356    signal(SIGCONT, SIG_DFL);
     357    signal(SIGSTOP, SIG_DFL);
     358    signal(SIGTSTP, SIG_DFL);
     359
     360    /* Create a new session and make ourself the process
     361     * group leader */
     362    setsid();
     363
     364    /* Open the new terminal device */
     365    open_stdio_to_tty(a->terminal, 1);
     366
     367    /* If the init Action requires us to wait, then force the
     368     * supplied terminal to be the controlling tty. */
     369    if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
     370
     371        /* Now fork off another process to just hang around */
     372        if ((pid = fork()) < 0) {
     373            message(L_LOG | L_CONSOLE, "Can't fork");
     374            _exit(1);
     375        }
     376
     377        if (pid > 0) {
     378
     379            /* We are the parent -- wait till the child is done */
     380            signal(SIGINT, SIG_IGN);
     381            signal(SIGTSTP, SIG_IGN);
     382            signal(SIGQUIT, SIG_IGN);
     383            signal(SIGCHLD, SIG_DFL);
     384
     385            waitfor(NULL, pid);
     386            /* See if stealing the controlling tty back is necessary */
     387            if (tcgetpgrp(0) != getpid())
     388                _exit(0);
     389
     390            /* Use a temporary process to steal the controlling tty. */
    465391            if ((pid = fork()) < 0) {
    466                 message(LOG | CONSOLE, "Can't fork!");
     392                message(L_LOG | L_CONSOLE, "Can't fork");
    467393                _exit(1);
    468394            }
    469 
    470             if (pid > 0) {
    471 
    472                 /* We are the parent -- wait till the child is done */
    473                 signal(SIGINT, SIG_IGN);
    474                 signal(SIGTSTP, SIG_IGN);
    475                 signal(SIGQUIT, SIG_IGN);
    476                 signal(SIGCHLD, SIG_DFL);
    477 
    478                 waitfor(NULL, pid);
    479                 /* See if stealing the controlling tty back is necessary */
    480                 if (tcgetpgrp(0) != getpid())
    481                     _exit(0);
    482 
    483                 /* Use a temporary process to steal the controlling tty. */
    484                 if ((pid = fork()) < 0) {
    485                     message(LOG | CONSOLE, "Can't fork!");
    486                     _exit(1);
    487                 }
    488                 if (pid == 0) {
    489                     setsid();
    490                     ioctl(0, TIOCSCTTY, 1);
    491                     _exit(0);
    492                 }
    493                 waitfor(NULL, pid);
     395            if (pid == 0) {
     396                setsid();
     397                ioctl(0, TIOCSCTTY, 1);
    494398                _exit(0);
    495399            }
    496 
    497             /* Now fall though to actually execute things */
    498         }
    499 
    500         /* See if any special /bin/sh requiring characters are present */
    501         if (strpbrk(a->command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {
    502             cmd[0] = (char *)DEFAULT_SHELL;
    503             cmd[1] = "-c";
    504             cmd[2] = strcat(strcpy(buf, "exec "), a->command);
    505             cmd[3] = NULL;
     400            waitfor(NULL, pid);
     401            _exit(0);
     402        }
     403
     404        /* Now fall though to actually execute things */
     405    }
     406
     407    /* See if any special /bin/sh requiring characters are present */
     408    if (strpbrk(a->command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {
     409        cmd[0] = (char*)DEFAULT_SHELL;
     410        cmd[1] = (char*)"-c";
     411        cmd[2] = strcat(strcpy(buf, "exec "), a->command);
     412        cmd[3] = NULL;
     413    } else {
     414        /* Convert command (char*) into cmd (char**, one word per string) */
     415        strcpy(buf, a->command);
     416        s = buf;
     417        for (tmpCmd = buf, i = 0; (tmpCmd = strsep(&s, " \t")) != NULL;) {
     418            if (*tmpCmd != '\0') {
     419                cmd[i] = tmpCmd;
     420                i++;
     421            }
     422        }
     423        cmd[i] = NULL;
     424    }
     425
     426    cmdpath = cmd[0];
     427
     428    /*
     429     * Interactive shells want to see a dash in argv[0].  This
     430     * typically is handled by login, argv will be setup this
     431     * way if a dash appears at the front of the command path
     432     * (like "-/bin/sh").
     433     */
     434    if (*cmdpath == '-') {
     435        /* skip over the dash */
     436        ++cmdpath;
     437
     438        /* find the last component in the command pathname */
     439        s = bb_get_last_path_component(cmdpath);
     440
     441        /* make a new argv[0] */
     442        if ((cmd[0] = malloc(strlen(s) + 2)) == NULL) {
     443            message(L_LOG | L_CONSOLE, bb_msg_memory_exhausted);
     444            cmd[0] = cmdpath;
    506445        } else {
    507             /* Convert command (char*) into cmd (char**, one word per string) */
    508             strcpy(buf, a->command);
    509             s = buf;
    510             for (tmpCmd = buf, i = 0; (tmpCmd = strsep(&s, " \t")) != NULL;) {
    511                 if (*tmpCmd != '\0') {
    512                     cmd[i] = tmpCmd;
    513                     i++;
    514                 }
    515             }
    516             cmd[i] = NULL;
    517         }
    518 
    519         cmdpath = cmd[0];
    520 
     446            cmd[0][0] = '-';
     447            strcpy(cmd[0] + 1, s);
     448        }
     449#if ENABLE_FEATURE_INIT_SCTTY
     450        /* Establish this process as session leader and
     451         * (attempt) to make the tty (if any) a controlling tty.
     452         */
     453        setsid();
     454        ioctl(0, TIOCSCTTY, 0 /*don't steal it*/);
     455#endif
     456    }
     457
     458#if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__)
     459    if (a->action & ASKFIRST) {
     460        static const char press_enter[] ALIGN1 =
     461#ifdef CUSTOMIZED_BANNER
     462#include CUSTOMIZED_BANNER
     463#endif
     464            "\nPlease press Enter to activate this console. ";
     465        char c;
    521466        /*
    522            Interactive shells want to see a dash in argv[0].  This
    523            typically is handled by login, argv will be setup this
    524            way if a dash appears at the front of the command path
    525            (like "-/bin/sh").
     467         * Save memory by not exec-ing anything large (like a shell)
     468         * before the user wants it. This is critical if swap is not
     469         * enabled and the system has low memory. Generally this will
     470         * be run on the second virtual console, and the first will
     471         * be allowed to start a shell or whatever an init script
     472         * specifies.
    526473         */
    527 
    528         if (*cmdpath == '-') {
    529 
    530             /* skip over the dash */
    531             ++cmdpath;
    532 
    533             /* find the last component in the command pathname */
    534             s = bb_get_last_path_component(cmdpath);
    535 
    536             /* make a new argv[0] */
    537             if ((cmd[0] = malloc(strlen(s) + 2)) == NULL) {
    538                 message(LOG | CONSOLE, bb_msg_memory_exhausted);
    539                 cmd[0] = cmdpath;
    540             } else {
    541                 cmd[0][0] = '-';
    542                 strcpy(cmd[0] + 1, s);
    543             }
    544 #ifdef CONFIG_FEATURE_INIT_SCTTY
    545             /* Establish this process as session leader and
    546              * (attempt) to make the tty (if any) a controlling tty.
    547              */
    548             (void) setsid();
    549             (void) ioctl(0, TIOCSCTTY, 0/*don't steal it*/);
    550 #endif
    551         }
    552 
    553 #if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__)
    554         if (a->action & ASKFIRST) {
    555             char c;
    556             /*
    557              * Save memory by not exec-ing anything large (like a shell)
    558              * before the user wants it. This is critical if swap is not
    559              * enabled and the system has low memory. Generally this will
    560              * be run on the second virtual console, and the first will
    561              * be allowed to start a shell or whatever an init script
    562              * specifies.
    563              */
    564             messageD(LOG, "Waiting for enter to start '%s'"
    565                         "(pid %d, terminal %s)\n",
    566                       cmdpath, getpid(), a->terminal);
    567             bb_full_write(1, press_enter, sizeof(press_enter) - 1);
    568             while(read(0, &c, 1) == 1 && c != '\n')
    569                 ;
    570         }
    571 #endif
    572 
    573         /* Log the process name and args */
    574         message(LOG, "Starting pid %d, console %s: '%s'",
    575                   getpid(), a->terminal, cmdpath);
    576 
    577 #if defined CONFIG_FEATURE_INIT_COREDUMPS
    578         {
    579             struct stat sb;
    580             if (stat(CORE_ENABLE_FLAG_FILE, &sb) == 0) {
    581                 struct rlimit limit;
    582 
    583                 limit.rlim_cur = RLIM_INFINITY;
    584                 limit.rlim_max = RLIM_INFINITY;
    585                 setrlimit(RLIMIT_CORE, &limit);
    586             }
    587         }
    588 #endif
    589 
    590         /* Now run it.  The new program will take over this PID,
    591          * so nothing further in init.c should be run. */
    592         execv(cmdpath, cmd);
    593 
    594         /* We're still here?  Some error happened. */
    595         message(LOG | CONSOLE, "Bummer, could not run '%s': %m", cmdpath);
    596         _exit(-1);
    597     }
    598     sigprocmask(SIG_SETMASK, &omask, NULL);
    599     return pid;
     474        messageD(L_LOG, "waiting for enter to start '%s'"
     475                    "(pid %d, tty '%s')\n",
     476                  cmdpath, getpid(), a->terminal);
     477        full_write(1, press_enter, sizeof(press_enter) - 1);
     478        while (read(0, &c, 1) == 1 && c != '\n')
     479            ;
     480    }
     481#endif
     482    /* Log the process name and args */
     483    message(L_LOG, "starting pid %d, tty '%s': '%s'",
     484              getpid(), a->terminal, cmdpath);
     485
     486#if ENABLE_FEATURE_INIT_COREDUMPS
     487    {
     488        struct stat sb;
     489        if (stat(CORE_ENABLE_FLAG_FILE, &sb) == 0) {
     490            struct rlimit limit;
     491
     492            limit.rlim_cur = RLIM_INFINITY;
     493            limit.rlim_max = RLIM_INFINITY;
     494            setrlimit(RLIMIT_CORE, &limit);
     495        }
     496    }
     497#endif
     498    /* Now run it.  The new program will take over this PID,
     499     * so nothing further in init.c should be run. */
     500    BB_EXECVP(cmdpath, cmd);
     501
     502    /* We're still here?  Some error happened. */
     503    message(L_LOG | L_CONSOLE, "Cannot run '%s': %s",
     504            cmdpath, strerror(errno));
     505    _exit(-1);
    600506}
    601507
     
    607513    runpid = (NULL == a)? pid : run(a);
    608514    while (1) {
    609         wpid = waitpid(runpid,&status,0);
     515        wpid = waitpid(runpid, &status, 0);
    610516        if (wpid == runpid)
    611517            break;
     
    628534        tmp = a->next;
    629535        if (a->action == action) {
    630             if (access(a->terminal, R_OK | W_OK)) {
     536            /* a->terminal of "" means "init's console" */
     537            if (a->terminal[0] && access(a->terminal, R_OK | W_OK)) {
    631538                delete_init_action(a);
    632539            } else if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
     
    654561     * linux/kernel/sys.c, which can cause the machine to panic when
    655562     * the init process is killed.... */
    656     if ((pid = fork()) == 0) {
     563    pid = vfork();
     564    if (pid == 0) { /* child */
    657565        reboot(magic);
    658566        _exit(0);
    659567    }
    660     waitpid (pid, NULL, 0);
     568    waitpid(pid, NULL, 0);
    661569}
    662570
     
    684592    sigprocmask(SIG_BLOCK, &block_signals, NULL);
    685593
     594    message(L_CONSOLE | L_LOG, "The system is going down NOW!");
     595
    686596    /* Allow Ctrl-Alt-Del to reboot system. */
    687597    init_reboot(RB_ENABLE_CAD);
    688598
    689     message(CONSOLE | LOG, "The system is going down NOW !!");
     599    /* Send signals to every process _except_ pid 1 */
     600    message(L_CONSOLE | L_LOG, "Sending SIG%s to all processes", "TERM");
     601    kill(-1, SIGTERM);
    690602    sync();
    691 
    692     /* Send signals to every process _except_ pid 1 */
    693     message(CONSOLE | LOG, init_sending_format, "TERM");
    694     kill(-1, SIGTERM);
    695603    sleep(1);
     604
     605    message(L_CONSOLE | L_LOG, "Sending SIG%s to all processes", "KILL");
     606    kill(-1, SIGKILL);
    696607    sync();
    697 
    698     message(CONSOLE | LOG, init_sending_format, "KILL");
    699     kill(-1, SIGKILL);
    700608    sleep(1);
    701 
    702     sync();
    703609}
    704610
     
    727633            sigprocmask(SIG_UNBLOCK, &unblock_signals, NULL);
    728634
    729             /* Close whatever files are open. */
    730             close(0);
    731             close(1);
    732             close(2);
    733 
    734635            /* Open the new terminal device */
    735             open_new_terminal(a->terminal, 0);
    736 
    737             /* Make sure the terminal will act fairly normal for us */
    738             set_term();
    739             /* Setup stdout, stderr on the supplied terminal */
    740             dup(0);
    741             dup(0);
    742 
    743             messageD(CONSOLE | LOG, "Trying to re-exec %s", a->command);
    744             execl(a->command, a->command, NULL);
    745 
    746             message(CONSOLE | LOG, "exec of '%s' failed: %m",
    747                     a->command);
    748             sync();
     636            open_stdio_to_tty(a->terminal, 0);
     637
     638            messageD(L_CONSOLE | L_LOG, "Trying to re-exec %s", a->command);
     639            BB_EXECLP(a->command, a->command, NULL);
     640
     641            message(L_CONSOLE | L_LOG, "Cannot run '%s': %s",
     642                    a->command, strerror(errno));
    749643            sleep(2);
    750644            init_reboot(RB_HALT_SYSTEM);
     
    756650static void shutdown_signal(int sig)
    757651{
    758     char *m;
     652    const char *m;
    759653    int rb;
    760654
    761655    shutdown_system();
    762656
     657    m = "halt";
     658    rb = RB_HALT_SYSTEM;
    763659    if (sig == SIGTERM) {
    764660        m = "reboot";
     
    767663        m = "poweroff";
    768664        rb = RB_POWER_OFF;
    769     } else {
    770         m = "halt";
    771         rb = RB_HALT_SYSTEM;
    772     }
    773     message(CONSOLE | LOG, "Requesting system %s.", m);
    774     sync();
    775 
     665    }
     666    message(L_CONSOLE | L_LOG, "Requesting system %s", m);
    776667    /* allow time for last message to reach serial console */
    777668    sleep(2);
    778 
    779669    init_reboot(rb);
    780 
    781670    loop_forever();
    782671}
     
    805694}
    806695
    807 #endif                          /* ! ENABLE_DEBUG_INIT */
     696#endif  /* !ENABLE_DEBUG_INIT */
    808697
    809698static void new_init_action(int action, const char *command, const char *cons)
    810699{
    811700    struct init_action *new_action, *a, *last;
    812 
    813     if (*cons == '\0')
    814         cons = console;
    815701
    816702    if (strcmp(cons, bb_dev_null) == 0 && (action & ASKFIRST))
    817703        return;
    818 
    819     new_action = calloc((size_t) (1), sizeof(struct init_action));
    820     if (!new_action) {
    821         message(LOG | CONSOLE, "Memory allocation failure");
    822         loop_forever();
    823     }
    824704
    825705    /* Append to the end of the list */
     
    827707        /* don't enter action if it's already in the list,
    828708         * but do overwrite existing actions */
    829         if ((strcmp(a->command, command) == 0) &&
    830             (strcmp(a->terminal, cons) ==0)) {
     709        if ((strcmp(a->command, command) == 0)
     710         && (strcmp(a->terminal, cons) == 0)
     711        ) {
    831712            a->action = action;
    832             free(new_action);
    833713            return;
    834714        }
    835715        last = a;
    836716    }
     717
     718    new_action = xzalloc(sizeof(struct init_action));
    837719    if (last) {
    838720        last->next = new_action;
     
    843725    new_action->action = action;
    844726    strcpy(new_action->terminal, cons);
    845 #if 0   /* calloc zeroed always */
    846     new_action->pid = 0;
    847 #endif
    848     messageD(LOG|CONSOLE, "command='%s' action='%d' terminal='%s'\n",
     727    messageD(L_LOG | L_CONSOLE, "command='%s' action=%d tty='%s'\n",
    849728        new_action->command, new_action->action, new_action->terminal);
    850729}
     
    876755static void parse_inittab(void)
    877756{
    878 #ifdef CONFIG_FEATURE_USE_INITTAB
     757#if ENABLE_FEATURE_USE_INITTAB
    879758    FILE *file;
    880759    char buf[INIT_BUFFS_SIZE], lineAsRead[INIT_BUFFS_SIZE];
    881     char tmpConsole[CONSOLE_BUFF_SIZE];
     760    char tmpConsole[CONSOLE_NAME_SIZE];
    882761    char *id, *runlev, *action, *command, *eol;
    883762    const struct init_action_type *a = actions;
    884 
    885763
    886764    file = fopen(INITTAB, "r");
     
    889767#endif
    890768        /* Reboot on Ctrl-Alt-Del */
    891         new_init_action(CTRLALTDEL, "/sbin/reboot", "");
     769        new_init_action(CTRLALTDEL, "reboot", "");
    892770        /* Umount all filesystems on halt/reboot */
    893         new_init_action(SHUTDOWN, "/bin/umount -a -r", "");
     771        new_init_action(SHUTDOWN, "umount -a -r", "");
    894772        /* Swapoff on halt/reboot */
    895         if(ENABLE_SWAPONOFF) new_init_action(SHUTDOWN, "/sbin/swapoff -a", "");
     773        if (ENABLE_SWAPONOFF) new_init_action(SHUTDOWN, "swapoff -a", "");
    896774        /* Prepare to restart init when a HUP is received */
    897         new_init_action(RESTART, "/sbin/init", "");
     775        new_init_action(RESTART, "init", "");
    898776        /* Askfirst shell on tty1-4 */
    899777        new_init_action(ASKFIRST, bb_default_login_shell, "");
     
    905783
    906784        return;
    907 #ifdef CONFIG_FEATURE_USE_INITTAB
     785#if ENABLE_FEATURE_USE_INITTAB
    908786    }
    909787
     
    917795
    918796        /* Trim the trailing \n */
     797        //XXX: chomp() ?
    919798        eol = strrchr(id, '\n');
    920799        if (eol != NULL)
     
    927806        runlev = strchr(id, ':');
    928807        if (runlev == NULL || *(runlev + 1) == '\0') {
    929             message(LOG | CONSOLE, "Bad inittab entry: %s", lineAsRead);
     808            message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);
    930809            continue;
    931810        } else {
     
    937816        action = strchr(runlev, ':');
    938817        if (action == NULL || *(action + 1) == '\0') {
    939             message(LOG | CONSOLE, "Bad inittab entry: %s", lineAsRead);
     818            message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);
    940819            continue;
    941820        } else {
     
    947826        command = strchr(action, ':');
    948827        if (command == NULL || *(command + 1) == '\0') {
    949             message(LOG | CONSOLE, "Bad inittab entry: %s", lineAsRead);
     828            message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);
    950829            continue;
    951830        } else {
     
    958837            if (strcmp(a->name, action) == 0) {
    959838                if (*id != '\0') {
    960                     if(strncmp(id, "/dev/", 5) == 0)
     839                    if (strncmp(id, "/dev/", 5) == 0)
    961840                        id += 5;
    962841                    strcpy(tmpConsole, "/dev/");
    963842                    safe_strncpy(tmpConsole + 5, id,
    964                         CONSOLE_BUFF_SIZE - 5);
     843                        sizeof(tmpConsole) - 5);
    965844                    id = tmpConsole;
    966845                }
     
    971850        if (a->name == 0) {
    972851            /* Choke on an unknown action */
    973             message(LOG | CONSOLE, "Bad inittab entry: %s", lineAsRead);
     852            message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);
    974853        }
    975854    }
    976855    fclose(file);
    977     return;
    978 #endif                          /* CONFIG_FEATURE_USE_INITTAB */
    979 }
    980 
    981 #ifdef CONFIG_FEATURE_USE_INITTAB
     856#endif /* FEATURE_USE_INITTAB */
     857}
     858
     859#if ENABLE_FEATURE_USE_INITTAB
    982860static void reload_signal(int sig ATTRIBUTE_UNUSED)
    983861{
    984862    struct init_action *a, *tmp;
    985863
    986     message(LOG, "Reloading /etc/inittab");
     864    message(L_LOG, "reloading /etc/inittab");
    987865
    988866    /* disable old entrys */
     
    996874    for (a = init_action_list; a; a = tmp) {
    997875        tmp = a->next;
    998         if (a->action & (ONCE | SYSINIT | WAIT ) &&
    999                 a->pid == 0 ) {
     876        if ((a->action & (ONCE | SYSINIT | WAIT)) && a->pid == 0) {
    1000877            delete_init_action(a);
    1001878        }
    1002879    }
    1003880    run_actions(RESPAWN);
    1004     return;
    1005 }
    1006 #endif                          /* CONFIG_FEATURE_USE_INITTAB */
    1007 
     881}
     882#endif  /* FEATURE_USE_INITTAB */
     883
     884int init_main(int argc, char **argv);
    1008885int init_main(int argc, char **argv)
    1009886{
     
    1011888    pid_t wpid;
    1012889
     890    die_sleep = 30 * 24*60*60; /* if xmalloc will ever die... */
     891
    1013892    if (argc > 1 && !strcmp(argv[1], "-q")) {
    1014         return kill(1,SIGHUP);
     893        return kill(1, SIGHUP);
    1015894    }
    1016895#if !ENABLE_DEBUG_INIT
    1017896    /* Expect to be invoked as init with PID=1 or be invoked as linuxrc */
    1018     if (getpid() != 1 &&
    1019         (!ENABLE_FEATURE_INITRD || !strstr(bb_applet_name, "linuxrc")))
    1020     {
     897    if (getpid() != 1
     898     && (!ENABLE_FEATURE_INITRD || !strstr(applet_name, "linuxrc"))
     899    ) {
    1021900        bb_show_usage();
    1022901    }
     
    1038917#endif
    1039918
     919
    1040920    /* Figure out where the default console should be */
    1041921    console_init();
    1042 
    1043     /* Close whatever files are open, and reset the console. */
    1044     close(0);
    1045     close(1);
    1046     close(2);
    1047 
    1048     if (device_open(console, O_RDWR | O_NOCTTY) == 0) {
    1049         set_term();
    1050         close(0);
    1051     }
    1052 
     922    set_sane_term();
    1053923    chdir("/");
    1054924    setsid();
    1055925    {
    1056         const char * const *e;
     926        const char *const *e;
    1057927        /* Make sure environs is set to something sane */
    1058         for(e = environment; *e; e++)
     928        for (e = environment; *e; e++)
    1059929            putenv((char *) *e);
    1060930    }
     931
     932    if (argc > 1) setenv("RUNLEVEL", argv[1], 1);
     933
    1061934    /* Hello world */
    1062     message(MAYBE_CONSOLE | LOG, "init started:  %s", bb_msg_full_version);
     935    message(MAYBE_CONSOLE | L_LOG, "init started: %s", bb_banner);
    1063936
    1064937    /* Make sure there is enough memory to do something useful. */
     
    1067940
    1068941        if (!sysinfo(&info) &&
    1069             (info.mem_unit ? : 1) * (long long)info.totalram < MEGABYTE)
     942            (info.mem_unit ? : 1) * (long long)info.totalram < 1024*1024)
    1070943        {
    1071             message(CONSOLE,"Low memory: forcing swapon.");
     944            message(L_CONSOLE, "Low memory, forcing swapon");
    1072945            /* swapon -a requires /proc typically */
    1073             new_init_action(SYSINIT, "/bin/mount -t proc proc /proc", "");
     946            new_init_action(SYSINIT, "mount -t proc proc /proc", "");
    1074947            /* Try to turn on swap */
    1075             new_init_action(SYSINIT, "/sbin/swapon -a", "");
     948            new_init_action(SYSINIT, "swapon -a", "");
    1076949            run_actions(SYSINIT);   /* wait and removing */
    1077950        }
     
    1079952
    1080953    /* Check if we are supposed to be in single user mode */
    1081     if (argc > 1 && (!strcmp(argv[1], "single") ||
    1082                      !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) {
     954    if (argc > 1
     955     && (!strcmp(argv[1], "single") || !strcmp(argv[1], "-s") || LONE_CHAR(argv[1], '1'))
     956    ) {
    1083957        /* Start a shell on console */
    1084958        new_init_action(RESPAWN, bb_default_login_shell, "");
     
    1093967    }
    1094968
    1095 #ifdef CONFIG_SELINUX
     969#if ENABLE_SELINUX
    1096970    if (getenv("SELINUX_INIT") == NULL) {
    1097971        int enforce = 0;
    1098972
    1099         putenv("SELINUX_INIT=YES");
     973        putenv((char*)"SELINUX_INIT=YES");
    1100974        if (selinux_init_load_policy(&enforce) == 0) {
    1101             execv(argv[0], argv);
     975            BB_EXECVP(argv[0], argv);
    1102976        } else if (enforce > 0) {
    1103977            /* SELinux in enforcing mode but load_policy failed */
    1104978            /* At this point, we probably can't open /dev/console, so log() won't work */
    1105             message(CONSOLE,"Unable to load SELinux Policy. Machine is in enforcing mode. Halting now.");
     979            message(L_CONSOLE, "Cannot load SELinux Policy. "
     980                "Machine is in enforcing mode. Halting now.");
    1106981            exit(1);
    1107982        }
     
    1110985
    1111986    /* Make the command line just say "init"  -- thats all, nothing else */
    1112     fixup_argv(argc, argv, "init");
     987    fixup_argv(argv);
    1113988
    1114989    /* Now run everything that needs to be run */
     
    1123998    run_actions(ONCE);
    1124999
    1125 #ifdef CONFIG_FEATURE_USE_INITTAB
     1000#if ENABLE_FEATURE_USE_INITTAB
    11261001    /* Redefine SIGHUP to reread /etc/inittab */
    11271002    signal(SIGHUP, reload_signal);
    11281003#else
    11291004    signal(SIGHUP, SIG_IGN);
    1130 #endif /* CONFIG_FEATURE_USE_INITTAB */
    1131 
     1005#endif /* FEATURE_USE_INITTAB */
    11321006
    11331007    /* Now run the looping stuff for the rest of forever */
     
    11511025                     * restarted by run_actions() */
    11521026                    a->pid = 0;
    1153                     message(LOG, "Process '%s' (pid %d) exited. "
     1027                    message(L_LOG, "process '%s' (pid %d) exited. "
    11541028                            "Scheduling it for restart.",
    11551029                            a->command, wpid);
     
    11571031            }
    11581032            /* see if anyone else is waiting to be reaped */
    1159             wpid = waitpid (-1, NULL, WNOHANG);
    1160         }
    1161     }
    1162 }
     1033            wpid = waitpid(-1, NULL, WNOHANG);
     1034        }
     1035    }
     1036}
Note: See TracChangeset for help on using the changeset viewer.