Implement minor suggestions from cppcheck report.
[oweals/dinit.git] / src / dinit.cc
1 #include <iostream>
2 #include <fstream>
3 #include <list>
4 #include <cstring>
5 #include <csignal>
6 #include <cstddef>
7 #include <cstdlib>
8
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <sys/un.h>
12 #include <sys/socket.h>
13 #include <unistd.h>
14 #include <fcntl.h>
15 #include <pwd.h>
16 #ifdef __linux__
17 #include <sys/prctl.h>
18 #include <sys/klog.h>
19 #include <sys/reboot.h>
20 #endif
21 #if defined(__FreeBSD__) || defined(__DragonFly__)
22 #include <sys/procctl.h>
23 #endif
24
25 #include "dinit.h"
26 #include "dasynq.h"
27 #include "service.h"
28 #include "control.h"
29 #include "dinit-log.h"
30 #include "dinit-socket.h"
31 #include "static-string.h"
32 #include "dinit-utmp.h"
33
34 #include "mconfig.h"
35
36 /*
37  * When running as the system init process, Dinit processes the following signals:
38  *
39  * SIGTERM - roll back services and then fork/exec /sbin/halt
40  * SIGINT - roll back services and then fork/exec /sbin/reboot
41  * SIGQUIT - exec() /sbin/shutdown without rolling back services
42  *
43  * It's an open question about whether Dinit should roll back services *before*
44  * running halt/reboot, since those commands should prompt rollback of services
45  * anyway. But it seems safe to do so, and it means the user can at least stop
46  * services even if the halt/reboot commands are unavailable for some reason.
47  */
48
49 using namespace cts;
50
51 using eventloop_t = dasynq::event_loop<dasynq::null_mutex>;
52
53 eventloop_t event_loop;
54
55 static void sigint_reboot_cb(eventloop_t &eloop) noexcept;
56 static void sigquit_cb(eventloop_t &eloop) noexcept;
57 static void sigterm_cb(eventloop_t &eloop) noexcept;
58 static void open_control_socket(bool report_ro_failure = true) noexcept;
59 static void close_control_socket() noexcept;
60 static void wait_for_user_input() noexcept;
61 static void read_env_file(const char *);
62
63 static void control_socket_cb(eventloop_t *loop, int fd);
64
65
66 // Variables
67
68 static dirload_service_set *services;
69
70 static bool am_pid_one = false;     // true if we are PID 1
71 static bool am_system_init = false; // true if we are the system init process
72
73 static bool did_log_boot = false;
74 static bool control_socket_open = false;
75 static bool external_log_open = false;
76 int active_control_conns = 0;
77
78 // Control socket path. We maintain a string (control_socket_str) in case we need
79 // to allocate storage, but control_socket_path is the authoritative value.
80 static const char *control_socket_path = SYSCONTROLSOCKET;
81 static std::string control_socket_str;
82
83 static const char *env_file_path = "/etc/dinit/environment";
84
85 static const char *log_path = "/dev/log";
86 static bool log_is_syslog = true; // if false, log is a file
87
88 static const char *user_home_path = nullptr;
89
90
91 // Get user home (and set user_home_path). (The return may become invalid after
92 // changing the evironment (HOME variable) or using the getpwuid() function).
93 const char * get_user_home()
94 {
95     if (user_home_path == nullptr) {
96         user_home_path = getenv("HOME");
97         if (user_home_path == nullptr) {
98             struct passwd * pwuid_p = getpwuid(getuid());
99             if (pwuid_p != nullptr) {
100                 user_home_path = pwuid_p->pw_dir;
101             }
102         }
103     }
104     return user_home_path;
105 }
106
107
108 namespace {
109     // Event-loop handler for a signal, which just delegates to a function (pointer).
110     class callback_signal_handler : public eventloop_t::signal_watcher_impl<callback_signal_handler>
111     {
112         using rearm = dasynq::rearm;
113
114         public:
115         typedef void (*cb_func_t)(eventloop_t &);
116         
117         private:
118         cb_func_t cb_func;
119         
120         public:
121         callback_signal_handler() : cb_func(nullptr) { }
122         callback_signal_handler(cb_func_t pcb_func) :  cb_func(pcb_func) { }
123         
124         void set_cb_func(cb_func_t cb_func)
125         {
126             this->cb_func = cb_func;
127         }
128         
129         rearm received(eventloop_t &eloop, int signo, siginfo_p siginfo)
130         {
131             cb_func(eloop);
132             return rearm::REARM;
133         }
134     };
135
136     // Event-loop handler for when a connection is made to the control socket.
137     class control_socket_watcher : public eventloop_t::fd_watcher_impl<control_socket_watcher>
138     {
139         using rearm = dasynq::rearm;
140
141         public:
142         rearm fd_event(eventloop_t &loop, int fd, int flags) noexcept
143         {
144             control_socket_cb(&loop, fd);
145             return rearm::REARM;
146         }
147     };
148
149     // Simple timer used to limit the amount of time waiting for the log flush to complete (at shutdown)
150     class log_flush_timer_t : public eventloop_t::timer_impl<log_flush_timer_t>
151     {
152         using rearm = dasynq::rearm;
153
154         bool expired = false;
155
156         public:
157         rearm timer_expiry(eventloop_t &, int expiry_count)
158         {
159             expired = true;
160             return rearm::DISARM;
161         }
162
163         bool has_expired()
164         {
165             return expired;
166         }
167     };
168
169     control_socket_watcher control_socket_io;
170     log_flush_timer_t log_flush_timer;
171 }
172
173 int dinit_main(int argc, char **argv)
174 {
175     using namespace std;
176     
177     am_pid_one = (getpid() == 1);
178     am_system_init = (getuid() == 0);
179     const char * service_dir = nullptr;
180     bool service_dir_dynamic = false; // service_dir dynamically allocated?
181     const char * env_file = nullptr;
182     bool control_socket_path_set = false;
183     bool env_file_set = false;
184
185     // list of services to start
186     list<const char *> services_to_start;
187     
188     // Arguments, if given, specify a list of services to start.
189     // If we are running as init (PID=1), the Linux kernel gives us any command line arguments it was given
190     // but didn't recognize, including "single" (usually for "boot to single user mode" aka just start the
191     // shell). We can treat them as service names. In the worst case we can't find any of the named
192     // services, and so we'll start the "boot" service by default.
193     if (argc > 1) {
194         for (int i = 1; i < argc; i++) {
195             if (argv[i][0] == '-') {
196                 // An option...
197                 if (strcmp(argv[i], "--env-file") == 0 || strcmp(argv[i], "-e") == 0) {
198                     if (++i < argc) {
199                         env_file_set = true;
200                         env_file = argv[i];
201                     }
202                     else {
203                         cerr << "dinit: '--env-file' (-e) requires an argument" << endl;
204                     }
205                 }
206                 else if (strcmp(argv[i], "--services-dir") == 0 || strcmp(argv[i], "-d") == 0) {
207                     if (++i < argc) {
208                         service_dir = argv[i];
209                     }
210                     else {
211                         cerr << "dinit: '--services-dir' (-d) requires an argument" << endl;
212                         return 1;
213                     }
214                 }
215                 else if (strcmp(argv[i], "--system") == 0 || strcmp(argv[i], "-s") == 0) {
216                     am_system_init = true;
217                 }
218                 else if (strcmp(argv[i], "--user") == 0 || strcmp(argv[i], "-u") == 0) {
219                     am_system_init = false;
220                 }
221                 else if (strcmp(argv[i], "--socket-path") == 0 || strcmp(argv[i], "-p") == 0) {
222                     if (++i < argc) {
223                         control_socket_path = argv[i];
224                         control_socket_path_set = true;
225                     }
226                     else {
227                         cerr << "dinit: '--socket-path' (-p) requires an argument" << endl;
228                         return 1;
229                     }
230                 }
231                 else if (strcmp(argv[i], "--log-file") == 0 || strcmp(argv[i], "-l") == 0) {
232                     if (++i < argc) {
233                         log_path = argv[i];
234                         log_is_syslog = false;
235                     }
236                     else {
237                         cerr << "dinit: '--log-file' (-l) requires an argument" << endl;
238                         return 1;
239                     }
240                 }
241                 else if (strcmp(argv[i], "--help") == 0) {
242                     cout << "dinit, an init with dependency management\n"
243                             " --help                       display help\n"
244                             " --env-file <file>, -e <file>\n"
245                             "                              environment variable initialisation file\n"
246                             " --services-dir <dir>, -d <dir>\n"
247                             "                              set base directory for service description\n"
248                             "                              files (-d <dir>)\n"
249                             " --system, -s                 run as the system service manager\n"
250                             " --user, -u                   run as a user service manager\n"
251                             " --socket-path <path>, -p <path>\n"
252                             "                              path to control socket\n"
253                             " <service-name>               start service with name <service-name>\n";
254                     return 0;
255                 }
256                 else {
257                     // unrecognized
258                     if (! am_system_init) {
259                         cerr << "dinit: Unrecognized option: " << argv[i] << endl;
260                         return 1;
261                     }
262                 }
263             }
264             else {
265 #ifdef __linux__
266                 // LILO puts "auto" on the kernel command line for unattended boots; we'll filter it.
267                 if (! am_pid_one || strcmp(argv[i], "auto") != 0) {
268                     services_to_start.push_back(argv[i]);
269                 }
270 #else
271                 services_to_start.push_back(argv[i]);
272 #endif
273             }
274         }
275     }
276     
277     if (am_system_init) {
278         // setup STDIN, STDOUT, STDERR so that we can use them
279         int onefd = open("/dev/console", O_RDONLY, 0);
280         dup2(onefd, 0);
281         int twofd = open("/dev/console", O_RDWR, 0);
282         dup2(twofd, 1);
283         dup2(twofd, 2);
284         
285         if (onefd > 2) close(onefd);
286         if (twofd > 2) close(twofd);
287
288         if (! env_file_set) {
289             env_file = env_file_path;
290         }
291     }
292
293     /* Set up signal handlers etc */
294     /* SIG_CHILD is ignored by default: good */
295     sigset_t sigwait_set;
296     sigemptyset(&sigwait_set);
297     sigaddset(&sigwait_set, SIGCHLD);
298     sigaddset(&sigwait_set, SIGINT);
299     sigaddset(&sigwait_set, SIGTERM);
300     if (am_pid_one) sigaddset(&sigwait_set, SIGQUIT);
301     sigprocmask(SIG_BLOCK, &sigwait_set, NULL);
302
303     // Terminal access control signals - we block these so that dinit can't be
304     // suspended if it writes to the terminal after some other process has claimed
305     // ownership of it.
306     signal(SIGTSTP, SIG_IGN);
307     signal(SIGTTIN, SIG_IGN);
308     signal(SIGTTOU, SIG_IGN);
309     
310     signal(SIGPIPE, SIG_IGN);
311     
312     if (! am_system_init && ! control_socket_path_set) {
313         const char * userhome = get_user_home();
314         if (userhome != nullptr) {
315             control_socket_str = userhome;
316             control_socket_str += "/.dinitctl";
317             control_socket_path = control_socket_str.c_str();
318         }
319     }
320     
321     /* service directory name */
322     if (service_dir == nullptr && ! am_system_init) {
323         const char * userhome = get_user_home();
324         if (userhome != nullptr) {
325             const char * user_home = get_user_home();
326             size_t user_home_len = strlen(user_home);
327             size_t dinit_d_len = strlen("/dinit.d");
328             size_t full_len = user_home_len + dinit_d_len + 1;
329             char *service_dir_w = new char[full_len];
330             std::memcpy(service_dir_w, user_home, user_home_len);
331             std::memcpy(service_dir_w + user_home_len, "/dinit.d", dinit_d_len);
332             service_dir_w[full_len - 1] = 0;
333
334             service_dir = service_dir_w;
335             service_dir_dynamic = true;
336         }
337     }
338     
339     if (services_to_start.empty()) {
340         services_to_start.push_back("boot");
341     }
342
343     // Set up signal handlers
344     callback_signal_handler sigterm_watcher {sigterm_cb};
345     callback_signal_handler sigint_watcher;
346     callback_signal_handler sigquit_watcher;
347
348     if (am_pid_one) {
349         sigint_watcher.set_cb_func(sigint_reboot_cb);
350         sigquit_watcher.set_cb_func(sigquit_cb);
351     }
352     else {
353         sigint_watcher.set_cb_func(sigterm_cb);
354     }
355
356     sigint_watcher.add_watch(event_loop, SIGINT);
357     sigterm_watcher.add_watch(event_loop, SIGTERM);
358     
359     if (am_pid_one) {
360         // PID 1: SIGQUIT exec's shutdown
361         sigquit_watcher.add_watch(event_loop, SIGQUIT);
362         // As a user process, we instead just let SIGQUIT perform the default action.
363     }
364
365     // Try to open control socket (may fail due to readonly filesystem)
366     open_control_socket(false);
367     
368 #ifdef __linux__
369     if (am_system_init) {
370         // Disable non-critical kernel output to console
371         klogctl(6 /* SYSLOG_ACTION_CONSOLE_OFF */, nullptr, 0);
372         // Make ctrl+alt+del combination send SIGINT to PID 1 (this process)
373         reboot(RB_DISABLE_CAD);
374     }
375
376     // Mark ourselves as a subreaper. This means that if a process we start double-forks, the
377     // orphaned child will re-parent to us rather than to PID 1 (although that could be us too).
378     prctl(PR_SET_CHILD_SUBREAPER, 1);
379 #elif defined(__FreeBSD__) || defined(__DragonFly__)
380     // Documentation (man page) for this kind of sucks. PROC_REAP_ACQUIRE "acquires the reaper status for
381     // the current process" but does that mean the first two arguments still need valid values to be
382     // supplied? We'll play it safe and explicitly target our own process:
383     procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL);
384 #endif
385     
386     log_flush_timer.add_timer(event_loop, dasynq::clock_type::MONOTONIC);
387
388     bool add_all_service_dirs = false;
389     if (service_dir == nullptr) {
390         service_dir = "/etc/dinit.d";
391         add_all_service_dirs = true;
392     }
393
394     /* start requested services */
395     services = new dirload_service_set(service_dir, service_dir_dynamic);
396     if (add_all_service_dirs) {
397         services->add_service_dir("/usr/local/lib/dinit.d", false);
398         services->add_service_dir("/lib/dinit.d", false);
399     }
400     
401     init_log(services, log_is_syslog);
402     if (am_system_init) {
403         log(loglevel_t::INFO, false, "starting system");
404     }
405     
406     // Only try to set up the external log now if we aren't the system init. (If we are the
407     // system init, wait until the log service starts).
408     if (! am_system_init) setup_external_log();
409
410     if (env_file != nullptr) {
411         read_env_file(env_file);
412     }
413
414     for (auto svc : services_to_start) {
415         try {
416             services->start_service(svc);
417             // Note in general if we fail to start a service we don't need any special error handling,
418             // since we either leave other services running or, if it was the only service, then no
419             // services will be running and we will process normally (reboot if system process,
420             // exit if user process).
421         }
422         catch (service_not_found &snf) {
423             log(loglevel_t::ERROR, snf.service_name, ": Could not find service description.");
424         }
425         catch (service_load_exc &sle) {
426             log(loglevel_t::ERROR, sle.service_name, ": ", sle.exc_description);
427         }
428         catch (std::bad_alloc &badalloce) {
429             log(loglevel_t::ERROR, "Out of memory when trying to start service: ", svc, ".");
430             break;
431         }
432     }
433     
434     event_loop:
435     
436     // Process events until all services have terminated.
437     while (services->count_active_services() != 0) {
438         event_loop.run();
439     }
440
441     shutdown_type_t shutdown_type = services->get_shutdown_type();
442     if (shutdown_type == shutdown_type_t::REMAIN) {
443         goto event_loop;
444     }
445     
446     if (am_pid_one) {
447         log_msg_begin(loglevel_t::INFO, "No more active services.");
448         
449         if (shutdown_type == shutdown_type_t::REBOOT) {
450             log_msg_end(" Will reboot.");
451         }
452         else if (shutdown_type == shutdown_type_t::HALT) {
453             log_msg_end(" Will halt.");
454         }
455         else if (shutdown_type == shutdown_type_t::POWEROFF) {
456             log_msg_end(" Will power down.");
457         }
458     }
459     
460     log_flush_timer.arm_timer_rel(event_loop, timespec{5,0}); // 5 seconds
461     while (! is_log_flushed() && ! log_flush_timer.has_expired()) {
462         event_loop.run();
463     }
464     
465     close_control_socket();
466     
467     if (am_pid_one) {
468         if (shutdown_type == shutdown_type_t::NONE) {
469             // Services all stopped but there was no shutdown issued. Inform user, wait for ack, and
470             // re-start boot sequence.
471             std::cout << "No shutdown was requested; boot failure? Will re-run boot sequence." << std::endl;
472             sync(); // Sync to minimise data loss if user elects to power off / hard reset
473             wait_for_user_input();
474             try {
475                 services->start_service("boot");
476                 goto event_loop; // yes, the "evil" goto
477             }
478             catch (...) {
479                 // Now what do we do? try to reboot, but wait for user ack to avoid boot loop.
480                 log(loglevel_t::ERROR, "Could not start 'boot' service. Will attempt reboot.");
481                 shutdown_type = shutdown_type_t::REBOOT;
482             }
483         }
484         
485         const char * cmd_arg;
486         if (shutdown_type == shutdown_type_t::HALT) {
487             cmd_arg = "-h";
488         }
489         else if (shutdown_type == shutdown_type_t::REBOOT) {
490             cmd_arg = "-r";
491         }
492         else {
493             // power off.
494             cmd_arg = "-p";
495         }
496         
497         // Fork and execute dinit-reboot.
498         constexpr auto shutdown_exec = literal(SBINDIR) + "/shutdown";
499         execl(shutdown_exec.c_str(), shutdown_exec.c_str(), "--system", cmd_arg, nullptr);
500         log(loglevel_t::ERROR, (literal("Could not execute ") + SBINDIR + "/shutdown: ").c_str(),
501                 strerror(errno));
502         
503         // PID 1 must not actually exit, although we should never reach this point:
504         while (true) {
505             event_loop.run();
506         }
507     }
508     else if (shutdown_type == shutdown_type_t::REBOOT) {
509         // Non-system-process. If we got SIGINT, let's die due to it:
510         sigset_t sigwait_set_int;
511         sigemptyset(&sigwait_set_int);
512         sigaddset(&sigwait_set_int, SIGINT);
513         raise(SIGINT);
514         sigprocmask(SIG_UNBLOCK, &sigwait_set_int, NULL);
515     }
516     
517     return 0;
518 }
519
520 // Log a parse error when reading the environment file.
521 static void log_bad_env(int linenum)
522 {
523     log(loglevel_t::ERROR, "invalid environment variable setting in environment file (line ", linenum, ")");
524 }
525
526 // Read and set environment variables from a file.
527 static void read_env_file(const char *env_file_path)
528 {
529     // Note that we can't use the log in this function; it hasn't been initialised yet.
530
531     std::ifstream env_file(env_file_path);
532     if (! env_file) return;
533
534     env_file.exceptions(std::ios::badbit);
535
536     auto &clocale = std::locale::classic();
537     std::string line;
538     int linenum = 0;
539
540     while (std::getline(env_file, line)) {
541         linenum++;
542         auto lpos = line.begin();
543         auto lend = line.end();
544         while (lpos != lend && std::isspace(*lpos, clocale)) {
545             ++lpos;
546         }
547
548         if (lpos != lend) {
549             if (*lpos != '#') {
550                 if (*lpos == '=') {
551                     log_bad_env(linenum);
552                     continue;
553                 }
554                 auto name_begin = lpos++;
555                 // skip until '=' or whitespace:
556                 while (lpos != lend && *lpos != '=' && ! std::isspace(*lpos, clocale)) ++lpos;
557                 auto name_end = lpos;
558                 //  skip whitespace:
559                 while (lpos != lend && std::isspace(*lpos, clocale)) ++lpos;
560                 if (lpos == lend) {
561                     log_bad_env(linenum);
562                     continue;
563                 }
564
565                 ++lpos;
566                 auto val_begin = lpos;
567                 while (lpos != lend && *lpos != '\n') ++lpos;
568                 auto val_end = lpos;
569
570                 std::string name = line.substr(name_begin - line.begin(), name_end - name_begin);
571                 std::string value = line.substr(val_begin - line.begin(), val_end - val_begin);
572                 if (setenv(name.c_str(), value.c_str(), true) == -1) {
573                     throw std::system_error(errno, std::system_category());
574                 }
575             }
576         }
577     }
578 }
579
580 // In exception situations we want user confirmation before proceeding (eg on critical boot failure
581 // we wait before rebooting to avoid a reboot loop).
582 static void wait_for_user_input() noexcept
583 {
584     std::cout << "Press Enter to continue." << std::endl;
585     char buf[1];
586     read(STDIN_FILENO, buf, 1);
587 }
588
589 // Callback for control socket
590 static void control_socket_cb(eventloop_t *loop, int sockfd)
591 {
592     // Considered keeping a limit the number of active connections, however, there doesn't
593     // seem much to be gained from that. Only root can create connections and not being
594     // able to establish a control connection is as much a denial-of-service as is not being
595     // able to start a service due to lack of fd's.
596
597     // Accept a connection
598     int newfd = dinit_accept4(sockfd, nullptr, nullptr, SOCK_NONBLOCK | SOCK_CLOEXEC);
599
600     if (newfd != -1) {
601         try {
602             new control_conn_t(*loop, services, newfd);  // will delete itself when it's finished
603         }
604         catch (std::exception &exc) {
605             log(loglevel_t::ERROR, "Accepting control connection: ", exc.what());
606             close(newfd);
607         }
608     }
609 }
610
611 // Callback when the root filesystem is read/write:
612 void rootfs_is_rw() noexcept
613 {
614     open_control_socket(true);
615     if (! did_log_boot) {
616         did_log_boot = log_boot();
617     }
618 }
619
620 // Open/create the control socket, normally /dev/dinitctl, used to allow client programs to connect
621 // and issue service orders and shutdown commands etc. This can safely be called multiple times;
622 // once the socket has been successfully opened, further calls have no effect.
623 static void open_control_socket(bool report_ro_failure) noexcept
624 {
625     if (! control_socket_open) {
626         const char * saddrname = control_socket_path;
627         size_t saddrname_len = strlen(saddrname);
628         uint sockaddr_size = offsetof(struct sockaddr_un, sun_path) + saddrname_len + 1;
629         
630         struct sockaddr_un * name = static_cast<sockaddr_un *>(malloc(sockaddr_size));
631         if (name == nullptr) {
632             log(loglevel_t::ERROR, "Opening control socket: out of memory");
633             return;
634         }
635
636         if (am_system_init) {
637             // Unlink any stale control socket file, but only if we are system init, since otherwise
638             // the 'stale' file may not be stale at all:
639             unlink(saddrname);
640         }
641
642         name->sun_family = AF_UNIX;
643         memcpy(name->sun_path, saddrname, saddrname_len + 1);
644
645         int sockfd = dinit_socket(AF_UNIX, SOCK_STREAM, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
646         if (sockfd == -1) {
647             log(loglevel_t::ERROR, "Error creating control socket: ", strerror(errno));
648             free(name);
649             return;
650         }
651
652         if (bind(sockfd, (struct sockaddr *) name, sockaddr_size) == -1) {
653             if (errno != EROFS || report_ro_failure) {
654                 log(loglevel_t::ERROR, "Error binding control socket: ", strerror(errno));
655             }
656             close(sockfd);
657             free(name);
658             return;
659         }
660         
661         free(name);
662
663         // No connections can be made until we listen, so it is fine to change the permissions now
664         // (and anyway there is no way to atomically create the socket and set permissions):
665         if (chmod(saddrname, S_IRUSR | S_IWUSR) == -1) {
666             log(loglevel_t::ERROR, "Error setting control socket permissions: ", strerror(errno));
667             close(sockfd);
668             return;
669         }
670
671         if (listen(sockfd, 10) == -1) {
672             log(loglevel_t::ERROR, "Error listening on control socket: ", strerror(errno));
673             close(sockfd);
674             return;
675         }
676
677         try {
678             control_socket_io.add_watch(event_loop, sockfd, dasynq::IN_EVENTS);
679             control_socket_open = true;
680         }
681         catch (std::exception &e)
682         {
683             log(loglevel_t::ERROR, "Could not setup I/O on control socket: ", e.what());
684             close(sockfd);
685         }
686     }
687 }
688
689 static void close_control_socket() noexcept
690 {
691     if (control_socket_open) {
692         int fd = control_socket_io.get_watched_fd();
693         control_socket_io.deregister(event_loop);
694         close(fd);
695         
696         // Unlink the socket:
697         unlink(control_socket_path);
698
699         control_socket_open = false;
700     }
701 }
702
703 void setup_external_log() noexcept
704 {
705     if (! external_log_open) {
706         if (log_is_syslog) {
707             const char * saddrname = log_path;
708             size_t saddrname_len = strlen(saddrname);
709             uint sockaddr_size = offsetof(struct sockaddr_un, sun_path) + saddrname_len + 1;
710
711             struct sockaddr_un * name = static_cast<sockaddr_un *>(malloc(sockaddr_size));
712             if (name == nullptr) {
713                 log(loglevel_t::ERROR, "Connecting to log socket: out of memory");
714                 return;
715             }
716
717             name->sun_family = AF_UNIX;
718             memcpy(name->sun_path, saddrname, saddrname_len + 1);
719
720             int sockfd = dinit_socket(AF_UNIX, SOCK_DGRAM, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
721             if (sockfd == -1) {
722                 log(loglevel_t::ERROR, "Error creating log socket: ", strerror(errno));
723                 free(name);
724                 return;
725             }
726
727             if (connect(sockfd, (struct sockaddr *) name, sockaddr_size) == 0 || errno == EINPROGRESS) {
728                 // For EINPROGRESS, connection is still being established; however, we can select on
729                 // the file descriptor so we will be notified when it's ready. In other words we can
730                 // basically use it anyway.
731                 try {
732                     setup_main_log(sockfd);
733                     external_log_open = true;
734                 }
735                 catch (std::exception &e) {
736                     log(loglevel_t::ERROR, "Setting up log failed: ", e.what());
737                     close(sockfd);
738                 }
739             }
740             else {
741                 // Note if connect fails, we haven't warned at all, because the syslog server might not
742                 // have started yet.
743                 close(sockfd);
744             }
745
746             free(name);
747         }
748         else {
749             // log to file:
750             int log_fd = open(log_path, O_WRONLY | O_CREAT | O_APPEND | O_NONBLOCK | O_CLOEXEC, 0644);
751             if (log_fd >= 0) {
752                 try {
753                     setup_main_log(log_fd);
754                     external_log_open = true;
755                 }
756                 catch (std::exception &e) {
757                     log(loglevel_t::ERROR, "Setting up log failed: ", e.what());
758                     close(log_fd);
759                 }
760             }
761             else {
762                 // log failure to log? It makes more sense than first appears, because we also log
763                 // to console:
764                 log(loglevel_t::ERROR, "Setting up log failed: ", strerror(errno));
765             }
766         }
767     }
768 }
769
770 /* handle SIGINT signal (generated by Linux kernel when ctrl+alt+del pressed) */
771 static void sigint_reboot_cb(eventloop_t &eloop) noexcept
772 {
773     services->stop_all_services(shutdown_type_t::REBOOT);
774 }
775
776 /* handle SIGQUIT (if we are system init) */
777 static void sigquit_cb(eventloop_t &eloop) noexcept
778 {
779     // This performs an immediate shutdown, without service rollback.
780     close_control_socket();
781     constexpr auto shutdown_exec = literal(SBINDIR) + "/shutdown";
782     execl(shutdown_exec.c_str(), shutdown_exec.c_str(), "--system", (char *) 0);
783     log(loglevel_t::ERROR, literal("Error executing ") + SBINDIR + "/sbin/shutdown: ", strerror(errno));
784     sync(); // since a hard poweroff might be required at this point...
785 }
786
787 /* handle SIGTERM/SIGQUIT(non-system-daemon) - stop all services and shut down */
788 static void sigterm_cb(eventloop_t &eloop) noexcept
789 {
790     services->stop_all_services();
791 }