Various renaming of camelCase to underscored_name for consistency.
[oweals/dinit.git] / src / dinit.cc
1 #include <iostream>
2 #include <list>
3 #include <cstring>
4 #include <csignal>
5 #include <cstddef>
6 #include <cstdlib>
7
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <sys/un.h>
11 #include <sys/socket.h>
12 #include <unistd.h>
13 #include <fcntl.h>
14 #include <pwd.h>
15 #ifdef __linux__
16 #include <sys/prctl.h>
17 #endif
18
19 #include "dasynq.h"
20 #include "service.h"
21 #include "control.h"
22 #include "dinit-log.h"
23 #include "dinit-socket.h"
24
25 #ifdef __linux__
26 #include <sys/klog.h>
27 #include <sys/reboot.h>
28 #endif
29
30 /*
31  * When running as the system init process, Dinit processes the following signals:
32  *
33  * SIGTERM - roll back services and then fork/exec /sbin/halt
34  * SIGINT - roll back services and then fork/exec /sbin/reboot
35  * SIGQUIT - exec() /sbin/shutdown without rolling back services
36  *
37  * It's an open question about whether Dinit should roll back services *before*
38  * running halt/reboot, since those commands should prompt rollback of services
39  * anyway. But it seems safe to do so, and it means the user can at least stop
40  * services even if the halt/reboot commands are unavailable for some reason.
41  */
42
43
44 using namespace dasynq;
45 using eventloop_t = event_loop<null_mutex>;
46
47 eventloop_t eventLoop = eventloop_t();
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
55 static void control_socket_cb(eventloop_t *loop, int fd);
56
57 void open_control_socket(bool report_ro_failure = true) noexcept;
58 void setup_external_log() noexcept;
59
60
61 // Variables
62
63 static dirload_service_set *services;
64
65 static bool am_system_init = false; // true if we are the system init process
66
67 static bool control_socket_open = false;
68 static bool external_log_open = false;
69 int active_control_conns = 0;
70
71 // Control socket path. We maintain a string (control_socket_str) in case we need
72 // to allocate storage, but control_socket_path is the authoritative value.
73 static const char *control_socket_path = "/dev/dinitctl";
74 static std::string control_socket_str;
75
76 static const char *log_socket_path = "/dev/log";
77
78 static const char *user_home_path = nullptr;
79
80
81 // Get user home (and set user_home_path). (The return may become invalid after
82 // changing the evironment (HOME variable) or using the getpwuid() function).
83 const char * get_user_home()
84 {
85     if (user_home_path == nullptr) {
86         user_home_path = getenv("HOME");
87         if (user_home_path == nullptr) {
88             struct passwd * pwuid_p = getpwuid(getuid());
89             if (pwuid_p != nullptr) {
90                 user_home_path = pwuid_p->pw_dir;
91             }
92         }
93     }
94     return user_home_path;
95 }
96
97
98 namespace {
99     class callback_signal_handler : public eventloop_t::signal_watcher_impl<callback_signal_handler>
100     {
101         public:
102         typedef void (*cb_func_t)(eventloop_t &);
103         
104         private:
105         cb_func_t cb_func;
106         
107         public:
108         callback_signal_handler() : cb_func(nullptr) { }
109         callback_signal_handler(cb_func_t pcb_func) :  cb_func(pcb_func) { }
110         
111         void setCbFunc(cb_func_t cb_func)
112         {
113             this->cb_func = cb_func;
114         }
115         
116         rearm received(eventloop_t &eloop, int signo, siginfo_p siginfo)
117         {
118             cb_func(eloop);
119             return rearm::REARM;
120         }
121     };
122
123     class control_socket_watcher : public eventloop_t::fd_watcher_impl<control_socket_watcher>
124     {
125         public:
126         rearm fd_event(eventloop_t &loop, int fd, int flags) noexcept
127         {
128             control_socket_cb(&loop, fd);
129             return rearm::REARM;
130         }
131     };
132
133     control_socket_watcher control_socket_io;
134 }
135
136 int dinit_main(int argc, char **argv)
137 {
138     using namespace std;
139     
140     am_system_init = (getpid() == 1);
141     const char * service_dir = nullptr;
142     string service_dir_str; // to hold storage for above if necessary
143     bool control_socket_path_set = false;
144
145     // list of services to start
146     list<const char *> services_to_start;
147     
148     // Arguments, if given, specify a list of services to start.
149     // If we are running as init (PID=1), the kernel gives us any command line
150     // arguments it was given but didn't recognize, including "single" (usually
151     // for "boot to single user mode" aka just start the shell). We can treat
152     // them as service names. In the worst case we can't find any of the named
153     // services, and so we'll start the "boot" service by default.
154     if (argc > 1) {
155       for (int i = 1; i < argc; i++) {
156         if (argv[i][0] == '-') {
157             // An option...
158             if (strcmp(argv[i], "--services-dir") == 0 ||
159                     strcmp(argv[i], "-d") == 0) {
160                 if (++i < argc) {
161                     service_dir = argv[i];
162                 }
163                 else {
164                     cerr << "dinit: '--services-dir' (-d) requires an argument" << endl;
165                     return 1;
166                 }
167             }
168             else if (strcmp(argv[i], "--system") == 0 ||
169                     strcmp(argv[i], "-s") == 0) {
170                 am_system_init = true;
171             }
172             else if (strcmp(argv[i], "--socket-path") == 0 ||
173                     strcmp(argv[i], "-p") == 0) {
174                 if (++i < argc) {
175                     control_socket_path = argv[i];
176                     control_socket_path_set = true;
177                 }
178                 else {
179                     cerr << "dinit: '--socket-path' (-p) requires an argument" << endl;
180                     return 1;
181                 }
182             }
183             else if (strcmp(argv[i], "--help") == 0) {
184                 cout << "dinit, an init with dependency management" << endl;
185                 cout << " --help                       display help" << endl;
186                 cout << " --services-dir <dir>, -d <dir>" << endl;
187                 cout << "                              set base directory for service description" << endl;
188                 cout << "                              files (-d <dir>)" << endl;
189                 cout << " --system, -s                 run as the system init process" << endl;
190                 cout << " --socket-path <path>, -p <path>" << endl;
191                 cout << "                              path to control socket" << endl;
192                 cout << " <service-name>               start service with name <service-name>" << endl;
193                 return 0;
194             }
195             else {
196                 // unrecognized
197                 if (! am_system_init) {
198                     cerr << "dinit: Unrecognized option: " << argv[i] << endl;
199                     return 1;
200                 }
201             }
202         }
203         else {
204 #ifdef __linux__
205             // LILO puts "auto" on the kernel command line for unattended boots; we'll filter it.
206             if (! am_system_init || strcmp(argv[i], "auto") != 0) {
207                 services_to_start.push_back(argv[i]);
208             }
209 #endif
210         }
211       }
212     }
213     
214     if (am_system_init) {
215         // setup STDIN, STDOUT, STDERR so that we can use them
216         int onefd = open("/dev/console", O_RDONLY, 0);
217         dup2(onefd, 0);
218         int twofd = open("/dev/console", O_RDWR, 0);
219         dup2(twofd, 1);
220         dup2(twofd, 2);
221         
222         if (onefd > 2) close(onefd);
223         if (twofd > 2) close(twofd);
224     }
225
226 #ifdef __linux__
227     prctl(PR_SET_CHILD_SUBREAPER, 1);
228 #endif
229
230     /* Set up signal handlers etc */
231     /* SIG_CHILD is ignored by default: good */
232     sigset_t sigwait_set;
233     sigemptyset(&sigwait_set);
234     sigaddset(&sigwait_set, SIGCHLD);
235     sigaddset(&sigwait_set, SIGINT);
236     sigaddset(&sigwait_set, SIGTERM);
237     if (am_system_init) sigaddset(&sigwait_set, SIGQUIT);
238     sigprocmask(SIG_BLOCK, &sigwait_set, NULL);
239
240     // Terminal access control signals - we block these so that dinit can't be
241     // suspended if it writes to the terminal after some other process has claimed
242     // ownership of it.
243     signal(SIGTSTP, SIG_IGN);
244     signal(SIGTTIN, SIG_IGN);
245     signal(SIGTTOU, SIG_IGN);
246     
247     signal(SIGPIPE, SIG_IGN);
248     
249     if (! am_system_init && ! control_socket_path_set) {
250         const char * userhome = get_user_home();
251         if (userhome != nullptr) {
252             control_socket_str = userhome;
253             control_socket_str += "/.dinitctl";
254             control_socket_path = control_socket_str.c_str();
255         }
256     }
257     
258     /* service directory name */
259     if (service_dir == nullptr && ! am_system_init) {
260         const char * userhome = get_user_home();
261         if (userhome != nullptr) {
262             service_dir_str = get_user_home();
263             service_dir_str += "/dinit.d";
264             service_dir = service_dir_str.c_str();
265         }
266     }
267     
268     if (service_dir == nullptr) {
269         service_dir = "/etc/dinit.d";
270     }
271     
272     if (services_to_start.empty()) {
273         services_to_start.push_back("boot");
274     }
275
276     // Set up signal handlers
277     callback_signal_handler sigterm_watcher {sigterm_cb};
278     callback_signal_handler sigint_watcher;
279     callback_signal_handler sigquit_watcher;
280
281     if (am_system_init) {
282         sigint_watcher.setCbFunc(sigint_reboot_cb);
283         sigquit_watcher.setCbFunc(sigquit_cb);
284     }
285     else {
286         sigint_watcher.setCbFunc(sigterm_cb);
287     }
288
289     sigint_watcher.add_watch(eventLoop, SIGINT);
290     sigterm_watcher.add_watch(eventLoop, SIGTERM);
291     
292     if (am_system_init) {
293         // PID 1: SIGQUIT exec's shutdown
294         sigquit_watcher.add_watch(eventLoop, SIGQUIT);
295         // As a user process, we instead just let SIGQUIT perform the default action.
296     }
297
298     // Try to open control socket (may fail due to readonly filesystem)
299     open_control_socket(false);
300     
301 #ifdef __linux__
302     if (am_system_init) {
303         // Disable non-critical kernel output to console
304         klogctl(6 /* SYSLOG_ACTION_CONSOLE_OFF */, nullptr, 0);
305         // Make ctrl+alt+del combination send SIGINT to PID 1 (this process)
306         reboot(RB_DISABLE_CAD);
307     }
308 #endif
309     
310     /* start requested services */
311     services = new dirload_service_set(service_dir);
312     
313     init_log(services);
314     
315     for (auto svc : services_to_start) {
316         try {
317             services->start_service(svc);
318             // Note in general if we fail to start a service we don't need any special error handling,
319             // since we either leave other services running or, if it was the only service, then no
320             // services will be running and we will process normally (reboot if system process,
321             // exit if user process).
322         }
323         catch (service_not_found &snf) {
324             log(LogLevel::ERROR, snf.serviceName, ": Could not find service description.");
325         }
326         catch (service_load_exc &sle) {
327             log(LogLevel::ERROR, sle.serviceName, ": ", sle.excDescription);
328         }
329         catch (std::bad_alloc &badalloce) {
330             log(LogLevel::ERROR, "Out of memory when trying to start service: ", svc, ".");
331             break;
332         }
333     }
334     
335     event_loop:
336     
337     // Process events until all services have terminated.
338     while (services->count_active_services() != 0) {
339         eventLoop.run();
340     }
341
342     shutdown_type_t shutdown_type = services->getShutdownType();
343     
344     if (am_system_init) {
345         log_msg_begin(LogLevel::INFO, "No more active services.");
346         
347         if (shutdown_type == shutdown_type_t::REBOOT) {
348             log_msg_end(" Will reboot.");
349         }
350         else if (shutdown_type == shutdown_type_t::HALT) {
351             log_msg_end(" Will halt.");
352         }
353         else if (shutdown_type == shutdown_type_t::POWEROFF) {
354             log_msg_end(" Will power down.");
355         }
356         else {
357             log_msg_end(" Re-initiating boot sequence.");
358         }
359     }
360     
361     while (! is_log_flushed()) {
362         eventLoop.run();
363     }
364     
365     close_control_socket();
366     
367     if (am_system_init) {
368         if (shutdown_type == shutdown_type_t::CONTINUE) {
369             // It could be that we started in single user mode, and the
370             // user has now exited the shell. We'll try and re-start the
371             // boot process...
372             try {
373                 services->start_service("boot");
374                 goto event_loop; // yes, the "evil" goto
375             }
376             catch (...) {
377                 // Now what do we do? try to reboot, but wait for user ack to avoid boot loop.
378                 log(LogLevel::ERROR, "Could not start 'boot' service. Will attempt reboot.");
379                 wait_for_user_input();
380                 shutdown_type = shutdown_type_t::REBOOT;
381             }
382         }
383         
384         const char * cmd_arg;
385         if (shutdown_type == shutdown_type_t::HALT) {
386             cmd_arg = "-h";
387         }
388         else if (shutdown_type == shutdown_type_t::REBOOT) {
389             cmd_arg = "-r";
390         }
391         else {
392             // power off.
393             cmd_arg = "-p";
394         }
395         
396         // Fork and execute dinit-reboot.
397         execl("/sbin/shutdown", "/sbin/shutdown", "--system", cmd_arg, nullptr);
398         log(LogLevel::ERROR, "Could not execute /sbin/shutdown: ", strerror(errno));
399         
400         // PID 1 must not actually exit, although we should never reach this point:
401         while (true) {
402             eventLoop.run();
403         }
404     }
405     else if (shutdown_type == shutdown_type_t::REBOOT) {
406         // Non-system-process. If we got SIGINT, let's die due to it:
407         sigset_t sigwait_set;
408         sigemptyset(&sigwait_set);
409         sigaddset(&sigwait_set, SIGINT);
410         raise(SIGINT);
411         sigprocmask(SIG_UNBLOCK, &sigwait_set, NULL);
412     }
413     
414     return 0;
415 }
416
417 // In exception situations we want user confirmation before proceeding (eg on critical boot failure
418 // we wait before rebooting to avoid a reboot loop).
419 static void wait_for_user_input() noexcept
420 {
421     std::cout << "Press Enter to continue." << std::endl;
422     char buf[1];
423     read(STDIN_FILENO, buf, 1);
424 }
425
426 // Callback for control socket
427 static void control_socket_cb(eventloop_t *loop, int sockfd)
428 {
429     // Considered keeping a limit the number of active connections, however, there doesn't
430     // seem much to be gained from that. Only root can create connections and not being
431     // able to establish a control connection is as much a denial-of-service as is not being
432     // able to start a service due to lack of fd's.
433
434     // Accept a connection
435     int newfd = dinit_accept4(sockfd, nullptr, nullptr, SOCK_NONBLOCK | SOCK_CLOEXEC);
436
437     if (newfd != -1) {
438         try {
439             new control_conn_t(loop, services, newfd);  // will delete itself when it's finished
440         }
441         catch (std::exception &exc) {
442             log(LogLevel::ERROR, "Accepting control connection: ", exc.what());
443             close(newfd);
444         }
445     }
446 }
447
448 void open_control_socket(bool report_ro_failure) noexcept
449 {
450     if (! control_socket_open) {
451         const char * saddrname = control_socket_path;
452         size_t saddrname_len = strlen(saddrname);
453         uint sockaddr_size = offsetof(struct sockaddr_un, sun_path) + saddrname_len + 1;
454         
455         struct sockaddr_un * name = static_cast<sockaddr_un *>(malloc(sockaddr_size));
456         if (name == nullptr) {
457             log(LogLevel::ERROR, "Opening control socket: out of memory");
458             return;
459         }
460
461         if (am_system_init) {
462             // Unlink any stale control socket file, but only if we are system init, since otherwise
463             // the 'stale' file may not be stale at all:
464             unlink(saddrname);
465         }
466
467         name->sun_family = AF_UNIX;
468         memcpy(name->sun_path, saddrname, saddrname_len + 1);
469
470         int sockfd = dinit_socket(AF_UNIX, SOCK_STREAM, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
471         if (sockfd == -1) {
472             log(LogLevel::ERROR, "Error creating control socket: ", strerror(errno));
473             free(name);
474             return;
475         }
476
477         if (bind(sockfd, (struct sockaddr *) name, sockaddr_size) == -1) {
478             if (errno != EROFS || report_ro_failure) {
479                 log(LogLevel::ERROR, "Error binding control socket: ", strerror(errno));
480             }
481             close(sockfd);
482             free(name);
483             return;
484         }
485         
486         free(name);
487
488         // No connections can be made until we listen, so it is fine to change the permissions now
489         // (and anyway there is no way to atomically create the socket and set permissions):
490         if (chmod(saddrname, S_IRUSR | S_IWUSR) == -1) {
491             log(LogLevel::ERROR, "Error setting control socket permissions: ", strerror(errno));
492             close(sockfd);
493             return;
494         }
495
496         if (listen(sockfd, 10) == -1) {
497             log(LogLevel::ERROR, "Error listening on control socket: ", strerror(errno));
498             close(sockfd);
499             return;
500         }
501
502         try {
503             control_socket_io.add_watch(eventLoop, sockfd, IN_EVENTS);
504             control_socket_open = true;
505         }
506         catch (std::exception &e)
507         {
508             log(LogLevel::ERROR, "Could not setup I/O on control socket: ", e.what());
509             close(sockfd);
510         }
511     }
512 }
513
514 static void close_control_socket() noexcept
515 {
516     if (control_socket_open) {
517         int fd = control_socket_io.get_watched_fd();
518         control_socket_io.deregister(eventLoop);
519         close(fd);
520         
521         // Unlink the socket:
522         unlink(control_socket_path);
523     }
524 }
525
526 void setup_external_log() noexcept
527 {
528     if (! external_log_open) {
529     
530         const char * saddrname = log_socket_path;
531         size_t saddrname_len = strlen(saddrname);
532         uint sockaddr_size = offsetof(struct sockaddr_un, sun_path) + saddrname_len + 1;
533         
534         struct sockaddr_un * name = static_cast<sockaddr_un *>(malloc(sockaddr_size));
535         if (name == nullptr) {
536             log(LogLevel::ERROR, "Connecting to log socket: out of memory");
537             return;
538         }
539         
540         name->sun_family = AF_UNIX;
541         memcpy(name->sun_path, saddrname, saddrname_len + 1);
542         
543         int sockfd = dinit_socket(AF_UNIX, SOCK_DGRAM, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
544         if (sockfd == -1) {
545             log(LogLevel::ERROR, "Error creating log socket: ", strerror(errno));
546             free(name);
547             return;
548         }
549         
550         if (connect(sockfd, (struct sockaddr *) name, sockaddr_size) == 0 || errno == EINPROGRESS) {
551             // For EINPROGRESS, connection is still being established; however, we can select on
552             // the file descriptor so we will be notified when it's ready. In other words we can
553             // basically use it anyway.
554             try {
555                 setup_main_log(sockfd);
556             }
557             catch (std::exception &e) {
558                 log(LogLevel::ERROR, "Setting up log failed: ", e.what());
559                 close(sockfd);
560             }
561         }
562         else {
563             // Note if connect fails, we haven't warned at all, because the syslog server might not
564             // have started yet.
565             close(sockfd);
566         }
567         
568         free(name);
569     }
570 }
571
572 /* handle SIGINT signal (generated by Linux kernel when ctrl+alt+del pressed) */
573 static void sigint_reboot_cb(eventloop_t &eloop) noexcept
574 {
575     services->stop_all_services(shutdown_type_t::REBOOT);
576 }
577
578 /* handle SIGQUIT (if we are system init) */
579 static void sigquit_cb(eventloop_t &eloop) noexcept
580 {
581     // This performs an immediate shutdown, without service rollback.
582     close_control_socket();
583     execl("/sbin/shutdown", "/sbin/shutdown", "--system", (char *) 0);
584     log(LogLevel::ERROR, "Error executing /sbin/shutdown: ", strerror(errno));
585     sync(); // since a hard poweroff might be required at this point...
586 }
587
588 /* handle SIGTERM/SIGQUIT(non-system-daemon) - stop all services and shut down */
589 static void sigterm_cb(eventloop_t &eloop) noexcept
590 {
591     services->stop_all_services();
592 }