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