-
Eric Vidal authoredEric Vidal authored
parse_module.c 25.10 KiB
/*
* parse_module.c
*
* Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
*
* All rights reserved.
*
* This file is part of Obarun. It is subject to the license terms in
* the LICENSE file found in the top-level directory of this
* distribution.
* This file may not be copied, modified, propagated, or distributed
* except according to the terms contained in the LICENSE file./
*/
#include <66/parser.h>
#include <string.h>
#include <stdio.h> //rename
#include <unistd.h> //chdir
#include <oblibs/string.h>
#include <oblibs/types.h>
#include <oblibs/log.h>
#include <oblibs/sastr.h>
#include <oblibs/environ.h>
#include <oblibs/files.h>
#include <oblibs/mill.h>
#include <oblibs/directory.h>
#include <skalibs/stralloc.h>
#include <skalibs/djbunix.h>
#include <skalibs/env.h>
#include <skalibs/bytestr.h>//byte_count
#include <skalibs/genalloc.h>
#include <66/resolve.h>
#include <66/utils.h>
#include <66/constants.h>
#include <66/environ.h>
#define SS_MODULE_CONFIG_DIR "/configure"
#define SS_MODULE_CONFIG_DIR_LEN (sizeof SS_MODULE_CONFIG_DIR - 1)
#define SS_MODULE_CONFIG_SCRIPT "configure"
#define SS_MODULE_CONFIG_SCRIPT_LEN (sizeof SS_MODULE_CONFIG_SCRIPT - 1)
#define SS_MODULE_SERVICE "/service"
#define SS_MODULE_SERVICE_LEN (sizeof SS_MODULE_SERVICE - 1)
#define SS_MODULE_SERVICE_INSTANCE "/service@"
#define SS_MODULE_SERVICE_INSTANCE_LEN (sizeof SS_MODULE_SERVICE_INSTANCE - 1)
static int check_dir(char const *src,char const *dir)
{
log_flow() ;
int r ;
size_t srclen = strlen(src) ;
size_t dirlen = strlen(dir) ;
char tsrc[srclen + dirlen + 1] ;
auto_strings(tsrc,src,dir) ;
r = scan_mode(tsrc,S_IFDIR) ;
if (r < 0) { errno = EEXIST ; log_warnusys_return(LOG_EXIT_ZERO,"conflicting format of: ",tsrc) ; }
if (!r) {
if (!dir_create_parent(tsrc,0755))
log_warnusys_return(LOG_EXIT_ZERO,"create directory: ",tsrc) ;
}
return 1 ;
}
static int get_list(stralloc *list, stralloc *sdir,size_t len, char const *svname, mode_t mode)
{
log_flow() ;
sdir->len = len ;
if (!auto_stra(sdir,SS_MODULE_SERVICE)) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ;
char const *exclude[1] = { 0 } ;
if (!sastr_dir_get_recursive(list,sdir->s,exclude,mode,1))
log_warnusys_return(LOG_EXIT_ZERO,"get file(s) of module: ",svname) ;
sdir->len = len ;
if (!auto_stra(sdir,SS_MODULE_SERVICE_INSTANCE)) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ;
if (!sastr_dir_get_recursive(list,sdir->s,exclude,mode,1))
log_warnusys_return(LOG_EXIT_ZERO,"get file(s) of module: ",svname) ;
return 1 ;
}
static int rebuild_list(sv_alltype *alltype,stralloc *list,stralloc *sv_all_type, stralloc *module_service)
{
log_flow() ;
size_t pos, id, did, nid, dnid ;
sv_alltype_ref sv ;
id = alltype->cname.idga, nid = alltype->cname.nga ;
for (; nid ; id += strlen(deps.s + id) + 1, nid--)
{
char *deps_name = deps.s + id ;
/** if we check the dependencies of a module which was declared
* inside the main module, the recursive operation enter on infinite loop.
* So, break it by dependency addition comparison */
if (sastr_cmp(sv_all_type,deps_name) == -1) {
for (pos = 0 ; pos < genalloc_len(sv_alltype,&gasv) ; pos++) {
sv = &genalloc_s(sv_alltype,&gasv)[pos] ;
int type = sv->cname.itype == TYPE_MODULE ? 1 : 0 ;
char *n = keep.s + sv->cname.name ;
if (!strcmp(n,deps_name)) {
if (!stralloc_catb(list,keep.s + sv->src,strlen(keep.s + sv->src) + 1))
return 0 ;
if (!sv->cname.nga)
continue ;
did = type ? sv->cname.idcontents : sv->cname.idga, dnid = type ? sv->cname.ncontents : sv->cname.nga ;
for (;dnid; did += strlen(deps.s + did) + 1, dnid--) {
if (sastr_cmp(list,deps.s + did) >= 0)
continue ;
if (!rebuild_list(sv,list,sv_all_type,module_service))
log_warnu(LOG_EXIT_ZERO,"rebuild dependencies list of: ",deps.s + did) ;
}
}
}
if (!stralloc_catb(sv_all_type,deps_name,strlen(deps_name) + 1))
return 0 ;
}
if (!stralloc_catb(module_service,deps_name,strlen(deps_name) + 1))
return 0 ;
}
if (!sastr_sortndrop_element(module_service))
return 0 ;
return 1 ;
}
/** return 1 on success
* return 0 on failure
* return 2 on already enabled
* @svname do not contents the path of the frontend file*/
int parse_module(sv_alltype *alltype, ssexec_t *info, stralloc *parsed_list, uint8_t force)
{
log_flow() ;
int r, err = 1, insta = -1, minsta = -1, svtype = -1, from_ext_insta = 0, already_parsed = 0 ;
size_t pos = 0, id, nid, newlen ;
stralloc sdir = STRALLOC_ZERO ; // service dir
stralloc list = STRALLOC_ZERO ;
stralloc tmp = STRALLOC_ZERO ;
stralloc addonsv = STRALLOC_ZERO ;
char *sv = keep.s + alltype->cname.name ;
char src[strlen(keep.s + alltype->src) + 1] ;
uint8_t conf = alltype->overwrite_conf ;
if (!ob_dirname(src, keep.s + alltype->src))
log_dieu(LOG_EXIT_SYS,"get dirname of: ", keep.s + alltype->src) ;
log_trace("start parse process of module: ",sv) ;
/** should be always right,
* be paranoid and check it */
insta = instance_check(sv) ;
if (insta <= 0)
log_die(LOG_EXIT_SYS, "invalid module instance name: ",sv);
minsta = insta ;
if (!module_path(&sdir, &tmp, sv, src, info->owner))
log_dieu(LOG_EXIT_SYS,"resolve source of module: ",sv);
/** check mandatory directories:
* module/module_name, module/module_name/{configure,service,service@} */
if (!check_dir(tmp.s, "")) return 0 ;
if (!check_dir(tmp.s, SS_MODULE_CONFIG_DIR)) return 0 ;
if (!check_dir(tmp.s, SS_MODULE_SERVICE)) return 0 ;
if (!check_dir(tmp.s, SS_MODULE_SERVICE_INSTANCE)) return 0 ;
newlen = sdir.len ;
char permanent_sdir[sdir.len + 2] ;
auto_strings(permanent_sdir, sdir.s, "/") ;
r = scan_mode(sdir.s, S_IFDIR) ;
if (r < 0) { errno = EEXIST ; log_dieusys(LOG_EXIT_SYS,"conflicting format of: ", sdir.s) ; }
else if (!r) {
if (!hiercopy(tmp.s, sdir.s))
log_dieusys(LOG_EXIT_SYS, "copy: ", tmp.s, " to: ", sdir.s) ;
} else {
/** Must reconfigure all services of the module */
if (force < 2) {
log_warn("skip configuration of the module: ", sv, " -- already configured") ;
err = 2 ;
goto make_deps ;
}
if (rm_rf(sdir.s) < 0)
log_dieusys (LOG_EXIT_SYS, "remove: ", sdir.s) ;
if (!hiercopy(tmp.s, sdir.s))
log_dieusys(LOG_EXIT_SYS,"copy: ", tmp.s, " to: ", sdir.s) ;
}
/** regex file content */
list.len = 0 ;
if (!get_list(&list, &sdir, newlen, sv, S_IFREG)) return 0 ;
if (!regex_replace(&list, alltype, sv)) return 0 ;
/* regex directories name */
if (!get_list(&list, &sdir, newlen, sv, S_IFDIR)) return 0 ;
if (!regex_rename(&list, alltype->type.module.iddir, alltype->type.module.ndir, sdir.s)) return 0 ;
/* regex files name */
list.len = 0 ;
if (!get_list(&list,&sdir, newlen, sv, S_IFREG)) return 0 ;
if (!regex_rename(&list, alltype->type.module.idfiles, alltype->type.module.nfiles, sdir.s)) return 0 ;
/* launch configure script */
if (!regex_configure(alltype, info, permanent_sdir, sv, conf)) return 0 ;
make_deps:
tmp.len = 0 ;
list.len = 0 ;
if (!auto_stra(&tmp, permanent_sdir, SS_MODULE_SERVICE + 1))
log_die_nomem("stralloc") ;
/** get all services */
char const *exclude[1] = { 0 } ;
if (!sastr_dir_get_recursive(&list, tmp.s, exclude, S_IFREG, 1))
log_dieusys(LOG_EXIT_SYS, "get file(s) of module: ", sv) ;
/** add addon services */
if (alltype->type.module.naddservices > 0) {
id = alltype->type.module.idaddservices, nid = alltype->type.module.naddservices ;
for (; nid ; id += strlen(keep.s + id) + 1, nid--) {
char *name = keep.s + id ;
if (service_frontend_path(&list, name, info->owner,0) < 1)
log_die(LOG_EXIT_SYS, "resolve source path of: ", name) ;
}
}
tmp.len = 0 ;
sdir.len = 0 ;
/** remake the depends field.
* incoporate the module services dependencies inside the list to parse
* and each dependency of each module service dependency.
* Do it recursively. */
if (!rebuild_list(alltype, &list, &tmp, &sdir))
log_dieu(LOG_EXIT_SYS,"rebuild dependencies list of: ", sv) ;
/** parse all services of the modules */
for (pos = 0 ; pos < list.len ; pos += strlen(list.s + pos) + 1) {
insta = 0, svtype = -1, from_ext_insta = 0, already_parsed = 0 ;
char *svname = list.s + pos ;
size_t len = strlen(svname) ;
char bname[len + 1] ;
char *pbname = 0 ;
addonsv.len = 0 ;
if (sastr_cmp(parsed_list, svname) >= 0) {
/** already parsed ? */
size_t idx = 0 ;
for (; idx < genalloc_len(sv_alltype, &gasv) ; idx++) {
char *name = keep.s + genalloc_s(sv_alltype, &gasv)[idx].src ;
if (!strcmp(name, svname)) {
svname = name ;
break ;
}
}
already_parsed = 1 ;
}
if (!ob_basename(bname,svname))
log_dieu(LOG_EXIT_SYS,"find basename of: ", svname) ;
pbname = bname ;
/** detect cyclic call. Sub-module cannot call it itself*/
if (!strcmp(sv, bname))
log_die(LOG_EXIT_SYS,"cyclic call detected -- ", sv, " call ", bname) ;
insta = instance_check(bname) ;
if (!insta) log_die(LOG_EXIT_SYS,"invalid instance name: ", svname) ;
if (insta > 0) {
/** we can't know the origin of the instanciated service.
* Search first at service@ directory, if it not found
* pass through the classic service_frontend_path() */
pbname = bname ;
if (!already_parsed) {
size_t l = strlen(permanent_sdir) ;
char tmp[l + SS_MODULE_SERVICE_INSTANCE_LEN + 2] ;
auto_strings(tmp, permanent_sdir, SS_MODULE_SERVICE_INSTANCE + 1, "/") ;
r = service_frontend_src(&addonsv, pbname, tmp) ;
if (r == -1) log_dieusys(LOG_EXIT_SYS,"parse source directory: ", tmp) ;
if (!r) {
if (service_frontend_path(&addonsv, pbname, info->owner, 0) < 1)
log_dieu(LOG_EXIT_SYS,"resolve source path of: ", pbname) ;
}
svname = addonsv.s ;
}
from_ext_insta++ ;
len = strlen(svname) ;
}
if (!already_parsed)
start_parser(svname, info, 0, permanent_sdir) ;
char ext_insta[len + 1] ;
if (from_ext_insta) {
size_t len = strlen(svname) ;
r = get_rlen_until(svname, '@', len) + 1 ;
size_t newlen = len - (len - r) ;
auto_strings(ext_insta, svname) ;
ext_insta[newlen] = 0 ;
svname = ext_insta ;
}
/** we want the configuration file for each service inside
* the configuration directory of the module.
* In case of sub-module, we skip it.
* Also, we skip every dependency of the sub-module,
* each module contains its own services.*/
char *version = keep.s + alltype->cname.version ;
{
stralloc tmpenv = STRALLOC_ZERO ;
/** SS_MAX_SERVICE is the maximum of services set at compile time
* that can be supervised by s6-svscan. 500 is the default which
* should be large enough for the majority of the cases */
size_t pos, spos, id, nid, idmodule[SS_MAX_SERVICE] = { 0 } ;
sv_alltype_ref svref ;
if (!env_resolve_conf(&tmpenv, sv, info->owner))
log_dieu(LOG_EXIT_SYS,"get path of the configuration file") ;
if (!auto_stra(&tmpenv, "/"))
log_die_nomem("stralloc") ;
/** search first for all sub-modules */
for (pos = 0 ; pos < genalloc_len(sv_alltype,&gasv); pos++) {
if (genalloc_s(sv_alltype,&gasv)[pos].cname.itype == TYPE_MODULE) {
idmodule[pos] = 1 ;
svref = &genalloc_s(sv_alltype,&gasv)[pos] ;
id = svref->cname.idcontents, nid = svref->cname.ncontents ;
for (;nid; id += strlen(deps.s + id) + 1, nid--) {
char *name = deps.s + id ;
for (spos = 0 ; spos < genalloc_len(sv_alltype,&gasv);spos++)
if (!strcmp(name,keep.s + genalloc_s(sv_alltype,&gasv)[spos].cname.name))
idmodule[spos] = 1 ;
}
}
}
for (pos = 0 ; pos < genalloc_len(sv_alltype,&gasv); pos++) {
if (!genalloc_s(sv_alltype,&gasv)[pos].opts[2] ||
idmodule[pos]) continue ;
char *n = keep.s + genalloc_s(sv_alltype,&gasv)[pos].cname.name ;
if (!strcmp(n,bname)) {
genalloc_s(sv_alltype,&gasv)[pos].srconf = keep.len ;
if (!auto_stra(&tmpenv,version,"/",bname)) log_warn_return(LOG_EXIT_ZERO,"stralloc") ;
if (!stralloc_catb(&keep,tmpenv.s,strlen(tmpenv.s) + 1))
log_die_nomem("stralloc") ;
break ;
}
}
stralloc_free(&tmpenv) ;
}
svtype = get_svtype_from_file(svname) ;
if (svtype == -1) log_dieu(LOG_EXIT_SYS,"get svtype of: ",svname) ;
if (sastr_cmp(&sdir,pbname) == -1)
if (!stralloc_catb(&sdir,pbname,strlen(pbname) + 1))
log_die_nomem("stralloc") ;
if (sastr_cmp(&tmp,pbname) == -1)
if (svtype != TYPE_CLASSIC)
if (!stralloc_catb(&tmp,pbname,strlen(pbname) + 1))
log_die_nomem("stralloc") ;
}
/** prefix each service inside the module with the name of the module */
list.len = 0 ;
if (!instance_splitname(&list,sv,minsta,SS_INSTANCE_NAME))
log_dieu(LOG_EXIT_SYS, "split instance service: ",sv) ;
list.len-- ; //instance_splitname close the string
if (!auto_stra(&list,"-"))
log_die_nomem("stralloc") ;
alltype->cname.idga = deps.len ;
alltype->cname.nga = 0 ;
for (pos = 0 ;pos < tmp.len ; pos += strlen(tmp.s + pos) + 1) {
if (!stralloc_catb(&deps,list.s, list.len) ||
!stralloc_catb(&deps,tmp.s + pos,strlen(tmp.s + pos) + 1))
log_die_nomem("stralloc") ;
alltype->cname.nga++ ;
}
alltype->cname.idcontents = deps.len ;
for (pos = 0 ;pos < sdir.len ; pos += strlen(sdir.s + pos) + 1) {
if (!stralloc_catb(&deps,list.s, list.len) ||
!stralloc_catb(&deps,sdir.s + pos,strlen(sdir.s + pos) + 1))
log_die_nomem("stralloc") ;
alltype->cname.ncontents++ ;
}
tmp.len = 0 ;
if (!auto_stra(&tmp,permanent_sdir,SS_MODULE_CONFIG_DIR + 1))
log_die_nomem("stralloc") ;
if (rm_rf(tmp.s) < 0)
log_dieusys(LOG_EXIT_SYS,"remove: ",tmp.s) ;
stralloc_free(&sdir) ;
stralloc_free(&list) ;
stralloc_free(&tmp) ;
stralloc_free(&addonsv) ;
return err ;
}
/* helper */
/* 0 filename undefine
* -1 system error
* should return at least 2 meaning :: no file define*/
int regex_get_file_name(char *filename,char const *str)
{
log_flow() ;
int r ;
size_t pos = 0 ;
stralloc kp = STRALLOC_ZERO ;
parse_mill_t MILL_GET_COLON = {
.open = ':', .close = ':',
.skip = " \t\r", .skiplen = 3,
.forceclose = 1,
.inner.debug = "get_colon" } ;
r = mill_element(&kp,str,&MILL_GET_COLON,&pos) ;
if (r == -1) goto err ;
auto_strings(filename,kp.s) ;
stralloc_free(&kp) ;
return pos ;
err:
stralloc_free(&kp) ;
return -1 ;
}
int regex_get_replace(char *replace, char const *str)
{
log_flow() ;
int pos = get_len_until(str,'=') ;
if (!pos || pos == -1) return 0 ;
char tmp[pos + 1] ;
memcpy(tmp,str,pos) ;
tmp[pos] = 0 ;
auto_strings(replace,tmp) ;
return 1 ;
}
int regex_get_regex(char *regex, char const *str)
{
log_flow() ;
size_t len = strlen(str) ;
int pos = get_len_until(str,'=') ;
if (!pos || pos == -1) return 0 ;
pos++ ; // remove '='
char tmp[len + 1] ;
memcpy(tmp,str + pos,len-pos) ;
tmp[len-pos] = 0 ;
auto_strings(regex,tmp) ;
return 1 ;
}
int regex_replace(stralloc *list,sv_alltype *alltype,char const *svname)
{
log_flow() ;
int r ;
size_t in = 0, pos, inlen ;
stralloc tmp = STRALLOC_ZERO ;
for (; in < list->len; in += strlen(list->s + in) + 1)
{
tmp.len = 0 ;
char *str = list->s + in ;
size_t len = strlen(str) ;
char bname[len + 1] ;
char dname[len + 1] ;
if (!ob_basename(bname,str)) log_warnu_return(LOG_EXIT_ZERO,"get basename of: ",str) ;
if (!ob_dirname(dname,str)) log_warnu_return(LOG_EXIT_ZERO,"get dirname of: ",str) ;
log_trace("read service file of: ",dname,bname) ;
r = read_svfile(&tmp,bname,dname) ;
if (!r) log_warnusys_return(LOG_EXIT_ZERO,"read file: ",str) ;
if (r == -1) continue ;
pos = alltype->type.module.start_infiles, inlen = alltype->type.module.end_infiles ;
for (; pos < inlen ; pos += strlen(keep.s + pos) + 1)
{
int all = 0, fpos = 0 ;
char filename[512] = { 0 } ;
char replace[512] = { 0 } ;
char regex[512] = { 0 } ;
char const *line = keep.s + pos ;
if (strlen(line) >= 511) log_warn_return(LOG_EXIT_ZERO,"limit exceeded in service: ", svname) ;
if ((line[0] != ':') || (get_sep_before(line + 1,':','=') < 0))
log_warn_return(LOG_EXIT_ZERO,"bad format in line: ",line," of key @infiles field") ;
fpos = regex_get_file_name(filename,line) ;
if (fpos == -1) log_warnu_return(LOG_EXIT_ZERO,"get filename of line: ",line) ;
else if (fpos < 3) all = 1 ;
if (!regex_get_replace(replace,line+fpos)) log_warnu_return(LOG_EXIT_ZERO,"replace string of line: ",line) ;
if (!regex_get_regex(regex,line+fpos)) log_warnu_return(LOG_EXIT_ZERO,"regex string of line: ",line) ;
if (obstr_equal(bname,filename) || all)
{
if (!sastr_replace_all(&tmp,replace,regex))
log_warnu_return(LOG_EXIT_ZERO,"replace: ",replace," by: ", regex," in file: ",str) ;
if (!stralloc_0(&tmp))
log_warnusys_return(LOG_EXIT_ZERO,"stralloc") ;
tmp.len-- ;
if (!file_write_unsafe(dname,bname,tmp.s,tmp.len))
log_warnusys_return(LOG_EXIT_ZERO,"write: ",dname,"/","filename") ;
}
}
}
stralloc_free(&tmp) ;
return 1 ;
}
int regex_rename(stralloc *list, int id, unsigned int nid, char const *sdir)
{
log_flow() ;
stralloc tmp = STRALLOC_ZERO ;
size_t pos = id, len = nid, in ;
pos = id, len = nid ;
for (;len; pos += strlen(keep.s + pos) + 1,len--)
{
char *line = keep.s + pos ;
char replace[512] = { 0 } ;
char regex[512] = { 0 } ;
if (!regex_get_replace(replace,line)) log_warnu_return(LOG_EXIT_ZERO,"replace string of line: ",line) ;
if (!regex_get_regex(regex,line)) log_warnu_return(LOG_EXIT_ZERO,"regex string of line: ",line) ;
for (in = 0 ; in < list->len; in += strlen(list->s + in) + 1)
{
tmp.len = 0 ;
char *str = list->s + in ;
size_t len = strlen(str) ;
char dname[len + 1] ;
if (!ob_dirname(dname,str)) log_warnu_return(LOG_EXIT_ZERO,"get dirname of: ",str) ;
if (!sabasename(&tmp,str,len)) log_warnusys_return(LOG_EXIT_ZERO,"get basename of: ",str) ;
if (!stralloc_0(&tmp)) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ;
if (!sastr_replace(&tmp,replace,regex))
log_warnu_return(LOG_EXIT_ZERO,"replace: ",replace," by: ", regex," in file: ",str) ;
if (!stralloc_0(&tmp))
log_warnu_return(LOG_EXIT_ZERO,"stralloc") ;
char new[len + tmp.len + 1] ;
auto_strings(new,dname,tmp.s) ;
/** do not try to rename the same directory */
if (!obstr_equal(str,new))
{
log_trace("rename: ",str," to: ",new) ;
if (rename(str,new) == -1)
log_warnusys_return(LOG_EXIT_ZERO,"rename: ",str," to: ",new) ;
}
}
}
stralloc_free(&tmp) ;
return 1 ;
}
int regex_configure(sv_alltype *alltype,ssexec_t *info, char const *module_dir,char const *module_name,uint8_t conf)
{
log_flow() ;
int wstat, r ;
pid_t pid ;
size_t clen = alltype->type.module.configure > 0 ? 1 : 0 ;
size_t module_dirlen = strlen(module_dir), n ;
stralloc env = STRALLOC_ZERO ;
char const *newargv[2 + clen] ;
unsigned int m = 0 ;
char pwd[module_dirlen + SS_MODULE_CONFIG_DIR_LEN + 1] ;
auto_strings(pwd,module_dir,SS_MODULE_CONFIG_DIR + 1) ;
char config_script[module_dirlen + SS_MODULE_CONFIG_DIR_LEN + 1 + SS_MODULE_CONFIG_SCRIPT_LEN + 1] ;
auto_strings(config_script,module_dir,SS_MODULE_CONFIG_DIR + 1,"/",SS_MODULE_CONFIG_SCRIPT) ;
r = scan_mode(config_script,S_IFREG) ;
if (r > 0)
{
/** export ssexec_t info value on the environment */
{
char owner[UID_FMT];
owner[uid_fmt(owner,info->owner)] = 0 ;
char verbo[UINT_FMT];
verbo[uid_fmt(verbo,VERBOSITY)] = 0 ;
if (!auto_stra(&env, \
"MOD_NAME=",module_name,"\n", \
"MOD_BASE=",info->base.s,"\n", \
"MOD_LIVE=",info->live.s,"\n", \
"MOD_TREE=",info->tree.s,"\n", \
"MOD_SCANDIR=",info->scandir.s,"\n", \
"MOD_TREENAME=",info->treename.s,"\n", \
"MOD_OWNER=",owner,"\n", \
"MOD_COLOR=",info->opt_color ? "1" : "0","\n", \
"MOD_VERBOSITY=",verbo,"\n", \
"MOD_MODULE_DIR=",module_dir,"\n", \
"MOD_SKEL_DIR=",SS_SKEL_DIR,"\n", \
"MOD_SERVICE_SYSDIR=",SS_SERVICE_SYSDIR,"\n", \
"MOD_SERVICE_ADMDIR=",SS_SERVICE_ADMDIR,"\n", \
"MOD_SERVICE_ADMCONFDIR=",SS_SERVICE_ADMCONFDIR,"\n", \
"MOD_MODULE_SYSDIR=",SS_MODULE_SYSDIR,"\n", \
"MOD_MODULE_ADMDIR=",SS_MODULE_ADMDIR,"\n", \
"MOD_SCRIPT_SYSDIR=",SS_SCRIPT_SYSDIR,"\n", \
"MOD_USER_DIR=",SS_USER_DIR,"\n", \
"MOD_SERVICE_USERDIR=",SS_SERVICE_USERDIR,"\n", \
"MOD_SERVICE_USERCONFDIR=",SS_SERVICE_USERCONFDIR,"\n", \
"MOD_MODULE_USERDIR=",SS_MODULE_USERDIR,"\n", \
"MOD_SCRIPT_USERDIR=",SS_SCRIPT_USERDIR,"\n"))
log_warnu_return(LOG_EXIT_ZERO,"append environment variables") ;
}
/** environment is not mandatory */
if (alltype->opts[2] > 0)
{
stralloc oenv = STRALLOC_ZERO ;
stralloc name = STRALLOC_ZERO ;
stralloc dst = STRALLOC_ZERO ;
if (!env_prepare_for_write(&name,&dst,&oenv,alltype,conf))
return 0 ;
if (!write_env(name.s,oenv.s,dst.s))
log_warnu_return(LOG_EXIT_ZERO,"write environment") ;
/** Reads all file from the directory */
if (!environ_clean_envfile(&env,dst.s))
log_warnu_return(LOG_EXIT_ZERO,"prepare environment") ;
if (!environ_remove_unexport(&env,&env))
log_warnu_return(LOG_EXIT_ZERO,"remove exclamation mark from environment variables") ;
stralloc_free(&name) ;
stralloc_free(&oenv) ;
stralloc_free(&dst) ;
}
if (!sastr_split_string_in_nline(&env))
log_warnu_return(LOG_EXIT_ZERO,"rebuild environment") ;
n = env_len((const char *const *)environ) + 1 + byte_count(env.s,env.len,'\0') ;
char const *newenv[n + 1] ;
if (!env_merge (newenv, n ,(const char *const *)environ,env_len((const char *const *)environ),env.s, env.len))
log_warnusys_return(LOG_EXIT_ZERO,"build environment") ;
if (chdir(pwd) < 0)
log_warnusys_return(LOG_EXIT_ZERO,"chdir to: ",pwd) ;
m = 0 ;
newargv[m++] = config_script ;
if (alltype->type.module.configure > 0)
newargv[m++] = keep.s + alltype->type.module.configure ;
newargv[m++] = 0 ;
log_info("launch script configure of module: ",module_name) ;
pid = child_spawn0(newargv[0],newargv,newenv) ;
if (waitpid_nointr(pid,&wstat, 0) < 0)
log_warnusys_return(LOG_EXIT_ZERO,"wait for: ",config_script) ;
if (wstat)
log_warnu_return(LOG_EXIT_ZERO,"run: ",config_script) ;
}
stralloc_free(&env) ;
return 1 ;
}