/* * Handle bootstrap transition to configured runlevel, start TTYs * * This is the final stage of bootstrap. It changes to the default * (configured) runlevel, calls all external start scripts and final * bootstrap hooks before bringing up TTYs. * * We must ensure that all declared `task [S]` and `run [S]` jobs in * finit.conf, or *.conf in finit.d/, run to completion before we * finalize the bootstrap process by calling this function. */ static void finalize(void) { /* * Run startup scripts in the runparts directory, if any. */ if (runparts && fisdir(runparts) && !rescue) run_parts(runparts, NULL); /* * Start all tasks/services in the configured runlevel */ _d("Change to default runlevel, start all services ..."); service_runlevel(cfglevel); /* Clean up bootstrap-only tasks/services that never started */ _d("Clean up all bootstrap-only tasks/services ..."); svc_prune_bootstrap(); /* All services/tasks/inetd/etc. in configure runlevel have started */ _d("Running svc up hooks ..."); plugin_run_hooks(HOOK_SVC_UP); service_step_all(SVC_TYPE_ANY); /* Convenient SysV compat for when you just don't care ... */ if (!access(FINIT_RC_LOCAL, X_OK) && !rescue) run_interactive(FINIT_RC_LOCAL, "Calling %s", FINIT_RC_LOCAL); /* Hooks that should run at the very end */ _d("Calling all system up hooks ..."); plugin_run_hooks(HOOK_SYSTEM_UP); service_step_all(SVC_TYPE_ANY); /* Enable silent mode before starting TTYs */ _d("Going silent ..."); log_silent(); /* Delayed start of TTYs at bootstrap */ _d("Launching all getty services ..."); tty_runlevel(); }
/* * SIGTERM: BusyBox style reboot */ static void sigterm_cb(uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events)) { _d("..."); halt = SHUT_REBOOT; service_runlevel(6); }
static void cb(uev_t *w, void *UNUSED(arg), int UNUSED(events)) { int sd; struct init_request rq; sd = accept(w->fd, NULL, NULL); if (sd < 0) { _pe("Failed serving API request"); return; } while (1) { int result = 0; ssize_t len; len = read(sd, &rq, sizeof(rq)); if (len <= 0) { if (-1 == len) { if (EINTR == errno) continue; if (EAGAIN == errno) break; _e("Failed reading initctl request, error %d: %s", errno, strerror(errno)); } break; } if (rq.magic != INIT_MAGIC || len != sizeof(rq)) { _e("Invalid initctl request."); break; } switch (rq.cmd) { case INIT_CMD_RUNLVL: switch (rq.runlevel) { case '0': _d("Halting system (SIGUSR2)"); do_shutdown(SIGUSR2); break; case 's': case 'S': _d("Cannot enter bootstrap after boot ..."); rq.runlevel = '1'; /* Fall through to regular processing */ case '1'...'5': case '7'...'9': _d("Setting new runlevel %c", rq.runlevel); service_runlevel(rq.runlevel - '0'); break; case '6': _d("Rebooting system (SIGUSR1)"); do_shutdown(SIGUSR1); break; default: _d("Unsupported runlevel: %d", rq.runlevel); break; } break; case INIT_CMD_DEBUG: debug = !debug; if (debug) silent = 0; else silent = quiet ? 1 : SILENT_MODE; break; case INIT_CMD_RELOAD: /* 'init q' and 'initctl reload' */ service_reload_dynamic(); break; case INIT_CMD_START_SVC: result = do_start(rq.data, sizeof(rq.data)); break; case INIT_CMD_STOP_SVC: result = do_pause(rq.data, sizeof(rq.data)); break; case INIT_CMD_RESTART_SVC: result = do_restart(rq.data, sizeof(rq.data)); break; #ifndef INETD_DISABLED case INIT_CMD_QUERY_INETD: result = do_query_inetd(rq.data, sizeof(rq.data)); break; #endif case INIT_CMD_EMIT: result = do_handle_emit(rq.data, sizeof(rq.data)); break; case INIT_CMD_GET_RUNLEVEL: rq.runlevel = runlevel; result = 0; break; case INIT_CMD_ACK: _d("Client failed reading ACK."); goto leave; default: _d("Unsupported cmd: %d", rq.cmd); break; } if (result) rq.cmd = INIT_CMD_NACK; else rq.cmd = INIT_CMD_ACK; len = write(sd, &rq, sizeof(rq)); if (len != sizeof(rq)) _d("Failed sending ACK/NACK back to client."); } leave: close(sd); }
/* * SIGUSR2: BusyBox style poweroff */ static void sigusr2_cb(uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events)) { _d("..."); halt = SHUT_OFF; service_runlevel(0); }
/* Standard reboot/shutdown utilities talk to init using /dev/initctl. * We should check if the fifo was recreated and reopen it. */ static void parse(void *UNUSED(arg), int fd, int UNUSED(events)) { struct init_request rq; while (1) { ssize_t len = read(fd, &rq, sizeof(rq)); if (len <= 0) { if (-1 == len) { if (EINTR == errno) continue; if (EAGAIN == errno) break; _e("Failed reading initctl request, error %d: %s", errno, strerror(errno)); } _d("Nothing to do, bailing out."); break; } if (rq.magic != INIT_MAGIC || len != sizeof(rq)) { _e("Invalid initctl request."); break; } switch (rq.cmd) { case INIT_CMD_RUNLVL: switch (rq.runlevel) { case '0': _d("Halting system (SIGUSR2)"); do_shutdown(SIGUSR2); break; case 's': case 'S': _d("Cannot enter bootstrap after boot ..."); rq.runlevel = '1'; /* Fall through to regular processing */ case '1'...'5': case '7'...'9': _d("Setting new runlevel %c", rq.runlevel); service_runlevel(rq.runlevel - '0'); break; case '6': _d("Rebooting system (SIGUSR1)"); do_shutdown(SIGUSR1); break; default: _d("Unsupported runlevel: %d", rq.runlevel); break; } break; case INIT_CMD_RELOAD: service_reload_dynamic(); break; default: _d("Unsupported cmd: %d", rq.cmd); break; } } close(fd); fifo_open(); }