12 #include <sys/socket.h>
17 #include <sys/prctl.h>
19 #include <sys/reboot.h>
21 #if defined(__FreeBSD__) || defined(__DragonFly__)
22 #include <sys/procctl.h>
29 #include "dinit-log.h"
30 #include "dinit-socket.h"
33 * When running as the system init process, Dinit processes the following signals:
35 * SIGTERM - roll back services and then fork/exec /sbin/halt
36 * SIGINT - roll back services and then fork/exec /sbin/reboot
37 * SIGQUIT - exec() /sbin/shutdown without rolling back services
39 * It's an open question about whether Dinit should roll back services *before*
40 * running halt/reboot, since those commands should prompt rollback of services
41 * anyway. But it seems safe to do so, and it means the user can at least stop
42 * services even if the halt/reboot commands are unavailable for some reason.
45 using eventloop_t = dasynq::event_loop<dasynq::null_mutex>;
47 eventloop_t event_loop;
49 static void sigint_reboot_cb(eventloop_t &eloop) noexcept;
50 static void sigquit_cb(eventloop_t &eloop) noexcept;
51 static void sigterm_cb(eventloop_t &eloop) noexcept;
52 static void close_control_socket() noexcept;
53 static void wait_for_user_input() noexcept;
54 static void read_env_file(const char *);
56 static void control_socket_cb(eventloop_t *loop, int fd);
61 static dirload_service_set *services;
63 static bool am_system_init = false; // true if we are the system init process
65 static bool control_socket_open = false;
66 static bool external_log_open = false;
67 int active_control_conns = 0;
69 // Control socket path. We maintain a string (control_socket_str) in case we need
70 // to allocate storage, but control_socket_path is the authoritative value.
71 static const char *control_socket_path = "/dev/dinitctl";
72 static std::string control_socket_str;
74 static const char *env_file_path = "/etc/dinit/environment";
76 static const char *log_path = "/dev/log";
77 static bool log_is_syslog = true; // if false, log is a file
79 static const char *user_home_path = nullptr;
82 // Get user home (and set user_home_path). (The return may become invalid after
83 // changing the evironment (HOME variable) or using the getpwuid() function).
84 const char * get_user_home()
86 if (user_home_path == nullptr) {
87 user_home_path = getenv("HOME");
88 if (user_home_path == nullptr) {
89 struct passwd * pwuid_p = getpwuid(getuid());
90 if (pwuid_p != nullptr) {
91 user_home_path = pwuid_p->pw_dir;
95 return user_home_path;
100 class callback_signal_handler : public eventloop_t::signal_watcher_impl<callback_signal_handler>
102 using rearm = dasynq::rearm;
105 typedef void (*cb_func_t)(eventloop_t &);
111 callback_signal_handler() : cb_func(nullptr) { }
112 callback_signal_handler(cb_func_t pcb_func) : cb_func(pcb_func) { }
114 void setCbFunc(cb_func_t cb_func)
116 this->cb_func = cb_func;
119 rearm received(eventloop_t &eloop, int signo, siginfo_p siginfo)
126 class control_socket_watcher : public eventloop_t::fd_watcher_impl<control_socket_watcher>
128 using rearm = dasynq::rearm;
131 rearm fd_event(eventloop_t &loop, int fd, int flags) noexcept
133 control_socket_cb(&loop, fd);
138 // Simple timer used to limit the amount of time waiting for the log flush to complete (at shutdown)
139 class log_flush_timer_t : public eventloop_t::timer_impl<log_flush_timer_t>
141 using rearm = dasynq::rearm;
143 bool expired = false;
146 rearm timer_expiry(eventloop_t &, int expiry_count)
149 return rearm::DISARM;
158 control_socket_watcher control_socket_io;
159 log_flush_timer_t log_flush_timer;
162 int dinit_main(int argc, char **argv)
166 am_system_init = (getpid() == 1);
167 const char * service_dir = nullptr;
168 bool service_dir_dynamic = false; // service_dir dynamically allocated?
169 const char * env_file = nullptr;
170 string service_dir_str; // to hold storage for above if necessary
171 bool control_socket_path_set = false;
172 bool env_file_set = false;
174 // list of services to start
175 list<const char *> services_to_start;
177 // Arguments, if given, specify a list of services to start.
178 // If we are running as init (PID=1), the Linux kernel gives us any command line arguments it was given
179 // but didn't recognize, including "single" (usually for "boot to single user mode" aka just start the
180 // shell). We can treat them as service names. In the worst case we can't find any of the named
181 // services, and so we'll start the "boot" service by default.
183 for (int i = 1; i < argc; i++) {
184 if (argv[i][0] == '-') {
186 if (strcmp(argv[i], "--env-file") == 0 || strcmp(argv[i], "-e") == 0) {
192 cerr << "dinit: '--env-file' (-e) requires an argument" << endl;
195 else if (strcmp(argv[i], "--services-dir") == 0 || strcmp(argv[i], "-d") == 0) {
197 service_dir = argv[i];
200 cerr << "dinit: '--services-dir' (-d) requires an argument" << endl;
204 else if (strcmp(argv[i], "--system") == 0 || strcmp(argv[i], "-s") == 0) {
205 am_system_init = true;
207 else if (strcmp(argv[i], "--socket-path") == 0 || strcmp(argv[i], "-p") == 0) {
209 control_socket_path = argv[i];
210 control_socket_path_set = true;
213 cerr << "dinit: '--socket-path' (-p) requires an argument" << endl;
217 else if (strcmp(argv[i], "--log-file") == 0 || strcmp(argv[i], "-l") == 0) {
220 log_is_syslog = false;
223 cerr << "dinit: '--log-file' (-l) requires an argument" << endl;
227 else if (strcmp(argv[i], "--help") == 0) {
228 cout << "dinit, an init with dependency management" << endl;
229 cout << " --help display help" << endl;
230 cout << " --env-file <file>, -e <file>" << endl;
231 cout << " environment variable initialisation file" << endl;
232 cout << " --services-dir <dir>, -d <dir>" << endl;
233 cout << " set base directory for service description" << endl;
234 cout << " files (-d <dir>)" << endl;
235 cout << " --system, -s run as the system init process" << endl;
236 cout << " --socket-path <path>, -p <path>" << endl;
237 cout << " path to control socket" << endl;
238 cout << " <service-name> start service with name <service-name>" << endl;
243 if (! am_system_init) {
244 cerr << "dinit: Unrecognized option: " << argv[i] << endl;
251 // LILO puts "auto" on the kernel command line for unattended boots; we'll filter it.
252 if (! am_system_init || strcmp(argv[i], "auto") != 0) {
253 services_to_start.push_back(argv[i]);
256 services_to_start.push_back(argv[i]);
262 if (am_system_init) {
263 // setup STDIN, STDOUT, STDERR so that we can use them
264 int onefd = open("/dev/console", O_RDONLY, 0);
266 int twofd = open("/dev/console", O_RDWR, 0);
270 if (onefd > 2) close(onefd);
271 if (twofd > 2) close(twofd);
273 if (! env_file_set) {
274 env_file = env_file_path;
278 /* Set up signal handlers etc */
279 /* SIG_CHILD is ignored by default: good */
280 sigset_t sigwait_set;
281 sigemptyset(&sigwait_set);
282 sigaddset(&sigwait_set, SIGCHLD);
283 sigaddset(&sigwait_set, SIGINT);
284 sigaddset(&sigwait_set, SIGTERM);
285 if (am_system_init) sigaddset(&sigwait_set, SIGQUIT);
286 sigprocmask(SIG_BLOCK, &sigwait_set, NULL);
288 // Terminal access control signals - we block these so that dinit can't be
289 // suspended if it writes to the terminal after some other process has claimed
291 signal(SIGTSTP, SIG_IGN);
292 signal(SIGTTIN, SIG_IGN);
293 signal(SIGTTOU, SIG_IGN);
295 signal(SIGPIPE, SIG_IGN);
297 if (! am_system_init && ! control_socket_path_set) {
298 const char * userhome = get_user_home();
299 if (userhome != nullptr) {
300 control_socket_str = userhome;
301 control_socket_str += "/.dinitctl";
302 control_socket_path = control_socket_str.c_str();
306 /* service directory name */
307 if (service_dir == nullptr && ! am_system_init) {
308 const char * userhome = get_user_home();
309 if (userhome != nullptr) {
310 const char * user_home = get_user_home();
311 size_t user_home_len = strlen(user_home);
312 size_t dinit_d_len = strlen("/dinit.d");
313 size_t full_len = user_home_len + dinit_d_len + 1;
314 char *service_dir_w = new char[full_len];
315 std::memcpy(service_dir_w, user_home, user_home_len);
316 std::memcpy(service_dir_w + user_home_len, "/dinit.d", dinit_d_len);
317 service_dir_w[full_len - 1] = 0;
319 service_dir = service_dir_w;
320 service_dir_dynamic = true;
324 if (services_to_start.empty()) {
325 services_to_start.push_back("boot");
328 // Set up signal handlers
329 callback_signal_handler sigterm_watcher {sigterm_cb};
330 callback_signal_handler sigint_watcher;
331 callback_signal_handler sigquit_watcher;
333 if (am_system_init) {
334 sigint_watcher.setCbFunc(sigint_reboot_cb);
335 sigquit_watcher.setCbFunc(sigquit_cb);
338 sigint_watcher.setCbFunc(sigterm_cb);
341 sigint_watcher.add_watch(event_loop, SIGINT);
342 sigterm_watcher.add_watch(event_loop, SIGTERM);
344 if (am_system_init) {
345 // PID 1: SIGQUIT exec's shutdown
346 sigquit_watcher.add_watch(event_loop, SIGQUIT);
347 // As a user process, we instead just let SIGQUIT perform the default action.
350 // Try to open control socket (may fail due to readonly filesystem)
351 open_control_socket(false);
354 if (am_system_init) {
355 // Disable non-critical kernel output to console
356 klogctl(6 /* SYSLOG_ACTION_CONSOLE_OFF */, nullptr, 0);
357 // Make ctrl+alt+del combination send SIGINT to PID 1 (this process)
358 reboot(RB_DISABLE_CAD);
361 // Mark ourselves as a subreaper. This means that if a process we start double-forks, the
362 // orphaned child will re-parent to us rather than to PID 1 (although that could be us too).
363 prctl(PR_SET_CHILD_SUBREAPER, 1);
364 #elif defined(__FreeBSD__) || defined(__DragonFly__)
365 // Documentation (man page) for this kind of sucks. PROC_REAP_ACQUIRE "acquires the reaper status for
366 // the current process" but does that mean the first two arguments still need valid values to be
367 // supplied? We'll play it safe and explicitly target our own process:
368 procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL);
371 log_flush_timer.add_timer(event_loop, dasynq::clock_type::MONOTONIC);
373 bool add_all_service_dirs = false;
374 if (service_dir == nullptr) {
375 service_dir = "/etc/dinit.d";
376 add_all_service_dirs = true;
379 /* start requested services */
380 services = new dirload_service_set(service_dir, service_dir_dynamic);
381 if (add_all_service_dirs) {
382 services->add_service_dir("/usr/local/lib/dinit.d", false);
383 services->add_service_dir("/lib/dinit.d", false);
386 init_log(services, log_is_syslog);
387 if (am_system_init) {
388 log(loglevel_t::INFO, false, "starting system");
391 // Only try to set up the external log now if we aren't the system init. (If we are the
392 // system init, wait until the log service starts).
393 if (! am_system_init) setup_external_log();
395 if (env_file != nullptr) {
396 read_env_file(env_file);
399 for (auto svc : services_to_start) {
401 services->start_service(svc);
402 // Note in general if we fail to start a service we don't need any special error handling,
403 // since we either leave other services running or, if it was the only service, then no
404 // services will be running and we will process normally (reboot if system process,
405 // exit if user process).
407 catch (service_not_found &snf) {
408 log(loglevel_t::ERROR, snf.serviceName, ": Could not find service description.");
410 catch (service_load_exc &sle) {
411 log(loglevel_t::ERROR, sle.serviceName, ": ", sle.excDescription);
413 catch (std::bad_alloc &badalloce) {
414 log(loglevel_t::ERROR, "Out of memory when trying to start service: ", svc, ".");
421 // Process events until all services have terminated.
422 while (services->count_active_services() != 0) {
426 shutdown_type_t shutdown_type = services->get_shutdown_type();
428 if (am_system_init) {
429 log_msg_begin(loglevel_t::INFO, "No more active services.");
431 if (shutdown_type == shutdown_type_t::REBOOT) {
432 log_msg_end(" Will reboot.");
434 else if (shutdown_type == shutdown_type_t::HALT) {
435 log_msg_end(" Will halt.");
437 else if (shutdown_type == shutdown_type_t::POWEROFF) {
438 log_msg_end(" Will power down.");
441 log_msg_end(" Re-initiating boot sequence.");
445 log_flush_timer.arm_timer_rel(event_loop, timespec{5,0}); // 5 seconds
446 while (! is_log_flushed() && ! log_flush_timer.has_expired()) {
450 close_control_socket();
452 if (am_system_init) {
453 if (shutdown_type == shutdown_type_t::CONTINUE) {
454 // It could be that we started in single user mode, and the
455 // user has now exited the shell. We'll try and re-start the
458 services->start_service("boot");
459 goto event_loop; // yes, the "evil" goto
462 // Now what do we do? try to reboot, but wait for user ack to avoid boot loop.
463 log(loglevel_t::ERROR, "Could not start 'boot' service. Will attempt reboot.");
464 wait_for_user_input();
465 shutdown_type = shutdown_type_t::REBOOT;
469 const char * cmd_arg;
470 if (shutdown_type == shutdown_type_t::HALT) {
473 else if (shutdown_type == shutdown_type_t::REBOOT) {
481 // Fork and execute dinit-reboot.
482 execl("/sbin/shutdown", "/sbin/shutdown", "--system", cmd_arg, nullptr);
483 log(loglevel_t::ERROR, "Could not execute /sbin/shutdown: ", strerror(errno));
485 // PID 1 must not actually exit, although we should never reach this point:
490 else if (shutdown_type == shutdown_type_t::REBOOT) {
491 // Non-system-process. If we got SIGINT, let's die due to it:
492 sigset_t sigwait_set;
493 sigemptyset(&sigwait_set);
494 sigaddset(&sigwait_set, SIGINT);
496 sigprocmask(SIG_UNBLOCK, &sigwait_set, NULL);
502 static void log_bad_env(int linenum)
504 log(loglevel_t::ERROR, "invalid environment variable setting in environment file (line ", linenum, ")");
507 // Read and set environment variables from a file.
508 static void read_env_file(const char *env_file_path)
510 // Note that we can't use the log in this function; it hasn't been initialised yet.
512 std::ifstream env_file(env_file_path);
513 if (! env_file) return;
515 env_file.exceptions(std::ios::badbit);
517 auto &clocale = std::locale::classic();
521 while (std::getline(env_file, line)) {
523 auto lpos = line.begin();
524 auto lend = line.end();
525 while (lpos != lend && std::isspace(*lpos, clocale)) {
532 log_bad_env(linenum);
535 auto name_begin = lpos++;
536 // skip until '=' or whitespace:
537 while (lpos != lend && *lpos != '=' && ! std::isspace(*lpos, clocale)) ++lpos;
538 auto name_end = lpos;
540 while (lpos != lend && std::isspace(*lpos, clocale)) ++lpos;
542 log_bad_env(linenum);
547 auto val_begin = lpos;
548 while (lpos != lend && *lpos != '\n') ++lpos;
551 std::string name = line.substr(name_begin - line.begin(), name_end - name_begin);
552 std::string value = line.substr(val_begin - line.begin(), val_end - val_begin);
553 if (setenv(name.c_str(), value.c_str(), true) == -1) {
554 throw std::system_error(errno, std::system_category());
561 // In exception situations we want user confirmation before proceeding (eg on critical boot failure
562 // we wait before rebooting to avoid a reboot loop).
563 static void wait_for_user_input() noexcept
565 std::cout << "Press Enter to continue." << std::endl;
567 read(STDIN_FILENO, buf, 1);
570 // Callback for control socket
571 static void control_socket_cb(eventloop_t *loop, int sockfd)
573 // Considered keeping a limit the number of active connections, however, there doesn't
574 // seem much to be gained from that. Only root can create connections and not being
575 // able to establish a control connection is as much a denial-of-service as is not being
576 // able to start a service due to lack of fd's.
578 // Accept a connection
579 int newfd = dinit_accept4(sockfd, nullptr, nullptr, SOCK_NONBLOCK | SOCK_CLOEXEC);
583 new control_conn_t(*loop, services, newfd); // will delete itself when it's finished
585 catch (std::exception &exc) {
586 log(loglevel_t::ERROR, "Accepting control connection: ", exc.what());
592 void open_control_socket(bool report_ro_failure) noexcept
594 if (! control_socket_open) {
595 const char * saddrname = control_socket_path;
596 size_t saddrname_len = strlen(saddrname);
597 uint sockaddr_size = offsetof(struct sockaddr_un, sun_path) + saddrname_len + 1;
599 struct sockaddr_un * name = static_cast<sockaddr_un *>(malloc(sockaddr_size));
600 if (name == nullptr) {
601 log(loglevel_t::ERROR, "Opening control socket: out of memory");
605 if (am_system_init) {
606 // Unlink any stale control socket file, but only if we are system init, since otherwise
607 // the 'stale' file may not be stale at all:
611 name->sun_family = AF_UNIX;
612 memcpy(name->sun_path, saddrname, saddrname_len + 1);
614 int sockfd = dinit_socket(AF_UNIX, SOCK_STREAM, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
616 log(loglevel_t::ERROR, "Error creating control socket: ", strerror(errno));
621 if (bind(sockfd, (struct sockaddr *) name, sockaddr_size) == -1) {
622 if (errno != EROFS || report_ro_failure) {
623 log(loglevel_t::ERROR, "Error binding control socket: ", strerror(errno));
632 // No connections can be made until we listen, so it is fine to change the permissions now
633 // (and anyway there is no way to atomically create the socket and set permissions):
634 if (chmod(saddrname, S_IRUSR | S_IWUSR) == -1) {
635 log(loglevel_t::ERROR, "Error setting control socket permissions: ", strerror(errno));
640 if (listen(sockfd, 10) == -1) {
641 log(loglevel_t::ERROR, "Error listening on control socket: ", strerror(errno));
647 control_socket_io.add_watch(event_loop, sockfd, dasynq::IN_EVENTS);
648 control_socket_open = true;
650 catch (std::exception &e)
652 log(loglevel_t::ERROR, "Could not setup I/O on control socket: ", e.what());
658 static void close_control_socket() noexcept
660 if (control_socket_open) {
661 int fd = control_socket_io.get_watched_fd();
662 control_socket_io.deregister(event_loop);
665 // Unlink the socket:
666 unlink(control_socket_path);
670 void setup_external_log() noexcept
672 if (! external_log_open) {
674 const char * saddrname = log_path;
675 size_t saddrname_len = strlen(saddrname);
676 uint sockaddr_size = offsetof(struct sockaddr_un, sun_path) + saddrname_len + 1;
678 struct sockaddr_un * name = static_cast<sockaddr_un *>(malloc(sockaddr_size));
679 if (name == nullptr) {
680 log(loglevel_t::ERROR, "Connecting to log socket: out of memory");
684 name->sun_family = AF_UNIX;
685 memcpy(name->sun_path, saddrname, saddrname_len + 1);
687 int sockfd = dinit_socket(AF_UNIX, SOCK_DGRAM, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
689 log(loglevel_t::ERROR, "Error creating log socket: ", strerror(errno));
694 if (connect(sockfd, (struct sockaddr *) name, sockaddr_size) == 0 || errno == EINPROGRESS) {
695 // For EINPROGRESS, connection is still being established; however, we can select on
696 // the file descriptor so we will be notified when it's ready. In other words we can
697 // basically use it anyway.
699 setup_main_log(sockfd);
701 catch (std::exception &e) {
702 log(loglevel_t::ERROR, "Setting up log failed: ", e.what());
707 // Note if connect fails, we haven't warned at all, because the syslog server might not
716 int log_fd = open(log_path, O_WRONLY | O_CREAT | O_APPEND | O_NONBLOCK | O_CLOEXEC, 0644);
719 setup_main_log(log_fd);
721 catch (std::exception &e) {
722 log(loglevel_t::ERROR, "Setting up log failed: ", e.what());
727 // log failure to log? It makes more sense than first appears, because we also log to console:
728 log(loglevel_t::ERROR, "Setting up log failed: ", strerror(errno));
734 /* handle SIGINT signal (generated by Linux kernel when ctrl+alt+del pressed) */
735 static void sigint_reboot_cb(eventloop_t &eloop) noexcept
737 services->stop_all_services(shutdown_type_t::REBOOT);
740 /* handle SIGQUIT (if we are system init) */
741 static void sigquit_cb(eventloop_t &eloop) noexcept
743 // This performs an immediate shutdown, without service rollback.
744 close_control_socket();
745 execl("/sbin/shutdown", "/sbin/shutdown", "--system", (char *) 0);
746 log(loglevel_t::ERROR, "Error executing /sbin/shutdown: ", strerror(errno));
747 sync(); // since a hard poweroff might be required at this point...
750 /* handle SIGTERM/SIGQUIT(non-system-daemon) - stop all services and shut down */
751 static void sigterm_cb(eventloop_t &eloop) noexcept
753 services->stop_all_services();