diff --git a/src/include/66/parser.h b/src/include/66/parser.h index 73519ebd930da37639ec67c73699773bb4899a37..ed511f0dbe393bd0baed84202639d2a11de9357f 100644 --- a/src/include/66/parser.h +++ b/src/include/66/parser.h @@ -55,7 +55,6 @@ struct sv_execlog_s int destination ; uint32_t backup ; uint32_t maxsize ; - /**timestamp=50->tai,timestamp=51->iso,52->none*/ int timestamp ; int idga ; //pos in stralloc deps unsigned int nga ; //number of deps in stralloc deps @@ -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 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_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_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_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_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,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 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 get_svtype(sv_alltype *sv_before, char const *contents) ; /** split */ @@ -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_oneshot_logger(stralloc *destlog, sv_alltype *sv) ; /** 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_replace(char *replace, char const *str) ; extern int regex_get_regex(char *regex, char const *str) ; diff --git a/src/lib66/deps-lib/66 b/src/lib66/deps-lib/66 index bbea3507f79d0005d4b9fe9f8d9ded14028cd66a..de7b216a102c3cc886565cfa7203033f614e207b 100644 --- a/src/lib66/deps-lib/66 +++ b/src/lib66/deps-lib/66 @@ -15,6 +15,7 @@ hpr_wall.o instance.o parser.o parser_enabled.o +parser_module.o parser_utils.o parser_write.o rc_init.o diff --git a/src/lib66/parser_enabled.c b/src/lib66/parser_enabled.c index 8b5bf3917eb58237751573f4a66d9e32599a5be7..45d074ce8b589a67de747c8d0642c7cbb86847f0 100644 --- a/src/lib66/parser_enabled.c +++ b/src/lib66/parser_enabled.c @@ -30,18 +30,20 @@ #include <skalibs/direntry.h> #include <skalibs/djbunix.h> #include <skalibs/env.h> +#include <skalibs/bytestr.h>//byte_count #include <66/resolve.h> #include <66/utils.h> #include <66/constants.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) ; int insta ; uint8_t exist = 0 ; size_t svlen = strlen(sv), svsrclen, svnamelen ; + stralloc svclassic = STRALLOC_ZERO ; char svname[svlen + 1], svsrc[svlen + 1] ; 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) ; @@ -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 ; } add: + 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 ; else if (r == 2) { @@ -141,213 +145,43 @@ int parse_service_before(ssexec_t *info,stralloc *parsed_list,stralloc *tree_lis sv_alltype_free(&sv_before) ; goto deps ; } - if (force > 1) + if (force > 1 && exist) { - int wstat ; - pid_t pid ; - int color = log_color == &log_color_enable ? 1 : 0 ; - char const *newargv[9 + color + 1] ; + char const *newargv[4] ; unsigned int m = 0 ; - char fmt[UINT_FMT] ; - fmt[uint_fmt(fmt,VERBOSITY)] = 0 ; - - 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++] = "fake_name" ; newargv[m++] = svname ; 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: 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 ; + if (ssexec_disable(m,newargv,(const char *const *)environ,info)) + log_warnu_return(LOG_EXIT_ZERO,"disable module: ",svname) ; } - - if (rm_rf(sdir.s) < 0) - 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) + deps: + if (svclassic.len) { - 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 (obstr_equal(bname,filename) || all) + size_t pos = 0 ; + for (; pos < svclassic.len ; pos += strlen(svclassic.s + pos) + 1) { - 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) ; - 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") ; + char *sv = svclassic.s + pos ; + if (!parse_service_before(info,parsed_list,tree_list,sv,nbsv,sasv,force,conf)) return 0 ; } } } - /* 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) ; - 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++ ; - } + if (!parse_add_service(parsed_list,&sv_before,svpath,nbsv,info->owner)) return 0 ; - 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 ; - char bname[len + sainsta.len + 1] ; - if (!ob_basename(bname,name)) log_warnu_return(LOG_EXIT_ZERO,"get basename of: ",name) ; - 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++ ; + if (!parse_service_deps(info,parsed_list,tree_list,&sv_before,sv,nbsv,sasv,force,conf)) return 0 ; + if (!parse_service_opts_deps(info,parsed_list,tree_list,&sv_before,sv,nbsv,sasv,force,conf,KEY_MAIN_EXTDEPS)) return 0 ; + if (!parse_service_opts_deps(info,parsed_list,tree_list,&sv_before,sv,nbsv,sasv,force,conf,KEY_MAIN_OPTSDEPS)) return 0 ; } - - stralloc_free(&mdir) ; - stralloc_free(&sdir) ; - stralloc_free(&list) ; - stralloc_free(&tmp) ; - stralloc_free(&sainsta) ; - - return err ; + freed: + stralloc_free(&svclassic) ; + return 1 ; } -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 ; char *dname = 0 ; @@ -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) ; 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") ; @@ -378,7 +212,7 @@ int parse_service_deps(ssexec_t *info,stralloc *parsed_list,stralloc *tree_list, 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 ; stralloc newsv = STRALLOC_ZERO ; @@ -441,7 +275,7 @@ int parse_service_opts_deps(ssexec_t *info,stralloc *parsed_list,stralloc *tree_ } // be paranoid with the else if 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 ; // we only keep the first found on optsdepends if (!ext) break ; @@ -486,7 +320,6 @@ int parse_service_check_enabled(char const *tree,char const *svname,uint8_t forc return 0 ; } - int parse_add_service(stralloc *parsed_list,sv_alltype *sv_before,char const *service,unsigned int *nbsv,uid_t owner) { stralloc conf = STRALLOC_ZERO ; @@ -511,99 +344,3 @@ int parse_add_service(stralloc *parsed_list,sv_alltype *sv_before,char const *se stralloc_free(&conf) ; 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 ; -} diff --git a/src/lib66/parser_module.c b/src/lib66/parser_module.c new file mode 100644 index 0000000000000000000000000000000000000000..5d160831eb37aecf34e55655699829af035d1cd0 --- /dev/null +++ b/src/lib66/parser_module.c @@ -0,0 +1,363 @@ +/* + * 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 ; +}