diff --git a/src/include/66/parser.h b/src/include/66/parser.h index 4e75163da2d5ca14c51cd0aea5b6ec45171641f5..602d993fae3dc49187f6cc3df9585b594a319873 100644 --- a/src/include/66/parser.h +++ b/src/include/66/parser.h @@ -104,6 +104,7 @@ struct sv_name_s int name ; //pos in keep int description ; //pos in keep int version ; // pos in keep + int intree ; // pos in keep int idga ; //pos in stralloc deps -> @depends unsigned int nga ; //number of deps in stralloc deps -> @depends int idopts ; // pos in stralloc deps -> @optsdepends @@ -223,6 +224,7 @@ struct sv_alltype_s -1 , \ -1 , \ -1 , \ + -1 , \ 0 , \ -1 , \ 0 , \ @@ -295,33 +297,36 @@ extern void keynocheck_free(keynocheck *nocheck) ; extern void section_free(section_t *sec) ; extern void freed_parser(void) ; extern void ssexec_enable_cleanup(void) ; + /** enable phase */ -extern void start_parser(stralloc *list,ssexec_t *info, unsigned int *nbsv,uint8_t FORCE) ; +extern void start_parser(char const *sv, ssexec_t *info, uint8_t disable_module, char const *directory_forced) ; +extern int parse_service(char const *sv, stralloc *parsed_list, ssexec_t *info, uint8_t force, uint8_t conf) ; +int parse_service_alldeps(sv_alltype *alltype, ssexec_t *info, stralloc *parsed_list, uint8_t force, char const *directory_forced) ; +extern int parse_service_deps(sv_alltype *alltype, ssexec_t *info, stralloc *parsed_list, uint8_t force, char const *directory_forced) ; +extern int parse_service_optsdeps(stralloc *rebuild, sv_alltype *alltype, ssexec_t *info, stralloc *parsed_list, uint8_t force, uint8_t field, char const *directory_forced) ; 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,uint8_t conf,uint8_t disable_module,char const *directory_forced) ; -extern int parse_service_all_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,char const *directory_forced) ; -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,char const *directory_forced) ; -extern int parse_service_opts_deps(stralloc *rebuild,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,char const *directory_forced) ; -extern int parse_add_service(stralloc *parsed_list,sv_alltype *sv_before,char const *service,unsigned int *nbsv,uid_t owner,uint8_t conf) ; -extern int get_svtype(sv_alltype *sv_before, char const *contents) ; -extern int get_svtype_from_file(char const *file) ; /** split */ extern int section_get_range(section_t *sasection,stralloc *src) ; extern int key_get_range(genalloc *ga, section_t *sasection) ; extern int check_mandatory(sv_alltype *service, section_t *sasection) ; -extern int nocheck_toservice(keynocheck *nocheck,int svtype, sv_alltype *service) ; +extern int nocheck_toservice(keynocheck *nocheck, int svtype, sv_alltype *service) ; + /** store */ extern int keep_common(sv_alltype *service,keynocheck *nocheck,int svtype) ; extern int keep_runfinish(sv_exec *exec,keynocheck *nocheck) ; extern int keep_logger(sv_execlog *log,keynocheck *nocheck) ; extern int keep_environ(sv_alltype *service,keynocheck *nocheck) ; extern int keep_regex(sv_module *module,keynocheck *nocheck) ; + /** helper */ +extern int get_svtype(sv_alltype *sv_before, char const *contents) ; +extern int get_svtype_from_file(char const *file) ; +extern int get_svintree(sv_alltype *sv_before, char const *contents) ; extern int add_pipe(sv_alltype *sv, stralloc *sa) ; + /** write */ -extern void start_write(stralloc *tostart,unsigned int *nclassic,unsigned int *nlongrun,char const *workdir, genalloc *gasv,ssexec_t *info,uint8_t FORCE,uint8_t CONF) ; +extern void start_write(stralloc *tostart,unsigned int *nclassic,unsigned int *nlongrun,char const *workdir, genalloc *gasv,ssexec_t *info) ; extern int write_services(sv_alltype *sv, char const *workdir, uint8_t force,uint8_t conf) ; extern int write_classic(sv_alltype *sv, char const *dst, uint8_t force, uint8_t conf) ; extern int write_longrun(sv_alltype *sv,char const *dst, uint8_t force, uint8_t conf) ; @@ -335,8 +340,9 @@ extern int write_consprod(sv_alltype *sv,char const *prodname,char const *consna extern int write_dependencies(unsigned int nga,unsigned int idga,char const *dst,char const *filename) ; extern int write_env(char const *name,char const *contents,char const *dst) ; extern int write_oneshot_logger(stralloc *destlog, sv_alltype *sv) ; + /** module */ -extern int parse_module(sv_alltype *sv_before,ssexec_t *info,stralloc *parsed_list,stralloc *tree_list, char const *svname,char const *src_frontend,unsigned int *nbsv, stralloc *sasv,uint8_t force,uint8_t conf) ; +extern int parse_module(sv_alltype *alltype, ssexec_t *info, stralloc *parsed_list, uint8_t force) ; 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/parser_module.c b/src/lib66/parse_module.c similarity index 68% rename from src/lib66/parser_module.c rename to src/lib66/parse_module.c index 3e4516893c602d77f104097a41526ffc367784d4..915eb483ab33d71f889edb6fd46e4326f50870f6 100644 --- a/src/lib66/parser_module.c +++ b/src/lib66/parse_module.c @@ -1,5 +1,5 @@ /* - * parser.c + * parse_module.c * * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org> * @@ -60,11 +60,12 @@ static int check_dir(char const *src,char const *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 (!r) { + if (!dir_create_parent(tsrc,0755)) log_warnusys_return(LOG_EXIT_ZERO,"create directory: ",tsrc) ; } + return 1 ; } @@ -75,58 +76,73 @@ static int get_list(stralloc *list, stralloc *sdir,size_t len, char const *svnam sdir->len = len ; if (!auto_stra(sdir,SS_MODULE_SERVICE)) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ; - if (!sastr_dir_get_recursive(list,sdir->s,"",mode, 0)) + 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,"",mode, 0)) + 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 *sv_before,stralloc *list,stralloc *sv_all_type, stralloc *module_service) +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 = sv_before->cname.idga, nid = sv_before->cname.nga ; - for (;nid; id += strlen(deps.s + id) + 1, nid--) + 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 dependencies addition comparison */ + * 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++) - { + 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 ; + + 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 ; + + 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(sv_all_type,deps_name,strlen(deps_name) + 1)) + return 0 ; } - if (sastr_cmp(module_service,deps_name) == -1) - if (!stralloc_catb(module_service,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 ; } @@ -135,195 +151,205 @@ static int rebuild_list(sv_alltype *sv_before,stralloc *list,stralloc *sv_all_ty * return 2 on already enabled * @svname do not contents the path of the frontend file*/ -int parse_module(sv_alltype *sv_before,ssexec_t *info,stralloc *parsed_list,stralloc *tree_list, char const *svname,char const *src_frontend,unsigned int *nbsv, stralloc *sasv,uint8_t force,uint8_t conf) +int parse_module(sv_alltype *alltype, ssexec_t *info, stralloc *parsed_list, uint8_t force) { log_flow() ; - log_trace("start parse process of module: ",svname) ; - int r, err = 1, insta = -1, svtype = -1, from_ext_insta = 0, already_parsed = 0 ; + 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 moduleinsta = 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(svname) ; + insta = instance_check(sv) ; if (insta <= 0) - log_warn_return(LOG_EXIT_ZERO,"invalid module instance name: ",svname); + log_die(LOG_EXIT_SYS, "invalid module instance name: ",sv); - if (!ss_resolve_module_path(&sdir,&tmp,svname,src_frontend,info->owner)) return 0 ; + minsta = insta ; + + if (!ss_resolve_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 ; + 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,"/") ; + 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 { - 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("skip configuration of the module: ",svname," -- already configured") ; + 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_warnusys_return (LOG_EXIT_ZERO,"remove: ",sdir.s) ; + log_dieusys (LOG_EXIT_SYS, "remove: ", sdir.s) ; - if (!hiercopy(tmp.s,sdir.s)) - log_warnusys_return(LOG_EXIT_ZERO,"copy: ",tmp.s," to: ",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,svname,S_IFREG)) return 0 ; - if (!regex_replace(&list,sv_before,svname)) return 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,svname,S_IFDIR)) return 0 ; - if (!regex_rename(&list,sv_before->type.module.iddir,sv_before->type.module.ndir,sdir.s)) return 0 ; + 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,svname,S_IFREG)) return 0 ; - if (!regex_rename(&list,sv_before->type.module.idfiles,sv_before->type.module.nfiles,sdir.s)) return 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(sv_before,info,permanent_sdir,svname,conf)) return 0 ; + 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_warnsys_return(LOG_EXIT_ZERO,"stralloc") ; + if (!auto_stra(&tmp, permanent_sdir, SS_MODULE_SERVICE + 1)) + log_die_nomem("stralloc") ; /** get all services */ - if (!sastr_dir_get_recursive(&list,tmp.s,"",S_IFREG, 0)) - log_warnusys_return(LOG_EXIT_ZERO,"get file(s) of module: ",svname) ; + 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--) { - /** add addon service */ - if (sv_before->type.module.naddservices > 0) - { - id = sv_before->type.module.idaddservices, nid = sv_before->type.module.naddservices ; - for (;nid; id += strlen(keep.s + id) + 1, nid--) - { char *name = keep.s + id ; - if (ss_resolve_src_path(&list,name,info->owner,0) < 1) - log_warnu_return(LOG_EXIT_ZERO,"resolve source path of: ",name) ; + if (ss_resolve_src_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 deps field - * incoporate the module service deps inside the list to parse + /** 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(sv_before,&list,&tmp,&sdir)) - log_warnu(LOG_EXIT_ZERO,"rebuild dependencies list of; ",svname) ; + 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 *sv = list.s + pos ; - size_t len = strlen(sv) ; + 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,sv) >= 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 ; + for (; idx < genalloc_len(sv_alltype, &gasv) ; idx++) { + + char *name = keep.s + genalloc_s(sv_alltype, &gasv)[idx].src ; - if (!strcmp(name,sv)) - { - sv = name ; + if (!strcmp(name, svname)) { + + svname = name ; break ; } } already_parsed = 1 ; } - if (!ob_basename(bname,sv)) - log_warnu_return(LOG_EXIT_ZERO,"find basename of: ",sv) ; + 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(svname,bname)) - log_warn_return(LOG_EXIT_ZERO,"cyclic call detected -- ",svname," call ",bname) ; + if (!strcmp(sv, bname)) + log_die(LOG_EXIT_SYS,"cyclic call detected -- ", sv, " call ", bname) ; insta = instance_check(bname) ; - if (!insta) log_warn_return(LOG_EXIT_ZERO,"invalid instance name: ",sv) ; - if (insta > 0) - { + 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 ss_resolve_src_path() */ pbname = bname ; - if (!already_parsed) - { + if (!already_parsed) { + int found = 0 ; 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,"/") ; + auto_strings(tmp, permanent_sdir, SS_MODULE_SERVICE_INSTANCE + 1, "/") ; + + r = ss_resolve_src(&addonsv, pbname, tmp, &found) ; - r = ss_resolve_src(&addonsv,pbname,tmp,&found) ; + if (r == -1) log_dieusys(LOG_EXIT_SYS,"parse source directory: ", tmp) ; + if (!r) { - if (r == -1) log_warnusys_return(LOG_EXIT_ZERO,"parse source directory: ",tmp) ; - if (!r) - { - if (ss_resolve_src_path(&addonsv,pbname,info->owner,0) < 1) - log_warnu_return(LOG_EXIT_ZERO,"resolve source path of: ",pbname) ; + if (ss_resolve_src_path(&addonsv, pbname, info->owner, 0) < 1) + log_dieu(LOG_EXIT_SYS,"resolve source path of: ", pbname) ; } - sv = addonsv.s ; + svname = addonsv.s ; } from_ext_insta++ ; - len = strlen(sv) ; + len = strlen(svname) ; } if (!already_parsed) - if (!parse_service_before(info,parsed_list,tree_list,sv,nbsv,sasv,force,conf,0,permanent_sdir)) - log_warnu_return(LOG_EXIT_ZERO,"parse: ",sv," from module: ",svname) ; + start_parser(svname, info, 0, permanent_sdir) ; char ext_insta[len + 1] ; if (from_ext_insta) { - size_t len = strlen(sv) ; - r = get_rlen_until(sv,'@',len) + 1 ; + + size_t len = strlen(svname) ; + r = get_rlen_until(svname, '@', len) + 1 ; size_t newlen = len - (len - r) ; - auto_strings(ext_insta,sv) ; + auto_strings(ext_insta, svname) ; ext_insta[newlen] = 0 ; - sv = ext_insta ; + svname = ext_insta ; } /** we want the configuration file for each service inside @@ -331,32 +357,34 @@ int parse_module(sv_alltype *sv_before,ssexec_t *info,stralloc *parsed_list,stra * 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 + sv_before->cname.version ; + char *version = keep.s + alltype->cname.version ; + { stralloc tmpenv = STRALLOC_ZERO ; - /** 512 is the maximum of services set by default - * that can be supervised by s6-svscan. It should be large - * enough for the majority of the cases */ - size_t pos, spos, id, nid, idmodule[512] = { 0 } ; + /** 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,svname,info->owner)) - log_warnu_return(LOG_EXIT_ZERO,"get path of the configuration file") ; + if (!env_resolve_conf(&tmpenv, sv, info->owner)) + log_dieu(LOG_EXIT_SYS,"get path of the configuration file") ; - if (!auto_stra(&tmpenv,"/")) log_warn_return(LOG_EXIT_ZERO,"stralloc") ; + 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) - { + 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--) - { + for (;nid; id += strlen(deps.s + id) + 1, nid--) { + char *name = deps.s + id ; for (spos = 0 ; spos < genalloc_len(sv_alltype,&gasv);spos++) @@ -366,63 +394,79 @@ int parse_module(sv_alltype *sv_before,ssexec_t *info,stralloc *parsed_list,stra } } - for (pos = 0 ; pos < genalloc_len(sv_alltype,&gasv);pos++) - { + 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)) - { + 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_warn_return(LOG_EXIT_ZERO,"stralloc") ; + log_die_nomem("stralloc") ; break ; } } stralloc_free(&tmpenv) ; } - svtype = get_svtype_from_file(sv) ; - if (svtype == -1) log_warnu_return(LOG_EXIT_ZERO,"get svtype of: ",sv) ; + 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_warnsys_return(LOG_EXIT_ZERO,"stralloc") ; + log_die_nomem("stralloc") ; if (sastr_cmp(&tmp,pbname) == -1) if (svtype != TYPE_CLASSIC) if (!stralloc_catb(&tmp,pbname,strlen(pbname) + 1)) - log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ; + log_die_nomem("stralloc") ; } - sv_before->cname.idga = deps.len ; - sv_before->cname.nga = 0 ; - for (pos = 0 ;pos < tmp.len ; pos += strlen(tmp.s + pos) + 1) - { - stralloc_catb(&deps,tmp.s + pos,strlen(tmp.s + pos) + 1) ; - sv_before->cname.nga++ ; + /** 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++ ; } - sv_before->cname.idcontents = deps.len ; - for (pos = 0 ;pos < sdir.len ; pos += strlen(sdir.s + pos) + 1) - { - stralloc_catb(&deps,sdir.s + pos,strlen(sdir.s + pos) + 1) ; - sv_before->cname.ncontents++ ; + 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_warnsys_return(LOG_EXIT_ZERO,"stralloc") ; + log_die_nomem("stralloc") ; + if (rm_rf(tmp.s) < 0) - log_warnusys_return(LOG_EXIT_ZERO,"remove: ",tmp.s) ; + log_dieusys(LOG_EXIT_SYS,"remove: ",tmp.s) ; stralloc_free(&sdir) ; stralloc_free(&list) ; stralloc_free(&tmp) ; - stralloc_free(&moduleinsta) ; stralloc_free(&addonsv) ; return err ; @@ -487,7 +531,7 @@ int regex_get_regex(char *regex, char const *str) return 1 ; } -int regex_replace(stralloc *list,sv_alltype *sv_before,char const *svname) +int regex_replace(stralloc *list,sv_alltype *alltype,char const *svname) { log_flow() ; @@ -511,7 +555,7 @@ int regex_replace(stralloc *list,sv_alltype *sv_before,char const *svname) if (!r) log_warnusys_return(LOG_EXIT_ZERO,"read file: ",str) ; if (r == -1) continue ; - pos = sv_before->type.module.start_infiles, inlen = sv_before->type.module.end_infiles ; + 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 ; @@ -603,13 +647,13 @@ int regex_rename(stralloc *list, int id, unsigned int nid, char const *sdir) return 1 ; } -int regex_configure(sv_alltype *sv_before,ssexec_t *info, char const *module_dir,char const *module_name,uint8_t conf) +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 = sv_before->type.module.configure > 0 ? 1 : 0 ; + size_t clen = alltype->type.module.configure > 0 ? 1 : 0 ; size_t module_dirlen = strlen(module_dir), n ; stralloc env = STRALLOC_ZERO ; @@ -658,13 +702,13 @@ int regex_configure(sv_alltype *sv_before,ssexec_t *info, char const *module_dir log_warnu_return(LOG_EXIT_ZERO,"append environment variables") ; } /** environment is not mandatory */ - if (sv_before->opts[2] > 0) + 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,sv_before,conf)) + if (!env_prepare_for_write(&name,&dst,&oenv,alltype,conf)) return 0 ; if (!write_env(name.s,oenv.s,dst.s)) @@ -697,8 +741,8 @@ int regex_configure(sv_alltype *sv_before,ssexec_t *info, char const *module_dir m = 0 ; newargv[m++] = config_script ; - if (sv_before->type.module.configure > 0) - newargv[m++] = keep.s + sv_before->type.module.configure ; + if (alltype->type.module.configure > 0) + newargv[m++] = keep.s + alltype->type.module.configure ; newargv[m++] = 0 ; diff --git a/src/lib66/parse_service.c b/src/lib66/parse_service.c new file mode 100644 index 0000000000000000000000000000000000000000..6c49e57b76daa01e072517f31c5e93c59a18192f --- /dev/null +++ b/src/lib66/parse_service.c @@ -0,0 +1,415 @@ +/* + * parse_service.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 <stdint.h> +#include <string.h> + +#include <oblibs/log.h> +#include <oblibs/sastr.h> +#include <oblibs/string.h> +#include <oblibs/types.h> + +#include <skalibs/stralloc.h> +#include <skalibs/genalloc.h> + +#include <66/utils.h> +#include <66/constants.h> +#include <66/ssexec.h> +#include <66/service.h> +#include <66/tree.h> + +static void parse_service_instance(stralloc *frontend, char const *svsrc, char const *sv, int insta) +{ + log_flow() ; + + stralloc sa = STRALLOC_ZERO ; + + if (!instance_splitname(&sa, sv, insta, SS_INSTANCE_TEMPLATE)) + log_die(LOG_EXIT_SYS, "split instance service: ", sv) ; + + log_trace("read frontend service of: ", svsrc, sa.s) ; + + if (read_svfile(frontend, sa.s, svsrc) <= 0) + log_dieusys(LOG_EXIT_SYS, "read frontend service of: ", svsrc, sa.s) ; + + stralloc_free(&sa) ; + + if (!instance_create(frontend, sv, SS_INSTANCE_REGEX, insta)) + log_die(LOG_EXIT_SYS, "create instance service: ", sv) ; + + /** ensure that we have an empty line at the end of the string*/ + if (!auto_stra(frontend, "\n")) + log_die_nomem("stralloc") ; + +} + +static int parse_add_service(stralloc *parsed_list, sv_alltype *alltype, char const *service, uint8_t conf) +{ + log_flow() ; + + log_trace("add service: ", service) ; + + // keep overwrite_conf + alltype->overwrite_conf = conf ; + + // keep source of the frontend file + alltype->src = keep.len ; + + if (!sastr_add_string(&keep, service)) + return 0 ; + + // keep service on current list + if (!sastr_add_string(parsed_list, service)) + return 0 ; + + if (!genalloc_append(sv_alltype, &gasv, alltype)) + return 0 ; + + return 1 ; +} + +static void set_info(ssexec_t *info) +{ + log_flow() ; + + info->tree.len = 0 ; + int r = ssexec_set_treeinfo(info) ; + if (r == -4) log_die(LOG_EXIT_USER,"You're not allowed to use the tree: ",info->tree.s) ; + if (r == -3) log_dieu(LOG_EXIT_USER,"find the current tree. You must use the -t options") ; + if (r == -2) log_dieu(LOG_EXIT_USER,"set the tree name") ; + if (r == -1) log_dieu(LOG_EXIT_USER,"parse seed file") ; + if (!r) log_dieusys(LOG_EXIT_SYS,"find tree: ", info->treename.s) ; + +} +#include <stdio.h> +/* @sv -> name of the service to parse with + * the path of the frontend file source + * @Return 0 on fail + * @Return 1 on success + * @Return 2 -> already parsed */ +int parse_service(char const *sv, stralloc *parsed_list, ssexec_t *info, uint8_t force, uint8_t conf) +{ + + log_flow() ; + + if (sastr_cmp(parsed_list, sv) >= 0) { + + log_warn("ignoring: ", sv, " service -- already parsed") ; + return 2 ; + } + + log_trace("parse service: ", sv) ; + + int insta, r ; + size_t svlen = strlen(sv) ; + char svname[svlen + 1], svsrc[svlen + 1] ; + + sv_alltype alltype = SV_ALLTYPE_ZERO ; + stralloc frontend = STRALLOC_ZERO ; + stralloc satree = STRALLOC_ZERO ; + + if (!ob_basename(svname, sv)) + log_dieu(LOG_EXIT_SYS, "get basename of: ", sv) ; + + if (!ob_dirname(svsrc, sv)) + log_dieu(LOG_EXIT_SYS, "get dirname of: ", sv) ; + + insta = instance_check(svname) ; + if (!insta) { + + log_die(LOG_EXIT_SYS, "invalid instance name: ", svname) ; + + } else if (insta > 0) { + + parse_service_instance(&frontend, svsrc, svname, insta) ; + + } else { + + log_trace("read frontend service of: ", sv) ; + + if (read_svfile(&frontend, svname, svsrc) <= 0) + log_dieusys(LOG_EXIT_SYS, "read frontend service of: ", sv) ; + } + + r = service_isenabledat(&satree, svname) ; + if (r < -1) + log_dieu(LOG_EXIT_SYS, "check already enabled services") ; + + if (r > 0) { + + if (force) { + + /* -t option was used */ + if (!info->skip_opt_tree) { + + if (strcmp(info->treename.s, satree.s)) + log_die(LOG_EXIT_SYS,"you can not force to enable again a service on different tree -- current: ", satree.s, " asked: ", info->treename.s, ". Try first to disable it") ; + + } else { + + if (!auto_stra(&info->treename, satree.s)) + log_die_nomem("stralloc") ; + } + + goto set ; + + } else { + + log_info("ignoring service: ", sv, " -- already enabled at tree: ", satree.s) ; + + /** we don't care about the use of the -t option. The define of the + * info->tree and info->treename is just made to avoid segmentation fault + * at the rest of the process. The service is not parsed or enable again anyway. */ + + info->treename.len = 0 ; + if (!auto_stra(&info->treename, satree.s)) + log_die_nomem("stralloc") ; + + set_info(info) ; + + sv_alltype_free(&alltype) ; + stralloc_free(&frontend) ; + stralloc_free(&satree) ; + return 2 ; + } + } + + if (info->skip_opt_tree) { + + /** first try to find the @intree key at the frontend file*/ + if (!get_svintree(&alltype,frontend.s)) + log_die(LOG_EXIT_USER, "invalid value for key: ",get_key_by_enum(ENUM_KEY_SECTION_MAIN,KEY_MAIN_INTREE)," in service file: ", sv) ; + + if (alltype.cname.intree >= 0) { + + info->treename.len = 0 ; + if (!auto_stra(&info->treename, keep.s + alltype.cname.intree)) + log_die_nomem("stralloc") ; + + } + } + + set: + + set_info(info) ; + + if (!get_svtype(&alltype, frontend.s)) + log_die(LOG_EXIT_USER, "invalid value for key: ", get_key_by_enum(ENUM_KEY_SECTION_MAIN, KEY_MAIN_TYPE), " at frontend service: ", sv) ; + + /** contents of directory should be listed by ss_resolve_src_path + * except for module type */ + if (scan_mode(sv,S_IFDIR) == 1 && alltype.cname.itype != TYPE_MODULE) + goto freed ; + + alltype.cname.name = keep.len ; + if (!sastr_add_string(&keep, svname)) + log_die_nomem("stralloc") ; + + if (!parser(&alltype, &frontend, svname, alltype.cname.itype)) + log_dieu(LOG_EXIT_SYS, "parse service: ", sv) ; + + if (!parse_add_service(parsed_list, &alltype, sv, conf)) + log_dieu(LOG_EXIT_SYS, "add service: ", sv) ; + + freed: + stralloc_free(&frontend) ; + stralloc_free(&satree) ; + + return 1 ; +} + +int parse_service_deps(sv_alltype *alltype, ssexec_t *info, stralloc *parsed_list, uint8_t force, char const *directory_forced) +{ + + log_flow() ; + + int r, e = 0 ; + stralloc sa = STRALLOC_ZERO ; + + if (alltype->cname.nga) { + + size_t id = alltype->cname.idga, nid = alltype->cname.nga ; + for (; nid ; id += strlen(deps.s + id) + 1, nid--) { + + sa.len = 0 ; + + if (alltype->cname.itype != TYPE_BUNDLE) { + + log_trace("service: ", keep.s + alltype->cname.name, " depends on: ", deps.s + id) ; + + } else log_trace("bundle: ", keep.s + alltype->cname.name, " contents: ", deps.s + id," as service") ; + + r = ss_resolve_src_path(&sa, deps.s + id, info->owner, directory_forced) ; + if (r < 1) goto err ;//don't warn here, the ss_revolve_src_path do it + + if (!parse_service(sa.s, parsed_list, info, force, alltype->overwrite_conf)) + goto err ; + } + + } else log_trace(keep.s + alltype->cname.name,": haven't dependencies") ; + + e = 1 ; + + err: + stralloc_free(&sa) ; + return e ; +} + +int parse_service_optsdeps(stralloc *rebuild, sv_alltype *alltype, ssexec_t *info, stralloc *parsed_list, uint8_t force, uint8_t field, char const *directory_forced) +{ + log_flow() ; + + int r, e = 0 ; + stralloc sa = STRALLOC_ZERO ; + + size_t id, nid ; + uint8_t ext = field == KEY_MAIN_EXTDEPS ? 1 : 0 ; + + int idref = alltype->cname.idopts ; + unsigned int nref = alltype->cname.nopts ; + if (ext) { + idref = alltype->cname.idext ; + nref = alltype->cname.next ; + } + + if (nref) { + + id = (size_t)idref, nid = (size_t)nref ; + for (; nid ; id += strlen(deps.s + id) + 1, nid--) { + + sa.len = 0 ; + // 0 -> not found, 1 -> found, -1 -> system error + r = service_isenabled(deps.s + id) ; + if (r == -1) + log_dieu(LOG_EXIT_SYS, "check already enabled services") ; + + if (r > 0) { + if (!ext) + break ; + else + continue ; + } + + r = ss_resolve_src_path(&sa, deps.s + id, info->owner, directory_forced) ; + if (r == -1) + goto err ; + + if (!r) { + + log_trace("unable to find", ext ? " external " : " optional ", "dependency: ", deps.s + id, " for service: ", keep.s + alltype->cname.name) ; + + // external deps must exist + if (ext) + goto err ; + + continue ; + } + + if (!parse_service(sa.s, parsed_list, info, force, alltype->overwrite_conf)) + goto err ; + + if (!sastr_add_string(rebuild, deps.s + id)) + log_die_nomem("stralloc") ; + + // we only keep the first optsdepends found + if (!ext) break ; + } + + } else log_trace(keep.s + alltype->cname.name,": haven't", ext ? " external " : " optional ", "dependencies") ; + + e = 1 ; + + err: + stralloc_free(&sa) ; + return e ; +} + +int parse_service_alldeps(sv_alltype *alltype, ssexec_t *info, stralloc *parsed_list, uint8_t force, char const *directory_forced) +{ + log_flow() ; + + int e = 0 ; + size_t id, nid, pos ; + char *name = keep.s + alltype->cname.name ; + stralloc sa = STRALLOC_ZERO ; + stralloc rebuild = STRALLOC_ZERO ; + + if (!parse_service_deps(alltype, info, parsed_list, force, directory_forced)) { + log_warnu("parse dependencies of: ", name) ; + goto err ; + } + + if (!parse_service_optsdeps(&rebuild, alltype, info, parsed_list, force, KEY_MAIN_EXTDEPS, directory_forced)) { + log_warnu("parse external dependencies of: ", name) ; + goto err ; + } + + if (!parse_service_optsdeps(&rebuild, alltype, info, parsed_list, force, KEY_MAIN_OPTSDEPS, directory_forced)) { + log_warnu("parse optional dependencies of: ", name) ; + goto err ; + } + + // rebuild the dependencies list of the service to add the new dependencies. + if (rebuild.len) { + + pos = 0 ; + sa.len = 0 ; + id = alltype->cname.idga ; + nid = alltype->cname.nga ; + + { + for (; nid ; id += strlen(deps.s + id) + 1, nid--) { + if (!sastr_add_string(&sa, deps.s + id)) { + log_warn("stralloc") ; + goto err ; + } + } + + + FOREACH_SASTR(&rebuild, pos) { + if (!sastr_add_string(&sa, rebuild.s + pos)) { + log_warn("stralloc") ; + goto err ; + } + } + + } + + alltype->cname.idga = deps.len ; + alltype->cname.nga = 0 ; + + pos = 0 ; + FOREACH_SASTR(&sa, pos) { + + log_info("rebuil list", sa.s + pos) ; + + if (!sastr_add_string(&deps,sa.s + pos)) { + log_warn("stralloc") ; + goto err ; + } + + alltype->cname.nga++ ; + } + } + + e = 1 ; + + err: + stralloc_free(&rebuild) ; + stralloc_free(&sa) ; + + return e ; +} diff --git a/src/lib66/parser_enabled.c b/src/lib66/parser_enabled.c deleted file mode 100644 index c7a3f3d034f50dc276739dd5be868ac5e124cbb1..0000000000000000000000000000000000000000 --- a/src/lib66/parser_enabled.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * parser.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 <oblibs/string.h> -#include <oblibs/types.h> -#include <oblibs/log.h> -#include <oblibs/sastr.h> -#include <oblibs/files.h> - -#include <skalibs/stralloc.h> -#include <skalibs/djbunix.h>//environ - -#include <66/resolve.h> -#include <66/utils.h> -#include <66/constants.h> -#include <66/environ.h> - -/* @sv -> name of the service to parse with - * the path of the frontend file source - * @Return 0 on fail - * @Return 1 on success - * @Return 2 -> already parsed */ -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,uint8_t disable_module,char const *directory_forced) -{ - log_flow() ; - - log_trace("start parse process of service: ",sv) ; - - if (sastr_cmp(parsed_list,sv) >= 0) - { - log_warn("ignoring: ",sv," service: already parsed") ; - sasv->len = 0 ; - return 2 ; - } - - int insta ; - uint8_t exist = 0 ; - size_t svlen = strlen(sv), 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) ; - - svnamelen = strlen(svname) ; - 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) { sasv->len = 0 ; return 2 ; } - - 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) - { - stralloc tmp = STRALLOC_ZERO ; - instance_splitname(&tmp,svname,insta,SS_INSTANCE_TEMPLATE) ; - log_trace("read service file of: ",svsrc,tmp.s) ; - if (read_svfile(sasv,tmp.s,svsrc) <= 0) return 0 ; - stralloc_free(&tmp) ; - } - else { - log_trace("read service file of: ",svsrc,svname) ; - if (read_svfile(sasv,svname,svsrc) <= 0) 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) ; - - - sv_before.cname.name = keep.len ; - if (!stralloc_catb(&keep,svname,svnamelen + 1)) return 0 ; - - /** contents of directory should be listed by ss_resolve_src_path - * execpt for module type */ - if (scan_mode(sv,S_IFDIR) == 1 && sv_before.cname.itype != TYPE_MODULE) return 1 ; - - if (insta > 0) - { - if (!instance_create(sasv,svname,SS_INSTANCE_REGEX,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") ; - } - - if (!parser(&sv_before,sasv,svname,sv_before.cname.itype)) return 0 ; - - if ((sv_before.cname.itype > TYPE_CLASSIC && force > 1) || !exist) - if (!parse_service_all_deps(info,parsed_list,tree_list,&sv_before,sv,nbsv,sasv,force,conf,directory_forced)) return 0 ; - - if (sv_before.cname.itype == TYPE_MODULE) - { - r = parse_module(&sv_before,info,parsed_list,tree_list,svname,svsrc,nbsv,sasv,force,conf) ; - if (!r) return 0 ; - else if (r == 2) - { - sasv->len = 0 ; - goto add ; - } - - if (force > 1 && exist && disable_module) - { - char const *newargv[4] ; - unsigned int m = 0 ; - - newargv[m++] = "fake_name" ; - newargv[m++] = svname ; - newargv[m++] = 0 ; - if (ssexec_disable(m,newargv,(const char *const *)environ,info)) - log_warnu_return(LOG_EXIT_ZERO,"disable module: ",svname) ; - } - } - add: - if (!parse_add_service(parsed_list,&sv_before,sv,nbsv,info->owner,conf)) return 0 ; - - return 1 ; -} - -int parse_service_all_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,char const *directory_forced) -{ - log_flow() ; - - stralloc rebuild = STRALLOC_ZERO ; - - if (!parse_service_deps(info,parsed_list,tree_list,sv_before,sv,nbsv,sasv,force,conf,directory_forced)) return 0 ; - if (!parse_service_opts_deps(&rebuild,info,parsed_list,tree_list,sv_before,sv,nbsv,sasv,force,conf,KEY_MAIN_EXTDEPS,0)) return 0 ; - if (!parse_service_opts_deps(&rebuild,info,parsed_list,tree_list,sv_before,sv,nbsv,sasv,force,conf,KEY_MAIN_OPTSDEPS,0)) return 0 ; - - if (rebuild.len) - { - size_t pos = 0 ; - stralloc old = STRALLOC_ZERO ; - - //rebuild the dependencies list of the service - int id = sv_before->cname.idga ; - unsigned int nid = sv_before->cname.nga ; - - for (;nid; id += strlen(deps.s + id) + 1, nid--) - { - if (!stralloc_catb(&old,deps.s + id,strlen(deps.s + id) + 1)) - log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ; - } - for (pos = 0 ; pos < rebuild.len ; pos += strlen(rebuild.s + pos) + 1) - { - if (!stralloc_catb(&old,rebuild.s + pos,strlen(rebuild.s + pos) + 1)) - log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ; - } - - sv_before->cname.idga = deps.len ; - sv_before->cname.nga = 0 ; - - for (pos = 0 ; pos < old.len ; pos += strlen(old.s + pos) + 1) - { - if (!stralloc_catb(&deps,old.s + pos,strlen(old.s + pos) + 1)) - log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ; - sv_before->cname.nga++ ; - } - stralloc_free(&old) ; - } - - stralloc_free(&rebuild) ; - - 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,uint8_t conf,char const *directory_forced) -{ - log_flow() ; - - int r ; - 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 ; - 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") ; - dname = deps.s + id ; - r = ss_resolve_src_path(&newsv,dname,info->owner,directory_forced) ; - 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,conf,0,directory_forced)) goto err ; - } - } - else log_trace(sv,": haven't dependencies") ; - stralloc_free(&newsv) ; - return 1 ; - err: - stralloc_free(&newsv) ; - return 0 ; -} - -int parse_service_opts_deps(stralloc *rebuild,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,char const *directory_forced) -{ - log_flow() ; - - int r ; - stralloc newsv = STRALLOC_ZERO ; - - size_t pos = 0 , baselen = strlen(info->base.s) + SS_SYSTEM_LEN ; - uint8_t found = 0, ext = mandatory == KEY_MAIN_EXTDEPS ? 1 : 0 ; - char *optname = 0 ; - char btmp[baselen + 1] ; - auto_strings(btmp,info->base.s,SS_SYSTEM) ; - - int idref = sv_before->cname.idopts ; - unsigned int nref = sv_before->cname.nopts ; - if (ext) { - idref = sv_before->cname.idext ; - nref = sv_before->cname.next ; - } - // only pass here for the first time - if (!tree_list->len) - { - if (!sastr_dir_get(tree_list, btmp,SS_BACKUP + 1, S_IFDIR)) log_warnusys_return(LOG_EXIT_ZERO,"get list of tree at: ",btmp) ; - } - - if (nref) - { - // may have no tree yet - if (tree_list->len) - { - size_t id = idref, nid = nref ; - for (;nid; id += strlen(deps.s + id) + 1, nid--) - { - - newsv.len = 0 ; - optname = deps.s + id ; - - for(pos = 0 ; pos < tree_list->len ; pos += strlen(tree_list->s + pos) +1 ) - { - found = 0 ; - char *tree = tree_list->s + pos ; - if (obstr_equal(tree,info->treename.s)) continue ; - size_t treelen = strlen(tree) ; - char tmp[baselen + 1 + treelen + SS_SVDIRS_LEN + 1] ; - auto_strings(tmp,btmp,"/",tree,SS_SVDIRS) ; - - parse_service_check_enabled(tmp,optname,force,&found) ; - if (found) - { - 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->owner,directory_forced) ; - if (r == -1) { - goto err ; //don't warn here, the ss_revolve_src_path already warn user - } - else if (!r) { - if (ext) goto err ; - } - // be paranoid with the else if - else if (r == 1) { - if (!parse_service_before(info,parsed_list,tree_list,newsv.s,nbsv,sasv,force,conf,0,directory_forced)) - goto err ; - - // add the new deps - if (!stralloc_catb(rebuild,optname,strlen(optname) + 1)) - log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ; - - // we only keep the first found on optsdepends - if (!ext) break ; - } - } - } - } - } - - stralloc_free(&newsv) ; - return 1 ; - err: - stralloc_free(&newsv) ; - return 0 ; -} - -/** General helper */ - -int parse_service_check_enabled(char const *tree,char const *svname,uint8_t force,uint8_t *exist) -{ - log_flow() ; - - /** 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 ; - } - - return 1 ; - found: - log_info("ignoring: ",svname," service: already enabled") ; - return 0 ; -} - -int parse_add_service(stralloc *parsed_list,sv_alltype *sv_before,char const *service,unsigned int *nbsv,uid_t owner,uint8_t conf) -{ - log_flow() ; - - log_trace("add service: ",service) ; - stralloc saconf = STRALLOC_ZERO ; - size_t svlen = strlen(service) ; - // keep overwrite_conf - sv_before->overwrite_conf = conf ; - // keep source of the frontend file - sv_before->src = keep.len ; - if (!stralloc_catb(&keep,service,svlen + 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(&saconf) ; - return 1 ; - err: - stralloc_free(&saconf) ; - return 0 ; -} diff --git a/src/lib66/ssexec_enable.c b/src/lib66/ssexec_enable.c index 650be9871d5707f18ee0aff5e690f32624c1826a..683f7d551223c061e65980a8d03b84793755075f 100644 --- a/src/lib66/ssexec_enable.c +++ b/src/lib66/ssexec_enable.c @@ -16,6 +16,8 @@ #include <stdint.h> #include <errno.h> +#include <stdio.h> + #include <oblibs/obgetopt.h> #include <oblibs/log.h> #include <oblibs/string.h> @@ -35,8 +37,11 @@ #include <66/resolve.h> #include <66/ssexec.h> #include <66/environ.h> +#include <66/service.h> static stralloc workdir = STRALLOC_ZERO ; +stralloc PARSED_LIST = STRALLOC_ZERO ; + /** force == 1, only rewrite the service * force == 2, rewrite the service and it dependencies*/ static uint8_t FORCE = 0 ; @@ -60,35 +65,76 @@ static void check_identifier(char const *name) int logname = get_rstrlen_until(name,SS_LOG_SUFFIX) ; if (logname > 0) log_die(LOG_EXIT_USER,"service: ",name,": ends with reserved suffix -log") ; - if (!memcmp(name,SS_MASTER+1,6)) log_die(LOG_EXIT_USER,"service: ",name,": starts with reserved prefix Master") ; + if (!memcmp(name, SS_MASTER + 1, 6)) log_die(LOG_EXIT_USER,"service: ",name,": starts with reserved prefix Master") ; if (!strcmp(name,SS_SERVICE)) log_die(LOG_EXIT_USER,"service as service name is a reserved name") ; if (!strcmp(name,"service@")) log_die(LOG_EXIT_USER,"service@ as service name is a reserved name") ; } -void start_parser(stralloc *list,ssexec_t *info, unsigned int *nbsv,uint8_t force) +void start_parser(char const *sv, ssexec_t *info, uint8_t disable_module, char const *directory_forced) { log_flow() ; - size_t i = 0 ; + size_t pos = 0 ; - stralloc sasv = STRALLOC_ZERO ; stralloc parsed_list = STRALLOC_ZERO ; - stralloc tree_list = STRALLOC_ZERO ; - uint8_t disable_module = 1 ; - FOREACH_SASTR(list,i) { + char *name = 0 ; + int r ; + + r = parse_service(sv, &parsed_list, info, FORCE, CONF) ; + if (!r) + log_dieu(LOG_EXIT_SYS, "parse service file: ",name,": or its dependencies") ; + + // already enabled + if (r == 2) + goto freed ; + + // parse deps + pos = 0 ; + for (; pos < genalloc_len(sv_alltype, &gasv) ; pos ++) { + + sv_alltype_ref sv = &genalloc_s(sv_alltype,&gasv)[pos] ; + + name = keep.s + sv->cname.name ; + + int exist = service_isenabled(name) ; + + if (sv->cname.itype != TYPE_CLASSIC) { - char *name = list->s + i ; + if (FORCE > 1 || !exist) { - if (!parse_service_before(info,&parsed_list,&tree_list,name,nbsv,&sasv,force,CONF,disable_module,0)) - log_dieu(LOG_EXIT_SYS,"parse service file: ",name,": or its dependencies") ; + if (!parse_service_alldeps(sv, info, &parsed_list, FORCE, directory_forced)) + log_dieu(LOG_EXIT_SYS, "parse dependencies of: ", name) ; + + if (sv->cname.itype == TYPE_MODULE) { + + r = parse_module(sv, info, &parsed_list, FORCE) ; + if (!r) + log_dieu(LOG_EXIT_SYS, "parse module: ", name) ; + + else if (r == 2) + continue ; + + if ((FORCE > 1) && (exist > 0) && disable_module) { + + char const *newargv[4] ; + unsigned int m = 0 ; + + newargv[m++] = "fake_name" ; + newargv[m++] = name ; + newargv[m++] = 0 ; + if (ssexec_disable(m, newargv, (char const *const *)environ, info)) + log_dieu(LOG_EXIT_SYS, "disable module: ", name) ; + } + } + } + } } - stralloc_free(&sasv) ; + freed: stralloc_free(&parsed_list) ; - stralloc_free(&tree_list) ; } -void start_write(stralloc *tostart,unsigned int *nclassic,unsigned int *nlongrun,char const *workdir, genalloc *gasv,ssexec_t *info,uint8_t FORCE,uint8_t CONF) +void start_write(stralloc *tostart,unsigned int *nclassic,unsigned int *nlongrun,char const *workdir, genalloc *gasv,ssexec_t *info) { log_flow() ; @@ -300,14 +346,24 @@ int ssexec_enable(int argc, char const *const *argv,char const *const *envp,ssex directory_forced = dname ; } else sv = *argv ; - if (ss_resolve_src_path(&sasrc,sv,info->owner,!directory_forced ? 0 : directory_forced) < 1) log_dieu(LOG_EXIT_SYS,"resolve source path of: ",*argv) ; + if (ss_resolve_src_path(&sasrc,sv,info->owner,!directory_forced ? 0 : directory_forced) < 1) + log_dieu(LOG_EXIT_SYS,"resolve source path of: ",*argv) ; } - start_parser(&sasrc,info,&nbsv,FORCE) ; - + FOREACH_SASTR(&sasrc, pos) + start_parser(sasrc.s + pos, info, 1, 0) ; + + /** + * + * + * ATTENTION si -t ne pas passait alors info->tree et info->treename.s + * n'est pas definie + * + * + * */ if (!tree_copy(&workdir,info->tree.s,info->treename.s)) log_dieusys(LOG_EXIT_SYS,"create tmp working directory") ; - start_write(&tostart,&nclassic,&nlongrun,workdir.s,&gasv,info,FORCE,CONF) ; + start_write(&tostart,&nclassic,&nlongrun,workdir.s,&gasv,info) ; if (nclassic) { @@ -353,7 +409,7 @@ int ssexec_enable(int argc, char const *const *argv,char const *const *envp,ssex stralloc_free(&workdir) ; stralloc_free(&sasrc) ; - for (; pos < tostart.len; pos += strlen(tostart.s + pos) + 1) + for (pos = 0 ; pos < tostart.len; pos += strlen(tostart.s + pos) + 1) log_info("Enabled successfully: ", tostart.s + pos) ; if (start && tostart.len)