+static void log_bad_env(int linenum)
+{
+ log(loglevel_t::ERROR, "invalid environment variable setting in environment file (line ", linenum, ")");
+}
+
+// Read and set environment variables from a file.
+static void read_env_file(const char *env_file_path)
+{
+ // Note that we can't use the log in this function; it hasn't been initialised yet.
+
+ std::ifstream env_file(env_file_path);
+ if (! env_file) return;
+
+ env_file.exceptions(std::ios::badbit);
+
+ auto &clocale = std::locale::classic();
+ std::string line;
+ int linenum = 0;
+
+ while (std::getline(env_file, line)) {
+ linenum++;
+ auto lpos = line.begin();
+ auto lend = line.end();
+ while (lpos != lend && std::isspace(*lpos, clocale)) {
+ ++lpos;
+ }
+
+ if (lpos != lend) {
+ if (*lpos != '#') {
+ if (*lpos == '=') {
+ log_bad_env(linenum);
+ continue;
+ }
+ auto name_begin = lpos++;
+ // skip until '=' or whitespace:
+ while (lpos != lend && *lpos != '=' && ! std::isspace(*lpos, clocale)) ++lpos;
+ auto name_end = lpos;
+ // skip whitespace:
+ while (lpos != lend && std::isspace(*lpos, clocale)) ++lpos;
+ if (lpos == lend) {
+ log_bad_env(linenum);
+ continue;
+ }
+
+ ++lpos;
+ auto val_begin = lpos;
+ while (lpos != lend && *lpos != '\n') ++lpos;
+ auto val_end = lpos;
+
+ std::string name = line.substr(name_begin - line.begin(), name_end - name_begin);
+ std::string value = line.substr(val_begin - line.begin(), val_end - val_begin);
+ if (setenv(name.c_str(), value.c_str(), true) == -1) {
+ throw std::system_error(errno, std::system_category());
+ }
+ }
+ }
+ }
+}
+