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