endif
dinit_objects = dinit.o load-service.o service.o proc-service.o baseproc-service.o control.o dinit-log.o \
- dinit-main.o run-child-proc.o
+ dinit-main.o run-child-proc.o options-processing.o
objects = $(dinit_objects) dinitctl.o dinitcheck.o shutdown.o
#include "dinit-socket.h"
#include "static-string.h"
#include "dinit-utmp.h"
+#include "options-processing.h"
#include "mconfig.h"
am_pid_one = (getpid() == 1);
am_system_init = (getuid() == 0);
- const char * service_dir = nullptr;
- bool service_dir_dynamic = false; // service_dir dynamically allocated?
const char * env_file = nullptr;
bool control_socket_path_set = false;
bool env_file_set = false;
bool log_specified = false;
+ service_dir_opt service_dir_opts;
+
// list of services to start
list<const char *> services_to_start;
}
else if (strcmp(argv[i], "--services-dir") == 0 || strcmp(argv[i], "-d") == 0) {
if (++i < argc) {
- service_dir = argv[i];
+ service_dir_opts.set_specified_service_dir(argv[i]);
}
else {
cerr << "dinit: '--services-dir' (-d) requires an argument" << endl;
}
}
- /* service directory name */
- if (service_dir == nullptr && ! am_system_init) {
- const char * userhome = get_user_home();
- if (userhome != nullptr) {
- const char * user_home = get_user_home();
- size_t user_home_len = strlen(user_home);
- size_t dinit_d_len = strlen("/dinit.d");
- size_t full_len = user_home_len + dinit_d_len + 1;
- char *service_dir_w = new char[full_len];
- std::memcpy(service_dir_w, user_home, user_home_len);
- std::memcpy(service_dir_w + user_home_len, "/dinit.d", dinit_d_len);
- service_dir_w[full_len - 1] = 0;
-
- service_dir = service_dir_w;
- service_dir_dynamic = true;
- }
- }
-
if (services_to_start.empty()) {
services_to_start.push_back("boot");
}
log_flush_timer.add_timer(event_loop, dasynq::clock_type::MONOTONIC);
- bool add_all_service_dirs = false;
- if (service_dir == nullptr) {
- service_dir = "/etc/dinit.d";
- add_all_service_dirs = true;
- }
+ service_dir_opts.build_paths();
/* start requested services */
- services = new dirload_service_set(service_dir, service_dir_dynamic);
- if (add_all_service_dirs) {
- services->add_service_dir("/usr/local/lib/dinit.d", false);
- services->add_service_dir("/lib/dinit.d", false);
- }
-
+ services = new dirload_service_set(std::move(service_dir_opts.get_paths()));
+
init_log(services, log_is_syslog);
if (am_system_init) {
log(loglevel_t::INFO, false, "starting system");
#include "dinit-util.h"
#include "service-constants.h"
#include "load-service.h"
+#include "options-processing.h"
// dinitcheck: utility to check Dinit configuration for correctness/lint
using service_set_t = std::map<std::string, service_record *>;
service_record *load_service(service_set_t &services, const std::string &name,
- const std::vector<dinit_load::dir_entry> &service_dirs);
+ const std::vector<dir_entry> &service_dirs);
// Add some missing standard library functionality...
template <typename T> bool contains(std::vector<T> vec, const T& elem)
add_all_service_dirs = true;
}
- std::vector<dinit_load::dir_entry> service_dirs;
+ std::vector<dir_entry> service_dirs;
service_dirs.emplace_back(service_dir, service_dir_dynamic);
if (add_all_service_dirs) {
}
service_record *load_service(service_set_t &services, const std::string &name,
- const std::vector<dinit_load::dir_entry> &service_dirs)
+ const std::vector<dir_entry> &service_dirs)
{
using namespace std;
using namespace dinit_load;
#include <list>
#include <limits>
#include <csignal>
+#include <cstring>
#include <sys/types.h>
#include <sys/time.h>
using string = std::string;
using string_iterator = std::string::iterator;
-// A service directory entry, tracking the directory as a nul-terminated string, which may either
-// be static or dynamically allocated (via new char[...]).
-class dir_entry
-{
- const char *dir;
- bool dir_dyn_allocd; // dynamically allocated?
-
- public:
- dir_entry(const char *dir_p, bool dir_dyn_allocd_p) :
- dir(dir_p), dir_dyn_allocd(dir_dyn_allocd_p)
- { }
-
- dir_entry(dir_entry &&other)
- {
- dir = other.dir;
- dir_dyn_allocd = other.dir_dyn_allocd;
- other.dir_dyn_allocd = false;
- }
-
- dir_entry(const dir_entry &other) = delete;
-
- ~dir_entry()
- {
- if (dir_dyn_allocd) {
- delete[] dir;
- }
- }
-
- const char *get_dir() const
- {
- return dir;
- }
-};
-
// exception thrown when encountering a syntax issue when reading a setting value
class setting_exception
{
--- /dev/null
+#ifndef DINIT_OPTIONS_PROCESSING_H
+#define DINIT_OPTIONS_PROCESSING_H 1
+
+#include <vector>
+
+// A service directory entry, tracking the directory as a nul-terminated string, which may either
+// be static or dynamically allocated (via new char[...]).
+class dir_entry
+{
+ const char *dir;
+ bool dir_dyn_allocd; // dynamically allocated?
+
+ public:
+ dir_entry(const char *dir_p, bool dir_dyn_allocd_p) :
+ dir(dir_p), dir_dyn_allocd(dir_dyn_allocd_p)
+ { }
+
+ dir_entry(dir_entry &&other)
+ {
+ dir = other.dir;
+ dir_dyn_allocd = other.dir_dyn_allocd;
+ other.dir_dyn_allocd = false;
+ }
+
+ dir_entry(const dir_entry &other) = delete;
+
+ ~dir_entry()
+ {
+ if (dir_dyn_allocd) {
+ delete[] dir;
+ }
+ }
+
+ const char *get_dir() const
+ {
+ return dir;
+ }
+};
+
+// TODO this is close to just being a vector; make it so?
+class service_dir_pathlist
+{
+ std::vector<dir_entry> service_dirs; // directories containing service descriptions
+
+public:
+ service_dir_pathlist() { }
+
+ service_dir_pathlist(const char *service_dir_p, bool dyn_allocd = false)
+ {
+ service_dirs.emplace_back(service_dir_p, dyn_allocd);
+ }
+
+ void add_dir(const char *service_dir_p, bool dyn_allocd = false)
+ {
+ service_dirs.emplace_back(service_dir_p, dyn_allocd);
+ }
+
+ size_t size()
+ {
+ return service_dirs.size();
+ }
+
+ dir_entry &operator[](size_t index)
+ {
+ return service_dirs[index];
+ }
+
+ std::vector<dir_entry>::iterator begin()
+ {
+ return service_dirs.begin();
+ }
+
+ std::vector<dir_entry>::iterator end()
+ {
+ return service_dirs.end();
+ }
+};
+
+class service_dir_opt
+{
+ const char *service_dir = nullptr;;
+ bool service_dir_dynamic = false;
+
+ bool am_system_init;
+
+ static const char *user_home_path;
+
+ service_dir_pathlist service_dir_paths;
+
+public:
+ // Get user home (and set user_home_path). (The return may become invalid after
+ // changing the environment (HOME variable) or using the getpwuid() function).
+ static const char * get_user_home();
+
+ void set_specified_service_dir(const char *specified_dir)
+ {
+ service_dir = specified_dir;
+ }
+
+ void build_paths();
+
+ service_dir_pathlist &get_paths()
+ {
+ return service_dir_paths;
+ }
+};
+
+#endif
#include "load-service.h"
#include "dinit-ll.h"
#include "dinit-log.h"
+#include "options-processing.h" // TODO maybe remove, service_dir_pathlist can be moved?
/*
* This header defines service_record, a data record maintaining information about a service,
// A service set which loads services from one of several service directories.
class dirload_service_set : public service_set
{
- using dir_entry = dinit_load::dir_entry;
-
- std::vector<dir_entry> service_dirs; // directories containing service descriptions
+ service_dir_pathlist service_dirs;
public:
dirload_service_set() : service_set()
// nothing to do.
}
- dirload_service_set(const dirload_service_set &) = delete;
-
- // Construct a dirload_service_set which loads services from the specified directory. The
- // directory specified can be dynamically allocated via "new char[...]" (dyn_allocd == true)
- // or statically allocated.
- dirload_service_set(const char *service_dir_p, bool dyn_allocd = false) : service_set()
+ dirload_service_set(service_dir_pathlist &&pathlist) : service_set(), service_dirs(std::move(pathlist))
{
- service_dirs.emplace_back(service_dir_p, dyn_allocd);
+ // nothing to do.
}
- // Append a directory to the list of service directories, so that it is searched last for
- // service description files.
- void add_service_dir(const char *service_dir_p, bool dyn_allocd = true)
- {
- service_dirs.emplace_back(service_dir_p, dyn_allocd);
- }
+ dirload_service_set(const dirload_service_set &) = delete;
int get_service_dir_count()
{
--- /dev/null
+#include <vector>
+
+#include <cstring>
+#include <cstdlib>
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "options-processing.h"
+
+const char *service_dir_opt::user_home_path = nullptr;
+
+const char * service_dir_opt::get_user_home()
+{
+ if (user_home_path == nullptr) {
+ user_home_path = getenv("HOME");
+ if (user_home_path == nullptr) {
+ struct passwd * pwuid_p = getpwuid(getuid());
+ if (pwuid_p != nullptr) {
+ user_home_path = pwuid_p->pw_dir;
+ }
+ }
+ }
+ return user_home_path;
+}
+
+void service_dir_opt::build_paths()
+{
+ /* service directory name */
+ if (service_dir == nullptr && ! am_system_init) {
+ const char * user_home = get_user_home();
+ if (user_home != nullptr) {
+ size_t user_home_len = strlen(user_home);
+ size_t dinit_d_len = strlen("/dinit.d");
+ size_t full_len = user_home_len + dinit_d_len + 1;
+ char *service_dir_w = new char[full_len];
+ std::memcpy(service_dir_w, user_home, user_home_len);
+ std::memcpy(service_dir_w + user_home_len, "/dinit.d", dinit_d_len);
+ service_dir_w[full_len - 1] = 0;
+
+ service_dir = service_dir_w;
+ service_dir_dynamic = true;
+ }
+ }
+
+ bool add_all_service_dirs = false;
+ if (service_dir == nullptr) {
+ service_dir = "/etc/dinit.d";
+ add_all_service_dirs = true;
+ }
+
+ service_dir_paths.add_dir(service_dir, service_dir_dynamic);
+ if (add_all_service_dirs) {
+ service_dir_paths.add_dir("/usr/local/lib/dinit.d", false);
+ service_dir_paths.add_dir("/lib/dinit.d", false);
+ }
+}