From: Davin McCall Date: Mon, 14 May 2018 09:24:01 +0000 (+0100) Subject: dirload_service_set: add support for multiple service directories. X-Git-Tag: v0.2.0~22 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=bf45b03a2d5b8dbab685ae1fe848a307f6545178;p=oweals%2Fdinit.git dirload_service_set: add support for multiple service directories. --- diff --git a/src/includes/service.h b/src/includes/service.h index b13e80e..318deef 100644 --- a/src/includes/service.h +++ b/src/includes/service.h @@ -845,13 +845,55 @@ class service_set } }; +// A service directory entry, tracking the directory as a nul-terminated string, which may either +// be static or dynamically allocated (via new char[...]). +class service_dir_entry +{ + const char *dir; + bool dir_dyn_allocd; // dynamically allocated? + + public: + service_dir_entry(const char *dir_p, bool dir_dyn_allocd_p) : + dir(dir_p), dir_dyn_allocd(dir_dyn_allocd_p) + { } + + ~service_dir_entry() + { + if (dir_dyn_allocd) { + delete[] dir; + } + } + + const char *get_dir() const + { + return dir; + } +}; + +// A service set which loads services from one of several service directories. class dirload_service_set : public service_set { - const char *service_dir; // directory containing service descriptions + std::vector service_dirs; // directories containing service descriptions public: - dirload_service_set(const char *service_dir_p) : service_set(), service_dir(service_dir_p) + dirload_service_set() : service_set() + { + // nothing to do. + } + + // 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() + { + service_dirs.emplace_back(service_dir_p, false); + } + + // 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); } service_record *load_service(const char *name) override; diff --git a/src/load-service.cc b/src/load-service.cc index 8e064b7..5a76a54 100644 --- a/src/load-service.cc +++ b/src/load-service.cc @@ -377,12 +377,19 @@ service_record * dirload_service_set::load_service(const char * name) return rval; } - // Couldn't find one. Have to load it. - string service_filename = service_dir; - if (*(service_filename.rbegin()) != '/') { - service_filename += '/'; + ifstream service_file; + + // Couldn't find one. Have to load it. + for (auto &service_dir : service_dirs) { + string service_filename = service_dir.get_dir(); + if (*(service_filename.rbegin()) != '/') { + service_filename += '/'; + } + service_filename += name; + + service_file.open(service_filename.c_str(), ios::in); + if (service_file) break; } - service_filename += name; string command; list> command_offsets; @@ -416,16 +423,8 @@ service_record * dirload_service_set::load_service(const char * name) gid_t run_as_gid = -1; string line; - ifstream service_file; service_file.exceptions(ios::badbit | ios::failbit); - try { - service_file.open(service_filename.c_str(), ios::in); - } - catch (std::ios_base::failure &exc) { - throw service_not_found(name); - } - // Add a dummy service record now to prevent infinite recursion in case of cyclic dependency. // We replace this with the real service later (or remove it if we find a configuration error). rval = new service_record(this, string(name));