📄 init.c
字号:
}static void halt_signal(int sig){ shutdown_system(); message(CONSOLE|LOG,#if #cpu(s390) /* Seems the s390 console is Wierd(tm). */ "\rThe system is halted. You may reboot now.\n"#else /* secondConsole is NULL for a serial console */ "\rThe system is halted. Press %s or turn off power\n", (secondConsole == NULL)? "Reset" : "CTRL-ALT-DEL"#endif ); sync(); /* allow time for last message to reach serial console */ sleep(2); if (sig == SIGUSR2 && kernelVersion >= KERNEL_VERSION(2,2,0)) init_reboot(RB_POWER_OFF); else init_reboot(RB_HALT_SYSTEM); loop_forever();}static void reboot_signal(int sig){ shutdown_system(); message(CONSOLE|LOG, "\rPlease stand by while rebooting the system.\n"); sync(); /* allow time for last message to reach serial console */ sleep(2); init_reboot(RB_AUTOBOOT); loop_forever();}static void ctrlaltdel_signal(int sig){ run_actions(CTRLALTDEL);}/* The SIGSTOP & SIGTSTP handler */static void stop_handler(int sig){ int saved_errno = errno; got_cont = 0; while(!got_cont) pause(); got_cont = 0; errno = saved_errno;}/* The SIGCONT handler */ static void cont_handler(int sig){ got_cont = 1;}#endif /* ! DEBUG_INIT */static void new_init_action(int action, char *command, char *cons){ struct init_action *new_action, *a; if (*cons == '\0') cons = console; /* If BusyBox detects that a serial console is in use, then entries * not refering to the console or null devices will _not_ be run. * The exception to this rule is the null device. */ if (secondConsole == NULL && strcmp(cons, console) && strcmp(cons, "/dev/null")) return; if (strcmp(cons, "/dev/null") == 0 && (action & ASKFIRST)) return; new_action = calloc((size_t) (1), sizeof(struct init_action)); if (!new_action) { message(LOG | CONSOLE, "\rMemory allocation failure\n"); loop_forever(); } /* Append to the end of the list */ for (a = init_action_list; a && a->next; a = a->next) ; if (a) { a->next = new_action; } else { init_action_list = new_action; } strcpy(new_action->command, command); new_action->action = action; strcpy(new_action->terminal, cons); new_action->pid = 0;// message(LOG|CONSOLE, "command='%s' action='%d' terminal='%s'\n",// new_action->command, new_action->action, new_action->terminal);}static void delete_init_action(struct init_action * action){ struct init_action *a, *b = NULL; for (a = init_action_list; a; b = a, a = a->next) { if (a == action) { if (b == NULL) { init_action_list = a->next; } else { b->next = a->next; } free(a); break; } }}/* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined, * then parse_inittab() simply adds in some default * actions(i.e., runs INIT_SCRIPT and then starts a pair * of "askfirst" shells). If CONFIG_FEATURE_USE_INITTAB * _is_ defined, but /etc/inittab is missing, this * results in the same set of default behaviors. * */static void parse_inittab(void){#ifdef CONFIG_FEATURE_USE_INITTAB FILE *file; char buf[INIT_BUFFS_SIZE], lineAsRead[INIT_BUFFS_SIZE], tmpConsole[INIT_BUFFS_SIZE]; char *id, *runlev, *action, *command, *eol; const struct init_action_type *a = actions; int foundIt; file = fopen(INITTAB, "r"); if (file == NULL) { /* No inittab file -- set up some default behavior */#endif /* Reboot on Ctrl-Alt-Del */ new_init_action(CTRLALTDEL, "/sbin/reboot", console); /* Umount all filesystems on halt/reboot */ new_init_action(SHUTDOWN, "/bin/umount -a -r", console);#if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__) /* Swapoff on halt/reboot */ new_init_action(SHUTDOWN, "/sbin/swapoff -a", console);#endif /* Prepare to restart init when a HUP is received */ new_init_action(RESTART, "/sbin/init", console); /* Askfirst shell on tty1 */ new_init_action(ASKFIRST, LOGIN_SHELL, console); /* Askfirst shell on tty2 */ if (secondConsole != NULL) new_init_action(ASKFIRST, LOGIN_SHELL, secondConsole); /* Askfirst shell on tty3 */ if (thirdConsole != NULL) new_init_action(ASKFIRST, LOGIN_SHELL, thirdConsole); /* Askfirst shell on tty4 */ if (fourthConsole != NULL) new_init_action(ASKFIRST, LOGIN_SHELL, fourthConsole); /* sysinit */ new_init_action(SYSINIT, INIT_SCRIPT, console); return;#ifdef CONFIG_FEATURE_USE_INITTAB } while (fgets(buf, INIT_BUFFS_SIZE, file) != NULL) { foundIt = FALSE; /* Skip leading spaces */ for (id = buf; *id == ' ' || *id == '\t'; id++); /* Skip the line if it's a comment */ if (*id == '#' || *id == '\n') continue; /* Trim the trailing \n */ eol = strrchr(id, '\n'); if (eol != NULL) *eol = '\0'; /* Keep a copy around for posterity's sake (and error msgs) */ strcpy(lineAsRead, buf); /* Separate the ID field from the runlevels */ runlev = strchr(id, ':'); if (runlev == NULL || *(runlev + 1) == '\0') { message(LOG | CONSOLE, "\rBad inittab entry: %s\n", lineAsRead); continue; } else { *runlev = '\0'; ++runlev; } /* Separate the runlevels from the action */ action = strchr(runlev, ':'); if (action == NULL || *(action + 1) == '\0') { message(LOG | CONSOLE, "\rBad inittab entry: %s\n", lineAsRead); continue; } else { *action = '\0'; ++action; } /* Separate the action from the command */ command = strchr(action, ':'); if (command == NULL || *(command + 1) == '\0') { message(LOG | CONSOLE, "\rBad inittab entry: %s\n", lineAsRead); continue; } else { *command = '\0'; ++command; } /* Ok, now process it */ a = actions; while (a->name != 0) { if (strcmp(a->name, action) == 0) { if (*id != '\0') { strcpy(tmpConsole, "/dev/"); strncat(tmpConsole, id, INIT_BUFFS_SIZE-6); id = tmpConsole; } new_init_action(a->action, command, id); foundIt = TRUE; } a++; } if (foundIt == TRUE) continue; else { /* Choke on an unknown action */ message(LOG | CONSOLE, "\rBad inittab entry: %s\n", lineAsRead); } } fclose(file); return;#endif /* CONFIG_FEATURE_USE_INITTAB */}extern int init_main(int argc, char **argv){ struct init_action *a; pid_t wpid; int status; if (argc > 1 && !strcmp(argv[1], "-q")) { /* don't assume init's pid == 1 */ long *pid = find_pid_by_name("init"); if (!pid || *pid<=0) { pid = find_pid_by_name("linuxrc"); if (!pid || *pid<=0) error_msg_and_die("no process killed"); } kill(*pid, SIGHUP); exit(0); }#ifndef DEBUG_INIT /* Expect to be invoked as init with PID=1 or be invoked as linuxrc */ if (getpid() != 1#ifdef CONFIG_FEATURE_INITRD && strstr(applet_name, "linuxrc") == NULL#endif ) { show_usage(); } /* Set up sig handlers -- be sure to * clear all of these in run() */ signal(SIGHUP, exec_signal); signal(SIGUSR1, halt_signal); signal(SIGUSR2, halt_signal); signal(SIGINT, ctrlaltdel_signal); signal(SIGTERM, reboot_signal); signal(SIGCONT, cont_handler); signal(SIGSTOP, stop_handler); signal(SIGTSTP, stop_handler); /* Turn off rebooting via CTL-ALT-DEL -- we get a * SIGINT on CAD so we can shut things down gracefully... */ init_reboot(RB_DISABLE_CAD);#endif /* Figure out what kernel this is running */ kernelVersion = get_kernel_revision(); /* Figure out where the default console should be */ console_init(); /* Close whatever files are open, and reset the console. */ close(0); close(1); close(2); if(device_open(console, O_RDWR|O_NOCTTY)==0) { set_term(0); close(0); } chdir("/"); setsid(); /* Make sure PATH is set to something sane */ putenv("PATH="_PATH_STDPATH); /* Hello world */ message(MAYBE_CONSOLE|LOG, "\rinit started: %s\n", full_version); /* Make sure there is enough memory to do something useful. */ check_memory(); /* Check if we are supposed to be in single user mode */ if (argc > 1 && (!strcmp(argv[1], "single") || !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) { /* Ask first then start a shell on tty2-4 */ if (secondConsole != NULL) new_init_action(ASKFIRST, LOGIN_SHELL, secondConsole); if (thirdConsole != NULL) new_init_action(ASKFIRST, LOGIN_SHELL, thirdConsole); if (fourthConsole != NULL) new_init_action(ASKFIRST, LOGIN_SHELL, fourthConsole); /* Start a shell on tty1 */ new_init_action(RESPAWN, LOGIN_SHELL, console); } else { /* Not in single user mode -- see what inittab says */ /* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined, * then parse_inittab() simply adds in some default * actions(i.e., runs INIT_SCRIPT and then starts a pair * of "askfirst" shells */ parse_inittab(); } /* Make the command line just say "init" -- thats all, nothing else */ fixup_argv(argc, argv, "init"); /* Now run everything that needs to be run */ /* First run the sysinit command */ run_actions(SYSINIT); /* Next run anything that wants to block */ run_actions(WAIT); /* Next run anything to be run only once */ run_actions(ONCE); /* If there is nothing else to do, stop */ if (init_action_list == NULL) { message(LOG | CONSOLE, "\rNo more tasks for init -- sleeping forever.\n"); loop_forever(); } /* Now run the looping stuff for the rest of forever */ while (1) { /* run the respawn stuff */ run_actions(RESPAWN); /* run the askfirst stuff */ run_actions(ASKFIRST); /* Don't consume all CPU time -- sleep a bit */ sleep(1); /* Wait for a child process to exit */ wpid = wait(&status); if (wpid > 0) { /* Find out who died and clean up their corpse */ for (a = init_action_list; a; a = a->next) { if (a->pid == wpid) { /* Set the pid to 0 so that the process gets * restarted by run_actions() */ a->pid = 0; message(LOG, "Process '%s' (pid %d) exited. " "Scheduling it for restart.\n", a->command, wpid); } } } }}/*Local Variables:c-file-style: "linux"c-basic-offset: 4tab-width: 4End:*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -