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