#include "missing.h"
#include "unit-name.h"
+#define COMMENTS "#;\n"
+#define LINE_MAX 4096
+
#define DEFINE_CONFIG_PARSE_ENUM(function,name,type,msg) \
static int function( \
const char *filename, \
return 0;
}
+static int config_parse_env_file(
+ const char *filename,
+ unsigned line,
+ const char *section,
+ const char *lvalue,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ FILE *f;
+ int r;
+ char ***env = data;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (!(f = fopen(rvalue, "re"))) {
+ log_error("[%s:%u] Failed to open environment file '%s': %m", filename, line, rvalue);
+ return -errno;
+ }
+
+ while (!feof(f)) {
+ char l[LINE_MAX], *p;
+ char **t;
+
+ if (!fgets(l, sizeof(l), f)) {
+ if (feof(f))
+ break;
+
+ r = -errno;
+ log_error("[%s:%u] Failed to read environment file '%s': %m", filename, line, rvalue);
+ goto finish;
+ }
+
+ p = strstrip(l);
+
+ if (!*p)
+ continue;
+
+ if (strchr(COMMENTS, *p))
+ continue;
+
+ t = strv_env_set(*env, p);
+ strv_free(*env);
+ *env = t;
+ }
+
+ r = 0;
+
+finish:
+ if (f)
+ fclose(f);
+
+ return r;
+}
+
+DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
+
#define FOLLOW_MAX 8
static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
{ config_parse_cpu_sched_prio, "CPUSCHEDPRIO" },
{ config_parse_cpu_affinity, "CPUAFFINITY" },
{ config_parse_mode, "MODE" },
+ { config_parse_env_file, "FILE" },
{ config_parse_output, "OUTPUT" },
{ config_parse_input, "INPUT" },
{ config_parse_facility, "FACILITY" },
{ config_parse_description, "DESCRIPTION" },
{ config_parse_timer, "TIMER" },
{ config_parse_timer_unit, "NAME" },
+ { config_parse_path_spec, "PATH" },
+ { config_parse_path_unit, "UNIT" },
+ { config_parse_notify_access, "ACCESS" }
};
assert(f);
{ "CPUAffinity", config_parse_cpu_affinity, &(context), section }, \
{ "UMask", config_parse_mode, &(context).umask, section }, \
{ "Environment", config_parse_strv, &(context).environment, section }, \
+ { "EnvironmentFile", config_parse_env_file, &(context).environment, section }, \
{ "StandardInput", config_parse_input, &(context).std_input, section }, \
{ "StandardOutput", config_parse_output, &(context).std_output, section }, \
{ "StandardError", config_parse_output, &(context).std_error, section }, \
{ "ReadOnlyDirectories", config_parse_path_strv, &(context).read_only_dirs, section }, \
{ "InaccessibleDirectories",config_parse_path_strv, &(context).inaccessible_dirs, section }, \
{ "PrivateTmp", config_parse_bool, &(context).private_tmp, section }, \
- { "MountFlags", config_parse_mount_flags, &(context), section }
+ { "MountFlags", config_parse_mount_flags, &(context), section }, \
+ { "TCPWrapName", config_parse_string, &(context).tcpwrap_name, section }, \
+ { "PAMName", config_parse_string, &(context).pam_name, section }
const ConfigItem items[] = {
{ "Names", config_parse_names, u, "Unit" },
{ "KillMode", config_parse_kill_mode, &u->service.kill_mode, "Service" },
{ "NonBlocking", config_parse_bool, &u->service.exec_context.non_blocking, "Service" },
{ "BusName", config_parse_string, &u->service.bus_name, "Service" },
+ { "NotifyAccess", config_parse_notify_access, &u->service.notify_access, "Service" },
EXEC_CONTEXT_CONFIG_ITEMS(u->service.exec_context, "Service"),
{ "ListenStream", config_parse_listen, &u->socket, "Socket" },
{ "SocketMode", config_parse_mode, &u->socket.socket_mode, "Socket" },
{ "KillMode", config_parse_kill_mode, &u->socket.kill_mode, "Socket" },
{ "Accept", config_parse_bool, &u->socket.accept, "Socket" },
- { "TCPWrapName", config_parse_string, &u->socket.tcpwrap_name, "Socket" },
EXEC_CONTEXT_CONFIG_ITEMS(u->socket.exec_context, "Socket"),
{ "What", config_parse_string, &u->mount.parameters_fragment.what, "Mount" },