Why have a separate CONFIG_INIT_SWAPON when we already have CONFIG_SWAPONOFF?
[oweals/busybox.git] / init / init.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini init implementation for busybox
4  *
5  * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
6  * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
7  * Adjusted by so many folks, it's impossible to keep track.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  *
23  */
24
25 /* Turn this on to disable all the dangerous
26    rebooting stuff when debugging.
27 #define DEBUG_INIT
28 */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <errno.h>
33 #include <paths.h>
34 #include <signal.h>
35 #include <stdarg.h>
36 #include <string.h>
37 #include <termios.h>
38 #include <unistd.h>
39 #include <limits.h>
40 #include <sys/fcntl.h>
41 #include <sys/ioctl.h>
42 #include <sys/types.h>
43 #include <sys/wait.h>
44 #include <sys/reboot.h>
45 #include "busybox.h"
46
47 #include "init_shared.h"
48
49
50 #ifdef CONFIG_SYSLOGD
51 # include <sys/syslog.h>
52 #endif
53
54
55 #define INIT_BUFFS_SIZE 256
56
57 /* From <linux/vt.h> */
58 struct vt_stat {
59         unsigned short v_active;        /* active vt */
60         unsigned short v_signal;        /* signal to send */
61         unsigned short v_state; /* vt bitmask */
62 };
63 static const int VT_GETSTATE = 0x5603;  /* get global vt state info */
64
65 /* From <linux/serial.h> */
66 struct serial_struct {
67         int     type;
68         int     line;
69         unsigned int    port;
70         int     irq;
71         int     flags;
72         int     xmit_fifo_size;
73         int     custom_divisor;
74         int     baud_base;
75         unsigned short  close_delay;
76         char    io_type;
77         char    reserved_char[1];
78         int     hub6;
79         unsigned short  closing_wait; /* time to wait before closing */
80         unsigned short  closing_wait2; /* no longer used... */
81         unsigned char   *iomem_base;
82         unsigned short  iomem_reg_shift;
83         unsigned int    port_high;
84         unsigned long   iomap_base;     /* cookie passed into ioremap */
85         int     reserved[1];
86 };
87
88
89 #ifndef _PATH_STDPATH
90 #define _PATH_STDPATH   "/usr/bin:/bin:/usr/sbin:/sbin"
91 #endif
92
93 #if defined CONFIG_FEATURE_INIT_COREDUMPS
94 /*
95  * When a file named CORE_ENABLE_FLAG_FILE exists, setrlimit is called
96  * before processes are spawned to set core file size as unlimited.
97  * This is for debugging only.  Don't use this is production, unless
98  * you want core dumps lying about....
99  */
100 #define CORE_ENABLE_FLAG_FILE "/.init_enable_core"
101 #include <sys/resource.h>
102 #include <sys/time.h>
103 #endif
104
105 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
106
107 #define INITTAB      "/etc/inittab"     /* inittab file location */
108 #ifndef INIT_SCRIPT
109 #define INIT_SCRIPT  "/etc/init.d/rcS"  /* Default sysinit script. */
110 #endif
111
112 #define MAXENV  16              /* Number of env. vars */
113
114 #define CONSOLE_BUFF_SIZE 32
115
116 /* Allowed init action types */
117 #define SYSINIT     0x001
118 #define RESPAWN     0x002
119 #define ASKFIRST    0x004
120 #define WAIT        0x008
121 #define ONCE        0x010
122 #define CTRLALTDEL  0x020
123 #define SHUTDOWN    0x040
124 #define RESTART     0x080
125
126 /* A mapping between "inittab" action name strings and action type codes. */
127 struct init_action_type {
128         const char *name;
129         int action;
130 };
131
132 static const struct init_action_type actions[] = {
133         {"sysinit", SYSINIT},
134         {"respawn", RESPAWN},
135         {"askfirst", ASKFIRST},
136         {"wait", WAIT},
137         {"once", ONCE},
138         {"ctrlaltdel", CTRLALTDEL},
139         {"shutdown", SHUTDOWN},
140         {"restart", RESTART},
141         {0, 0}
142 };
143
144 /* Set up a linked list of init_actions, to be read from inittab */
145 struct init_action {
146         pid_t pid;
147         char command[INIT_BUFFS_SIZE];
148         char terminal[CONSOLE_BUFF_SIZE];
149         struct init_action *next;
150         int action;
151 };
152
153 /* Static variables */
154 static struct init_action *init_action_list = NULL;
155 static char console[CONSOLE_BUFF_SIZE] = _PATH_CONSOLE;
156
157 #ifndef CONFIG_SYSLOGD
158 static char *log_console = VC_5;
159 #endif
160 static sig_atomic_t got_cont = 0;
161 static const int LOG = 0x1;
162 static const int CONSOLE = 0x2;
163
164 #if defined CONFIG_FEATURE_EXTRA_QUIET
165 static const int MAYBE_CONSOLE = 0x0;
166 #else
167 #define MAYBE_CONSOLE   CONSOLE
168 #endif
169 #ifndef RB_HALT_SYSTEM
170 static const int RB_HALT_SYSTEM = 0xcdef0123;
171 static const int RB_ENABLE_CAD = 0x89abcdef;
172 static const int RB_DISABLE_CAD = 0;
173
174 #define RB_POWER_OFF    0x4321fedc
175 static const int RB_AUTOBOOT = 0x01234567;
176 #endif
177
178 static const char * const environment[] = {
179         "HOME=/",
180         "PATH=" _PATH_STDPATH,
181         "SHELL=/bin/sh",
182         "USER=root",
183         NULL
184 };
185
186 /* Function prototypes */
187 static void delete_init_action(struct init_action *a);
188 static int waitfor(const struct init_action *a);
189 static void halt_signal(int sig);
190
191
192 static void loop_forever(void)
193 {
194         while (1)
195                 sleep(1);
196 }
197
198 /* Print a message to the specified device.
199  * Device may be bitwise-or'd from LOG | CONSOLE */
200 #ifndef DEBUG_INIT
201 static inline void messageD(int device, const char *fmt, ...)
202 {
203 }
204 #else
205 #define messageD message
206 #endif
207 static void message(int device, const char *fmt, ...)
208         __attribute__ ((format(printf, 2, 3)));
209 static void message(int device, const char *fmt, ...)
210 {
211         va_list arguments;
212         int l;
213         char msg[1024];
214 #ifndef CONFIG_SYSLOGD
215         static int log_fd = -1;
216 #endif
217
218         msg[0] = '\r';
219                 va_start(arguments, fmt);
220         l = vsnprintf(msg + 1, sizeof(msg) - 2, fmt, arguments) + 1;
221                 va_end(arguments);
222
223 #ifdef CONFIG_SYSLOGD
224         /* Log the message to syslogd */
225         if (device & LOG) {
226                 /* don`t out "\r\n" */
227                 openlog(bb_applet_name, 0, LOG_DAEMON);
228                 syslog(LOG_INFO, "%s", msg);
229                 closelog();
230         }
231
232         msg[l++] = '\n';
233         msg[l] = 0;
234 #else
235
236         msg[l++] = '\n';
237         msg[l] = 0;
238         /* Take full control of the log tty, and never close it.
239          * It's mine, all mine!  Muhahahaha! */
240         if (log_fd < 0) {
241                 if ((log_fd = device_open(log_console, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
242                         log_fd = -2;
243                         bb_error_msg("Bummer, can't write to log on %s!", log_console);
244                         device = CONSOLE;
245                 } else {
246                         fcntl(log_fd, F_SETFD, FD_CLOEXEC);
247                 }
248         }
249         if ((device & LOG) && (log_fd >= 0)) {
250                 bb_full_write(log_fd, msg, l);
251         }
252 #endif
253
254         if (device & CONSOLE) {
255                 int fd = device_open(_PATH_CONSOLE,
256                                         O_WRONLY | O_NOCTTY | O_NONBLOCK);
257                 /* Always send console messages to /dev/console so people will see them. */
258                 if (fd >= 0) {
259                         bb_full_write(fd, msg, l);
260                         close(fd);
261 #ifdef DEBUG_INIT
262                 /* all descriptors may be closed */
263                 } else {
264                         bb_error_msg("Bummer, can't print: ");
265                         va_start(arguments, fmt);
266                         vfprintf(stderr, fmt, arguments);
267                         va_end(arguments);
268 #endif
269                 }
270         }
271 }
272
273 /* Set terminal settings to reasonable defaults */
274 static void set_term(int fd)
275 {
276         struct termios tty;
277
278         tcgetattr(fd, &tty);
279
280         /* set control chars */
281         tty.c_cc[VINTR] = 3;    /* C-c */
282         tty.c_cc[VQUIT] = 28;   /* C-\ */
283         tty.c_cc[VERASE] = 127; /* C-? */
284         tty.c_cc[VKILL] = 21;   /* C-u */
285         tty.c_cc[VEOF] = 4;     /* C-d */
286         tty.c_cc[VSTART] = 17;  /* C-q */
287         tty.c_cc[VSTOP] = 19;   /* C-s */
288         tty.c_cc[VSUSP] = 26;   /* C-z */
289
290         /* use line dicipline 0 */
291         tty.c_line = 0;
292
293         /* Make it be sane */
294         tty.c_cflag &= CBAUD | CBAUDEX | CSIZE | CSTOPB | PARENB | PARODD;
295         tty.c_cflag |= CREAD | HUPCL | CLOCAL;
296
297
298         /* input modes */
299         tty.c_iflag = ICRNL | IXON | IXOFF;
300
301         /* output modes */
302         tty.c_oflag = OPOST | ONLCR;
303
304         /* local modes */
305         tty.c_lflag =
306                 ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
307
308         tcsetattr(fd, TCSANOW, &tty);
309 }
310
311 static void console_init(void)
312 {
313         int fd;
314         int tried = 0;
315         struct vt_stat vt;
316         struct serial_struct sr;
317         char *s;
318
319         if ((s = getenv("CONSOLE")) != NULL || (s = getenv("console")) != NULL) {
320                 safe_strncpy(console, s, sizeof(console));
321 #if #cpu(sparc)
322         /* sparc kernel supports console=tty[ab] parameter which is also
323          * passed to init, so catch it here */
324                 /* remap tty[ab] to /dev/ttyS[01] */
325                 if (strcmp(s, "ttya") == 0)
326                         safe_strncpy(console, SC_0, sizeof(console));
327                 else if (strcmp(s, "ttyb") == 0)
328                         safe_strncpy(console, SC_1, sizeof(console));
329 #endif
330         } else {
331                 /* 2.2 kernels: identify the real console backend and try to use it */
332                 if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
333                         /* this is a serial console */
334                         snprintf(console, sizeof(console) - 1, SC_FORMAT, sr.line);
335                 } else if (ioctl(0, VT_GETSTATE, &vt) == 0) {
336                         /* this is linux virtual tty */
337                         snprintf(console, sizeof(console) - 1, VC_FORMAT, vt.v_active);
338                 } else {
339                         safe_strncpy(console, _PATH_CONSOLE, sizeof(console));
340                         tried++;
341                 }
342         }
343
344         while ((fd = open(console, O_RDONLY | O_NONBLOCK)) < 0 && tried < 2) {
345                 /* Can't open selected console -- try
346                         logical system console and VT_MASTER */
347                 safe_strncpy(console, (tried == 0 ? _PATH_CONSOLE : CURRENT_VC),
348                                                         sizeof(console));
349                 tried++;
350         }
351         if (fd < 0) {
352                 /* Perhaps we should panic here? */
353 #ifndef CONFIG_SYSLOGD
354                 log_console =
355 #endif
356                 safe_strncpy(console, "/dev/null", sizeof(console));
357         } else {
358                 s = getenv("TERM");
359                 /* check for serial console */
360                 if (ioctl(fd, TIOCGSERIAL, &sr) == 0) {
361                         /* Force the TERM setting to vt102 for serial console --
362                          * if TERM is set to linux (the default) */
363                         if (s == NULL || strcmp(s, "linux") == 0)
364                                 putenv("TERM=vt102");
365 #ifndef CONFIG_SYSLOGD
366                         log_console = console;
367 #endif
368                 } else {
369                         if (s == NULL)
370                                 putenv("TERM=linux");
371                 }
372                 close(fd);
373         }
374         messageD(LOG, "console=%s", console);
375 }
376
377 static void fixup_argv(int argc, char **argv, char *new_argv0)
378 {
379         int len;
380
381         /* Fix up argv[0] to be certain we claim to be init */
382         len = strlen(argv[0]);
383         memset(argv[0], 0, len);
384         safe_strncpy(argv[0], new_argv0, len + 1);
385
386         /* Wipe argv[1]-argv[N] so they don't clutter the ps listing */
387         len = 1;
388         while (argc > len) {
389                 memset(argv[len], 0, strlen(argv[len]));
390                 len++;
391         }
392 }
393
394 static pid_t run(const struct init_action *a)
395 {
396         int i, junk;
397         pid_t pid;
398         char *s, *tmpCmd, *cmd[INIT_BUFFS_SIZE], *cmdpath;
399         char buf[INIT_BUFFS_SIZE + 6];  /* INIT_BUFFS_SIZE+strlen("exec ")+1 */
400         sigset_t nmask, omask;
401         static const char press_enter[] =
402 #ifdef CUSTOMIZED_BANNER
403 #include CUSTOMIZED_BANNER
404 #endif
405                 "\nPlease press Enter to activate this console. ";
406
407         /* Block sigchild while forking.  */
408         sigemptyset(&nmask);
409         sigaddset(&nmask, SIGCHLD);
410         sigprocmask(SIG_BLOCK, &nmask, &omask);
411
412         if ((pid = fork()) == 0) {
413                 struct stat sb;
414
415                 /* Clean up */
416                 close(0);
417                 close(1);
418                 close(2);
419                 sigprocmask(SIG_SETMASK, &omask, NULL);
420
421                 /* Reset signal handlers that were set by the parent process */
422                 signal(SIGUSR1, SIG_DFL);
423                 signal(SIGUSR2, SIG_DFL);
424                 signal(SIGINT, SIG_DFL);
425                 signal(SIGTERM, SIG_DFL);
426                 signal(SIGHUP, SIG_DFL);
427                 signal(SIGQUIT, SIG_DFL);
428                 signal(SIGCONT, SIG_DFL);
429                 signal(SIGSTOP, SIG_DFL);
430                 signal(SIGTSTP, SIG_DFL);
431
432                 /* Create a new session and make ourself the process
433                  * group leader */
434                 setsid();
435
436                 /* Open the new terminal device */
437                 if ((device_open(a->terminal, O_RDWR)) < 0) {
438                         if (stat(a->terminal, &sb) != 0) {
439                                 message(LOG | CONSOLE, "device '%s' does not exist.", a->terminal);
440                         } else {
441                                 message(LOG | CONSOLE, "Bummer, can't open %s", a->terminal);
442                         }
443                         _exit(1);
444                 }
445
446                 /* Make sure the terminal will act fairly normal for us */
447                 set_term(0);
448                 /* Setup stdout, stderr for the new process so
449                  * they point to the supplied terminal */
450                 dup(0);
451                 dup(0);
452
453                 /* If the init Action requires us to wait, then force the
454                  * supplied terminal to be the controlling tty. */
455                 if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
456                         pid_t pgrp, tmp_pid;
457
458                         /* Now fork off another process to just hang around */
459                         if ((pid = fork()) < 0) {
460                                 message(LOG | CONSOLE, "Can't fork!");
461                                 _exit(1);
462                         }
463
464                         if (pid > 0) {
465
466                                 /* We are the parent -- wait till the child is done */
467                                 signal(SIGINT, SIG_IGN);
468                                 signal(SIGTSTP, SIG_IGN);
469                                 signal(SIGQUIT, SIG_IGN);
470                                 signal(SIGCHLD, SIG_DFL);
471
472                                 /* Wait for child to exit */
473                                 while ((tmp_pid = waitpid(pid, &junk, 0)) != pid) {
474                                         if (tmp_pid == -1 && errno == ECHILD) {
475                                                 break;
476                                         }
477                                         /* FIXME handle other errors */
478                 }
479
480                                 /* See if stealing the controlling tty back is necessary */
481                                 pgrp = tcgetpgrp(0);
482                                 if (pgrp != getpid())
483                                         _exit(0);
484
485                                 /* Use a temporary process to steal the controlling tty. */
486                                 if ((pid = fork()) < 0) {
487                                         message(LOG | CONSOLE, "Can't fork!");
488                                         _exit(1);
489                                 }
490                                 if (pid == 0) {
491                                         setsid();
492                                         ioctl(0, TIOCSCTTY, 1);
493                                         _exit(0);
494                                 }
495                                 while ((tmp_pid = waitpid(pid, &junk, 0)) != pid) {
496                                         if (tmp_pid < 0 && errno == ECHILD)
497                                                 break;
498                                 }
499                                 _exit(0);
500                         }
501
502                         /* Now fall though to actually execute things */
503                 }
504
505                 /* See if any special /bin/sh requiring characters are present */
506                 if (strpbrk(a->command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {
507                         cmd[0] = (char *)DEFAULT_SHELL;
508                         cmd[1] = "-c";
509                         cmd[2] = strcat(strcpy(buf, "exec "), a->command);
510                         cmd[3] = NULL;
511                 } else {
512                         /* Convert command (char*) into cmd (char**, one word per string) */
513                         strcpy(buf, a->command);
514                         s = buf;
515                         for (tmpCmd = buf, i = 0; (tmpCmd = strsep(&s, " \t")) != NULL;) {
516                                 if (*tmpCmd != '\0') {
517                                         cmd[i] = tmpCmd;
518                                         i++;
519                                 }
520                         }
521                         cmd[i] = NULL;
522                 }
523
524                 cmdpath = cmd[0];
525
526                 /*
527                    Interactive shells want to see a dash in argv[0].  This
528                    typically is handled by login, argv will be setup this
529                    way if a dash appears at the front of the command path
530                    (like "-/bin/sh").
531                  */
532
533                 if (*cmdpath == '-') {
534
535                         /* skip over the dash */
536                         ++cmdpath;
537
538                         /* find the last component in the command pathname */
539                         s = bb_get_last_path_component(cmdpath);
540
541                         /* make a new argv[0] */
542                         if ((cmd[0] = malloc(strlen(s) + 2)) == NULL) {
543                                 message(LOG | CONSOLE, bb_msg_memory_exhausted);
544                                 cmd[0] = cmdpath;
545                         } else {
546                                 cmd[0][0] = '-';
547                                 strcpy(cmd[0] + 1, s);
548                         }
549 #ifdef CONFIG_FEATURE_INIT_SCTTY
550                         /* Establish this process as session leader and
551                          * (attempt) to make the tty (if any) a controlling tty.
552                          */
553                         (void) setsid();
554                         (void) ioctl(0, TIOCSCTTY, 0/*don't steal it*/);
555 #endif
556                 }
557
558 #if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__)
559                 if (a->action & ASKFIRST) {
560                         char c;
561                         /*
562                          * Save memory by not exec-ing anything large (like a shell)
563                          * before the user wants it. This is critical if swap is not
564                          * enabled and the system has low memory. Generally this will
565                          * be run on the second virtual console, and the first will
566                          * be allowed to start a shell or whatever an init script
567                          * specifies.
568                          */
569                         messageD(LOG, "Waiting for enter to start '%s'"
570                                                 "(pid %d, terminal %s)\n",
571                                           cmdpath, getpid(), a->terminal);
572                         bb_full_write(1, press_enter, sizeof(press_enter) - 1);
573                         while(read(0, &c, 1) == 1 && c != '\n')
574                                 ;
575                 }
576 #endif
577
578                 /* Log the process name and args */
579                 message(LOG, "Starting pid %d, console %s: '%s'",
580                                   getpid(), a->terminal, cmdpath);
581
582 #if defined CONFIG_FEATURE_INIT_COREDUMPS
583                 if (stat(CORE_ENABLE_FLAG_FILE, &sb) == 0) {
584                         struct rlimit limit;
585
586                         limit.rlim_cur = RLIM_INFINITY;
587                         limit.rlim_max = RLIM_INFINITY;
588                         setrlimit(RLIMIT_CORE, &limit);
589                 }
590 #endif
591
592                 /* Now run it.  The new program will take over this PID,
593                  * so nothing further in init.c should be run. */
594                 execv(cmdpath, cmd);
595
596                 /* We're still here?  Some error happened. */
597                 message(LOG | CONSOLE, "Bummer, could not run '%s': %m", cmdpath);
598                 _exit(-1);
599         }
600         sigprocmask(SIG_SETMASK, &omask, NULL);
601         return pid;
602 }
603
604 static int waitfor(const struct init_action *a)
605 {
606         int pid;
607         int status, wpid;
608
609         pid = run(a);
610         while (1) {
611                 wpid = waitpid(pid,&status,0);
612                 if (wpid == pid)
613                         break;
614                 if (wpid == -1 && errno == ECHILD) {
615                         /* we missed its termination */
616                         break;
617                 }
618                 /* FIXME other errors should maybe trigger an error, but allow
619                  * the program to continue */
620         }
621         return wpid;
622 }
623
624 /* Run all commands of a particular type */
625 static void run_actions(int action)
626 {
627         struct init_action *a, *tmp;
628
629         for (a = init_action_list; a; a = tmp) {
630                 tmp = a->next;
631                 if (a->action == action) {
632                         if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
633                                 waitfor(a);
634                                 delete_init_action(a);
635                         } else if (a->action & ONCE) {
636                                 run(a);
637                                 delete_init_action(a);
638                         } else if (a->action & (RESPAWN | ASKFIRST)) {
639                                 /* Only run stuff with pid==0.  If they have
640                                  * a pid, that means it is still running */
641                                 if (a->pid == 0) {
642                                         a->pid = run(a);
643                                 }
644                         }
645                 }
646         }
647 }
648
649 #ifndef DEBUG_INIT
650 static void init_reboot(unsigned long magic)
651 {
652         pid_t pid;
653         /* We have to fork here, since the kernel calls do_exit(0) in
654          * linux/kernel/sys.c, which can cause the machine to panic when
655          * the init process is killed.... */
656         if ((pid = fork()) == 0) {
657                 reboot(magic);
658                 _exit(0);
659         }
660         waitpid (pid, NULL, 0);
661 }
662
663 static void shutdown_system(void)
664 {
665         sigset_t block_signals;
666
667         /* run everything to be run at "shutdown".  This is done _prior_
668          * to killing everything, in case people wish to use scripts to
669          * shut things down gracefully... */
670         run_actions(SHUTDOWN);
671
672         /* first disable all our signals */
673         sigemptyset(&block_signals);
674         sigaddset(&block_signals, SIGHUP);
675         sigaddset(&block_signals, SIGQUIT);
676         sigaddset(&block_signals, SIGCHLD);
677         sigaddset(&block_signals, SIGUSR1);
678         sigaddset(&block_signals, SIGUSR2);
679         sigaddset(&block_signals, SIGINT);
680         sigaddset(&block_signals, SIGTERM);
681         sigaddset(&block_signals, SIGCONT);
682         sigaddset(&block_signals, SIGSTOP);
683         sigaddset(&block_signals, SIGTSTP);
684         sigprocmask(SIG_BLOCK, &block_signals, NULL);
685
686         /* Allow Ctrl-Alt-Del to reboot system. */
687         init_reboot(RB_ENABLE_CAD);
688
689         message(CONSOLE | LOG, "The system is going down NOW !!");
690         sync();
691
692         /* Send signals to every process _except_ pid 1 */
693         message(CONSOLE | LOG, "Sending SIGTERM to all processes.");
694         kill(-1, SIGTERM);
695         sleep(1);
696         sync();
697
698         message(CONSOLE | LOG, "Sending SIGKILL to all processes.");
699         kill(-1, SIGKILL);
700         sleep(1);
701
702         sync();
703 }
704
705 static void exec_signal(int sig)
706 {
707         struct init_action *a, *tmp;
708         sigset_t unblock_signals;
709
710         for (a = init_action_list; a; a = tmp) {
711                 tmp = a->next;
712                 if (a->action & RESTART) {
713                         shutdown_system();
714
715                         /* unblock all signals, blocked in shutdown_system() */
716                         sigemptyset(&unblock_signals);
717                         sigaddset(&unblock_signals, SIGHUP);
718                         sigaddset(&unblock_signals, SIGQUIT);
719                         sigaddset(&unblock_signals, SIGCHLD);
720                         sigaddset(&unblock_signals, SIGUSR1);
721                         sigaddset(&unblock_signals, SIGUSR2);
722                         sigaddset(&unblock_signals, SIGINT);
723                         sigaddset(&unblock_signals, SIGTERM);
724                         sigaddset(&unblock_signals, SIGCONT);
725                         sigaddset(&unblock_signals, SIGSTOP);
726                         sigaddset(&unblock_signals, SIGTSTP);
727                         sigprocmask(SIG_UNBLOCK, &unblock_signals, NULL);
728
729                         /* Close whatever files are open. */
730                         close(0);
731                         close(1);
732                         close(2);
733
734                         /* Open the new terminal device */
735                         if ((device_open(a->terminal, O_RDWR)) < 0) {
736                                 struct stat sb;
737                                 if (stat(a->terminal, &sb) != 0) {
738                                         message(LOG | CONSOLE, "device '%s' does not exist.", a->terminal);
739                                 } else {
740                                         message(LOG | CONSOLE, "Bummer, can't open %s", a->terminal);
741                                 }
742                                 halt_signal(SIGUSR1);
743                         }
744
745                         /* Make sure the terminal will act fairly normal for us */
746                         set_term(0);
747                         /* Setup stdout, stderr on the supplied terminal */
748                         dup(0);
749                         dup(0);
750
751                         messageD(CONSOLE | LOG, "Trying to re-exec %s", a->command);
752                         execl(a->command, a->command, NULL);
753
754                         message(CONSOLE | LOG, "exec of '%s' failed: %m",
755                                         a->command);
756                         sync();
757                         sleep(2);
758                         init_reboot(RB_HALT_SYSTEM);
759                         loop_forever();
760                 }
761         }
762 }
763
764 static void halt_signal(int sig)
765 {
766         shutdown_system();
767         message(CONSOLE | LOG,
768 #if #cpu(s390)
769                         /* Seems the s390 console is Wierd(tm). */
770                         "The system is halted. You may reboot now."
771 #else
772                         "The system is halted. Press Reset or turn off power"
773 #endif
774                 );
775         sync();
776
777         /* allow time for last message to reach serial console */
778         sleep(2);
779
780         if (sig == SIGUSR2)
781                 init_reboot(RB_POWER_OFF);
782         else
783                 init_reboot(RB_HALT_SYSTEM);
784
785         loop_forever();
786 }
787
788 static void reboot_signal(int sig)
789 {
790         shutdown_system();
791         message(CONSOLE | LOG, "Please stand by while rebooting the system.");
792         sync();
793
794         /* allow time for last message to reach serial console */
795         sleep(2);
796
797         init_reboot(RB_AUTOBOOT);
798
799         loop_forever();
800 }
801
802 static void ctrlaltdel_signal(int sig)
803 {
804         run_actions(CTRLALTDEL);
805 }
806
807 /* The SIGSTOP & SIGTSTP handler */
808 static void stop_handler(int sig)
809 {
810         int saved_errno = errno;
811
812         got_cont = 0;
813         while (!got_cont)
814                 pause();
815         got_cont = 0;
816         errno = saved_errno;
817 }
818
819 /* The SIGCONT handler */
820 static void cont_handler(int sig)
821 {
822         got_cont = 1;
823 }
824
825 #endif                                                  /* ! DEBUG_INIT */
826
827 static void new_init_action(int action, const char *command, const char *cons)
828 {
829         struct init_action *new_action, *a, *last;
830
831         if (*cons == '\0')
832                 cons = console;
833
834         /* do not run entries if console device is not available */
835         if (access(cons, R_OK | W_OK))
836                 return;
837         if (strcmp(cons, "/dev/null") == 0 && (action & ASKFIRST))
838                 return;
839
840         new_action = calloc((size_t) (1), sizeof(struct init_action));
841         if (!new_action) {
842                 message(LOG | CONSOLE, "Memory allocation failure");
843                 loop_forever();
844         }
845
846         /* Append to the end of the list */
847         for (a = last = init_action_list; a; a = a->next) {
848                 /* don't enter action if it's already in the list,
849                  * but do overwrite existing actions */
850                 if ((strcmp(a->command, command) == 0) &&
851                     (strcmp(a->terminal, cons) ==0)) {
852                         a->action = action;
853                         free(new_action);
854                         return;
855                 }
856                 last = a;
857         }
858         if (last) {
859                 last->next = new_action;
860         } else {
861                 init_action_list = new_action;
862         }
863         strcpy(new_action->command, command);
864         new_action->action = action;
865         strcpy(new_action->terminal, cons);
866 #if 0   /* calloc zeroed always */
867         new_action->pid = 0;
868 #endif
869         messageD(LOG|CONSOLE, "command='%s' action='%d' terminal='%s'\n",
870                 new_action->command, new_action->action, new_action->terminal);
871 }
872
873 static void delete_init_action(struct init_action *action)
874 {
875         struct init_action *a, *b = NULL;
876
877         for (a = init_action_list; a; b = a, a = a->next) {
878                 if (a == action) {
879                         if (b == NULL) {
880                                 init_action_list = a->next;
881                         } else {
882                                 b->next = a->next;
883                         }
884                         free(a);
885                         break;
886                 }
887         }
888 }
889
890 /* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,
891  * then parse_inittab() simply adds in some default
892  * actions(i.e., runs INIT_SCRIPT and then starts a pair
893  * of "askfirst" shells).  If CONFIG_FEATURE_USE_INITTAB
894  * _is_ defined, but /etc/inittab is missing, this
895  * results in the same set of default behaviors.
896  */
897 static void parse_inittab(void)
898 {
899 #ifdef CONFIG_FEATURE_USE_INITTAB
900         FILE *file;
901         char buf[INIT_BUFFS_SIZE], lineAsRead[INIT_BUFFS_SIZE];
902         char tmpConsole[CONSOLE_BUFF_SIZE];
903         char *id, *runlev, *action, *command, *eol;
904         const struct init_action_type *a = actions;
905
906
907         file = fopen(INITTAB, "r");
908         if (file == NULL) {
909                 /* No inittab file -- set up some default behavior */
910 #endif
911                 /* Reboot on Ctrl-Alt-Del */
912                 new_init_action(CTRLALTDEL, "/sbin/reboot", "");
913                 /* Umount all filesystems on halt/reboot */
914                 new_init_action(SHUTDOWN, "/bin/umount -a -r", "");
915                 /* Swapoff on halt/reboot */
916                 if(ENABLE_SWAPONOFF) new_init_action(SHUTDOWN, "/sbin/swapoff -a", "");
917                 /* Prepare to restart init when a HUP is received */
918                 new_init_action(RESTART, "/sbin/init", "");
919                 /* Askfirst shell on tty1-4 */
920                 new_init_action(ASKFIRST, bb_default_login_shell, "");
921                 new_init_action(ASKFIRST, bb_default_login_shell, VC_2);
922                 new_init_action(ASKFIRST, bb_default_login_shell, VC_3);
923                 new_init_action(ASKFIRST, bb_default_login_shell, VC_4);
924                 /* sysinit */
925                 new_init_action(SYSINIT, INIT_SCRIPT, "");
926
927                 return;
928 #ifdef CONFIG_FEATURE_USE_INITTAB
929         }
930
931         while (fgets(buf, INIT_BUFFS_SIZE, file) != NULL) {
932                 /* Skip leading spaces */
933                 for (id = buf; *id == ' ' || *id == '\t'; id++);
934
935                 /* Skip the line if it's a comment */
936                 if (*id == '#' || *id == '\n')
937                         continue;
938
939                 /* Trim the trailing \n */
940                 eol = strrchr(id, '\n');
941                 if (eol != NULL)
942                         *eol = '\0';
943
944                 /* Keep a copy around for posterity's sake (and error msgs) */
945                 strcpy(lineAsRead, buf);
946
947                 /* Separate the ID field from the runlevels */
948                 runlev = strchr(id, ':');
949                 if (runlev == NULL || *(runlev + 1) == '\0') {
950                         message(LOG | CONSOLE, "Bad inittab entry: %s", lineAsRead);
951                         continue;
952                 } else {
953                         *runlev = '\0';
954                         ++runlev;
955                 }
956
957                 /* Separate the runlevels from the action */
958                 action = strchr(runlev, ':');
959                 if (action == NULL || *(action + 1) == '\0') {
960                         message(LOG | CONSOLE, "Bad inittab entry: %s", lineAsRead);
961                         continue;
962                 } else {
963                         *action = '\0';
964                         ++action;
965                 }
966
967                 /* Separate the action from the command */
968                 command = strchr(action, ':');
969                 if (command == NULL || *(command + 1) == '\0') {
970                         message(LOG | CONSOLE, "Bad inittab entry: %s", lineAsRead);
971                         continue;
972                 } else {
973                         *command = '\0';
974                         ++command;
975                 }
976
977                 /* Ok, now process it */
978                 for (a = actions; a->name != 0; a++) {
979                         if (strcmp(a->name, action) == 0) {
980                                 if (*id != '\0') {
981                                         if(strncmp(id, "/dev/", 5) == 0)
982                                                 id += 5;
983                                         strcpy(tmpConsole, "/dev/");
984                                         safe_strncpy(tmpConsole + 5, id,
985                                                 CONSOLE_BUFF_SIZE - 5);
986                                         id = tmpConsole;
987                                 }
988                                 new_init_action(a->action, command, id);
989                                 break;
990                         }
991                 }
992                 if (a->name == 0) {
993                         /* Choke on an unknown action */
994                         message(LOG | CONSOLE, "Bad inittab entry: %s", lineAsRead);
995                 }
996         }
997         fclose(file);
998         return;
999 #endif                                                  /* CONFIG_FEATURE_USE_INITTAB */
1000 }
1001
1002 #ifdef CONFIG_FEATURE_USE_INITTAB
1003 static void reload_signal(int sig)
1004 {
1005         struct init_action *a, *tmp;
1006
1007         message(LOG, "Reloading /etc/inittab");
1008
1009         /* disable old entrys */
1010         for (a = init_action_list; a; a = a->next ) {
1011                 a->action = ONCE;
1012         }
1013
1014         parse_inittab();
1015
1016         /* remove unused entrys */
1017         for (a = init_action_list; a; a = tmp) {
1018                 tmp = a->next;
1019                 if (a->action & (ONCE | SYSINIT | WAIT ) &&
1020                                 a->pid == 0 ) {
1021                         delete_init_action(a);
1022                 }
1023         }
1024         run_actions(RESPAWN);
1025         return;
1026 }
1027 #endif                                                  /* CONFIG_FEATURE_USE_INITTAB */
1028
1029 extern int init_main(int argc, char **argv)
1030 {
1031         struct init_action *a;
1032         pid_t wpid;
1033         int status;
1034
1035         if (argc > 1 && !strcmp(argv[1], "-q")) {
1036                 return kill_init(SIGHUP);
1037         }
1038 #ifndef DEBUG_INIT
1039         /* Expect to be invoked as init with PID=1 or be invoked as linuxrc */
1040         if (getpid() != 1
1041 #ifdef CONFIG_FEATURE_INITRD
1042                 && strstr(bb_applet_name, "linuxrc") == NULL
1043 #endif
1044                 ) {
1045                 bb_show_usage();
1046         }
1047         /* Set up sig handlers  -- be sure to
1048          * clear all of these in run() */
1049         signal(SIGHUP, exec_signal);
1050         signal(SIGQUIT, exec_signal);
1051         signal(SIGUSR1, halt_signal);
1052         signal(SIGUSR2, halt_signal);
1053         signal(SIGINT, ctrlaltdel_signal);
1054         signal(SIGTERM, reboot_signal);
1055         signal(SIGCONT, cont_handler);
1056         signal(SIGSTOP, stop_handler);
1057         signal(SIGTSTP, stop_handler);
1058
1059         /* Turn off rebooting via CTL-ALT-DEL -- we get a
1060          * SIGINT on CAD so we can shut things down gracefully... */
1061         init_reboot(RB_DISABLE_CAD);
1062 #endif
1063
1064         /* Figure out where the default console should be */
1065         console_init();
1066
1067         /* Close whatever files are open, and reset the console. */
1068         close(0);
1069         close(1);
1070         close(2);
1071
1072         if (device_open(console, O_RDWR | O_NOCTTY) == 0) {
1073                 set_term(0);
1074                 close(0);
1075         }
1076
1077         chdir("/");
1078         setsid();
1079         {
1080                 const char * const *e;
1081                 /* Make sure environs is set to something sane */
1082                 for(e = environment; *e; e++)
1083                         putenv((char *) *e);
1084         }
1085         /* Hello world */
1086         message(MAYBE_CONSOLE | LOG, "init started:  %s", bb_msg_full_version);
1087
1088         /* Make sure there is enough memory to do something useful. */
1089         if (ENABLE_SWAPONOFF) {
1090                 struct sysinfo info;
1091
1092                 if (!sysinfo(&info) &&
1093                         (info.mem_unit ? : 1) * (long long)info.totalram < MEGABYTE)
1094                 {
1095                         message(CONSOLE,"Low memory: forcing swapon.");
1096                         /* swapon -a requires /proc typically */
1097                         new_init_action(SYSINIT, "/bin/mount -t proc proc /proc", "");
1098                         /* Try to turn on swap */
1099                         new_init_action(SYSINIT, "/sbin/swapon -a", "");
1100                         run_actions(SYSINIT);   /* wait and removing */
1101                 }
1102         }
1103
1104         /* Check if we are supposed to be in single user mode */
1105         if (argc > 1 && (!strcmp(argv[1], "single") ||
1106                                          !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) {
1107                 /* Start a shell on console */
1108                 new_init_action(RESPAWN, bb_default_login_shell, "");
1109         } else {
1110                 /* Not in single user mode -- see what inittab says */
1111
1112                 /* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,
1113                  * then parse_inittab() simply adds in some default
1114                  * actions(i.e., runs INIT_SCRIPT and then starts a pair
1115                  * of "askfirst" shells */
1116                 parse_inittab();
1117         }
1118
1119         /* Make the command line just say "init"  -- thats all, nothing else */
1120         fixup_argv(argc, argv, "init");
1121
1122         /* Now run everything that needs to be run */
1123
1124         /* First run the sysinit command */
1125         run_actions(SYSINIT);
1126
1127         /* Next run anything that wants to block */
1128         run_actions(WAIT);
1129
1130         /* Next run anything to be run only once */
1131         run_actions(ONCE);
1132
1133 #ifdef CONFIG_FEATURE_USE_INITTAB
1134         /* Redefine SIGHUP to reread /etc/inittab */
1135         signal(SIGHUP, reload_signal);
1136 #else
1137         signal(SIGHUP, SIG_IGN);
1138 #endif /* CONFIG_FEATURE_USE_INITTAB */
1139
1140
1141         /* Now run the looping stuff for the rest of forever */
1142         while (1) {
1143                 /* run the respawn stuff */
1144                 run_actions(RESPAWN);
1145
1146                 /* run the askfirst stuff */
1147                 run_actions(ASKFIRST);
1148
1149                 /* Don't consume all CPU time -- sleep a bit */
1150                 sleep(1);
1151
1152                 /* Wait for a child process to exit */
1153                 wpid = wait(&status);
1154                 while (wpid > 0) {
1155                         /* Find out who died and clean up their corpse */
1156                         for (a = init_action_list; a; a = a->next) {
1157                                 if (a->pid == wpid) {
1158                                         /* Set the pid to 0 so that the process gets
1159                                          * restarted by run_actions() */
1160                                         a->pid = 0;
1161                                         message(LOG, "Process '%s' (pid %d) exited.  "
1162                                                         "Scheduling it for restart.",
1163                                                         a->command, wpid);
1164                                 }
1165                         }
1166                         /* see if anyone else is waiting to be reaped */
1167                         wpid = waitpid (-1, &status, WNOHANG);
1168                 }
1169         }
1170 }
1171
1172 /*
1173 Local Variables:
1174 c-file-style: "linux"
1175 c-basic-offset: 4
1176 tab-width: 4
1177 End:
1178 */