1
2
3
4
5
6
7
8
9
10
11
12#include "libbb.h"
13#include <syslog.h>
14#include <paths.h>
15#include <sys/reboot.h>
16#include <sys/resource.h>
17#include <linux/vt.h>
18
19
20
21
22#define DEBUG_INIT 0
23
24#define COMMAND_SIZE 256
25#define CONSOLE_NAME_SIZE 32
26
27
28#ifndef INIT_SCRIPT
29#define INIT_SCRIPT "/etc/init.d/rcS"
30#endif
31
32
33
34
35
36#define SYSINIT 0x01
37
38#define WAIT 0x02
39
40#define ONCE 0x04
41
42
43
44
45
46
47
48#define RESPAWN 0x08
49
50#define ASKFIRST 0x10
51
52
53
54
55
56#define CTRLALTDEL 0x20
57
58
59
60
61
62
63#define SHUTDOWN 0x40
64
65
66
67
68
69
70#define RESTART 0x80
71
72
73
74struct init_action {
75 struct init_action *next;
76 pid_t pid;
77 uint8_t action_type;
78 char terminal[CONSOLE_NAME_SIZE];
79 char command[COMMAND_SIZE];
80};
81
82static struct init_action *init_action_list = NULL;
83
84static const char *log_console = VC_5;
85
86enum {
87 L_LOG = 0x1,
88 L_CONSOLE = 0x2,
89 MAYBE_CONSOLE = L_CONSOLE * !ENABLE_FEATURE_EXTRA_QUIET,
90#ifndef RB_HALT_SYSTEM
91 RB_HALT_SYSTEM = 0xcdef0123,
92 RB_ENABLE_CAD = 0x89abcdef,
93 RB_DISABLE_CAD = 0,
94 RB_POWER_OFF = 0x4321fedc,
95 RB_AUTOBOOT = 0x01234567,
96#endif
97};
98
99
100
101
102
103#define dbg_message(...) do { if (DEBUG_INIT) message(__VA_ARGS__); } while (0)
104static void message(int where, const char *fmt, ...)
105 __attribute__ ((format(printf, 2, 3)));
106static void message(int where, const char *fmt, ...)
107{
108 va_list arguments;
109 unsigned l;
110 char msg[128];
111
112 msg[0] = '\r';
113 va_start(arguments, fmt);
114 l = 1 + vsnprintf(msg + 1, sizeof(msg) - 2, fmt, arguments);
115 if (l > sizeof(msg) - 1)
116 l = sizeof(msg) - 1;
117 va_end(arguments);
118
119#if ENABLE_FEATURE_INIT_SYSLOG
120 msg[l] = '\0';
121 if (where & L_LOG) {
122
123 openlog("init", 0, LOG_DAEMON);
124
125 syslog(LOG_INFO, "%s", msg + 1);
126 closelog();
127 }
128 msg[l++] = '\n';
129 msg[l] = '\0';
130#else
131 {
132 static int log_fd = -1;
133
134 msg[l++] = '\n';
135 msg[l] = '\0';
136
137
138 if (log_fd < 0) {
139 if (!log_console) {
140 log_fd = STDERR_FILENO;
141 } else {
142 log_fd = device_open(log_console, O_WRONLY | O_NONBLOCK | O_NOCTTY);
143 if (log_fd < 0) {
144 bb_error_msg("can't log to %s", log_console);
145 where = L_CONSOLE;
146 } else {
147 close_on_exec_on(log_fd);
148 }
149 }
150 }
151 if (where & L_LOG) {
152 full_write(log_fd, msg, l);
153 if (log_fd == STDERR_FILENO)
154 return;
155 }
156 }
157#endif
158
159 if (where & L_CONSOLE) {
160
161 full_write(STDERR_FILENO, msg, l);
162 }
163}
164
165static void console_init(void)
166{
167 int vtno;
168 char *s;
169
170 s = getenv("CONSOLE");
171 if (!s)
172 s = getenv("console");
173 if (s) {
174 int fd = open(s, O_RDWR | O_NONBLOCK | O_NOCTTY);
175 if (fd >= 0) {
176 dup2(fd, STDIN_FILENO);
177 dup2(fd, STDOUT_FILENO);
178 xmove_fd(fd, STDERR_FILENO);
179 }
180 dbg_message(L_LOG, "console='%s'", s);
181 } else {
182
183
184 bb_sanitize_stdio();
185
186
187
188 }
189
190 s = getenv("TERM");
191 if (ioctl(STDIN_FILENO, VT_OPENQRY, &vtno) != 0) {
192
193
194
195 if (!s || strcmp(s, "linux") == 0)
196 putenv((char*)"TERM=vt102");
197 if (!ENABLE_FEATURE_INIT_SYSLOG)
198 log_console = NULL;
199 } else if (!s)
200 putenv((char*)"TERM=linux");
201}
202
203
204
205static void set_sane_term(void)
206{
207 struct termios tty;
208
209 tcgetattr(STDIN_FILENO, &tty);
210
211
212 tty.c_cc[VINTR] = 3;
213 tty.c_cc[VQUIT] = 28;
214 tty.c_cc[VERASE] = 127;
215 tty.c_cc[VKILL] = 21;
216 tty.c_cc[VEOF] = 4;
217 tty.c_cc[VSTART] = 17;
218 tty.c_cc[VSTOP] = 19;
219 tty.c_cc[VSUSP] = 26;
220
221
222 tty.c_line = 0;
223
224
225 tty.c_cflag &= CBAUD | CBAUDEX | CSIZE | CSTOPB | PARENB | PARODD;
226 tty.c_cflag |= CREAD | HUPCL | CLOCAL;
227
228
229 tty.c_iflag = ICRNL | IXON | IXOFF;
230
231
232 tty.c_oflag = OPOST | ONLCR;
233
234
235 tty.c_lflag =
236 ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
237
238 tcsetattr_stdin_TCSANOW(&tty);
239}
240
241
242
243static int open_stdio_to_tty(const char* tty_name)
244{
245
246 if (tty_name[0]) {
247 int fd;
248
249 close(STDIN_FILENO);
250
251 fd = device_open(tty_name, O_RDWR);
252 if (fd) {
253 message(L_LOG | L_CONSOLE, "can't open %s: %s",
254 tty_name, strerror(errno));
255 return 0;
256 }
257 dup2(STDIN_FILENO, STDOUT_FILENO);
258 dup2(STDIN_FILENO, STDERR_FILENO);
259 }
260 set_sane_term();
261 return 1;
262}
263
264
265
266
267
268
269
270
271static void init_exec(const char *command)
272{
273 char *cmd[COMMAND_SIZE / 2];
274 char buf[COMMAND_SIZE + 6];
275 int dash = (command[0] == '-' );
276
277
278 if (strpbrk(command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {
279 strcpy(buf, "exec ");
280 strcpy(buf + 5, command + dash);
281
282 cmd[0] = (char*)(LIBBB_DEFAULT_LOGIN_SHELL + !dash);
283 cmd[1] = (char*)"-c";
284 cmd[2] = buf;
285 cmd[3] = NULL;
286 } else {
287
288 char *word, *next;
289 int i = 0;
290 next = strcpy(buf, command);
291 while ((word = strsep(&next, " \t")) != NULL) {
292 if (*word != '\0') {
293 cmd[i] = word;
294 i++;
295 }
296 }
297 cmd[i] = NULL;
298 }
299
300
301
302 if (dash) {
303
304 if (ENABLE_FEATURE_INIT_SCTTY)
305 ioctl(STDIN_FILENO, TIOCSCTTY, 0 );
306 }
307 BB_EXECVP(cmd[0] + dash, cmd);
308 message(L_LOG | L_CONSOLE, "cannot run '%s': %s", cmd[0], strerror(errno));
309
310}
311
312
313static pid_t run(const struct init_action *a)
314{
315 pid_t pid;
316
317
318 sigprocmask_allsigs(SIG_BLOCK);
319 if (BB_MMU && (a->action_type & ASKFIRST))
320 pid = fork();
321 else
322 pid = vfork();
323 if (pid < 0)
324 message(L_LOG | L_CONSOLE, "can't fork");
325 if (pid) {
326 sigprocmask_allsigs(SIG_UNBLOCK);
327 return pid;
328 }
329
330
331
332
333 bb_signals(0
334 + (1 << SIGUSR1)
335 + (1 << SIGUSR2)
336 + (1 << SIGTERM)
337 + (1 << SIGQUIT)
338 + (1 << SIGINT)
339 + (1 << SIGHUP)
340 + (1 << SIGTSTP)
341 , SIG_DFL);
342 sigprocmask_allsigs(SIG_UNBLOCK);
343
344
345 setsid();
346
347
348 if (!open_stdio_to_tty(a->terminal))
349 _exit(EXIT_FAILURE);
350
351
352
353 if (BB_MMU && (a->action_type & ASKFIRST)) {
354 static const char press_enter[] ALIGN1 =
355#ifdef CUSTOMIZED_BANNER
356#include CUSTOMIZED_BANNER
357#endif
358 "\nPlease press Enter to activate this console. ";
359 char c;
360
361
362
363
364
365
366
367
368 dbg_message(L_LOG, "waiting for enter to start '%s'"
369 "(pid %d, tty '%s')\n",
370 a->command, getpid(), a->terminal);
371 full_write(STDOUT_FILENO, press_enter, sizeof(press_enter) - 1);
372 while (safe_read(STDIN_FILENO, &c, 1) == 1 && c != '\n')
373 continue;
374 }
375
376
377
378
379
380
381
382 if (ENABLE_FEATURE_INIT_COREDUMPS) {
383 if (access("/.init_enable_core", F_OK) == 0) {
384 struct rlimit limit;
385 limit.rlim_cur = RLIM_INFINITY;
386 limit.rlim_max = RLIM_INFINITY;
387 setrlimit(RLIMIT_CORE, &limit);
388 }
389 }
390
391
392 message(L_LOG, "starting pid %d, tty '%s': '%s'",
393 getpid(), a->terminal, a->command);
394
395
396
397 init_exec(a->command);
398
399 _exit(-1);
400}
401
402static struct init_action *mark_terminated(pid_t pid)
403{
404 struct init_action *a;
405
406 if (pid > 0) {
407 for (a = init_action_list; a; a = a->next) {
408 if (a->pid == pid) {
409 a->pid = 0;
410 return a;
411 }
412 }
413 }
414 return NULL;
415}
416
417static void waitfor(pid_t pid)
418{
419
420 if (pid <= 0)
421 return;
422
423
424
425 while (1) {
426 pid_t wpid = wait(NULL);
427 mark_terminated(wpid);
428
429
430
431 if (kill(pid, 0))
432 break;
433 }
434}
435
436
437static void run_actions(int action_type)
438{
439 struct init_action *a;
440
441 for (a = init_action_list; a; a = a->next) {
442 if (!(a->action_type & action_type))
443 continue;
444
445 if (a->action_type & (SYSINIT | WAIT | ONCE | CTRLALTDEL | SHUTDOWN)) {
446 pid_t pid = run(a);
447 if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN))
448 waitfor(pid);
449 }
450 if (a->action_type & (RESPAWN | ASKFIRST)) {
451
452
453
454 if (a->pid == 0)
455 a->pid = run(a);
456 }
457 }
458}
459
460static void new_init_action(uint8_t action_type, const char *command, const char *cons)
461{
462 struct init_action *a, **nextp;
463
464
465
466
467
468
469
470
471
472
473
474
475 nextp = &init_action_list;
476 while ((a = *nextp) != NULL) {
477
478
479
480 if ((strcmp(a->command, command) == 0)
481 && (strcmp(a->terminal, cons) == 0)
482 ) {
483
484 *nextp = a->next;
485
486 while (*nextp != NULL)
487 nextp = &(*nextp)->next;
488 a->next = NULL;
489 break;
490 }
491 nextp = &a->next;
492 }
493
494 if (!a)
495 a = xzalloc(sizeof(*a));
496
497 *nextp = a;
498 a->action_type = action_type;
499 safe_strncpy(a->command, command, sizeof(a->command));
500 safe_strncpy(a->terminal, cons, sizeof(a->terminal));
501 dbg_message(L_LOG | L_CONSOLE, "command='%s' action=%d tty='%s'\n",
502 a->command, a->action_type, a->terminal);
503}
504
505
506
507
508
509
510
511
512static void parse_inittab(void)
513{
514#if ENABLE_FEATURE_USE_INITTAB
515 char *token[4];
516 parser_t *parser = config_open2("/etc/inittab", fopen_for_read);
517
518 if (parser == NULL)
519#endif
520 {
521
522
523 new_init_action(CTRLALTDEL, "reboot", "");
524
525 new_init_action(SHUTDOWN, "umount -a -r", "");
526
527 if (ENABLE_SWAPONOFF)
528 new_init_action(SHUTDOWN, "swapoff -a", "");
529
530 new_init_action(RESTART, "init", "");
531
532 new_init_action(ASKFIRST, bb_default_login_shell, "");
533
534 new_init_action(ASKFIRST, bb_default_login_shell, VC_2);
535 new_init_action(ASKFIRST, bb_default_login_shell, VC_3);
536 new_init_action(ASKFIRST, bb_default_login_shell, VC_4);
537
538 new_init_action(SYSINIT, INIT_SCRIPT, "");
539 return;
540 }
541
542#if ENABLE_FEATURE_USE_INITTAB
543
544
545
546 while (config_read(parser, token, 4, 0, "#:",
547 PARSE_NORMAL & ~(PARSE_TRIM | PARSE_COLLAPSE))) {
548
549 static const char actions[] ALIGN1 =
550 "sysinit\0""wait\0""once\0""respawn\0""askfirst\0"
551 "ctrlaltdel\0""shutdown\0""restart\0";
552 int action;
553 char *tty = token[0];
554
555 if (!token[3])
556 goto bad_entry;
557 action = index_in_strings(actions, token[2]);
558 if (action < 0 || !token[3][0])
559 goto bad_entry;
560
561 if (tty[0]) {
562 if (strncmp(tty, "/dev/", 5) == 0)
563 tty += 5;
564 tty = concat_path_file("/dev/", tty);
565 }
566 new_init_action(1 << action, token[3], tty);
567 if (tty[0])
568 free(tty);
569 continue;
570 bad_entry:
571 message(L_LOG | L_CONSOLE, "Bad inittab entry at line %d",
572 parser->lineno);
573 }
574 config_close(parser);
575#endif
576}
577
578static void pause_and_low_level_reboot(unsigned magic) NORETURN;
579static void pause_and_low_level_reboot(unsigned magic)
580{
581 pid_t pid;
582
583
584 sleep(1);
585
586
587
588
589 pid = vfork();
590 if (pid == 0) {
591 reboot(magic);
592 _exit(EXIT_SUCCESS);
593 }
594 while (1)
595 sleep(1);
596}
597
598static void run_shutdown_and_kill_processes(void)
599{
600
601
602
603 run_actions(SHUTDOWN);
604
605 message(L_CONSOLE | L_LOG, "The system is going down NOW!");
606
607
608 kill(-1, SIGTERM);
609 message(L_CONSOLE | L_LOG, "Sent SIG%s to all processes", "TERM");
610 sync();
611 sleep(1);
612
613 kill(-1, SIGKILL);
614 message(L_CONSOLE, "Sent SIG%s to all processes", "KILL");
615 sync();
616
617}
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655static void halt_reboot_pwoff(int sig) NORETURN;
656static void halt_reboot_pwoff(int sig)
657{
658 const char *m;
659 unsigned rb;
660
661 run_shutdown_and_kill_processes();
662
663 m = "halt";
664 rb = RB_HALT_SYSTEM;
665 if (sig == SIGTERM) {
666 m = "reboot";
667 rb = RB_AUTOBOOT;
668 } else if (sig == SIGUSR2) {
669 m = "poweroff";
670 rb = RB_POWER_OFF;
671 }
672 message(L_CONSOLE, "Requesting system %s", m);
673 pause_and_low_level_reboot(rb);
674
675}
676
677
678
679
680
681static void stop_handler(int sig UNUSED_PARAM)
682{
683 smallint saved_bb_got_signal;
684 int saved_errno;
685
686 saved_bb_got_signal = bb_got_signal;
687 saved_errno = errno;
688 signal(SIGCONT, record_signo);
689
690 while (1) {
691 pid_t wpid;
692
693 if (bb_got_signal == SIGCONT)
694 break;
695
696
697
698
699 wpid = wait_any_nohang(NULL);
700 mark_terminated(wpid);
701 sleep(1);
702 }
703
704 signal(SIGCONT, SIG_DFL);
705 errno = saved_errno;
706 bb_got_signal = saved_bb_got_signal;
707}
708
709
710
711static void restart_handler(int sig UNUSED_PARAM)
712{
713 struct init_action *a;
714
715 for (a = init_action_list; a; a = a->next) {
716 if (!(a->action_type & RESTART))
717 continue;
718
719
720
721
722
723 run_shutdown_and_kill_processes();
724
725
726
727
728 reboot(RB_ENABLE_CAD);
729
730 if (open_stdio_to_tty(a->terminal)) {
731 dbg_message(L_CONSOLE, "Trying to re-exec %s", a->command);
732
733
734
735
736
737
738
739
740 init_exec(a->command);
741 }
742
743 pause_and_low_level_reboot(RB_HALT_SYSTEM);
744
745 }
746}
747
748#if ENABLE_FEATURE_USE_INITTAB
749static void reload_inittab(void)
750{
751 struct init_action *a, **nextp;
752
753 message(L_LOG, "reloading /etc/inittab");
754
755
756 for (a = init_action_list; a; a = a->next)
757 a->action_type = ONCE;
758
759
760
761
762
763
764 parse_inittab();
765
766#if ENABLE_FEATURE_KILL_REMOVED
767
768
769 for (a = init_action_list; a; a = a->next)
770 if (a->action_type == ONCE && a->pid != 0)
771 kill(a->pid, SIGTERM);
772 if (CONFIG_FEATURE_KILL_DELAY) {
773
774 if ((BB_MMU ? fork() : vfork()) == 0) {
775 sleep(CONFIG_FEATURE_KILL_DELAY);
776 for (a = init_action_list; a; a = a->next)
777 if (a->action_type == ONCE && a->pid != 0)
778 kill(a->pid, SIGKILL);
779 _exit(EXIT_SUCCESS);
780 }
781 }
782#endif
783
784
785 nextp = &init_action_list;
786 while ((a = *nextp) != NULL) {
787 if (a->action_type & (ONCE | SYSINIT | WAIT)) {
788 *nextp = a->next;
789 free(a);
790 } else {
791 nextp = &a->next;
792 }
793 }
794
795
796
797
798}
799#endif
800
801static int check_delayed_sigs(void)
802{
803 int sigs_seen = 0;
804
805 while (1) {
806 smallint sig = bb_got_signal;
807
808 if (!sig)
809 return sigs_seen;
810 bb_got_signal = 0;
811 sigs_seen = 1;
812#if ENABLE_FEATURE_USE_INITTAB
813 if (sig == SIGHUP)
814 reload_inittab();
815#endif
816 if (sig == SIGINT)
817 run_actions(CTRLALTDEL);
818 }
819}
820
821int init_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
822int init_main(int argc UNUSED_PARAM, char **argv)
823{
824 die_sleep = 30 * 24*60*60;
825
826 if (argv[1] && !strcmp(argv[1], "-q")) {
827 return kill(1, SIGHUP);
828 }
829
830 if (!DEBUG_INIT) {
831
832 if (getpid() != 1
833 && (!ENABLE_FEATURE_INITRD || !strstr(applet_name, "linuxrc"))
834 ) {
835 bb_show_usage();
836 }
837
838
839 reboot(RB_DISABLE_CAD);
840 }
841
842
843 console_init();
844 set_sane_term();
845 xchdir("/");
846 setsid();
847
848
849 putenv((char *) "HOME=/");
850 putenv((char *) bb_PATH_root_path);
851 putenv((char *) "SHELL=/bin/sh");
852 putenv((char *) "USER=root");
853
854 if (argv[1])
855 xsetenv("RUNLEVEL", argv[1]);
856
857
858 message(MAYBE_CONSOLE | L_LOG, "init started: %s", bb_banner);
859
860
861 if (ENABLE_SWAPONOFF) {
862 struct sysinfo info;
863
864 if (sysinfo(&info) == 0
865 && (info.mem_unit ? : 1) * (long long)info.totalram < 1024*1024
866 ) {
867 message(L_CONSOLE, "Low memory, forcing swapon");
868
869 new_init_action(SYSINIT, "mount -t proc proc /proc", "");
870
871 new_init_action(SYSINIT, "swapon -a", "");
872 run_actions(SYSINIT);
873 }
874 }
875
876
877 if (argv[1]
878 && (!strcmp(argv[1], "single") || !strcmp(argv[1], "-s") || LONE_CHAR(argv[1], '1'))
879 ) {
880
881
882 new_init_action(RESPAWN, bb_default_login_shell, "");
883 } else {
884
885
886
887
888
889
890 parse_inittab();
891 }
892
893#if ENABLE_SELINUX
894 if (getenv("SELINUX_INIT") == NULL) {
895 int enforce = 0;
896
897 putenv((char*)"SELINUX_INIT=YES");
898 if (selinux_init_load_policy(&enforce) == 0) {
899 BB_EXECVP(argv[0], argv);
900 } else if (enforce > 0) {
901
902 message(L_CONSOLE, "cannot load SELinux Policy. "
903 "Machine is in enforcing mode. Halting now.");
904 exit(EXIT_FAILURE);
905 }
906 }
907#endif
908
909
910 strncpy(argv[0], "init", strlen(argv[0]));
911
912 while (*++argv)
913 memset(*argv, 0, strlen(*argv));
914
915
916 if (!DEBUG_INIT) {
917 struct sigaction sa;
918
919 bb_signals(0
920 + (1 << SIGUSR1)
921 + (1 << SIGTERM)
922 + (1 << SIGUSR2)
923 , halt_reboot_pwoff);
924 signal(SIGQUIT, restart_handler);
925
926
927 memset(&sa, 0, sizeof(sa));
928 sigfillset(&sa.sa_mask);
929 sigdelset(&sa.sa_mask, SIGCONT);
930 sa.sa_handler = stop_handler;
931
932
933
934 sigaction_set(SIGTSTP, &sa);
935
936
937
938 sigaction_set(SIGSTOP, &sa);
939
940
941
942
943 bb_signals_recursive_norestart((1 << SIGINT), record_signo);
944 }
945
946
947
948 run_actions(SYSINIT);
949 check_delayed_sigs();
950
951 run_actions(WAIT);
952 check_delayed_sigs();
953
954 run_actions(ONCE);
955
956
957
958
959 if (!DEBUG_INIT && ENABLE_FEATURE_USE_INITTAB)
960 bb_signals_recursive_norestart((1 << SIGHUP), record_signo);
961
962
963
964
965 while (1) {
966 int maybe_WNOHANG;
967
968 maybe_WNOHANG = check_delayed_sigs();
969
970
971 run_actions(RESPAWN | ASKFIRST);
972 maybe_WNOHANG |= check_delayed_sigs();
973
974
975 sleep(1);
976 maybe_WNOHANG |= check_delayed_sigs();
977
978
979
980
981
982
983
984 if (maybe_WNOHANG)
985 maybe_WNOHANG = WNOHANG;
986 while (1) {
987 pid_t wpid;
988 struct init_action *a;
989
990 wpid = waitpid(-1, NULL, maybe_WNOHANG);
991 if (wpid <= 0)
992 break;
993
994 a = mark_terminated(wpid);
995 if (a) {
996 message(L_LOG, "process '%s' (pid %d) exited. "
997 "Scheduling for restart.",
998 a->command, wpid);
999 }
1000
1001 maybe_WNOHANG = WNOHANG;
1002 }
1003 }
1004}
1005