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