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