Skip to content
Snippets Groups Projects
Commit cf311fbf authored by Eric Vidal's avatar Eric Vidal :speech_balloon:
Browse files

split parser_module from parser_enabled to a independent file,add conf...

split parser_module from parser_enabled to a independent file,add conf argument to parse_service_before, parse_service_deps and parse_service_opts_deps
parent 66bbb7d0
No related branches found
No related tags found
No related merge requests found
...@@ -55,7 +55,6 @@ struct sv_execlog_s ...@@ -55,7 +55,6 @@ struct sv_execlog_s
int destination ; int destination ;
uint32_t backup ; uint32_t backup ;
uint32_t maxsize ; uint32_t maxsize ;
/**timestamp=50->tai,timestamp=51->iso,52->none*/
int timestamp ; int timestamp ;
int idga ; //pos in stralloc deps int idga ; //pos in stralloc deps
unsigned int nga ; //number of deps in stralloc deps unsigned int nga ; //number of deps in stralloc deps
...@@ -285,9 +284,9 @@ extern void freed_parser(void) ; ...@@ -285,9 +284,9 @@ extern void freed_parser(void) ;
extern void start_parser(stralloc *list,ssexec_t *info, unsigned int *nbsv,uint8_t FORCE) ; extern void start_parser(stralloc *list,ssexec_t *info, unsigned int *nbsv,uint8_t FORCE) ;
extern int parser(sv_alltype *service,stralloc *src,char const *svname,int svtype) ; extern int parser(sv_alltype *service,stralloc *src,char const *svname,int svtype) ;
extern int parse_service_check_enabled(char const *tree_directory, char const *svname,uint8_t force,uint8_t *exist) ; extern int parse_service_check_enabled(char const *tree_directory, char const *svname,uint8_t force,uint8_t *exist) ;
extern int parse_service_before(ssexec_t *info, stralloc *parsed_list, stralloc *opts_deps_list, char const *sv,unsigned int *nbsv, stralloc *sasv,uint8_t force) ; extern int parse_service_before(ssexec_t *info, stralloc *parsed_list, stralloc *opts_deps_list, char const *sv,unsigned int *nbsv, stralloc *sasv,uint8_t force,uint8_t conf) ;
extern int parse_service_deps(ssexec_t *info,stralloc *parsed_list, stralloc *opts_deps_list, sv_alltype *sv_before, char const *sv,unsigned int *nbsv,stralloc *sasv,uint8_t force) ; extern int parse_service_deps(ssexec_t *info,stralloc *parsed_list, stralloc *opts_deps_list, sv_alltype *sv_before, char const *sv,unsigned int *nbsv,stralloc *sasv,uint8_t force,uint8_t conf) ;
extern int parse_service_opts_deps(ssexec_t *info,stralloc *parsed_list,stralloc *opts_deps_list,sv_alltype *sv_before,char const *sv,unsigned int *nbsv,stralloc *sasv,uint8_t force,uint8_t mandatory) ; extern int parse_service_opts_deps(ssexec_t *info,stralloc *parsed_list,stralloc *opts_deps_list,sv_alltype *sv_before,char const *sv,unsigned int *nbsv,stralloc *sasv,uint8_t force,uint8_t conf,uint8_t mandatory) ;
extern int parse_add_service(stralloc *parsed_list,sv_alltype *sv_before,char const *service,unsigned int *nbsv,uid_t owner) ; extern int parse_add_service(stralloc *parsed_list,sv_alltype *sv_before,char const *service,unsigned int *nbsv,uid_t owner) ;
extern int get_svtype(sv_alltype *sv_before, char const *contents) ; extern int get_svtype(sv_alltype *sv_before, char const *contents) ;
/** split */ /** split */
...@@ -319,7 +318,7 @@ extern int write_dependencies(unsigned int nga,unsigned int idga,char const *dst ...@@ -319,7 +318,7 @@ extern int write_dependencies(unsigned int nga,unsigned int idga,char const *dst
extern int write_env(char const *name,stralloc *sa,char const *dst) ; extern int write_env(char const *name,stralloc *sa,char const *dst) ;
extern int write_oneshot_logger(stralloc *destlog, sv_alltype *sv) ; extern int write_oneshot_logger(stralloc *destlog, sv_alltype *sv) ;
/** module */ /** module */
extern int parse_module(sv_alltype *sv_before,char const *svname,uid_t owner,uint8_t force) ; extern int parse_module(stralloc *svclassic,sv_alltype *sv_before,char const *svname,uid_t owner,uint8_t force,uint8_t conf) ;
extern int regex_get_file_name(char *filename,char const *str) ; extern int regex_get_file_name(char *filename,char const *str) ;
extern int regex_get_replace(char *replace, char const *str) ; extern int regex_get_replace(char *replace, char const *str) ;
extern int regex_get_regex(char *regex, char const *str) ; extern int regex_get_regex(char *regex, char const *str) ;
......
...@@ -15,6 +15,7 @@ hpr_wall.o ...@@ -15,6 +15,7 @@ hpr_wall.o
instance.o instance.o
parser.o parser.o
parser_enabled.o parser_enabled.o
parser_module.o
parser_utils.o parser_utils.o
parser_write.o parser_write.o
rc_init.o rc_init.o
......
...@@ -30,18 +30,20 @@ ...@@ -30,18 +30,20 @@
#include <skalibs/direntry.h> #include <skalibs/direntry.h>
#include <skalibs/djbunix.h> #include <skalibs/djbunix.h>
#include <skalibs/env.h> #include <skalibs/env.h>
#include <skalibs/bytestr.h>//byte_count
#include <66/resolve.h> #include <66/resolve.h>
#include <66/utils.h> #include <66/utils.h>
#include <66/constants.h> #include <66/constants.h>
#include <66/environ.h> #include <66/environ.h>
int parse_service_before(ssexec_t *info,stralloc *parsed_list,stralloc *tree_list, char const *sv,unsigned int *nbsv, stralloc *sasv,uint8_t force) int parse_service_before(ssexec_t *info,stralloc *parsed_list,stralloc *tree_list, char const *sv,unsigned int *nbsv, stralloc *sasv,uint8_t force,uint8_t conf)
{ {
log_trace("start parse process of service: ",sv) ; log_trace("start parse process of service: ",sv) ;
int insta ; int insta ;
uint8_t exist = 0 ; uint8_t exist = 0 ;
size_t svlen = strlen(sv), svsrclen, svnamelen ; size_t svlen = strlen(sv), svsrclen, svnamelen ;
stralloc svclassic = STRALLOC_ZERO ;
char svname[svlen + 1], svsrc[svlen + 1] ; char svname[svlen + 1], svsrc[svlen + 1] ;
if (!ob_basename(svname,sv)) log_warnu_return(LOG_EXIT_ZERO,"get basename of: ",sv) ; if (!ob_basename(svname,sv)) log_warnu_return(LOG_EXIT_ZERO,"get basename of: ",sv) ;
if (!ob_dirname(svsrc,sv)) log_warnu_return(LOG_EXIT_ZERO,"get dirname of: ",sv) ; if (!ob_dirname(svsrc,sv)) log_warnu_return(LOG_EXIT_ZERO,"get dirname of: ",sv) ;
...@@ -131,9 +133,11 @@ int parse_service_before(ssexec_t *info,stralloc *parsed_list,stralloc *tree_lis ...@@ -131,9 +133,11 @@ int parse_service_before(ssexec_t *info,stralloc *parsed_list,stralloc *tree_lis
if (!stralloc_catb(&keep,svname,svnamelen + 1)) return 0 ; if (!stralloc_catb(&keep,svname,svnamelen + 1)) return 0 ;
} }
add: add:
if (sv_before.cname.itype == TYPE_MODULE) if (sv_before.cname.itype == TYPE_MODULE)
{ {
r = parse_module(&sv_before,svname,info->owner,force) ; svclassic.len = 0 ;
r = parse_module(&svclassic,&sv_before,svname,info->owner,force,conf) ;
if (!r) return 0 ; if (!r) return 0 ;
else if (r == 2) else if (r == 2)
{ {
...@@ -141,213 +145,43 @@ int parse_service_before(ssexec_t *info,stralloc *parsed_list,stralloc *tree_lis ...@@ -141,213 +145,43 @@ int parse_service_before(ssexec_t *info,stralloc *parsed_list,stralloc *tree_lis
sv_alltype_free(&sv_before) ; sv_alltype_free(&sv_before) ;
goto deps ; goto deps ;
} }
if (force > 1) if (force > 1 && exist)
{ {
int wstat ; char const *newargv[4] ;
pid_t pid ;
int color = log_color == &log_color_enable ? 1 : 0 ;
char const *newargv[9 + color + 1] ;
unsigned int m = 0 ; unsigned int m = 0 ;
char fmt[UINT_FMT] ;
fmt[uint_fmt(fmt,VERBOSITY)] = 0 ; newargv[m++] = "fake_name" ;
newargv[m++] = SS_BINPREFIX "66-disable" ;
newargv[m++] = "-v" ;
newargv[m++] = fmt ;
if (color)
newargv[m++] = "-z" ;
newargv[m++] = "-l" ;
newargv[m++] = info->live.s ;
newargv[m++] = "-t" ;
newargv[m++] = info->treename.s ;
newargv[m++] = svname ; newargv[m++] = svname ;
newargv[m++] = 0 ; newargv[m++] = 0 ;
if (ssexec_disable(m,newargv,(const char *const *)environ,info))
pid = child_spawn0(newargv[0],newargv,(const char *const *)environ) ; log_warnu_return(LOG_EXIT_ZERO,"disable module: ",svname) ;
if (waitpid_nointr(pid,&wstat, 0) < 0)
log_warnusys_return (LOG_EXIT_ZERO,"wait for: 66-disable") ;
/** may not be enabled yet, don't crash if it's the case */
if (wstat && WEXITSTATUS(wstat) != LOG_EXIT_USER) log_warnu_return(LOG_EXIT_ZERO,"disable module: ",svname) ;
}
}
deps:
if (!parse_add_service(parsed_list,&sv_before,svpath,nbsv,info->owner)) return 0 ;
if ((sv_before.cname.itype > TYPE_CLASSIC && force > 1) || !exist)
{
if (!parse_service_deps(info,parsed_list,tree_list,&sv_before,sv,nbsv,sasv,force)) return 0 ;
if (!parse_service_opts_deps(info,parsed_list,tree_list,&sv_before,sv,nbsv,sasv,force,KEY_MAIN_EXTDEPS)) return 0 ;
if (!parse_service_opts_deps(info,parsed_list,tree_list,&sv_before,sv,nbsv,sasv,force,KEY_MAIN_OPTSDEPS)) return 0 ;
}
freed:
return 1 ;
}
/** return 1 if all good
* return 0 on crash
* return 2 on already enabled */
int parse_module(sv_alltype *sv_before,char const *svname,uid_t owner,uint8_t force)
{
log_trace("start parse process of module: ",svname) ;
int r, insta, err = 1 ;
size_t in = 0 , pos = 0, len = 0 ;
stralloc mdir = STRALLOC_ZERO ; // module dir
stralloc sdir = STRALLOC_ZERO ; // service dir
stralloc list = STRALLOC_ZERO ;
stralloc tmp = STRALLOC_ZERO ;
stralloc sainsta = STRALLOC_ZERO ; // SS_INSTANCE_NAME
if (!ss_resolve_module_path(&sdir,&mdir,svname,owner)) return 0 ;
/** keep instance name */
insta = instance_check(svname) ;
if (!instance_splitname(&sainsta,svname,insta,SS_INSTANCE_NAME))
log_warnu_return(LOG_EXIT_ZERO,"get instance name") ;
r = scan_mode(sdir.s,S_IFDIR) ;
if (r < 0) { errno = EEXIST ; log_warnusys_return(LOG_EXIT_ZERO,"conflicting format of: ",sdir.s) ; }
else if (!r)
{
if (!hiercopy(mdir.s,sdir.s))
log_warnusys_return(LOG_EXIT_ZERO,"copy: ",mdir.s," to: ",sdir.s) ;
}
else
{
if (force < 2)
{
log_warn("Ignoring module: ",svname," -- already configured") ;
err = 2 ;
goto make_deps ;
} }
deps:
if (rm_rf(sdir.s) < 0) if (svclassic.len)
log_warnusys_return (LOG_EXIT_ZERO,"remove: ",sdir.s) ;
if (!hiercopy(mdir.s,sdir.s))
log_warnusys_return(LOG_EXIT_ZERO,"copy: ",mdir.s," to: ",sdir.s) ;
}
/** regex file content */
if (!sastr_dir_get_recursive(&list,sdir.s,"",S_IFREG))
log_warnusys_return(LOG_EXIT_ZERO,"get file(s) of module: ",svname) ;
pos = sv_before->type.module.start_infiles, len = sv_before->type.module.end_infiles ;
for (;pos < len; pos += strlen(keep.s + pos) + 1)
{
int all = 0 ; int 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,"file name 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) ;
for (in = 0 ; in < list.len; in += strlen(list.s + in) + 1)
{ {
tmp.len = 0 ; size_t pos = 0 ;
char *str = list.s + in ; for (; pos < svclassic.len ; pos += strlen(svclassic.s + pos) + 1)
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 (obstr_equal(bname,filename) || all)
{ {
if (!ob_dirname(dname,str)) log_warnu_return(LOG_EXIT_ZERO,"get dirname of: ",str) ; char *sv = svclassic.s + pos ;
if (!read_svfile(&tmp,bname,dname)) log_warnusys_return(LOG_EXIT_ZERO,"read file: ",str) ; if (!parse_service_before(info,parsed_list,tree_list,sv,nbsv,sasv,force,conf)) return 0 ;
if (!sastr_replace_all(&tmp,replace,regex)) log_warnu_return(LOG_EXIT_ZERO,"replace: ",replace," by: ", regex," in file: ",str) ;
if (!file_write_unsafe(dname,bname,tmp.s,tmp.len))
log_warnusys_return(LOG_EXIT_ZERO,"write: ",dname,"/","filename") ;
} }
} }
} }
/* regex directories name */
if (!regex_replace(sv_before->type.module.iddir,sv_before->type.module.ndir,sdir.s,S_IFDIR)) return 0 ;
/* regex files name */
if (!regex_replace(sv_before->type.module.idfiles,sv_before->type.module.nfiles,sdir.s,S_IFREG)) return 0 ;
/* configure script */
tmp.len = 0 ;
if (!auto_stra(&tmp,sdir.s,"/.configure/configure")) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ;
r = scan_mode(tmp.s,S_IFREG) ;
if (r > 0)
{
int wstat ;
pid_t pid ;
size_t clen = sv_before->type.module.configure > 0 ? 1 : 0 ;
char const *newargv[2 + clen] ;
unsigned int m = 0 ;
char pwd[sdir.len + 12] ;
auto_strings(pwd,sdir.s,"/.configure") ;
if (chdir(pwd) < 0) log_warnusys_return(LOG_EXIT_ZERO,"chdir to: ",pwd) ;
newargv[m++] = tmp.s ;
if (sv_before->type.module.configure > 0)
newargv[m++] = keep.s + sv_before->type.module.configure ;
newargv[m++] = 0 ;
pid = child_spawn0(newargv[0],newargv,(const char *const *)environ) ;
if (waitpid_nointr(pid,&wstat, 0) < 0)
log_warnusys_return(LOG_EXIT_ZERO,"wait for: ",sdir.s) ;
if (wstat) log_warnu_return(LOG_EXIT_ZERO,"run: ",sdir.s) ; if (!parse_add_service(parsed_list,&sv_before,svpath,nbsv,info->owner)) return 0 ;
tmp.len = 0 ;
if (!auto_stra(&tmp,sdir.s,"/.configure")) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ;
if (rm_rf(tmp.s) < 0)
log_warnusys_return(LOG_EXIT_ZERO,"remove: ",tmp.s) ;
}
make_deps:
/** get all services */
list.len = 0 ;
if (!sastr_dir_get_recursive(&list,sdir.s,".configure",S_IFREG))
log_warnusys_return(LOG_EXIT_ZERO,"get file(s) of module: ",svname) ;
/** remake the deps field */
size_t id = sv_before->cname.idga, nid = sv_before->cname.nga ;
sv_before->cname.idga = deps.len ;
sv_before->cname.nga = 0 ;
for (;nid; id += strlen(deps.s + id) + 1, nid--)
{
char *name = deps.s + id ;
if (!stralloc_catb(&deps,name,strlen(deps.s + id) + 1)) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ; ;
sv_before->cname.nga++ ;
}
for (pos = 0 ; pos < list.len ; pos += strlen(list.s + pos) + 1) if ((sv_before.cname.itype > TYPE_CLASSIC && force > 1) || !exist)
{ {
char *name = list.s + pos ; if (!parse_service_deps(info,parsed_list,tree_list,&sv_before,sv,nbsv,sasv,force,conf)) return 0 ;
char bname[len + sainsta.len + 1] ; if (!parse_service_opts_deps(info,parsed_list,tree_list,&sv_before,sv,nbsv,sasv,force,conf,KEY_MAIN_EXTDEPS)) return 0 ;
if (!ob_basename(bname,name)) log_warnu_return(LOG_EXIT_ZERO,"get basename of: ",name) ; if (!parse_service_opts_deps(info,parsed_list,tree_list,&sv_before,sv,nbsv,sasv,force,conf,KEY_MAIN_OPTSDEPS)) return 0 ;
insta = get_len_until(bname,'@') ;
insta++ ; // keep '@'
if (insta > 0)
{
auto_string_from(bname,insta,sainsta.s) ;
}
if (!stralloc_catb(&deps,bname,strlen(bname) + 1)) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ;
sv_before->cname.nga++ ;
} }
freed:
stralloc_free(&mdir) ; stralloc_free(&svclassic) ;
stralloc_free(&sdir) ; return 1 ;
stralloc_free(&list) ;
stralloc_free(&tmp) ;
stralloc_free(&sainsta) ;
return err ;
} }
int parse_service_deps(ssexec_t *info,stralloc *parsed_list,stralloc *tree_list, sv_alltype *sv_before, char const *sv,unsigned int *nbsv,stralloc *sasv,uint8_t force) int parse_service_deps(ssexec_t *info,stralloc *parsed_list,stralloc *tree_list, sv_alltype *sv_before, char const *sv,unsigned int *nbsv,stralloc *sasv,uint8_t force,uint8_t conf)
{ {
int r ; int r ;
char *dname = 0 ; char *dname = 0 ;
...@@ -367,7 +201,7 @@ int parse_service_deps(ssexec_t *info,stralloc *parsed_list,stralloc *tree_list, ...@@ -367,7 +201,7 @@ int parse_service_deps(ssexec_t *info,stralloc *parsed_list,stralloc *tree_list,
r = ss_resolve_src_path(&newsv,dname,info->owner) ; r = ss_resolve_src_path(&newsv,dname,info->owner) ;
if (r < 1) goto err ;//don't warn here, the ss_revolve_src_path already warn user if (r < 1) goto err ;//don't warn here, the ss_revolve_src_path already warn user
if (!parse_service_before(info,parsed_list,tree_list,newsv.s,nbsv,sasv,force)) goto err ; if (!parse_service_before(info,parsed_list,tree_list,newsv.s,nbsv,sasv,force,conf)) goto err ;
} }
} }
else log_trace(sv,": haven't dependencies") ; else log_trace(sv,": haven't dependencies") ;
...@@ -378,7 +212,7 @@ int parse_service_deps(ssexec_t *info,stralloc *parsed_list,stralloc *tree_list, ...@@ -378,7 +212,7 @@ int parse_service_deps(ssexec_t *info,stralloc *parsed_list,stralloc *tree_list,
return 0 ; return 0 ;
} }
int parse_service_opts_deps(ssexec_t *info,stralloc *parsed_list,stralloc *tree_list,sv_alltype *sv_before,char const *sv,unsigned int *nbsv,stralloc *sasv,uint8_t force, uint8_t mandatory) int parse_service_opts_deps(ssexec_t *info,stralloc *parsed_list,stralloc *tree_list,sv_alltype *sv_before,char const *sv,unsigned int *nbsv,stralloc *sasv,uint8_t force,uint8_t conf, uint8_t mandatory)
{ {
int r ; int r ;
stralloc newsv = STRALLOC_ZERO ; stralloc newsv = STRALLOC_ZERO ;
...@@ -441,7 +275,7 @@ int parse_service_opts_deps(ssexec_t *info,stralloc *parsed_list,stralloc *tree_ ...@@ -441,7 +275,7 @@ int parse_service_opts_deps(ssexec_t *info,stralloc *parsed_list,stralloc *tree_
} }
// be paranoid with the else if // be paranoid with the else if
else if (r == 1) { else if (r == 1) {
if (!parse_service_before(info,parsed_list,tree_list,newsv.s,nbsv,sasv,force)) if (!parse_service_before(info,parsed_list,tree_list,newsv.s,nbsv,sasv,force,conf))
goto err ; goto err ;
// we only keep the first found on optsdepends // we only keep the first found on optsdepends
if (!ext) break ; if (!ext) break ;
...@@ -486,7 +320,6 @@ int parse_service_check_enabled(char const *tree,char const *svname,uint8_t forc ...@@ -486,7 +320,6 @@ int parse_service_check_enabled(char const *tree,char const *svname,uint8_t forc
return 0 ; return 0 ;
} }
int parse_add_service(stralloc *parsed_list,sv_alltype *sv_before,char const *service,unsigned int *nbsv,uid_t owner) int parse_add_service(stralloc *parsed_list,sv_alltype *sv_before,char const *service,unsigned int *nbsv,uid_t owner)
{ {
stralloc conf = STRALLOC_ZERO ; stralloc conf = STRALLOC_ZERO ;
...@@ -511,99 +344,3 @@ int parse_add_service(stralloc *parsed_list,sv_alltype *sv_before,char const *se ...@@ -511,99 +344,3 @@ int parse_add_service(stralloc *parsed_list,sv_alltype *sv_before,char const *se
stralloc_free(&conf) ; stralloc_free(&conf) ;
return 0 ; return 0 ;
} }
/* module 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)
{
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)
{
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)
{
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(int id,unsigned int nid, char const *sdir,mode_t mode)
{
stralloc list = STRALLOC_ZERO ;
stralloc tmp = STRALLOC_ZERO ;
size_t pos = id, len = nid, in ;
if (!sastr_dir_get_recursive(&list,sdir,"",mode))
log_warnusys_return(LOG_EXIT_ZERO,"get content of: ",sdir) ;
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) ;
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))
if (rename(str,new) < 0)
log_warnusys_return(LOG_EXIT_ZERO,"rename: ",str," by: ",new) ;
}
}
stralloc_free(&tmp) ;
stralloc_free(&list) ;
return 1 ;
}
/*
* parser.c
*
* Copyright (c) 2018-2020 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 <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>
/** return 1 if all good
* return 0 on crash
* return 2 on already enabled */
int parse_module(stralloc *svclassic,sv_alltype *sv_before,char const *svname,uid_t owner,uint8_t force,uint8_t conf)
{
log_trace("start parse process of module: ",svname) ;
int r, insta, err = 1 ;
size_t in = 0 , pos = 0, inlen = 0 ;
stralloc sdir = STRALLOC_ZERO ; // service dir
stralloc list = STRALLOC_ZERO ;
stralloc tmp = STRALLOC_ZERO ;
stralloc sainsta = STRALLOC_ZERO ; // SS_INSTANCE_NAME
stralloc satype = STRALLOC_ZERO ; // keep information of module service
genalloc galist = GENALLOC_ZERO ; // module_type_t
if (!ss_resolve_module_path(&sdir,&tmp,svname,owner)) return 0 ;
/** keep instance name */
insta = instance_check(svname) ;
if (!instance_splitname(&sainsta,svname,insta,SS_INSTANCE_NAME))
log_warnu_return(LOG_EXIT_ZERO,"get instance name") ;
r = scan_mode(sdir.s,S_IFDIR) ;
if (r < 0) { errno = EEXIST ; log_warnusys_return(LOG_EXIT_ZERO,"conflicting format of: ",sdir.s) ; }
else if (!r)
{
if (!hiercopy(tmp.s,sdir.s))
log_warnusys_return(LOG_EXIT_ZERO,"copy: ",tmp.s," to: ",sdir.s) ;
}
else
{
/** Must reconfigure all services of the module */
if (force < 2)
{
log_warn("Ignoring module: ",svname," -- already configured") ;
err = 2 ;
goto make_deps ;
}
if (rm_rf(sdir.s) < 0)
log_warnusys_return (LOG_EXIT_ZERO,"remove: ",sdir.s) ;
if (!hiercopy(tmp.s,sdir.s))
log_warnusys_return(LOG_EXIT_ZERO,"copy: ",tmp.s," to: ",sdir.s) ;
}
/** regex file content */
if (!sastr_dir_get_recursive(&list,sdir.s,".configure",S_IFREG))
log_warnusys_return(LOG_EXIT_ZERO,"get file(s) of module: ",svname) ;
for (in = 0 ; in < list.len; in += strlen(list.s + in) + 1)
{
tmp.len = 0 ;
sv_alltype m_type = SV_ALLTYPE_ZERO ;
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) ;
if (!read_svfile(&tmp,bname,dname)) log_warnusys_return(LOG_EXIT_ZERO,"read file: ",str) ;
pos = sv_before->type.module.start_infiles, inlen = sv_before->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 (!file_write_unsafe(dname,bname,tmp.s,tmp.len))
log_warnusys_return(LOG_EXIT_ZERO,"write: ",dname,"/","filename") ;
}
}
/** keep information of the service */
m_type.cname.name = satype.len ;
if (!stralloc_catb(&satype,bname,strlen(bname) + 1)) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ;
m_type.src = satype.len ;
if (!stralloc_catb(&satype,dname,strlen(dname) + 1)) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ;
if (!get_svtype(&m_type,tmp.s))
log_warn_return (LOG_EXIT_ZERO,"invalid value for key: ",get_key_by_enum(ENUM_KEY_SECTION_MAIN,KEY_MAIN_TYPE)," in service file: ",dname,"/",bname) ;
if (!genalloc_append(sv_alltype,&galist,&m_type))
log_warnsys_return(LOG_EXIT_ZERO,"genalloc") ;
}
/* regex directories name */
if (!regex_replace(sv_before->type.module.iddir,sv_before->type.module.ndir,sdir.s,S_IFDIR)) return 0 ;
/* regex files name */
if (!regex_replace(sv_before->type.module.idfiles,sv_before->type.module.nfiles,sdir.s,S_IFREG)) return 0 ;
/* configure script */
tmp.len = 0 ;
if (!auto_stra(&tmp,sdir.s,"/.configure/configure")) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ;
r = scan_mode(tmp.s,S_IFREG) ;
if (r > 0)
{
stralloc oenv = STRALLOC_ZERO ;
stralloc env = STRALLOC_ZERO ;
/** environment is not mandatory */
if (sv_before->opts[2] > 0)
{
/** sv_before->srconf is not set yet
* we don't care, env_compute will find it.
* env_compute return 2 in case of need to write */
r = env_compute(&oenv,sv_before,conf) ;
if (!r) log_warnu_return(LOG_EXIT_ZERO,"compute environment") ;
if (!stralloc_0(&oenv)) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ;
/** prepare for the environment merge */
if (!environ_clean_envfile(&env,&oenv))
log_warnu_return(LOG_EXIT_ZERO,"prepare environment") ;
if (!stralloc_0(&oenv)) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ;
if (!sastr_split_string_in_nline(&env))
log_warnu_return(LOG_EXIT_ZERO,"rebuild environment") ;
}
size_t 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") ;
int wstat ;
pid_t pid ;
size_t clen = sv_before->type.module.configure > 0 ? 1 : 0 ;
char const *newargv[2 + clen] ;
unsigned int m = 0 ;
char pwd[sdir.len + 12] ;
auto_strings(pwd,sdir.s,"/.configure") ;
if (chdir(pwd) < 0) log_warnusys_return(LOG_EXIT_ZERO,"chdir to: ",pwd) ;
newargv[m++] = tmp.s ;
if (sv_before->type.module.configure > 0)
newargv[m++] = keep.s + sv_before->type.module.configure ;
newargv[m++] = 0 ;
log_trace("launch script configure of module: ",svname) ;
pid = child_spawn0(newargv[0],newargv,newenv) ;
if (waitpid_nointr(pid,&wstat, 0) < 0)
log_warnusys_return(LOG_EXIT_ZERO,"wait for: ",tmp.s) ;
if (wstat) log_warnu_return(LOG_EXIT_ZERO,"run: ",tmp.s) ;
tmp.len = 0 ;
if (!auto_stra(&tmp,sdir.s,"/.configure")) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ;
if (rm_rf(tmp.s) < 0)
log_warnusys_return(LOG_EXIT_ZERO,"remove: ",tmp.s) ;
stralloc_free(&oenv) ;
stralloc_free(&env) ;
}
make_deps:
/** get all services */
list.len = 0 ;
if (!sastr_dir_get_recursive(&list,sdir.s,".configure",S_IFREG))
log_warnusys_return(LOG_EXIT_ZERO,"get file(s) of module: ",svname) ;
/** remake the deps field */
size_t id = sv_before->cname.idga, nid = sv_before->cname.nga ;
sv_before->cname.idga = deps.len ;
sv_before->cname.nga = 0 ;
for (;nid; id += strlen(deps.s + id) + 1, nid--)
{
char *name = deps.s + id ;
if (!stralloc_catb(&deps,name,strlen(deps.s + id) + 1)) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ; ;
sv_before->cname.nga++ ;
}
/*** change name for instantiated service
* remove classic service from the list
* and add service to the stralloc deps.
* The genalloc was built before the configure script.
* Some services was removed. So we need to compare with
* the effective @list to match exactly our needs */
for (size_t i = 0; i < genalloc_len(sv_alltype,&galist); i++)
{
sv_alltype_ref sv = &genalloc_s(sv_alltype,&galist)[i] ;
char *name = satype.s + sv->cname.name ;
char *src = satype.s + sv->src ;
size_t namelen = strlen(name), srclen = strlen(src) ;
char tmp[namelen + srclen + 1] ;
auto_strings(tmp,src,name) ;
if (sv->cname.itype == TYPE_CLASSIC)
{
if (!sastr_add_string(svclassic,tmp))
log_warnu_return(LOG_EXIT_ZERO,"store classic service: ",tmp) ;
continue ;
}
if (sastr_find(&list,name) < 0) continue ;
insta = get_len_until(name,'@') ;
if (insta > 0)
{
insta++ ; // keep '@'
auto_string_from(name,insta,sainsta.s) ;
}
if (!stralloc_catb(&deps,name,strlen(name) + 1)) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ;
sv_before->cname.nga++ ;
}
stralloc_free(&sdir) ;
stralloc_free(&list) ;
stralloc_free(&tmp) ;
stralloc_free(&sainsta) ;
for (size_t i = 0 ; i < genalloc_len(sv_alltype,&galist) ; i++)
sv_alltype_free(&genalloc_s(sv_alltype,&galist)[i]) ;
genalloc_free(sv_alltype,&galist) ;
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)
{
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)
{
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)
{
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(int id,unsigned int nid, char const *sdir,mode_t mode)
{
stralloc list = STRALLOC_ZERO ;
stralloc tmp = STRALLOC_ZERO ;
size_t pos = id, len = nid, in ;
if (!sastr_dir_get_recursive(&list,sdir,"",mode))
log_warnusys_return(LOG_EXIT_ZERO,"get content of: ",sdir) ;
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) ;
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))
if (rename(str,new) < 0)
log_warnusys_return(LOG_EXIT_ZERO,"rename: ",str," by: ",new) ;
}
}
stralloc_free(&tmp) ;
stralloc_free(&list) ;
return 1 ;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment