diff --git a/src/lib66/parser_enabled.c b/src/lib66/parser_enabled.c index 2f26b10405616effe653f34557f3387755fb2abf..f827d474cc6db6b3591454296ce82bd5e48a33e9 100644 --- a/src/lib66/parser_enabled.c +++ b/src/lib66/parser_enabled.c @@ -23,98 +23,343 @@ #include <oblibs/log.h> #include <oblibs/sastr.h> #include <oblibs/environ.h> +#include <oblibs/files.h> #include <skalibs/stralloc.h> +#include <skalibs/direntry.h> +#include <skalibs/djbunix.h> #include <66/resolve.h> #include <66/utils.h> #include <66/constants.h> #include <66/environ.h> -int parse_service_check_enabled(ssexec_t *info, char const *svname,uint8_t force,uint8_t *exist) +int parse_service_before(ssexec_t *info,stralloc *parsed_list,stralloc *tree_list, char const *sv,unsigned int *nbsv, stralloc *sasv,uint8_t force) { - stralloc sares = STRALLOC_ZERO ; - ss_resolve_t res = RESOLVE_ZERO ; - int ret = 1 ; - if (!ss_resolve_pointo(&sares,info,SS_NOTYPE,SS_RESOLVE_SRC)) + log_trace("start parse process of service: ",sv) ; + int insta ; + uint8_t exist = 0 ; + size_t svlen = strlen(sv), svsrclen, svnamelen ; + 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) ; + svsrclen = strlen(svsrc) ; + svnamelen = strlen(svname) ; + char svpath[svsrclen + svnamelen + 1] ; + if (scan_mode(sv,S_IFDIR) == 1) return 1 ; + char tree[info->tree.len + SS_SVDIRS_LEN + 1] ; + auto_strings(tree,info->tree.s,SS_SVDIRS) ; + + int r = parse_service_check_enabled(tree,svname,force,&exist) ; + if (!r) goto freed ; + + sv_alltype sv_before = SV_ALLTYPE_ZERO ; + sasv->len = 0 ; + + insta = instance_check(svname) ; + if (!insta) + { + log_warn_return(LOG_EXIT_ZERO, "invalid instance name: ",svname) ; + } + else if (insta > 0) { - log_warnusys("set revolve pointer to source") ; - goto err ; - } - if (ss_resolve_check(sares.s,svname)) + stralloc tmp = STRALLOC_ZERO ; + instance_splitname(&tmp,svname,insta,SS_INSTANCE_TEMPLATE) ; + if (!read_svfile(sasv,tmp.s,svsrc)) return 0 ; + stralloc_free(&tmp) ; + } + else if (!read_svfile(sasv,svname,svsrc)) return 0 ; + + if (!get_svtype(&sv_before,sasv->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: ",svsrc,svname) ; + + if (insta > 0) { - if (!ss_resolve_read(&res,sares.s,svname)) + if (!instance_create(sasv,svname,SS_INSTANCE,insta)) + log_warn_return(LOG_EXIT_ZERO,"create instance service: ",svname) ; + + /** ensure that we have an empty line at the end of the string*/ + if (!stralloc_cats(sasv,"\n")) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ; + if (!stralloc_0(sasv)) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ; + } + + memcpy(svpath,svsrc,svsrclen) ; + memcpy(svpath + svsrclen,svname,svnamelen) ; + svpath[svsrclen + svnamelen] = 0 ; + + if (sastr_cmp(parsed_list,svpath) >= 0) + { + log_warn("Ignoring: ",sv," service: already parsed") ; + sasv->len = 0 ; + sv_alltype_free(&sv_before) ; + goto freed ; + } + if (!parser(&sv_before,sasv,svname,sv_before.cname.itype)) return 0 ; + + /** keep the name set by user + * uniquely for instantiated service + * The name must contain the template string */ + + if (insta > 0 && sv_before.cname.name >= 0 ) + { + stralloc sainsta = STRALLOC_ZERO ; + stralloc name = STRALLOC_ZERO ; + if (!stralloc_cats(&name,keep.s + sv_before.cname.name)) goto err ; + + if (!instance_splitname(&sainsta,svname,insta,SS_INSTANCE_TEMPLATE)) goto err ; + if (sastr_find(&name,sainsta.s) == -1) { - log_warnusys("read resolve file of: ",svname) ; + log_warn("invalid instantiated service name: ", keep.s + sv_before.cname.name) ; goto err ; } - if (res.disen) + stralloc_free(&sainsta) ; + stralloc_free(&name) ; + goto add ; + err: + stralloc_free(&sainsta) ; + stralloc_free(&name) ; + return 0 ; + } + else + { + sv_before.cname.name = keep.len ; + 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) ; + if (!r) return 0 ; + else if (r == 2) + { + sasv->len = 0 ; + sv_alltype_free(&sv_before) ; + goto deps ; + } + if (force > 1) { - (*exist) = 1 ; - if (!force) { - log_warn("Ignoring: ",svname," service: already enabled") ; - ret = 2 ; - goto freed ; - } + int wstat ; + pid_t pid ; + int color = log_color == &log_color_enable ? 1 : 0 ; + char const *newargv[9 + color + 1] ; + 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++] = 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_OPTSDEPS)) return 0 ; + if (!parse_service_opts_deps(info,parsed_list,tree_list,&sv_before,sv,nbsv,sasv,force,KEY_MAIN_EXTDEPS)) return 0 ; + } freed: - stralloc_free(&sares) ; - ss_resolve_free(&res) ; - return ret ; - err: - stralloc_free(&sares) ; - ss_resolve_free(&res) ; - return 0 ; + return 1 ; } -int parse_add_service(stralloc *parsed_list,sv_alltype *sv_before,char const *service,unsigned int *nbsv,uid_t owner) +/** 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) { - stralloc conf = STRALLOC_ZERO ; - size_t svlen = strlen(service) ; - // keep source of the frontend file - sv_before->src = keep.len ; - if (!stralloc_catb(&keep,service,svlen + 1)) goto err ; - // keep source of the configuration file - if (sv_before->opts[2]) + 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 (!env_resolve_conf(&conf,owner)) goto err ; - sv_before->srconf = keep.len ; - if (!stralloc_catb(&keep,conf.s,conf.len + 1)) goto err ; + if (!hiercopy(mdir.s,sdir.s)) + log_warnusys_return(LOG_EXIT_ZERO,"copy: ",mdir.s," to: ",sdir.s) ; } - // keep service on current list - if (!stralloc_catb(parsed_list,service,svlen + 1)) goto err ; - if (!genalloc_append(sv_alltype,&gasv,sv_before)) goto err ; - (*nbsv)++ ; - stralloc_free(&conf) ; - return 1 ; - err: - stralloc_free(&conf) ; - return 0 ; + else + { + 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(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,".configure",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 ; + 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) + { + 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") ; + } + } + } + /* 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 ; + + 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++ ; + } + + for (pos = 0 ; pos < list.len ; pos += strlen(list.s + pos) + 1) + { + 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++ ; + } + + stralloc_free(&mdir) ; + stralloc_free(&sdir) ; + 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 r ; - uint8_t exist = 0 ; char *dname = 0 ; stralloc newsv = STRALLOC_ZERO ; + if (sv_before->cname.nga) { size_t id = sv_before->cname.idga, nid = sv_before->cname.nga ; for (;nid; id += strlen(deps.s + id) + 1, nid--) { newsv.len = 0 ; - exist = 0 ; if (sv_before->cname.itype != TYPE_BUNDLE) { - log_trace("Service : ",sv, " depends on : ",deps.s+id) ; - }else log_trace("Bundle : ",sv, " contents : ",deps.s+id," as service") ; + log_trace("service: ",sv, " depends on: ",deps.s+id) ; + }else log_trace("bundle: ",sv, " contents: ",deps.s+id," as service") ; dname = deps.s + id ; - r = ss_resolve_src_path(&newsv,dname,info) ; + 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,&exist)) goto err ; + if (!parse_service_before(info,parsed_list,tree_list,newsv.s,nbsv,sasv,force)) goto err ; } } else log_trace(sv,": haven't dependencies") ; @@ -129,17 +374,16 @@ int parse_service_opts_deps(ssexec_t *info,stralloc *parsed_list,stralloc *tree_ { int r ; stralloc newsv = STRALLOC_ZERO ; - ss_resolve_t res = RESOLVE_ZERO ; - + size_t pos = 0 , baselen = strlen(info->base.s) + SS_SYSTEM_LEN ; - uint8_t exist = 0, found = 0, ext = 0 ; + uint8_t found = 0, ext = 0 ; char *optname = 0 ; char btmp[baselen + 1] ; auto_strings(btmp,info->base.s,SS_SYSTEM) ; - unsigned int idref = sv_before->cname.idopts ; + int idref = sv_before->cname.idopts ; unsigned int nref = sv_before->cname.nopts ; - if (mandatory == KEY_EXTDEPS) { + if (mandatory == KEY_MAIN_EXTDEPS) { idref = sv_before->cname.idext ; nref = sv_before->cname.next ; ext = 1 ; @@ -170,23 +414,18 @@ int parse_service_opts_deps(ssexec_t *info,stralloc *parsed_list,stralloc *tree_ size_t treelen = strlen(tree) ; char tmp[baselen + 1 + treelen + SS_SVDIRS_LEN + 1] ; auto_strings(tmp,btmp,"/",tree,SS_SVDIRS) ; - - // already added on a tree - if (ss_resolve_check(tmp,optname)) + + parse_service_check_enabled(tmp,optname,force,&found) ; + if (found) { - if (!ss_resolve_read(&res,tmp,optname)) log_warnusys_return(LOG_EXIT_ZERO,"read resolve file of: ",optname) ; - if (res.disen) - { - found = 1 ; - log_trace(ext ? "external" : "optional"," service dependency: ",optname," is already enabled at tree: ",btmp,"/",tree) ; - break ; - } + log_trace(ext ? "external" : "optional"," service dependency: ",optname," is already enabled at tree: ",btmp,"/",tree) ; + break ; } } if (!found) { // -1 mean system error. If the service doesn't exist it return 0 - r = ss_resolve_src_path(&newsv,optname,info) ; + r = ss_resolve_src_path(&newsv,optname,info->owner) ; if (r == -1) { goto err ; //don't warn here, the ss_revolve_src_path already warn user } @@ -195,7 +434,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,&exist)) + if (!parse_service_before(info,parsed_list,tree_list,newsv.s,nbsv,sasv,force)) goto err ; // we only keep the first found on optsdepends if (!ext) break ; @@ -206,124 +445,158 @@ int parse_service_opts_deps(ssexec_t *info,stralloc *parsed_list,stralloc *tree_ } stralloc_free(&newsv) ; - ss_resolve_free(&res) ; return 1 ; err: stralloc_free(&newsv) ; return 0 ; } -int get_svtype(sv_alltype *sv_before, char const *contents) -{ - stralloc sa = STRALLOC_ZERO ; - - if (!auto_stra(&sa,contents)) goto err ; +/** General helper */ - if (!environ_get_val_of_key(&sa,get_key_by_enum(ENUM_KEY,KEY_TYPE))) goto err ; +int parse_service_check_enabled(char const *tree,char const *svname,uint8_t force,uint8_t *exist) +{ + /** char const tree -> tree.s + SS_SVDIRS */ + size_t namelen = strlen(svname), newlen = strlen(tree) ; + char tmp[newlen + SS_DB_LEN + SS_SRC_LEN + 1 + namelen + 1] ; + auto_strings(tmp,tree,SS_DB,SS_SRC,"/",svname) ; + /** search in db first, the most used */ + if (scan_mode(tmp,S_IFDIR) > 0) + { + (*exist) = 1 ; + if (!force) goto found ; + } + /** svc */ + auto_string_from(tmp,newlen,SS_SVC,"/",svname) ; + if (scan_mode(tmp,S_IFDIR) > 0) + { + (*exist) = 1 ; + if (!force) goto found ; + } - if (!sastr_clean_element(&sa)) goto err ; - sv_before->cname.itype = get_enum_by_key(sa.s) ; + return 1 ; + found: + log_info("Ignoring: ",svname," service: already enabled") ; + return 0 ; +} - if (sv_before->cname.itype == -1) goto err ; - stralloc_free(&sa) ; +int parse_add_service(stralloc *parsed_list,sv_alltype *sv_before,char const *service,unsigned int *nbsv,uid_t owner) +{ + stralloc conf = STRALLOC_ZERO ; + size_t svlen = strlen(service) ; + // keep source of the frontend file + sv_before->src = keep.len ; + if (!stralloc_catb(&keep,service,svlen + 1)) goto err ; + // keep source of the configuration file + if (sv_before->opts[2]) + { + if (!env_resolve_conf(&conf,owner)) goto err ; + sv_before->srconf = keep.len ; + if (!stralloc_catb(&keep,conf.s,conf.len + 1)) goto err ; + } + // keep service on current list + if (!stralloc_catb(parsed_list,service,svlen + 1)) goto err ; + if (!genalloc_append(sv_alltype,&gasv,sv_before)) goto err ; + (*nbsv)++ ; + stralloc_free(&conf) ; return 1 ; err: - stralloc_free(&sa) ; + stralloc_free(&conf) ; return 0 ; } -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 *exist) +/* 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" } ; - int r, insta ; - size_t svlen = strlen(sv), svsrclen, svnamelen ; - char svname[svlen + 1], svsrc[svlen + 1] ; - if (!basename(svname,sv)) return 0 ; - if (!dirname(svsrc,sv)) return 0 ; - svsrclen = strlen(svsrc) ; - svnamelen = strlen(svname) ; - char svpath[svsrclen + svnamelen + 1] ; - if (scan_mode(sv,S_IFDIR) == 1) return 1 ; - - r = parse_service_check_enabled(info,svname,force,exist) ; - if (r == 2) goto freed ; - else if (!r) return 0 ; - - sv_alltype sv_before = SV_ALLTYPE_ZERO ; - sasv->len = 0 ; - - if (!read_svfile(sasv,svname,svsrc)) return 0 ; - - if (!get_svtype(&sv_before,sasv->s)) - log_warn_return (LOG_EXIT_ZERO,"invalid value for key: ",get_key_by_enum(ENUM_KEY,KEY_TYPE)," in service file: ",svsrc,"/",svname) ; + r = mill_element(&kp,str,&MILL_GET_COLON,&pos) ; + if (r == -1) goto err ; - insta = instance_check(svname) ; - if (!insta) - log_warn_return(LOG_EXIT_ZERO, "invalid instance name: ",svname) ; - - if (insta > 0) - { - if (!instance_create(sasv,svname,SS_INSTANCE,insta)) - log_warn_return(LOG_EXIT_ZERO,"create instance service: ",svname) ; - - /** ensure that we have an empty line at the end of the string*/ - if (!stralloc_cats(sasv,"\n")) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ; - if (!stralloc_0(sasv)) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ; - } - - memcpy(svpath,svsrc,svsrclen) ; - memcpy(svpath + svsrclen,svname,svnamelen) ; - svpath[svsrclen + svnamelen] = 0 ; - - if (sastr_cmp(parsed_list,svpath) >= 0) - { - log_trace(sv,": already added") ; - sasv->len = 0 ; - sv_alltype_free(&sv_before) ; - goto freed ; - } + auto_strings(filename,kp.s) ; + + stralloc_free(&kp) ; + return pos ; + err: + stralloc_free(&kp) ; + return -1 ; +} - if (!parser(&sv_before,sasv,svname,sv_before.cname.itype)) return 0 ; +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 ; +} - /** keep the name set by user - * uniquely for instantiated service - * The name must contain the template string */ +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 ; +} - if (insta > 0 && sv_before.cname.name >= 0 ) - { - stralloc sainsta = STRALLOC_ZERO ; - stralloc name = STRALLOC_ZERO ; - if (!stralloc_cats(&name,keep.s + sv_before.cname.name)) goto err ; +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,".configure",mode)) + log_warnusys_return(LOG_EXIT_ZERO,"get content of: ",sdir) ; - if (!instance_splitname(&sainsta,svname,insta,0)) goto err ; - if (sastr_find(&name,sainsta.s) == -1) + 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) { - log_warn("invalid instantiated service name: ", keep.s + sv_before.cname.name) ; - goto err ; + 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(&sainsta) ; - stralloc_free(&name) ; - goto add ; - err: - stralloc_free(&sainsta) ; - stralloc_free(&name) ; - return 0 ; - } - else - { - sv_before.cname.name = keep.len ; - if (!stralloc_catb(&keep,svname,svnamelen + 1)) return 0 ; } - add: - 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_OPTSDEPS)) return 0 ; - if (!parse_service_opts_deps(info,parsed_list,tree_list,&sv_before,sv,nbsv,sasv,force,KEY_EXTDEPS)) return 0 ; - } - freed: + stralloc_free(&tmp) ; + stralloc_free(&list) ; return 1 ; }