aboutsummaryrefslogtreecommitdiff
path: root/init
diff options
context:
space:
mode:
authorErik Andersen <andersen@codepoet.org>2000-02-08 19:58:47 +0000
committerErik Andersen <andersen@codepoet.org>2000-02-08 19:58:47 +0000
commite49d5ecbbe51718fa925b6890a735e5937cc2aa2 (patch)
treec90bda10731ad9333ce3b404f993354c9fc104b8 /init
parentc0bf817bbc5c7867fbe8fb76d5c39f8ee802692f (diff)
downloadbusybox-w32-e49d5ecbbe51718fa925b6890a735e5937cc2aa2.tar.gz
busybox-w32-e49d5ecbbe51718fa925b6890a735e5937cc2aa2.tar.bz2
busybox-w32-e49d5ecbbe51718fa925b6890a735e5937cc2aa2.zip
Some formatting updates (ran the code through indent)
-Erik
Diffstat (limited to 'init')
-rw-r--r--init/halt.c9
-rw-r--r--init/init.c1335
-rw-r--r--init/poweroff.c8
-rw-r--r--init/reboot.c8
4 files changed, 690 insertions, 670 deletions
diff --git a/init/halt.c b/init/halt.c
index 23eb23c30..d61c38760 100644
--- a/init/halt.c
+++ b/init/halt.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini halt implementation for busybox 3 * Mini halt implementation for busybox
3 * 4 *
@@ -23,10 +24,8 @@
23#include "internal.h" 24#include "internal.h"
24#include <signal.h> 25#include <signal.h>
25 26
26extern int 27extern int halt_main(int argc, char **argv)
27halt_main(int argc, char ** argv)
28{ 28{
29 /* don't assume init's pid == 1 */ 29 /* don't assume init's pid == 1 */
30 exit( kill(findInitPid(), SIGUSR1)); 30 exit(kill(findInitPid(), SIGUSR1));
31} 31}
32
diff --git a/init/init.c b/init/init.c
index 6dad7181b..899dca48c 100644
--- a/init/init.c
+++ b/init/init.c
@@ -41,8 +41,8 @@
41#include <sys/kdaemon.h> 41#include <sys/kdaemon.h>
42#include <sys/sysmacros.h> 42#include <sys/sysmacros.h>
43#include <asm/types.h> 43#include <asm/types.h>
44#include <linux/serial.h> /* for serial_struct */ 44#include <linux/serial.h> /* for serial_struct */
45#include <sys/vt.h> /* for vt_stat */ 45#include <sys/vt.h> /* for vt_stat */
46#include <sys/ioctl.h> 46#include <sys/ioctl.h>
47#include <linux/version.h> 47#include <linux/version.h>
48#ifdef BB_SYSLOGD 48#ifdef BB_SYSLOGD
@@ -58,15 +58,15 @@
58#endif 58#endif
59 59
60 60
61#define VT_PRIMARY "/dev/tty1" /* Primary virtual console */ 61#define VT_PRIMARY "/dev/tty1" /* Primary virtual console */
62#define VT_SECONDARY "/dev/tty2" /* Virtual console */ 62#define VT_SECONDARY "/dev/tty2" /* Virtual console */
63#define VT_LOG "/dev/tty3" /* Virtual console */ 63#define VT_LOG "/dev/tty3" /* Virtual console */
64#define SERIAL_CON0 "/dev/ttyS0" /* Primary serial console */ 64#define SERIAL_CON0 "/dev/ttyS0" /* Primary serial console */
65#define SERIAL_CON1 "/dev/ttyS1" /* Serial console */ 65#define SERIAL_CON1 "/dev/ttyS1" /* Serial console */
66#define SHELL "/bin/sh" /* Default shell */ 66#define SHELL "/bin/sh" /* Default shell */
67#define INITTAB "/etc/inittab" /* inittab file location */ 67#define INITTAB "/etc/inittab" /* inittab file location */
68#ifndef INIT_SCRIPT 68#ifndef INIT_SCRIPT
69#define INIT_SCRIPT "/etc/init.d/rcS" /* Default sysinit script. */ 69#define INIT_SCRIPT "/etc/init.d/rcS" /* Default sysinit script. */
70#endif 70#endif
71 71
72#define LOG 0x1 72#define LOG 0x1
@@ -74,38 +74,38 @@
74 74
75/* Allowed init action types */ 75/* Allowed init action types */
76typedef enum { 76typedef enum {
77 SYSINIT=1, 77 SYSINIT = 1,
78 RESPAWN, 78 RESPAWN,
79 ASKFIRST, 79 ASKFIRST,
80 WAIT, 80 WAIT,
81 ONCE 81 ONCE
82} initActionEnum; 82} initActionEnum;
83 83
84/* And now a list of the actions we support in the version of init */ 84/* And now a list of the actions we support in the version of init */
85typedef struct initActionType{ 85typedef struct initActionType {
86 const char* name; 86 const char *name;
87 initActionEnum action; 87 initActionEnum action;
88} initActionType; 88} initActionType;
89 89
90static const struct initActionType actions[] = { 90static const struct initActionType actions[] = {
91 {"sysinit", SYSINIT}, 91 {"sysinit", SYSINIT},
92 {"respawn", RESPAWN}, 92 {"respawn", RESPAWN},
93 {"askfirst", ASKFIRST}, 93 {"askfirst", ASKFIRST},
94 {"wait", WAIT}, 94 {"wait", WAIT},
95 {"once", ONCE}, 95 {"once", ONCE},
96 {0} 96 {0}
97}; 97};
98 98
99/* Set up a linked list of initactions, to be read from inittab */ 99/* Set up a linked list of initactions, to be read from inittab */
100typedef struct initActionTag initAction; 100typedef struct initActionTag initAction;
101struct initActionTag { 101struct initActionTag {
102 pid_t pid; 102 pid_t pid;
103 char process[256]; 103 char process[256];
104 char console[256]; 104 char console[256];
105 initAction *nextPtr; 105 initAction *nextPtr;
106 initActionEnum action; 106 initActionEnum action;
107}; 107};
108initAction* initActionList = NULL; 108initAction *initActionList = NULL;
109 109
110 110
111static char *secondConsole = VT_SECONDARY; 111static char *secondConsole = VT_SECONDARY;
@@ -119,517 +119,533 @@ static char console[32] = _PATH_CONSOLE;
119 * device may be bitwise-or'd from LOG | CONSOLE */ 119 * device may be bitwise-or'd from LOG | CONSOLE */
120void message(int device, char *fmt, ...) 120void message(int device, char *fmt, ...)
121{ 121{
122 va_list arguments; 122 va_list arguments;
123 int fd; 123 int fd;
124 124
125#ifdef BB_SYSLOGD 125#ifdef BB_SYSLOGD
126 126
127 /* Log the message to syslogd */ 127 /* Log the message to syslogd */
128 if (device & LOG ) { 128 if (device & LOG) {
129 char msg[1024]; 129 char msg[1024];
130 va_start(arguments, fmt);
131 vsnprintf(msg, sizeof(msg), fmt, arguments);
132 va_end(arguments);
133 openlog( "init", 0, LOG_DAEMON);
134 syslog(LOG_DAEMON|LOG_NOTICE, msg);
135 closelog();
136 }
137 130
131 va_start(arguments, fmt);
132 vsnprintf(msg, sizeof(msg), fmt, arguments);
133 va_end(arguments);
134 openlog("init", 0, LOG_DAEMON);
135 syslog(LOG_DAEMON | LOG_NOTICE, msg);
136 closelog();
137 }
138#else 138#else
139 static int log_fd = -1; 139 static int log_fd = -1;
140 140
141 /* Take full control of the log tty, and never close it. 141 /* Take full control of the log tty, and never close it.
142 * It's mine, all mine! Muhahahaha! */ 142 * It's mine, all mine! Muhahahaha! */
143 if (log_fd < 0) { 143 if (log_fd < 0) {
144 if (log == NULL) { 144 if (log == NULL) {
145 /* don't even try to log, because there is no such console */ 145 /* don't even try to log, because there is no such console */
146 log_fd = -2; 146 log_fd = -2;
147 /* log to main console instead */ 147 /* log to main console instead */
148 device = CONSOLE; 148 device = CONSOLE;
149 } 149 } else if ((log_fd = device_open(log, O_RDWR | O_NDELAY)) < 0) {
150 else if ((log_fd = device_open(log, O_RDWR|O_NDELAY)) < 0) { 150 log_fd = -1;
151 log_fd = -1; 151 fprintf(stderr, "Bummer, can't write to log on %s!\r\n", log);
152 fprintf(stderr, "Bummer, can't write to log on %s!\r\n", log); 152 fflush(stderr);
153 fflush(stderr); 153 return;
154 return; 154 }
155 }
156 if ((device & LOG) && (log_fd >= 0)) {
157 va_start(arguments, fmt);
158 vdprintf(log_fd, fmt, arguments);
159 va_end(arguments);
155 } 160 }
156 }
157 if ( (device & LOG) && (log_fd >= 0) ) {
158 va_start(arguments, fmt);
159 vdprintf(log_fd, fmt, arguments);
160 va_end(arguments);
161 }
162#endif 161#endif
163 162
164 if (device & CONSOLE) { 163 if (device & CONSOLE) {
165 /* Always send console messages to /dev/console so people will see them. */ 164 /* Always send console messages to /dev/console so people will see them. */
166 if ((fd = device_open(_PATH_CONSOLE, O_WRONLY|O_NOCTTY|O_NDELAY)) >= 0) { 165 if (
167 va_start(arguments, fmt); 166 (fd =
168 vdprintf(fd, fmt, arguments); 167 device_open(_PATH_CONSOLE,
169 va_end(arguments); 168 O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) {
170 close(fd); 169 va_start(arguments, fmt);
171 } else { 170 vdprintf(fd, fmt, arguments);
172 fprintf(stderr, "Bummer, can't print: "); 171 va_end(arguments);
173 va_start(arguments, fmt); 172 close(fd);
174 vfprintf(stderr, fmt, arguments); 173 } else {
175 fflush(stderr); 174 fprintf(stderr, "Bummer, can't print: ");
176 va_end(arguments); 175 va_start(arguments, fmt);
176 vfprintf(stderr, fmt, arguments);
177 fflush(stderr);
178 va_end(arguments);
179 }
177 } 180 }
178 }
179} 181}
180 182
181 183
182/* Set terminal settings to reasonable defaults */ 184/* Set terminal settings to reasonable defaults */
183void set_term( int fd) 185void set_term(int fd)
184{ 186{
185 struct termios tty; 187 struct termios tty;
186 static const char control_characters[] = { 188 static const char control_characters[] = {
187 '\003', '\034', '\177', '\025', '\004', '\0', 189 '\003', '\034', '\177', '\025', '\004', '\0',
188 '\1', '\0', '\021', '\023', '\032', '\0', '\022', 190 '\1', '\0', '\021', '\023', '\032', '\0', '\022',
189 '\017', '\027', '\026', '\0' 191 '\017', '\027', '\026', '\0'
190 }; 192 };
191 193
192 tcgetattr(fd, &tty); 194 tcgetattr(fd, &tty);
193 195
194 /* set control chars */ 196 /* set control chars */
195 memcpy(tty.c_cc, control_characters, sizeof(control_characters)); 197 memcpy(tty.c_cc, control_characters, sizeof(control_characters));
196 198
197 /* use line dicipline 0 */ 199 /* use line dicipline 0 */
198 tty.c_line = 0; 200 tty.c_line = 0;
199 201
200 /* Make it be sane */ 202 /* Make it be sane */
201 //tty.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD; 203 //tty.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD;
202 //tty.c_cflag |= HUPCL|CLOCAL; 204 //tty.c_cflag |= HUPCL|CLOCAL;
203 205
204 /* input modes */ 206 /* input modes */
205 tty.c_iflag = ICRNL|IXON|IXOFF; 207 tty.c_iflag = ICRNL | IXON | IXOFF;
206 208
207 /* output modes */ 209 /* output modes */
208 tty.c_oflag = OPOST|ONLCR; 210 tty.c_oflag = OPOST | ONLCR;
209 211
210 /* local modes */ 212 /* local modes */
211 tty.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE|IEXTEN; 213 tty.c_lflag =
214 ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
212 215
213 tcsetattr(fd, TCSANOW, &tty); 216 tcsetattr(fd, TCSANOW, &tty);
214} 217}
215 218
216/* How much memory does this machine have? */ 219/* How much memory does this machine have? */
217static int mem_total() 220static int mem_total()
218{ 221{
219 char s[80]; 222 char s[80];
220 char *p = "/proc/meminfo"; 223 char *p = "/proc/meminfo";
221 FILE *f; 224 FILE *f;
222 const char pattern[] = "MemTotal:"; 225 const char pattern[] = "MemTotal:";
223 226
224 if ((f = fopen(p, "r")) < 0) { 227 if ((f = fopen(p, "r")) < 0) {
225 message(LOG, "Error opening %s: %s\n", p, strerror( errno)); 228 message(LOG, "Error opening %s: %s\n", p, strerror(errno));
226 return -1; 229 return -1;
227 } 230 }
228 while (NULL != fgets(s, 79, f)) { 231 while (NULL != fgets(s, 79, f)) {
229 p = strstr(s, pattern); 232 p = strstr(s, pattern);
230 if (NULL != p) { 233 if (NULL != p) {
231 fclose(f); 234 fclose(f);
232 return (atoi(p + strlen(pattern))); 235 return (atoi(p + strlen(pattern)));
236 }
233 } 237 }
234 } 238 return -1;
235 return -1;
236} 239}
237 240
238static void console_init() 241static void console_init()
239{ 242{
240 int fd; 243 int fd;
241 int tried_devcons = 0; 244 int tried_devcons = 0;
242 int tried_vtprimary = 0; 245 int tried_vtprimary = 0;
243 struct serial_struct sr; 246 struct serial_struct sr;
244 char *s; 247 char *s;
245 248
246 if ((s = getenv("TERM")) != NULL) { 249 if ((s = getenv("TERM")) != NULL) {
247 snprintf(termType,sizeof(termType)-1,"TERM=%s",s); 250 snprintf(termType, sizeof(termType) - 1, "TERM=%s", s);
248 } 251 }
249
250 if ((s = getenv("CONSOLE")) != NULL) {
251 snprintf(console, sizeof(console)-1, "%s",s);
252 }
253#if #cpu(sparc)
254 /* sparc kernel supports console=tty[ab] parameter which is also
255 * passed to init, so catch it here */
256 else if ((s = getenv("console")) != NULL) {
257 /* remap tty[ab] to /dev/ttyS[01] */
258 if (strcmp( s, "ttya" )==0)
259 snprintf(console, sizeof(console)-1, "%s", SERIAL_CON0);
260 else if (strcmp( s, "ttyb" )==0)
261 snprintf(console, sizeof(console)-1, "%s", SERIAL_CON1);
262 }
263#endif
264 else {
265 struct vt_stat vt;
266 252
267 /* 2.2 kernels: identify the real console backend and try to use it */ 253 if ((s = getenv("CONSOLE")) != NULL) {
268 if (ioctl(0, TIOCGSERIAL, &sr) == 0) { 254 snprintf(console, sizeof(console) - 1, "%s", s);
269 /* this is a serial console */
270 snprintf(console, sizeof(console)-1, "/dev/ttyS%d", sr.line);
271 } 255 }
272 else if (ioctl(0, VT_GETSTATE, &vt) == 0) { 256#if #cpu(sparc)
273 /* this is linux virtual tty */ 257 /* sparc kernel supports console=tty[ab] parameter which is also
274 snprintf(console, sizeof(console)-1, "/dev/tty%d", vt.v_active); 258 * passed to init, so catch it here */
275 } else { 259 else if ((s = getenv("console")) != NULL) {
276 snprintf(console, sizeof(console)-1, "%s", _PATH_CONSOLE); 260 /* remap tty[ab] to /dev/ttyS[01] */
277 tried_devcons++; 261 if (strcmp(s, "ttya") == 0)
262 snprintf(console, sizeof(console) - 1, "%s", SERIAL_CON0);
263 else if (strcmp(s, "ttyb") == 0)
264 snprintf(console, sizeof(console) - 1, "%s", SERIAL_CON1);
278 } 265 }
279 } 266#endif
280 267 else {
281 while ((fd = open(console, O_RDONLY | O_NONBLOCK)) < 0) { 268 struct vt_stat vt;
282 /* Can't open selected console -- try /dev/console */ 269
283 if (!tried_devcons) { 270 /* 2.2 kernels: identify the real console backend and try to use it */
284 tried_devcons++; 271 if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
285 snprintf(console, sizeof(console)-1, "%s", _PATH_CONSOLE); 272 /* this is a serial console */
286 continue; 273 snprintf(console, sizeof(console) - 1, "/dev/ttyS%d", sr.line);
274 } else if (ioctl(0, VT_GETSTATE, &vt) == 0) {
275 /* this is linux virtual tty */
276 snprintf(console, sizeof(console) - 1, "/dev/tty%d",
277 vt.v_active);
278 } else {
279 snprintf(console, sizeof(console) - 1, "%s", _PATH_CONSOLE);
280 tried_devcons++;
281 }
287 } 282 }
288 /* Can't open selected console -- try vt1 */ 283
289 if (!tried_vtprimary) { 284 while ((fd = open(console, O_RDONLY | O_NONBLOCK)) < 0) {
290 tried_vtprimary++; 285 /* Can't open selected console -- try /dev/console */
291 snprintf(console, sizeof(console)-1, "%s", VT_PRIMARY); 286 if (!tried_devcons) {
292 continue; 287 tried_devcons++;
288 snprintf(console, sizeof(console) - 1, "%s", _PATH_CONSOLE);
289 continue;
290 }
291 /* Can't open selected console -- try vt1 */
292 if (!tried_vtprimary) {
293 tried_vtprimary++;
294 snprintf(console, sizeof(console) - 1, "%s", VT_PRIMARY);
295 continue;
296 }
297 break;
293 } 298 }
294 break; 299 if (fd < 0) {
295 } 300 /* Perhaps we should panic here? */
296 if (fd < 0) { 301 snprintf(console, sizeof(console) - 1, "/dev/null");
297 /* Perhaps we should panic here? */ 302 } else {
298 snprintf(console, sizeof(console)-1, "/dev/null"); 303 /* check for serial console and disable logging to tty3 & running a
299 } else { 304 * shell to tty2 */
300 /* check for serial console and disable logging to tty3 & running a 305 if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
301 * shell to tty2 */ 306 message(LOG | CONSOLE,
302 if (ioctl(0,TIOCGSERIAL,&sr) == 0) { 307 "serial console detected. Disabling virtual terminals.\r\n");
303 message(LOG|CONSOLE, "serial console detected. Disabling virtual terminals.\r\n" ); 308 log = NULL;
304 log = NULL; 309 secondConsole = NULL;
305 secondConsole = NULL; 310 }
311 close(fd);
306 } 312 }
307 close(fd); 313 message(LOG, "console=%s\n", console);
308 }
309 message(LOG, "console=%s\n", console );
310} 314}
311 315
312static pid_t run(char* command, 316static pid_t run(char *command, char *terminal, int get_enter)
313 char *terminal, int get_enter)
314{ 317{
315 int i, fd; 318 int i, fd;
316 pid_t pid; 319 pid_t pid;
317 char* tmpCmd; 320 char *tmpCmd;
318 char* cmd[255]; 321 char *cmd[255];
319 static const char press_enter[] = 322 static const char press_enter[] =
320 "\nPlease press Enter to activate this console. "; 323
321 char* environment[] = { 324 "\nPlease press Enter to activate this console. ";
322 "HOME=/", 325 char *environment[] = {
323 "PATH=/usr/bin:/bin:/usr/sbin:/sbin", 326 "HOME=/",
324 "SHELL=/bin/sh", 327 "PATH=/usr/bin:/bin:/usr/sbin:/sbin",
325 termType, 328 "SHELL=/bin/sh",
326 "USER=root", 329 termType,
327 0 330 "USER=root",
328 }; 331 0
329 332 };
330
331 if ((pid = fork()) == 0) {
332 pid_t shell_pgid = getpid ();
333
334 /* Clean up */
335 close(0);
336 close(1);
337 close(2);
338 setsid();
339 333
340 /* Reset signal handlers set for parent process */
341 signal(SIGUSR1, SIG_DFL);
342 signal(SIGUSR2, SIG_DFL);
343 signal(SIGINT, SIG_DFL);
344 signal(SIGTERM, SIG_DFL);
345 signal(SIGHUP, SIG_DFL);
346 334
347 if ((fd = device_open(terminal, O_RDWR)) < 0) { 335 if ((pid = fork()) == 0) {
348 message(LOG|CONSOLE, "Bummer, can't open %s\r\n", terminal); 336 pid_t shell_pgid = getpid();
349 exit(1);
350 }
351 dup2(fd, 0);
352 dup2(fd, 1);
353 dup2(fd, 2);
354 tcsetpgrp (0, getpgrp());
355 set_term(0);
356 337
357 if (get_enter==TRUE) { 338 /* Clean up */
358 /* 339 close(0);
359 * Save memory by not exec-ing anything large (like a shell) 340 close(1);
360 * before the user wants it. This is critical if swap is not 341 close(2);
361 * enabled and the system has low memory. Generally this will 342 setsid();
362 * be run on the second virtual console, and the first will 343
363 * be allowed to start a shell or whatever an init script 344 /* Reset signal handlers set for parent process */
364 * specifies. 345 signal(SIGUSR1, SIG_DFL);
365 */ 346 signal(SIGUSR2, SIG_DFL);
366 char c; 347 signal(SIGINT, SIG_DFL);
367 message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n", 348 signal(SIGTERM, SIG_DFL);
368 command, shell_pgid, terminal ); 349 signal(SIGHUP, SIG_DFL);
369 write(fileno(stdout), press_enter, sizeof(press_enter) - 1); 350
370 read(fileno(stdin), &c, 1); 351 if ((fd = device_open(terminal, O_RDWR)) < 0) {
371 } 352 message(LOG | CONSOLE, "Bummer, can't open %s\r\n", terminal);
353 exit(1);
354 }
355 dup2(fd, 0);
356 dup2(fd, 1);
357 dup2(fd, 2);
358 tcsetpgrp(0, getpgrp());
359 set_term(0);
360
361 if (get_enter == TRUE) {
362 /*
363 * Save memory by not exec-ing anything large (like a shell)
364 * before the user wants it. This is critical if swap is not
365 * enabled and the system has low memory. Generally this will
366 * be run on the second virtual console, and the first will
367 * be allowed to start a shell or whatever an init script
368 * specifies.
369 */
370 char c;
371
372 message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n",
373 command, shell_pgid, terminal);
374 write(fileno(stdout), press_enter, sizeof(press_enter) - 1);
375 read(fileno(stdin), &c, 1);
376 }
372 377
373 /* Log the process name and args */ 378 /* Log the process name and args */
374 message(LOG, "Starting pid %d, console %s: '", 379 message(LOG, "Starting pid %d, console %s: '",
375 shell_pgid, terminal, command); 380 shell_pgid, terminal, command);
376 381
377 /* Convert command (char*) into cmd (char**, one word per string) */ 382 /* Convert command (char*) into cmd (char**, one word per string) */
378 for (tmpCmd=command, i=0; (tmpCmd=strsep(&command, " \t")) != NULL;) { 383 for (tmpCmd = command, i = 0;
379 if (*tmpCmd != '\0') { 384 (tmpCmd = strsep(&command, " \t")) != NULL;) {
380 cmd[i] = tmpCmd; 385 if (*tmpCmd != '\0') {
381 message(LOG, "%s ", tmpCmd); 386 cmd[i] = tmpCmd;
382 tmpCmd++; 387#ifdef DEBUG_INIT
383 i++; 388 message(LOG, "%s ", tmpCmd);
384 } 389#endif
390 tmpCmd++;
391 i++;
392 }
393 }
394 cmd[i] = NULL;
395 message(LOG, "'\r\n");
396
397 /* Now run it. The new program will take over this PID,
398 * so nothing further in init.c should be run. */
399 execve(cmd[0], cmd, environment);
400
401 /* We're still here? Some error happened. */
402 message(LOG | CONSOLE, "Bummer, could not run '%s': %s\n", cmd[0],
403 strerror(errno));
404 exit(-1);
385 } 405 }
386 cmd[i] = NULL; 406 return pid;
387 message(LOG, "'\r\n");
388
389 /* Now run it. The new program will take over this PID,
390 * so nothing further in init.c should be run. */
391 execve(cmd[0], cmd, environment);
392
393 /* We're still here? Some error happened. */
394 message(LOG|CONSOLE, "Bummer, could not run '%s': %s\n", cmd[0],
395 strerror(errno));
396 exit(-1);
397 }
398 return pid;
399} 407}
400 408
401static int waitfor(char* command, 409static int waitfor(char *command, char *terminal, int get_enter)
402 char *terminal, int get_enter)
403{ 410{
404 int status, wpid; 411 int status, wpid;
405 int pid = run( command, terminal, get_enter); 412 int pid = run(command, terminal, get_enter);
406 413
407 while (1) { 414 while (1) {
408 wpid = wait(&status); 415 wpid = wait(&status);
409 if (wpid > 0 ) { 416 if (wpid > 0) {
410 message(LOG, "Process '%s' (pid %d) exited.\n", 417 message(LOG, "Process '%s' (pid %d) exited.\n", command, wpid);
411 command, wpid); 418 break;
412 break; 419 }
420 if (wpid == pid)
421 break;
413 } 422 }
414 if (wpid == pid ) 423 return wpid;
415 break;
416 }
417 return wpid;
418} 424}
419 425
420/* Make sure there is enough memory to do something useful. * 426/* Make sure there is enough memory to do something useful. *
421 * Calls swapon if needed so be sure /proc is mounted. */ 427 * Calls swapon if needed so be sure /proc is mounted. */
422static void check_memory() 428static void check_memory()
423{ 429{
424 struct stat statBuf; 430 struct stat statBuf;
425 431
426 if (mem_total() > 3500) 432 if (mem_total() > 3500)
433 return;
434
435 if (stat("/etc/fstab", &statBuf) == 0) {
436 /* Try to turn on swap */
437 waitfor("/bin/swapon swapon -a", log, FALSE);
438 if (mem_total() < 3500)
439 goto goodnight;
440 } else
441 goto goodnight;
427 return; 442 return;
428 443
429 if (stat("/etc/fstab", &statBuf) == 0) { 444 goodnight:
430 /* Try to turn on swap */ 445 message(CONSOLE,
431 waitfor("/bin/swapon swapon -a", log, FALSE); 446 "Sorry, your computer does not have enough memory.\r\n");
432 if (mem_total() < 3500) 447 while (1)
433 goto goodnight; 448 sleep(1);
434 } else
435 goto goodnight;
436 return;
437
438goodnight:
439 message(CONSOLE, "Sorry, your computer does not have enough memory.\r\n");
440 while (1) sleep(1);
441} 449}
442 450
443#ifndef DEBUG_INIT 451#ifndef DEBUG_INIT
444static void shutdown_system(void) 452static void shutdown_system(void)
445{ 453{
446 /* first disable our SIGHUP signal */ 454 /* first disable our SIGHUP signal */
447 signal(SIGHUP, SIG_DFL); 455 signal(SIGHUP, SIG_DFL);
448 456
449 /* Allow Ctrl-Alt-Del to reboot system. */ 457 /* Allow Ctrl-Alt-Del to reboot system. */
450 reboot(RB_ENABLE_CAD); 458 reboot(RB_ENABLE_CAD);
451 message(CONSOLE, "\r\nThe system is going down NOW !!\r\n"); 459 message(CONSOLE, "\r\nThe system is going down NOW !!\r\n");
452 sync(); 460 sync();
453 461
454 /* Send signals to every process _except_ pid 1 */ 462 /* Send signals to every process _except_ pid 1 */
455 message(CONSOLE, "Sending SIGTERM to all processes.\r\n"); 463 message(CONSOLE, "Sending SIGTERM to all processes.\r\n");
456 kill(-1, SIGTERM); 464 kill(-1, SIGTERM);
457 sleep(5); 465 sleep(5);
458 sync(); 466 sync();
459 467
460 message(CONSOLE, "Sending SIGKILL to all processes.\r\n"); 468 message(CONSOLE, "Sending SIGKILL to all processes.\r\n");
461 kill(-1, SIGKILL); 469 kill(-1, SIGKILL);
462 sleep(5); 470 sleep(5);
463 471
464 message(CONSOLE, "Disabling swap.\r\n"); 472 message(CONSOLE, "Disabling swap.\r\n");
465 waitfor( "swapoff -a", console, FALSE); 473 waitfor("swapoff -a", console, FALSE);
466 message(CONSOLE, "Unmounting filesystems.\r\n"); 474 message(CONSOLE, "Unmounting filesystems.\r\n");
467 waitfor("umount -a -r", console, FALSE); 475 waitfor("umount -a -r", console, FALSE);
468 sync();
469 if (kernelVersion > 0 && kernelVersion <= 2 * 65536 + 2 * 256 + 11) {
470 /* bdflush, kupdate not needed for kernels >2.2.11 */
471 bdflush(1, 0);
472 sync(); 476 sync();
473 } 477 if (kernelVersion > 0 && kernelVersion <= 2 * 65536 + 2 * 256 + 11) {
478 /* bdflush, kupdate not needed for kernels >2.2.11 */
479 bdflush(1, 0);
480 sync();
481 }
474} 482}
475 483
476static void halt_signal(int sig) 484static void halt_signal(int sig)
477{ 485{
478 shutdown_system(); 486 shutdown_system();
479 message(CONSOLE, "The system is halted. Press %s or turn off power\r\n", 487 message(CONSOLE,
480 (secondConsole == NULL) /* serial console */ 488 "The system is halted. Press %s or turn off power\r\n",
481 ? "Reset" : "CTRL-ALT-DEL"); 489 (secondConsole == NULL) /* serial console */
482 sync(); 490 ? "Reset" : "CTRL-ALT-DEL");
491 sync();
483 492
484 /* allow time for last message to reach serial console */ 493 /* allow time for last message to reach serial console */
485 sleep(5); 494 sleep(5);
486 495
487#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) 496#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
488 if (sig == SIGUSR2) 497 if (sig == SIGUSR2)
489 reboot(RB_POWER_OFF); 498 reboot(RB_POWER_OFF);
490 else 499 else
491#endif 500#endif
492 reboot(RB_HALT_SYSTEM); 501 reboot(RB_HALT_SYSTEM);
493 exit(0); 502 exit(0);
494} 503}
495 504
496static void reboot_signal(int sig) 505static void reboot_signal(int sig)
497{ 506{
498 shutdown_system(); 507 shutdown_system();
499 message(CONSOLE, "Please stand by while rebooting the system.\r\n"); 508 message(CONSOLE, "Please stand by while rebooting the system.\r\n");
500 sync(); 509 sync();
501 510
502 /* allow time for last message to reach serial console */ 511 /* allow time for last message to reach serial console */
503 sleep(2); 512 sleep(2);
504 513
505 reboot(RB_AUTOBOOT); 514 reboot(RB_AUTOBOOT);
506 exit(0); 515 exit(0);
507} 516}
508 517
509#if defined BB_FEATURE_INIT_CHROOT 518#if defined BB_FEATURE_INIT_CHROOT
510static void check_chroot(int sig) 519static void check_chroot(int sig)
511{ 520{
512 char *argv_init[2] = { "init", NULL, }; 521 char *argv_init[2] = { "init", NULL, };
513 char *envp_init[3] = { "HOME=/", "TERM=linux", NULL, }; 522 char *envp_init[3] = { "HOME=/", "TERM=linux", NULL, };
514 char rootpath[256], *tc; 523 char rootpath[256], *tc;
515 int fd; 524 int fd;
525
526 if ((fd = open("/proc/sys/kernel/init-chroot", O_RDONLY)) == -1) {
527 message(CONSOLE,
528 "SIGHUP recived, but could not open proc file\r\n");
529 sleep(2);
530 return;
531 }
532 if (read(fd, rootpath, sizeof(rootpath)) == -1) {
533 message(CONSOLE,
534 "SIGHUP recived, but could not read proc file\r\n");
535 sleep(2);
536 return;
537 }
538 close(fd);
516 539
517 if ((fd = open("/proc/sys/kernel/init-chroot", O_RDONLY)) == -1) { 540 if (rootpath[0] == '\0') {
518 message(CONSOLE, "SIGHUP recived, but could not open proc file\r\n"); 541 message(CONSOLE,
519 sleep(2); 542 "SIGHUP recived, but new root is not valid: %s\r\n",
520 return; 543 rootpath);
521 } 544 sleep(2);
522 if (read(fd, rootpath, sizeof(rootpath)) == -1) { 545 return;
523 message(CONSOLE, "SIGHUP recived, but could not read proc file\r\n"); 546 }
547
548 tc = strrchr(rootpath, '\n');
549 *tc = '\0';
550
551 /* Ok, making it this far means we commit */
552 message(CONSOLE, "Please stand by, changing root to `%s'.\r\n",
553 rootpath);
554
555 /* kill all other programs first */
556 message(CONSOLE, "Sending SIGTERM to all processes.\r\n");
557 kill(-1, SIGTERM);
524 sleep(2); 558 sleep(2);
525 return; 559 sync();
526 }
527 close(fd);
528 560
529 if (rootpath[0] == '\0') { 561 message(CONSOLE, "Sending SIGKILL to all processes.\r\n");
530 message(CONSOLE, "SIGHUP recived, but new root is not valid: %s\r\n", 562 kill(-1, SIGKILL);
531 rootpath);
532 sleep(2); 563 sleep(2);
564 sync();
565
566 /* ok, we don't need /proc anymore. we also assume that the signaling
567 * process left the rest of the filesystems alone for us */
568 umount("/proc");
569
570 /* Ok, now we chroot. Hopefully we only have two things mounted, the
571 * new chroot'd mount point, and the old "/" mount. s,
572 * we go ahead and unmount the old "/". This should trigger the kernel
573 * to set things up the Right Way(tm). */
574
575 if (!chroot(rootpath))
576 umount("/dev/root");
577
578 /* If the chroot fails, we are already too far to turn back, so we
579 * continue and hope that executing init below will revive the system */
580
581 /* close all of our descriptors and open new ones */
582 close(0);
583 close(1);
584 close(2);
585 open("/dev/console", O_RDWR, 0);
586 dup(0);
587 dup(0);
588
589 message(CONSOLE, "Executing real init...\r\n");
590 /* execute init in the (hopefully) new root */
591 execve("/sbin/init", argv_init, envp_init);
592
593 message(CONSOLE,
594 "ERROR: Could not exec new init. Press %s to reboot.\r\n",
595 (secondConsole == NULL) /* serial console */
596 ? "Reset" : "CTRL-ALT-DEL");
533 return; 597 return;
534 } 598}
535 599#endif /* BB_FEATURE_INIT_CHROOT */
536 tc = strrchr(rootpath, '\n');
537 *tc = '\0';
538
539 /* Ok, making it this far means we commit */
540 message(CONSOLE, "Please stand by, changing root to `%s'.\r\n", rootpath);
541
542 /* kill all other programs first */
543 message(CONSOLE, "Sending SIGTERM to all processes.\r\n");
544 kill(-1, SIGTERM);
545 sleep(2);
546 sync();
547
548 message(CONSOLE, "Sending SIGKILL to all processes.\r\n");
549 kill(-1, SIGKILL);
550 sleep(2);
551 sync();
552
553 /* ok, we don't need /proc anymore. we also assume that the signaling
554 * process left the rest of the filesystems alone for us */
555 umount("/proc");
556
557 /* Ok, now we chroot. Hopefully we only have two things mounted, the
558 * new chroot'd mount point, and the old "/" mount. s,
559 * we go ahead and unmount the old "/". This should trigger the kernel
560 * to set things up the Right Way(tm). */
561
562 if (!chroot(rootpath))
563 umount("/dev/root");
564
565 /* If the chroot fails, we are already too far to turn back, so we
566 * continue and hope that executing init below will revive the system */
567
568 /* close all of our descriptors and open new ones */
569 close(0);
570 close(1);
571 close(2);
572 open("/dev/console", O_RDWR, 0);
573 dup(0);
574 dup(0);
575
576 message(CONSOLE, "Executing real init...\r\n");
577 /* execute init in the (hopefully) new root */
578 execve("/sbin/init",argv_init,envp_init);
579
580 message(CONSOLE, "ERROR: Could not exec new init. Press %s to reboot.\r\n",
581 (secondConsole == NULL) /* serial console */
582 ? "Reset" : "CTRL-ALT-DEL");
583 return;
584}
585#endif /* BB_FEATURE_INIT_CHROOT */
586
587#endif /* ! DEBUG_INIT */
588
589void new_initAction (initActionEnum action,
590 char* process, char* cons)
591{
592 initAction* newAction;
593
594 if (*cons == '\0')
595 cons = console;
596
597 /* If BusyBox detects that a serial console is in use,
598 * then entries not refering to the console or null devices will _not_ be run.
599 * The exception to this rule is the null device.
600 */
601 if (secondConsole == NULL && strcmp(cons, console) && strcmp(cons, "/dev/null"))
602 return;
603 600
604 newAction = calloc ((size_t)(1), sizeof(initAction)); 601#endif /* ! DEBUG_INIT */
605 if (!newAction) { 602
606 message(LOG|CONSOLE,"Memory allocation failure\n"); 603void new_initAction(initActionEnum action, char *process, char *cons)
607 while (1) sleep(1); 604{
608 } 605 initAction *newAction;
609 newAction->nextPtr = initActionList; 606
610 initActionList = newAction; 607 if (*cons == '\0')
611 strncpy( newAction->process, process, 255); 608 cons = console;
612 newAction->action = action; 609
613 strncpy(newAction->console, cons, 255); 610 /* If BusyBox detects that a serial console is in use,
614 newAction->pid = 0; 611 * then entries not refering to the console or null devices will _not_ be run.
612 * The exception to this rule is the null device.
613 */
614 if (secondConsole == NULL && strcmp(cons, console)
615 && strcmp(cons, "/dev/null"))
616 return;
617
618 newAction = calloc((size_t) (1), sizeof(initAction));
619 if (!newAction) {
620 message(LOG | CONSOLE, "Memory allocation failure\n");
621 while (1)
622 sleep(1);
623 }
624 newAction->nextPtr = initActionList;
625 initActionList = newAction;
626 strncpy(newAction->process, process, 255);
627 newAction->action = action;
628 strncpy(newAction->console, cons, 255);
629 newAction->pid = 0;
615// message(LOG|CONSOLE, "process='%s' action='%d' console='%s'\n", 630// message(LOG|CONSOLE, "process='%s' action='%d' console='%s'\n",
616// newAction->process, newAction->action, newAction->console); 631// newAction->process, newAction->action, newAction->console);
617} 632}
618 633
619void delete_initAction (initAction *action) 634void delete_initAction(initAction * action)
620{ 635{
621 initAction *a, *b=NULL; 636 initAction *a, *b = NULL;
622 for( a=initActionList ; a ; b=a, a=a->nextPtr) { 637
623 if (a == action) { 638 for (a = initActionList; a; b = a, a = a->nextPtr) {
624 if (b==NULL) { 639 if (a == action) {
625 initActionList=a->nextPtr; 640 if (b == NULL) {
626 } else { 641 initActionList = a->nextPtr;
627 b->nextPtr=a->nextPtr; 642 } else {
628 } 643 b->nextPtr = a->nextPtr;
629 free( a); 644 }
630 break; 645 free(a);
646 break;
647 }
631 } 648 }
632 }
633} 649}
634 650
635/* NOTE that if BB_FEATURE_USE_INITTAB is NOT defined, 651/* NOTE that if BB_FEATURE_USE_INITTAB is NOT defined,
@@ -639,253 +655,258 @@ void delete_initAction (initAction *action)
639 * _is_ defined, but /etc/inittab is missing, this 655 * _is_ defined, but /etc/inittab is missing, this
640 * results in the same set of default behaviors. 656 * results in the same set of default behaviors.
641 * */ 657 * */
642void parse_inittab(void) 658void parse_inittab(void)
643{ 659{
644#ifdef BB_FEATURE_USE_INITTAB 660#ifdef BB_FEATURE_USE_INITTAB
645 FILE* file; 661 FILE *file;
646 char buf[256], lineAsRead[256], tmpConsole[256]; 662 char buf[256], lineAsRead[256], tmpConsole[256];
647 char *p, *q, *r, *s; 663 char *p, *q, *r, *s;
648 const struct initActionType *a = actions; 664 const struct initActionType *a = actions;
649 int foundIt; 665 int foundIt;
650 666
651 667
652 file = fopen(INITTAB, "r"); 668 file = fopen(INITTAB, "r");
653 if (file == NULL) { 669 if (file == NULL) {
654 /* No inittab file -- set up some default behavior */ 670 /* No inittab file -- set up some default behavior */
655#endif 671#endif
656 /* Askfirst shell on tty1 */ 672 /* Askfirst shell on tty1 */
657 new_initAction( ASKFIRST, SHELL, console ); 673 new_initAction(ASKFIRST, SHELL, console);
658 /* Askfirst shell on tty2 */ 674 /* Askfirst shell on tty2 */
659 if (secondConsole != NULL) 675 if (secondConsole != NULL)
660 new_initAction( ASKFIRST, SHELL, secondConsole ); 676 new_initAction(ASKFIRST, SHELL, secondConsole);
661 /* sysinit */ 677 /* sysinit */
662 new_initAction( SYSINIT, INIT_SCRIPT, console ); 678 new_initAction(SYSINIT, INIT_SCRIPT, console);
663 679
664 return; 680 return;
665#ifdef BB_FEATURE_USE_INITTAB 681#ifdef BB_FEATURE_USE_INITTAB
666 }
667
668 while ( fgets(buf, 255, file) != NULL) {
669 foundIt=FALSE;
670 for(p = buf; *p == ' ' || *p == '\t'; p++);
671 if (*p == '#' || *p == '\n') continue;
672
673 /* Trim the trailing \n */
674 q = strrchr( p, '\n');
675 if (q != NULL)
676 *q='\0';
677
678 /* Keep a copy around for posterity's sake (and error msgs) */
679 strcpy(lineAsRead, buf);
680
681 /* Grab the ID field */
682 s=p;
683 p = strchr( p, ':');
684 if ( p != NULL || *(p+1) != '\0' ) {
685 *p='\0';
686 ++p;
687 } 682 }
688 683
689 /* Now peal off the process field from the end 684 while (fgets(buf, 255, file) != NULL) {
690 * of the string */ 685 foundIt = FALSE;
691 q = strrchr( p, ':'); 686 for (p = buf; *p == ' ' || *p == '\t'; p++);
692 if ( q == NULL || *(q+1) == '\0' ) { 687 if (*p == '#' || *p == '\n')
693 message(LOG|CONSOLE,"Bad inittab entry: %s\n", lineAsRead); 688 continue;
694 continue; 689
695 } else { 690 /* Trim the trailing \n */
696 *q='\0'; 691 q = strrchr(p, '\n');
697 ++q; 692 if (q != NULL)
698 } 693 *q = '\0';
694
695 /* Keep a copy around for posterity's sake (and error msgs) */
696 strcpy(lineAsRead, buf);
697
698 /* Grab the ID field */
699 s = p;
700 p = strchr(p, ':');
701 if (p != NULL || *(p + 1) != '\0') {
702 *p = '\0';
703 ++p;
704 }
699 705
700 /* Now peal off the action field */ 706 /* Now peal off the process field from the end
701 r = strrchr( p, ':'); 707 * of the string */
702 if ( r == NULL || *(r+1) == '\0') { 708 q = strrchr(p, ':');
703 message(LOG|CONSOLE,"Bad inittab entry: %s\n", lineAsRead); 709 if (q == NULL || *(q + 1) == '\0') {
704 continue; 710 message(LOG | CONSOLE, "Bad inittab entry: %s\n", lineAsRead);
705 } else { 711 continue;
706 ++r; 712 } else {
707 } 713 *q = '\0';
714 ++q;
715 }
708 716
709 /* Ok, now process it */ 717 /* Now peal off the action field */
710 a = actions; 718 r = strrchr(p, ':');
711 while (a->name != 0) { 719 if (r == NULL || *(r + 1) == '\0') {
712 if (strcmp(a->name, r) == 0) { 720 message(LOG | CONSOLE, "Bad inittab entry: %s\n", lineAsRead);
713 if (*s != '\0') { 721 continue;
714 struct stat statBuf; 722 } else {
715 strcpy(tmpConsole, "/dev/"); 723 ++r;
716 strncat(tmpConsole, s, 200); 724 }
717 if (stat(tmpConsole, &statBuf) != 0) { 725
718 message(LOG|CONSOLE, "device '%s' does not exist. Did you read the directions?\n", tmpConsole); 726 /* Ok, now process it */
719 break; 727 a = actions;
720 } 728 while (a->name != 0) {
721 s = tmpConsole; 729 if (strcmp(a->name, r) == 0) {
730 if (*s != '\0') {
731 struct stat statBuf;
732
733 strcpy(tmpConsole, "/dev/");
734 strncat(tmpConsole, s, 200);
735 if (stat(tmpConsole, &statBuf) != 0) {
736 message(LOG | CONSOLE,
737 "device '%s' does not exist. Did you read the directions?\n",
738 tmpConsole);
739 break;
740 }
741 s = tmpConsole;
742 }
743 new_initAction(a->action, q, s);
744 foundIt = TRUE;
745 }
746 a++;
747 }
748 if (foundIt == TRUE)
749 continue;
750 else {
751 /* Choke on an unknown action */
752 message(LOG | CONSOLE, "Bad inittab entry: %s\n", lineAsRead);
722 } 753 }
723 new_initAction( a->action, q, s);
724 foundIt=TRUE;
725 }
726 a++;
727 }
728 if (foundIt==TRUE)
729 continue;
730 else {
731 /* Choke on an unknown action */
732 message(LOG|CONSOLE, "Bad inittab entry: %s\n", lineAsRead);
733 } 754 }
734 } 755 return;
735 return;
736#endif 756#endif
737} 757}
738 758
739extern int init_main(int argc, char **argv) 759extern int init_main(int argc, char **argv)
740{ 760{
741 initAction *a; 761 initAction *a;
742 pid_t wpid; 762 pid_t wpid;
743 int status; 763 int status;
744 764
745#ifndef DEBUG_INIT 765#ifndef DEBUG_INIT
746 /* Expect to be PID 1 if we are run as init (not linuxrc) */ 766 /* Expect to be PID 1 if we are run as init (not linuxrc) */
747 if (getpid() != 1 && strstr(argv[0], "init")!=NULL ) { 767 if (getpid() != 1 && strstr(argv[0], "init") != NULL) {
748 usage( "init\n\nInit is the parent of all processes.\n\n" 768 usage("init\n\nInit is the parent of all processes.\n\n"
749 "This version of init is designed to be run only by the kernel\n"); 769 "This version of init is designed to be run only by the kernel\n");
750 } 770 }
751 /* Fix up argv[0] to be certain we claim to be init */ 771 /* Fix up argv[0] to be certain we claim to be init */
752 strncpy(argv[0], "init", strlen(argv[0])); 772 strncpy(argv[0], "init", strlen(argv[0]));
753 773
754 /* Set up sig handlers -- be sure to 774 /* Set up sig handlers -- be sure to
755 * clear all of these in run() */ 775 * clear all of these in run() */
756 signal(SIGUSR1, halt_signal); 776 signal(SIGUSR1, halt_signal);
757 signal(SIGUSR2, reboot_signal); 777 signal(SIGUSR2, reboot_signal);
758 signal(SIGINT, reboot_signal); 778 signal(SIGINT, reboot_signal);
759 signal(SIGTERM, reboot_signal); 779 signal(SIGTERM, reboot_signal);
760#if defined BB_FEATURE_INIT_CHROOT 780#if defined BB_FEATURE_INIT_CHROOT
761 signal(SIGHUP, check_chroot); 781 signal(SIGHUP, check_chroot);
762#endif 782#endif
763 783
764 /* Turn off rebooting via CTL-ALT-DEL -- we get a 784 /* Turn off rebooting via CTL-ALT-DEL -- we get a
765 * SIGINT on CAD so we can shut things down gracefully... */ 785 * SIGINT on CAD so we can shut things down gracefully... */
766 reboot(RB_DISABLE_CAD); 786 reboot(RB_DISABLE_CAD);
767#endif 787#endif
768 788
769 /* Figure out where the default console should be */ 789 /* Figure out where the default console should be */
770 console_init(); 790 console_init();
771 791
772 /* Close whatever files are open, and reset the console. */ 792 /* Close whatever files are open, and reset the console. */
773 close(0); 793 close(0);
774 close(1); 794 close(1);
775 close(2); 795 close(2);
776 set_term(0); 796 set_term(0);
777 setsid(); 797 setsid();
778 798
779 /* Make sure PATH is set to something sane */ 799 /* Make sure PATH is set to something sane */
780 putenv(_PATH_STDPATH); 800 putenv(_PATH_STDPATH);
781 801
782 /* Hello world */ 802 /* Hello world */
783#ifndef DEBUG_INIT 803#ifndef DEBUG_INIT
784 message(LOG|CONSOLE, 804 message(LOG | CONSOLE,
785 "init started: BusyBox v%s (%s) multi-call binary\r\n", 805 "init started: BusyBox v%s (%s) multi-call binary\r\n",
786 BB_VER, BB_BT); 806 BB_VER, BB_BT);
787#else 807#else
788 message(LOG|CONSOLE, 808 message(LOG | CONSOLE,
789 "init(%d) started: BusyBox v%s (%s) multi-call binary\r\n", 809 "init(%d) started: BusyBox v%s (%s) multi-call binary\r\n",
790 getpid(), BB_VER, BB_BT); 810 getpid(), BB_VER, BB_BT);
791#endif 811#endif
792 812
793 813
794 /* Mount /proc */ 814 /* Mount /proc */
795 if (mount ("proc", "/proc", "proc", 0, 0) == 0) { 815 if (mount("proc", "/proc", "proc", 0, 0) == 0) {
796 message(LOG|CONSOLE, "Mounting /proc: done.\n"); 816 message(LOG | CONSOLE, "Mounting /proc: done.\n");
797 kernelVersion = get_kernel_revision(); 817 kernelVersion = get_kernel_revision();
798 } else 818 } else
799 message(LOG|CONSOLE, "Mounting /proc: failed!\n"); 819 message(LOG | CONSOLE, "Mounting /proc: failed!\n");
800 820
801 /* Make sure there is enough memory to do something useful. */ 821 /* Make sure there is enough memory to do something useful. */
802 check_memory(); 822 check_memory();
803 823
804 /* Check if we are supposed to be in single user mode */ 824 /* Check if we are supposed to be in single user mode */
805 if ( argc > 1 && (!strcmp(argv[1], "single") || 825 if (argc > 1 && (!strcmp(argv[1], "single") ||
806 !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) 826 !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) {
807 { 827 /* Ask first then start a shell on tty2 */
808 /* Ask first then start a shell on tty2 */ 828 if (secondConsole != NULL)
809 if (secondConsole != NULL) 829 new_initAction(ASKFIRST, SHELL, secondConsole);
810 new_initAction( ASKFIRST, SHELL, secondConsole); 830 /* Start a shell on tty1 */
811 /* Start a shell on tty1 */ 831 new_initAction(RESPAWN, SHELL, console);
812 new_initAction( RESPAWN, SHELL, console); 832 } else {
813 } else { 833 /* Not in single user mode -- see what inittab says */
814 /* Not in single user mode -- see what inittab says */ 834
815 835 /* NOTE that if BB_FEATURE_USE_INITTAB is NOT defined,
816 /* NOTE that if BB_FEATURE_USE_INITTAB is NOT defined, 836 * then parse_inittab() simply adds in some default
817 * then parse_inittab() simply adds in some default 837 * actions(i.e runs INIT_SCRIPT and then starts a pair
818 * actions(i.e runs INIT_SCRIPT and then starts a pair 838 * of "askfirst" shells */
819 * of "askfirst" shells */ 839 parse_inittab();
820 parse_inittab();
821 }
822
823 /* Now run everything that needs to be run */
824
825 /* First run the sysinit command */
826 for( a=initActionList ; a; a=a->nextPtr) {
827 if (a->action == SYSINIT) {
828 waitfor(a->process, a->console, FALSE);
829 /* Now remove the "sysinit" entry from the list */
830 delete_initAction( a);
831 } 840 }
832 } 841
833 /* Next run anything that wants to block */ 842 /* Now run everything that needs to be run */
834 for( a=initActionList ; a; a=a->nextPtr) { 843
835 if (a->action == WAIT) { 844 /* First run the sysinit command */
836 waitfor(a->process, a->console, FALSE); 845 for (a = initActionList; a; a = a->nextPtr) {
837 /* Now remove the "wait" entry from the list */ 846 if (a->action == SYSINIT) {
838 delete_initAction( a); 847 waitfor(a->process, a->console, FALSE);
848 /* Now remove the "sysinit" entry from the list */
849 delete_initAction(a);
850 }
839 } 851 }
840 } 852 /* Next run anything that wants to block */
841 /* Next run anything to be run only once */ 853 for (a = initActionList; a; a = a->nextPtr) {
842 for( a=initActionList ; a; a=a->nextPtr) { 854 if (a->action == WAIT) {
843 if (a->action == ONCE) { 855 waitfor(a->process, a->console, FALSE);
844 run(a->process, a->console, FALSE); 856 /* Now remove the "wait" entry from the list */
845 /* Now remove the "once" entry from the list */ 857 delete_initAction(a);
846 delete_initAction( a); 858 }
847 } 859 }
848 } 860 /* Next run anything to be run only once */
849 /* If there is nothing else to do, stop */ 861 for (a = initActionList; a; a = a->nextPtr) {
850 if (initActionList == NULL) { 862 if (a->action == ONCE) {
851 message(LOG|CONSOLE, "No more tasks for init -- sleeping forever.\n"); 863 run(a->process, a->console, FALSE);
852 while (1) sleep(1); 864 /* Now remove the "once" entry from the list */
853 } 865 delete_initAction(a);
854
855 /* Now run the looping stuff for the rest of forever */
856 while (1) {
857 for( a=initActionList ; a; a=a->nextPtr) {
858 /* Only run stuff with pid==0. If they have
859 * a pid, that means they are still running */
860 if (a->pid == 0) {
861 switch(a->action) {
862 case RESPAWN:
863 /* run the respawn stuff */
864 a->pid = run(a->process, a->console, FALSE);
865 break;
866 case ASKFIRST:
867 /* run the askfirst stuff */
868 a->pid = run(a->process, a->console, TRUE);
869 break;
870 /* silence the compiler's incessant whining */
871 default:
872 break;
873 } 866 }
874 }
875 } 867 }
876 /* Wait for a child process to exit */ 868 /* If there is nothing else to do, stop */
877 wpid = wait(&status); 869 if (initActionList == NULL) {
878 if (wpid > 0 ) { 870 message(LOG | CONSOLE,
879 /* Find out who died and clean up their corpse */ 871 "No more tasks for init -- sleeping forever.\n");
880 for( a=initActionList ; a; a=a->nextPtr) { 872 while (1)
881 if (a->pid==wpid) { 873 sleep(1);
882 a->pid=0; 874 }
883 message(LOG, "Process '%s' (pid %d) exited. Scheduling it for restart.\n", 875
884 a->process, wpid); 876 /* Now run the looping stuff for the rest of forever */
877 while (1) {
878 for (a = initActionList; a; a = a->nextPtr) {
879 /* Only run stuff with pid==0. If they have
880 * a pid, that means they are still running */
881 if (a->pid == 0) {
882 switch (a->action) {
883 case RESPAWN:
884 /* run the respawn stuff */
885 a->pid = run(a->process, a->console, FALSE);
886 break;
887 case ASKFIRST:
888 /* run the askfirst stuff */
889 a->pid = run(a->process, a->console, TRUE);
890 break;
891 /* silence the compiler's incessant whining */
892 default:
893 break;
894 }
895 }
896 }
897 /* Wait for a child process to exit */
898 wpid = wait(&status);
899 if (wpid > 0) {
900 /* Find out who died and clean up their corpse */
901 for (a = initActionList; a; a = a->nextPtr) {
902 if (a->pid == wpid) {
903 a->pid = 0;
904 message(LOG,
905 "Process '%s' (pid %d) exited. Scheduling it for restart.\n",
906 a->process, wpid);
907 }
908 }
885 } 909 }
886 } 910 sleep(1);
887 } 911 }
888 sleep(1);
889 }
890} 912}
891
diff --git a/init/poweroff.c b/init/poweroff.c
index 405ca3fe2..7f9abf14a 100644
--- a/init/poweroff.c
+++ b/init/poweroff.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini poweroff implementation for busybox 3 * Mini poweroff implementation for busybox
3 * 4 *
@@ -23,9 +24,8 @@
23#include "internal.h" 24#include "internal.h"
24#include <signal.h> 25#include <signal.h>
25 26
26extern int 27extern int poweroff_main(int argc, char **argv)
27poweroff_main(int argc, char ** argv)
28{ 28{
29 /* don't assume init's pid == 1 */ 29 /* don't assume init's pid == 1 */
30 exit( kill(findInitPid(), SIGUSR2)); 30 exit(kill(findInitPid(), SIGUSR2));
31} 31}
diff --git a/init/reboot.c b/init/reboot.c
index 1339a60f4..ef2a848ee 100644
--- a/init/reboot.c
+++ b/init/reboot.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini reboot implementation for busybox 3 * Mini reboot implementation for busybox
3 * 4 *
@@ -23,9 +24,8 @@
23#include "internal.h" 24#include "internal.h"
24#include <signal.h> 25#include <signal.h>
25 26
26extern int 27extern int reboot_main(int argc, char **argv)
27reboot_main(int argc, char ** argv)
28{ 28{
29 /* don't assume init's pid == 1 */ 29 /* don't assume init's pid == 1 */
30 exit( kill(findInitPid(), SIGINT)); 30 exit(kill(findInitPid(), SIGINT));
31} 31}