diff options
Diffstat (limited to 'init.c')
| -rw-r--r-- | init.c | 406 |
1 files changed, 194 insertions, 212 deletions
| @@ -37,40 +37,39 @@ | |||
| 37 | #include <sys/reboot.h> | 37 | #include <sys/reboot.h> |
| 38 | #include <sys/kdaemon.h> | 38 | #include <sys/kdaemon.h> |
| 39 | #include <sys/sysmacros.h> | 39 | #include <sys/sysmacros.h> |
| 40 | #include <linux/serial.h> /* for serial_struct */ | 40 | #include <linux/serial.h> /* for serial_struct */ |
| 41 | #include <sys/vt.h> /* for vt_stat */ | 41 | #include <sys/vt.h> /* for vt_stat */ |
| 42 | #include <sys/ioctl.h> | 42 | #include <sys/ioctl.h> |
| 43 | 43 | ||
| 44 | #define DEBUG_INIT | 44 | #define DEBUG_INIT |
| 45 | 45 | ||
| 46 | #define CONSOLE "/dev/console" /* Logical system console */ | 46 | #define CONSOLE "/dev/console" /* Logical system console */ |
| 47 | #define VT_PRIMARY "/dev/tty0" /* Virtual console master */ | 47 | #define VT_PRIMARY "/dev/tty0" /* Virtual console master */ |
| 48 | #define VT_SECONDARY "/dev/tty1" /* Virtual console master */ | 48 | #define VT_SECONDARY "/dev/tty1" /* Virtual console master */ |
| 49 | #define VT_LOG "/dev/tty2" /* Virtual console master */ | 49 | #define VT_LOG "/dev/tty2" /* Virtual console master */ |
| 50 | #define SHELL "/bin/sh" /* Default shell */ | 50 | #define SHELL "/bin/sh" /* Default shell */ |
| 51 | #define INITSCRIPT "/etc/init.d/rcS" /* Initscript. */ | 51 | #define INITSCRIPT "/etc/init.d/rcS" /* Initscript. */ |
| 52 | #define PATH_DEFAULT "PATH=/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin" | 52 | #define PATH_DEFAULT "PATH=/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin" |
| 53 | 53 | ||
| 54 | static int maxproclen=0; | 54 | static char *console = CONSOLE; |
| 55 | static char* argv0; | 55 | static char *second_terminal = "/dev/tty2"; |
| 56 | 56 | static char *log = "/dev/tty3"; | |
| 57 | static char* console = CONSOLE; | ||
| 58 | static char* second_terminal = "/dev/tty2"; | ||
| 59 | static char* log = "/dev/tty3"; | ||
| 60 | 57 | ||
| 61 | 58 | ||
| 62 | 59 | ||
| 63 | /* try to open up the specified device */ | 60 | /* try to open up the specified device */ |
| 64 | int device_open(char* device, int mode) | 61 | int device_open(char *device, int mode) |
| 65 | { | 62 | { |
| 66 | int m, f, fd = -1; | 63 | int m, f, fd = -1; |
| 67 | 64 | ||
| 68 | mode = m | O_NONBLOCK; | 65 | mode = m | O_NONBLOCK; |
| 69 | 66 | ||
| 70 | /* Retry up to 5 times */ | 67 | /* Retry up to 5 times */ |
| 71 | for(f = 0; f < 5; f++) | 68 | for (f = 0; f < 5; f++) |
| 72 | if ((fd = open(device, m)) >= 0) break; | 69 | if ((fd = open(device, m)) >= 0) |
| 73 | if (fd < 0) return fd; | 70 | break; |
| 71 | if (fd < 0) | ||
| 72 | return fd; | ||
| 74 | /* Set original flags. */ | 73 | /* Set original flags. */ |
| 75 | if (m != mode) | 74 | if (m != mode) |
| 76 | fcntl(fd, F_SETFL, mode); | 75 | fcntl(fd, F_SETFL, mode); |
| @@ -78,16 +77,18 @@ int device_open(char* device, int mode) | |||
| 78 | } | 77 | } |
| 79 | 78 | ||
| 80 | /* print a message to the specified device */ | 79 | /* print a message to the specified device */ |
| 81 | void message(char* device, char *fmt, ...) | 80 | void message(char *device, char *fmt, ...) |
| 82 | { | 81 | { |
| 83 | int fd; | 82 | int fd; |
| 84 | va_list arguments; | 83 | va_list arguments; |
| 85 | if ((fd = device_open(device, O_WRONLY|O_NOCTTY|O_NDELAY)) >= 0) { | 84 | |
| 85 | if ((fd = device_open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) { | ||
| 86 | va_start(arguments, fmt); | 86 | va_start(arguments, fmt); |
| 87 | vdprintf(fd, fmt, arguments); | 87 | vdprintf(fd, fmt, arguments); |
| 88 | va_end(arguments); | 88 | va_end(arguments); |
| 89 | } | 89 | close(fd); |
| 90 | close( fd); | 90 | } else |
| 91 | vprintf(fmt, arguments); | ||
| 91 | } | 92 | } |
| 92 | 93 | ||
| 93 | /* Set terminal settings to reasonable defaults */ | 94 | /* Set terminal settings to reasonable defaults */ |
| @@ -96,74 +97,71 @@ void set_term() | |||
| 96 | int fd; | 97 | int fd; |
| 97 | struct termios tty; | 98 | struct termios tty; |
| 98 | 99 | ||
| 99 | if ((fd = device_open(console, O_RDWR|O_NOCTTY)) < 0) { | 100 | if ((fd = device_open(console, O_RDWR | O_NOCTTY)) < 0) { |
| 100 | message(log, "can't open %s", console); | 101 | message(log, "can't open %s\n", console); |
| 101 | return; | 102 | return; |
| 102 | } | 103 | } |
| 103 | ioctl(fd, TCGETS, &tty); | 104 | ioctl(fd, TCGETS, &tty); |
| 104 | tty.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD; | 105 | tty.c_cflag &= CBAUD | CBAUDEX | CSIZE | CSTOPB | PARENB | PARODD; |
| 105 | tty.c_cflag |= HUPCL|CLOCAL; | 106 | tty.c_cflag |= HUPCL | CLOCAL; |
| 106 | 107 | ||
| 107 | tty.c_cc[VINTR] = 3; | 108 | tty.c_cc[VINTR] = 3; |
| 108 | tty.c_cc[VQUIT] = 28; | 109 | tty.c_cc[VQUIT] = 28; |
| 109 | tty.c_cc[VERASE] = 127; | 110 | tty.c_cc[VERASE] = 127; |
| 110 | tty.c_cc[VKILL] = 24; | 111 | tty.c_cc[VKILL] = 24; |
| 111 | tty.c_cc[VEOF] = 4; | 112 | tty.c_cc[VEOF] = 4; |
| 112 | tty.c_cc[VTIME] = 0; | 113 | tty.c_cc[VTIME] = 0; |
| 113 | tty.c_cc[VMIN] = 1; | 114 | tty.c_cc[VMIN] = 1; |
| 114 | tty.c_cc[VSTART] = 17; | 115 | tty.c_cc[VSTART] = 17; |
| 115 | tty.c_cc[VSTOP] = 19; | 116 | tty.c_cc[VSTOP] = 19; |
| 116 | tty.c_cc[VSUSP] = 26; | 117 | tty.c_cc[VSUSP] = 26; |
| 117 | 118 | ||
| 118 | /* Set pre and post processing */ | 119 | /* Set pre and post processing */ |
| 119 | tty.c_iflag = IGNPAR|ICRNL|IXON|IXANY; | 120 | tty.c_iflag = IGNPAR | ICRNL | IXON | IXANY; |
| 120 | tty.c_oflag = OPOST|ONLCR; | 121 | tty.c_oflag = OPOST | ONLCR; |
| 121 | tty.c_lflag = ISIG|ICANON|ECHO|ECHOCTL|ECHOPRT|ECHOKE; | 122 | tty.c_lflag = ISIG | ICANON | ECHO | ECHOCTL | ECHOPRT | ECHOKE; |
| 122 | 123 | ||
| 123 | /* Now set the terminal line. */ | 124 | /* Now set the terminal line. */ |
| 124 | ioctl(fd, TCSETS, &tty); | 125 | ioctl(fd, TCSETS, &tty); |
| 125 | close( fd); | 126 | close(fd); |
| 126 | } | 127 | } |
| 127 | 128 | ||
| 128 | static int | 129 | static int mem_total() |
| 129 | mem_total() | ||
| 130 | { | 130 | { |
| 131 | char s[80]; | 131 | char s[80]; |
| 132 | char *p; | 132 | char *p; |
| 133 | FILE *f; | 133 | FILE *f; |
| 134 | const char pattern[]="MemTotal:"; | 134 | const char pattern[] = "MemTotal:"; |
| 135 | 135 | ||
| 136 | f=fopen("/proc/meminfo","r"); | 136 | f = fopen("/proc/meminfo", "r"); |
| 137 | while (NULL != fgets(s,79,f)) { | 137 | while (NULL != fgets(s, 79, f)) { |
| 138 | p=strstr(s, pattern); | 138 | p = strstr(s, pattern); |
| 139 | if (NULL != p) { | 139 | if (NULL != p) { |
| 140 | fclose(f); | 140 | fclose(f); |
| 141 | return(atoi(p+strlen(pattern))); | 141 | return (atoi(p + strlen(pattern))); |
| 142 | } | 142 | } |
| 143 | } | 143 | } |
| 144 | return -1; | 144 | return -1; |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | static void | 147 | static void set_free_pages() |
| 148 | set_free_pages() | ||
| 149 | { | 148 | { |
| 150 | char s[80]; | 149 | char s[80]; |
| 151 | FILE *f; | 150 | FILE *f; |
| 152 | 151 | ||
| 153 | f=fopen("/proc/sys/vm/freepages","r"); | 152 | f = fopen("/proc/sys/vm/freepages", "r"); |
| 154 | fgets(s,79,f); | 153 | fgets(s, 79, f); |
| 155 | if (atoi(s) < 32) { | 154 | if (atoi(s) < 32) { |
| 156 | fclose(f); | 155 | fclose(f); |
| 157 | f=fopen("/proc/sys/vm/freepages","w"); | 156 | f = fopen("/proc/sys/vm/freepages", "w"); |
| 158 | fprintf(f,"30\t40\t50\n"); | 157 | fprintf(f, "30\t40\t50\n"); |
| 159 | printf("\nIncreased /proc/sys/vm/freepages values to 30/40/50\n"); | 158 | printf("\nIncreased /proc/sys/vm/freepages values to 30/40/50\n"); |
| 160 | } | 159 | } |
| 161 | fclose(f); | 160 | fclose(f); |
| 162 | } | 161 | } |
| 163 | 162 | ||
| 164 | 163 | ||
| 165 | static void | 164 | static void console_init() |
| 166 | console_init() | ||
| 167 | { | 165 | { |
| 168 | int fd; | 166 | int fd; |
| 169 | int tried_devcons = 0; | 167 | int tried_devcons = 0; |
| @@ -176,7 +174,7 @@ console_init() | |||
| 176 | console = CONSOLE; | 174 | console = CONSOLE; |
| 177 | tried_devcons++; | 175 | tried_devcons++; |
| 178 | } | 176 | } |
| 179 | while ((fd = open(console, O_RDONLY|O_NONBLOCK)) < 0) { | 177 | while ((fd = open(console, O_RDONLY | O_NONBLOCK)) < 0) { |
| 180 | if (!tried_devcons) { | 178 | if (!tried_devcons) { |
| 181 | tried_devcons++; | 179 | tried_devcons++; |
| 182 | console = CONSOLE; | 180 | console = CONSOLE; |
| @@ -195,41 +193,41 @@ console_init() | |||
| 195 | close(fd); | 193 | close(fd); |
| 196 | } | 194 | } |
| 197 | 195 | ||
| 198 | static int | 196 | static int waitfor(int pid) |
| 199 | waitfor(int pid) | ||
| 200 | { | 197 | { |
| 201 | int status, wpid; | 198 | int status, wpid; |
| 202 | 199 | ||
| 203 | message(log, "Waiting for process %d.\n", pid); | 200 | message(log, "Waiting for process %d.\n", pid); |
| 204 | while ( (wpid = wait(&status)) != pid ) { | 201 | while ((wpid = wait(&status)) != pid) { |
| 205 | if ( wpid > 0 ) | 202 | if (wpid > 0) |
| 206 | message(log,"pid %d exited, status=%x.\n", wpid, status); | 203 | message(log, "pid %d exited, status=%x.\n", wpid, status); |
| 207 | } | 204 | } |
| 208 | return wpid; | 205 | return wpid; |
| 209 | } | 206 | } |
| 210 | 207 | ||
| 211 | static int | 208 | static int run(const char *command, char *terminal, int get_enter) |
| 212 | run(const char* command, char* terminal, int get_enter) | ||
| 213 | { | 209 | { |
| 214 | int f, pid; | 210 | int f, pid; |
| 215 | char *args[16]; | 211 | char *args[16]; |
| 216 | char buf[256]; | 212 | char buf[256]; |
| 217 | char* ptr; | 213 | char *ptr; |
| 218 | static const char press_enter[] = | 214 | static const char press_enter[] = |
| 219 | "\nPlease press Enter to activate this console. "; | 215 | "\nPlease press Enter to activate this console. "; |
| 220 | 216 | ||
| 221 | 217 | ||
| 222 | /* Make a proper command from the command string */ | 218 | /* Make a proper command from the command string */ |
| 223 | strcpy(buf, command); | 219 | strcpy(buf, command); |
| 224 | ptr = buf; | 220 | ptr = buf; |
| 225 | for(f = 1; f < 15; f++) { | 221 | for (f = 1; f < 15; f++) { |
| 226 | /* Skip white space */ | 222 | /* Skip white space */ |
| 227 | while(*ptr == ' ' || *ptr == '\t') ptr++; | 223 | while (*ptr == ' ' || *ptr == '\t') |
| 224 | ptr++; | ||
| 228 | args[f] = ptr; | 225 | args[f] = ptr; |
| 229 | /* May be trailing space.. */ | 226 | /* May be trailing space.. */ |
| 230 | if (*ptr == 0) break; | 227 | if (*ptr == 0) |
| 228 | break; | ||
| 231 | /* Skip this `word' */ | 229 | /* Skip this `word' */ |
| 232 | while(*ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '#') | 230 | while (*ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '#') |
| 233 | ptr++; | 231 | ptr++; |
| 234 | /* If end-of-line, break */ | 232 | /* If end-of-line, break */ |
| 235 | if (*ptr == '#' || *ptr == 0) { | 233 | if (*ptr == '#' || *ptr == 0) { |
| @@ -241,7 +239,7 @@ run(const char* command, char* terminal, int get_enter) | |||
| 241 | args[f] = NULL; | 239 | args[f] = NULL; |
| 242 | } | 240 | } |
| 243 | args[0] = args[1]; | 241 | args[0] = args[1]; |
| 244 | 242 | ||
| 245 | 243 | ||
| 246 | if ((pid = fork()) == 0) { | 244 | if ((pid = fork()) == 0) { |
| 247 | /* Clean up */ | 245 | /* Clean up */ |
| @@ -250,8 +248,8 @@ run(const char* command, char* terminal, int get_enter) | |||
| 250 | close(2); | 248 | close(2); |
| 251 | setsid(); | 249 | setsid(); |
| 252 | 250 | ||
| 253 | if ((f = device_open(terminal, O_RDWR|O_NOCTTY)) < 0) { | 251 | if ((f = device_open(terminal, O_RDWR | O_NOCTTY)) < 0) { |
| 254 | message( log, "open(%s) failed: %s", terminal, strerror(errno)); | 252 | message(log, "open(%s) failed: %s\n", terminal, strerror(errno)); |
| 255 | return -1; | 253 | return -1; |
| 256 | } | 254 | } |
| 257 | dup(f); | 255 | dup(f); |
| @@ -259,7 +257,7 @@ run(const char* command, char* terminal, int get_enter) | |||
| 259 | tcsetpgrp(0, getpgrp()); | 257 | tcsetpgrp(0, getpgrp()); |
| 260 | set_term(); | 258 | set_term(); |
| 261 | 259 | ||
| 262 | if ( get_enter ) { | 260 | if (get_enter) { |
| 263 | /* | 261 | /* |
| 264 | * Save memory by not exec-ing anything large (like a shell) | 262 | * Save memory by not exec-ing anything large (like a shell) |
| 265 | * before the user wants it. This is critical if swap is not | 263 | * before the user wants it. This is critical if swap is not |
| @@ -268,18 +266,21 @@ run(const char* command, char* terminal, int get_enter) | |||
| 268 | * be allowed to start a shell or whatever an init script | 266 | * be allowed to start a shell or whatever an init script |
| 269 | * specifies. | 267 | * specifies. |
| 270 | */ | 268 | */ |
| 271 | char c; | 269 | char c; |
| 272 | write(1, press_enter, sizeof(press_enter) - 1); | 270 | write(1, press_enter, sizeof(press_enter) - 1); |
| 273 | read(0, &c, 1); | 271 | read(0, &c, 1); |
| 272 | message(console, "Got an enter\r\n"); | ||
| 274 | } | 273 | } |
| 275 | 274 | ||
| 276 | /* Log the process name and args */ | 275 | /* Log the process name and args */ |
| 277 | message(log, "Executing '%s'\n", command); | 276 | message(console, "Executing "); |
| 277 | message(console, "'%s'\r\n", command); | ||
| 278 | 278 | ||
| 279 | /* Now run it. This should take over the PID, so nothing | 279 | /* Now run it. This should take over the PID, so nothing |
| 280 | * further in init.c should be run by this PID. */ | 280 | * further in init.c should be run by this PID. */ |
| 281 | execvp(args[1], args + 1); | 281 | execvp(args[1], args + 1); |
| 282 | 282 | ||
| 283 | message(console, "Hmm. Trying as a script.\r\n"); | ||
| 283 | /* If shell scripts are not executed, force the issue */ | 284 | /* If shell scripts are not executed, force the issue */ |
| 284 | if (errno == ENOEXEC) { | 285 | if (errno == ENOEXEC) { |
| 285 | char buf[256]; | 286 | char buf[256]; |
| @@ -291,18 +292,17 @@ run(const char* command, char* terminal, int get_enter) | |||
| 291 | args[4] = NULL; | 292 | args[4] = NULL; |
| 292 | execvp(args[1], args + 1); | 293 | execvp(args[1], args + 1); |
| 293 | } | 294 | } |
| 294 | message(log, "Could not execute '%s'\n", command, strerror(errno)); | 295 | message(console, "Could not execute '%s'\n", command); |
| 295 | exit(-1); | 296 | exit(-1); |
| 296 | } | 297 | } |
| 297 | return pid; | 298 | return pid; |
| 298 | } | 299 | } |
| 299 | 300 | ||
| 300 | #ifndef DEBUG_INIT | 301 | #ifndef DEBUG_INIT |
| 301 | static void | 302 | static void shutdown_system(void) |
| 302 | shutdown_system(void) | ||
| 303 | { | 303 | { |
| 304 | 304 | ||
| 305 | message(console, "The system is going down NOW !!"); | 305 | message(console, "The system is going down NOW !!\r\n"); |
| 306 | sync(); | 306 | sync(); |
| 307 | /* Allow Ctrl-Alt-Del to reboot system. */ | 307 | /* Allow Ctrl-Alt-Del to reboot system. */ |
| 308 | reboot(RB_ENABLE_CAD); | 308 | reboot(RB_ENABLE_CAD); |
| @@ -318,169 +318,151 @@ shutdown_system(void) | |||
| 318 | waitfor(run("/bin/swapoff -a", console, 0)); | 318 | waitfor(run("/bin/swapoff -a", console, 0)); |
| 319 | waitfor(run("/bin/umount -a -n", console, 0)); | 319 | waitfor(run("/bin/umount -a -n", console, 0)); |
| 320 | sync(); | 320 | sync(); |
| 321 | if (get_kernel_revision() <= 2*65536+2*256+11) { | 321 | if (get_kernel_revision() <= 2 * 65536 + 2 * 256 + 11) { |
| 322 | /* Removed bdflush call, kupdate in kernels >2.2.11 */ | 322 | /* Removed bdflush call, kupdate in kernels >2.2.11 */ |
| 323 | bdflush(1, 0); | 323 | bdflush(1, 0); |
| 324 | sync(); | 324 | sync(); |
| 325 | } | 325 | } |
| 326 | } | 326 | } |
| 327 | 327 | ||
| 328 | static void | 328 | static void halt_signal(int sig) |
| 329 | halt_signal(int sig) | ||
| 330 | { | 329 | { |
| 331 | shutdown_system(); | 330 | shutdown_system(); |
| 332 | message(console, "The system is halted. Press CTRL-ALT-DEL or turn off power\r\n"); | 331 | message(console, |
| 333 | reboot( RB_POWER_OFF); | 332 | "The system is halted. Press CTRL-ALT-DEL or turn off power\r\n"); |
| 333 | reboot(RB_POWER_OFF); | ||
| 334 | exit(0); | 334 | exit(0); |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | static void | 337 | static void reboot_signal(int sig) |
| 338 | reboot_signal(int sig) | ||
| 339 | { | 338 | { |
| 340 | shutdown_system(); | 339 | shutdown_system(); |
| 341 | message(console, "Please stand by while rebooting the system.\r\n"); | 340 | message(console, "Please stand by while rebooting the system.\r\n"); |
| 342 | reboot( RB_AUTOBOOT); | 341 | reboot(RB_AUTOBOOT); |
| 343 | exit(0); | 342 | exit(0); |
| 344 | } | 343 | } |
| 345 | #endif | ||
| 346 | 344 | ||
| 347 | int setproctitle(char *fmt, ...) | 345 | #endif |
| 348 | { | ||
| 349 | va_list ap; | ||
| 350 | int len; | ||
| 351 | char buf[256]; | ||
| 352 | |||
| 353 | buf[0] = 0; | ||
| 354 | va_start(ap, fmt); | ||
| 355 | len = vsprintf(buf, fmt, ap); | ||
| 356 | va_end(ap); | ||
| 357 | memset(argv0, 0, maxproclen + 1); | ||
| 358 | strncpy(argv0, buf, maxproclen); | ||
| 359 | return len; | ||
| 360 | } | ||
| 361 | 346 | ||
| 362 | extern int | 347 | extern int init_main(int argc, char **argv) |
| 363 | init_main(int argc, char * * argv) | ||
| 364 | { | 348 | { |
| 365 | int run_rc = TRUE; | 349 | int run_rc = TRUE; |
| 366 | int pid1 = 0; | 350 | int pid1 = 0; |
| 367 | int pid2 = 0; | 351 | int pid2 = 0; |
| 368 | struct stat statbuf; | 352 | struct stat statbuf; |
| 369 | const char* init_commands = SHELL "-c exec " INITSCRIPT; | 353 | const char *init_commands = SHELL "-c exec " INITSCRIPT; |
| 370 | const char* shell_commands = SHELL; | 354 | const char *shell_commands = SHELL; |
| 371 | const char* tty0_commands = init_commands; | 355 | const char *tty0_commands = init_commands; |
| 372 | const char* tty1_commands = shell_commands; | 356 | const char *tty1_commands = shell_commands; |
| 373 | const char* no_memory = | 357 | char *hello_msg_format = |
| 374 | "Sorry, your computer does not have enough memory.\n"; | 358 | "init started: BusyBox v%s (%s) multi-call binary\r\n"; |
| 375 | 359 | const char *no_memory = | |
| 376 | /* For later use */ | 360 | "Sorry, your computer does not have enough memory.\r\n"; |
| 377 | argv0 = argv[0]; | ||
| 378 | maxproclen = strlen(argv[0]); | ||
| 379 | setproctitle("init [boot]"); | ||
| 380 | 361 | ||
| 381 | 362 | ||
| 382 | #ifndef DEBUG_INIT | 363 | #ifndef DEBUG_INIT |
| 383 | /* Set up sig handlers */ | 364 | /* Set up sig handlers */ |
| 384 | signal(SIGUSR1, halt_signal); | 365 | signal(SIGUSR1, halt_signal); |
| 385 | signal(SIGSEGV, halt_signal); | 366 | signal(SIGSEGV, halt_signal); |
| 386 | signal(SIGPWR, halt_signal); | 367 | signal(SIGPWR, halt_signal); |
| 387 | signal(SIGALRM, halt_signal); | 368 | signal(SIGALRM, halt_signal); |
| 388 | signal(SIGHUP, halt_signal); | 369 | signal(SIGHUP, halt_signal); |
| 389 | signal(SIGUSR2, reboot_signal); | 370 | signal(SIGUSR2, reboot_signal); |
| 390 | signal(SIGINT, reboot_signal); | 371 | signal(SIGINT, reboot_signal); |
| 391 | signal(SIGTERM, reboot_signal); | 372 | signal(SIGTERM, reboot_signal); |
| 392 | #endif | 373 | #endif |
| 393 | /* Figure out where the default console should be */ | 374 | /* Figure out where the default console should be */ |
| 394 | console_init(); | 375 | console_init(); |
| 395 | 376 | ||
| 396 | /* Turn off rebooting via CTL-ALT-DEL -- we get a | 377 | /* Turn off rebooting via CTL-ALT-DEL -- we get a |
| 397 | * SIGINT on CAD so we can shut things down gracefully... */ | 378 | * SIGINT on CAD so we can shut things down gracefully... */ |
| 398 | #ifndef DEBUG_INIT | 379 | #ifndef DEBUG_INIT |
| 399 | reboot(RB_DISABLE_CAD); | 380 | reboot(RB_DISABLE_CAD); |
| 400 | #endif | 381 | #endif |
| 401 | 382 | ||
| 402 | /* Close whatever files are open, and reset the console. */ | 383 | /* Close whatever files are open, and reset the console. */ |
| 403 | close(0); | 384 | close(0); |
| 404 | close(1); | 385 | close(1); |
| 405 | close(2); | 386 | close(2); |
| 406 | set_term(); | 387 | set_term(); |
| 407 | setsid(); | 388 | setsid(); |
| 408 | 389 | ||
| 409 | /* Make sure PATH is set to something sane */ | 390 | /* Make sure PATH is set to something sane */ |
| 410 | if (getenv("PATH") == NULL) | 391 | if (getenv("PATH") == NULL) |
| 411 | putenv(PATH_DEFAULT); | 392 | putenv(PATH_DEFAULT); |
| 412 | 393 | ||
| 413 | /* Hello world */ | 394 | /* Hello world */ |
| 414 | message(console, "%s started: BusyBox v%s (%s) multi-call binary", | 395 | message(log, hello_msg_format, BB_VER, BB_BT); |
| 415 | argv[0], BB_VER, BB_BT); | 396 | message(console, hello_msg_format, BB_VER, BB_BT); |
| 416 | message(log, "%s started: BusyBox v%s (%s) multi-call binary", | 397 | |
| 417 | argv[0], BB_VER, BB_BT); | 398 | /* Mount /proc */ |
| 418 | 399 | if (mount("/proc", "/proc", "proc", 0, 0)) { | |
| 419 | 400 | message(log, "Mounting /proc: failed!\n"); | |
| 420 | /* Mount /proc */ | 401 | message(console, "Mounting /proc: failed!\r\n"); |
| 421 | message(console, "Mounting /proc: \n"); | 402 | } else { |
| 422 | if (mount("/proc","/proc","proc",0,0)) { | 403 | message(console, "Mounting /proc: done.\r\n"); |
| 423 | message(log, "%s: could not mount /proc!\n", argv[0]); | 404 | } |
| 424 | message(console, "failed!\n"); | ||
| 425 | } | ||
| 426 | message(console, "done.\n"); | ||
| 427 | |||
| 428 | 405 | ||
| 429 | /* Make sure there is enough memory to do something useful*/ | 406 | /* Make sure there is enough memory to do something useful */ |
| 430 | set_free_pages(); | 407 | set_free_pages(); |
| 431 | if (mem_total() < 2000) { | 408 | if (mem_total() < 2000) { |
| 432 | int retval; | 409 | int retval; |
| 433 | retval= stat("/etc/fstab",&statbuf); | 410 | retval = stat("/etc/fstab", &statbuf); |
| 434 | if (retval) { | 411 | if (retval) { |
| 412 | message(console, "%s", no_memory); | ||
| 413 | while (1) { | ||
| 414 | sleep(1); | ||
| 415 | } | ||
| 416 | } else { | ||
| 417 | /* Try to turn on swap */ | ||
| 418 | waitfor(run("/bin/swapon -a", console, 0)); | ||
| 419 | if (mem_total() < 2000) { | ||
| 435 | message(console, "%s", no_memory); | 420 | message(console, "%s", no_memory); |
| 436 | while (1) { sleep(1);} | 421 | while (1) { |
| 437 | } else { | 422 | sleep(1); |
| 438 | /* Try to turn on swap */ | ||
| 439 | waitfor(run("/bin/swapon -a", console, 0)); | ||
| 440 | if (mem_total() < 2000) { | ||
| 441 | message(console, "%s", no_memory); | ||
| 442 | while (1) { sleep(1);} | ||
| 443 | } | 423 | } |
| 444 | } | 424 | } |
| 445 | } | 425 | } |
| 426 | } | ||
| 446 | 427 | ||
| 447 | /* Check if we are supposed to be in single user mode */ | 428 | /* Check if we are supposed to be in single user mode */ |
| 448 | if (!strcmp(argv[1], "single") || !strcmp(argv[1], "-s") || !strcmp(argv[1], "1")) { | 429 | if ( argc > 1 && (!strcmp(argv[1], "single") || |
| 449 | run_rc = FALSE; | 430 | !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) { |
| 450 | tty0_commands = shell_commands; | 431 | run_rc = FALSE; |
| 451 | tty1_commands = 0; | 432 | tty0_commands = shell_commands; |
| 452 | setproctitle("init [S]"); | 433 | tty1_commands = 0; |
| 453 | } else { | 434 | } |
| 454 | setproctitle("init [1]"); | ||
| 455 | } | ||
| 456 | 435 | ||
| 457 | /* Make sure an init script exists before trying to run it */ | 436 | /* Make sure an init script exists before trying to run it */ |
| 458 | if ( run_rc == TRUE && stat( INITSCRIPT, &statbuf)) { | 437 | if (run_rc == TRUE && stat(INITSCRIPT, &statbuf)) { |
| 459 | tty0_commands = shell_commands; | 438 | tty0_commands = shell_commands; |
| 460 | tty1_commands = shell_commands; | 439 | tty1_commands = shell_commands; |
| 461 | } | 440 | } |
| 462 | 441 | ||
| 463 | /* Ok, now launch the rc script and/or prepare to | 442 | /* Ok, now launch the rc script and/or prepare to |
| 464 | * start up some VTs if somebody hits enter... | 443 | * start up some VTs if somebody hits enter... |
| 465 | */ | 444 | */ |
| 466 | for ( ; ; ) { | 445 | for (;;) { |
| 467 | int wpid; | 446 | int wpid; |
| 468 | int status; | 447 | int status; |
| 469 | 448 | ||
| 470 | if ( pid1 == 0 && *tty0_commands ) { | 449 | if (pid1 == 0 && tty0_commands) { |
| 471 | pid1 = run(tty0_commands, console, 1); | 450 | pid1 = run(tty0_commands, console, 1); |
| 472 | } | ||
| 473 | if ( pid2 == 0 && *tty1_commands ) { | ||
| 474 | pid2 = run(tty1_commands, second_terminal, 1); | ||
| 475 | } | ||
| 476 | wpid = wait(&status); | ||
| 477 | if ( wpid > 0 && wpid != pid1) { | ||
| 478 | message(log, "pid %d exited, status=%x.\n", wpid, status); | ||
| 479 | } | ||
| 480 | if ( wpid == pid2 ) { | ||
| 481 | pid2 = 0; | ||
| 482 | } | ||
| 483 | sleep(1); | ||
| 484 | } | 451 | } |
| 452 | if (pid2 == 0 && tty1_commands) { | ||
| 453 | pid2 = run(tty1_commands, second_terminal, 1); | ||
| 454 | } | ||
| 455 | wpid = wait(&status); | ||
| 456 | if (wpid > 0 && wpid != pid1) { | ||
| 457 | message(log, "pid %d exited, status=%x.\n", wpid, status); | ||
| 458 | } | ||
| 459 | /* Don't respawn an init script if it exits */ | ||
| 460 | if (run_rc == FALSE && wpid == pid1) { | ||
| 461 | pid1 = 0; | ||
| 462 | } | ||
| 463 | if (wpid == pid2) { | ||
| 464 | pid2 = 0; | ||
| 465 | } | ||
| 466 | sleep(1); | ||
| 467 | } | ||
| 485 | } | 468 | } |
| 486 | |||
