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