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