aboutsummaryrefslogtreecommitdiff
path: root/init/init.c
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>1999-10-19 00:27:50 +0000
committerEric Andersen <andersen@codepoet.org>1999-10-19 00:27:50 +0000
commitabc7d597cb78a0ee3e92ecaeb73f6cbb2a3412bf (patch)
treebeefd109c47f20772f26fe2aa9830fbd9be52ea2 /init/init.c
parentb0e9a709ba1ae1724d413a77f5b67b1a3e6c6cb7 (diff)
downloadbusybox-w32-abc7d597cb78a0ee3e92ecaeb73f6cbb2a3412bf.tar.gz
busybox-w32-abc7d597cb78a0ee3e92ecaeb73f6cbb2a3412bf.tar.bz2
busybox-w32-abc7d597cb78a0ee3e92ecaeb73f6cbb2a3412bf.zip
More stuff
Diffstat (limited to 'init/init.c')
-rw-r--r--init/init.c269
1 files changed, 151 insertions, 118 deletions
diff --git a/init/init.c b/init/init.c
index ade29c7c2..ca194dd35 100644
--- a/init/init.c
+++ b/init/init.c
@@ -13,19 +13,21 @@
13#include <sys/mount.h> 13#include <sys/mount.h>
14#include <sys/reboot.h> 14#include <sys/reboot.h>
15#include <sys/kdaemon.h> 15#include <sys/kdaemon.h>
16#include <sys/swap.h>
17#include <sys/sysmacros.h> 16#include <sys/sysmacros.h>
18 17#include <linux/serial.h> /* for serial_struct */
19const char init_usage[] = "Used internally by the system."; 18#include <sys/vt.h> /* for vt_stat */
20char console[16] = ""; 19#include <sys/ioctl.h>
21const char * default_console = "/dev/tty1"; 20
22char * first_terminal = NULL; 21static const char init_usage[] = "Used internally by the system.";
23const char * second_terminal = "/dev/tty2"; 22static char console[16] = "";
24const char log[] = "/dev/tty3"; 23static const char* default_console = "/dev/tty2";
25char * term_ptr = NULL; 24static char* first_terminal = NULL;
25static const char* second_terminal = "/dev/tty2";
26static const char* log = "/dev/tty3";
27static char* term_ptr = NULL;
26 28
27static void 29static void
28message(const char * terminal, const char * pattern, ...) 30message(const char* terminal, const char * pattern, ...)
29{ 31{
30 int fd; 32 int fd;
31 FILE * con = 0; 33 FILE * con = 0;
@@ -36,7 +38,8 @@ message(const char * terminal, const char * pattern, ...)
36 * has switched consoles, the open will get the new console. If we kept 38 * has switched consoles, the open will get the new console. If we kept
37 * the console open, we'd always print to the same one. 39 * the console open, we'd always print to the same one.
38 */ 40 */
39 if ( ((fd = open(terminal, O_WRONLY|O_NOCTTY)) < 0) 41 if ( !terminal
42 || ((fd = open(terminal, O_WRONLY|O_NOCTTY)) < 0)
40 || ((con = fdopen(fd, "w")) == NULL) ) 43 || ((con = fdopen(fd, "w")) == NULL) )
41 return; 44 return;
42 45
@@ -158,44 +161,59 @@ run(const char* program, const char* const* arguments,
158static int 161static int
159mem_total() 162mem_total()
160{ 163{
161 char s[80]; 164 char s[80];
162 char *p; 165 char *p;
163 FILE *f; 166 FILE *f;
164 const char pattern[]="MemTotal:"; 167 const char pattern[]="MemTotal:";
165 168
166 f=fopen("/proc/meminfo","r"); 169 f=fopen("/proc/meminfo","r");
167 while (NULL != fgets(s,79,f)) { 170 while (NULL != fgets(s,79,f)) {
168 p=strstr(s, pattern); 171 p=strstr(s, pattern);
169 if (NULL != p) { 172 if (NULL != p) {
170 fclose(f); 173 fclose(f);
171 return(atoi(p+strlen(pattern))); 174 return(atoi(p+strlen(pattern)));
175 }
172 } 176 }
173 } 177 return -1;
174 return -1;
175} 178}
176 179
177static void 180static void
178set_free_pages() 181set_free_pages()
179{ 182{
180 char s[80]; 183 char s[80];
184 FILE *f;
185
186 f=fopen("/proc/sys/vm/freepages","r");
187 fgets(s,79,f);
188 if (atoi(s) < 32) {
189 fclose(f);
190 f=fopen("/proc/sys/vm/freepages","w");
191 fprintf(f,"30\t40\t50\n");
192 printf("\nIncreased /proc/sys/vm/freepages values to 30/40/50\n");
193 }
194 fclose(f);
195}
196
197static int
198get_kernel_revision()
199{
181 FILE *f; 200 FILE *f;
201 int major=0, minor=0, patch=0;
182 202
183 f=fopen("/proc/sys/vm/freepages","r"); 203 f = fopen("/proc/sys/kernel/osrelease","r");
184 fgets(s,79,f); 204 fscanf(f,"%d.%d.%d",&major,&minor,&patch);
185 if (atoi(s) < 32) {
186 fclose(f);
187 f=fopen("/proc/sys/vm/freepages","w");
188 fprintf(f,"30\t40\t50\n");
189 printf("\nIncreased /proc/sys/vm/freepages values to 30/40/50\n");
190 }
191 fclose(f); 205 fclose(f);
206 return major*65536 + minor*256 + patch;
192} 207}
193 208
209
194static void 210static void
195shutdown_system(int do_reboot) 211shutdown_system(void)
196{ 212{
197 static const char * const umount_args[] = {"/bin/umount", "-a", "-n", 0}; 213 static const char * const umount_args[] = {"/bin/umount", "-a", "-n", 0};
214 static const char * const swapoff_args[] = {"/bin/swapoff", "-a", 0};
198 215
216 message(console, "The system is going down NOW !!");
199 sync(); 217 sync();
200 /* Allow Ctrl-Alt-Del to reboot system. */ 218 /* Allow Ctrl-Alt-Del to reboot system. */
201 reboot(RB_ENABLE_CAD); 219 reboot(RB_ENABLE_CAD);
@@ -208,59 +226,72 @@ shutdown_system(int do_reboot)
208 message(console, "Sending SIGKILL to all processes.\r\n"); 226 message(console, "Sending SIGKILL to all processes.\r\n");
209 kill(-1, SIGKILL); 227 kill(-1, SIGKILL);
210 sleep(1); 228 sleep(1);
229 waitfor(run("/bin/swapoff", swapoff_args, console, 0));
211 waitfor(run("/bin/umount", umount_args, console, 0)); 230 waitfor(run("/bin/umount", umount_args, console, 0));
212 sync(); 231 sync();
213 bdflush(1, 0); 232 if (get_kernel_revision() <= 2*65536+2*256+11) {
214 sync(); 233 /* Removed bdflush call, kupdate in kernels >2.2.11 */
215 reboot(do_reboot ?RB_AUTOBOOT : RB_HALT_SYSTEM); 234 bdflush(1, 0);
216 exit(0); 235 sync();
236 }
217} 237}
218 238
219static void 239static void
220halt_signal(int sig) 240halt_signal(int sig)
221{ 241{
222 shutdown_system(0); 242 shutdown_system();
243 message(console, "The system is halted. Press CTRL-ALT-DEL or turn off power\r\n");
244 reboot( RB_HALT_SYSTEM);
245 exit(0);
223} 246}
224 247
225static void 248static void
226reboot_signal(int sig) 249reboot_signal(int sig)
227{ 250{
228 shutdown_system(1); 251 shutdown_system();
252 message(console, "Please stand by while rebooting the system.\r\n");
253 reboot( RB_AUTOBOOT);
254 exit(0);
229} 255}
230 256
231static void 257static void
232exit_signal(int sig) 258configure_terminals( int serial_cons, int single_user_mode )
233{ 259{
234
235 /* initrd doesn't work anyway */
236
237 shutdown_system(1);
238
239 /* This is used on the initial ramdisk */
240
241 /* message(log, "Init exiting.");
242 exit(0);
243 */
244}
245
246void
247configure_terminals( int serial_cons )
248{
249 //struct stat statbuf;
250 char *tty; 260 char *tty;
261 struct serial_struct sr;
262 struct vt_stat vt;
263
251 264
252 switch (serial_cons) { 265 switch (serial_cons) {
266 case -1:
267 /* 2.2 kernels:
268 * identify the real console backend and try to make use of it */
269 if (ioctl(0,TIOCGSERIAL,&sr) == 0) {
270 sprintf( console, "/dev/ttyS%d", sr.line );
271 serial_cons = sr.line+1;
272 }
273 else if (ioctl(0, VT_GETSTATE, &vt) == 0) {
274 sprintf( console, "/dev/tty%d", vt.v_active );
275 serial_cons = 0;
276 }
277 else {
278 /* unknown backend: fallback to /dev/console */
279 strcpy( console, "/dev/console" );
280 serial_cons = 0;
281 }
282 break;
283
253 case 1: 284 case 1:
254 strcpy( console, "/dev/ttyS0" ); 285 strcpy( console, "/dev/cua0" );
255 break; 286 break;
256 case 2: 287 case 2:
257 strcpy( console, "/dev/ttyS1" ); 288 strcpy( console, "/dev/cua1" );
258 break; 289 break;
259 default: 290 default:
260 tty = ttyname(0); 291 tty = ttyname(0);
261 if (tty) { 292 if (tty) {
262 strcpy( console, tty ); 293 strcpy( console, tty );
263 if (!strncmp( tty, "/dev/ttyS", 9 )) 294 if (!strncmp( tty, "/dev/cua", 8 ))
264 serial_cons=1; 295 serial_cons=1;
265 } 296 }
266 else 297 else
@@ -269,24 +300,33 @@ configure_terminals( int serial_cons )
269 } 300 }
270 if (!first_terminal) 301 if (!first_terminal)
271 first_terminal = console; 302 first_terminal = console;
272 if (serial_cons && !strncmp(term_ptr,"TERM=linux",10)) 303#if #cpu (sparc)
273 term_ptr = "TERM=vt100"; 304 if (serial_cons > 0 && !strncmp(term_ptr,"TERM=linux",10))
305 term_ptr = "TERM=vt100";
306#endif
307 if (serial_cons) {
308 /* disable other but the first terminal:
309 * VT is not initialized anymore on 2.2 kernel when booting from
310 * serial console, therefore modprobe is flooding the display with
311 * "can't locate module char-major-4" messages. */
312 log = 0;
313 second_terminal = 0;
314 }
274} 315}
275 316
276extern int 317extern int
277init_main(int argc, char * * argv) 318init_main(int argc, char * * argv)
278{ 319{
279 static const char* const rc = "etc/rc"; 320 const char * rc_arguments[100];
280 const char * arguments[100]; 321 const char * arguments[100];
281 int run_rc = 1; 322 int run_rc = TRUE;
282 int j; 323 int j;
283 int pid1 = 0; 324 int pid1 = 0;
284 int pid2 = 0; 325 int pid2 = 0;
285 int create_swap= -1;
286 struct stat statbuf; 326 struct stat statbuf;
287 const char * tty_commands[2] = { "bin/sh", "bin/sh"}; 327 const char * tty_commands[3] = { "etc/init.d/rcS", "bin/sh"};
288 char swap[20];
289 int serial_console = 0; 328 int serial_console = 0;
329 int retval;
290 330
291 /* 331 /*
292 * If I am started as /linuxrc instead of /sbin/init, I don't have the 332 * If I am started as /linuxrc instead of /sbin/init, I don't have the
@@ -299,7 +339,7 @@ init_main(int argc, char * * argv)
299 signal(SIGUSR1, halt_signal); 339 signal(SIGUSR1, halt_signal);
300 signal(SIGUSR2, reboot_signal); 340 signal(SIGUSR2, reboot_signal);
301 signal(SIGINT, reboot_signal); 341 signal(SIGINT, reboot_signal);
302 signal(SIGTERM, exit_signal); 342 signal(SIGTERM, reboot_signal);
303 343
304 reboot(RB_DISABLE_CAD); 344 reboot(RB_DISABLE_CAD);
305 345
@@ -307,7 +347,7 @@ init_main(int argc, char * * argv)
307 347
308 for ( j = 1; j < argc; j++ ) { 348 for ( j = 1; j < argc; j++ ) {
309 if ( strcmp(argv[j], "single") == 0 ) { 349 if ( strcmp(argv[j], "single") == 0 ) {
310 run_rc = 0; 350 run_rc = FALSE;
311 tty_commands[0] = "bin/sh"; 351 tty_commands[0] = "bin/sh";
312 tty_commands[1] = 0; 352 tty_commands[1] = 0;
313 } 353 }
@@ -341,7 +381,6 @@ init_main(int argc, char * * argv)
341 term_ptr=__environ[j]; 381 term_ptr=__environ[j];
342 } 382 }
343 } 383 }
344 configure_terminals( serial_console );
345 384
346 printf("mounting /proc ...\n"); 385 printf("mounting /proc ...\n");
347 if (mount("/proc","/proc","proc",0,0)) { 386 if (mount("/proc","/proc","proc",0,0)) {
@@ -349,81 +388,75 @@ init_main(int argc, char * * argv)
349 } 388 }
350 printf("\tdone.\n"); 389 printf("\tdone.\n");
351 390
391 if (get_kernel_revision() >= 2*65536+1*256+71) {
392 /* if >= 2.1.71 kernel, /dev/console is not a symlink anymore:
393 * use it as primary console */
394 serial_console=-1;
395 }
396
397 /* Make sure /etc/init.d/rc exists */
398 retval= stat(tty_commands[0],&statbuf);
399 if (retval)
400 run_rc = FALSE;
401
402 configure_terminals( serial_console, run_rc);
403
352 set_free_pages(); 404 set_free_pages();
353 405
354 /* not enough memory to do anything useful*/ 406 /* not enough memory to do anything useful*/
355 if (mem_total() < 2000) { 407 if (mem_total() < 2000) {
356 int retval; 408 retval= stat("/etc/fstab",&statbuf);
357 retval= stat("/etc/swappartition",&statbuf); 409 if (retval) {
358 if (retval) { 410 printf("You do not have enough RAM, sorry.\n");
359 printf("You do not have enough RAM, sorry.\n"); 411 while (1) { sleep(1);}
360 while (1) { sleep(1);} 412 } else {
361 } else { /* everything OK */ 413 /* Try to turn on swap */
362 FILE *f; 414 static const char * const swapon_args[] = {"/bin/swapon", "-a", 0};
363 415 waitfor(run("/bin/swapon", swapon_args, console, 0));
364 f=fopen("/etc/swappartition","r"); 416 if (mem_total() < 2000) {
365 fgets(swap,19,f); 417 printf("You do not have enough RAM, sorry.\n");
366 fclose(f); 418 while (1) { sleep(1);}
367 *(strstr(swap,"\n"))='\0'; 419 }
368
369 if (swapon(swap,0)) {
370 perror("swapon failed\n");
371 } else {
372 f=fopen("/etc/swaps","w");
373 fprintf(f,"%s none swap rw 0 0",swap);
374 fclose(f);
375 create_swap = 0;
376 } 420 }
377 }
378 } 421 }
379 422
380 /* 423 /*
381 * Don't modify **argv directly, it would show up in the "ps" display. 424 * Don't modify **argv directly, it would show up in the "ps" display.
382 * I don't want "init" to look like "rc". 425 * I don't want "init" to look like "rc".
383 */ 426 */
384 arguments[0] = rc; 427 rc_arguments[0] = tty_commands[0];
385 for ( j = 1; j < argc; j++ ) { 428 for ( j = 1; j < argc; j++ ) {
386 arguments[j] = argv[j]; 429 rc_arguments[j] = argv[j];
387 }
388 arguments[j] = 0;
389
390 if ( run_rc ) {
391 run(rc, arguments, console, 0);
392 //waitfor(run(rc, arguments, console, 0));
393 }
394
395 if ( 0 == create_swap) {
396 if (unlink("/etc/swappartition")) {
397 perror("unlinking /etc/swappartition");
398 }
399 } 430 }
431 rc_arguments[j] = 0;
400 432
401 arguments[0] = "-sh"; 433 arguments[0] = "-sh";
402 arguments[1] = 0; 434 arguments[1] = 0;
435
436 /* Ok, now launch the rc script /etc/init.d/rcS and prepare to start up
437 * some VTs on tty1 and tty2 if somebody hits enter
438 */
403 for ( ; ; ) { 439 for ( ; ; ) {
404 int wpid; 440 int wpid;
405 int status; 441 int status;
406 442
407 if ( pid1 == 0 && tty_commands[0] ) { 443 if ( pid1 == 0 && tty_commands[0] ) {
408 /* Ask before starting a shell */ 444 if ( run_rc == TRUE ) {
409 /* 445 pid1 = run(tty_commands[0], rc_arguments, first_terminal, 0);
410 arguments[0] = tty_commands[0]; 446 } else {
411 */ 447 pid2 = run(tty_commands[1], arguments, first_terminal, 1);
412 pid1 = run(tty_commands[0], arguments, first_terminal, 1); 448 }
413 } 449 }
414 if ( pid2 == 0 && tty_commands[1] ) { 450 if ( pid2 == 0 && second_terminal && tty_commands[1] ) {
415 pid2 = run(tty_commands[1], arguments, second_terminal, 1); 451 pid2 = run(tty_commands[1], arguments, second_terminal, 1);
416 } 452 }
417 wpid = wait(&status); 453 wpid = wait(&status);
418 if ( wpid > 0 ) { 454 if ( wpid > 0 && wpid != pid1) {
419 /* DEBUGGING */
420 message(log, "pid %d exited, status=%x.\n", wpid, status); 455 message(log, "pid %d exited, status=%x.\n", wpid, status);
421 } 456 }
422 if ( wpid == pid1 ) { 457 if ( wpid == pid2 ) {
423 pid1 = 0;
424 }
425 if ( wpid == pid2 )
426 pid2 = 0; 458 pid2 = 0;
459 }
427 } 460 }
428} 461}
429 462