void procd_shutdown(int event) { DEBUG(1, "Shutting down system with event %x\n", event); reboot_event = event; state = STATE_SHUTDOWN; state_enter(); }
/** * Undo a state_protect call. **/ static void state_unprotect(state_t *state, int needed_it) { if (! needed_it) return; state_enter(state); state_ungrab(state); }
/** * Compile the state stack into a single state and enter it. **/ static void state_stack_aggregate(void) { state_t *state; size_t i; if (! state_stack_size) return; if (state_stack_size == 1) { state_enter(state_stack[0]); return; } state = state_create(); for (i = state_stack_size; i; i--) state_underlay(state, state_stack[i - 1]); state_enter(state); state_ungrab(state); }
/** * Protect the state in case it is the current state and we need to modify it. **/ static void state_protect(state_t *state, int *needs_it) { state_t *tmp; *needs_it = (state == current_state); if (! *needs_it) return; state_grab(state); tmp = state_clone(state); state_enter(tmp); state_ungrab(tmp); }
void procd_state_next(void) { DEBUG(2, "Change state %d -> %d\n", state, state + 1); state++; state_enter(); }
static void set_console(void) { const char* tty; char* split; char line[ 20 ]; const char* try[] = { "tty0", "console", NULL }; /* Try the most common outputs */ int f, i = 0; tty = get_cmdline_val("console",line,sizeof(line)); if (tty != NULL) { split = strchr(tty, ','); if ( split != NULL ) *split = '\0'; } else { // Try a default tty=try[i]; i++; } if (chdir("/dev")) { ERROR("failed to change dir to /dev\n"); return; } while (tty!=NULL) { f = open(tty, O_RDONLY); if (f >= 0) { close(f); break; } tty=try[i]; i++; } if (chdir("/")) ERROR("failed to change dir to /\n"); if (tty != NULL) set_stdio(tty); } static void state_enter(void) { char ubus_cmd[] = "/sbin/ubusd"; switch (state) { case STATE_EARLY: LOG("- early -\n"); watchdog_init(0); hotplug("/etc/hotplug.json"); procd_coldplug(); break; case STATE_UBUS: // try to reopen incase the wdt was not available before coldplug watchdog_init(0); set_stdio("console"); LOG("- ubus -\n"); procd_connect_ubus(); service_start_early("ubus", ubus_cmd); break; case STATE_INIT: LOG("- init -\n"); procd_inittab(); procd_inittab_run("respawn"); procd_inittab_run("askconsole"); procd_inittab_run("askfirst"); procd_inittab_run("sysinit"); // switch to syslog log channel ulog_open(ULOG_SYSLOG, LOG_DAEMON, "procd"); break; case STATE_RUNNING: LOG("- init complete -\n"); break; case STATE_SHUTDOWN: /* Redirect output to the console for the users' benefit */ set_console(); LOG("- shutdown -\n"); procd_inittab_run("shutdown"); sync(); break; case STATE_HALT: // To prevent killed processes from interrupting the sleep signal(SIGCHLD, SIG_IGN); LOG("- SIGTERM processes -\n"); kill(-1, SIGTERM); sync(); sleep(1); LOG("- SIGKILL processes -\n"); kill(-1, SIGKILL); sync(); sleep(1); #ifndef DISABLE_INIT if (reboot_event == RB_POWER_OFF) LOG("- power down -\n"); else LOG("- reboot -\n"); /* Allow time for last message to reach serial console, etc */ sleep(1); /* We have to fork here, since the kernel calls do_exit(EXIT_SUCCESS) * in linux/kernel/sys.c, which can cause the machine to panic when * the init process exits... */ if (!vfork( )) { /* child */ reboot(reboot_event); _exit(EXIT_SUCCESS); } while (1) sleep(1); #else exit(0); #endif break; default: ERROR("Unhandled state %d\n", state); return; }; } void procd_state_next(void) { DEBUG(4, "Change state %d -> %d\n", state, state + 1); state++; state_enter(); } void procd_state_ubus_connect(void) { if (state == STATE_UBUS) procd_state_next(); } void procd_shutdown(int event) { if (state >= STATE_SHUTDOWN) return; DEBUG(2, "Shutting down system with event %x\n", event); reboot_event = event; state = STATE_SHUTDOWN; state_enter(); }