9b4782608e1a7a9f411eaacfa9b97b2d6b3fe89c
[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 #include "../utils/utils.h"
33 #include "init.h"
34 #include "../watchdog.h"
35
36 unsigned int debug = 0;
37
38 static void
39 signal_shutdown(int signal, siginfo_t *siginfo, void *data)
40 {
41 fprintf(stderr, "reboot\n");
42 fflush(stderr);
43 sync();
44 sleep(2);
45 reboot(RB_AUTOBOOT);
46 while (1)
47 ;
48 }
49
50 static struct sigaction sa_shutdown = {
51 .sa_sigaction = signal_shutdown,
52 .sa_flags = SA_SIGINFO
53 };
54
55 static void
56 cmdline(void)
57 {
58 char line[20];
59 char* res;
60 long r;
61
62 res = get_cmdline_val("init_debug", line, sizeof(line));
63 if (res != NULL) {
64 r = strtol(line, NULL, 10);
65 if ((r != LONG_MIN) && (r != LONG_MAX))
66 debug = (int) r;
67 }
68 }
69
70 int
71 main(int argc, char **argv)
72 {
73 pid_t pid;
74
75 ulog_open(ULOG_KMSG, LOG_DAEMON, "init");
76
77 sigaction(SIGTERM, &sa_shutdown, NULL);
78 sigaction(SIGUSR1, &sa_shutdown, NULL);
79 sigaction(SIGUSR2, &sa_shutdown, NULL);
80 sigaction(SIGPWR, &sa_shutdown, NULL);
81
82 early();
83 cmdline();
84 watchdog_init(1);
85
86 pid = fork();
87 if (!pid) {
88 char *kmod[] = { "/sbin/kmodloader", "/etc/modules-boot.d/", NULL };
89
90 if (debug < 3)
91 patch_stdio("/dev/null");
92
93 execvp(kmod[0], kmod);
94 ERROR("Failed to start kmodloader: %m\n");
95 exit(EXIT_FAILURE);
96 }
97 if (pid <= 0) {
98 ERROR("Failed to start kmodloader instance: %m\n");
99 } else {
100 const struct timespec req = {0, 10 * 1000 * 1000};
101 int i;
102
103 for (i = 0; i < 1200; i++) {
104 if (waitpid(pid, NULL, WNOHANG) > 0)
105 break;
106 nanosleep(&req, NULL);
107 watchdog_ping();
108 }
109 }
110 uloop_init();
111 preinit();
112 uloop_run();
113
114 return 0;
115 }