mirror of
https://github.com/troglobit/finit.git
synced 2026-10-24 11:54:36 +00:00
Add support for setting environment variables from finit.conf
Finit can now track and set environment variables from finit.conf. The
syntax is pretty much what you'd expect:
foo=bar
baz="qux"
On reload of .conf files, all tracked environment variables are cleared
so if `foo=bar` is removed from finit.conf, or any finit.d/*.conf file,
it will no longer be used by Finit or any new (!) started run/tasks or
services.
The only variables reset to sane defaults on .conf reload are:
PATH=_PATH_STDPATH
SHELL=_PATH_BSHELL
LOGNAME=root
USER=root
It is entirely possible to override these as well from the .conf files,
but be careful. Changing SHELL changes the behavior of system() and a
lot of other commands as well.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
1 parent
bf62bee440
commit
38db52aa4e
3 files changed
+135
-28
No files matched your search
+133
-24
@@ -54,6 +54,12 @@
|
|||||||
int logfile_size_max = 200000; /* 200 kB */
|
int logfile_size_max = 200000; /* 200 kB */
|
||||||
int logfile_count_max = 5;
|
int logfile_count_max = 5;
|
||||||
|
|
||||||
|
struct env_entry {
|
||||||
|
TAILQ_ENTRY(env_entry) link;
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
static TAILQ_HEAD(, env_entry) env_list = TAILQ_HEAD_INITIALIZER(env_list);
|
||||||
|
|
||||||
struct rlimit initial_rlimit[RLIMIT_NLIMITS];
|
struct rlimit initial_rlimit[RLIMIT_NLIMITS];
|
||||||
struct rlimit global_rlimit[RLIMIT_NLIMITS];
|
struct rlimit global_rlimit[RLIMIT_NLIMITS];
|
||||||
|
|
||||||
@@ -67,7 +73,7 @@ struct conf_change {
|
|||||||
static struct iwatch iw_conf;
|
static struct iwatch iw_conf;
|
||||||
static uev_t etcw;
|
static uev_t etcw;
|
||||||
|
|
||||||
static TAILQ_HEAD(head, conf_change) conf_change_list = TAILQ_HEAD_INITIALIZER(conf_change_list);
|
static TAILQ_HEAD(, conf_change) conf_change_list = TAILQ_HEAD_INITIALIZER(conf_change_list);
|
||||||
|
|
||||||
static int parse_conf(char *file, int is_rcsd);
|
static int parse_conf(char *file, int is_rcsd);
|
||||||
static void drop_changes(void);
|
static void drop_changes(void);
|
||||||
@@ -213,6 +219,98 @@ void conf_parse_cmdline(int argc, char *argv[])
|
|||||||
parse_kernel_loglevel();
|
parse_kernel_loglevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear all environment variables read in parse_env(), they may be
|
||||||
|
* removed now so let the next call to parse_env() restore them.
|
||||||
|
*/
|
||||||
|
void conf_reset_env(void)
|
||||||
|
{
|
||||||
|
struct env_entry *node, *tmp;
|
||||||
|
|
||||||
|
TAILQ_FOREACH_SAFE(node, &env_list, link, tmp) {
|
||||||
|
TAILQ_REMOVE(&env_list, node, link);
|
||||||
|
if (node->name) {
|
||||||
|
unsetenv(node->name);
|
||||||
|
free(node->name);
|
||||||
|
}
|
||||||
|
free(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
setenv("PATH", _PATH_STDPATH, 1);
|
||||||
|
setenv("SHELL", _PATH_BSHELL, 1);
|
||||||
|
setenv("LOGNAME", "root", 1);
|
||||||
|
setenv("USER", "root", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets, and makes a note of, all KEY=VALUE lines in a given .conf line
|
||||||
|
* from finit.conf, or other .conf file. Note, PATH is always reset in
|
||||||
|
* the conf_reset_env() function.
|
||||||
|
*/
|
||||||
|
static void parse_env(char *line)
|
||||||
|
{
|
||||||
|
struct env_entry *node;
|
||||||
|
char *key, *val, *end;
|
||||||
|
|
||||||
|
/* skip any leading whitespace */
|
||||||
|
key = line;
|
||||||
|
while (isspace(*key))
|
||||||
|
key++;
|
||||||
|
|
||||||
|
/* find end of line */
|
||||||
|
end = key;
|
||||||
|
while (*end)
|
||||||
|
end++;
|
||||||
|
|
||||||
|
/* strip trailing whitespace */
|
||||||
|
if (end > key) {
|
||||||
|
end--;
|
||||||
|
while (isspace(*end))
|
||||||
|
*end-- = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = strchr(key, '=');
|
||||||
|
if (!val)
|
||||||
|
return;
|
||||||
|
*val++ = 0;
|
||||||
|
|
||||||
|
/* strip leading whitespace from value */
|
||||||
|
while (isspace(*val))
|
||||||
|
val++;
|
||||||
|
|
||||||
|
/* unquote value, if quoted */
|
||||||
|
if (val[0] == '"' || val[0] == '\'') {
|
||||||
|
char q = val[0];
|
||||||
|
|
||||||
|
if (*end == q) {
|
||||||
|
val = &val[1];
|
||||||
|
*end = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find end of key */
|
||||||
|
end = key;
|
||||||
|
while (*end)
|
||||||
|
end++;
|
||||||
|
|
||||||
|
/* strip trailing whitespace */
|
||||||
|
if (end > key) {
|
||||||
|
end--;
|
||||||
|
while (isspace(*end))
|
||||||
|
*end-- = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
setenv(key, val, 1);
|
||||||
|
|
||||||
|
node = malloc(sizeof(*node));
|
||||||
|
if (!node) {
|
||||||
|
_pe("Out of memory cannot track env vars");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
node->name = strdup(key);
|
||||||
|
TAILQ_INSERT_HEAD(&env_list, node, link);
|
||||||
|
}
|
||||||
|
|
||||||
static int kmod_exists(char *mod)
|
static int kmod_exists(char *mod)
|
||||||
{
|
{
|
||||||
char buf[256];
|
char buf[256];
|
||||||
@@ -484,7 +582,7 @@ static void conf_parse_cgroup(char *line)
|
|||||||
cgroup_add(name, config, 0);
|
cgroup_add(name, config, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_static(char *line, int is_rcsd)
|
static int parse_static(char *line, int is_rcsd)
|
||||||
{
|
{
|
||||||
char cmd[CMD_SIZE];
|
char cmd[CMD_SIZE];
|
||||||
char *x;
|
char *x;
|
||||||
@@ -492,7 +590,7 @@ static void parse_static(char *line, int is_rcsd)
|
|||||||
if (BOOTSTRAP && (MATCH_CMD(line, "host ", x) || MATCH_CMD(line, "hostname ", x))) {
|
if (BOOTSTRAP && (MATCH_CMD(line, "host ", x) || MATCH_CMD(line, "hostname ", x))) {
|
||||||
if (hostname) free(hostname);
|
if (hostname) free(hostname);
|
||||||
hostname = strdup(strip_line(x));
|
hostname = strdup(strip_line(x));
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BOOTSTRAP && MATCH_CMD(line, "mknod ", x)) {
|
if (BOOTSTRAP && MATCH_CMD(line, "mknod ", x)) {
|
||||||
@@ -501,25 +599,25 @@ static void parse_static(char *line, int is_rcsd)
|
|||||||
strcpy(cmd, "mknod ");
|
strcpy(cmd, "mknod ");
|
||||||
strlcat(cmd, dev, sizeof(cmd));
|
strlcat(cmd, dev, sizeof(cmd));
|
||||||
run_interactive(cmd, "Creating device node %s", dev);
|
run_interactive(cmd, "Creating device node %s", dev);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Kernel module to load */
|
/* Kernel module to load */
|
||||||
if (BOOTSTRAP && MATCH_CMD(line, "module ", x)) {
|
if (BOOTSTRAP && MATCH_CMD(line, "module ", x)) {
|
||||||
kmod_load(strip_line(x));
|
kmod_load(strip_line(x));
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BOOTSTRAP && MATCH_CMD(line, "network ", x)) {
|
if (BOOTSTRAP && MATCH_CMD(line, "network ", x)) {
|
||||||
if (network) free(network);
|
if (network) free(network);
|
||||||
network = strdup(strip_line(x));
|
network = strdup(strip_line(x));
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BOOTSTRAP && MATCH_CMD(line, "runparts ", x)) {
|
if (BOOTSTRAP && MATCH_CMD(line, "runparts ", x)) {
|
||||||
if (runparts) free(runparts);
|
if (runparts) free(runparts);
|
||||||
runparts = strdup(strip_line(x));
|
runparts = strdup(strip_line(x));
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MATCH_CMD(line, "include ", x)) {
|
if (MATCH_CMD(line, "include ", x)) {
|
||||||
@@ -528,11 +626,10 @@ static void parse_static(char *line, int is_rcsd)
|
|||||||
strlcpy(cmd, file, sizeof(cmd));
|
strlcpy(cmd, file, sizeof(cmd));
|
||||||
if (!fexist(cmd)) {
|
if (!fexist(cmd)) {
|
||||||
_e("Cannot find include file %s, absolute path required!", x);
|
_e("Cannot find include file %s, absolute path required!", x);
|
||||||
return;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_conf(cmd, is_rcsd);
|
return parse_conf(cmd, is_rcsd);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MATCH_CMD(line, "log ", x)) {
|
if (MATCH_CMD(line, "log ", x)) {
|
||||||
@@ -553,12 +650,14 @@ static void parse_static(char *line, int is_rcsd)
|
|||||||
logfile_size_max = size;
|
logfile_size_max = size;
|
||||||
if (count >= 0)
|
if (count >= 0)
|
||||||
logfile_count_max = count;
|
logfile_count_max = count;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MATCH_CMD(line, "shutdown ", x)) {
|
if (MATCH_CMD(line, "shutdown ", x)) {
|
||||||
if (sdown) free(sdown);
|
if (sdown) free(sdown);
|
||||||
sdown = strdup(strip_line(x));
|
sdown = strdup(strip_line(x));
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -575,7 +674,7 @@ static void parse_static(char *line, int is_rcsd)
|
|||||||
cfglevel = RUNLEVEL;
|
cfglevel = RUNLEVEL;
|
||||||
if (cfglevel < 1 || cfglevel > 9 || cfglevel == 6)
|
if (cfglevel < 1 || cfglevel > 9 || cfglevel == 6)
|
||||||
cfglevel = 2; /* Fallback */
|
cfglevel = 2; /* Fallback */
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -595,61 +694,65 @@ static void parse_static(char *line, int is_rcsd)
|
|||||||
if (disabled)
|
if (disabled)
|
||||||
service_init();
|
service_init();
|
||||||
}
|
}
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_dynamic(char *line, struct rlimit rlimit[], char *file)
|
static int parse_dynamic(char *line, struct rlimit rlimit[], char *file)
|
||||||
{
|
{
|
||||||
char *x;
|
char *x;
|
||||||
|
|
||||||
/* Monitored daemon, will be respawned on exit */
|
/* Monitored daemon, will be respawned on exit */
|
||||||
if (MATCH_CMD(line, "service ", x)) {
|
if (MATCH_CMD(line, "service ", x)) {
|
||||||
service_register(SVC_TYPE_SERVICE, x, rlimit, file);
|
service_register(SVC_TYPE_SERVICE, x, rlimit, file);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* One-shot task, will not be respawned */
|
/* One-shot task, will not be respawned */
|
||||||
if (MATCH_CMD(line, "task ", x)) {
|
if (MATCH_CMD(line, "task ", x)) {
|
||||||
service_register(SVC_TYPE_TASK, x, rlimit, file);
|
service_register(SVC_TYPE_TASK, x, rlimit, file);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Like task but waits for completion, useful w/ [S] */
|
/* Like task but waits for completion, useful w/ [S] */
|
||||||
if (MATCH_CMD(line, "run ", x)) {
|
if (MATCH_CMD(line, "run ", x)) {
|
||||||
service_register(SVC_TYPE_RUN, x, rlimit, file);
|
service_register(SVC_TYPE_RUN, x, rlimit, file);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Similar to task but is treated like a SysV init script */
|
/* Similar to task but is treated like a SysV init script */
|
||||||
if (MATCH_CMD(line, "sysv ", x)) {
|
if (MATCH_CMD(line, "sysv ", x)) {
|
||||||
service_register(SVC_TYPE_SYSV, x, rlimit, file);
|
service_register(SVC_TYPE_SYSV, x, rlimit, file);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read resource limits */
|
/* Read resource limits */
|
||||||
if (MATCH_CMD(line, "rlimit ", x)) {
|
if (MATCH_CMD(line, "rlimit ", x)) {
|
||||||
conf_parse_rlimit(x, rlimit);
|
conf_parse_rlimit(x, rlimit);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read control group limits */
|
/* Read control group limits */
|
||||||
if (MATCH_CMD(line, "cgroup ", x)) {
|
if (MATCH_CMD(line, "cgroup ", x)) {
|
||||||
conf_parse_cgroup(x);
|
conf_parse_cgroup(x);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set current cgroup for the following services/run/tasks */
|
/* Set current cgroup for the following services/run/tasks */
|
||||||
if (MATCH_CMD(line, "cgroup.", x)) {
|
if (MATCH_CMD(line, "cgroup.", x)) {
|
||||||
strlcpy(cgroup_current, x, sizeof(cgroup_current));
|
strlcpy(cgroup_current, x, sizeof(cgroup_current));
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Regular or serial TTYs to run getty */
|
/* Regular or serial TTYs to run getty */
|
||||||
if (MATCH_CMD(line, "tty ", x)) {
|
if (MATCH_CMD(line, "tty ", x)) {
|
||||||
service_register(SVC_TYPE_TTY, strip_line(x), rlimit, file);
|
service_register(SVC_TYPE_TTY, strip_line(x), rlimit, file);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tabstospaces(char *line)
|
static void tabstospaces(char *line)
|
||||||
@@ -694,8 +797,13 @@ static int parse_conf(char *file, int is_rcsd)
|
|||||||
if (MATCH_CMD(line, "#", x))
|
if (MATCH_CMD(line, "#", x))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
parse_static(line, is_rcsd);
|
if (!parse_static(line, is_rcsd))
|
||||||
parse_dynamic(line, is_rcsd ? rlimit : global_rlimit, file);
|
continue;
|
||||||
|
if (!parse_dynamic(line, is_rcsd ? rlimit : global_rlimit, file))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Not static or dynamic conf, check if it is a global env. */
|
||||||
|
parse_env(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@@ -719,6 +827,7 @@ int conf_reload(void)
|
|||||||
/* Mark and sweep */
|
/* Mark and sweep */
|
||||||
cgroup_mark_all();
|
cgroup_mark_all();
|
||||||
svc_mark_dynamic();
|
svc_mark_dynamic();
|
||||||
|
conf_reset_env();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reset global rlimit to bootstrap values from conf_init().
|
* Reset global rlimit to bootstrap values from conf_init().
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ int conf_any_change (void);
|
|||||||
int conf_changed (char *file);
|
int conf_changed (char *file);
|
||||||
int conf_monitor (void);
|
int conf_monitor (void);
|
||||||
|
|
||||||
|
void conf_reset_env (void);
|
||||||
void conf_parse_cmdline (int argc, char *argv[]);
|
void conf_parse_cmdline (int argc, char *argv[]);
|
||||||
int conf_parse_runlevels (char *runlevels);
|
int conf_parse_runlevels (char *runlevels);
|
||||||
void conf_parse_cond (svc_t *svc, char *cond);
|
void conf_parse_cond (svc_t *svc, char *cond);
|
||||||
|
|||||||
+1
-4
@@ -729,10 +729,7 @@ int main(int argc, char *argv[])
|
|||||||
/*
|
/*
|
||||||
* Set PATH, SHELL, and PWD early to something sane
|
* Set PATH, SHELL, and PWD early to something sane
|
||||||
*/
|
*/
|
||||||
setenv("PATH", _PATH_STDPATH, 1);
|
conf_reset_env();
|
||||||
setenv("SHELL", _PATH_BSHELL, 1);
|
|
||||||
setenv("LOGNAME", "root", 1);
|
|
||||||
setenv("USER", "root", 1);
|
|
||||||
|
|
||||||
if (chdir("/"))
|
if (chdir("/"))
|
||||||
_pe("Failed cd /");
|
_pe("Failed cd /");
|
||||||
|
|||||||
Reference in new issue
Block a user