Stuf
This commit is contained in:
parent
d143e8f2bd
commit
0460ff2e5d
@ -4,6 +4,9 @@
|
|||||||
* Fixed mkdir -m option so that it works.
|
* Fixed mkdir -m option so that it works.
|
||||||
* kill segfaulted w/o any arguments. Now it doesn't do that.
|
* kill segfaulted w/o any arguments. Now it doesn't do that.
|
||||||
* kill wasn't properly accepting signal names. It does now.
|
* kill wasn't properly accepting signal names. It does now.
|
||||||
|
* Added new apps chvt and deallocvt
|
||||||
|
* Major adjustment of init.c. Code is now readable IMHO,
|
||||||
|
and much more solid.
|
||||||
|
|
||||||
-Erik Andersen
|
-Erik Andersen
|
||||||
|
|
||||||
|
2
Makefile
2
Makefile
@ -22,7 +22,7 @@ BUILDTIME=$(shell date "+%Y%m%d-%H%M")
|
|||||||
|
|
||||||
# Comment out the following to make a debuggable build
|
# Comment out the following to make a debuggable build
|
||||||
# Leave this off for production use.
|
# Leave this off for production use.
|
||||||
DODEBUG=false
|
DODEBUG=true
|
||||||
# If you want a static binary, turn this on. I can't think
|
# If you want a static binary, turn this on. I can't think
|
||||||
# of many situations where anybody would ever want it static,
|
# of many situations where anybody would ever want it static,
|
||||||
# but...
|
# but...
|
||||||
|
@ -51,6 +51,12 @@ static const struct Applet applets[] = {
|
|||||||
#ifdef BB_FIND //usr/bin
|
#ifdef BB_FIND //usr/bin
|
||||||
{"find", find_main},
|
{"find", find_main},
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef BB_CHVT //usr/bin
|
||||||
|
{"chvt", chvt_main},
|
||||||
|
#endif
|
||||||
|
#ifdef BB_DEALLOCVT //usr/bin
|
||||||
|
{"deallocvt", deallocvt_main},
|
||||||
|
#endif
|
||||||
#ifdef BB_FSCK_MINIX //sbin
|
#ifdef BB_FSCK_MINIX //sbin
|
||||||
{"fsck.minix", fsck_minix_main},
|
{"fsck.minix", fsck_minix_main},
|
||||||
#endif
|
#endif
|
||||||
@ -156,6 +162,9 @@ static const struct Applet applets[] = {
|
|||||||
{"true", true_main},
|
{"true", true_main},
|
||||||
{"false", false_main},
|
{"false", false_main},
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef BB_UNAME //bin
|
||||||
|
{"uname", uname_main},
|
||||||
|
#endif
|
||||||
#ifdef BB_UMOUNT //bin
|
#ifdef BB_UMOUNT //bin
|
||||||
{"umount", umount_main},
|
{"umount", umount_main},
|
||||||
#endif
|
#endif
|
||||||
|
@ -51,6 +51,12 @@ static const struct Applet applets[] = {
|
|||||||
#ifdef BB_FIND //usr/bin
|
#ifdef BB_FIND //usr/bin
|
||||||
{"find", find_main},
|
{"find", find_main},
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef BB_CHVT //usr/bin
|
||||||
|
{"chvt", chvt_main},
|
||||||
|
#endif
|
||||||
|
#ifdef BB_DEALLOCVT //usr/bin
|
||||||
|
{"deallocvt", deallocvt_main},
|
||||||
|
#endif
|
||||||
#ifdef BB_FSCK_MINIX //sbin
|
#ifdef BB_FSCK_MINIX //sbin
|
||||||
{"fsck.minix", fsck_minix_main},
|
{"fsck.minix", fsck_minix_main},
|
||||||
#endif
|
#endif
|
||||||
@ -156,6 +162,9 @@ static const struct Applet applets[] = {
|
|||||||
{"true", true_main},
|
{"true", true_main},
|
||||||
{"false", false_main},
|
{"false", false_main},
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef BB_UNAME //bin
|
||||||
|
{"uname", uname_main},
|
||||||
|
#endif
|
||||||
#ifdef BB_UMOUNT //bin
|
#ifdef BB_UMOUNT //bin
|
||||||
{"umount", umount_main},
|
{"umount", umount_main},
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
#define BB_FIND
|
#define BB_FIND
|
||||||
//#define BB_FSCK_MINIX
|
//#define BB_FSCK_MINIX
|
||||||
//#define BB_MKFS_MINIX
|
//#define BB_MKFS_MINIX
|
||||||
|
#define BB_CHVT
|
||||||
|
#define BB_DEALLOCVT
|
||||||
#define BB_GREP
|
#define BB_GREP
|
||||||
//#define BB_HALT
|
//#define BB_HALT
|
||||||
#define BB_INIT
|
#define BB_INIT
|
||||||
@ -53,6 +55,7 @@
|
|||||||
//#define BB_TRUE_FALSE // Supplied by ash
|
//#define BB_TRUE_FALSE // Supplied by ash
|
||||||
#define BB_UMOUNT
|
#define BB_UMOUNT
|
||||||
#define BB_UPDATE
|
#define BB_UPDATE
|
||||||
|
#define BB_UNAME
|
||||||
#define BB_ZCAT
|
#define BB_ZCAT
|
||||||
//#define BB_GZIP
|
//#define BB_GZIP
|
||||||
// Don't turn BB_UTILITY off. It contains support code
|
// Don't turn BB_UTILITY off. It contains support code
|
||||||
|
36
chvt.c
Normal file
36
chvt.c
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* chvt.c - aeb - 940227 - Change virtual terminal
|
||||||
|
*
|
||||||
|
* busyboxed by Erik Andersen
|
||||||
|
*/
|
||||||
|
#include "internal.h"
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <linux/vt.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
extern int getfd(void);
|
||||||
|
|
||||||
|
int
|
||||||
|
chvt_main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
int fd, num;
|
||||||
|
|
||||||
|
if ( ( argc != 2) || (**(argv+1) == '-' ) ) {
|
||||||
|
usage ("chvt </dev/ttyN>\n");
|
||||||
|
}
|
||||||
|
fd = get_console_fd("/dev/console");
|
||||||
|
num = atoi(argv[1]);
|
||||||
|
if (ioctl(fd,VT_ACTIVATE,num)) {
|
||||||
|
perror("VT_ACTIVATE");
|
||||||
|
exit(FALSE);
|
||||||
|
}
|
||||||
|
if (ioctl(fd,VT_WAITACTIVE,num)) {
|
||||||
|
perror("VT_WAITACTIVE");
|
||||||
|
exit(FALSE);
|
||||||
|
}
|
||||||
|
exit( TRUE);
|
||||||
|
}
|
||||||
|
|
36
console-tools/chvt.c
Normal file
36
console-tools/chvt.c
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* chvt.c - aeb - 940227 - Change virtual terminal
|
||||||
|
*
|
||||||
|
* busyboxed by Erik Andersen
|
||||||
|
*/
|
||||||
|
#include "internal.h"
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <linux/vt.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
extern int getfd(void);
|
||||||
|
|
||||||
|
int
|
||||||
|
chvt_main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
int fd, num;
|
||||||
|
|
||||||
|
if ( ( argc != 2) || (**(argv+1) == '-' ) ) {
|
||||||
|
usage ("chvt </dev/ttyN>\n");
|
||||||
|
}
|
||||||
|
fd = get_console_fd("/dev/console");
|
||||||
|
num = atoi(argv[1]);
|
||||||
|
if (ioctl(fd,VT_ACTIVATE,num)) {
|
||||||
|
perror("VT_ACTIVATE");
|
||||||
|
exit(FALSE);
|
||||||
|
}
|
||||||
|
if (ioctl(fd,VT_WAITACTIVE,num)) {
|
||||||
|
perror("VT_WAITACTIVE");
|
||||||
|
exit(FALSE);
|
||||||
|
}
|
||||||
|
exit( TRUE);
|
||||||
|
}
|
||||||
|
|
47
console-tools/deallocvt.c
Normal file
47
console-tools/deallocvt.c
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* disalloc.c - aeb - 940501 - Disallocate virtual terminal(s)
|
||||||
|
* Renamed deallocvt.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <linux/vt.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
extern int getfd(void);
|
||||||
|
char *progname;
|
||||||
|
|
||||||
|
int
|
||||||
|
deallocvt_main(int argc, char *argv[]) {
|
||||||
|
int fd, num, i;
|
||||||
|
|
||||||
|
if (argc < 1) /* unlikely */
|
||||||
|
exit(1);
|
||||||
|
progname = argv[0];
|
||||||
|
|
||||||
|
fd = get_console_fd("/dev/console");
|
||||||
|
|
||||||
|
if (argc == 1) {
|
||||||
|
/* deallocate all unused consoles */
|
||||||
|
if (ioctl(fd,VT_DISALLOCATE,0)) {
|
||||||
|
perror("VT_DISALLOCATE");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
num = atoi(argv[i]);
|
||||||
|
if (num == 0)
|
||||||
|
fprintf(stderr, "%s: 0: illegal VT number\n", progname);
|
||||||
|
else if (num == 1)
|
||||||
|
fprintf(stderr, "%s: VT 1 cannot be deallocated\n", progname);
|
||||||
|
else
|
||||||
|
if (ioctl(fd,VT_DISALLOCATE,num)) {
|
||||||
|
perror("VT_DISALLOCATE");
|
||||||
|
fprintf(stderr, "%s: could not deallocate console %d\n",
|
||||||
|
progname, num);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
47
deallocvt.c
Normal file
47
deallocvt.c
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* disalloc.c - aeb - 940501 - Disallocate virtual terminal(s)
|
||||||
|
* Renamed deallocvt.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <linux/vt.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
extern int getfd(void);
|
||||||
|
char *progname;
|
||||||
|
|
||||||
|
int
|
||||||
|
deallocvt_main(int argc, char *argv[]) {
|
||||||
|
int fd, num, i;
|
||||||
|
|
||||||
|
if (argc < 1) /* unlikely */
|
||||||
|
exit(1);
|
||||||
|
progname = argv[0];
|
||||||
|
|
||||||
|
fd = get_console_fd("/dev/console");
|
||||||
|
|
||||||
|
if (argc == 1) {
|
||||||
|
/* deallocate all unused consoles */
|
||||||
|
if (ioctl(fd,VT_DISALLOCATE,0)) {
|
||||||
|
perror("VT_DISALLOCATE");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
num = atoi(argv[i]);
|
||||||
|
if (num == 0)
|
||||||
|
fprintf(stderr, "%s: 0: illegal VT number\n", progname);
|
||||||
|
else if (num == 1)
|
||||||
|
fprintf(stderr, "%s: VT 1 cannot be deallocated\n", progname);
|
||||||
|
else
|
||||||
|
if (ioctl(fd,VT_DISALLOCATE,num)) {
|
||||||
|
perror("VT_DISALLOCATE");
|
||||||
|
fprintf(stderr, "%s: could not deallocate console %d\n",
|
||||||
|
progname, num);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
630
init.c
630
init.c
@ -41,144 +41,88 @@
|
|||||||
#include <sys/vt.h> /* for vt_stat */
|
#include <sys/vt.h> /* for vt_stat */
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
static const char init_usage[] = "Used internally by the system.";
|
#define DEBUG_INIT
|
||||||
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
|
#define CONSOLE "/dev/console" /* Logical system console */
|
||||||
message(const char* terminal, const char * pattern, ...)
|
#define VT_PRIMARY "/dev/tty0" /* Virtual console master */
|
||||||
|
#define VT_SECONDARY "/dev/tty1" /* Virtual console master */
|
||||||
|
#define VT_LOG "/dev/tty2" /* Virtual console master */
|
||||||
|
#define SHELL "/bin/sh" /* Default shell */
|
||||||
|
#define INITSCRIPT "/etc/init.d/rcS" /* Initscript. */
|
||||||
|
#define PATH_DEFAULT "PATH=/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin"
|
||||||
|
|
||||||
|
static int maxproclen=0;
|
||||||
|
static char* argv0;
|
||||||
|
|
||||||
|
static char* console = CONSOLE;
|
||||||
|
static char* second_terminal = "/dev/tty2";
|
||||||
|
static char* log = "/dev/tty3";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* try to open up the specified device */
|
||||||
|
int device_open(char* device, int mode)
|
||||||
{
|
{
|
||||||
int fd;
|
int m, f, fd = -1;
|
||||||
FILE * con = 0;
|
|
||||||
va_list arguments;
|
mode = m | O_NONBLOCK;
|
||||||
|
|
||||||
|
/* Retry up to 5 times */
|
||||||
|
for(f = 0; f < 5; f++)
|
||||||
|
if ((fd = open(device, m)) >= 0) break;
|
||||||
|
if (fd < 0) return fd;
|
||||||
|
/* Set original flags. */
|
||||||
|
if (m != mode)
|
||||||
|
fcntl(fd, F_SETFL, mode);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/* print a message to the specified device */
|
||||||
* Open the console device each time a message is printed. If the user
|
void message(char* device, char *fmt, ...)
|
||||||
* has switched consoles, the open will get the new console. If we kept
|
{
|
||||||
* the console open, we'd always print to the same one.
|
int fd;
|
||||||
*/
|
va_list arguments;
|
||||||
if ( !terminal
|
if ((fd = device_open(device, O_WRONLY|O_NOCTTY|O_NDELAY)) >= 0) {
|
||||||
|| ((fd = open(terminal, O_WRONLY|O_NOCTTY)) < 0)
|
va_start(arguments, fmt);
|
||||||
|| ((con = fdopen(fd, "w")) == NULL) )
|
vdprintf(fd, fmt, arguments);
|
||||||
return;
|
|
||||||
|
|
||||||
va_start(arguments, pattern);
|
|
||||||
vfprintf(con, pattern, arguments);
|
|
||||||
va_end(arguments);
|
va_end(arguments);
|
||||||
fclose(con);
|
}
|
||||||
|
close( fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
/* Set terminal settings to reasonable defaults */
|
||||||
waitfor(int pid)
|
void set_term()
|
||||||
{
|
{
|
||||||
int status;
|
int fd;
|
||||||
int wpid;
|
struct termios tty;
|
||||||
|
|
||||||
message(log, "Waiting for process %d.\n", pid);
|
|
||||||
while ( (wpid = wait(&status)) != pid ) {
|
|
||||||
if ( wpid > 0 ) {
|
|
||||||
message(
|
|
||||||
log
|
|
||||||
,"pid %d exited, status=%x.\n"
|
|
||||||
,wpid
|
|
||||||
,status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return wpid;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
if ((fd = device_open(console, O_RDWR|O_NOCTTY)) < 0) {
|
||||||
run(const char* program, const char* const* arguments,
|
message(log, "can't open %s", console);
|
||||||
const char* terminal, int get_enter)
|
return;
|
||||||
{
|
}
|
||||||
static const char control_characters[] = {
|
ioctl(fd, TCGETS, &tty);
|
||||||
'\003',
|
tty.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD;
|
||||||
'\034',
|
tty.c_cflag |= HUPCL|CLOCAL;
|
||||||
'\177',
|
|
||||||
'\025',
|
|
||||||
'\004',
|
|
||||||
'\0',
|
|
||||||
'\1',
|
|
||||||
'\0',
|
|
||||||
'\021',
|
|
||||||
'\023',
|
|
||||||
'\032',
|
|
||||||
'\0',
|
|
||||||
'\022',
|
|
||||||
'\017',
|
|
||||||
'\027',
|
|
||||||
'\026',
|
|
||||||
'\0'
|
|
||||||
};
|
|
||||||
|
|
||||||
static char * environment[] = {
|
tty.c_cc[VINTR] = 3;
|
||||||
"HOME=/",
|
tty.c_cc[VQUIT] = 28;
|
||||||
"PATH=/bin:/sbin:/usr/bin:/usr/sbin",
|
tty.c_cc[VERASE] = 127;
|
||||||
"SHELL=/bin/sh",
|
tty.c_cc[VKILL] = 24;
|
||||||
0,
|
tty.c_cc[VEOF] = 4;
|
||||||
"USER=root",
|
tty.c_cc[VTIME] = 0;
|
||||||
0
|
tty.c_cc[VMIN] = 1;
|
||||||
};
|
tty.c_cc[VSTART] = 17;
|
||||||
|
tty.c_cc[VSTOP] = 19;
|
||||||
|
tty.c_cc[VSUSP] = 26;
|
||||||
|
|
||||||
static const char press_enter[] =
|
/* Set pre and post processing */
|
||||||
"\nPlease press Enter to activate this console. ";
|
tty.c_iflag = IGNPAR|ICRNL|IXON|IXANY;
|
||||||
|
tty.c_oflag = OPOST|ONLCR;
|
||||||
|
tty.c_lflag = ISIG|ICANON|ECHO|ECHOCTL|ECHOPRT|ECHOKE;
|
||||||
|
|
||||||
int pid;
|
/* Now set the terminal line. */
|
||||||
|
ioctl(fd, TCSETS, &tty);
|
||||||
environment[3]=term_ptr;
|
close( fd);
|
||||||
|
|
||||||
pid = fork();
|
|
||||||
if ( pid == 0 ) {
|
|
||||||
struct termios t;
|
|
||||||
const char * const * arg;
|
|
||||||
|
|
||||||
close(0);
|
|
||||||
close(1);
|
|
||||||
close(2);
|
|
||||||
setsid();
|
|
||||||
|
|
||||||
open(terminal, O_RDWR);
|
|
||||||
dup(0);
|
|
||||||
dup(0);
|
|
||||||
tcsetpgrp(0, getpgrp());
|
|
||||||
|
|
||||||
tcgetattr(0, &t);
|
|
||||||
memcpy(t.c_cc, control_characters, sizeof(control_characters));
|
|
||||||
t.c_line = 0;
|
|
||||||
t.c_iflag = ICRNL|IXON|IXOFF;
|
|
||||||
t.c_oflag = OPOST|ONLCR;
|
|
||||||
t.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE|IEXTEN;
|
|
||||||
tcsetattr(0, TCSANOW, &t);
|
|
||||||
|
|
||||||
if ( get_enter ) {
|
|
||||||
/*
|
|
||||||
* Save memory by not exec-ing anything large (like a shell)
|
|
||||||
* before the user wants it. This is critical if swap is not
|
|
||||||
* enabled and the system has low memory. Generally this will
|
|
||||||
* be run on the second virtual console, and the first will
|
|
||||||
* be allowed to start a shell or whatever an init script
|
|
||||||
* specifies.
|
|
||||||
*/
|
|
||||||
char c;
|
|
||||||
write(1, press_enter, sizeof(press_enter) - 1);
|
|
||||||
read(0, &c, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
message(log, "Executing ");
|
|
||||||
arg = arguments;
|
|
||||||
while ( *arg != 0 )
|
|
||||||
message(log, "%s ", *arg++);
|
|
||||||
message(log, "\n");
|
|
||||||
|
|
||||||
execve(program, (char * *)arguments, (char * *)environment);
|
|
||||||
message(log, "%s: could not execute: %s.\r\n", program, strerror(errno));
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
return pid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -217,33 +161,168 @@ set_free_pages()
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
console_init()
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int tried_devcons = 0;
|
||||||
|
int tried_vtmaster = 0;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
if ((s = getenv("CONSOLE")) != NULL)
|
||||||
|
console = s;
|
||||||
|
else {
|
||||||
|
console = CONSOLE;
|
||||||
|
tried_devcons++;
|
||||||
|
}
|
||||||
|
while ((fd = open(console, O_RDONLY|O_NONBLOCK)) < 0) {
|
||||||
|
if (!tried_devcons) {
|
||||||
|
tried_devcons++;
|
||||||
|
console = CONSOLE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!tried_vtmaster) {
|
||||||
|
tried_vtmaster++;
|
||||||
|
console = VT_PRIMARY;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (fd < 0)
|
||||||
|
console = "/dev/null";
|
||||||
|
else
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
waitfor(int pid)
|
||||||
|
{
|
||||||
|
int status, wpid;
|
||||||
|
|
||||||
|
message(log, "Waiting for process %d.\n", pid);
|
||||||
|
while ( (wpid = wait(&status)) != pid ) {
|
||||||
|
if ( wpid > 0 )
|
||||||
|
message(log,"pid %d exited, status=%x.\n", wpid, status);
|
||||||
|
}
|
||||||
|
return wpid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
run(const char* command, char* terminal, int get_enter)
|
||||||
|
{
|
||||||
|
int f, pid;
|
||||||
|
char *args[16];
|
||||||
|
char buf[256];
|
||||||
|
char* ptr;
|
||||||
|
static const char press_enter[] =
|
||||||
|
"\nPlease press Enter to activate this console. ";
|
||||||
|
|
||||||
|
|
||||||
|
/* Make a proper command from the command string */
|
||||||
|
strcpy(buf, command);
|
||||||
|
ptr = buf;
|
||||||
|
for(f = 1; f < 15; f++) {
|
||||||
|
/* Skip white space */
|
||||||
|
while(*ptr == ' ' || *ptr == '\t') ptr++;
|
||||||
|
args[f] = ptr;
|
||||||
|
/* May be trailing space.. */
|
||||||
|
if (*ptr == 0) break;
|
||||||
|
/* Skip this `word' */
|
||||||
|
while(*ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '#')
|
||||||
|
ptr++;
|
||||||
|
/* If end-of-line, break */
|
||||||
|
if (*ptr == '#' || *ptr == 0) {
|
||||||
|
f++;
|
||||||
|
*ptr = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* End word with \0 and continue */
|
||||||
|
args[f] = NULL;
|
||||||
|
}
|
||||||
|
args[0] = args[1];
|
||||||
|
|
||||||
|
|
||||||
|
if ((pid = fork()) == 0) {
|
||||||
|
/* Clean up */
|
||||||
|
close(0);
|
||||||
|
close(1);
|
||||||
|
close(2);
|
||||||
|
setsid();
|
||||||
|
|
||||||
|
if ((f = device_open(terminal, O_RDWR|O_NOCTTY)) < 0) {
|
||||||
|
message( log, "open(%s) failed: %s", terminal, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
dup(f);
|
||||||
|
dup(f);
|
||||||
|
tcsetpgrp(0, getpgrp());
|
||||||
|
set_term();
|
||||||
|
|
||||||
|
if ( get_enter ) {
|
||||||
|
/*
|
||||||
|
* Save memory by not exec-ing anything large (like a shell)
|
||||||
|
* before the user wants it. This is critical if swap is not
|
||||||
|
* enabled and the system has low memory. Generally this will
|
||||||
|
* be run on the second virtual console, and the first will
|
||||||
|
* be allowed to start a shell or whatever an init script
|
||||||
|
* specifies.
|
||||||
|
*/
|
||||||
|
char c;
|
||||||
|
write(1, press_enter, sizeof(press_enter) - 1);
|
||||||
|
read(0, &c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Log the process name and args */
|
||||||
|
message(log, "Executing '%s'\n", command);
|
||||||
|
|
||||||
|
/* Now run it. This should take over the PID, so nothing
|
||||||
|
* further in init.c should be run by this PID. */
|
||||||
|
execvp(args[1], args + 1);
|
||||||
|
|
||||||
|
/* If shell scripts are not executed, force the issue */
|
||||||
|
if (errno == ENOEXEC) {
|
||||||
|
char buf[256];
|
||||||
|
args[1] = SHELL;
|
||||||
|
args[2] = "-c";
|
||||||
|
strcpy(buf, "exec ");
|
||||||
|
strcat(buf, command);
|
||||||
|
args[3] = buf;
|
||||||
|
args[4] = NULL;
|
||||||
|
execvp(args[1], args + 1);
|
||||||
|
}
|
||||||
|
message(log, "Could not execute '%s'\n", command, strerror(errno));
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef DEBUG_INIT
|
||||||
static void
|
static void
|
||||||
shutdown_system(void)
|
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 !!");
|
message(console, "The system is going down NOW !!");
|
||||||
sync();
|
sync();
|
||||||
/* Allow Ctrl-Alt-Del to reboot system. */
|
/* Allow Ctrl-Alt-Del to reboot system. */
|
||||||
reboot(RB_ENABLE_CAD);
|
reboot(RB_ENABLE_CAD);
|
||||||
|
|
||||||
/* Send signals to every process _except_ pid 1 */
|
/* Send signals to every process _except_ pid 1 */
|
||||||
message(console, "Sending SIGHUP to all processes.\r\n");
|
message(console, "Sending SIGHUP to all processes.\r\n");
|
||||||
kill(-1, SIGHUP);
|
kill(-1, SIGHUP);
|
||||||
sleep(2);
|
sleep(2);
|
||||||
|
sync();
|
||||||
|
message(console, "Sending SIGKILL to all processes.\r\n");
|
||||||
|
kill(-1, SIGKILL);
|
||||||
|
sleep(1);
|
||||||
|
waitfor(run("/bin/swapoff -a", console, 0));
|
||||||
|
waitfor(run("/bin/umount -a -n", console, 0));
|
||||||
|
sync();
|
||||||
|
if (get_kernel_revision() <= 2*65536+2*256+11) {
|
||||||
|
/* Removed bdflush call, kupdate in kernels >2.2.11 */
|
||||||
|
bdflush(1, 0);
|
||||||
sync();
|
sync();
|
||||||
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();
|
|
||||||
if (get_kernel_revision() <= 2*65536+2*256+11) {
|
|
||||||
/* Removed bdflush call, kupdate in kernels >2.2.11 */
|
|
||||||
bdflush(1, 0);
|
|
||||||
sync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -251,7 +330,7 @@ halt_signal(int sig)
|
|||||||
{
|
{
|
||||||
shutdown_system();
|
shutdown_system();
|
||||||
message(console, "The system is halted. Press CTRL-ALT-DEL or turn off power\r\n");
|
message(console, "The system is halted. Press CTRL-ALT-DEL or turn off power\r\n");
|
||||||
reboot( RB_HALT_SYSTEM);
|
reboot( RB_POWER_OFF);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,202 +342,136 @@ reboot_signal(int sig)
|
|||||||
reboot( RB_AUTOBOOT);
|
reboot( RB_AUTOBOOT);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
configure_terminals( int serial_cons, int single_user_mode )
|
|
||||||
{
|
|
||||||
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/cua0" );
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
strcpy( console, "/dev/cua1" );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tty = ttyname(0);
|
|
||||||
if (tty) {
|
|
||||||
strcpy( console, tty );
|
|
||||||
if (!strncmp( tty, "/dev/cua", 8 ))
|
|
||||||
serial_cons=1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* falls back to /dev/tty1 if an error occurs */
|
|
||||||
strcpy( console, default_console );
|
|
||||||
}
|
|
||||||
if (!first_terminal)
|
|
||||||
first_terminal = console;
|
|
||||||
#if defined (__sparc__)
|
|
||||||
if (serial_cons > 0 && !strncmp(term_ptr,"TERM=linux",10))
|
|
||||||
term_ptr = "TERM=vt100";
|
|
||||||
#endif
|
#endif
|
||||||
if (serial_cons) {
|
|
||||||
/* disable other but the first terminal:
|
int setproctitle(char *fmt, ...)
|
||||||
* VT is not initialized anymore on 2.2 kernel when booting from
|
{
|
||||||
* serial console, therefore modprobe is flooding the display with
|
va_list ap;
|
||||||
* "can't locate module char-major-4" messages. */
|
int len;
|
||||||
log = 0;
|
char buf[256];
|
||||||
second_terminal = 0;
|
|
||||||
}
|
buf[0] = 0;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
len = vsprintf(buf, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
memset(argv0, 0, maxproclen + 1);
|
||||||
|
strncpy(argv0, buf, maxproclen);
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
init_main(int argc, char * * argv)
|
init_main(int argc, char * * argv)
|
||||||
{
|
{
|
||||||
const char * rc_arguments[100];
|
int run_rc = TRUE;
|
||||||
const char * arguments[100];
|
int pid1 = 0;
|
||||||
int run_rc = TRUE;
|
int pid2 = 0;
|
||||||
int j;
|
struct stat statbuf;
|
||||||
int pid1 = 0;
|
const char* init_commands = SHELL "-c exec " INITSCRIPT;
|
||||||
int pid2 = 0;
|
const char* shell_commands = SHELL;
|
||||||
struct stat statbuf;
|
const char* tty0_commands = init_commands;
|
||||||
const char * tty_commands[3] = { "etc/init.d/rcS", "bin/sh"};
|
const char* tty1_commands = shell_commands;
|
||||||
int serial_console = 0;
|
const char* no_memory =
|
||||||
int retval;
|
"Sorry, your computer does not have enough memory.\n";
|
||||||
|
|
||||||
/*
|
/* For later use */
|
||||||
* If I am started as /linuxrc instead of /sbin/init, I don't have the
|
argv0 = argv[0];
|
||||||
* environment that init expects. I can't fix the signal behavior. Try
|
maxproclen = strlen(argv[0]);
|
||||||
* to divorce from the controlling terminal with setsid(). This won't work
|
setproctitle("init [boot]");
|
||||||
* if I am the process group leader.
|
|
||||||
*/
|
|
||||||
|
#ifndef DEBUG_INIT
|
||||||
|
/* Set up sig handlers */
|
||||||
|
signal(SIGUSR1, halt_signal);
|
||||||
|
signal(SIGSEGV, halt_signal);
|
||||||
|
signal(SIGPWR, halt_signal);
|
||||||
|
signal(SIGALRM, halt_signal);
|
||||||
|
signal(SIGHUP, halt_signal);
|
||||||
|
signal(SIGUSR2, reboot_signal);
|
||||||
|
signal(SIGINT, reboot_signal);
|
||||||
|
signal(SIGTERM, reboot_signal);
|
||||||
|
#endif
|
||||||
|
/* Figure out where the default console should be */
|
||||||
|
console_init();
|
||||||
|
|
||||||
|
/* Turn off rebooting via CTL-ALT-DEL -- we get a
|
||||||
|
* SIGINT on CAD so we can shut things down gracefully... */
|
||||||
|
#ifndef DEBUG_INIT
|
||||||
|
reboot(RB_DISABLE_CAD);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Close whatever files are open, and reset the console. */
|
||||||
|
close(0);
|
||||||
|
close(1);
|
||||||
|
close(2);
|
||||||
|
set_term();
|
||||||
setsid();
|
setsid();
|
||||||
|
|
||||||
signal(SIGUSR1, halt_signal);
|
/* Make sure PATH is set to something sane */
|
||||||
signal(SIGUSR2, reboot_signal);
|
if (getenv("PATH") == NULL)
|
||||||
signal(SIGINT, reboot_signal);
|
putenv(PATH_DEFAULT);
|
||||||
signal(SIGTERM, reboot_signal);
|
|
||||||
|
|
||||||
reboot(RB_DISABLE_CAD);
|
/* Hello world */
|
||||||
|
message(console, "%s started: BusyBox v%s (%s) multi-call binary",
|
||||||
|
argv[0], BB_VER, BB_BT);
|
||||||
|
message(log, "%s started: BusyBox v%s (%s) multi-call binary",
|
||||||
|
argv[0], BB_VER, BB_BT);
|
||||||
|
|
||||||
message(log, "%s: started. ", argv[0]);
|
|
||||||
|
|
||||||
for ( j = 1; j < argc; j++ ) {
|
/* Mount /proc */
|
||||||
if ( strcmp(argv[j], "single") == 0 ) {
|
message(console, "Mounting /proc: \n");
|
||||||
run_rc = FALSE;
|
|
||||||
tty_commands[0] = "bin/sh";
|
|
||||||
tty_commands[1] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for ( j = 0; __environ[j] != 0; j++ ) {
|
|
||||||
if ( strncmp(__environ[j], "tty", 3) == 0
|
|
||||||
&& __environ[j][3] >= '1'
|
|
||||||
&& __environ[j][3] <= '2'
|
|
||||||
&& __environ[j][4] == '=' ) {
|
|
||||||
const char * s = &__environ[j][5];
|
|
||||||
|
|
||||||
if ( *s == 0 || strcmp(s, "off") == 0 )
|
|
||||||
s = 0;
|
|
||||||
|
|
||||||
tty_commands[__environ[j][3] - '1'] = s;
|
|
||||||
}
|
|
||||||
/* Should catch the syntax of Sparc kernel console setting. */
|
|
||||||
/* The kernel does not recognize a serial console when getting*/
|
|
||||||
/* console=/dev/ttySX !! */
|
|
||||||
else if ( strcmp(__environ[j], "console=ttya") == 0 ) {
|
|
||||||
serial_console=1;
|
|
||||||
}
|
|
||||||
else if ( strcmp(__environ[j], "console=ttyb") == 0 ) {
|
|
||||||
serial_console=2;
|
|
||||||
}
|
|
||||||
/* standard console settings */
|
|
||||||
else if ( strncmp(__environ[j], "console=", 8) == 0 ) {
|
|
||||||
first_terminal=&(__environ[j][8]);
|
|
||||||
}
|
|
||||||
else if ( strncmp(__environ[j], "TERM=", 5) == 0) {
|
|
||||||
term_ptr=__environ[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("mounting /proc ...\n");
|
|
||||||
if (mount("/proc","/proc","proc",0,0)) {
|
if (mount("/proc","/proc","proc",0,0)) {
|
||||||
perror("mounting /proc failed\n");
|
message(log, "%s: could not mount /proc!\n", argv[0]);
|
||||||
|
message(console, "failed!\n");
|
||||||
}
|
}
|
||||||
printf("\tdone.\n");
|
message(console, "done.\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);
|
|
||||||
|
|
||||||
|
/* Make sure there is enough memory to do something useful*/
|
||||||
set_free_pages();
|
set_free_pages();
|
||||||
|
|
||||||
/* not enough memory to do anything useful*/
|
|
||||||
if (mem_total() < 2000) {
|
if (mem_total() < 2000) {
|
||||||
|
int retval;
|
||||||
retval= stat("/etc/fstab",&statbuf);
|
retval= stat("/etc/fstab",&statbuf);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
printf("You do not have enough RAM, sorry.\n");
|
message(console, "%s", no_memory);
|
||||||
while (1) { sleep(1);}
|
while (1) { sleep(1);}
|
||||||
} else {
|
} else {
|
||||||
/* Try to turn on swap */
|
/* Try to turn on swap */
|
||||||
static const char * const swapon_args[] = {"/bin/swapon", "-a", 0};
|
waitfor(run("/bin/swapon -a", console, 0));
|
||||||
waitfor(run("/bin/swapon", swapon_args, console, 0));
|
|
||||||
if (mem_total() < 2000) {
|
if (mem_total() < 2000) {
|
||||||
printf("You do not have enough RAM, sorry.\n");
|
message(console, "%s", no_memory);
|
||||||
while (1) { sleep(1);}
|
while (1) { sleep(1);}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Check if we are supposed to be in single user mode */
|
||||||
* Don't modify **argv directly, it would show up in the "ps" display.
|
if (!strcmp(argv[1], "single") || !strcmp(argv[1], "-s") || !strcmp(argv[1], "1")) {
|
||||||
* I don't want "init" to look like "rc".
|
run_rc = FALSE;
|
||||||
*/
|
tty0_commands = shell_commands;
|
||||||
rc_arguments[0] = tty_commands[0];
|
tty1_commands = 0;
|
||||||
for ( j = 1; j < argc; j++ ) {
|
setproctitle("init [S]");
|
||||||
rc_arguments[j] = argv[j];
|
} else {
|
||||||
|
setproctitle("init [1]");
|
||||||
}
|
}
|
||||||
rc_arguments[j] = 0;
|
|
||||||
|
|
||||||
arguments[0] = "-sh";
|
/* Make sure an init script exists before trying to run it */
|
||||||
arguments[1] = 0;
|
if ( run_rc == TRUE && stat( INITSCRIPT, &statbuf)) {
|
||||||
|
tty0_commands = shell_commands;
|
||||||
/* Ok, now launch the rc script /etc/init.d/rcS and prepare to start up
|
tty1_commands = shell_commands;
|
||||||
* some VTs on tty1 and tty2 if somebody hits enter
|
}
|
||||||
|
|
||||||
|
/* Ok, now launch the rc script and/or prepare to
|
||||||
|
* start up some VTs if somebody hits enter...
|
||||||
*/
|
*/
|
||||||
for ( ; ; ) {
|
for ( ; ; ) {
|
||||||
int wpid;
|
int wpid;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
if ( pid1 == 0 && tty_commands[0] ) {
|
if ( pid1 == 0 && *tty0_commands ) {
|
||||||
if ( run_rc == TRUE ) {
|
pid1 = run(tty0_commands, console, 1);
|
||||||
pid1 = run(tty_commands[0], rc_arguments, first_terminal, 0);
|
|
||||||
} else {
|
|
||||||
pid2 = run(tty_commands[1], arguments, first_terminal, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ( pid2 == 0 && second_terminal && tty_commands[1] ) {
|
if ( pid2 == 0 && *tty1_commands ) {
|
||||||
pid2 = run(tty_commands[1], arguments, second_terminal, 1);
|
pid2 = run(tty1_commands, second_terminal, 1);
|
||||||
}
|
}
|
||||||
wpid = wait(&status);
|
wpid = wait(&status);
|
||||||
if ( wpid > 0 && wpid != pid1) {
|
if ( wpid > 0 && wpid != pid1) {
|
||||||
@ -467,6 +480,7 @@ init_main(int argc, char * * argv)
|
|||||||
if ( wpid == pid2 ) {
|
if ( wpid == pid2 ) {
|
||||||
pid2 = 0;
|
pid2 = 0;
|
||||||
}
|
}
|
||||||
|
sleep(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
630
init/init.c
630
init/init.c
@ -41,144 +41,88 @@
|
|||||||
#include <sys/vt.h> /* for vt_stat */
|
#include <sys/vt.h> /* for vt_stat */
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
static const char init_usage[] = "Used internally by the system.";
|
#define DEBUG_INIT
|
||||||
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
|
#define CONSOLE "/dev/console" /* Logical system console */
|
||||||
message(const char* terminal, const char * pattern, ...)
|
#define VT_PRIMARY "/dev/tty0" /* Virtual console master */
|
||||||
|
#define VT_SECONDARY "/dev/tty1" /* Virtual console master */
|
||||||
|
#define VT_LOG "/dev/tty2" /* Virtual console master */
|
||||||
|
#define SHELL "/bin/sh" /* Default shell */
|
||||||
|
#define INITSCRIPT "/etc/init.d/rcS" /* Initscript. */
|
||||||
|
#define PATH_DEFAULT "PATH=/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin"
|
||||||
|
|
||||||
|
static int maxproclen=0;
|
||||||
|
static char* argv0;
|
||||||
|
|
||||||
|
static char* console = CONSOLE;
|
||||||
|
static char* second_terminal = "/dev/tty2";
|
||||||
|
static char* log = "/dev/tty3";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* try to open up the specified device */
|
||||||
|
int device_open(char* device, int mode)
|
||||||
{
|
{
|
||||||
int fd;
|
int m, f, fd = -1;
|
||||||
FILE * con = 0;
|
|
||||||
va_list arguments;
|
mode = m | O_NONBLOCK;
|
||||||
|
|
||||||
|
/* Retry up to 5 times */
|
||||||
|
for(f = 0; f < 5; f++)
|
||||||
|
if ((fd = open(device, m)) >= 0) break;
|
||||||
|
if (fd < 0) return fd;
|
||||||
|
/* Set original flags. */
|
||||||
|
if (m != mode)
|
||||||
|
fcntl(fd, F_SETFL, mode);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/* print a message to the specified device */
|
||||||
* Open the console device each time a message is printed. If the user
|
void message(char* device, char *fmt, ...)
|
||||||
* has switched consoles, the open will get the new console. If we kept
|
{
|
||||||
* the console open, we'd always print to the same one.
|
int fd;
|
||||||
*/
|
va_list arguments;
|
||||||
if ( !terminal
|
if ((fd = device_open(device, O_WRONLY|O_NOCTTY|O_NDELAY)) >= 0) {
|
||||||
|| ((fd = open(terminal, O_WRONLY|O_NOCTTY)) < 0)
|
va_start(arguments, fmt);
|
||||||
|| ((con = fdopen(fd, "w")) == NULL) )
|
vdprintf(fd, fmt, arguments);
|
||||||
return;
|
|
||||||
|
|
||||||
va_start(arguments, pattern);
|
|
||||||
vfprintf(con, pattern, arguments);
|
|
||||||
va_end(arguments);
|
va_end(arguments);
|
||||||
fclose(con);
|
}
|
||||||
|
close( fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
/* Set terminal settings to reasonable defaults */
|
||||||
waitfor(int pid)
|
void set_term()
|
||||||
{
|
{
|
||||||
int status;
|
int fd;
|
||||||
int wpid;
|
struct termios tty;
|
||||||
|
|
||||||
message(log, "Waiting for process %d.\n", pid);
|
|
||||||
while ( (wpid = wait(&status)) != pid ) {
|
|
||||||
if ( wpid > 0 ) {
|
|
||||||
message(
|
|
||||||
log
|
|
||||||
,"pid %d exited, status=%x.\n"
|
|
||||||
,wpid
|
|
||||||
,status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return wpid;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
if ((fd = device_open(console, O_RDWR|O_NOCTTY)) < 0) {
|
||||||
run(const char* program, const char* const* arguments,
|
message(log, "can't open %s", console);
|
||||||
const char* terminal, int get_enter)
|
return;
|
||||||
{
|
}
|
||||||
static const char control_characters[] = {
|
ioctl(fd, TCGETS, &tty);
|
||||||
'\003',
|
tty.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD;
|
||||||
'\034',
|
tty.c_cflag |= HUPCL|CLOCAL;
|
||||||
'\177',
|
|
||||||
'\025',
|
|
||||||
'\004',
|
|
||||||
'\0',
|
|
||||||
'\1',
|
|
||||||
'\0',
|
|
||||||
'\021',
|
|
||||||
'\023',
|
|
||||||
'\032',
|
|
||||||
'\0',
|
|
||||||
'\022',
|
|
||||||
'\017',
|
|
||||||
'\027',
|
|
||||||
'\026',
|
|
||||||
'\0'
|
|
||||||
};
|
|
||||||
|
|
||||||
static char * environment[] = {
|
tty.c_cc[VINTR] = 3;
|
||||||
"HOME=/",
|
tty.c_cc[VQUIT] = 28;
|
||||||
"PATH=/bin:/sbin:/usr/bin:/usr/sbin",
|
tty.c_cc[VERASE] = 127;
|
||||||
"SHELL=/bin/sh",
|
tty.c_cc[VKILL] = 24;
|
||||||
0,
|
tty.c_cc[VEOF] = 4;
|
||||||
"USER=root",
|
tty.c_cc[VTIME] = 0;
|
||||||
0
|
tty.c_cc[VMIN] = 1;
|
||||||
};
|
tty.c_cc[VSTART] = 17;
|
||||||
|
tty.c_cc[VSTOP] = 19;
|
||||||
|
tty.c_cc[VSUSP] = 26;
|
||||||
|
|
||||||
static const char press_enter[] =
|
/* Set pre and post processing */
|
||||||
"\nPlease press Enter to activate this console. ";
|
tty.c_iflag = IGNPAR|ICRNL|IXON|IXANY;
|
||||||
|
tty.c_oflag = OPOST|ONLCR;
|
||||||
|
tty.c_lflag = ISIG|ICANON|ECHO|ECHOCTL|ECHOPRT|ECHOKE;
|
||||||
|
|
||||||
int pid;
|
/* Now set the terminal line. */
|
||||||
|
ioctl(fd, TCSETS, &tty);
|
||||||
environment[3]=term_ptr;
|
close( fd);
|
||||||
|
|
||||||
pid = fork();
|
|
||||||
if ( pid == 0 ) {
|
|
||||||
struct termios t;
|
|
||||||
const char * const * arg;
|
|
||||||
|
|
||||||
close(0);
|
|
||||||
close(1);
|
|
||||||
close(2);
|
|
||||||
setsid();
|
|
||||||
|
|
||||||
open(terminal, O_RDWR);
|
|
||||||
dup(0);
|
|
||||||
dup(0);
|
|
||||||
tcsetpgrp(0, getpgrp());
|
|
||||||
|
|
||||||
tcgetattr(0, &t);
|
|
||||||
memcpy(t.c_cc, control_characters, sizeof(control_characters));
|
|
||||||
t.c_line = 0;
|
|
||||||
t.c_iflag = ICRNL|IXON|IXOFF;
|
|
||||||
t.c_oflag = OPOST|ONLCR;
|
|
||||||
t.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE|IEXTEN;
|
|
||||||
tcsetattr(0, TCSANOW, &t);
|
|
||||||
|
|
||||||
if ( get_enter ) {
|
|
||||||
/*
|
|
||||||
* Save memory by not exec-ing anything large (like a shell)
|
|
||||||
* before the user wants it. This is critical if swap is not
|
|
||||||
* enabled and the system has low memory. Generally this will
|
|
||||||
* be run on the second virtual console, and the first will
|
|
||||||
* be allowed to start a shell or whatever an init script
|
|
||||||
* specifies.
|
|
||||||
*/
|
|
||||||
char c;
|
|
||||||
write(1, press_enter, sizeof(press_enter) - 1);
|
|
||||||
read(0, &c, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
message(log, "Executing ");
|
|
||||||
arg = arguments;
|
|
||||||
while ( *arg != 0 )
|
|
||||||
message(log, "%s ", *arg++);
|
|
||||||
message(log, "\n");
|
|
||||||
|
|
||||||
execve(program, (char * *)arguments, (char * *)environment);
|
|
||||||
message(log, "%s: could not execute: %s.\r\n", program, strerror(errno));
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
return pid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -217,33 +161,168 @@ set_free_pages()
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
console_init()
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int tried_devcons = 0;
|
||||||
|
int tried_vtmaster = 0;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
if ((s = getenv("CONSOLE")) != NULL)
|
||||||
|
console = s;
|
||||||
|
else {
|
||||||
|
console = CONSOLE;
|
||||||
|
tried_devcons++;
|
||||||
|
}
|
||||||
|
while ((fd = open(console, O_RDONLY|O_NONBLOCK)) < 0) {
|
||||||
|
if (!tried_devcons) {
|
||||||
|
tried_devcons++;
|
||||||
|
console = CONSOLE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!tried_vtmaster) {
|
||||||
|
tried_vtmaster++;
|
||||||
|
console = VT_PRIMARY;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (fd < 0)
|
||||||
|
console = "/dev/null";
|
||||||
|
else
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
waitfor(int pid)
|
||||||
|
{
|
||||||
|
int status, wpid;
|
||||||
|
|
||||||
|
message(log, "Waiting for process %d.\n", pid);
|
||||||
|
while ( (wpid = wait(&status)) != pid ) {
|
||||||
|
if ( wpid > 0 )
|
||||||
|
message(log,"pid %d exited, status=%x.\n", wpid, status);
|
||||||
|
}
|
||||||
|
return wpid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
run(const char* command, char* terminal, int get_enter)
|
||||||
|
{
|
||||||
|
int f, pid;
|
||||||
|
char *args[16];
|
||||||
|
char buf[256];
|
||||||
|
char* ptr;
|
||||||
|
static const char press_enter[] =
|
||||||
|
"\nPlease press Enter to activate this console. ";
|
||||||
|
|
||||||
|
|
||||||
|
/* Make a proper command from the command string */
|
||||||
|
strcpy(buf, command);
|
||||||
|
ptr = buf;
|
||||||
|
for(f = 1; f < 15; f++) {
|
||||||
|
/* Skip white space */
|
||||||
|
while(*ptr == ' ' || *ptr == '\t') ptr++;
|
||||||
|
args[f] = ptr;
|
||||||
|
/* May be trailing space.. */
|
||||||
|
if (*ptr == 0) break;
|
||||||
|
/* Skip this `word' */
|
||||||
|
while(*ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '#')
|
||||||
|
ptr++;
|
||||||
|
/* If end-of-line, break */
|
||||||
|
if (*ptr == '#' || *ptr == 0) {
|
||||||
|
f++;
|
||||||
|
*ptr = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* End word with \0 and continue */
|
||||||
|
args[f] = NULL;
|
||||||
|
}
|
||||||
|
args[0] = args[1];
|
||||||
|
|
||||||
|
|
||||||
|
if ((pid = fork()) == 0) {
|
||||||
|
/* Clean up */
|
||||||
|
close(0);
|
||||||
|
close(1);
|
||||||
|
close(2);
|
||||||
|
setsid();
|
||||||
|
|
||||||
|
if ((f = device_open(terminal, O_RDWR|O_NOCTTY)) < 0) {
|
||||||
|
message( log, "open(%s) failed: %s", terminal, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
dup(f);
|
||||||
|
dup(f);
|
||||||
|
tcsetpgrp(0, getpgrp());
|
||||||
|
set_term();
|
||||||
|
|
||||||
|
if ( get_enter ) {
|
||||||
|
/*
|
||||||
|
* Save memory by not exec-ing anything large (like a shell)
|
||||||
|
* before the user wants it. This is critical if swap is not
|
||||||
|
* enabled and the system has low memory. Generally this will
|
||||||
|
* be run on the second virtual console, and the first will
|
||||||
|
* be allowed to start a shell or whatever an init script
|
||||||
|
* specifies.
|
||||||
|
*/
|
||||||
|
char c;
|
||||||
|
write(1, press_enter, sizeof(press_enter) - 1);
|
||||||
|
read(0, &c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Log the process name and args */
|
||||||
|
message(log, "Executing '%s'\n", command);
|
||||||
|
|
||||||
|
/* Now run it. This should take over the PID, so nothing
|
||||||
|
* further in init.c should be run by this PID. */
|
||||||
|
execvp(args[1], args + 1);
|
||||||
|
|
||||||
|
/* If shell scripts are not executed, force the issue */
|
||||||
|
if (errno == ENOEXEC) {
|
||||||
|
char buf[256];
|
||||||
|
args[1] = SHELL;
|
||||||
|
args[2] = "-c";
|
||||||
|
strcpy(buf, "exec ");
|
||||||
|
strcat(buf, command);
|
||||||
|
args[3] = buf;
|
||||||
|
args[4] = NULL;
|
||||||
|
execvp(args[1], args + 1);
|
||||||
|
}
|
||||||
|
message(log, "Could not execute '%s'\n", command, strerror(errno));
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef DEBUG_INIT
|
||||||
static void
|
static void
|
||||||
shutdown_system(void)
|
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 !!");
|
message(console, "The system is going down NOW !!");
|
||||||
sync();
|
sync();
|
||||||
/* Allow Ctrl-Alt-Del to reboot system. */
|
/* Allow Ctrl-Alt-Del to reboot system. */
|
||||||
reboot(RB_ENABLE_CAD);
|
reboot(RB_ENABLE_CAD);
|
||||||
|
|
||||||
/* Send signals to every process _except_ pid 1 */
|
/* Send signals to every process _except_ pid 1 */
|
||||||
message(console, "Sending SIGHUP to all processes.\r\n");
|
message(console, "Sending SIGHUP to all processes.\r\n");
|
||||||
kill(-1, SIGHUP);
|
kill(-1, SIGHUP);
|
||||||
sleep(2);
|
sleep(2);
|
||||||
|
sync();
|
||||||
|
message(console, "Sending SIGKILL to all processes.\r\n");
|
||||||
|
kill(-1, SIGKILL);
|
||||||
|
sleep(1);
|
||||||
|
waitfor(run("/bin/swapoff -a", console, 0));
|
||||||
|
waitfor(run("/bin/umount -a -n", console, 0));
|
||||||
|
sync();
|
||||||
|
if (get_kernel_revision() <= 2*65536+2*256+11) {
|
||||||
|
/* Removed bdflush call, kupdate in kernels >2.2.11 */
|
||||||
|
bdflush(1, 0);
|
||||||
sync();
|
sync();
|
||||||
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();
|
|
||||||
if (get_kernel_revision() <= 2*65536+2*256+11) {
|
|
||||||
/* Removed bdflush call, kupdate in kernels >2.2.11 */
|
|
||||||
bdflush(1, 0);
|
|
||||||
sync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -251,7 +330,7 @@ halt_signal(int sig)
|
|||||||
{
|
{
|
||||||
shutdown_system();
|
shutdown_system();
|
||||||
message(console, "The system is halted. Press CTRL-ALT-DEL or turn off power\r\n");
|
message(console, "The system is halted. Press CTRL-ALT-DEL or turn off power\r\n");
|
||||||
reboot( RB_HALT_SYSTEM);
|
reboot( RB_POWER_OFF);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,202 +342,136 @@ reboot_signal(int sig)
|
|||||||
reboot( RB_AUTOBOOT);
|
reboot( RB_AUTOBOOT);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
configure_terminals( int serial_cons, int single_user_mode )
|
|
||||||
{
|
|
||||||
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/cua0" );
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
strcpy( console, "/dev/cua1" );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tty = ttyname(0);
|
|
||||||
if (tty) {
|
|
||||||
strcpy( console, tty );
|
|
||||||
if (!strncmp( tty, "/dev/cua", 8 ))
|
|
||||||
serial_cons=1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* falls back to /dev/tty1 if an error occurs */
|
|
||||||
strcpy( console, default_console );
|
|
||||||
}
|
|
||||||
if (!first_terminal)
|
|
||||||
first_terminal = console;
|
|
||||||
#if defined (__sparc__)
|
|
||||||
if (serial_cons > 0 && !strncmp(term_ptr,"TERM=linux",10))
|
|
||||||
term_ptr = "TERM=vt100";
|
|
||||||
#endif
|
#endif
|
||||||
if (serial_cons) {
|
|
||||||
/* disable other but the first terminal:
|
int setproctitle(char *fmt, ...)
|
||||||
* VT is not initialized anymore on 2.2 kernel when booting from
|
{
|
||||||
* serial console, therefore modprobe is flooding the display with
|
va_list ap;
|
||||||
* "can't locate module char-major-4" messages. */
|
int len;
|
||||||
log = 0;
|
char buf[256];
|
||||||
second_terminal = 0;
|
|
||||||
}
|
buf[0] = 0;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
len = vsprintf(buf, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
memset(argv0, 0, maxproclen + 1);
|
||||||
|
strncpy(argv0, buf, maxproclen);
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
init_main(int argc, char * * argv)
|
init_main(int argc, char * * argv)
|
||||||
{
|
{
|
||||||
const char * rc_arguments[100];
|
int run_rc = TRUE;
|
||||||
const char * arguments[100];
|
int pid1 = 0;
|
||||||
int run_rc = TRUE;
|
int pid2 = 0;
|
||||||
int j;
|
struct stat statbuf;
|
||||||
int pid1 = 0;
|
const char* init_commands = SHELL "-c exec " INITSCRIPT;
|
||||||
int pid2 = 0;
|
const char* shell_commands = SHELL;
|
||||||
struct stat statbuf;
|
const char* tty0_commands = init_commands;
|
||||||
const char * tty_commands[3] = { "etc/init.d/rcS", "bin/sh"};
|
const char* tty1_commands = shell_commands;
|
||||||
int serial_console = 0;
|
const char* no_memory =
|
||||||
int retval;
|
"Sorry, your computer does not have enough memory.\n";
|
||||||
|
|
||||||
/*
|
/* For later use */
|
||||||
* If I am started as /linuxrc instead of /sbin/init, I don't have the
|
argv0 = argv[0];
|
||||||
* environment that init expects. I can't fix the signal behavior. Try
|
maxproclen = strlen(argv[0]);
|
||||||
* to divorce from the controlling terminal with setsid(). This won't work
|
setproctitle("init [boot]");
|
||||||
* if I am the process group leader.
|
|
||||||
*/
|
|
||||||
|
#ifndef DEBUG_INIT
|
||||||
|
/* Set up sig handlers */
|
||||||
|
signal(SIGUSR1, halt_signal);
|
||||||
|
signal(SIGSEGV, halt_signal);
|
||||||
|
signal(SIGPWR, halt_signal);
|
||||||
|
signal(SIGALRM, halt_signal);
|
||||||
|
signal(SIGHUP, halt_signal);
|
||||||
|
signal(SIGUSR2, reboot_signal);
|
||||||
|
signal(SIGINT, reboot_signal);
|
||||||
|
signal(SIGTERM, reboot_signal);
|
||||||
|
#endif
|
||||||
|
/* Figure out where the default console should be */
|
||||||
|
console_init();
|
||||||
|
|
||||||
|
/* Turn off rebooting via CTL-ALT-DEL -- we get a
|
||||||
|
* SIGINT on CAD so we can shut things down gracefully... */
|
||||||
|
#ifndef DEBUG_INIT
|
||||||
|
reboot(RB_DISABLE_CAD);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Close whatever files are open, and reset the console. */
|
||||||
|
close(0);
|
||||||
|
close(1);
|
||||||
|
close(2);
|
||||||
|
set_term();
|
||||||
setsid();
|
setsid();
|
||||||
|
|
||||||
signal(SIGUSR1, halt_signal);
|
/* Make sure PATH is set to something sane */
|
||||||
signal(SIGUSR2, reboot_signal);
|
if (getenv("PATH") == NULL)
|
||||||
signal(SIGINT, reboot_signal);
|
putenv(PATH_DEFAULT);
|
||||||
signal(SIGTERM, reboot_signal);
|
|
||||||
|
|
||||||
reboot(RB_DISABLE_CAD);
|
/* Hello world */
|
||||||
|
message(console, "%s started: BusyBox v%s (%s) multi-call binary",
|
||||||
|
argv[0], BB_VER, BB_BT);
|
||||||
|
message(log, "%s started: BusyBox v%s (%s) multi-call binary",
|
||||||
|
argv[0], BB_VER, BB_BT);
|
||||||
|
|
||||||
message(log, "%s: started. ", argv[0]);
|
|
||||||
|
|
||||||
for ( j = 1; j < argc; j++ ) {
|
/* Mount /proc */
|
||||||
if ( strcmp(argv[j], "single") == 0 ) {
|
message(console, "Mounting /proc: \n");
|
||||||
run_rc = FALSE;
|
|
||||||
tty_commands[0] = "bin/sh";
|
|
||||||
tty_commands[1] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for ( j = 0; __environ[j] != 0; j++ ) {
|
|
||||||
if ( strncmp(__environ[j], "tty", 3) == 0
|
|
||||||
&& __environ[j][3] >= '1'
|
|
||||||
&& __environ[j][3] <= '2'
|
|
||||||
&& __environ[j][4] == '=' ) {
|
|
||||||
const char * s = &__environ[j][5];
|
|
||||||
|
|
||||||
if ( *s == 0 || strcmp(s, "off") == 0 )
|
|
||||||
s = 0;
|
|
||||||
|
|
||||||
tty_commands[__environ[j][3] - '1'] = s;
|
|
||||||
}
|
|
||||||
/* Should catch the syntax of Sparc kernel console setting. */
|
|
||||||
/* The kernel does not recognize a serial console when getting*/
|
|
||||||
/* console=/dev/ttySX !! */
|
|
||||||
else if ( strcmp(__environ[j], "console=ttya") == 0 ) {
|
|
||||||
serial_console=1;
|
|
||||||
}
|
|
||||||
else if ( strcmp(__environ[j], "console=ttyb") == 0 ) {
|
|
||||||
serial_console=2;
|
|
||||||
}
|
|
||||||
/* standard console settings */
|
|
||||||
else if ( strncmp(__environ[j], "console=", 8) == 0 ) {
|
|
||||||
first_terminal=&(__environ[j][8]);
|
|
||||||
}
|
|
||||||
else if ( strncmp(__environ[j], "TERM=", 5) == 0) {
|
|
||||||
term_ptr=__environ[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("mounting /proc ...\n");
|
|
||||||
if (mount("/proc","/proc","proc",0,0)) {
|
if (mount("/proc","/proc","proc",0,0)) {
|
||||||
perror("mounting /proc failed\n");
|
message(log, "%s: could not mount /proc!\n", argv[0]);
|
||||||
|
message(console, "failed!\n");
|
||||||
}
|
}
|
||||||
printf("\tdone.\n");
|
message(console, "done.\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);
|
|
||||||
|
|
||||||
|
/* Make sure there is enough memory to do something useful*/
|
||||||
set_free_pages();
|
set_free_pages();
|
||||||
|
|
||||||
/* not enough memory to do anything useful*/
|
|
||||||
if (mem_total() < 2000) {
|
if (mem_total() < 2000) {
|
||||||
|
int retval;
|
||||||
retval= stat("/etc/fstab",&statbuf);
|
retval= stat("/etc/fstab",&statbuf);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
printf("You do not have enough RAM, sorry.\n");
|
message(console, "%s", no_memory);
|
||||||
while (1) { sleep(1);}
|
while (1) { sleep(1);}
|
||||||
} else {
|
} else {
|
||||||
/* Try to turn on swap */
|
/* Try to turn on swap */
|
||||||
static const char * const swapon_args[] = {"/bin/swapon", "-a", 0};
|
waitfor(run("/bin/swapon -a", console, 0));
|
||||||
waitfor(run("/bin/swapon", swapon_args, console, 0));
|
|
||||||
if (mem_total() < 2000) {
|
if (mem_total() < 2000) {
|
||||||
printf("You do not have enough RAM, sorry.\n");
|
message(console, "%s", no_memory);
|
||||||
while (1) { sleep(1);}
|
while (1) { sleep(1);}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Check if we are supposed to be in single user mode */
|
||||||
* Don't modify **argv directly, it would show up in the "ps" display.
|
if (!strcmp(argv[1], "single") || !strcmp(argv[1], "-s") || !strcmp(argv[1], "1")) {
|
||||||
* I don't want "init" to look like "rc".
|
run_rc = FALSE;
|
||||||
*/
|
tty0_commands = shell_commands;
|
||||||
rc_arguments[0] = tty_commands[0];
|
tty1_commands = 0;
|
||||||
for ( j = 1; j < argc; j++ ) {
|
setproctitle("init [S]");
|
||||||
rc_arguments[j] = argv[j];
|
} else {
|
||||||
|
setproctitle("init [1]");
|
||||||
}
|
}
|
||||||
rc_arguments[j] = 0;
|
|
||||||
|
|
||||||
arguments[0] = "-sh";
|
/* Make sure an init script exists before trying to run it */
|
||||||
arguments[1] = 0;
|
if ( run_rc == TRUE && stat( INITSCRIPT, &statbuf)) {
|
||||||
|
tty0_commands = shell_commands;
|
||||||
/* Ok, now launch the rc script /etc/init.d/rcS and prepare to start up
|
tty1_commands = shell_commands;
|
||||||
* some VTs on tty1 and tty2 if somebody hits enter
|
}
|
||||||
|
|
||||||
|
/* Ok, now launch the rc script and/or prepare to
|
||||||
|
* start up some VTs if somebody hits enter...
|
||||||
*/
|
*/
|
||||||
for ( ; ; ) {
|
for ( ; ; ) {
|
||||||
int wpid;
|
int wpid;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
if ( pid1 == 0 && tty_commands[0] ) {
|
if ( pid1 == 0 && *tty0_commands ) {
|
||||||
if ( run_rc == TRUE ) {
|
pid1 = run(tty0_commands, console, 1);
|
||||||
pid1 = run(tty_commands[0], rc_arguments, first_terminal, 0);
|
|
||||||
} else {
|
|
||||||
pid2 = run(tty_commands[1], arguments, first_terminal, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ( pid2 == 0 && second_terminal && tty_commands[1] ) {
|
if ( pid2 == 0 && *tty1_commands ) {
|
||||||
pid2 = run(tty_commands[1], arguments, second_terminal, 1);
|
pid2 = run(tty1_commands, second_terminal, 1);
|
||||||
}
|
}
|
||||||
wpid = wait(&status);
|
wpid = wait(&status);
|
||||||
if ( wpid > 0 && wpid != pid1) {
|
if ( wpid > 0 && wpid != pid1) {
|
||||||
@ -467,6 +480,7 @@ init_main(int argc, char * * argv)
|
|||||||
if ( wpid == pid2 ) {
|
if ( wpid == pid2 ) {
|
||||||
pid2 = 0;
|
pid2 = 0;
|
||||||
}
|
}
|
||||||
|
sleep(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +82,8 @@ extern int loadfont_main(int argc, char** argv);
|
|||||||
extern int loadkmap_main(int argc, char** argv);
|
extern int loadkmap_main(int argc, char** argv);
|
||||||
extern int losetup_main(int argc, char** argv);
|
extern int losetup_main(int argc, char** argv);
|
||||||
extern int ls_main(int argc, char** argv);
|
extern int ls_main(int argc, char** argv);
|
||||||
|
extern int chvt_main(int argc, char** argv);
|
||||||
|
extern int deallocvt_main(int argc, char** argv);
|
||||||
extern int makedevs_main(int argc, char** argv);
|
extern int makedevs_main(int argc, char** argv);
|
||||||
extern int math_main(int argc, char** argv);
|
extern int math_main(int argc, char** argv);
|
||||||
extern int mkdir_main(int argc, char** argv);
|
extern int mkdir_main(int argc, char** argv);
|
||||||
@ -110,6 +112,7 @@ extern int true_main(int argc, char** argv);
|
|||||||
extern int tryopen_main(int argc, char** argv);
|
extern int tryopen_main(int argc, char** argv);
|
||||||
extern int umount_main(int argc, char** argv);
|
extern int umount_main(int argc, char** argv);
|
||||||
extern int update_main(int argc, char** argv);
|
extern int update_main(int argc, char** argv);
|
||||||
|
extern int uname_main(int argc, char** argv);
|
||||||
extern int zcat_main(int argc, char** argv);
|
extern int zcat_main(int argc, char** argv);
|
||||||
extern int gzip_main(int argc, char** argv);
|
extern int gzip_main(int argc, char** argv);
|
||||||
|
|
||||||
@ -141,7 +144,7 @@ extern gid_t my_getgrnam(char *name);
|
|||||||
extern void my_getpwuid(char* name, uid_t uid);
|
extern void my_getpwuid(char* name, uid_t uid);
|
||||||
extern void my_getgrgid(char* group, gid_t gid);
|
extern void my_getgrgid(char* group, gid_t gid);
|
||||||
extern int get_kernel_revision();
|
extern int get_kernel_revision();
|
||||||
|
extern int get_console_fd(char* tty_name);
|
||||||
|
|
||||||
|
|
||||||
#if defined (BB_FSCK_MINIX) || defined (BB_MKFS_MINIX)
|
#if defined (BB_FSCK_MINIX) || defined (BB_MKFS_MINIX)
|
||||||
|
92
utility.c
92
utility.c
@ -720,5 +720,97 @@ extern int find_match(char *haystack, char *needle, int ignoreCase)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if (defined BB_CHVT) || (defined BB_DEALLOCVT)
|
||||||
|
|
||||||
|
|
||||||
|
#include <linux/kd.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
int is_a_console(int fd)
|
||||||
|
{
|
||||||
|
char arg;
|
||||||
|
|
||||||
|
arg = 0;
|
||||||
|
return (ioctl(fd, KDGKBTYPE, &arg) == 0
|
||||||
|
&& ((arg == KB_101) || (arg == KB_84)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int open_a_console(char *fnam)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
/* try read-only */
|
||||||
|
fd = open(fnam, O_RDWR);
|
||||||
|
|
||||||
|
/* if failed, try read-only */
|
||||||
|
if (fd < 0 && errno == EACCES)
|
||||||
|
fd = open(fnam, O_RDONLY);
|
||||||
|
|
||||||
|
/* if failed, try write-only */
|
||||||
|
if (fd < 0 && errno == EACCES)
|
||||||
|
fd = open(fnam, O_WRONLY);
|
||||||
|
|
||||||
|
/* if failed, fail */
|
||||||
|
if (fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* if not a console, fail */
|
||||||
|
if (! is_a_console(fd))
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get an fd for use with kbd/console ioctls.
|
||||||
|
* We try several things because opening /dev/console will fail
|
||||||
|
* if someone else used X (which does a chown on /dev/console).
|
||||||
|
*
|
||||||
|
* if tty_name is non-NULL, try this one instead.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int get_console_fd(char* tty_name)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (tty_name)
|
||||||
|
{
|
||||||
|
if (-1 == (fd = open_a_console(tty_name)))
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = open_a_console("/dev/tty");
|
||||||
|
if (fd >= 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
fd = open_a_console("/dev/tty0");
|
||||||
|
if (fd >= 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
fd = open_a_console("/dev/console");
|
||||||
|
if (fd >= 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
for (fd = 0; fd < 3; fd++)
|
||||||
|
if (is_a_console(fd))
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"Couldnt get a file descriptor referring to the console\n");
|
||||||
|
return -1; /* total failure */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* END CODE */
|
/* END CODE */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user