#include <assert.h>
#include <definit.h>
#include <libuutil.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zone.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "startd.h"
#define MAXCMDL 512
#define DEF_PATH "PATH=/usr/sbin:/usr/bin"
static char **glob_envp;
static int glob_env_n;
static char zonename[ZONENAME_MAX];
void
init_env()
{
void *dstate;
const char *tokp;
int i;
glob_env_n = 16;
glob_envp = startd_alloc(sizeof (*glob_envp) * glob_env_n);
glob_envp[0] = startd_alloc((unsigned)(strlen(DEF_PATH)+2));
(void) strcpy(glob_envp[0], DEF_PATH);
if (definit_open(DEFINIT_DEFAULT_FILE, &dstate) != 0) {
uu_warn("Cannot open %s. Environment not initialized.\n",
DEFINIT_DEFAULT_FILE);
glob_envp[1] = NULL;
return;
}
i = 1;
while ((tokp = definit_token(dstate)) != NULL) {
size_t length = strlen(tokp);
if (strncmp(tokp, "CMASK=", 6) == 0 ||
strncmp(tokp, "SMF_", 4) == 0) {
continue;
}
glob_envp[i] = startd_alloc((unsigned)(length + 1));
(void) strcpy(glob_envp[i], tokp);
if (++i == glob_env_n) {
char **newp;
glob_env_n *= 2;
newp = startd_alloc(sizeof (*glob_envp) * glob_env_n);
(void) memcpy(newp, glob_envp,
sizeof (*glob_envp) * glob_env_n / 2);
startd_free(glob_envp,
sizeof (*glob_envp) * glob_env_n / 2);
glob_envp = newp;
}
}
glob_envp[i] = NULL;
definit_close(dstate);
(void) getzonenamebyid(getzoneid(), zonename, sizeof (zonename));
}
static int
valid_env_var(const char *var, const restarter_inst_t *inst, const char *path)
{
char *cp = strchr(var, '=');
if (cp == NULL || cp == var) {
if (inst != NULL)
log_instance(inst, B_FALSE, "Invalid environment "
"variable \"%s\".", var);
return (0);
} else if (strncmp(var, "SMF_", 4) == 0) {
if (inst != NULL)
log_instance(inst, B_FALSE, "Invalid environment "
"variable \"%s\"; \"SMF_\" prefix is reserved.",
var);
return (0);
} else if (path != NULL && strncmp(var, "PATH=", 5) == 0) {
return (0);
}
return (1);
}
static char **
find_dup(const char *var, char **env, const restarter_inst_t *inst)
{
char **p;
char *tmp;
for (p = env; *p != NULL; p++) {
assert((tmp = strchr(*p, '=')) != NULL);
tmp++;
if (strncmp(*p, var, tmp - *p) == 0)
break;
}
if (*p == NULL)
return (NULL);
if (inst != NULL && p != env &&
strncmp(*p, DEF_PATH, strlen(DEF_PATH)) != 0) {
log_instance(inst, B_FALSE, "Ignoring duplicate "
"environment variable \"%s\".", *p);
}
return (p);
}
char **
set_smf_env(char **env, size_t env_sz, const char *path,
const restarter_inst_t *inst, const char *method)
{
char **nenv;
char **p, **np;
size_t nenv_size;
size_t sz;
nenv_size = glob_env_n + env_sz + 4 + 1 + 1;
nenv = startd_zalloc(sizeof (char *) * nenv_size);
np = nenv;
if (path != NULL) {
sz = strlen(path) + 1;
*np = startd_alloc(sz);
(void) strlcpy(*np, path, sz);
np++;
}
if (inst) {
sz = sizeof ("SMF_FMRI=") + strlen(inst->ri_i.i_fmri);
*np = startd_alloc(sz);
(void) strlcpy(*np, "SMF_FMRI=", sz);
(void) strlcat(*np, inst->ri_i.i_fmri, sz);
np++;
}
if (method) {
sz = sizeof ("SMF_METHOD=") + strlen(method);
*np = startd_alloc(sz);
(void) strlcpy(*np, "SMF_METHOD=", sz);
(void) strlcat(*np, method, sz);
np++;
}
sz = sizeof ("SMF_RESTARTER=") + strlen(SCF_SERVICE_STARTD);
*np = startd_alloc(sz);
(void) strlcpy(*np, "SMF_RESTARTER=", sz);
(void) strlcat(*np, SCF_SERVICE_STARTD, sz);
np++;
sz = sizeof ("SMF_ZONENAME=") + strlen(zonename);
*np = startd_alloc(sz);
(void) strlcpy(*np, "SMF_ZONENAME=", sz);
(void) strlcat(*np, zonename, sz);
np++;
for (p = glob_envp; *p != NULL; p++) {
if (valid_env_var(*p, inst, path)) {
sz = strlen(*p) + 1;
*np = startd_alloc(sz);
(void) strlcpy(*np, *p, sz);
np++;
}
}
if (env) {
for (p = env; *p != NULL; p++) {
char **dup_pos;
if (!valid_env_var(*p, inst, path))
continue;
if ((dup_pos = find_dup(*p, nenv, inst)) != NULL) {
startd_free(*dup_pos, strlen(*dup_pos) + 1);
sz = strlen(*p) + 1;
*dup_pos = startd_alloc(sz);
(void) strlcpy(*dup_pos, *p, sz);
} else {
sz = strlen(*p) + 1;
*np = startd_alloc(sz);
(void) strlcpy(*np, *p, sz);
np++;
}
}
}
*np = NULL;
return (nenv);
}