summaryrefslogtreecommitdiff
path: root/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'init.c')
-rw-r--r--init.c269
1 files changed, 151 insertions, 118 deletions
diff --git a/init.c b/init.c
index ade29c7..ca194dd 100644
--- a/init.c
+++ b/init.c
@@ -13,19 +13,21 @@
#include <sys/mount.h>
#include <sys/reboot.h>
#include <sys/kdaemon.h>
-#include <sys/swap.h>
#include <sys/sysmacros.h>
-
-const char init_usage[] = "Used internally by the system.";
-char console[16] = "";
-const char * default_console = "/dev/tty1";
-char * first_terminal = NULL;
-const char * second_terminal = "/dev/tty2";
-const char log[] = "/dev/tty3";
-char * term_ptr = NULL;
+#include <linux/serial.h> /* for serial_struct */
+#include <sys/vt.h> /* for vt_stat */
+#include <sys/ioctl.h>
+
+static const char init_usage[] = "Used internally by the system.";
+static char console[16] = "";
+static const char* default_console = "/dev/tty2";
+static char* first_terminal = NULL;
+static const char* second_terminal = "/dev/tty2";
+static const char* log = "/dev/tty3";
+static char* term_ptr = NULL;
static void
-message(const char * terminal, const char * pattern, ...)
+message(const char* terminal, const char * pattern, ...)
{
int fd;
FILE * con = 0;
@@ -36,7 +38,8 @@ message(const char * terminal, const char * pattern, ...)
* has switched consoles, the open will get the new console. If we kept
* the console open, we'd always print to the same one.
*/
- if ( ((fd = open(terminal, O_WRONLY|O_NOCTTY)) < 0)
+ if ( !terminal
+ || ((fd = open(terminal, O_WRONLY|O_NOCTTY)) < 0)
|| ((con = fdopen(fd, "w")) == NULL) )
return;
@@ -158,44 +161,59 @@ run(const char* program, const char* const* arguments,
static int
mem_total()
{
- char s[80];
- char *p;
- FILE *f;
- const char pattern[]="MemTotal:";
-
- f=fopen("/proc/meminfo","r");
- while (NULL != fgets(s,79,f)) {
- p=strstr(s, pattern);
- if (NULL != p) {
- fclose(f);
- return(atoi(p+strlen(pattern)));
+ char s[80];
+ char *p;
+ FILE *f;
+ const char pattern[]="MemTotal:";
+
+ f=fopen("/proc/meminfo","r");
+ while (NULL != fgets(s,79,f)) {
+ p=strstr(s, pattern);
+ if (NULL != p) {
+ fclose(f);
+ return(atoi(p+strlen(pattern)));
+ }
}
- }
- return -1;
+ return -1;
}
static void
set_free_pages()
{
- char s[80];
+ char s[80];
+ FILE *f;
+
+ f=fopen("/proc/sys/vm/freepages","r");
+ fgets(s,79,f);
+ if (atoi(s) < 32) {
+ fclose(f);
+ f=fopen("/proc/sys/vm/freepages","w");
+ fprintf(f,"30\t40\t50\n");
+ printf("\nIncreased /proc/sys/vm/freepages values to 30/40/50\n");
+ }
+ fclose(f);
+}
+
+static int
+get_kernel_revision()
+{
FILE *f;
+ int major=0, minor=0, patch=0;
- f=fopen("/proc/sys/vm/freepages","r");
- fgets(s,79,f);
- if (atoi(s) < 32) {
- fclose(f);
- f=fopen("/proc/sys/vm/freepages","w");
- fprintf(f,"30\t40\t50\n");
- printf("\nIncreased /proc/sys/vm/freepages values to 30/40/50\n");
- }
+ f = fopen("/proc/sys/kernel/osrelease","r");
+ fscanf(f,"%d.%d.%d",&major,&minor,&patch);
fclose(f);
+ return major*65536 + minor*256 + patch;
}
+
static void
-shutdown_system(int do_reboot)
+shutdown_system(void)
{
static const char * const umount_args[] = {"/bin/umount", "-a", "-n", 0};
+ static const char * const swapoff_args[] = {"/bin/swapoff", "-a", 0};
+ message(console, "The system is going down NOW !!");
sync();
/* Allow Ctrl-Alt-Del to reboot system. */
reboot(RB_ENABLE_CAD);
@@ -208,59 +226,72 @@ shutdown_system(int do_reboot)
message(console, "Sending SIGKILL to all processes.\r\n");
kill(-1, SIGKILL);
sleep(1);
+ waitfor(run("/bin/swapoff", swapoff_args, console, 0));
waitfor(run("/bin/umount", umount_args, console, 0));
sync();
- bdflush(1, 0);
- sync();
- reboot(do_reboot ?RB_AUTOBOOT : RB_HALT_SYSTEM);
- exit(0);
+ if (get_kernel_revision() <= 2*65536+2*256+11) {
+ /* Removed bdflush call, kupdate in kernels >2.2.11 */
+ bdflush(1, 0);
+ sync();
+ }
}
static void
halt_signal(int sig)
{
- shutdown_system(0);
+ shutdown_system();
+ message(console, "The system is halted. Press CTRL-ALT-DEL or turn off power\r\n");
+ reboot( RB_HALT_SYSTEM);
+ exit(0);
}
static void
reboot_signal(int sig)
{
- shutdown_system(1);
+ shutdown_system();
+ message(console, "Please stand by while rebooting the system.\r\n");
+ reboot( RB_AUTOBOOT);
+ exit(0);
}
static void
-exit_signal(int sig)
+configure_terminals( int serial_cons, int single_user_mode )
{
-
- /* initrd doesn't work anyway */
-
- shutdown_system(1);
-
- /* This is used on the initial ramdisk */
-
- /* message(log, "Init exiting.");
- exit(0);
- */
-}
-
-void
-configure_terminals( int serial_cons )
-{
- //struct stat statbuf;
char *tty;
+ struct serial_struct sr;
+ struct vt_stat vt;
+
switch (serial_cons) {
+ case -1:
+ /* 2.2 kernels:
+ * identify the real console backend and try to make use of it */
+ if (ioctl(0,TIOCGSERIAL,&sr) == 0) {
+ sprintf( console, "/dev/ttyS%d", sr.line );
+ serial_cons = sr.line+1;
+ }
+ else if (ioctl(0, VT_GETSTATE, &vt) == 0) {
+ sprintf( console, "/dev/tty%d", vt.v_active );
+ serial_cons = 0;
+ }
+ else {
+ /* unknown backend: fallback to /dev/console */
+ strcpy( console, "/dev/console" );
+ serial_cons = 0;
+ }
+ break;
+
case 1:
- strcpy( console, "/dev/ttyS0" );
+ strcpy( console, "/dev/cua0" );
break;
case 2:
- strcpy( console, "/dev/ttyS1" );
+ strcpy( console, "/dev/cua1" );
break;
default:
tty = ttyname(0);
if (tty) {
strcpy( console, tty );
- if (!strncmp( tty, "/dev/ttyS", 9 ))
+ if (!strncmp( tty, "/dev/cua", 8 ))
serial_cons=1;
}
else
@@ -269,24 +300,33 @@ configure_terminals( int serial_cons )
}
if (!first_terminal)
first_terminal = console;
- if (serial_cons && !strncmp(term_ptr,"TERM=linux",10))
- term_ptr = "TERM=vt100";
+#if #cpu (sparc)
+ if (serial_cons > 0 && !strncmp(term_ptr,"TERM=linux",10))
+ term_ptr = "TERM=vt100";
+#endif
+ if (serial_cons) {
+ /* disable other but the first terminal:
+ * VT is not initialized anymore on 2.2 kernel when booting from
+ * serial console, therefore modprobe is flooding the display with
+ * "can't locate module char-major-4" messages. */
+ log = 0;
+ second_terminal = 0;
+ }
}
extern int
init_main(int argc, char * * argv)
{
- static const char* const rc = "etc/rc";
+ const char * rc_arguments[100];
const char * arguments[100];
- int run_rc = 1;
+ int run_rc = TRUE;
int j;
int pid1 = 0;
int pid2 = 0;
- int create_swap= -1;
struct stat statbuf;
- const char * tty_commands[2] = { "bin/sh", "bin/sh"};
- char swap[20];
+ const char * tty_commands[3] = { "etc/init.d/rcS", "bin/sh"};
int serial_console = 0;
+ int retval;
/*
* 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)
signal(SIGUSR1, halt_signal);
signal(SIGUSR2, reboot_signal);
signal(SIGINT, reboot_signal);
- signal(SIGTERM, exit_signal);
+ signal(SIGTERM, reboot_signal);
reboot(RB_DISABLE_CAD);
@@ -307,7 +347,7 @@ init_main(int argc, char * * argv)
for ( j = 1; j < argc; j++ ) {
if ( strcmp(argv[j], "single") == 0 ) {
- run_rc = 0;
+ run_rc = FALSE;
tty_commands[0] = "bin/sh";
tty_commands[1] = 0;
}
@@ -341,7 +381,6 @@ init_main(int argc, char * * argv)
term_ptr=__environ[j];
}
}
- configure_terminals( serial_console );
printf("mounting /proc ...\n");
if (mount("/proc","/proc","proc",0,0)) {
@@ -349,81 +388,75 @@ init_main(int argc, char * * argv)
}
printf("\tdone.\n");
+ if (get_kernel_revision() >= 2*65536+1*256+71) {
+ /* if >= 2.1.71 kernel, /dev/console is not a symlink anymore:
+ * use it as primary console */
+ serial_console=-1;
+ }
+
+ /* Make sure /etc/init.d/rc exists */
+ retval= stat(tty_commands[0],&statbuf);
+ if (retval)
+ run_rc = FALSE;
+
+ configure_terminals( serial_console, run_rc);
+
set_free_pages();
/* not enough memory to do anything useful*/
if (mem_total() < 2000) {
- int retval;
- retval= stat("/etc/swappartition",&statbuf);
- if (retval) {
- printf("You do not have enough RAM, sorry.\n");
- while (1) { sleep(1);}
- } else { /* everything OK */
- FILE *f;
-
- f=fopen("/etc/swappartition","r");
- fgets(swap,19,f);
- fclose(f);
- *(strstr(swap,"\n"))='\0';
-
- if (swapon(swap,0)) {
- perror("swapon failed\n");
- } else {
- f=fopen("/etc/swaps","w");
- fprintf(f,"%s none swap rw 0 0",swap);
- fclose(f);
- create_swap = 0;
+ retval= stat("/etc/fstab",&statbuf);
+ if (retval) {
+ printf("You do not have enough RAM, sorry.\n");
+ while (1) { sleep(1);}
+ } else {
+ /* Try to turn on swap */
+ static const char * const swapon_args[] = {"/bin/swapon", "-a", 0};
+ waitfor(run("/bin/swapon", swapon_args, console, 0));
+ if (mem_total() < 2000) {
+ printf("You do not have enough RAM, sorry.\n");
+ while (1) { sleep(1);}
+ }
}
- }
}
/*
* Don't modify **argv directly, it would show up in the "ps" display.
* I don't want "init" to look like "rc".
*/
- arguments[0] = rc;
+ rc_arguments[0] = tty_commands[0];
for ( j = 1; j < argc; j++ ) {
- arguments[j] = argv[j];
- }
- arguments[j] = 0;
-
- if ( run_rc ) {
- run(rc, arguments, console, 0);
- //waitfor(run(rc, arguments, console, 0));
- }
-
- if ( 0 == create_swap) {
- if (unlink("/etc/swappartition")) {
- perror("unlinking /etc/swappartition");
- }
+ rc_arguments[j] = argv[j];
}
+ rc_arguments[j] = 0;
arguments[0] = "-sh";
arguments[1] = 0;
+
+ /* Ok, now launch the rc script /etc/init.d/rcS and prepare to start up
+ * some VTs on tty1 and tty2 if somebody hits enter
+ */
for ( ; ; ) {
int wpid;
int status;
- if ( pid1 == 0 && tty_commands[0] ) {
- /* Ask before starting a shell */
- /*
- arguments[0] = tty_commands[0];
- */
- pid1 = run(tty_commands[0], arguments, first_terminal, 1);
+ if ( pid1 == 0 && tty_commands[0] ) {
+ if ( run_rc == TRUE ) {
+ pid1 = run(tty_commands[0], rc_arguments, first_terminal, 0);
+ } else {
+ pid2 = run(tty_commands[1], arguments, first_terminal, 1);
+ }
}
- if ( pid2 == 0 && tty_commands[1] ) {
+ if ( pid2 == 0 && second_terminal && tty_commands[1] ) {
pid2 = run(tty_commands[1], arguments, second_terminal, 1);
}
wpid = wait(&status);
- if ( wpid > 0 ) {
- /* DEBUGGING */
+ if ( wpid > 0 && wpid != pid1) {
message(log, "pid %d exited, status=%x.\n", wpid, status);
}
- if ( wpid == pid1 ) {
- pid1 = 0;
- }
- if ( wpid == pid2 )
+ if ( wpid == pid2 ) {
pid2 = 0;
+ }
}
}