dinit.cc 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143
  1. #include <iostream>
  2. #include <fstream>
  3. #include <list>
  4. #include <cstring>
  5. #include <csignal>
  6. #include <cstddef>
  7. #include <cstdlib>
  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. #include <termios.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. #include <dasynq.h>
  25. #include "dinit.h"
  26. #include "service.h"
  27. #include "control.h"
  28. #include "dinit-log.h"
  29. #include "dinit-socket.h"
  30. #include "static-string.h"
  31. #include "dinit-utmp.h"
  32. #include "options-processing.h"
  33. #include "mconfig.h"
  34. /*
  35. * When running as the system init process, Dinit processes the following signals:
  36. *
  37. * SIGTERM - roll back services and then fork/exec /sbin/halt
  38. * SIGINT - roll back services and then fork/exec /sbin/reboot
  39. * SIGQUIT - exec() /sbin/shutdown without rolling back services
  40. *
  41. * It's an open question about whether Dinit should roll back services *before*
  42. * running halt/reboot, since those commands should prompt rollback of services
  43. * anyway. But it seems safe to do so, and it means the user can at least stop
  44. * services even if the halt/reboot commands are unavailable for some reason.
  45. */
  46. using namespace cts;
  47. using eventloop_t = dasynq::event_loop<dasynq::null_mutex>;
  48. eventloop_t event_loop(dasynq::delayed_init {});
  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 bool open_control_socket(bool report_ro_failure = true) noexcept;
  53. static void close_control_socket() noexcept;
  54. static void confirm_restart_boot() noexcept;
  55. static void flush_log() noexcept;
  56. static void control_socket_cb(eventloop_t *loop, int fd) noexcept;
  57. #ifdef SUPPORT_CGROUPS
  58. static void find_cgroup_path() noexcept;
  59. #endif
  60. static void printVersion();
  61. // Variables
  62. static dirload_service_set *services;
  63. static bool am_system_mgr = false; // true if we are PID 1
  64. static bool am_system_init = false; // true if we are the system init process
  65. static bool did_log_boot = false;
  66. static bool control_socket_open = false;
  67. bool external_log_open = false;
  68. int active_control_conns = 0;
  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 = SYSCONTROLSOCKET;
  72. static std::string control_socket_str;
  73. static const char *env_file_path = "/etc/dinit/environment";
  74. static const char *log_path = "/dev/log";
  75. static bool log_is_syslog = true; // if false, log is a file
  76. // Set to true (when console_input_watcher is active) if console input becomes available
  77. static bool console_input_ready = false;
  78. #ifdef SUPPORT_CGROUPS
  79. // Path of the root cgroup according to dinit. This will be dinit's own cgroup path.
  80. std::string cgroups_path;
  81. bool have_cgroups_path = false;
  82. #endif
  83. namespace {
  84. // Event-loop handler for a signal, which just delegates to a function (pointer).
  85. class callback_signal_handler : public eventloop_t::signal_watcher_impl<callback_signal_handler>
  86. {
  87. using rearm = dasynq::rearm;
  88. public:
  89. typedef void (*cb_func_t)(eventloop_t &);
  90. private:
  91. cb_func_t cb_func;
  92. public:
  93. callback_signal_handler() : cb_func(nullptr) { }
  94. callback_signal_handler(cb_func_t pcb_func) : cb_func(pcb_func) { }
  95. void set_cb_func(cb_func_t cb_func)
  96. {
  97. this->cb_func = cb_func;
  98. }
  99. rearm received(eventloop_t &eloop, int signo, siginfo_p siginfo)
  100. {
  101. cb_func(eloop);
  102. return rearm::REARM;
  103. }
  104. };
  105. // Event-loop handler for when a connection is made to the control socket.
  106. class control_socket_watcher : public eventloop_t::fd_watcher_impl<control_socket_watcher>
  107. {
  108. using rearm = dasynq::rearm;
  109. public:
  110. rearm fd_event(eventloop_t &loop, int fd, int flags) noexcept
  111. {
  112. control_socket_cb(&loop, fd);
  113. return rearm::REARM;
  114. }
  115. };
  116. // Watch for console input and set a flag when it is available.
  117. class console_input_watcher : public eventloop_t::fd_watcher_impl<console_input_watcher>
  118. {
  119. using rearm = dasynq::rearm;
  120. public:
  121. rearm fd_event(eventloop_t &loop, int fd, int flags) noexcept
  122. {
  123. console_input_ready = true;
  124. return rearm::DISARM;
  125. }
  126. };
  127. // Simple timer used to limit the amount of time waiting for the log flush to complete (at shutdown)
  128. class log_flush_timer_t : public eventloop_t::timer_impl<log_flush_timer_t>
  129. {
  130. using rearm = dasynq::rearm;
  131. bool expired;
  132. public:
  133. rearm timer_expiry(eventloop_t &, int expiry_count)
  134. {
  135. expired = true;
  136. return rearm::DISARM;
  137. }
  138. bool has_expired()
  139. {
  140. return expired;
  141. }
  142. void reset()
  143. {
  144. expired = false;
  145. }
  146. };
  147. control_socket_watcher control_socket_io;
  148. console_input_watcher console_input_io;
  149. log_flush_timer_t log_flush_timer;
  150. // These need to be at namespace scope to prevent causing stack allocations when using them:
  151. constexpr auto shutdown_exec = literal(SBINDIR) + "/" + SHUTDOWN_PREFIX + "shutdown";
  152. constexpr auto error_exec_sd = literal("Error executing ") + shutdown_exec + ": ";
  153. }
  154. // Options handled in dinit_main
  155. struct options {
  156. const char * env_file = nullptr;
  157. bool control_socket_path_set = false;
  158. bool env_file_set = false;
  159. bool log_specified = false;
  160. bool process_sys_args = false;
  161. service_dir_opt service_dir_opts;
  162. // list of services to start
  163. std::list<const char *> services_to_start;
  164. };
  165. // Process a command line argument (and possibly its follow-up value)
  166. // Returns -1 for clean exit required, 0 for success, 1 for error exit required
  167. static int process_commandline_arg(char **argv, int argc, int &i, options &opts)
  168. {
  169. using std::cerr;
  170. using std::cout;
  171. using std::endl;
  172. using std::list;
  173. const char * &env_file = opts.env_file;
  174. bool &control_socket_path_set = opts.control_socket_path_set;
  175. bool &env_file_set = opts.env_file_set;
  176. bool &log_specified = opts.log_specified;
  177. service_dir_opt &service_dir_opts = opts.service_dir_opts;
  178. list<const char *> &services_to_start = opts.services_to_start;
  179. if (argv[i][0] == '-') {
  180. // An option...
  181. if (strcmp(argv[i], "--env-file") == 0 || strcmp(argv[i], "-e") == 0) {
  182. if (++i < argc) {
  183. env_file_set = true;
  184. env_file = argv[i];
  185. }
  186. else {
  187. cerr << "dinit: '--env-file' (-e) requires an argument\n";
  188. return 1;
  189. }
  190. }
  191. else if (strcmp(argv[i], "--services-dir") == 0 || strcmp(argv[i], "-d") == 0) {
  192. if (++i < argc) {
  193. service_dir_opts.set_specified_service_dir(argv[i]);
  194. }
  195. else {
  196. cerr << "dinit: '--services-dir' (-d) requires an argument\n";
  197. return 1;
  198. }
  199. }
  200. else if (strcmp(argv[i], "--system") == 0 || strcmp(argv[i], "-s") == 0) {
  201. am_system_init = true;
  202. }
  203. else if (strcmp(argv[i], "--system-mgr") == 0 || strcmp(argv[i], "-m") == 0) {
  204. am_system_mgr = true;
  205. opts.process_sys_args = false;
  206. }
  207. else if (strcmp(argv[i], "--user") == 0 || strcmp(argv[i], "-u") == 0) {
  208. am_system_init = false;
  209. }
  210. else if (strcmp(argv[i], "--container") == 0 || strcmp(argv[i], "-o") == 0) {
  211. am_system_mgr = false;
  212. opts.process_sys_args = false;
  213. }
  214. else if (strcmp(argv[i], "--socket-path") == 0 || strcmp(argv[i], "-p") == 0) {
  215. if (++i < argc) {
  216. control_socket_path = argv[i];
  217. control_socket_path_set = true;
  218. }
  219. else {
  220. cerr << "dinit: '--socket-path' (-p) requires an argument\n";
  221. return 1;
  222. }
  223. }
  224. else if (strcmp(argv[i], "--log-file") == 0 || strcmp(argv[i], "-l") == 0) {
  225. if (++i < argc) {
  226. log_path = argv[i];
  227. log_is_syslog = false;
  228. log_specified = true;
  229. }
  230. else {
  231. cerr << "dinit: '--log-file' (-l) requires an argument\n";
  232. return 1;
  233. }
  234. }
  235. else if (strcmp(argv[i], "--quiet") == 0 || strcmp(argv[i], "-q") == 0) {
  236. console_service_status = false;
  237. log_level[DLOG_CONS] = loglevel_t::ZERO;
  238. }
  239. #ifdef SUPPORT_CGROUPS
  240. else if (strcmp(argv[i], "--cgroup-path") == 0 || strcmp(argv[i], "-b") == 0) {
  241. if (++i < argc) {
  242. cgroups_path = argv[i];
  243. have_cgroups_path = true;
  244. }
  245. else {
  246. cerr << "dinit: '--cgroup-path' (-b) requires an argument\n";
  247. return 1;
  248. }
  249. }
  250. #endif
  251. else if (strcmp(argv[i], "--version") == 0) {
  252. printVersion();
  253. return -1;
  254. }
  255. else if (strcmp(argv[i], "--help") == 0) {
  256. cout << "dinit: init/service manager daemon\n"
  257. " --help display (this) help\n"
  258. " --version display version\n"
  259. " --env-file <file>, -e <file>\n"
  260. " environment variable initialisation file\n"
  261. " --services-dir <dir>, -d <dir>\n"
  262. " set base directory for service description\n"
  263. " files, can be specified multiple times\n"
  264. " --system, -s run as the system service manager\n"
  265. " --system-mgr, -m run as system manager (perform shutdown etc)\n"
  266. " --user, -u run as a user service manager\n"
  267. " --container, -o run in container mode (do not manage system)\n"
  268. " --socket-path <path>, -p <path>\n"
  269. " path to control socket\n"
  270. #ifdef SUPPORT_CGROUPS
  271. " --cgroup-path <path>, -b <path>\n"
  272. " cgroup base path (for resolving relative paths)\n"
  273. #endif
  274. " --log-file <file>, -l <file> log to the specified file\n"
  275. " --quiet, -q disable output to standard output\n"
  276. " <service-name> [...] start service with name <service-name>\n";
  277. return -1;
  278. }
  279. else {
  280. // unrecognized
  281. if (!opts.process_sys_args) {
  282. cerr << "dinit: unrecognized option: " << argv[i] << endl;
  283. return 1;
  284. }
  285. }
  286. }
  287. else {
  288. #ifdef __linux__
  289. // If we are running as init (PID=1), the Linux kernel gives us all command line arguments it was
  290. // given but didn't recognize, and, uh, *some* that it did recognize, which means we can't assume
  291. // that anything is a service name (for example "nopti" seems to get passed through to init).
  292. // However, we can look for special names that we know aren't kernel parameters, such as "single".
  293. //
  294. // (Note this may have been fixed in recent kernels: see changelog for 5.15.46/5.18.3,
  295. // "x86: Fix return value of __setup handlers")
  296. //
  297. // LILO puts "auto" on the command line for unattended boots, but we don't care about that and want
  298. // it filtered.
  299. //
  300. // We don't expect to see options beginning with '-' appear on the kernel command line either, so we
  301. // can interpret those as dinit arguments. In particular if we see -m or -o, we assume that every
  302. // name we see from then is a service name (i.e. process_sys_args is set false when we seem them,
  303. // see above).
  304. //
  305. // (Note, you can give "--" on the kernel command line to pass every option from that point to init
  306. // directly, but init doesn't see the "--" itself, which makes it less useful, since we still can't
  307. // tell whether a "name" was intended as a kernel parameter or init parameter).
  308. // So, long story short: if we think we're PID 1 and we haven't seen -m or -c options yet, only
  309. // recognise "single" as a service name and ignore everything else.
  310. if (!opts.process_sys_args || strcmp(argv[i], "single") == 0) {
  311. services_to_start.push_back(argv[i]);
  312. }
  313. #else
  314. services_to_start.push_back(argv[i]);
  315. #endif
  316. }
  317. return 0;
  318. }
  319. // Main entry point
  320. int dinit_main(int argc, char **argv)
  321. {
  322. using namespace std;
  323. am_system_mgr = (getpid() == 1);
  324. am_system_init = (getuid() == 0);
  325. struct options opts;
  326. // if we are PID 1 and user id 0, we are *most probably* the system init. (Or on linux at least, we
  327. // could instead be in a container; then we expect -o argument and unset this then).
  328. opts.process_sys_args = am_system_mgr && am_system_init;
  329. const char * &env_file = opts.env_file;
  330. bool &control_socket_path_set = opts.control_socket_path_set;
  331. bool &env_file_set = opts.env_file_set;
  332. bool &log_specified = opts.log_specified;
  333. service_dir_opt &service_dir_opts = opts.service_dir_opts;
  334. list<const char *> &services_to_start = opts.services_to_start;
  335. for (int i = 1; i < argc; i++) {
  336. int p = process_commandline_arg(argv, argc, i, opts);
  337. if (p == -1) {
  338. // clean exit
  339. return 0;
  340. }
  341. if (p == 1) {
  342. // error exit
  343. return 1;
  344. }
  345. }
  346. if (am_system_mgr) {
  347. // setup STDIN, STDOUT, STDERR so that we can use them
  348. int onefd = open("/dev/console", O_RDONLY, 0);
  349. if (onefd != -1) {
  350. dup2(onefd, 0);
  351. }
  352. int twofd = open("/dev/console", O_RDWR, 0);
  353. if (twofd != -1) {
  354. dup2(twofd, 1);
  355. dup2(twofd, 2);
  356. }
  357. if (onefd > 2) close(onefd);
  358. if (twofd > 2) close(twofd);
  359. if (! env_file_set) {
  360. env_file = env_file_path;
  361. }
  362. // we will assume an empty cgroups root path
  363. #if SUPPORT_CGROUPS
  364. have_cgroups_path = true;
  365. #endif
  366. }
  367. /* Set up signal handlers etc */
  368. sigset_t sigwait_set;
  369. sigemptyset(&sigwait_set);
  370. sigaddset(&sigwait_set, SIGCHLD);
  371. sigaddset(&sigwait_set, SIGINT);
  372. sigaddset(&sigwait_set, SIGTERM);
  373. if (am_system_mgr) sigaddset(&sigwait_set, SIGQUIT);
  374. sigprocmask(SIG_BLOCK, &sigwait_set, NULL);
  375. // Terminal access control signals - we ignore these so that dinit can't be
  376. // suspended if it writes to the terminal after some other process has claimed
  377. // ownership of it.
  378. signal(SIGTSTP, SIG_IGN);
  379. signal(SIGTTIN, SIG_IGN);
  380. signal(SIGTTOU, SIG_IGN);
  381. signal(SIGPIPE, SIG_IGN);
  382. event_loop.init();
  383. if (!am_system_init && !control_socket_path_set) {
  384. const char * rundir = getenv("XDG_RUNTIME_DIR");
  385. const char * sockname = "dinitctl";
  386. if (rundir == nullptr) {
  387. rundir = service_dir_opt::get_user_home();
  388. sockname = ".dinitctl";
  389. }
  390. if (rundir != nullptr) {
  391. control_socket_str = rundir;
  392. control_socket_str.push_back('/');
  393. control_socket_str += sockname;
  394. control_socket_path = control_socket_str.c_str();
  395. }
  396. }
  397. if (services_to_start.empty()) {
  398. services_to_start.push_back("boot");
  399. }
  400. // Set up signal handlers
  401. callback_signal_handler sigterm_watcher {sigterm_cb};
  402. callback_signal_handler sigint_watcher;
  403. callback_signal_handler sigquit_watcher;
  404. if (am_system_mgr) {
  405. sigint_watcher.set_cb_func(sigint_reboot_cb);
  406. sigquit_watcher.set_cb_func(sigquit_cb);
  407. }
  408. else {
  409. sigint_watcher.set_cb_func(sigterm_cb);
  410. }
  411. sigint_watcher.add_watch(event_loop, SIGINT);
  412. sigterm_watcher.add_watch(event_loop, SIGTERM);
  413. if (am_system_mgr) {
  414. // PID 1: we may ask for console input; SIGQUIT exec's shutdown
  415. console_input_io.add_watch(event_loop, STDIN_FILENO, dasynq::IN_EVENTS, false);
  416. sigquit_watcher.add_watch(event_loop, SIGQUIT);
  417. // (If not PID 1, we instead just let SIGQUIT perform the default action.)
  418. }
  419. init_log(log_is_syslog);
  420. log_flush_timer.add_timer(event_loop, dasynq::clock_type::MONOTONIC);
  421. #if SUPPORT_CGROUPS
  422. if (!have_cgroups_path) {
  423. find_cgroup_path();
  424. // We will press on if the cgroup root path could not be identified, since services might
  425. // not require cgroups anyway and/or might only specify absolute cgroups paths.
  426. }
  427. #endif
  428. // Try to open control socket (may fail due to readonly filesystem, we ignore that if we are
  429. // system init)
  430. if (!open_control_socket(!am_system_init)) {
  431. flush_log();
  432. return EXIT_FAILURE;
  433. }
  434. #ifdef __linux__
  435. if (am_system_mgr) {
  436. // Disable non-critical kernel output to console
  437. klogctl(6 /* SYSLOG_ACTION_CONSOLE_OFF */, nullptr, 0);
  438. // Make ctrl+alt+del combination send SIGINT to PID 1 (this process)
  439. reboot(RB_DISABLE_CAD);
  440. }
  441. // Mark ourselves as a subreaper. This means that if a process we start double-forks, the
  442. // orphaned child will re-parent to us rather than to PID 1 (although that could be us too).
  443. prctl(PR_SET_CHILD_SUBREAPER, 1);
  444. #elif defined(__FreeBSD__) || defined(__DragonFly__)
  445. // Documentation (man page) for this kind-of sucks. PROC_REAP_ACQUIRE "acquires the reaper status for
  446. // the current process" but does that mean the first two arguments still need valid values to be
  447. // supplied? We'll play it safe and explicitly target our own process:
  448. procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL);
  449. #endif
  450. service_dir_opts.build_paths(am_system_init);
  451. // Start requested services
  452. services = new dirload_service_set(std::move(service_dir_opts.get_paths()));
  453. setup_log_console_handoff(services);
  454. if (am_system_init) {
  455. log(loglevel_t::NOTICE, false, "Starting system");
  456. }
  457. // Only try to set up the external log now if we aren't the system init. (If we are the
  458. // system init, wait until the log service starts).
  459. if (!am_system_init && log_specified) setup_external_log();
  460. if (env_file != nullptr) {
  461. read_env_file(env_file);
  462. }
  463. for (auto svc : services_to_start) {
  464. try {
  465. services->start_service(svc);
  466. // Note in general if we fail to start a service we don't need any special error handling,
  467. // since we either leave other services running or, if it was the only service, then no
  468. // services will be running and we will process normally (reboot if system process,
  469. // exit if user process).
  470. }
  471. catch (service_not_found &snf) {
  472. log(loglevel_t::ERROR, snf.service_name, ": could not find service description.");
  473. }
  474. catch (service_description_exc &sde) {
  475. log_service_load_failure(sde);
  476. }
  477. catch (service_load_exc &sle) {
  478. log(loglevel_t::ERROR, sle.service_name, ": ", sle.exc_description);
  479. }
  480. catch (std::bad_alloc &badalloce) {
  481. log(loglevel_t::ERROR, "Out of memory when trying to start service: ", svc, ".");
  482. break;
  483. }
  484. }
  485. run_event_loop:
  486. // Process events until all services have terminated.
  487. while (services->count_active_services() != 0) {
  488. event_loop.run();
  489. }
  490. shutdown_type_t shutdown_type = services->get_shutdown_type();
  491. if (shutdown_type == shutdown_type_t::REMAIN) {
  492. goto run_event_loop;
  493. }
  494. if (am_system_mgr) {
  495. log_msg_begin(loglevel_t::NOTICE, "No more active services.");
  496. if (shutdown_type == shutdown_type_t::REBOOT) {
  497. log_msg_end(" Will reboot.");
  498. }
  499. else if (shutdown_type == shutdown_type_t::HALT) {
  500. log_msg_end(" Will halt.");
  501. }
  502. else if (shutdown_type == shutdown_type_t::POWEROFF) {
  503. log_msg_end(" Will power down.");
  504. }
  505. }
  506. flush_log();
  507. close_control_socket();
  508. if (am_system_mgr) {
  509. if (shutdown_type == shutdown_type_t::NONE) {
  510. // Services all stopped but there was no shutdown issued. Inform user, wait for ack, and
  511. // re-start boot sequence.
  512. sync(); // Sync to minimise data loss if user elects to power off / hard reset
  513. confirm_restart_boot();
  514. if (services->count_active_services() != 0) {
  515. // Recovery service started
  516. goto run_event_loop;
  517. }
  518. shutdown_type = services->get_shutdown_type();
  519. if (shutdown_type == shutdown_type_t::NONE) {
  520. try {
  521. services->start_service("boot");
  522. goto run_event_loop; // yes, the "evil" goto
  523. }
  524. catch (...) {
  525. // Now what do we do? try to reboot, but wait for user ack to avoid boot loop.
  526. log(loglevel_t::ERROR, "Could not start 'boot' service. Will attempt reboot.");
  527. shutdown_type = shutdown_type_t::REBOOT;
  528. }
  529. }
  530. }
  531. const char * cmd_arg;
  532. if (shutdown_type == shutdown_type_t::HALT) {
  533. cmd_arg = "-h";
  534. }
  535. else if (shutdown_type == shutdown_type_t::REBOOT) {
  536. cmd_arg = "-r";
  537. }
  538. else {
  539. // power off.
  540. cmd_arg = "-p";
  541. }
  542. // Fork and execute dinit-reboot.
  543. execl(shutdown_exec.c_str(), shutdown_exec.c_str(), "--system", cmd_arg, nullptr);
  544. log(loglevel_t::ERROR, error_exec_sd, strerror(errno));
  545. // PID 1 must not actually exit, although we should never reach this point:
  546. while (true) {
  547. event_loop.run();
  548. }
  549. }
  550. else if (shutdown_type == shutdown_type_t::REBOOT) {
  551. // Non-system-process. If we got SIGINT, let's die due to it:
  552. sigset_t sigwait_set_int;
  553. sigemptyset(&sigwait_set_int);
  554. sigaddset(&sigwait_set_int, SIGINT);
  555. raise(SIGINT);
  556. sigprocmask(SIG_UNBLOCK, &sigwait_set_int, NULL);
  557. }
  558. return 0;
  559. }
  560. // Log a parse error when reading the environment file.
  561. static void log_bad_env(int linenum)
  562. {
  563. log(loglevel_t::ERROR, "Invalid environment variable setting in environment file (line ", linenum, ")");
  564. }
  565. // Read and set environment variables from a file. May throw std::bad_alloc, std::system_error.
  566. void read_env_file(const char *env_file_path)
  567. {
  568. // Note that we can't use the log in this function; it hasn't been initialised yet.
  569. std::ifstream env_file(env_file_path);
  570. if (! env_file) return;
  571. env_file.exceptions(std::ios::badbit);
  572. auto &clocale = std::locale::classic();
  573. std::string line;
  574. int linenum = 0;
  575. while (std::getline(env_file, line)) {
  576. linenum++;
  577. auto lpos = line.begin();
  578. auto lend = line.end();
  579. while (lpos != lend && std::isspace(*lpos, clocale)) {
  580. ++lpos;
  581. }
  582. if (lpos != lend) {
  583. if (*lpos != '#') {
  584. if (*lpos == '=') {
  585. log_bad_env(linenum);
  586. continue;
  587. }
  588. auto name_begin = lpos++;
  589. // skip until '=' or whitespace:
  590. while (lpos != lend && *lpos != '=' && ! std::isspace(*lpos, clocale)) ++lpos;
  591. auto name_end = lpos;
  592. // skip whitespace:
  593. while (lpos != lend && std::isspace(*lpos, clocale)) ++lpos;
  594. if (lpos == lend) {
  595. log_bad_env(linenum);
  596. continue;
  597. }
  598. ++lpos;
  599. auto val_begin = lpos;
  600. while (lpos != lend && *lpos != '\n') ++lpos;
  601. auto val_end = lpos;
  602. std::string name = line.substr(name_begin - line.begin(), name_end - name_begin);
  603. std::string value = line.substr(val_begin - line.begin(), val_end - val_begin);
  604. if (setenv(name.c_str(), value.c_str(), true) == -1) {
  605. throw std::system_error(errno, std::system_category());
  606. }
  607. }
  608. }
  609. }
  610. }
  611. // Get user confirmation before proceeding with restarting boot sequence.
  612. // Returns after confirmation, possibly with shutdown type altered.
  613. static void confirm_restart_boot() noexcept
  614. {
  615. // Bypass log; we want to make certain the message is seen:
  616. std::cout << "All services have stopped with no shutdown issued; boot failure?\n";
  617. // Drain input, set non-canonical input mode (receive characters as they are typed)
  618. struct termios term_attr;
  619. if (tcgetattr(STDIN_FILENO, &term_attr) != 0) {
  620. // Not a terminal?
  621. std::cout << "Halting." << std::endl;
  622. services->stop_all_services(shutdown_type_t::HALT);
  623. return;
  624. }
  625. term_attr.c_lflag &= ~ICANON;
  626. tcsetattr(STDIN_FILENO, TCSAFLUSH, &term_attr);
  627. // Set non-blocking mode
  628. int origFlags = fcntl(STDIN_FILENO, F_GETFL);
  629. fcntl(STDIN_FILENO, F_SETFL, origFlags | O_NONBLOCK);
  630. do_prompt:
  631. std::cout << "Choose: (r)eboot, r(e)covery, re(s)tart boot sequence, (p)ower off? " << std::flush;
  632. console_input_io.set_enabled(event_loop, true);
  633. do {
  634. event_loop.run();
  635. } while (! console_input_ready && services->get_shutdown_type() == shutdown_type_t::NONE);
  636. console_input_io.set_enabled(event_loop, false);
  637. // We either have input, or shutdown type has been set, or both.
  638. if (console_input_ready) {
  639. console_input_ready = false;
  640. char buf[1];
  641. int r = read(STDIN_FILENO, buf, 1); // read a single character, to make sure we wait for input
  642. if (r == 1) {
  643. std::cout << "\n"; // force new line after input
  644. if (buf[0] == 'r' || buf[0] == 'R') {
  645. services->stop_all_services(shutdown_type_t::REBOOT);
  646. }
  647. else if (buf[0] == 'e' || buf[0] == 'E') {
  648. try {
  649. services->start_service("recovery");
  650. }
  651. catch (...) {
  652. std::cout << "Unable to start recovery service.\n";
  653. goto do_prompt;
  654. }
  655. }
  656. else if (buf[0] == 's' || buf[0] == 'S') {
  657. // nothing - leave no shutdown type
  658. }
  659. else if (buf[0] == 'p' || buf[0] == 'P') {
  660. services->stop_all_services(shutdown_type_t::POWEROFF);
  661. }
  662. else {
  663. goto do_prompt;
  664. }
  665. }
  666. tcflush(STDIN_FILENO, TCIFLUSH); // discard the rest of input
  667. }
  668. term_attr.c_lflag |= ICANON;
  669. tcsetattr(STDIN_FILENO, TCSANOW, &term_attr);
  670. fcntl(STDIN_FILENO, F_SETFL, origFlags);
  671. }
  672. // Callback for control socket
  673. static void control_socket_cb(eventloop_t *loop, int sockfd) noexcept
  674. {
  675. // Considered keeping a limit the number of active connections, however, there doesn't
  676. // seem much to be gained from that. Only root can create connections and not being
  677. // able to establish a control connection is as much a denial-of-service as is not being
  678. // able to start a service due to lack of fd's.
  679. // Accept a connection
  680. int newfd = dinit_accept4(sockfd, nullptr, nullptr, SOCK_NONBLOCK | SOCK_CLOEXEC);
  681. if (newfd != -1) {
  682. try {
  683. new control_conn_t(*loop, services, newfd); // will delete itself when it's finished
  684. }
  685. catch (std::exception &exc) {
  686. log(loglevel_t::ERROR, "Error accepting control connection: ", exc.what());
  687. close(newfd);
  688. }
  689. }
  690. }
  691. // Callback when the root filesystem is read/write:
  692. void rootfs_is_rw() noexcept
  693. {
  694. open_control_socket(true);
  695. if (! did_log_boot) {
  696. did_log_boot = log_boot();
  697. }
  698. }
  699. // Open/create the control socket, normally /dev/dinitctl, used to allow client programs to connect
  700. // and issue service orders and shutdown commands etc. This can safely be called multiple times;
  701. // once the socket has been successfully opened, further calls will check the socket file is still
  702. // present and re-create it if not.
  703. static bool open_control_socket(bool report_ro_failure) noexcept
  704. {
  705. if (control_socket_open) {
  706. struct stat stat_buf;
  707. if (stat(control_socket_path, &stat_buf) != 0 && errno == ENOENT) {
  708. // Looks like our control socket has disappeared from the filesystem. Close our control
  709. // socket and re-create it:
  710. control_socket_io.deregister(event_loop);
  711. close(control_socket_io.get_watched_fd());
  712. control_socket_open = false; // now re-open below
  713. }
  714. }
  715. if (! control_socket_open) {
  716. const char * saddrname = control_socket_path;
  717. size_t saddrname_len = strlen(saddrname);
  718. uint sockaddr_size = offsetof(struct sockaddr_un, sun_path) + saddrname_len + 1;
  719. struct sockaddr_un * name = static_cast<sockaddr_un *>(malloc(sockaddr_size));
  720. if (name == nullptr) {
  721. log(loglevel_t::ERROR, "Opening control socket: out of memory");
  722. return false;
  723. }
  724. name->sun_family = AF_UNIX;
  725. memcpy(name->sun_path, saddrname, saddrname_len + 1);
  726. int sockfd = dinit_socket(AF_UNIX, SOCK_STREAM, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
  727. if (sockfd == -1) {
  728. log(loglevel_t::ERROR, "Error creating control socket: ", strerror(errno));
  729. free(name);
  730. return false;
  731. }
  732. // Check if there is already an active control socket (from another instance).
  733. // Unfortunately, there's no way to check atomically if a socket file is stale. Still, we
  734. // will try to check, since the consequences of running a system dinit instance twice are
  735. // potentially severe.
  736. int connr = connect(sockfd, (struct sockaddr *) name, sockaddr_size);
  737. if (connr != -1 || errno == EAGAIN) {
  738. log(loglevel_t::ERROR, "Control socket is already active"
  739. " (another instance already running?)");
  740. close(connr);
  741. close(sockfd);
  742. free(name);
  743. return false;
  744. }
  745. // Unlink any stale control socket file.
  746. //
  747. // In the worst case, this potentially removes a socket which was not active at the time
  748. // we checked (just above) but has since become active; there's just no good API to avoid
  749. // this (we'd have to use a file lock, on yet another file). Since that's unlikely to
  750. // occur in practice, and because a stale socket will prevent communication with dinit (or
  751. // prevent it starting), then we'll take the chance on unlinking here.
  752. unlink(saddrname);
  753. if (bind(sockfd, (struct sockaddr *) name, sockaddr_size) == -1) {
  754. if (errno != EROFS || report_ro_failure) {
  755. log(loglevel_t::ERROR, "Error binding control socket: ", strerror(errno));
  756. }
  757. close(sockfd);
  758. free(name);
  759. return (errno != EROFS || report_ro_failure);
  760. }
  761. free(name);
  762. // No connections can be made until we listen, so it is fine to change the permissions now
  763. // (and anyway there is no way to atomically create the socket and set permissions):
  764. if (chmod(saddrname, S_IRUSR | S_IWUSR) == -1) {
  765. log(loglevel_t::ERROR, "Error setting control socket permissions: ", strerror(errno));
  766. close(sockfd);
  767. return false;
  768. }
  769. if (listen(sockfd, 10) == -1) {
  770. log(loglevel_t::ERROR, "Error listening on control socket: ", strerror(errno));
  771. close(sockfd);
  772. return false;
  773. }
  774. try {
  775. control_socket_io.add_watch(event_loop, sockfd, dasynq::IN_EVENTS);
  776. control_socket_open = true;
  777. }
  778. catch (std::exception &e)
  779. {
  780. log(loglevel_t::ERROR, "Could not setup I/O on control socket: ", e.what());
  781. close(sockfd);
  782. }
  783. }
  784. return control_socket_open;
  785. }
  786. static void close_control_socket() noexcept
  787. {
  788. if (control_socket_open) {
  789. int fd = control_socket_io.get_watched_fd();
  790. control_socket_io.deregister(event_loop);
  791. close(fd);
  792. // Unlink the socket:
  793. unlink(control_socket_path);
  794. control_socket_open = false;
  795. }
  796. }
  797. void setup_external_log() noexcept
  798. {
  799. if (! external_log_open) {
  800. if (log_is_syslog) {
  801. const char * saddrname = log_path;
  802. size_t saddrname_len = strlen(saddrname);
  803. uint sockaddr_size = offsetof(struct sockaddr_un, sun_path) + saddrname_len + 1;
  804. struct sockaddr_un * name = static_cast<sockaddr_un *>(malloc(sockaddr_size));
  805. if (name == nullptr) {
  806. log(loglevel_t::ERROR, "Connecting to log socket: out of memory");
  807. return;
  808. }
  809. name->sun_family = AF_UNIX;
  810. memcpy(name->sun_path, saddrname, saddrname_len + 1);
  811. int sockfd = dinit_socket(AF_UNIX, SOCK_DGRAM, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
  812. if (sockfd == -1) {
  813. log(loglevel_t::ERROR, "Error creating log socket: ", strerror(errno));
  814. free(name);
  815. return;
  816. }
  817. if (connect(sockfd, (struct sockaddr *) name, sockaddr_size) == 0 || errno == EINPROGRESS) {
  818. // For EINPROGRESS, connection is still being established; however, we can select on
  819. // the file descriptor so we will be notified when it's ready. In other words we can
  820. // basically use it anyway.
  821. try {
  822. setup_main_log(sockfd);
  823. external_log_open = true;
  824. }
  825. catch (std::exception &e) {
  826. log(loglevel_t::ERROR, "Setting up log failed: ", e.what());
  827. close(sockfd);
  828. }
  829. }
  830. else {
  831. // Note if connect fails, we haven't warned at all, because the syslog server might not
  832. // have started yet.
  833. close(sockfd);
  834. }
  835. free(name);
  836. }
  837. else {
  838. // log to file:
  839. int log_fd = open(log_path, O_WRONLY | O_CREAT | O_APPEND | O_NONBLOCK | O_CLOEXEC, 0644);
  840. if (log_fd >= 0) {
  841. try {
  842. setup_main_log(log_fd);
  843. external_log_open = true;
  844. }
  845. catch (std::exception &e) {
  846. log(loglevel_t::ERROR, "Setting up log failed: ", e.what());
  847. close(log_fd);
  848. }
  849. }
  850. else {
  851. // log failure to log? It makes more sense than first appears, because we also log
  852. // to console:
  853. log(loglevel_t::ERROR, "Setting up log failed: ", strerror(errno));
  854. }
  855. }
  856. }
  857. }
  858. static void flush_log() noexcept
  859. {
  860. log_flush_timer.reset();
  861. log_flush_timer.arm_timer_rel(event_loop, timespec{5,0}); // 5 seconds
  862. while (!is_log_flushed() && !log_flush_timer.has_expired()) {
  863. event_loop.run();
  864. }
  865. }
  866. #ifdef SUPPORT_CGROUPS
  867. static void find_cgroup_path() noexcept
  868. {
  869. if (have_cgroups_path) {
  870. return;
  871. }
  872. int pfd = open("/proc/self/cgroup", O_RDONLY);
  873. if (pfd == -1) {
  874. return;
  875. }
  876. try {
  877. size_t cgroup_line_sz = 64;
  878. size_t cur_read = 0;
  879. size_t line_end_pos = (size_t)-1;
  880. size_t colon_count = 0; // how many colons have we seen?
  881. size_t second_colon_pos = 0;
  882. std::vector<char, default_init_allocator<char>> cgroup_line(cgroup_line_sz);
  883. while (true) {
  884. ssize_t r = read(pfd, cgroup_line.data() + cur_read, cgroup_line_sz - cur_read);
  885. if (r == 0) {
  886. if (line_end_pos == (size_t)-1) {
  887. line_end_pos = cur_read + 1;
  888. }
  889. break;
  890. }
  891. if (r == -1) {
  892. close(pfd);
  893. return;
  894. }
  895. size_t rr = (size_t)r;
  896. for (size_t i = 0; i < rr; ++i) {
  897. if (cgroup_line[cur_read + i] == '\n') {
  898. line_end_pos = cur_read + i;
  899. }
  900. else if (line_end_pos != (size_t)-1) {
  901. log(loglevel_t::WARN, "In multiple cgroups, cannot determine cgroup root path");
  902. close(pfd);
  903. return;
  904. }
  905. else if (cgroup_line[cur_read + i] == ':') {
  906. if (++colon_count == 2) {
  907. second_colon_pos = cur_read + i;
  908. }
  909. }
  910. }
  911. cur_read += rr;
  912. if (line_end_pos != 0) {
  913. break;
  914. }
  915. if (cur_read == cgroup_line_sz) {
  916. cgroup_line.resize(cgroup_line_sz * 2);
  917. cgroup_line_sz *= 2;
  918. }
  919. };
  920. close(pfd);
  921. pfd = -1;
  922. // Now extract the path
  923. // The group line should look something like:
  924. //
  925. // 0::/some/path
  926. //
  927. // We want "some/path", i.e. we'll skip the leading slash.
  928. if (colon_count < 2 || (line_end_pos - second_colon_pos) == 1
  929. || cgroup_line[second_colon_pos+1] != '/') {
  930. // path is from 2nd colon to end
  931. log(loglevel_t::WARN, "Could not determine cgroup root path");
  932. return;
  933. }
  934. cgroups_path.clear();
  935. size_t first_char_pos = second_colon_pos + 2;
  936. size_t root_path_len = line_end_pos - first_char_pos;
  937. cgroups_path.append(cgroup_line.data() + first_char_pos, root_path_len);
  938. have_cgroups_path = true;
  939. return;
  940. }
  941. catch (std::bad_alloc &b) {
  942. if (pfd != -1) {
  943. close(pfd);
  944. }
  945. log(loglevel_t::WARN, "Out-of-memory reading cgroup root path");
  946. return;
  947. }
  948. }
  949. #endif // SUPPORT_CGROUPS
  950. static void printVersion()
  951. {
  952. std::cout << "Dinit version " << DINIT_VERSION << '.' << std::endl;
  953. const unsigned feature_count = 0
  954. #ifdef SUPPORT_CGROUPS
  955. +1
  956. #endif
  957. #ifdef USE_UTMPX
  958. +1
  959. #endif
  960. ;
  961. if (feature_count != 0) {
  962. std::cout << "Supported features:"
  963. #ifdef SUPPORT_CGROUPS
  964. " cgroups"
  965. #endif
  966. #ifdef USE_UTMPX
  967. " utmp"
  968. #endif
  969. "\n";
  970. }
  971. }
  972. /* handle SIGINT signal (generated by Linux kernel when ctrl+alt+del pressed) */
  973. static void sigint_reboot_cb(eventloop_t &eloop) noexcept
  974. {
  975. services->stop_all_services(shutdown_type_t::REBOOT);
  976. }
  977. /* handle SIGQUIT (if we are system init) */
  978. static void sigquit_cb(eventloop_t &eloop) noexcept
  979. {
  980. // This performs an immediate shutdown, without service rollback.
  981. close_control_socket();
  982. execl(shutdown_exec.c_str(), shutdown_exec.c_str(), "--system", (char *) 0);
  983. log(loglevel_t::ERROR, error_exec_sd, strerror(errno));
  984. sync(); // since a hard poweroff might be required at this point...
  985. }
  986. /* handle SIGTERM/SIGQUIT(non-system-daemon) - stop all services and shut down */
  987. static void sigterm_cb(eventloop_t &eloop) noexcept
  988. {
  989. services->stop_all_services();
  990. }