initd: use patch_stdio() for kmodloader stdio redirection
[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
81 early();
82 cmdline();
83 watchdog_init(1);
84
85 pid = fork();
86 if (!pid) {
87 char *kmod[] = { "/sbin/kmodloader", "/etc/modules-boot.d/", NULL };
88
89 if (debug < 3)
90 patch_stdio("/dev/null");
91
92 execvp(kmod[0], kmod);
93 ERROR("Failed to start kmodloader\n");
94 exit(-1);
95 }
96 if (pid <= 0) {
97 ERROR("Failed to start kmodloader instance\n");
98 } else {
99 int i;
100
101 for (i = 0; i < 1200; i++) {
102 if (waitpid(pid, NULL, WNOHANG) > 0)
103 break;
104 usleep(10 * 1000);
105 watchdog_ping();
106 }
107 }
108 uloop_init();
109 preinit();
110 uloop_run();
111
112 return 0;
113 }