10f66f451Sopenharmony_ci/* init.c - init program. 20f66f451Sopenharmony_ci * 30f66f451Sopenharmony_ci * Copyright 2012 Harvind Singh <harvindsingh1981@gmail.com> 40f66f451Sopenharmony_ci * Copyright 2013 Kyungwan Han <asura321@gmail.com> 50f66f451Sopenharmony_ci * 60f66f451Sopenharmony_ci * No Standard 70f66f451Sopenharmony_ci 80f66f451Sopenharmony_ciUSE_INIT(NEWTOY(init, "", TOYFLAG_SBIN)) 90f66f451Sopenharmony_ci 100f66f451Sopenharmony_ciconfig INIT 110f66f451Sopenharmony_ci bool "init" 120f66f451Sopenharmony_ci default n 130f66f451Sopenharmony_ci help 140f66f451Sopenharmony_ci usage: init 150f66f451Sopenharmony_ci 160f66f451Sopenharmony_ci System V style init. 170f66f451Sopenharmony_ci 180f66f451Sopenharmony_ci First program to run (as PID 1) when the system comes up, reading 190f66f451Sopenharmony_ci /etc/inittab to determine actions. 200f66f451Sopenharmony_ci*/ 210f66f451Sopenharmony_ci 220f66f451Sopenharmony_ci#include "toys.h" 230f66f451Sopenharmony_ci#include <sys/reboot.h> 240f66f451Sopenharmony_ci 250f66f451Sopenharmony_cistruct action_list_seed { 260f66f451Sopenharmony_ci struct action_list_seed *next; 270f66f451Sopenharmony_ci pid_t pid; 280f66f451Sopenharmony_ci uint8_t action; 290f66f451Sopenharmony_ci char *terminal_name; 300f66f451Sopenharmony_ci char *command; 310f66f451Sopenharmony_ci} *action_list_pointer = NULL; 320f66f451Sopenharmony_ciint caught_signal; 330f66f451Sopenharmony_ci 340f66f451Sopenharmony_ci//INITTAB action defination 350f66f451Sopenharmony_ci#define SYSINIT 0x01 360f66f451Sopenharmony_ci#define WAIT 0x02 370f66f451Sopenharmony_ci#define ONCE 0x04 380f66f451Sopenharmony_ci#define RESPAWN 0x08 390f66f451Sopenharmony_ci#define ASKFIRST 0x10 400f66f451Sopenharmony_ci#define CTRLALTDEL 0x20 410f66f451Sopenharmony_ci#define SHUTDOWN 0x40 420f66f451Sopenharmony_ci#define RESTART 0x80 430f66f451Sopenharmony_ci 440f66f451Sopenharmony_cistatic void initialize_console(void) 450f66f451Sopenharmony_ci{ 460f66f451Sopenharmony_ci int fd; 470f66f451Sopenharmony_ci char *p = getenv("CONSOLE"); 480f66f451Sopenharmony_ci 490f66f451Sopenharmony_ci if (!p) p = getenv("console"); 500f66f451Sopenharmony_ci if (!p) { 510f66f451Sopenharmony_ci fd = open("/dev/null", O_RDWR); 520f66f451Sopenharmony_ci if (fd >= 0) { 530f66f451Sopenharmony_ci while (fd < 2) fd = dup(fd); 540f66f451Sopenharmony_ci while (fd > 2) close(fd--); 550f66f451Sopenharmony_ci } 560f66f451Sopenharmony_ci } else { 570f66f451Sopenharmony_ci fd = open(p, O_RDWR | O_NONBLOCK | O_NOCTTY); 580f66f451Sopenharmony_ci if (fd < 0) printf("Unable to open console %s\n",p); 590f66f451Sopenharmony_ci else { 600f66f451Sopenharmony_ci dup2(fd,0); 610f66f451Sopenharmony_ci dup2(fd,1); 620f66f451Sopenharmony_ci dup2(fd,2); 630f66f451Sopenharmony_ci } 640f66f451Sopenharmony_ci } 650f66f451Sopenharmony_ci 660f66f451Sopenharmony_ci if (!getenv("TERM")) putenv("TERM=linux"); 670f66f451Sopenharmony_ci} 680f66f451Sopenharmony_ci 690f66f451Sopenharmony_cistatic void reset_term(int fd) 700f66f451Sopenharmony_ci{ 710f66f451Sopenharmony_ci struct termios terminal; 720f66f451Sopenharmony_ci 730f66f451Sopenharmony_ci tcgetattr(fd, &terminal); 740f66f451Sopenharmony_ci terminal.c_cc[VINTR] = 3; //ctrl-c 750f66f451Sopenharmony_ci terminal.c_cc[VQUIT] = 28; /*ctrl-\*/ 760f66f451Sopenharmony_ci terminal.c_cc[VERASE] = 127; //ctrl-? 770f66f451Sopenharmony_ci terminal.c_cc[VKILL] = 21; //ctrl-u 780f66f451Sopenharmony_ci terminal.c_cc[VEOF] = 4; //ctrl-d 790f66f451Sopenharmony_ci terminal.c_cc[VSTART] = 17; //ctrl-q 800f66f451Sopenharmony_ci terminal.c_cc[VSTOP] = 19; //ctrl-s 810f66f451Sopenharmony_ci terminal.c_cc[VSUSP] = 26; //ctrl-z 820f66f451Sopenharmony_ci 830f66f451Sopenharmony_ci terminal.c_line = 0; 840f66f451Sopenharmony_ci terminal.c_cflag &= CRTSCTS|PARODD|PARENB|CSTOPB|CSIZE|CBAUDEX|CBAUD; 850f66f451Sopenharmony_ci terminal.c_cflag |= CLOCAL|HUPCL|CREAD; 860f66f451Sopenharmony_ci 870f66f451Sopenharmony_ci //enable start/stop input and output control + map CR to NL on input 880f66f451Sopenharmony_ci terminal.c_iflag = IXON|IXOFF|ICRNL; 890f66f451Sopenharmony_ci 900f66f451Sopenharmony_ci //Map NL to CR-NL on output 910f66f451Sopenharmony_ci terminal.c_oflag = ONLCR|OPOST; 920f66f451Sopenharmony_ci terminal.c_lflag = IEXTEN|ECHOKE|ECHOCTL|ECHOK|ECHOE|ECHO|ICANON|ISIG; 930f66f451Sopenharmony_ci tcsetattr(fd, TCSANOW, &terminal); 940f66f451Sopenharmony_ci} 950f66f451Sopenharmony_ci 960f66f451Sopenharmony_cistatic void add_new_action(int action, char *command, char *term) 970f66f451Sopenharmony_ci{ 980f66f451Sopenharmony_ci struct action_list_seed *x,**y; 990f66f451Sopenharmony_ci 1000f66f451Sopenharmony_ci y = &action_list_pointer; 1010f66f451Sopenharmony_ci x = *y; 1020f66f451Sopenharmony_ci while (x) { 1030f66f451Sopenharmony_ci if (!(strcmp(x->command, command)) && !(strcmp(x->terminal_name, term))) { 1040f66f451Sopenharmony_ci *y = x->next; //remove from the list 1050f66f451Sopenharmony_ci while(*y) y = &(*y)->next; //traverse through list till end 1060f66f451Sopenharmony_ci x->next = NULL; 1070f66f451Sopenharmony_ci break; 1080f66f451Sopenharmony_ci } 1090f66f451Sopenharmony_ci y = &(x)->next; 1100f66f451Sopenharmony_ci x = *y; 1110f66f451Sopenharmony_ci } 1120f66f451Sopenharmony_ci 1130f66f451Sopenharmony_ci //create a new node 1140f66f451Sopenharmony_ci if (!x) { 1150f66f451Sopenharmony_ci x = xzalloc(sizeof(*x)); 1160f66f451Sopenharmony_ci x->command = xstrdup(command); 1170f66f451Sopenharmony_ci x->terminal_name = xstrdup(term); 1180f66f451Sopenharmony_ci } 1190f66f451Sopenharmony_ci x->action = action; 1200f66f451Sopenharmony_ci *y = x; 1210f66f451Sopenharmony_ci} 1220f66f451Sopenharmony_ci 1230f66f451Sopenharmony_cistatic void parse_inittab(void) 1240f66f451Sopenharmony_ci{ 1250f66f451Sopenharmony_ci char *line = 0; 1260f66f451Sopenharmony_ci size_t allocated_length = 0; 1270f66f451Sopenharmony_ci int line_number = 0; 1280f66f451Sopenharmony_ci char *act_name = "sysinit\0wait\0once\0respawn\0askfirst\0ctrlaltdel\0" 1290f66f451Sopenharmony_ci "shutdown\0restart\0"; 1300f66f451Sopenharmony_ci FILE *fp = fopen("/etc/inittab", "r"); 1310f66f451Sopenharmony_ci 1320f66f451Sopenharmony_ci if (!fp) { 1330f66f451Sopenharmony_ci error_msg("Unable to open /etc/inittab. Using Default inittab"); 1340f66f451Sopenharmony_ci add_new_action(SYSINIT, "/etc/init.d/rcS", ""); 1350f66f451Sopenharmony_ci add_new_action(RESPAWN, "/sbin/getty -n -l /bin/sh -L 115200 tty1 vt100", ""); 1360f66f451Sopenharmony_ci return; 1370f66f451Sopenharmony_ci } 1380f66f451Sopenharmony_ci 1390f66f451Sopenharmony_ci while (getline(&line, &allocated_length, fp) > 0) { 1400f66f451Sopenharmony_ci char *p = line, *x, *tty_name = 0, *command = 0, *extracted_token, *tmp; 1410f66f451Sopenharmony_ci int action = 0, token_count = 0, i; 1420f66f451Sopenharmony_ci 1430f66f451Sopenharmony_ci if ((x = strchr(p, '#'))) *x = '\0'; 1440f66f451Sopenharmony_ci line_number++; 1450f66f451Sopenharmony_ci action = 0; 1460f66f451Sopenharmony_ci 1470f66f451Sopenharmony_ci while ((extracted_token = strsep(&p,":"))) { 1480f66f451Sopenharmony_ci token_count++; 1490f66f451Sopenharmony_ci switch (token_count) { 1500f66f451Sopenharmony_ci case 1: 1510f66f451Sopenharmony_ci if (*extracted_token) { 1520f66f451Sopenharmony_ci if (!strncmp(extracted_token, "/dev/", 5)) 1530f66f451Sopenharmony_ci tty_name = xmprintf("%s",extracted_token); 1540f66f451Sopenharmony_ci else tty_name = xmprintf("/dev/%s",extracted_token); 1550f66f451Sopenharmony_ci } else tty_name = xstrdup(""); 1560f66f451Sopenharmony_ci break; 1570f66f451Sopenharmony_ci case 2: 1580f66f451Sopenharmony_ci break; 1590f66f451Sopenharmony_ci case 3: 1600f66f451Sopenharmony_ci for (tmp = act_name, i = 0; *tmp; i++, tmp += strlen(tmp) +1) { 1610f66f451Sopenharmony_ci if (!strcmp(tmp, extracted_token)) { 1620f66f451Sopenharmony_ci action = 1 << i; 1630f66f451Sopenharmony_ci break; 1640f66f451Sopenharmony_ci } 1650f66f451Sopenharmony_ci } 1660f66f451Sopenharmony_ci if (!*tmp) error_msg("Invalid action at line number %d ---- ignoring",line_number); 1670f66f451Sopenharmony_ci break; 1680f66f451Sopenharmony_ci case 4: 1690f66f451Sopenharmony_ci command = xstrdup(extracted_token); 1700f66f451Sopenharmony_ci break; 1710f66f451Sopenharmony_ci default: 1720f66f451Sopenharmony_ci error_msg("Bad inittab entry at line %d", line_number); 1730f66f451Sopenharmony_ci break; 1740f66f451Sopenharmony_ci } 1750f66f451Sopenharmony_ci } //while token 1760f66f451Sopenharmony_ci 1770f66f451Sopenharmony_ci if (token_count == 4 && action) add_new_action(action, command, tty_name); 1780f66f451Sopenharmony_ci free(tty_name); 1790f66f451Sopenharmony_ci free(command); 1800f66f451Sopenharmony_ci } 1810f66f451Sopenharmony_ci free(line); 1820f66f451Sopenharmony_ci fclose(fp); 1830f66f451Sopenharmony_ci} 1840f66f451Sopenharmony_ci 1850f66f451Sopenharmony_cistatic void reload_inittab(void) 1860f66f451Sopenharmony_ci{ 1870f66f451Sopenharmony_ci // Remove all inactive actions, then reload /etc/inittab 1880f66f451Sopenharmony_ci struct action_list_seed **y; 1890f66f451Sopenharmony_ci y = &action_list_pointer; 1900f66f451Sopenharmony_ci while (*y) { 1910f66f451Sopenharmony_ci if (!(*y)->pid) { 1920f66f451Sopenharmony_ci struct action_list_seed *x = *y; 1930f66f451Sopenharmony_ci free(x->terminal_name); 1940f66f451Sopenharmony_ci free(x->command); 1950f66f451Sopenharmony_ci *y = (*y)->next; 1960f66f451Sopenharmony_ci free(x); 1970f66f451Sopenharmony_ci continue; 1980f66f451Sopenharmony_ci } 1990f66f451Sopenharmony_ci y = &(*y)->next; 2000f66f451Sopenharmony_ci } 2010f66f451Sopenharmony_ci parse_inittab(); 2020f66f451Sopenharmony_ci} 2030f66f451Sopenharmony_ci 2040f66f451Sopenharmony_cistatic void run_command(char *command) 2050f66f451Sopenharmony_ci{ 2060f66f451Sopenharmony_ci char *final_command[128]; 2070f66f451Sopenharmony_ci int hyphen = (command[0]=='-'); 2080f66f451Sopenharmony_ci 2090f66f451Sopenharmony_ci command = command + hyphen; 2100f66f451Sopenharmony_ci if (!strpbrk(command, "?<>'\";[]{}\\|=()*&^$!`~")) { 2110f66f451Sopenharmony_ci char *next_command; 2120f66f451Sopenharmony_ci char *extracted_command; 2130f66f451Sopenharmony_ci int x = 0; 2140f66f451Sopenharmony_ci 2150f66f451Sopenharmony_ci next_command = strncpy(toybuf, command - hyphen, sizeof(toybuf)); 2160f66f451Sopenharmony_ci next_command[sizeof(toybuf) - 1] = toybuf[sizeof(toybuf) - 1 ] = '\0'; 2170f66f451Sopenharmony_ci command = next_command + hyphen; 2180f66f451Sopenharmony_ci while ((extracted_command = strsep(&next_command," \t"))) { 2190f66f451Sopenharmony_ci if (*extracted_command) { 2200f66f451Sopenharmony_ci final_command[x] = extracted_command; 2210f66f451Sopenharmony_ci x++; 2220f66f451Sopenharmony_ci } 2230f66f451Sopenharmony_ci } 2240f66f451Sopenharmony_ci final_command[x] = NULL; 2250f66f451Sopenharmony_ci } else { 2260f66f451Sopenharmony_ci snprintf(toybuf, sizeof(toybuf), "exec %s", command); 2270f66f451Sopenharmony_ci command = "-/bin/sh"+1; 2280f66f451Sopenharmony_ci final_command[0] = ("-/bin/sh"+!hyphen); 2290f66f451Sopenharmony_ci final_command[1] = "-c"; 2300f66f451Sopenharmony_ci final_command[2] = toybuf; 2310f66f451Sopenharmony_ci final_command[3] = NULL; 2320f66f451Sopenharmony_ci } 2330f66f451Sopenharmony_ci if (hyphen) ioctl(0, TIOCSCTTY, 0); 2340f66f451Sopenharmony_ci execvp(command, final_command); 2350f66f451Sopenharmony_ci error_msg("unable to run %s",command); 2360f66f451Sopenharmony_ci} 2370f66f451Sopenharmony_ci 2380f66f451Sopenharmony_ci//runs all same type of actions 2390f66f451Sopenharmony_cistatic pid_t final_run(struct action_list_seed *x) 2400f66f451Sopenharmony_ci{ 2410f66f451Sopenharmony_ci pid_t pid; 2420f66f451Sopenharmony_ci int fd; 2430f66f451Sopenharmony_ci sigset_t signal_set; 2440f66f451Sopenharmony_ci 2450f66f451Sopenharmony_ci sigfillset(&signal_set); 2460f66f451Sopenharmony_ci sigprocmask(SIG_BLOCK, &signal_set, NULL); 2470f66f451Sopenharmony_ci if (x->action & ASKFIRST) pid = fork(); 2480f66f451Sopenharmony_ci else pid = vfork(); 2490f66f451Sopenharmony_ci 2500f66f451Sopenharmony_ci if (pid > 0) { 2510f66f451Sopenharmony_ci //parent process or error 2520f66f451Sopenharmony_ci //unblock the signals 2530f66f451Sopenharmony_ci sigfillset(&signal_set); 2540f66f451Sopenharmony_ci sigprocmask(SIG_UNBLOCK, &signal_set, NULL); 2550f66f451Sopenharmony_ci 2560f66f451Sopenharmony_ci return pid; 2570f66f451Sopenharmony_ci } else if (pid < 0) { 2580f66f451Sopenharmony_ci perror_msg("fork fail"); 2590f66f451Sopenharmony_ci sleep(1); 2600f66f451Sopenharmony_ci return 0; 2610f66f451Sopenharmony_ci } 2620f66f451Sopenharmony_ci 2630f66f451Sopenharmony_ci //new born child process 2640f66f451Sopenharmony_ci sigset_t signal_set_c; 2650f66f451Sopenharmony_ci sigfillset(&signal_set_c); 2660f66f451Sopenharmony_ci sigprocmask(SIG_UNBLOCK, &signal_set_c, NULL); 2670f66f451Sopenharmony_ci setsid(); //new session 2680f66f451Sopenharmony_ci 2690f66f451Sopenharmony_ci if (x->terminal_name[0]) { 2700f66f451Sopenharmony_ci close(0); 2710f66f451Sopenharmony_ci fd = open(x->terminal_name, (O_RDWR|O_NONBLOCK),0600); 2720f66f451Sopenharmony_ci if (fd != 0) { 2730f66f451Sopenharmony_ci error_msg("Unable to open %s,%s\n", x->terminal_name, strerror(errno)); 2740f66f451Sopenharmony_ci _exit(EXIT_FAILURE); 2750f66f451Sopenharmony_ci } else { 2760f66f451Sopenharmony_ci dup2(0, 1); 2770f66f451Sopenharmony_ci dup2(0, 2); 2780f66f451Sopenharmony_ci } 2790f66f451Sopenharmony_ci } 2800f66f451Sopenharmony_ci reset_term(0); 2810f66f451Sopenharmony_ci run_command(x->command); 2820f66f451Sopenharmony_ci _exit(-1); 2830f66f451Sopenharmony_ci} 2840f66f451Sopenharmony_ci 2850f66f451Sopenharmony_cistatic struct action_list_seed* mark_as_terminated_process(pid_t pid) 2860f66f451Sopenharmony_ci{ 2870f66f451Sopenharmony_ci struct action_list_seed *x; 2880f66f451Sopenharmony_ci 2890f66f451Sopenharmony_ci if (pid > 0) { 2900f66f451Sopenharmony_ci for (x = action_list_pointer; x; x = x->next) { 2910f66f451Sopenharmony_ci if (x->pid == pid) { 2920f66f451Sopenharmony_ci x->pid = 0; 2930f66f451Sopenharmony_ci return x; 2940f66f451Sopenharmony_ci } 2950f66f451Sopenharmony_ci } 2960f66f451Sopenharmony_ci } 2970f66f451Sopenharmony_ci 2980f66f451Sopenharmony_ci return NULL; 2990f66f451Sopenharmony_ci} 3000f66f451Sopenharmony_ci 3010f66f451Sopenharmony_cistatic void waitforpid(pid_t pid) 3020f66f451Sopenharmony_ci{ 3030f66f451Sopenharmony_ci if (pid <= 0) return; 3040f66f451Sopenharmony_ci 3050f66f451Sopenharmony_ci while (!kill(pid, 0)) mark_as_terminated_process(wait(NULL)); 3060f66f451Sopenharmony_ci} 3070f66f451Sopenharmony_ci 3080f66f451Sopenharmony_cistatic void run_action_from_list(int action) 3090f66f451Sopenharmony_ci{ 3100f66f451Sopenharmony_ci pid_t pid; 3110f66f451Sopenharmony_ci struct action_list_seed *x = action_list_pointer; 3120f66f451Sopenharmony_ci 3130f66f451Sopenharmony_ci for (; x; x = x->next) { 3140f66f451Sopenharmony_ci if (!(x->action & action)) continue; 3150f66f451Sopenharmony_ci if (x->action & (SHUTDOWN|ONCE|SYSINIT|CTRLALTDEL|WAIT)) { 3160f66f451Sopenharmony_ci pid = final_run(x); 3170f66f451Sopenharmony_ci if (!pid) return; 3180f66f451Sopenharmony_ci if (x->action & (SHUTDOWN|SYSINIT|CTRLALTDEL|WAIT)) waitforpid(pid); 3190f66f451Sopenharmony_ci } 3200f66f451Sopenharmony_ci if (x->action & (ASKFIRST|RESPAWN)) 3210f66f451Sopenharmony_ci if (!(x->pid)) x->pid = final_run(x); 3220f66f451Sopenharmony_ci } 3230f66f451Sopenharmony_ci } 3240f66f451Sopenharmony_ci 3250f66f451Sopenharmony_cistatic void set_default(void) 3260f66f451Sopenharmony_ci{ 3270f66f451Sopenharmony_ci sigset_t signal_set_c; 3280f66f451Sopenharmony_ci 3290f66f451Sopenharmony_ci sigatexit(SIG_DFL); 3300f66f451Sopenharmony_ci sigfillset(&signal_set_c); 3310f66f451Sopenharmony_ci sigprocmask(SIG_UNBLOCK,&signal_set_c, NULL); 3320f66f451Sopenharmony_ci 3330f66f451Sopenharmony_ci run_action_from_list(SHUTDOWN); 3340f66f451Sopenharmony_ci error_msg("The system is going down NOW!"); 3350f66f451Sopenharmony_ci kill(-1, SIGTERM); 3360f66f451Sopenharmony_ci error_msg("Sent SIGTERM to all processes"); 3370f66f451Sopenharmony_ci sync(); 3380f66f451Sopenharmony_ci sleep(1); 3390f66f451Sopenharmony_ci kill(-1,SIGKILL); 3400f66f451Sopenharmony_ci sync(); 3410f66f451Sopenharmony_ci} 3420f66f451Sopenharmony_ci 3430f66f451Sopenharmony_cistatic void halt_poweroff_reboot_handler(int sig_no) 3440f66f451Sopenharmony_ci{ 3450f66f451Sopenharmony_ci unsigned int reboot_magic_no = 0; 3460f66f451Sopenharmony_ci pid_t pid; 3470f66f451Sopenharmony_ci 3480f66f451Sopenharmony_ci set_default(); 3490f66f451Sopenharmony_ci 3500f66f451Sopenharmony_ci switch (sig_no) { 3510f66f451Sopenharmony_ci case SIGUSR1: 3520f66f451Sopenharmony_ci error_msg("Requesting system halt"); 3530f66f451Sopenharmony_ci reboot_magic_no=RB_HALT_SYSTEM; 3540f66f451Sopenharmony_ci break; 3550f66f451Sopenharmony_ci case SIGUSR2: 3560f66f451Sopenharmony_ci error_msg("Requesting system poweroff"); 3570f66f451Sopenharmony_ci reboot_magic_no=RB_POWER_OFF; 3580f66f451Sopenharmony_ci break; 3590f66f451Sopenharmony_ci case SIGTERM: 3600f66f451Sopenharmony_ci error_msg("Requesting system reboot"); 3610f66f451Sopenharmony_ci reboot_magic_no=RB_AUTOBOOT; 3620f66f451Sopenharmony_ci break; 3630f66f451Sopenharmony_ci default: 3640f66f451Sopenharmony_ci break; 3650f66f451Sopenharmony_ci } 3660f66f451Sopenharmony_ci 3670f66f451Sopenharmony_ci sleep(1); 3680f66f451Sopenharmony_ci pid = vfork(); 3690f66f451Sopenharmony_ci 3700f66f451Sopenharmony_ci if (pid == 0) { 3710f66f451Sopenharmony_ci reboot(reboot_magic_no); 3720f66f451Sopenharmony_ci _exit(EXIT_SUCCESS); 3730f66f451Sopenharmony_ci } 3740f66f451Sopenharmony_ci 3750f66f451Sopenharmony_ci while(1) sleep(1); 3760f66f451Sopenharmony_ci} 3770f66f451Sopenharmony_ci 3780f66f451Sopenharmony_cistatic void restart_init_handler(int sig_no) 3790f66f451Sopenharmony_ci{ 3800f66f451Sopenharmony_ci struct action_list_seed *x; 3810f66f451Sopenharmony_ci pid_t pid; 3820f66f451Sopenharmony_ci int fd; 3830f66f451Sopenharmony_ci 3840f66f451Sopenharmony_ci for (x = action_list_pointer; x; x = x->next) { 3850f66f451Sopenharmony_ci if (!(x->action & RESTART)) continue; 3860f66f451Sopenharmony_ci 3870f66f451Sopenharmony_ci set_default(); 3880f66f451Sopenharmony_ci 3890f66f451Sopenharmony_ci if (x->terminal_name[0]) { 3900f66f451Sopenharmony_ci close(0); 3910f66f451Sopenharmony_ci fd = open(x->terminal_name, (O_RDWR|O_NONBLOCK),0600); 3920f66f451Sopenharmony_ci 3930f66f451Sopenharmony_ci if (fd != 0) { 3940f66f451Sopenharmony_ci error_msg("Unable to open %s,%s\n", x->terminal_name, strerror(errno)); 3950f66f451Sopenharmony_ci sleep(1); 3960f66f451Sopenharmony_ci pid = vfork(); 3970f66f451Sopenharmony_ci 3980f66f451Sopenharmony_ci if (pid == 0) { 3990f66f451Sopenharmony_ci reboot(RB_HALT_SYSTEM); 4000f66f451Sopenharmony_ci _exit(EXIT_SUCCESS); 4010f66f451Sopenharmony_ci } 4020f66f451Sopenharmony_ci 4030f66f451Sopenharmony_ci while(1) sleep(1); 4040f66f451Sopenharmony_ci } else { 4050f66f451Sopenharmony_ci dup2(0, 1); 4060f66f451Sopenharmony_ci dup2(0, 2); 4070f66f451Sopenharmony_ci reset_term(0); 4080f66f451Sopenharmony_ci run_command(x->command); 4090f66f451Sopenharmony_ci } 4100f66f451Sopenharmony_ci } 4110f66f451Sopenharmony_ci } 4120f66f451Sopenharmony_ci} 4130f66f451Sopenharmony_ci 4140f66f451Sopenharmony_cistatic void catch_signal(int sig_no) 4150f66f451Sopenharmony_ci{ 4160f66f451Sopenharmony_ci caught_signal = sig_no; 4170f66f451Sopenharmony_ci error_msg("signal seen: %d", sig_no); 4180f66f451Sopenharmony_ci} 4190f66f451Sopenharmony_ci 4200f66f451Sopenharmony_cistatic void pause_handler(int sig_no) 4210f66f451Sopenharmony_ci{ 4220f66f451Sopenharmony_ci int signal_backup,errno_backup; 4230f66f451Sopenharmony_ci pid_t pid; 4240f66f451Sopenharmony_ci 4250f66f451Sopenharmony_ci errno_backup = errno; 4260f66f451Sopenharmony_ci signal_backup = caught_signal; 4270f66f451Sopenharmony_ci xsignal(SIGCONT, catch_signal); 4280f66f451Sopenharmony_ci 4290f66f451Sopenharmony_ci while(1) { 4300f66f451Sopenharmony_ci if (caught_signal == SIGCONT) break; 4310f66f451Sopenharmony_ci do pid = waitpid(-1,NULL,WNOHANG); while((pid==-1) && (errno=EINTR)); 4320f66f451Sopenharmony_ci mark_as_terminated_process(pid); 4330f66f451Sopenharmony_ci sleep(1); 4340f66f451Sopenharmony_ci } 4350f66f451Sopenharmony_ci 4360f66f451Sopenharmony_ci signal(SIGCONT, SIG_DFL); 4370f66f451Sopenharmony_ci errno = errno_backup; 4380f66f451Sopenharmony_ci caught_signal = signal_backup; 4390f66f451Sopenharmony_ci} 4400f66f451Sopenharmony_ci 4410f66f451Sopenharmony_cistatic int check_if_pending_signals(void) 4420f66f451Sopenharmony_ci{ 4430f66f451Sopenharmony_ci int signal_caught = 0; 4440f66f451Sopenharmony_ci 4450f66f451Sopenharmony_ci while(1) { 4460f66f451Sopenharmony_ci int sig = caught_signal; 4470f66f451Sopenharmony_ci if (!sig) return signal_caught; 4480f66f451Sopenharmony_ci caught_signal = 0; 4490f66f451Sopenharmony_ci signal_caught = 1; 4500f66f451Sopenharmony_ci if (sig == SIGINT) run_action_from_list(CTRLALTDEL); 4510f66f451Sopenharmony_ci else if (sig == SIGHUP) { 4520f66f451Sopenharmony_ci error_msg("reloading inittab"); 4530f66f451Sopenharmony_ci reload_inittab(); 4540f66f451Sopenharmony_ci } 4550f66f451Sopenharmony_ci } 4560f66f451Sopenharmony_ci} 4570f66f451Sopenharmony_ci 4580f66f451Sopenharmony_civoid init_main(void) 4590f66f451Sopenharmony_ci{ 4600f66f451Sopenharmony_ci struct sigaction sig_act; 4610f66f451Sopenharmony_ci 4620f66f451Sopenharmony_ci if (getpid() != 1) error_exit("Already running"); 4630f66f451Sopenharmony_ci printf("Started init\n"); 4640f66f451Sopenharmony_ci initialize_console(); 4650f66f451Sopenharmony_ci reset_term(0); 4660f66f451Sopenharmony_ci 4670f66f451Sopenharmony_ci if (chdir("/")) perror_exit("Can't cd to /"); 4680f66f451Sopenharmony_ci setsid(); 4690f66f451Sopenharmony_ci 4700f66f451Sopenharmony_ci putenv("HOME=/"); 4710f66f451Sopenharmony_ci putenv("PATH=/sbin:/usr/sbin:/bin:/usr/bin"); 4720f66f451Sopenharmony_ci putenv("SHELL=/bin/sh"); 4730f66f451Sopenharmony_ci putenv("USER=root"); 4740f66f451Sopenharmony_ci 4750f66f451Sopenharmony_ci parse_inittab(); 4760f66f451Sopenharmony_ci xsignal(SIGUSR1, halt_poweroff_reboot_handler);//halt 4770f66f451Sopenharmony_ci xsignal(SIGUSR2, halt_poweroff_reboot_handler);//poweroff 4780f66f451Sopenharmony_ci xsignal(SIGTERM, halt_poweroff_reboot_handler);//reboot 4790f66f451Sopenharmony_ci xsignal(SIGQUIT, restart_init_handler);//restart init 4800f66f451Sopenharmony_ci memset(&sig_act, 0, sizeof(sig_act)); 4810f66f451Sopenharmony_ci sigfillset(&sig_act.sa_mask); 4820f66f451Sopenharmony_ci sigdelset(&sig_act.sa_mask, SIGCONT); 4830f66f451Sopenharmony_ci sig_act.sa_handler = pause_handler; 4840f66f451Sopenharmony_ci sigaction(SIGTSTP, &sig_act, NULL); 4850f66f451Sopenharmony_ci memset(&sig_act, 0, sizeof(sig_act)); 4860f66f451Sopenharmony_ci sig_act.sa_handler = catch_signal; 4870f66f451Sopenharmony_ci sigaction(SIGINT, &sig_act, NULL); 4880f66f451Sopenharmony_ci sigaction(SIGHUP, &sig_act, NULL); 4890f66f451Sopenharmony_ci run_action_from_list(SYSINIT); 4900f66f451Sopenharmony_ci check_if_pending_signals(); 4910f66f451Sopenharmony_ci run_action_from_list(WAIT); 4920f66f451Sopenharmony_ci check_if_pending_signals(); 4930f66f451Sopenharmony_ci run_action_from_list(ONCE); 4940f66f451Sopenharmony_ci while (1) { 4950f66f451Sopenharmony_ci int suspected_WNOHANG = check_if_pending_signals(); 4960f66f451Sopenharmony_ci 4970f66f451Sopenharmony_ci run_action_from_list(RESPAWN | ASKFIRST); 4980f66f451Sopenharmony_ci suspected_WNOHANG = suspected_WNOHANG|check_if_pending_signals(); 4990f66f451Sopenharmony_ci sleep(1);//let cpu breath 5000f66f451Sopenharmony_ci suspected_WNOHANG = suspected_WNOHANG|check_if_pending_signals(); 5010f66f451Sopenharmony_ci if (suspected_WNOHANG) suspected_WNOHANG=WNOHANG; 5020f66f451Sopenharmony_ci 5030f66f451Sopenharmony_ci while(1) { 5040f66f451Sopenharmony_ci pid_t pid = waitpid(-1, NULL, suspected_WNOHANG); 5050f66f451Sopenharmony_ci 5060f66f451Sopenharmony_ci if (pid <= 0) break; 5070f66f451Sopenharmony_ci mark_as_terminated_process(pid); 5080f66f451Sopenharmony_ci suspected_WNOHANG = WNOHANG; 5090f66f451Sopenharmony_ci } 5100f66f451Sopenharmony_ci } 5110f66f451Sopenharmony_ci} 512