Only enable console logging via the service layer (when no services
[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
16 #include "service.h"
17 #include "ev++.h"
18 #include "control.h"
19 #include "dinit-log.h"
20
21 #ifdef __linux__
22 #include <sys/klog.h>
23 #include <sys/reboot.h>
24 #endif
25
26 /*
27  * "simpleinit" from util-linux-ng package handles signals as follows:
28  * SIGTSTP - spawn no more gettys (in preparation for shutdown etc).
29  *           In dinit terms this should probably mean "no more auto restarts"
30  *           (for any service). (Actually the signal acts as a toggle, if
31  *           respawn is disabled it will be re-enabled and init will
32  *           act as if SIGHUP had also been sent)
33  * SIGTERM - kill spawned gettys (which are still alive)
34  *           Interestingly, simpleinit just sends a SIGTERM to the gettys,
35  *           which will not normall kill shells (eg bash ignores SIGTERM).
36  * "/sbin/initctl -r" - rollback services (ran by "shutdown"/halt etc);
37  *           shouldn't return until all services have been stopped.
38  *           shutdown calls this after sending SIGTERM to processes running
39  *           with uid >= 100 ("mortals").
40  * SIGQUIT - init will exec() shutdown. shutdown will detect that it is
41  *           running as pid 1 and will just loop and reap child processes.
42  *           This is used by shutdown so that init will not hang on to its
43  *           inode, allowing the filesystem to be re-mounted readonly
44  *           (this is only an issue if the init binary has been unlinked,
45  *           since it's then holding an inode which can't be maintained
46  *           when the filesystem is unmounted).
47  *
48  * Not sent by shutdown:
49  * SIGHUP -  re-read inittab and spawn any new getty entries
50  * SIGINT - (ctrl+alt+del handler) - fork & exec "reboot"
51  * 
52  * On the contrary dinit currently uses:
53  * SIGTERM - roll back services and then fork/exec /sbin/halt
54  * SIGINT - roll back services and then fork/exec /sbin/reboot
55  * SIGQUIT - exec() /sbin/shutdown as per above.
56  *
57  * It's an open question about whether dinit should roll back services *before*
58  * running halt/reboot, since those commands should prompt rollback of services
59  * anyway. But it seems safe to do so.
60  */
61
62
63 static void sigint_reboot_cb(struct ev_loop *loop, ev_signal *w, int revents);
64 static void sigquit_cb(struct ev_loop *loop, ev_signal *w, int revents);
65 static void sigterm_cb(struct ev_loop *loop, ev_signal *w, int revents);
66 void open_control_socket(struct ev_loop *loop) noexcept;
67 void close_control_socket(struct ev_loop *loop) noexcept;
68
69 struct ev_io control_socket_io;
70
71
72 // Variables
73
74 static ServiceSet *service_set;
75
76 static bool am_system_init = false; // true if we are the system init process
77
78 static bool control_socket_open = false;
79 int active_control_conns = 0;
80
81 // Control socket path. We maintain a string (control_socket_str) in case we need
82 // to allocate storage, but control_socket_path is the authoritative value.
83 static const char *control_socket_path = "/dev/dinitctl";
84 static std::string control_socket_str;
85
86 static const char *user_home_path = nullptr;
87
88
89 // Get user home (and set user_home_path). (The return may become invalid after
90 // changing the evironment (HOME variable) or using the getpwuid() function).
91 const char * get_user_home()
92 {
93     if (user_home_path == nullptr) {
94         user_home_path = getenv("HOME");
95         if (user_home_path == nullptr) {
96             struct passwd * pwuid_p = getpwuid(getuid());
97             if (pwuid_p != nullptr) {
98                 user_home_path = pwuid_p->pw_dir;
99             }
100         }
101     }
102     return user_home_path;
103 }
104
105
106 int main(int argc, char **argv)
107 {
108     using namespace std;
109     
110     am_system_init = (getpid() == 1);
111     const char * service_dir = nullptr;
112     string service_dir_str; // to hold storage for above if necessary
113     bool control_socket_path_set = false;
114
115     // list of services to start
116     list<const char *> services_to_start;
117     
118     // Arguments, if given, specify a list of services to start.
119     // If we are running as init (PID=1), the kernel gives us any command line
120     // arguments it was given but didn't recognize, including "single" (usually
121     // for "boot to single user mode" aka just start the shell). We can treat
122     // them as service names. In the worst case we can't find any of the named
123     // services, and so we'll start the "boot" service by default.
124     if (argc > 1) {
125       for (int i = 1; i < argc; i++) {
126         if (argv[i][0] == '-') {
127             // An option...
128             if (strcmp(argv[i], "--services-dir") == 0 ||
129                     strcmp(argv[i], "-d") == 0) {
130                 if (++i < argc) {
131                     service_dir = argv[i];
132                 }
133                 else {
134                     cerr << "dinit: '--services-dir' (-d) requires an argument" << endl;
135                     return 1;
136                 }
137             }
138             else if (strcmp(argv[i], "--system") == 0 ||
139                     strcmp(argv[i], "-s") == 0) {
140                 am_system_init = true;
141             }
142             else if (strcmp(argv[i], "--socket-path") == 0 ||
143                     strcmp(argv[i], "-p") == 0) {
144                 if (++i < argc) {
145                     control_socket_path = argv[i];
146                     control_socket_path_set = true;
147                 }
148                 else {
149                     cerr << "dinit: '--socket-path' (-p) requires an argument" << endl;
150                     return 1;
151                 }
152             }
153             else if (strcmp(argv[i], "--help") == 0) {
154                 cout << "dinit, an init with dependency management" << endl;
155                 cout << " --help                       display help" << endl;
156                 cout << " --services-dir <dir>, -d <dir>" << endl;
157                 cout << "                              set base directory for service description" << endl;
158                 cout << "                              files (-d <dir>)" << endl;
159                 cout << " --system, -s                 run as the system init process" << endl;
160                 cout << " --socket-path <path>, -p <path>" << endl;
161                 cout << "                              path to control socket" << endl;
162                 cout << " <service-name>               start service with name <service-name>" << endl;
163                 return 0;
164             }
165             else {
166                 // unrecognized
167                 if (! am_system_init) {
168                     cerr << "dinit: Unrecognized option: " << argv[i] << endl;
169                     return 1;
170                 }
171             }
172         }
173         else {
174             // LILO puts "auto" on the kernel command line for unattended boots; we'll filter it.
175             if (! am_system_init || strcmp(argv[i], "auto") != 0) {
176                 services_to_start.push_back(argv[i]);
177             }
178         }
179       }
180     }
181     
182     if (am_system_init) {
183         // setup STDIN, STDOUT, STDERR so that we can use them
184         int onefd = open("/dev/console", O_RDONLY, 0);
185         dup2(onefd, 0);
186         int twofd = open("/dev/console", O_RDWR, 0);
187         dup2(twofd, 1);
188         dup2(twofd, 2);
189         
190         if (onefd > 2) close(onefd);
191         if (twofd > 2) close(twofd);
192     }
193     
194     /* Set up signal handlers etc */
195     /* SIG_CHILD is ignored by default: good */
196     /* sigemptyset(&sigwait_set); */
197     /* sigaddset(&sigwait_set, SIGCHLD); */
198     /* sigaddset(&sigwait_set, SIGINT); */
199     /* sigaddset(&sigwait_set, SIGTERM); */
200     /* sigprocmask(SIG_BLOCK, &sigwait_set, NULL); */
201     
202     // Terminal access control signals - we block these so that dinit can't be
203     // suspended if it writes to the terminal after some other process has claimed
204     // ownership of it.
205     signal(SIGTSTP, SIG_IGN);
206     signal(SIGTTIN, SIG_IGN);
207     signal(SIGTTOU, SIG_IGN);
208     
209     if (! am_system_init && ! control_socket_path_set) {
210         const char * userhome = get_user_home();
211         if (userhome != nullptr) {
212             control_socket_str = userhome;
213             control_socket_str += "/.dinitctl";
214             control_socket_path = control_socket_str.c_str();
215         }
216     }
217     
218     /* service directory name */
219     if (service_dir == nullptr && ! am_system_init) {
220         const char * userhome = get_user_home();
221         if (userhome != nullptr) {
222             service_dir_str = get_user_home();
223             service_dir_str += "/dinit.d";
224             service_dir = service_dir_str.c_str();
225         }
226     }
227     
228     if (service_dir == nullptr) {
229         service_dir = "/etc/dinit.d";
230     }
231     
232     if (services_to_start.empty()) {
233         services_to_start.push_back("boot");
234     }
235
236     // Set up signal handlers
237     ev_signal sigint_ev_signal;
238     if (am_system_init) {
239       ev_signal_init(&sigint_ev_signal, sigint_reboot_cb, SIGINT);
240     }
241     else {
242       ev_signal_init(&sigint_ev_signal, sigterm_cb, SIGINT);
243     }
244     
245     ev_signal sigquit_ev_signal;
246     if (am_system_init) {
247         // PID 1: SIGQUIT exec's shutdown
248         ev_signal_init(&sigquit_ev_signal, sigquit_cb, SIGQUIT);
249     }
250     else {
251         // Otherwise: SIGQUIT terminates dinit
252         ev_signal_init(&sigquit_ev_signal, sigterm_cb, SIGQUIT);
253     }
254     
255     ev_signal sigterm_ev_signal;
256     ev_signal_init(&sigterm_ev_signal, sigterm_cb, SIGTERM);
257     
258     /* Set up libev */
259     struct ev_loop *loop = ev_default_loop(EVFLAG_AUTO /* | EVFLAG_SIGNALFD */);
260     ev_signal_start(loop, &sigint_ev_signal);
261     ev_signal_start(loop, &sigquit_ev_signal);
262     ev_signal_start(loop, &sigterm_ev_signal);
263
264     // Try to open control socket (may fail due to readonly filesystem)
265     open_control_socket(loop);
266     
267 #ifdef __linux__
268     if (am_system_init) {
269         // Disable non-critical kernel output to console
270         klogctl(6 /* SYSLOG_ACTION_CONSOLE_OFF */, nullptr, 0);
271         // Make ctrl+alt+del combination send SIGINT to PID 1 (this process)
272         reboot(RB_DISABLE_CAD);
273     }
274 #endif
275     
276     /* start requested services */
277     service_set = new ServiceSet(service_dir);
278     for (list<const char *>::iterator i = services_to_start.begin();
279             i != services_to_start.end();
280             ++i) {
281         try {
282             service_set->startService(*i);
283         }
284         catch (ServiceNotFound &snf) {
285             log(LogLevel::ERROR, snf.serviceName, ": Could not find service description.");
286         }
287         catch (ServiceLoadExc &sle) {
288             log(LogLevel::ERROR, sle.serviceName, ": ", sle.excDescription);
289         }
290         catch (std::bad_alloc &badalloce) {
291             log(LogLevel::ERROR, "Out of memory when trying to start service: ", *i, ".");
292         }
293     }
294     
295     event_loop:
296     
297     // Process events until all services have terminated.
298     while (service_set->count_active_services() != 0) {
299         ev_loop(loop, EVLOOP_ONESHOT);
300     }
301
302     ShutdownType shutdown_type = service_set->getShutdownType();
303     
304     if (am_system_init) {
305         logMsgBegin(LogLevel::INFO, "No more active services.");
306         
307         if (shutdown_type == ShutdownType::REBOOT) {
308             logMsgEnd(" Will reboot.");
309         }
310         else if (shutdown_type == ShutdownType::HALT) {
311             logMsgEnd(" Will halt.");
312         }
313         else if (shutdown_type == ShutdownType::POWEROFF) {
314             logMsgEnd(" Will power down.");
315         }
316         else {
317             logMsgEnd(" Re-initiating boot sequence.");
318         }
319     }
320     
321     close_control_socket(ev_default_loop(EVFLAG_AUTO));
322     
323     if (am_system_init) {
324         if (shutdown_type == ShutdownType::CONTINUE) {
325             // It could be that we started in single user mode, and the
326             // user has now exited the shell. We'll try and re-start the
327             // boot process...
328             try {
329                 service_set->startService("boot");
330                 goto event_loop; // yes, the "evil" goto
331             }
332             catch (...) {
333                 // Now WTF do we do? try to reboot
334                 log(LogLevel::ERROR, "Could not start 'boot' service; rebooting.");
335                 shutdown_type = ShutdownType::REBOOT;
336             }
337         }
338         
339         const char * cmd_arg;
340         if (shutdown_type == ShutdownType::HALT) {
341             cmd_arg = "-h";
342         }
343         else if (shutdown_type == ShutdownType::REBOOT) {
344             cmd_arg = "-r";
345         }
346         else {
347             // power off.
348             cmd_arg = "-p";
349         }
350         
351         // Fork and execute dinit-reboot.
352         execl("/sbin/shutdown", "/sbin/shutdown", "--system", cmd_arg, nullptr);
353         log(LogLevel::ERROR, "Could not execute /sbin/shutdown: ", strerror(errno));
354         
355         // PID 1 must not actually exit, although we should never reach this point:
356         while (true) {
357             ev_loop(loop, EVLOOP_ONESHOT);
358         }
359     }
360     
361     return 0;
362 }
363
364 // Callback for control socket
365 static void control_socket_cb(struct ev_loop *loop, ev_io *w, int revents)
366 {
367     // TODO limit the number of active connections. Keep a tally, and disable the
368     // control connection listening socket watcher if it gets high, and re-enable
369     // it once it falls below the maximum.
370
371     // Accept a connection
372     int sockfd = w->fd;
373
374     int newfd = accept4(sockfd, nullptr, nullptr, SOCK_NONBLOCK | SOCK_CLOEXEC);
375
376     if (newfd != -1) {
377         try {
378             new ControlConn(loop, service_set, newfd);  // will delete itself when it's finished
379         }
380         catch (std::bad_alloc &bad_alloc_exc) {
381             log(LogLevel::ERROR, "Accepting control connection: Out of memory");
382             close(newfd);
383         }
384     }
385 }
386
387 void open_control_socket(struct ev_loop *loop) noexcept
388 {
389     if (! control_socket_open) {
390         const char * saddrname = control_socket_path;
391         uint sockaddr_size = offsetof(struct sockaddr_un, sun_path) + strlen(saddrname) + 1;
392         
393         struct sockaddr_un * name = static_cast<sockaddr_un *>(malloc(sockaddr_size));
394         if (name == nullptr) {
395             log(LogLevel::ERROR, "Opening control socket: out of memory");
396             return;
397         }
398
399         if (am_system_init) {
400             // Unlink any stale control socket file, but only if we are system init, since otherwise
401             // the 'stale' file may not be stale at all:
402             unlink(saddrname);
403         }
404
405         name->sun_family = AF_UNIX;
406         strcpy(name->sun_path, saddrname);
407
408         // OpenBSD and Linux both allow combining NONBLOCK/CLOEXEC flags with socket type, however
409         // it's not actually POSIX. (TODO).
410         int sockfd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
411         if (sockfd == -1) {
412             log(LogLevel::ERROR, "Error creating control socket: ", strerror(errno));
413             free(name);
414             return;
415         }
416
417         if (bind(sockfd, (struct sockaddr *) name, sockaddr_size) == -1) {
418             log(LogLevel::ERROR, "Error binding control socket: ", strerror(errno));
419             close(sockfd);
420             free(name);
421             return;
422         }
423         
424         free(name);
425
426         // No connections can be made until we listen, so it is fine to change the permissions now
427         // (and anyway there is no way to atomically create the socket and set permissions):
428         if (chmod(saddrname, S_IRUSR | S_IWUSR) == -1) {
429             log(LogLevel::ERROR, "Error setting control socket permissions: ", strerror(errno));
430             close(sockfd);
431             return;
432         }
433
434         if (listen(sockfd, 10) == -1) {
435             log(LogLevel::ERROR, "Error listening on control socket: ", strerror(errno));
436             close(sockfd);
437             return;
438         }
439
440         control_socket_open = true;
441         ev_io_init(&control_socket_io, control_socket_cb, sockfd, EV_READ);
442         ev_io_start(loop, &control_socket_io);
443     }
444 }
445
446 void close_control_socket(struct ev_loop *loop) noexcept
447 {
448     if (control_socket_open) {
449         int fd = control_socket_io.fd;
450         ev_io_stop(loop, &control_socket_io);
451         close(fd);
452         
453         // Unlink the socket:
454         unlink(control_socket_path);
455     }
456 }
457
458 /* handle SIGINT signal (generated by kernel when ctrl+alt+del pressed) */
459 static void sigint_reboot_cb(struct ev_loop *loop, ev_signal *w, int revents)
460 {
461     service_set->stop_all_services(ShutdownType::REBOOT);
462 }
463
464 /* handle SIGQUIT (if we are system init) */
465 static void sigquit_cb(struct ev_loop *loop, ev_signal *w, int revents)
466 {
467     // This allows remounting the filesystem read-only if the dinit binary has been
468     // unlinked. In that case the kernel holds the binary open, so that it can't be
469     // properly removed.
470     close_control_socket(ev_default_loop(EVFLAG_AUTO));
471     execl("/sbin/shutdown", "/sbin/shutdown", (char *) 0);
472     log(LogLevel::ERROR, "Error executing /sbin/shutdown: ", strerror(errno));
473 }
474
475 /* handle SIGTERM/SIGQUIT - stop all services (not used for system daemon) */
476 static void sigterm_cb(struct ev_loop *loop, ev_signal *w, int revents)
477 {
478     service_set->stop_all_services();
479 }