procd: clean up /dev/pts mounts
[project/procd.git] / initd / init.c
1 /*
2 * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
3 * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License version 2.1
7 * as published by the Free Software Foundation
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15 #include <sys/wait.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <sys/reboot.h>
19
20 #include <libubox/uloop.h>
21 #include <libubus.h>
22
23 #include <limits.h>
24 #include <stdlib.h>
25 #include <fcntl.h>
26 #include <getopt.h>
27 #include <libgen.h>
28 #include <regex.h>
29 #include <unistd.h>
30 #include <stdio.h>
31
32 #if defined(WITH_SELINUX)
33 #include <selinux/selinux.h>
34 #endif
35
36 #include "../utils/utils.h"
37 #include "init.h"
38 #include "../watchdog.h"
39
40 unsigned int debug = 0;
41
42 static void
43 signal_shutdown(int signal, siginfo_t *siginfo, void *data)
44 {
45 fprintf(stderr, "reboot\n");
46 fflush(stderr);
47 sync();
48 sleep(2);
49 reboot(RB_AUTOBOOT);
50 while (1)
51 ;
52 }
53
54 static struct sigaction sa_shutdown = {
55 .sa_sigaction = signal_shutdown,
56 .sa_flags = SA_SIGINFO
57 };
58
59 static void
60 cmdline(void)
61 {
62 char line[20];
63 char* res;
64 long r;
65
66 res = get_cmdline_val("init_debug", line, sizeof(line));
67 if (res != NULL) {
68 r = strtol(line, NULL, 10);
69 if ((r != LONG_MIN) && (r != LONG_MAX))
70 debug = (int) r;
71 }
72 }
73
74 #if defined(WITH_SELINUX)
75 static int
76 selinux(char **argv)
77 {
78 int enforce = 0;
79 int ret;
80
81 /* SELinux already initialized */
82 if (getenv("SELINUX_INIT"))
83 return 0;
84
85 putenv("SELINUX_INIT=1");
86
87 ret = selinux_init_load_policy(&enforce);
88 if (ret == 0)
89 execv(argv[0], argv);
90
91 if (enforce > 0) {
92 fprintf(stderr, "Cannot load SELinux policy, but system in enforcing mode. Halting.\n");
93 return 1;
94 }
95
96 return 0;
97 }
98 #else
99 static int
100 selinux(char **argv)
101 {
102 return 0;
103 }
104 #endif
105
106 int
107 main(int argc, char **argv)
108 {
109 pid_t pid;
110
111 ulog_open(ULOG_KMSG, LOG_DAEMON, "init");
112
113 sigaction(SIGTERM, &sa_shutdown, NULL);
114 sigaction(SIGUSR1, &sa_shutdown, NULL);
115 sigaction(SIGUSR2, &sa_shutdown, NULL);
116 sigaction(SIGPWR, &sa_shutdown, NULL);
117
118 if (selinux(argv))
119 exit(-1);
120 early();
121 cmdline();
122 watchdog_init(1);
123
124 pid = fork();
125 if (!pid) {
126 char *kmod[] = { "/sbin/kmodloader", "/etc/modules-boot.d/", NULL };
127
128 if (debug < 3)
129 patch_stdio("/dev/null");
130
131 execvp(kmod[0], kmod);
132 ERROR("Failed to start kmodloader: %m\n");
133 exit(EXIT_FAILURE);
134 }
135 if (pid <= 0) {
136 ERROR("Failed to start kmodloader instance: %m\n");
137 } else {
138 const struct timespec req = {0, 10 * 1000 * 1000};
139 int i;
140
141 for (i = 0; i < 1200; i++) {
142 if (waitpid(pid, NULL, WNOHANG) > 0)
143 break;
144 nanosleep(&req, NULL);
145 watchdog_ping();
146 }
147 }
148 uloop_init();
149 preinit();
150 uloop_run();
151
152 return 0;
153 }