From 6468a372c707ac556c7c232467fc96a6632d57df Mon Sep 17 00:00:00 2001 From: obarun <eric@obarun.org> Date: Thu, 29 Sep 2022 20:59:36 +1100 Subject: [PATCH] revamp parse process --- src/include/66/parser.h | 348 +------- src/lib66/parse/deps-lib/deps | 23 +- src/lib66/parse/parse_clean_line.c | 42 + src/lib66/parse/parse_clean_list.c | 35 + src/lib66/parse/parse_clean_quotes.c | 41 + src/lib66/parse/parse_clean_runas.c | 102 +++ src/lib66/parse/parse_compute_list.c | 77 ++ src/lib66/parse/parse_contents.c | 137 +++ src/lib66/parse/parse_dependencies.c | 110 +++ src/lib66/parse/parse_error.c | 65 ++ src/lib66/parse/parse_frontend.c | 251 ++++++ src/lib66/parse/parse_line_g.c | 53 ++ src/lib66/parse/parse_mandatory.c | 90 ++ src/lib66/parse/parse_module.c | 980 +++++++++------------ src/lib66/parse/parse_parentheses.c | 87 ++ src/lib66/parse/parse_section.c | 72 ++ src/lib66/parse/parse_split_from_section.c | 223 +++++ src/lib66/parse/parse_store_environ.c | 66 ++ src/lib66/parse/parse_store_g.c | 67 ++ src/lib66/parse/parse_store_logger.c | 122 +++ src/lib66/parse/parse_store_main.c | 370 ++++++++ src/lib66/parse/parse_store_regex.c | 78 ++ src/lib66/parse/parse_store_start_stop.c | 105 +++ 23 files changed, 2690 insertions(+), 854 deletions(-) create mode 100644 src/lib66/parse/parse_clean_line.c create mode 100644 src/lib66/parse/parse_clean_list.c create mode 100644 src/lib66/parse/parse_clean_quotes.c create mode 100644 src/lib66/parse/parse_clean_runas.c create mode 100644 src/lib66/parse/parse_compute_list.c create mode 100644 src/lib66/parse/parse_contents.c create mode 100644 src/lib66/parse/parse_dependencies.c create mode 100644 src/lib66/parse/parse_error.c create mode 100644 src/lib66/parse/parse_frontend.c create mode 100644 src/lib66/parse/parse_line_g.c create mode 100644 src/lib66/parse/parse_mandatory.c create mode 100644 src/lib66/parse/parse_parentheses.c create mode 100644 src/lib66/parse/parse_section.c create mode 100644 src/lib66/parse/parse_split_from_section.c create mode 100644 src/lib66/parse/parse_store_environ.c create mode 100644 src/lib66/parse/parse_store_g.c create mode 100644 src/lib66/parse/parse_store_logger.c create mode 100644 src/lib66/parse/parse_store_main.c create mode 100644 src/lib66/parse/parse_store_regex.c create mode 100644 src/lib66/parse/parse_store_start_stop.c diff --git a/src/include/66/parser.h b/src/include/66/parser.h index 602d993f..7db31619 100644 --- a/src/include/66/parser.h +++ b/src/include/66/parser.h @@ -15,338 +15,66 @@ #ifndef SS_PARSER_H #define SS_PARSER_H -#include <66/enum.h> - #include <sys/types.h> #include <stdint.h> #include <oblibs/mill.h> #include <skalibs/stralloc.h> -#include <skalibs/genalloc.h> -#include <skalibs/types.h> -#include <skalibs/avltree.h> #include <66/ssexec.h> +#include <66/service.h> -extern stralloc keep ; -extern stralloc deps ; -extern genalloc gasv ; - -/**struct for run and finish file*/ -typedef struct sv_exec_s sv_exec,*sv_exec_ref ; -struct sv_exec_s -{ - int build ; - int runas ; - int shebang ; - int exec ; - int real_exec ; -} ; - -typedef struct sv_execlog_s sv_execlog,*sv_execlog_ref ; -struct sv_execlog_s -{ - sv_exec run ; - /**timeout[0]->kill,timeout[1]->finish - * kill[0][X] enabled,kill[0][0] not enabled*/ - uint32_t timeout[2][UINT_FMT] ; - int destination ; - uint32_t backup ; - uint32_t maxsize ; - int timestamp ; - int idga ; //pos in stralloc deps - unsigned int nga ; //number of deps in stralloc deps -} ; - -typedef struct sv_classic_longrun_s sv_classic_longrun,*sv_classic_ref ; -struct sv_classic_longrun_s -{ - sv_exec run ; - sv_exec finish ; - sv_execlog log ; -} ; - -typedef struct sv_oneshot_s sv_oneshot,*sv_oneshot_ref ; -struct sv_oneshot_s -{ - sv_exec up ; - sv_exec down ; - sv_execlog log ; -} ; - -typedef struct sv_module_s sv_module,*sv_module_ref ; -struct sv_module_s -{ - int configure ; - int iddir ; // pos in stralloc keep -> @directories - unsigned int ndir ; //number of regex directories in stralloc keep -> @directories - int idfiles ; // pos in stralloc keep -> @files - unsigned int nfiles ; //number of regex files in stralloc keep -> @files - int start_infiles ; // pos in stralloc keep of the start of the string -> @infiles - int end_infiles ; // pos in stralloc keep of the end of the string -> @infiles - int idaddservices ; // pos in stralloc keep -> @addservices - unsigned int naddservices ; // number of addon services in stralloc keep > @addservices -} ; - -typedef struct sv_type_s sv_type_t,*sv_type_t_ref ; -struct sv_type_s -{ - sv_classic_longrun classic_longrun ; - sv_oneshot oneshot ; - sv_module module ; -} ; - -typedef struct sv_name_s sv_name_t, *sv_name_t_ref ; -struct sv_name_s -{ - int itype ; //servcie type: classic->bundle->longrun->oneshot->modules - 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 - unsigned int nopts ; // number of optional depends in stralloc deps-> @optsdepends - int idext ; // pos in stralloc deps -> @extdepends - unsigned int next ; // number of optinal depends in stralloc deps -> @extdepends - int logname ; //pos in keep - int dstlog ; //pos in keep - int idcontents ; // pos in stralloc deps -> @contents - unsigned int ncontents ; // number of service inside a bundle -} ; - - -typedef struct sv_alltype_s sv_alltype,*sv_alltype_ref ; -struct sv_alltype_s -{ - sv_type_t type ; - sv_name_t cname ;//cname, Container Name - /**opts[0]->logger,opts[1]->pipeline,[2]->env - * logger[1] enabled,logger[0] not enabled*/ - unsigned int opts[3] ; - /**0->no notification*/ - /**flags[0]->down - * down[1] enabled,down[0] not enabled*/ - unsigned int flags[1] ; - uint32_t notification ; - /** array of uid_t - * the first element of the table - * is reserved to know the number of - * user set e.g user[0]=3->3 user*/ - uid_t user[256] ; - /**timeout[0]->kill,timeout[1]->finish - * timeout[2]->up,timeout[3]->down - * timeout-kill[0][X] enabled,timeout-kill[0][0] not enabled*/ - uint32_t timeout[4][UINT_FMT] ; - uint32_t src ;// original source of the service - uint32_t death ;//max-death-tally file - /** array of uint32_t - * the first element of the table - * is reserved to know the number of - * dir/file to copy e.g hiercopy[0]=3->3 dir/file to copy */ - uint32_t hiercopy[24] ; //dir/file to copy - int signal ;//down-signal file - int pipeline ; //pos in deps - stralloc saenv ; - /* path of the environment file, this is only concern the write - * process, the read process could be different if conf/sysadmin/service - * exist */ - uint32_t srconf ; - /** set the CONF variable for each service. - * useful in case of module. We do not overwrite - * the configuration of the module but we overwrite - * the configuration of each service inside a module */ - uint8_t overwrite_conf ; - -} ; - -#define SV_EXEC_ZERO \ -{ \ - -1 , \ - -1 , \ - -1 , \ - -1 , \ - -1 \ -} +#define parse_error_return(ret, nerr, idsec, idkey) do { \ + parse_error(nerr, idsec, idkey) ; \ + return ret ; \ +} while (0) -#define SV_EXECLOG_ZERO \ -{ \ - SV_EXEC_ZERO, \ - { { 0 } } , \ - -1 , \ - 0 , \ - 0 , \ - -1 , \ - -1 , \ - 0 \ -} +#define parse_error_type(type, idsec, idkey ) do { \ + if (type == TYPE_BUNDLE || type == TYPE_MODULE) \ + log_warn_return(LOG_EXIT_ONE, "key: ", get_key_by_enum(idsec, idkey), " is not valid for type ", get_key_by_enum(ENUM_TYPE, type), " -- ignoring it") ; \ +} while (0) -#define SV_CLASSIC_LONGRUN_ZERO \ -{ \ - SV_EXEC_ZERO, \ - SV_EXEC_ZERO, \ - SV_EXECLOG_ZERO \ -} - -#define SV_ONESHOT_ZERO \ -{ \ - SV_EXEC_ZERO, \ - SV_EXEC_ZERO, \ - SV_EXECLOG_ZERO \ -} - -#define SV_TYPE_ZERO \ -{ \ - SV_CLASSIC_LONGRUN_ZERO , \ - SV_ONESHOT_ZERO , \ - SV_MODULE_ZERO \ -} - -#define SV_MODULE_ZERO \ -{ \ - -1 , \ - -1 , \ - 0 , \ - -1 , \ - 0 , \ - -1 , \ - -1 , \ - -1 , \ - 0 \ -} - -#define SV_NAME_ZERO \ -{ \ - -1 , \ - -1 , \ - -1 , \ - -1 , \ - -1 , \ - -1 , \ - 0 , \ - -1 , \ - 0 , \ - -1 , \ - 0 , \ - -1 , \ - -1 , \ - -1 , \ - 0 \ -} - -#define SV_ALLTYPE_ZERO \ -{ \ - SV_TYPE_ZERO , \ - SV_NAME_ZERO , \ - { 1,0,0 } , \ - { 0 } , \ - 0 , \ - { 0 } , \ - { { 0 } } , \ - 0 , \ - 0 , \ - { 0 } , \ - -1 , \ - -1 , \ - STRALLOC_ZERO , \ - 0 , \ - 0 \ -} - -extern sv_alltype const sv_alltype_zero ; -extern sv_name_t const sv_name_zero ;//set in sv_alltype_zero.c - -typedef struct keynocheck_s keynocheck, *keynocheck_t_ref; -struct keynocheck_s -{ - int idsec ; - int idkey ; - int expected ; - stralloc val ; - -} ; -#define KEYNOCHECK_ZERO { .idsec = -1, .idkey = -1, .expected = -1, .val = STRALLOC_ZERO } -extern keynocheck const keynocheck_zero ;//set in sv_alltype_zero.c - -typedef struct section_s section_t,*section_t_ref ; -struct section_s -{ - stralloc main ; - stralloc start ; - stralloc stop ; - stralloc logger ; - stralloc environment ; - stralloc regex ; - uint32_t idx[6] ; //[0] == 0 -> no, [0] == 1-> yes - char const *file ; -} ; -#define SECTION_ZERO { .main = STRALLOC_ZERO , \ - .start = STRALLOC_ZERO , \ - .stop = STRALLOC_ZERO , \ - .logger = STRALLOC_ZERO , \ - .environment = STRALLOC_ZERO , \ - .regex = STRALLOC_ZERO , \ - .idx = { 0 } , \ - .file = 0 } +/** mill configuration */ +extern parse_mill_t MILL_GET_SECTION_NAME ; +extern parse_mill_t MILL_GET_KEY ; +extern parse_mill_t MILL_GET_VALUE ; /** freed and cleanup*/ -extern void sv_alltype_free(sv_alltype *sv) ; -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 */ +/** main */ 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 void parser(char const *sv, char const *dst, ssexec_t *info, uint8_t force, uint8_t conf) ; +extern int parse_frontend(char const *sv, resolve_service_t *ares, unsigned int *areslen, ssexec_t *info, uint8_t force, uint8_t conf, unsigned int *residx, char const *forced_directory) ; +extern int parse_dependencies(resolve_service_t *res, resolve_service_t *ares, unsigned int *areslen, ssexec_t *info, uint8_t force,uint8_t conf, char const *forced_directory) ; /** 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 parse_section(stralloc *secname, char const *str, size_t *pos) ; +extern int parse_split_from_section(resolve_service_t *res, stralloc *secname, char *str, char const *svname) ; +extern int parse_contents(resolve_wrapper_t_ref wres, char const *contents, char const *svname) ; +extern int parse_compute_list(resolve_wrapper_t_ref wres, stralloc *sa, uint32_t *res, uint8_t opts) ; /** 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) ; +extern int parse_store_g(resolve_service_t *res, char *store, int idsec, int idkey) ; +extern int parse_store_main(resolve_service_t *res, char *store, int idsec, int idkey) ; +extern int parse_store_start_stop(resolve_service_t *res, char *store, int idsec, int idkey) ; +extern int parse_store_logger(resolve_service_t *res, char *store, int idsec, int idkey) ; +extern int parse_store_environ(resolve_service_t *res, char *store, int idsec, int idkey) ; +extern int parse_store_regex(resolve_service_t *res, char *store, int idsec, int idkey) ; /** 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) ; -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) ; -extern int write_oneshot(sv_alltype *sv,char const *dst, uint8_t conf) ; -extern int write_bundle(sv_alltype *sv, char const *dst) ; -extern int write_common(sv_alltype *sv, char const *dst,uint8_t conf) ; -extern int write_exec(sv_alltype *sv, sv_exec *exec,char const *name,char const *dst,mode_t mode) ; -extern int write_uint(char const *dst, char const *name, uint32_t ui) ; -extern int write_logger(sv_alltype *sv, sv_execlog *log,char const *name, char const *dst, mode_t mode, uint8_t force) ; -extern int write_consprod(sv_alltype *sv,char const *prodname,char const *consname,char const *proddst,char const *consdst) ; -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) ; +extern int parse_line_g(char *store, parse_mill_t *config, char const *str, size_t *pos) ; +extern int parse_parentheses(char *store, char const *str, size_t *pos) ; +extern int parse_clean_runas(char const *str, int idsec, int idkey) ; +extern int parse_clean_quotes(char *str) ; +extern int parse_clean_list(stralloc *sa, char const *str) ; +extern int parse_clean_line(char *str) ; +extern int parse_mandatory(resolve_service_t *res) ; +extern void parse_error(int ierr, int idsec, int idkey) ; /** module */ -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) ; -extern int regex_replace(stralloc *list,sv_alltype *sv_before,char const *svname) ; -extern int regex_rename(stralloc *list, int id, unsigned int nid, char const *sdir) ; -extern int regex_configure(sv_alltype *sv_before,ssexec_t *info, char const *module_dir,char const *module_name, uint8_t conf) ; +extern void parse_module(resolve_service_t *res, resolve_service_t *ares, unsigned int *areslen, ssexec_t *info, uint8_t force) ; + #endif diff --git a/src/lib66/parse/deps-lib/deps b/src/lib66/parse/deps-lib/deps index d1a8772b..d802130c 100644 --- a/src/lib66/parse/deps-lib/deps +++ b/src/lib66/parse/deps-lib/deps @@ -1,8 +1,25 @@ +parse_clean_line.o +parse_clean_list.o +parse_clean_quotes.o +parse_clean_runas.o +parse_compute_list.o +parse_contents.o +parse_dependencies.o +parse_error.o +parse_frontend.o +parse_line_g.o +parse_mandatory.o parse_module.o +parse_parentheses.o +parse_section.o parse_service.o -parser.o -parser_utils.o -parser_write.o +parse_split_from_section.o +parse_store_environ.o +parse_store_g.o +parse_store_logger.o +parse_store_main.o +parse_store_regex.o +parse_store_start_stop.o -ls6 -loblibs -lexecline diff --git a/src/lib66/parse/parse_clean_line.c b/src/lib66/parse/parse_clean_line.c new file mode 100644 index 00000000..375c13d2 --- /dev/null +++ b/src/lib66/parse/parse_clean_line.c @@ -0,0 +1,42 @@ +/* + * parse_clean_line.c + * + * Copyright (c) 2018-2022 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 <stddef.h> + +#include <oblibs/mill.h> +#include <oblibs/string.h> + +#include <skalibs/stralloc.h> + +int parse_clean_line(char *str) +{ + + int r = 0, e = 0 ; + size_t tpos = 0 ; + stralloc sa = STRALLOC_ZERO ; + + wild_zero_all(&MILL_CLEAN_LINE) ; + r = mill_element(&sa, str, &MILL_CLEAN_LINE, &tpos) ; + if (r <= 0) + goto err ; + + auto_strings(str, sa.s) ; + + e = 1 ; + + err: + stralloc_free(&sa) ; + return e ; + +} diff --git a/src/lib66/parse/parse_clean_list.c b/src/lib66/parse/parse_clean_list.c new file mode 100644 index 00000000..31c9ebc8 --- /dev/null +++ b/src/lib66/parse/parse_clean_list.c @@ -0,0 +1,35 @@ +/* + * parse_clean_list.c + * + * Copyright (c) 2018-2022 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 <oblibs/string.h> +#include <oblibs/sastr.h> + +#include <skalibs/stralloc.h> + +int parse_clean_list(stralloc *sa, char const *str) +{ + int e = 0 ; + sa->len = 0 ; + + if (!auto_stra(sa, str)) + goto err ; + + if (!sastr_clean_element(sa)) + goto err ; + + e = 1 ; + + err: + return e ; +} diff --git a/src/lib66/parse/parse_clean_quotes.c b/src/lib66/parse/parse_clean_quotes.c new file mode 100644 index 00000000..067def0a --- /dev/null +++ b/src/lib66/parse/parse_clean_quotes.c @@ -0,0 +1,41 @@ +/* + * parse_clean_quotes.c + * + * Copyright (c) 2018-2022 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 <oblibs/string.h> +#include <oblibs/sastr.h> + +#include <skalibs/stralloc.h> + +int parse_clean_quotes(char *str) +{ + int e = 0 ; + stralloc sa = STRALLOC_ZERO ; + + if (!auto_stra(&sa, str)) + goto err ; + + if (!sastr_clean_element(&sa)) + goto err ; + + if (!sastr_rebuild_in_oneline(&sa)) + goto err ; + + auto_strings(str, sa.s) ; + + e = 1 ; + + err: + stralloc_free(&sa) ; + return e ; +} diff --git a/src/lib66/parse/parse_clean_runas.c b/src/lib66/parse/parse_clean_runas.c new file mode 100644 index 00000000..3db2aaf2 --- /dev/null +++ b/src/lib66/parse/parse_clean_runas.c @@ -0,0 +1,102 @@ +/* + * parser_clean_runas.c + * + * Copyright (c) 2018-2022 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 <string.h> +#include <sys/types.h> +#include <pwd.h> +#include <unistd.h> + +#include <oblibs/string.h> +#include <oblibs/types.h> + +#include <skalibs/types.h> + +#include <66/parser.h> +#include <66/utils.h> + +int parse_clean_runas(char const *str, int idsec, int idkey) +{ + size_t len = strlen(str) ; + char file[len + 1] ; + auto_strings(file, str) ; + + char *colon ; + colon = strchr(file,':') ; + + if (colon) { + + *colon = 0 ; + + uid_t uid ; + gid_t gid ; + size_t uid_strlen ; + size_t gid_strlen ; + static char uid_str[UID_FMT] ; + static char gid_str[GID_FMT] ; + + /** on format :gid, get the uid of + * the owner of the process */ + if (!*file) { + + uid = getuid() ; + + } + else { + + if (get_uidbyname(file, &uid) == -1) + parse_error_return(0, 0, idsec, idkey) ; + } + + uid_strlen = uid_fmt(uid_str,uid) ; + uid_str[uid_strlen] = 0 ; + + /** on format uid:, get the gid of + * the owner of the process */ + if (!*(colon + 1)) { + + if (!yourgid(&gid,uid)) + parse_error_return(0, 0, idsec, idkey) ; + } + else { + + if (get_gidbygroup(colon + 1,&gid) == -1) + parse_error_return(0, 0, idsec, idkey) ; + } + gid_strlen = gid_fmt(gid_str,gid) ; + gid_str[gid_strlen] = 0 ; + + + auto_strings((char *)str, uid_str, ":", gid_str) ; + + } else { + + int e = errno ; + errno = 0 ; + + struct passwd *pw = getpwnam(str); + + if (!pw) { + + if (!errno) + errno = ESRCH ; + + parse_error_return(0, 0, idsec, idkey) ; + } + + errno = e ; + + } + + return 1 ; +} diff --git a/src/lib66/parse/parse_compute_list.c b/src/lib66/parse/parse_compute_list.c new file mode 100644 index 00000000..b85f0a1d --- /dev/null +++ b/src/lib66/parse/parse_compute_list.c @@ -0,0 +1,77 @@ +/* + * parse_compute_list.c + * + * Copyright (c) 2018-2022 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 <string.h> +#include <stdint.h> +#include <unistd.h> // getuid + +#include <oblibs/string.h> +#include <oblibs/sastr.h> +#include <oblibs/log.h> + +#include <skalibs/stralloc.h> + +#include <66/parser.h> +#include <66/resolve.h> +#include <66/service.h> + +/** + * @opts -> 1 : build list of optional deps + * */ +int parse_compute_list(resolve_wrapper_t_ref wres, stralloc *sa, uint32_t *res, uint8_t opts) +{ + int r, found = 0 ; + size_t len = sa->len, pos = 0 ; + char t[len + 1] ; + char f[len + 1] ; + + memset(f, 0, len) ; + memset(t, 0, len) ; + + sastr_to_char(t, sa) ; + + for (; pos < len ; pos += strlen(t + pos) + 1) { + + if (t[pos] == '#') + continue ; + + if (opts) { + + sa->len = 0 ; + + r = service_frontend_path(sa, t + pos, getuid(), 0) ; + if (r == -1) + log_dieu(LOG_EXIT_SYS, "get frontend service file of: ", t + pos) ; + + if (!r) + continue ; + + found++ ; + + } + + auto_strings(f + strlen(f), t + pos, " ") ; + + (*res)++ ; + + if (found) + break ; + } + + f[strlen(f) - 1] = 0 ; + + return resolve_add_string(wres, f) ; + +} + diff --git a/src/lib66/parse/parse_contents.c b/src/lib66/parse/parse_contents.c new file mode 100644 index 00000000..517a1d99 --- /dev/null +++ b/src/lib66/parse/parse_contents.c @@ -0,0 +1,137 @@ +/* + * parse_contents.c + * + * Copyright (c) 2018-2022 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 <string.h> + +#include <oblibs/log.h> +#include <oblibs/string.h> + +#include <skalibs/stralloc.h> + +#include <66/parser.h> +#include <66/resolve.h> +#include <66/enum.h> + +int parse_contents(resolve_wrapper_t_ref wres, char const *contents, char const *svname) +{ + log_flow() ; + + size_t clen = strlen(contents), pos = 0, start = 0, len = 0 ; + + stralloc secname = STRALLOC_ZERO ; + stralloc sadir = STRALLOC_ZERO ; + + int e = 0, found = 0 ; + + while (pos < clen) { + + found = 0 ; + + /** keep the starting point of the beginning + * of the section search process */ + start = pos ; + + // get the section name + found = parse_section(&secname, contents, &pos) ; + + if (found == -1) + log_die_nomem("stralloc") ; + + // we are not able to find any section and we are at the start of the file + if (!found && !start) { + log_warn("invalid frontend file of: ", svname, " -- no section found") ; + goto err ; + } + + if (!start && strcmp(secname.s, enum_str_section[SECTION_MAIN])) { + log_warn("invalid frontend file of: ", svname, " -- section [main] must be set first") ; + goto err ; + } + + // not more section, end of file. We copy the rest of the file + if (!found) { + + len = clen - start ; + + char tmp[clen + 1] ; + + auto_strings(tmp, contents + start + 1) ; + + if (!parse_split_from_section((resolve_service_t *)wres->obj, &secname, tmp, svname)) + goto err ; + + break ; + } + else { + + /** again, keep the starting point of the begin + * of the section search process */ + start = pos ; + + found = 0 ; + + /* search for the next section + * we don't want to keep the section name to + * avoid a double entry at the next pass of the loop */ + len = secname.len ; + found = parse_section(&secname, contents, &pos) ; + secname.len = len ; + + if (found == -1) + log_die_nomem("stralloc") ; + + int r = get_rlen_until(contents, '\n', pos - 1) ; + + // found a new one + if (found) { + + len = r - start ; + + char tmp[clen + 1] ; + memcpy(tmp, contents + start + 1, len) ; + tmp[len] = 0 ; + + if (!parse_split_from_section((resolve_service_t *)wres->obj, &secname, tmp, svname)) + goto err ; + + // jump the contents of the section just parsed + start += len ; + } + else { + + len = clen - start ; + + char tmp[clen + 1] ; + + auto_strings(tmp, contents + start + 1) ; + + if (!parse_split_from_section((resolve_service_t *)wres->obj, &secname, tmp, svname)) + goto err ; + + // end of file + break ; + } + /** restart the next research from the end of the previous + * copy A.K.A start of the next section just found previously */ + pos = start ; + } + } + + e = 1 ; + + err: + stralloc_free(&secname) ; + stralloc_free(&sadir) ; + return e ; +} diff --git a/src/lib66/parse/parse_dependencies.c b/src/lib66/parse/parse_dependencies.c new file mode 100644 index 00000000..84265424 --- /dev/null +++ b/src/lib66/parse/parse_dependencies.c @@ -0,0 +1,110 @@ +/* + * parse_dependencies.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 <string.h> +#include <unistd.h> // getuid + +#include <oblibs/log.h> +#include <oblibs/sastr.h> +#include <oblibs/string.h> + +#include <skalibs/stralloc.h> + +#include <66/resolve.h> +#include <66/service.h> +#include <66/parser.h> +#include <66/ssexec.h> +#include <66/utils.h> +#include <66/constants.h> + +int parse_dependencies(resolve_service_t *res, resolve_service_t *ares, unsigned int *areslen, ssexec_t *info, uint8_t force, uint8_t conf, char const *forced_directory) +{ + log_flow() ; + + size_t pos = 0, len = 0 ; + int r, e = 0 ; + unsigned int residx = 0 ; + stralloc sa = STRALLOC_ZERO ; + + if (res->dependencies.ndepends) { + + if (!sastr_clean_string(&sa, res->sa.s + res->dependencies.depends)) { + log_warnu("clean the string") ; + goto freed ; + } + + char t[sa.len] ; + + sastr_to_char(t, &sa) ; + + len = sa.len ; + + for (; pos < len ; pos += strlen(t + pos) + 1) { + + sa.len = 0 ; + char name[strlen(t + pos)] ; + char ainsta[strlen(t + pos)] ; + int insta = -1 ; + + log_trace("parse dependencies: ", t + pos, " of service: ", res->sa.s + res->name) ; + + insta = instance_check(t + pos) ; + + if (insta > 0) { + + if (!instance_splitname(&sa, t + pos, insta, SS_INSTANCE_TEMPLATE)) + log_die(LOG_EXIT_SYS, "split instance service of: ", t + pos) ; + + auto_strings(name, sa.s) ; + sa.len = 0 ; + + if (!instance_splitname(&sa, t + pos, insta, SS_INSTANCE_NAME)) + log_die(LOG_EXIT_SYS, "split instance service of: ", t + pos) ; + + auto_strings(ainsta, sa.s) ; + sa.len = 0 ; + + } else { + + auto_strings(name, t + pos) ; + } + + r = service_frontend_path(&sa, name, getuid(), forced_directory) ; + if (r < 1) { + log_warnu( "get frontend service file of: ", t + pos) ; + goto freed ; + } + + if (insta > 0) { + sa.len-- ; + if (!stralloc_catb(&sa, ainsta, strlen(ainsta))) + log_die_nomem("stralloc") ; + } + + if (!stralloc_0(&sa)) + log_die_nomem("stralloc") ; + + /** nothing to do with the exit code */ + parse_frontend(sa.s, ares, areslen, info, force, conf, &residx, forced_directory) ; + } + + } else + log_trace("no dependencies found for: ", res->sa.s + res->name) ; + + e = 1 ; + + freed: + stralloc_free(&sa) ; + return e ; +} diff --git a/src/lib66/parse/parse_error.c b/src/lib66/parse/parse_error.c new file mode 100644 index 00000000..f8aeb93d --- /dev/null +++ b/src/lib66/parse/parse_error.c @@ -0,0 +1,65 @@ +/* + * parse_error.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 <oblibs/log.h> + +#include <66/enum.h> + +void parse_error(int ierr, int idsec, int idkey) +{ + log_flow() ; + + char const *section = get_key_by_enum(ENUM_SECTION, idsec) ; + /* start stop enum are the same, enum_all must increase by one to match + * the correct list + * */ + char const *key = get_key_by_enum(idsec < 2 ? idsec + 1 : idsec,idkey) ; + + switch(ierr) + { + case 0: + log_warn("invalid value for key: ",key,": in section: ",section) ; + break ; + case 1: + log_warn("multiple definition of key: ",key,": in section: ",section) ; + break ; + case 2: + log_warn("same value for key: ",key,": in section: ",section) ; + break ; + case 3: + log_warn("key: ",key,": must be an integrer value in section: ",section) ; + break ; + case 4: + log_warn("key: ",key,": must be an absolute path in section: ",section) ; + break ; + case 5: + log_warn("key: ",key,": must be set in section: ",section) ; + break ; + case 6: + log_warn("invalid format of key: ",key,": in section: ",section) ; + break ; + case 7: + log_warnu("parse key: ",key,": in section: ",section) ; + break ; + case 8: + log_warnu("clean value of key: ",key,": in section: ",section) ; + break ; + case 9: + log_warn("empty value of key: ",key,": in section: ",section) ; + break ; + default: + log_warn("unknown parse_err number") ; + break ; + } +} diff --git a/src/lib66/parse/parse_frontend.c b/src/lib66/parse/parse_frontend.c new file mode 100644 index 00000000..d9d30760 --- /dev/null +++ b/src/lib66/parse/parse_frontend.c @@ -0,0 +1,251 @@ +/* + * parse_frontend.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 <stdint.h> +#include <string.h> +#include <stdlib.h> //free + +#include <oblibs/log.h> +#include <oblibs/sastr.h> +#include <oblibs/string.h> +#include <oblibs/types.h> +#include <oblibs/environ.h> + +#include <skalibs/stralloc.h> + +#include <66/utils.h> +#include <66/constants.h> +#include <66/ssexec.h> +#include <66/service.h> +#include <66/tree.h> +#include <66/config.h> +#include <66/resolve.h> +#include <66/environ.h> +#include <66/enum.h> +#include <66/state.h> // service_is_g flag +#include <66/parser.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 of: ", 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) ; + +} + +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) ; + +} + +static void already_parsed(char const *sv, char const *atree, ssexec_t *info) +{ + log_info("ignoring service: ", sv, " -- already present at tree: ", atree) ; + /** 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 enabled again anyway. */ + info->treename.len = 0 ; + if (!auto_stra(&info->treename, atree)) + log_die_nomem("stralloc") ; + set_info(info) ; +} + +/* @sv -> name of the service to parse with + * the path of the frontend file source + * @Die on fail + * @Return 1 on success + * @Return 2 -> already parsed */ +int parse_frontend(char const *sv, resolve_service_t *ares, unsigned int *areslen, ssexec_t *info, uint8_t force, uint8_t conf, unsigned int *residx, char const *forced_directory) +{ + log_flow() ; + + int insta, r ; + size_t svlen = strlen(sv) ; + char svname[svlen + 1], svsrc[svlen + 1] ; + char atree[SS_MAX_TREENAME + 1] ; + stralloc sa = 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) ; + + if (service_resolve_array_search(ares, *areslen, svname) >= 0) + log_warn_return(2, "ignoring: ", svname, " service -- already appended to the selection") ; + + log_trace("parse service: ", sv) ; + + resolve_service_t res = RESOLVE_SERVICE_ZERO ; + resolve_wrapper_t_ref wres = resolve_set_struct(DATA_SERVICE, &res) ; + + resolve_init(wres) ; + + insta = instance_check(svname) ; + + if (!insta) { + + log_die(LOG_EXIT_SYS, "invalid instance name: ", svname) ; + + } else if (insta > 0) { + + parse_service_instance(&sa, svsrc, svname, insta) ; + + } else { + + log_trace("read frontend service of: ", sv) ; + + if (read_svfile(&sa, svname, svsrc) <= 0) + log_dieusys(LOG_EXIT_SYS, "read frontend service of: ", sv) ; + } + + char file[sa.len + 1] ; + auto_strings(file, sa.s) ; + + r = service_is_g(atree, svname, STATE_FLAGS_ISPARSED) ; + if (r == -1) + log_dieu(LOG_EXIT_SYS, "check already parsed services") ; + + if (r) { + + if (!force) { + + already_parsed(svname, atree, info) ; + return 2 ; + + } else if (!info->skip_opt_tree) { + /* -t option was used */ + if (strcmp(info->treename.s, atree)) + log_die(LOG_EXIT_SYS,"you can not enable again a service already set on another tree -- current: ", atree, " asked: ", info->treename.s, ". Try first to disable it") ; + + } + + } + + if (info->skip_opt_tree) { + + /** @intree may not exist */ + r = sastr_find(&sa, get_key_by_enum(ENUM_KEY_SECTION_MAIN, KEY_MAIN_INTREE)) ; + if (r == -1) + goto follow ; + + if (!environ_get_val_of_key(&sa, get_key_by_enum(ENUM_KEY_SECTION_MAIN, KEY_MAIN_INTREE))) + log_dieu(LOG_EXIT_SYS, "get field intree of service: ", sv) ; + + if (!sastr_clean_element(&sa)) + log_dieu(LOG_EXIT_SYS, "clean field intree of service: ", sv) ; + + res.intree = resolve_add_string(wres, sa.s) ; + + info->treename.len = 0 ; + if (!auto_stra(&info->treename, res.sa.s + res.intree) || + !auto_stra(&sa, file)) + log_die_nomem("stralloc") ; + + } + + follow: + + if (!environ_get_val_of_key(&sa, get_key_by_enum(ENUM_KEY_SECTION_MAIN, KEY_MAIN_TYPE))) + log_dieu(LOG_EXIT_SYS, "get field ", get_key_by_enum(ENUM_KEY_SECTION_MAIN, KEY_MAIN_TYPE)," of service: ", svname) ; + + char store[sa.len + 1] ; + auto_strings(store, sa.s) ; + + if (!parse_store_main(&res, store, SECTION_MAIN, KEY_MAIN_TYPE)) + log_dieu(LOG_EXIT_SYS, "store field type of service: ", svname) ; + + stralloc_free(&sa) ; + + res.name = resolve_add_string(wres, svname) ; + res.owner = info->owner ; + res.ownerstr = resolve_add_string(wres, info->ownerstr) ; + + res.path.frontend = resolve_add_string(wres, svsrc) ; + + // keep overwrite_conf + res.environ.env_overwrite = conf ; + + /** try to create the tree if not exist yet with + * the help of the seed files */ + set_info(info) ; + + /** contents of directory should be listed by service_frontend_path + * except for module type */ + if (scan_mode(sv,S_IFDIR) == 1 && res.type != TYPE_MODULE) + goto freed ; + + if (!parse_contents(wres, file, svname)) + log_dieu(LOG_EXIT_SYS, "parse file of service: ", svname) ; + + if (!parse_mandatory(&res)) + log_die(LOG_EXIT_SYS, "some mandatory field is missing for service: ", svname) ; + + /** append res.dependencies.depends list with the optional dependencies list */ + if (res.dependencies.noptsdeps) { + + if (res.dependencies.ndepends) { + size_t len = strlen(res.sa.s + res.dependencies.depends) ; + char t[len + 1] ; + auto_strings(t + len, " ", res.sa.s + res.dependencies.optsdeps) ; + res.dependencies.depends = resolve_add_string(wres, t) ; + + } else { + + res.dependencies.depends = resolve_add_string(wres, res.sa.s + res.dependencies.optsdeps) ; + } + } + + if (!parse_dependencies(&res, ares, areslen, info, force, conf, forced_directory)) + log_dieu(LOG_EXIT_SYS, "parse dependencies of service: ", svname) ; + + service_resolve_compute(&res, info) ; + + if (res.type == TYPE_MODULE) + parse_module(&res, ares, areslen, info, force) ; + + log_warn("add service: ", svname) ; + + if (service_resolve_array_search(ares, *areslen, svname) < 0) { + (*residx) = *areslen ; + ares[(*areslen)++] = res ; + } + + freed: + + free(wres) ; + return 1 ; +} diff --git a/src/lib66/parse/parse_line_g.c b/src/lib66/parse/parse_line_g.c new file mode 100644 index 00000000..e4646b30 --- /dev/null +++ b/src/lib66/parse/parse_line_g.c @@ -0,0 +1,53 @@ +/* + * parser_line_g.c + * + * Copyright (c) 2018-2022 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 <stddef.h> + +#include <oblibs/string.h> +#include <oblibs/mill.h> + +#include <skalibs/stralloc.h> + +#include <66/parser.h> + +/* @Return 2 if bad format */ +int parse_line_g(char *store, parse_mill_t *config, char const *str, size_t *pos) +{ + int r = 0, e = 0 ; + stralloc sa = STRALLOC_ZERO ; + + r = mill_element(&sa, str, config, pos) ; + if (r <= 0 || !sa.len) + goto err ; + + if (!stralloc_0(&sa)) + goto err ; + + if (sa.s[0] == ' ') + goto err ; + + r = get_len_until(str, '\n') ; + if (r < 1) + r = 0 ; + + (*pos) = r + 1 ; // +1 remove '\n' + + e = 1 ; + + auto_strings(store, sa.s) ; + + err: + stralloc_free(&sa) ; + return e ; +} diff --git a/src/lib66/parse/parse_mandatory.c b/src/lib66/parse/parse_mandatory.c new file mode 100644 index 00000000..4c09d650 --- /dev/null +++ b/src/lib66/parse/parse_mandatory.c @@ -0,0 +1,90 @@ +/* + * parse_mandatory.c + * + * Copyright (c) 2018-2022 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 <oblibs/log.h> + +#include <66/parser.h> +#include <66/resolve.h> +#include <66/enum.h> + +int parse_mandatory(resolve_service_t *res) +{ + log_flow() ; + + if (!res->description) + log_warn_return(LOG_EXIT_ZERO,"key @description at section [main] must be set") ; + + if (!res->user) + log_warn_return(LOG_EXIT_ZERO,"key @user at section [main] must be set") ; + + if (!res->version) + log_warn_return(LOG_EXIT_ZERO,"key @version at section [main] must be set") ; + + switch (res->type) { + + case TYPE_ONESHOT: + + if (!strcmp(res->sa.s + res->execute.run.build, "custom") && !res->execute.run.shebang) + log_warn_return(LOG_EXIT_ZERO,"custom build asked at section [start] -- key @shebang must be set") ; + + if (!res->execute.run.run_user) + log_warn_return(LOG_EXIT_ZERO,"key @execute at section [start] must be set") ; + + if (!strcmp(res->sa.s + res->execute.finish.build, "custom") && !res->execute.finish.shebang) + log_warn_return(LOG_EXIT_ZERO,"custom build asked at section [stop] -- key @shebang must be set") ; + + break ; + + case TYPE_CLASSIC: + + if (!strcmp(res->sa.s + res->execute.run.build, "custom") && !res->execute.run.shebang) + log_warn_return(LOG_EXIT_ZERO,"custom build asked at section [start] -- key @shebang must be set") ; + + if (!res->execute.run.run_user) + log_warn_return(LOG_EXIT_ZERO,"key @execute at section [start] must be set") ; + + + if (!strcmp(res->sa.s + res->execute.finish.build, "custom") && !res->execute.finish.shebang) + log_warn_return(LOG_EXIT_ZERO,"custom build asked at section [stop] -- key @shebang must be set") ; + + if (!strcmp(res->sa.s + res->logger.execute.finish.build, "custom") && !res->logger.execute.finish.shebang) + log_warn_return(LOG_EXIT_ZERO,"custom build asked at section [stop] -- key @shebang must be set") ; + + break ; + + case TYPE_MODULE: + + /* + + if (!sasection->idx[SECTION_REGEX]) + log_warn_return(LOG_EXIT_ZERO,"section [regex] must be set") ; + + if (service->type.module.iddir < 0) + log_warn_return(LOG_EXIT_ZERO,"key @directories at section [regex] must be set") ; + + if (service->type.module.idfiles < 0) + log_warn_return(LOG_EXIT_ZERO,"key @files at section [regex] must be set") ; + + if (service->type.module.start_infiles < 0) + log_warn_return(LOG_EXIT_ZERO,"key @infiles at section [regex] must be set") ; + + break ; + + */ + + /** really nothing to do here */ + default: break ; + } + return 1 ; +} diff --git a/src/lib66/parse/parse_module.c b/src/lib66/parse/parse_module.c index 1ad8206f..992b6ef5 100644 --- a/src/lib66/parse/parse_module.c +++ b/src/lib66/parse/parse_module.c @@ -1,7 +1,7 @@ /* * parse_module.c * - * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org> + * Copyright (c) 2018-2022 Eric Vidal <eric@obarun.org> * * All rights reserved. * @@ -12,31 +12,35 @@ * except according to the terms contained in the LICENSE file./ */ -#include <66/parser.h> - #include <string.h> +#include <errno.h> +#include <pwd.h> +#include <sys/types.h> +#include <unistd.h> //chdir, unlink +#include <stdlib.h> #include <stdio.h> //rename -#include <unistd.h> //chdir #include <oblibs/string.h> -#include <oblibs/types.h> #include <oblibs/log.h> +#include <oblibs/mill.h> #include <oblibs/sastr.h> +#include <oblibs/types.h> +#include <oblibs/directory.h> #include <oblibs/environ.h> #include <oblibs/files.h> -#include <oblibs/mill.h> -#include <oblibs/directory.h> #include <skalibs/stralloc.h> -#include <skalibs/djbunix.h> -#include <skalibs/env.h> -#include <skalibs/bytestr.h>//byte_count -#include <skalibs/genalloc.h> +#include <skalibs/djbunix.h> //hiercopy +#include <skalibs/env.h> //hiercopy +#include <skalibs/bytestr.h> -#include <66/resolve.h> +#include <66/write.h> #include <66/utils.h> -#include <66/constants.h> #include <66/environ.h> +#include <66/resolve.h> +#include <66/service.h> +#include <66/constants.h> +#include <66/utils.h> #define SS_MODULE_CONFIG_DIR "/configure" #define SS_MODULE_CONFIG_DIR_LEN (sizeof SS_MODULE_CONFIG_DIR - 1) @@ -47,716 +51,610 @@ #define SS_MODULE_SERVICE_INSTANCE "/service@" #define SS_MODULE_SERVICE_INSTANCE_LEN (sizeof SS_MODULE_SERVICE_INSTANCE - 1) -static int check_dir(char const *src,char const *dir) +static void instance_splitname_to_char(char *store, char const *name, int len, int what) { log_flow() ; - int r ; - size_t srclen = strlen(src) ; - size_t dirlen = strlen(dir) ; + char const *copy ; + size_t tlen = len + 1, clen = 0 ; + + char template[tlen + 1] ; + memcpy(template,name,tlen) ; + template[tlen] = 0 ; + + copy = name + tlen ; - char tsrc[srclen + dirlen + 1] ; - auto_strings(tsrc,src,dir) ; + if (!what) { - r = scan_mode(tsrc,S_IFDIR) ; - if (r < 0) { errno = EEXIST ; log_warnusys_return(LOG_EXIT_ZERO,"conflicting format of: ",tsrc) ; } - if (!r) { + auto_strings(store, template) ; - if (!dir_create_parent(tsrc,0755)) - log_warnusys_return(LOG_EXIT_ZERO,"create directory: ",tsrc) ; + } else { + + clen = strlen(copy) ; + memcpy(store, copy, clen) ; + store[clen] = 0 ; } - return 1 ; } -static int get_list(stralloc *list, stralloc *sdir,size_t len, char const *svname, mode_t mode) +static void parse_module_check_dir(char const *src,char const *dir) { log_flow() ; - sdir->len = len ; - if (!auto_stra(sdir,SS_MODULE_SERVICE)) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ; - - char const *exclude[1] = { 0 } ; - if (!sastr_dir_get_recursive(list,sdir->s,exclude,mode,1)) - log_warnusys_return(LOG_EXIT_ZERO,"get file(s) of module: ",svname) ; - - sdir->len = len ; + int r ; + size_t srclen = strlen(src) ; + size_t dirlen = strlen(dir) ; - if (!auto_stra(sdir,SS_MODULE_SERVICE_INSTANCE)) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ; + char t[srclen + dirlen + 1] ; + auto_strings(t, src, dir) ; - if (!sastr_dir_get_recursive(list,sdir->s,exclude,mode,1)) - log_warnusys_return(LOG_EXIT_ZERO,"get file(s) of module: ",svname) ; + r = scan_mode(t,S_IFDIR) ; + if (r < 0) { + errno = EEXIST ; + log_diesys(LOG_EXIT_ZERO, "conflicting format of: ", t) ; + } - return 1 ; + if (!r) + if (!dir_create_parent(t, 0755)) + log_dieusys(LOG_EXIT_ZERO, "create directory: ", t) ; } -static int rebuild_list(sv_alltype *alltype,stralloc *list,stralloc *sv_all_type, stralloc *module_service) +static void parse_module_check_name(char const *src, char const *name) { log_flow() ; - size_t pos, id, did, nid, dnid ; - sv_alltype_ref sv ; - id = alltype->cname.idga, nid = alltype->cname.nga ; - for (; nid ; id += strlen(deps.s + id) + 1, nid--) - { - char *deps_name = deps.s + id ; - /** if we check the dependencies of a module which was declared - * inside the main module, the recursive operation enter on infinite loop. - * So, break it by dependency addition comparison */ - if (sastr_cmp(sv_all_type,deps_name) == -1) { - - for (pos = 0 ; pos < genalloc_len(sv_alltype,&gasv) ; pos++) { - - sv = &genalloc_s(sv_alltype,&gasv)[pos] ; - int type = sv->cname.itype == TYPE_MODULE ? 1 : 0 ; - char *n = keep.s + sv->cname.name ; + char basename[strlen(src)] ; + int insta = -1 ; - if (!strcmp(n,deps_name)) { + if (!ob_basename(basename, src)) + log_dieu(LOG_EXIT_SYS, "get basename of: ", src) ; - if (!stralloc_catb(list,keep.s + sv->src,strlen(keep.s + sv->src) + 1)) - return 0 ; + insta = instance_check(name) ; - if (!sv->cname.nga) - continue ; - - did = type ? sv->cname.idcontents : sv->cname.idga, dnid = type ? sv->cname.ncontents : sv->cname.nga ; - - for (;dnid; did += strlen(deps.s + did) + 1, dnid--) { - - if (sastr_cmp(list,deps.s + did) >= 0) - continue ; + if (insta <= 0) + log_die(LOG_EXIT_SYS, "invalid module instance name: ", name) ; - if (!rebuild_list(sv,list,sv_all_type,module_service)) - log_warnu(LOG_EXIT_ZERO,"rebuild dependencies list of: ",deps.s + did) ; - } - } - } + if (basename[0] != '@') + log_die(LOG_EXIT_USER, "invalid directory name for module: ", name, " -- directory name must start with a '@' character") ; +} - if (!stralloc_catb(sv_all_type,deps_name,strlen(deps_name) + 1)) - return 0 ; - } +static int parse_module_ownerhome(char *store) +{ + log_flow() ; - if (!stralloc_catb(module_service,deps_name,strlen(deps_name) + 1)) - return 0 ; + char const *user_home = 0 ; + int e = errno ; + struct passwd *st = getpwuid(getuid()) ; + errno = 0 ; + if (!st) { + if (!errno) errno = ESRCH ; + return 0 ; } - - if (!sastr_sortndrop_element(module_service)) + user_home = st->pw_dir ; + errno = e ; + if (!user_home) return 0 ; + auto_strings(store, user_home, "/") ; + return 1 ; } -/** return 1 on success - * return 0 on failure - * return 2 on already enabled - * @svname do not contents the path of the frontend file*/ - -int parse_module(sv_alltype *alltype, ssexec_t *info, stralloc *parsed_list, uint8_t force) +/* 0 filename undefine + * -1 system error + * should return at least 2 meaning :: no file define*/ +static int regex_get_file_name(char *filename, char const *str) { log_flow() ; - int r, err = 1, insta = -1, minsta = -1, svtype = -1, from_ext_insta = 0, already_parsed = 0 ; - size_t pos = 0, id, nid, newlen ; - stralloc sdir = STRALLOC_ZERO ; // service dir - stralloc list = STRALLOC_ZERO ; - stralloc tmp = STRALLOC_ZERO ; - stralloc addonsv = STRALLOC_ZERO ; - char *sv = keep.s + alltype->cname.name ; - char src[strlen(keep.s + alltype->src) + 1] ; - uint8_t conf = alltype->overwrite_conf ; - - if (!ob_dirname(src, keep.s + alltype->src)) - log_dieu(LOG_EXIT_SYS,"get dirname of: ", keep.s + alltype->src) ; + int r ; + size_t pos = 0 ; + stralloc kp = STRALLOC_ZERO ; - log_trace("start parse process of module: ",sv) ; + parse_mill_t MILL_GET_COLON = { + .open = ':', .close = ':', + .skip = " \t\r", .skiplen = 3, + .forceclose = 1, + .inner.debug = "get_colon" } ; - /** should be always right, - * be paranoid and check it */ - insta = instance_check(sv) ; - if (insta <= 0) - log_die(LOG_EXIT_SYS, "invalid module instance name: ",sv); + r = mill_element(&kp, str, &MILL_GET_COLON, &pos) ; + if (r == -1) + log_dieu(LOG_EXIT_SYS, "get filename of line: ", str) ; - minsta = insta ; + auto_strings(filename, kp.s) ; - if (!module_path(&sdir, &tmp, sv, src, info->owner)) - log_dieu(LOG_EXIT_SYS,"resolve source of module: ",sv); + stralloc_free(&kp) ; + return pos ; +} - /** 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 ; +static void regex_get_replace(char *replace, char const *str) +{ + log_flow() ; - newlen = sdir.len ; + int pos = get_len_until(str,'=') ; + if (!pos || pos == -1) + log_dieu(LOG_EXIT_SYS,"replace string of line: ", str) ; + char tmp[pos + 1] ; + memcpy(tmp,str,pos) ; + tmp[pos] = 0 ; + auto_strings(replace, tmp) ; +} - char permanent_sdir[sdir.len + 2] ; - auto_strings(permanent_sdir, sdir.s, "/") ; +static void regex_get_regex(char *regex, char const *str) +{ + log_flow() ; - 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) { + size_t len = strlen(str) ; + int pos = get_len_until(str,'=') ; + if (!pos || pos == -1) + log_dieu(LOG_EXIT_SYS, "get regex string of line: ", str) ; + pos++ ; // remove '=' + char tmp[len + 1] ; + memcpy(tmp,str + pos,len-pos) ; + tmp[len-pos] = 0 ; + auto_strings(regex,tmp) ; +} - if (!hiercopy(tmp.s, sdir.s)) - log_dieusys(LOG_EXIT_SYS, "copy: ", tmp.s, " to: ", sdir.s) ; +static void get_list(stralloc *list, char const *src, char const *name, mode_t mode) +{ + log_flow() ; - } else { + list->len = 0 ; + char const *exclude[2] = { SS_MODULE_CONFIG_DIR + 1, 0 } ; - /** Must reconfigure all services of the module */ - if (force < 2) { + char t[strlen(src) + 1] ; - log_warn("skip configuration of the module: ", sv, " -- already configured") ; - err = 2 ; - goto make_deps ; - } + auto_strings(t, src) ; - if (rm_rf(sdir.s) < 0) - log_dieusys (LOG_EXIT_SYS, "remove: ", sdir.s) ; + if (!sastr_dir_get_recursive(list, t, exclude, mode, 1)) + log_dieusys(LOG_EXIT_SYS,"get file(s) of module: ", name) ; - if (!hiercopy(tmp.s, sdir.s)) - log_dieusys(LOG_EXIT_SYS,"copy: ", tmp.s, " to: ", sdir.s) ; - } +} - /** regex file content */ - list.len = 0 ; +static void regex_replace(stralloc *list, resolve_service_t *res) +{ + log_flow() ; - if (!get_list(&list, &sdir, newlen, sv, S_IFREG)) return 0 ; - if (!regex_replace(&list, alltype, sv)) return 0 ; + int r ; + size_t pos = 0, idx = 0 ; - /* regex directories name */ - if (!get_list(&list, &sdir, newlen, sv, S_IFDIR)) return 0 ; - if (!regex_rename(&list, alltype->type.module.iddir, alltype->type.module.ndir, sdir.s)) return 0 ; + stralloc frontend = STRALLOC_ZERO ; + stralloc sa = STRALLOC_ZERO ; - /* regex files name */ - list.len = 0 ; + if (!res->regex.ninfiles) + return ; - 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 ; + if (!sastr_clean_string(&sa, res->sa.s + res->regex.infiles)) + log_dieu(LOG_EXIT_SYS, "clean string") ; - /* launch configure script */ - if (!regex_configure(alltype, info, permanent_sdir, sv, conf)) return 0 ; + FOREACH_SASTR(list, pos) { - make_deps: + frontend.len = idx = 0 ; + char *str = list->s + pos ; + size_t len = strlen(str) ; + char bname[len + 1] ; + char dname[len + 1] ; - tmp.len = 0 ; - list.len = 0 ; + if (!ob_basename(bname, str)) + log_dieu(LOG_EXIT_SYS, "get basename of: ", str) ; - if (!auto_stra(&tmp, permanent_sdir, SS_MODULE_SERVICE + 1)) - log_die_nomem("stralloc") ; + if (!ob_dirname(dname, str)) + log_dieu(LOG_EXIT_SYS, "get dirname of: ", str) ; - /** get all services */ - char const *exclude[1] = { 0 } ; - if (!sastr_dir_get_recursive(&list, tmp.s, exclude, S_IFREG, 1)) - log_dieusys(LOG_EXIT_SYS, "get file(s) of module: ", sv) ; + //log_trace("read service file of: ", dname, bname) ; + r = read_svfile(&frontend, bname, dname) ; + if (!r) + log_dieusys(LOG_EXIT_SYS, "read file: ", str) ; + else if (r == -1) + continue ; - /** add addon services */ - if (alltype->type.module.naddservices > 0) { + { + FOREACH_SASTR(&sa, idx) { - id = alltype->type.module.idaddservices, nid = alltype->type.module.naddservices ; - for (; nid ; id += strlen(keep.s + id) + 1, nid--) { + int all = 0, fpos = 0 ; + char const *line = sa.s + idx ; + size_t linelen = strlen(line) ; + char filename[SS_MAX_SERVICE_NAME + 1] ; + char replace[linelen + 1] ; + char regex[linelen + 1] ; - char *name = keep.s + id ; - if (service_frontend_path(&list, name, info->owner,0) < 1) - log_die(LOG_EXIT_SYS, "resolve source path of: ", name) ; - } - } + if (linelen >= SS_MAX_PATH_LEN) + log_die(LOG_EXIT_SYS, "limit exceeded in service: ", res->sa.s + res->name) ; - tmp.len = 0 ; - sdir.len = 0 ; + if ((line[0] != ':') || (get_sep_before(line + 1, ':', '=') < 0)) + log_die(LOG_EXIT_SYS, "bad format in line: ", line, " of key @infiles field") ; - /** remake the depends field. - * incoporate the module services dependencies inside the list to parse - * and each dependency of each module service dependency. - * Do it recursively. */ - if (!rebuild_list(alltype, &list, &tmp, &sdir)) - log_dieu(LOG_EXIT_SYS,"rebuild dependencies list of: ", sv) ; + memset(filename, 0, SS_MAX_SERVICE_NAME + 1) ; + memset(replace, 0, linelen + 1) ; + memset(regex, 0, linelen + 1) ; - /** parse all services of the modules */ - for (pos = 0 ; pos < list.len ; pos += strlen(list.s + pos) + 1) { + fpos = regex_get_file_name(filename, line) ; + if (fpos < 3) all = 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 ; + regex_get_replace(replace, line + fpos) ; - addonsv.len = 0 ; + regex_get_regex(regex, line + fpos) ; - if (sastr_cmp(parsed_list, svname) >= 0) { + if (!strcmp(bname, filename) || all) { - /** already parsed ? */ - size_t idx = 0 ; - for (; idx < genalloc_len(sv_alltype, &gasv) ; idx++) { + if (!sastr_replace_all(&frontend, replace, regex)) + log_dieu(LOG_EXIT_SYS, "replace: ", replace, " by: ", regex, " in file: ", str) ; - char *name = keep.s + genalloc_s(sv_alltype, &gasv)[idx].src ; + if (!stralloc_0(&frontend)) + log_dieusys(LOG_EXIT_SYS, "stralloc") ; - if (!strcmp(name, svname)) { + frontend.len-- ; - svname = name ; - break ; + if (!file_write_unsafe(dname, bname, frontend.s, frontend.len)) + log_dieusys(LOG_EXIT_SYS, "write: ", dname, "/", bname) ; } } - already_parsed = 1 ; } + } - if (!ob_basename(bname,svname)) - log_dieu(LOG_EXIT_SYS,"find basename of: ", svname) ; - - pbname = bname ; + stralloc_free(&sa) ; +} - /** detect cyclic call. Sub-module cannot call it itself*/ - if (!strcmp(sv, bname)) - log_die(LOG_EXIT_SYS,"cyclic call detected -- ", sv, " call ", bname) ; +static void regex_rename(stralloc *list, resolve_service_t *res, uint32_t element) +{ + log_flow() ; - insta = instance_check(bname) ; - if (!insta) log_die(LOG_EXIT_SYS,"invalid instance name: ", svname) ; - if (insta > 0) { + stralloc sa = STRALLOC_ZERO ; - /** we can't know the origin of the instanciated service. - * Search first at service@ directory, if it not found - * pass through the classic service_frontend_path() */ + if (!element) + return ; - pbname = bname ; - if (!already_parsed) { + if (!sastr_clean_string(&sa, res->sa.s + element)) + log_dieu(LOG_EXIT_SYS, "clean string") ; - 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, "/") ; + size_t pos = 0, idx = 0, salen = sa.len ; + char t[sa.len] ; - r = service_frontend_src(&addonsv, pbname, tmp) ; + sastr_to_char(t, &sa) ; - if (r == -1) log_dieusys(LOG_EXIT_SYS,"parse source directory: ", tmp) ; - if (!r) { + for (; pos < salen ; pos += strlen(t + pos) + 1) { - if (service_frontend_path(&addonsv, pbname, info->owner, 0) < 1) - log_dieu(LOG_EXIT_SYS,"resolve source path of: ", pbname) ; - } - svname = addonsv.s ; - } - from_ext_insta++ ; - len = strlen(svname) ; - } + idx = 0 ; + char *line = t + pos ; + char replace[SS_MAX_PATH] = { 0 } ; + char regex[SS_MAX_PATH] = { 0 } ; - if (!already_parsed) - start_parser(svname, info, 0, permanent_sdir) ; + regex_get_replace(replace,line) ; - char ext_insta[len + 1] ; - if (from_ext_insta) { + regex_get_regex(regex,line) ; - size_t len = strlen(svname) ; - r = get_rlen_until(svname, '@', len) + 1 ; - size_t newlen = len - (len - r) ; - auto_strings(ext_insta, svname) ; - ext_insta[newlen] = 0 ; - svname = ext_insta ; - } + FOREACH_SASTR(list, idx) { - /** we want the configuration file for each service inside - * the configuration directory of the module. - * In case of sub-module, we skip it. - * Also, we skip every dependency of the sub-module, - * each module contains its own services.*/ - char *version = keep.s + alltype->cname.version ; + sa.len = 0 ; + char *str = list->s + idx ; + size_t len = strlen(str) ; + char dname[len + 1] ; - { - stralloc tmpenv = STRALLOC_ZERO ; - /** SS_MAX_SERVICE is the maximum of services set at compile time - * that can be supervised by s6-svscan. 500 is the default which - * should be large enough for the majority of the cases */ - size_t pos, spos, id, nid, idmodule[SS_MAX_SERVICE] = { 0 } ; - sv_alltype_ref svref ; + if (!ob_dirname(dname, str)) + log_dieu(LOG_EXIT_SYS, "get dirname of: ", str) ; - if (!env_resolve_conf(&tmpenv, sv, info->owner)) - log_dieu(LOG_EXIT_SYS,"get path of the configuration file") ; + if (!sabasename(&sa, str, len)) + log_dieu(LOG_EXIT_SYS, "get basename of: ", str) ; - if (!auto_stra(&tmpenv, "/")) + if (!stralloc_0(&sa)) 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) { + if (!sastr_replace(&sa, replace, regex)) + log_dieu(LOG_EXIT_SYS, "replace: ", replace, " by: ", regex, " in file: ", str) ; - idmodule[pos] = 1 ; + if (!stralloc_0(&sa)) + log_die_nomem("stralloc") ; - svref = &genalloc_s(sv_alltype,&gasv)[pos] ; + char new[len + sa.len + 1] ; + auto_strings(new, dname, sa.s) ; - id = svref->cname.idcontents, nid = svref->cname.ncontents ; - for (;nid; id += strlen(deps.s + id) + 1, nid--) { + /** do not try to rename the same directory */ + if (strcmp(str, new)) { - char *name = deps.s + id ; + log_trace("rename: ", str, " to: ", new) ; + if (rename(str, new) == -1) + //log_warnusys( "rename: ", str, " to: ", new) ; + log_dieusys(LOG_EXIT_SYS, "rename: ", str, " to: ", new) ; - for (spos = 0 ; spos < genalloc_len(sv_alltype,&gasv);spos++) - if (!strcmp(name,keep.s + genalloc_s(sv_alltype,&gasv)[spos].cname.name)) - idmodule[spos] = 1 ; - } - } + break ; } + } + } + stralloc_free(&sa) ; +} - for (pos = 0 ; pos < genalloc_len(sv_alltype,&gasv); pos++) { - - if (!genalloc_s(sv_alltype,&gasv)[pos].opts[2] || - idmodule[pos]) continue ; - char *n = keep.s + genalloc_s(sv_alltype,&gasv)[pos].cname.name ; - - if (!strcmp(n,bname)) { - - genalloc_s(sv_alltype,&gasv)[pos].srconf = keep.len ; - if (!auto_stra(&tmpenv,version,"/",bname)) log_warn_return(LOG_EXIT_ZERO,"stralloc") ; +static void regex_configure(resolve_service_t *res, ssexec_t *info, char const *path, char const *name) +{ + log_flow() ; - if (!stralloc_catb(&keep,tmpenv.s,strlen(tmpenv.s) + 1)) - log_die_nomem("stralloc") ; - break ; - } - } - stralloc_free(&tmpenv) ; - } + int wstat, r ; + pid_t pid ; + size_t clen = res->regex.configure > 0 ? 1 : 0 ; + size_t pathlen = strlen(path), n ; - svtype = get_svtype_from_file(svname) ; - if (svtype == -1) log_dieu(LOG_EXIT_SYS,"get svtype of: ",svname) ; + stralloc env = STRALLOC_ZERO ; - if (sastr_cmp(&sdir,pbname) == -1) - if (!stralloc_catb(&sdir,pbname,strlen(pbname) + 1)) - log_die_nomem("stralloc") ; + char const *newargv[2 + clen] ; + unsigned int m = 0 ; - if (sastr_cmp(&tmp,pbname) == -1) - if (svtype != TYPE_CLASSIC) - if (!stralloc_catb(&tmp,pbname,strlen(pbname) + 1)) - log_die_nomem("stralloc") ; - } + char pwd[pathlen + 1 + SS_MODULE_CONFIG_DIR_LEN + 1] ; + auto_strings(pwd, path, "/", SS_MODULE_CONFIG_DIR + 1) ; - /** 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) ; + char config_script[pathlen + 1 + SS_MODULE_CONFIG_DIR_LEN + 1 + SS_MODULE_CONFIG_SCRIPT_LEN + 1] ; + auto_strings(config_script, path, "/", SS_MODULE_CONFIG_DIR + 1, "/", SS_MODULE_CONFIG_SCRIPT) ; - list.len-- ; //instance_splitname close the string + r = scan_mode(config_script, S_IFREG) ; + if (r > 0) + { + /** export ssexec_t info value on the environment */ + { + char verbo[UINT_FMT]; + verbo[uid_fmt(verbo, VERBOSITY)] = 0 ; + if (!auto_stra(&env, \ + "MOD_NAME=", name, "\n", \ + "MOD_BASE=", res->sa.s + res->path.home, "\n", \ + "MOD_LIVE=", res->sa.s + res->live.livedir, "\n", \ + "MOD_TREE=", res->sa.s + res->path.tree, "\n", \ + "MOD_SCANDIR=", res->sa.s + res->live.scandir, "\n", \ + "MOD_TREENAME=", res->sa.s + res->treename, "\n", \ + "MOD_OWNER=", res->sa.s + res->ownerstr, "\n", \ + "MOD_COLOR=", info->opt_color ? "1" : "0", "\n", \ + "MOD_VERBOSITY=", verbo, "\n", \ + "MOD_MODULE_DIR=", path, "\n", \ + "MOD_SKEL_DIR=", SS_SKEL_DIR, "\n", \ + "MOD_SERVICE_SYSDIR=", SS_SERVICE_SYSDIR, "\n", \ + "MOD_SERVICE_ADMDIR=", SS_SERVICE_ADMDIR, "\n", \ + "MOD_SERVICE_ADMCONFDIR=", SS_SERVICE_ADMCONFDIR, "\n", \ + "MOD_MODULE_SYSDIR=", SS_MODULE_SYSDIR, "\n", \ + "MOD_MODULE_ADMDIR=", SS_MODULE_ADMDIR, "\n", \ + "MOD_SCRIPT_SYSDIR=", SS_SCRIPT_SYSDIR, "\n", \ + "MOD_USER_DIR=", SS_USER_DIR, "\n", \ + "MOD_SERVICE_USERDIR=", SS_SERVICE_USERDIR, "\n", \ + "MOD_SERVICE_USERCONFDIR=", SS_SERVICE_USERCONFDIR, "\n", \ + "MOD_MODULE_USERDIR=", SS_MODULE_USERDIR, "\n", \ + "MOD_SCRIPT_USERDIR=", SS_SCRIPT_USERDIR, "\n")) + log_dieu(LOG_EXIT_SYS, "append environment variables") ; + } - if (!auto_stra(&list,"-")) - log_die_nomem("stralloc") ; + /** environment is not mandatory */ + if (res->environ.env > 0) + { + stralloc oenv = STRALLOC_ZERO ; + stralloc dst = STRALLOC_ZERO ; + char name[strlen(res->sa.s + res->name) + 2] ; + auto_strings(name, ".", res->sa.s + res->name) ; - alltype->cname.idga = deps.len ; - alltype->cname.nga = 0 ; - for (pos = 0 ;pos < tmp.len ; pos += strlen(tmp.s + pos) + 1) { + if (!env_prepare_for_write(&dst, &oenv, res)) + log_dieu(LOG_EXIT_SYS, "prepare environment") ; - if (!stralloc_catb(&deps,list.s, list.len) || - !stralloc_catb(&deps,tmp.s + pos,strlen(tmp.s + pos) + 1)) - log_die_nomem("stralloc") ; + write_environ(name, oenv.s, dst.s) ; - alltype->cname.nga++ ; - } + /** Reads all files from the directory */ + if (!environ_clean_envfile(&env, dst.s)) + log_dieu(LOG_EXIT_SYS, "read environment") ; - alltype->cname.idcontents = deps.len ; - for (pos = 0 ;pos < sdir.len ; pos += strlen(sdir.s + pos) + 1) { + if (!environ_remove_unexport(&env, &env)) + log_dieu(LOG_EXIT_SYS, "remove exclamation mark from environment variables") ; - if (!stralloc_catb(&deps,list.s, list.len) || - !stralloc_catb(&deps,sdir.s + pos,strlen(sdir.s + pos) + 1)) - log_die_nomem("stralloc") ; + stralloc_free(&oenv) ; + stralloc_free(&dst) ; + } - alltype->cname.ncontents++ ; - } + if (!sastr_split_string_in_nline(&env)) + log_dieu(LOG_EXIT_SYS, "rebuild environment") ; - tmp.len = 0 ; - if (!auto_stra(&tmp,permanent_sdir,SS_MODULE_CONFIG_DIR + 1)) - log_die_nomem("stralloc") ; + n = env_len((const char *const *)environ) + 1 + byte_count(env.s,env.len,'\0') ; + char const *newenv[n + 1] ; - if (rm_rf(tmp.s) < 0) - log_dieusys(LOG_EXIT_SYS,"remove: ",tmp.s) ; + if (!env_merge (newenv, n ,(const char *const *)environ,env_len((const char *const *)environ), env.s, env.len)) + log_dieu(LOG_EXIT_SYS, "build environment") ; - stralloc_free(&sdir) ; - stralloc_free(&list) ; - stralloc_free(&tmp) ; - stralloc_free(&addonsv) ; + if (chdir(pwd) < 0) + log_dieu(LOG_EXIT_SYS, "chdir to: ", pwd) ; - return err ; -} + m = 0 ; + newargv[m++] = config_script ; -/* helper */ + if (res->regex.configure > 0) + newargv[m++] = res->sa.s + res->regex.configure ; -/* 0 filename undefine - * -1 system error - * should return at least 2 meaning :: no file define*/ -int regex_get_file_name(char *filename,char const *str) -{ - log_flow() ; + newargv[m++] = 0 ; - int r ; - size_t pos = 0 ; - stralloc kp = STRALLOC_ZERO ; + log_info("launch script configure of module: ", name) ; - parse_mill_t MILL_GET_COLON = { - .open = ':', .close = ':', - .skip = " \t\r", .skiplen = 3, - .forceclose = 1, - .inner.debug = "get_colon" } ; + pid = child_spawn0(newargv[0], newargv, newenv) ; - r = mill_element(&kp,str,&MILL_GET_COLON,&pos) ; - if (r == -1) goto err ; + if (waitpid_nointr(pid, &wstat, 0) < 0) + log_dieusys(LOG_EXIT_SYS, "wait for: ", config_script) ; - auto_strings(filename,kp.s) ; + if (wstat) + log_dieu(LOG_EXIT_SYS, "run: ", config_script) ; + } - stralloc_free(&kp) ; - return pos ; - err: - stralloc_free(&kp) ; - return -1 ; + stralloc_free(&env) ; } -int regex_get_replace(char *replace, char const *str) +void parse_module(resolve_service_t *res, resolve_service_t *ares, unsigned int *areslen, ssexec_t *info, uint8_t force) { log_flow() ; - int pos = get_len_until(str,'=') ; - if (!pos || pos == -1) return 0 ; - char tmp[pos + 1] ; - memcpy(tmp,str,pos) ; - tmp[pos] = 0 ; - auto_strings(replace,tmp) ; - return 1 ; -} + int r, insta = -1 ; + unsigned int residx = 0 ; + size_t pos = 0, pathlen = 0 ; + char *name = res->sa.s + res->name ; + char *src = res->sa.s + res->path.frontend ; + char path[SS_MAX_PATH_LEN] ; + char ainsta[strlen(name)] ; + stralloc list = STRALLOC_ZERO ; + resolve_wrapper_t_ref wres = 0 ; -int regex_get_regex(char *regex, char const *str) -{ - log_flow() ; + log_trace("parse module: ", name) ; - 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 ; -} + insta = instance_check(name) ; + instance_splitname_to_char(ainsta, name, insta, 0) ; -int regex_replace(stralloc *list,sv_alltype *alltype,char const *svname) -{ - log_flow() ; + size_t prefixlen = strlen(ainsta) ; + size_t len = prefixlen + SS_MAX_SERVICE_NAME ; - int r ; - size_t in = 0, pos, inlen ; + char prefix[len + 1] ; + auto_strings(prefix, ainsta) ; + //prefix[insta] = '-' ; + prefix[insta] = 0 ; - stralloc tmp = STRALLOC_ZERO ; + if (!getuid()) { - for (; in < list->len; in += strlen(list->s + in) + 1) - { - tmp.len = 0 ; - char *str = list->s + in ; - size_t len = strlen(str) ; - char bname[len + 1] ; - char dname[len + 1] ; - if (!ob_basename(bname,str)) log_warnu_return(LOG_EXIT_ZERO,"get basename of: ",str) ; - if (!ob_dirname(dname,str)) log_warnu_return(LOG_EXIT_ZERO,"get dirname of: ",str) ; + auto_strings(path, SS_SERVICE_ADMDIR, name) ; - log_trace("read service file of: ",dname,bname) ; - r = read_svfile(&tmp,bname,dname) ; - if (!r) log_warnusys_return(LOG_EXIT_ZERO,"read file: ",str) ; - if (r == -1) continue ; + } else { - pos = alltype->type.module.start_infiles, inlen = alltype->type.module.end_infiles ; - for (; pos < inlen ; pos += strlen(keep.s + pos) + 1) - { - int all = 0, fpos = 0 ; - char filename[512] = { 0 } ; - char replace[512] = { 0 } ; - char regex[512] = { 0 } ; - char const *line = keep.s + pos ; + if (!parse_module_ownerhome(path)) + log_dieusys(LOG_EXIT_SYS, "unable to find the home directory of the user") ; - 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") ; + pathlen = strlen(path) ; + auto_strings(path + pathlen, SS_SERVICE_USERDIR, name) ; + } - fpos = regex_get_file_name(filename,line) ; + uint8_t conf = res->environ.env_overwrite ; - if (fpos == -1) log_warnu_return(LOG_EXIT_ZERO,"get filename of line: ",line) ; - else if (fpos < 3) all = 1 ; + /** Check the validity of the module directory. + * The frontend file of the module must be located in + * a directory with a name in the format @template_name: + * - frontend file -> scandir@ + * - directory name containing the frontend service file -> @scandir */ + parse_module_check_name(src, name) ; - if (!regex_get_replace(replace,line+fpos)) log_warnu_return(LOG_EXIT_ZERO,"replace string of line: ",line) ; + /** check mandatory directories + * res->frontend/module_name/{configure,service,service@} */ + parse_module_check_dir(src, SS_MODULE_CONFIG_DIR) ; + parse_module_check_dir(src, SS_MODULE_SERVICE) ; + parse_module_check_dir(src, SS_MODULE_SERVICE_INSTANCE) ; - if (!regex_get_regex(regex,line+fpos)) log_warnu_return(LOG_EXIT_ZERO,"regex string of line: ",line) ; + r = scan_mode(path, S_IFDIR) ; + if (r == -1) { + errno = EEXIST ; + log_dieusys(LOG_EXIT_SYS, "conflicting format of: ", path) ; - 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) ; + } else if (!r) { - if (!stralloc_0(&tmp)) - log_warnusys_return(LOG_EXIT_ZERO,"stralloc") ; + if (!hiercopy(src, path)) + log_dieusys(LOG_EXIT_SYS, "copy: ", src, " to: ", path) ; - tmp.len-- ; + } else { - if (!file_write_unsafe(dname,bname,tmp.s,tmp.len)) - log_warnusys_return(LOG_EXIT_ZERO,"write: ",dname,"/","filename") ; - } - } - } - stralloc_free(&tmp) ; + /** Must reconfigure all services of the module */ + if (force < 2) { - return 1 ; -} + log_warn("skip configuration of the module: ", name, " -- already configured") ; + goto deps ; + } -int regex_rename(stralloc *list, int id, unsigned int nid, char const *sdir) -{ - log_flow() ; + if (rm_rf(path) < 0) + log_dieusys (LOG_EXIT_SYS, "remove: ", path) ; - stralloc tmp = STRALLOC_ZERO ; - size_t pos = id, len = nid, in ; + if (!hiercopy(src, path)) + log_dieusys(LOG_EXIT_SYS,"copy: ", src, " to: ", path) ; + } - pos = id, len = nid ; + pathlen = strlen(path) ; + /** remove the original service frontend file inside the copied directory + * to avoid double frontend service file for a same service.*/ + auto_strings(path + pathlen, "/", ainsta) ; - 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) ; + if (unlink(path) < 0) + log_dieusys(LOG_EXIT_ZERO, "unlink: ", path) ; - 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) ; + path[pathlen] = 0 ; - 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") ; + /** contents */ + get_list(&list, path, name, S_IFREG) ; + regex_replace(&list, res) ; - if (!sastr_replace(&tmp,replace,regex)) - log_warnu_return(LOG_EXIT_ZERO,"replace: ",replace," by: ", regex," in file: ",str) ; + /** directories */ + get_list(&list, path, name, S_IFDIR) ; + regex_rename(&list, res, res->regex.directories) ; - if (!stralloc_0(&tmp)) - log_warnu_return(LOG_EXIT_ZERO,"stralloc") ; + /** filename */ + get_list(&list, path, name, S_IFREG) ; + regex_rename(&list, res, res->regex.files) ; - char new[len + tmp.len + 1] ; - auto_strings(new,dname,tmp.s) ; - /** do not try to rename the same directory */ - if (!obstr_equal(str,new)) - { - log_trace("rename: ",str," to: ",new) ; - if (rename(str,new) == -1) - log_warnusys_return(LOG_EXIT_ZERO,"rename: ",str," to: ",new) ; - } - } - } - stralloc_free(&tmp) ; + /** configure script */ + regex_configure(res, info, path, name) ; - return 1 ; -} + deps: -int regex_configure(sv_alltype *alltype,ssexec_t *info, char const *module_dir,char const *module_name,uint8_t conf) -{ - log_flow() ; + list.len = 0 ; - int wstat, r ; - pid_t pid ; - size_t clen = alltype->type.module.configure > 0 ? 1 : 0 ; - size_t module_dirlen = strlen(module_dir), n ; + if (!auto_stra(&list, path)) + log_die_nomem("stralloc") ; - stralloc env = STRALLOC_ZERO ; + char t[list.len] ; - char const *newargv[2 + clen] ; - unsigned int m = 0 ; + sastr_to_char(t, &list) ; - char pwd[module_dirlen + SS_MODULE_CONFIG_DIR_LEN + 1] ; - auto_strings(pwd,module_dir,SS_MODULE_CONFIG_DIR + 1) ; + list.len = 0 ; + char const *exclude[3] = { SS_MODULE_CONFIG_DIR + 1, SS_MODULE_SERVICE_INSTANCE + 1, 0 } ; + if (!sastr_dir_get_recursive(&list, t, exclude, S_IFREG, 1)) + log_dieusys(LOG_EXIT_SYS, "get file(s) of module: ", name) ; - char config_script[module_dirlen + SS_MODULE_CONFIG_DIR_LEN + 1 + SS_MODULE_CONFIG_SCRIPT_LEN + 1] ; - auto_strings(config_script,module_dir,SS_MODULE_CONFIG_DIR + 1,"/",SS_MODULE_CONFIG_SCRIPT) ; + char l[list.len] ; + size_t llen = list.len ; - r = scan_mode(config_script,S_IFREG) ; - if (r > 0) - { - /** export ssexec_t info value on the environment */ - { - char owner[UID_FMT]; - owner[uid_fmt(owner,info->owner)] = 0 ; - char verbo[UINT_FMT]; - verbo[uid_fmt(verbo,VERBOSITY)] = 0 ; - if (!auto_stra(&env, \ - "MOD_NAME=",module_name,"\n", \ - "MOD_BASE=",info->base.s,"\n", \ - "MOD_LIVE=",info->live.s,"\n", \ - "MOD_TREE=",info->tree.s,"\n", \ - "MOD_SCANDIR=",info->scandir.s,"\n", \ - "MOD_TREENAME=",info->treename.s,"\n", \ - "MOD_OWNER=",owner,"\n", \ - "MOD_COLOR=",info->opt_color ? "1" : "0","\n", \ - "MOD_VERBOSITY=",verbo,"\n", \ - "MOD_MODULE_DIR=",module_dir,"\n", \ - "MOD_SKEL_DIR=",SS_SKEL_DIR,"\n", \ - "MOD_SERVICE_SYSDIR=",SS_SERVICE_SYSDIR,"\n", \ - "MOD_SERVICE_ADMDIR=",SS_SERVICE_ADMDIR,"\n", \ - "MOD_SERVICE_ADMCONFDIR=",SS_SERVICE_ADMCONFDIR,"\n", \ - "MOD_MODULE_SYSDIR=",SS_MODULE_SYSDIR,"\n", \ - "MOD_MODULE_ADMDIR=",SS_MODULE_ADMDIR,"\n", \ - "MOD_SCRIPT_SYSDIR=",SS_SCRIPT_SYSDIR,"\n", \ - "MOD_USER_DIR=",SS_USER_DIR,"\n", \ - "MOD_SERVICE_USERDIR=",SS_SERVICE_USERDIR,"\n", \ - "MOD_SERVICE_USERCONFDIR=",SS_SERVICE_USERCONFDIR,"\n", \ - "MOD_MODULE_USERDIR=",SS_MODULE_USERDIR,"\n", \ - "MOD_SCRIPT_USERDIR=",SS_SCRIPT_USERDIR,"\n")) - log_warnu_return(LOG_EXIT_ZERO,"append environment variables") ; - } - /** environment is not mandatory */ - if (alltype->opts[2] > 0) - { - stralloc oenv = STRALLOC_ZERO ; - stralloc name = STRALLOC_ZERO ; - stralloc dst = STRALLOC_ZERO ; + sastr_to_char(l, &list) ; - if (!env_prepare_for_write(&name,&dst,&oenv,alltype,conf)) - return 0 ; + list.len = 0 ; - if (!write_env(name.s,oenv.s,dst.s)) - log_warnu_return(LOG_EXIT_ZERO,"write environment") ; + for (pos = 0 ; pos < llen ; pos += strlen(l + pos) + 1) { - /** Reads all file from the directory */ - if (!environ_clean_envfile(&env,dst.s)) - log_warnu_return(LOG_EXIT_ZERO,"prepare environment") ; + char *dname = l + pos ; + char ainsta[pathlen + SS_MODULE_SERVICE_INSTANCE_LEN + 1 + SS_MAX_SERVICE_NAME + 1] ; + size_t namelen = strlen(dname) ; + char bname[namelen] ; - if (!environ_remove_unexport(&env,&env)) - log_warnu_return(LOG_EXIT_ZERO,"remove exclamation mark from environment variables") ; + if (!ob_basename(bname,dname)) + log_dieu(LOG_EXIT_SYS, "find basename of: ", dname) ; - stralloc_free(&name) ; - stralloc_free(&oenv) ; - stralloc_free(&dst) ; + if (instance_check(bname) > 0) { + auto_strings(ainsta, path, SS_MODULE_SERVICE_INSTANCE, "/", bname) ; + dname = ainsta ; } - if (!sastr_split_string_in_nline(&env)) - log_warnu_return(LOG_EXIT_ZERO,"rebuild environment") ; + if (!sastr_add_string(&list, bname)) + log_die_nomem("stralloc") ; - n = env_len((const char *const *)environ) + 1 + byte_count(env.s,env.len,'\0') ; - char const *newenv[n + 1] ; + if (!strcmp(name, bname)) + log_die(LOG_EXIT_SYS, "cyclic call detected -- ", name, " call ", bname) ; - 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") ; + /** nothing to do with the exit code */ + parse_frontend(dname, ares, areslen, info, force, conf, &residx, path) ; - if (chdir(pwd) < 0) - log_warnusys_return(LOG_EXIT_ZERO,"chdir to: ",pwd) ; + wres = resolve_set_struct(DATA_SERVICE, &ares[residx]) ; - m = 0 ; - newargv[m++] = config_script ; + ares[residx].inmodule = resolve_add_string(wres, prefix - 1) ; + } - if (alltype->type.module.configure > 0) - newargv[m++] = keep.s + alltype->type.module.configure ; + char deps[list.len] ; - newargv[m++] = 0 ; + sastr_to_char(deps, &list) ; - log_info("launch script configure of module: ",module_name) ; + llen = list.len ; - pid = child_spawn0(newargv[0],newargv,newenv) ; + list.len = 0 ; - if (waitpid_nointr(pid,&wstat, 0) < 0) - log_warnusys_return(LOG_EXIT_ZERO,"wait for: ",config_script) ; + /* rebuild the dependencies list incorporating the services defined inside + * the module. */ - if (wstat) - log_warnu_return(LOG_EXIT_ZERO,"run: ",config_script) ; - } + if (res->dependencies.ndepends) + if (!sastr_clean_string(&list, res->sa.s + res->dependencies.depends)) + log_dieu(LOG_EXIT_SYS, "clean string") ; - stralloc_free(&env) ; + for (pos = 0 ; pos < llen ; pos += strlen(deps + pos) + 1) + if (!sastr_add_string(&list, deps + pos)) + log_die_nomem("stralloc") ; - return 1 ; + wres = resolve_set_struct(DATA_SERVICE, res) ; + + res->dependencies.depends = parse_compute_list(wres, &list, &res->dependencies.ndepends, 0) ; + + free(wres) ; + stralloc_free(&list) ; } diff --git a/src/lib66/parse/parse_parentheses.c b/src/lib66/parse/parse_parentheses.c new file mode 100644 index 00000000..fc3bbd6c --- /dev/null +++ b/src/lib66/parse/parse_parentheses.c @@ -0,0 +1,87 @@ +/* + * parser_parentheses.c + * + * Copyright (c) 2018-2022 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 <string.h> +#include <stdint.h> + +#include <oblibs/string.h> + +#include <66/parser.h> + +static char parse_char_next(char const *s, size_t *pos) +{ + char c = 0 ; + size_t slen = strlen(s) ; + if (*pos > slen) return -1 ; + c = s[*pos] ; + (*pos)++ ; + return c ; +} + +int parse_parentheses(char *store, char const *str, size_t *pos) +{ + int open = 0, close = 0 ; + uint8_t parentheses = 1 ; + size_t o = 0, slen = strlen(str) ; + + open = get_sep_before(str, '=', '(') ; + if (open <= 0) + return 0 ; + close = get_sep_before(str, '(', ')') ; + if (close < 0) + return 0 ; + open += get_len_until(str + open + 1, '(') ; // +1 remove '=' + open += 2 ; // +2 remove '(' + + + char line[slen + 1] ; + auto_strings(line, str + open) ; + size_t len = strlen(line) ; + + while(parentheses && o < len) { + + char c = parse_char_next(line, &o) ; + + switch(c) { + + case '(': + parentheses++ ; + break ; + case ')': + parentheses-- ; + break ; + case -1: + return 0 ; + default: + break ; + } + } + + if (parentheses) + return 0 ; + + (*pos) = open + len ; + + open = get_len_until(str, '\n') ; + if (open < 1) + open = 0 ; + + (*pos) = open + 1 ; // +1 remove '\n' + + len = len - (len - o) - 1 ; + memcpy(store, line, len) ; + store[len] = 0 ; + + return 1 ; +} diff --git a/src/lib66/parse/parse_section.c b/src/lib66/parse/parse_section.c new file mode 100644 index 00000000..014c5abd --- /dev/null +++ b/src/lib66/parse/parse_section.c @@ -0,0 +1,72 @@ +/* + * parse_section.c + * + * Copyright (c) 2018-2022 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 <string.h> + +#include <oblibs/mill.h> +#include <oblibs/log.h> +#include <oblibs/string.h> + +#include <skalibs/stralloc.h> + +#include <66/parser.h> +#include <66/enum.h> + +int parse_section(stralloc *secname, char const *str, size_t *pos) +{ + int id = -1 ; + size_t len = strlen(str) ; + size_t newpos = 0, found = 0 ; + + stralloc tmp = STRALLOC_ZERO ; + + while ((*pos) < len) { + tmp.len = 0 ; + newpos = 0 ; + + if (mill_element(&tmp, str + (*pos), &MILL_GET_SECTION_NAME, &newpos) == -1) + goto end ; + + if (tmp.len) { + if (!stralloc_0(&tmp)) + return -1 ; + + found = 1 ; + + // check the validity of the section name + id = get_enum_by_key(tmp.s) ; + + if (id < 0) { + log_warn("invalid section name: ", tmp.s, " -- ignoring it") ; + newpos-- ; // " retrieve the last ']'" + // find the start of the section and pass the next line + id = get_len_until(str + (newpos - tmp.len), '\n') ; + newpos = newpos - tmp.len + id + 1 ; + found = 0 ; + } + } + + (*pos) += newpos ; + + if (found) break ; + } + + if (found) + if (!stralloc_catb(secname, tmp.s, strlen(tmp.s) + 1)) + return -1 ; + + end: + stralloc_free(&tmp) ; + return found ? 1 : 0 ; +} diff --git a/src/lib66/parse/parse_split_from_section.c b/src/lib66/parse/parse_split_from_section.c new file mode 100644 index 00000000..f1ac67b6 --- /dev/null +++ b/src/lib66/parse/parse_split_from_section.c @@ -0,0 +1,223 @@ +/* + * parse_split_from_section.c + * + * Copyright (c) 2018-2022 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 <string.h> +#include <sys/types.h> + +#include <oblibs/log.h> +#include <oblibs/sastr.h> +#include <oblibs/string.h> +#include <oblibs/mill.h> + +#include <skalibs/stralloc.h> + +#include <66/parser.h> +#include <66/resolve.h> +#include <66/enum.h> + +static ssize_t parse_get_previous_element(stralloc *sa, size_t where) +{ + size_t n = sastr_nelement(sa) ; + n-- ; + if ((n - where) < n) + return -1 ; + + return sastr_find_element_byid(sa,n - where) ; +} + +/* * + * For now the ability to comment an entire section when + * commenting the section name is not available anymore + * */ +int parse_split_from_section(resolve_service_t *res, stralloc *secname, char *str, char const *svname) +{ + log_flow() ; + + int e = 0, r = 0, found = 0, skip = 0 ; + + key_all_t const *list = total_list ; + stralloc sakey = STRALLOC_ZERO ; + + // cpos -> current, ipos -> idx pos, tpos -> temporary pos, end -> end the parse process + size_t len = strlen(str), cpos = 0, ipos = 0, tpos = 0, end = 0 ; + char tline[len + 1] ; + char store[len + 1] ; + char *line ; + + // find the name of the current section + ssize_t previous_sec = parse_get_previous_element(secname, 0) ; + + if (previous_sec == -1) { + log_warn("get previous section") ; + goto err ; + } + + int id = get_enum_by_key(secname->s + previous_sec) ; + + if (id < 0) { + log_warn("invalid section name: ", secname->s + previous_sec, " for service: ", svname) ; + goto err ; + } + + log_trace("parsing section: ", secname->s + previous_sec) ; + + if (!strcmp(secname->s + previous_sec, enum_str_section[SECTION_ENV])) { + str[strlen(str)] = 0 ; + + if (!parse_store_g(res, str, SECTION_ENV, KEY_ENVIRON_ENVAL)) { + log_warnu("store resolve file of: ", svname) ; + goto err ; + } + + goto end ; + } + + while(cpos < len) { + + skip = 0 ; + ipos = 0 ; + tpos = 0 ; + end = 0 ; + sakey.len = 0 ; + line = (char *)str + cpos ; // (char *) shut up compiler + + /** comment must be the first character found + * at the begin of the line */ + if (line[tpos] == '#') { + cpos += get_len_until(line, '\n') + 1 ; + continue ; + } + + // empty line or no more key=value? + while (get_sep_before(line, '=', '\n') < 1){ + + // Try to see if it's an empty line. + r = get_len_until(line, '\n') ; + if (r < 0) { + // end of string + end++ ; + break ; + } + + cpos += r + 1 ; // +1 to remove '\n' + + if (cpos >= len) { + // end of string + end++ ; + break ; + } + + line = (char *)str + cpos ; + } + + if (end) + break ; + + // get a cleaned key string + wild_zero_all(&MILL_GET_KEY) ; + r = mill_element(&sakey, line, &MILL_GET_KEY, &tpos) ; + if (r < 1) { + log_warnu("get key at frontend service file of service: ", svname, " from line: ", line, " -- please make a bug report") ; + goto err ; + } else if (!r || tpos + cpos >= len) { + // '=' was not find or end of string? + break ; + } + + // copy the string to parse + auto_strings(tline, line) ; + + tpos = 0 ; + + // loop around all keys for the section + while (*total_list[id].list[ipos].name) { + + found = 0 ; + + // look for a valid key name + if (*list[id].list[ipos].name && !strcmp(sakey.s, *list[id].list[ipos].name)) { + + found = 1 ; + + log_trace("parsing key: ", get_key_by_key_all(id, ipos)) ; + + switch(list[id].list[ipos].expected) { + + case EXPECT_QUOTE: + + r = get_len_until(tline, '\n') ; + + if (r >= 0) + /** user migth forgot to close the double-quotes. + * so, only keep the line and not the complete string + * +1 for the parse_line_g which search for the '\n' character */ + tline[r + 1] = 0 ; + + wild_zero_all(&MILL_GET_DOUBLE_QUOTE) ; + if (!parse_line_g(store, &MILL_GET_DOUBLE_QUOTE, tline, &tpos)) + parse_error_return(0, 6, id, ipos) ; + + break ; + + case EXPECT_BRACKET: + + if (!parse_parentheses(store, tline, &tpos)) + parse_error_return(0, 6, id, ipos) ; + + break ; + + case EXPECT_LINE: + case EXPECT_UINT: + case EXPECT_SLASH: + + wild_zero_all(&MILL_GET_VALUE) ; + if (!parse_line_g(store, &MILL_GET_VALUE, tline, &tpos)) + parse_error_return(0, 6, id, ipos) ; + + break ; + + default: + return 0 ; + } + } + + cpos += tpos ; + + if (found) { + + if (!parse_store_g(res, store, id, ipos)) { + log_warnu("store resolve file of: ", svname) ; + goto err ; + } ; + + break ; + } + + ipos++ ; + } + + if (!found && r >= 0) { + log_warn("unknown key: ", sakey.s," : in section: ", secname->s + previous_sec, " -- ignoring it") ; + tpos = get_len_until(line, '\n') ; + cpos += tpos + 1 ; + } + } + end: + + e = 1 ; + + err: + stralloc_free(&sakey) ; + return e ; +} diff --git a/src/lib66/parse/parse_store_environ.c b/src/lib66/parse/parse_store_environ.c new file mode 100644 index 00000000..2f4d644f --- /dev/null +++ b/src/lib66/parse/parse_store_environ.c @@ -0,0 +1,66 @@ +/* + * parse_store_environ.c + * + * Copyright (c) 2018-2022 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 <stdlib.h> //free + +#include <oblibs/string.h> +#include <oblibs/log.h> + +#include <skalibs/stralloc.h> + +#include <66/parser.h> +#include <66/resolve.h> +#include <66/enum.h> +#include <66/utils.h> +#include <66/environ.h> + +#include <stdio.h> + +int parse_store_environ(resolve_service_t *res, char *store, int idsec, int idkey) +{ + int e = 0 ; + stralloc sa = STRALLOC_ZERO ; + resolve_wrapper_t_ref wres = resolve_set_struct(DATA_SERVICE, res) ; + + switch(idkey) { + + case KEY_ENVIRON_ENVAL: + + if (!auto_stra(&sa, store)) + goto err ; + + if (!env_clean_with_comment(&sa)) + log_warnu_return(LOG_EXIT_ZERO,"clean environment value") ; + + res->environ.env = resolve_add_string(wres, sa.s) ; + + sa.len = 0 ; + if (!env_resolve_conf(&sa, res->sa.s + res->name, MYUID)) + goto err ; + + res->environ.envdir = resolve_add_string(wres, sa.s) ; + + break ; + + default: + log_warn_return(LOG_EXIT_ZERO, "unknown key: ", get_key_by_key_all(idsec, idkey)) ; + } + + e = 1 ; + + err : + stralloc_free(&sa) ; + free(wres) ; + return e ; +} diff --git a/src/lib66/parse/parse_store_g.c b/src/lib66/parse/parse_store_g.c new file mode 100644 index 00000000..f0a2a770 --- /dev/null +++ b/src/lib66/parse/parse_store_g.c @@ -0,0 +1,67 @@ +/* + * parse_store_g.c + * + * Copyright (c) 2018-2022 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 <oblibs/log.h> + +#include <66/parser.h> +#include <66/resolve.h> +#include <66/enum.h> + +int parse_store_g(resolve_service_t *res, char *store, int idsec, int idkey) +{ + log_trace("storing key: ", get_key_by_key_all(idsec, idkey)) ; + + switch(idsec) { + + + case SECTION_MAIN: + + if (!parse_store_main(res, store, idsec, idkey)) + log_warnu_return(LOG_EXIT_ZERO, "store value of section: ", enum_str_section[SECTION_MAIN]); + + break ; + + case SECTION_START: + case SECTION_STOP: + + if (!parse_store_start_stop(res, store, idsec, idkey)) + log_warnu_return(LOG_EXIT_ZERO, "store value of section: ", enum_str_section[SECTION_START]); + + break ; + + case SECTION_LOG: + + if (!parse_store_logger(res, store, idsec, idkey)) + log_warnu_return(LOG_EXIT_ZERO, "store value of section: ", enum_str_section[SECTION_LOG]); + + + break ; + + case SECTION_ENV: + + if (!parse_store_environ(res, store, idsec, idkey)) + log_warnu_return(LOG_EXIT_ZERO, "store value of section: ", enum_str_section[SECTION_ENV]); + + break ; + + case SECTION_REGEX: + + if (!parse_store_regex(res, store, idsec, idkey)) + log_warnu_return(LOG_EXIT_ZERO, "store value of section: ", enum_str_section[SECTION_REGEX]); + + break ; + } + + return 1 ; +} diff --git a/src/lib66/parse/parse_store_logger.c b/src/lib66/parse/parse_store_logger.c new file mode 100644 index 00000000..9dad2be5 --- /dev/null +++ b/src/lib66/parse/parse_store_logger.c @@ -0,0 +1,122 @@ +/* + * parse_store_logger.c + * + * Copyright (c) 2018-2022 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 <stdlib.h> //free + +#include <oblibs/log.h> + +#include <skalibs/types.h> + +#include <66/parser.h> +#include <66/resolve.h> +#include <66/service.h> +#include <66/enum.h> + +int parse_store_logger(resolve_service_t *res, char *store, int idsec, int idkey) +{ + int r = 0, e = 0 ; + stralloc sa = STRALLOC_ZERO ; + resolve_wrapper_t_ref wres = resolve_set_struct(DATA_SERVICE, res) ; + + switch(idkey) { + + case KEY_LOGGER_BUILD: + + if (!parse_store_start_stop(res, store, idsec, KEY_STARTSTOP_BUILD)) + goto err ; + + break ; + + case KEY_LOGGER_RUNAS: + + if (!parse_store_start_stop(res, store, idsec, KEY_STARTSTOP_RUNAS)) + goto err ; + + break ; + + case KEY_LOGGER_SHEBANG: + + if (!parse_store_start_stop(res, store, idsec, KEY_STARTSTOP_SHEBANG)) + goto err ; + + break ; + + case KEY_LOGGER_EXEC: + + if (!parse_store_start_stop(res, store, idsec, KEY_STARTSTOP_EXEC)) + goto err ; + + break ; + + case KEY_LOGGER_T_KILL: + + if (!uint320_scan(store, &res->logger.execute.timeout.kill)) + parse_error_return(0, 3, idsec, idkey) ; + + break ; + + case KEY_LOGGER_T_FINISH: + + if (!uint320_scan(store, &res->logger.execute.timeout.finish)) + parse_error_return(0, 3, idsec, idkey) ; + + break ; + + case KEY_LOGGER_DESTINATION: + + if (!parse_clean_line(store)) + parse_error_return(0, 8, idsec, idkey) ; + + if (store[0] != '/') + parse_error_return(0, 4, idsec, idkey) ; + + res->logger.destination = resolve_add_string(wres, store) ; + + break ; + + case KEY_LOGGER_BACKUP: + + if (!uint320_scan(store, &res->logger.backup)) + parse_error_return(0, 3, idsec, idkey) ; + + break ; + + case KEY_LOGGER_MAXSIZE: + + if (!uint320_scan(store, &res->logger.maxsize)) + parse_error_return(0, 3, idsec, idkey) ; + + break ; + + case KEY_LOGGER_TIMESTP: + + r = get_enum_by_key(store) ; + if (r == -1) + parse_error_return(0, 0, idsec, idkey) ; + + res->logger.timestamp = (uint32_t)r ; + + break ; + + default: + log_warn_return(LOG_EXIT_ZERO, "unknown key: ", get_key_by_key_all(idsec, idkey)) ; + } + + e = 1 ; + + err : + stralloc_free(&sa) ; + free(wres) ; + return e ; +} diff --git a/src/lib66/parse/parse_store_main.c b/src/lib66/parse/parse_store_main.c new file mode 100644 index 00000000..29331239 --- /dev/null +++ b/src/lib66/parse/parse_store_main.c @@ -0,0 +1,370 @@ +/* + * parse_store_main.c + * + * Copyright (c) 2018-2022 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 <string.h> +#include <stdint.h> +#include <stdlib.h> //free +#include <pwd.h> + +#include <oblibs/string.h> +#include <oblibs/sastr.h> +#include <oblibs/log.h> +#include <oblibs/directory.h> +#include <oblibs/types.h> + +#include <skalibs/stralloc.h> +#include <skalibs/types.h> +#include <skalibs/sig.h> + +#include <66/parser.h> +#include <66/resolve.h> +#include <66/constants.h> +#include <66/service.h> +#include <66/enum.h> +#include <66/utils.h> + +int parse_store_main(resolve_service_t *res, char *store, int idsec, int idkey) +{ + int r = 0, e = 0 ; + size_t pos = 0 ; + stralloc sa = STRALLOC_ZERO ; + resolve_wrapper_t_ref wres = resolve_set_struct(DATA_SERVICE, res) ; + + switch(idkey) { + + case KEY_MAIN_DESCRIPTION: + + if (!parse_clean_quotes(store)) + parse_error_return(0, 8, idsec, idkey) ; + + res->description = resolve_add_string(wres, store) ; + + break ; + + case KEY_MAIN_VERSION: + + if (!parse_clean_line(store)) + parse_error_return(0, 8, idsec, idkey) ; + + if (!auto_stra(&sa, store)) + goto err ; + + r = version_scan(&sa, store, SS_CONFIG_VERSION_NDOT) ; + if (r == -1) + goto err ; + + if (!r) + parse_error_return(0, 0, idsec, idkey) ; + + res->version = resolve_add_string(wres, sa.s) ; + + break ; + + case KEY_MAIN_TYPE: + + if (!parse_clean_line(store)) + parse_error_return(0, 8, idsec, idkey) ; + + if (!strcmp(store, "longrun")) { + log_1_warn("deprecated type longrun -- convert it automatically to classic type") ; + res->type = 0 ; + break ; + } + + r = get_enum_by_key(store) ; + if (r == -1) + parse_error_return(0, 0, idsec, idkey) ; + + res->type = (uint32_t)r ; + + break ; + + case KEY_MAIN_NOTIFY: + + parse_error_type(res->type,ENUM_KEY_SECTION_MAIN, idkey) ; + + if (!uint320_scan(store, &res->notify)) + parse_error_return(0, 3, idsec, idkey) ; + + if (res->notify < 3) + parse_error_return(0, 0, idsec, idkey) ; + + break ; + + case KEY_MAIN_DEATH: + + + if (!uint320_scan(store, &res->maxdeath)) + parse_error_return(0, 3, idsec, idkey) ; + + break ; + + case KEY_MAIN_FLAGS: + + parse_error_type(res->type,ENUM_KEY_SECTION_MAIN, idkey) ; + + if (!parse_clean_list(&sa, store)) + parse_error_return(0, 8, idsec, idkey) ; + + { + pos = 0 ; + FOREACH_SASTR(&sa, pos) { + + r = get_enum_by_key_one(sa.s + pos, ENUM_FLAGS) ; + + if (r == -1) + parse_error_return(0, 0, idsec, idkey) ; + + if (r == FLAGS_DOWN) + res->execute.down = 1 ;/**0 means not enabled*/ + + if (r == FLAGS_EARLIER) + res->earlier = 1 ;/**0 means not enabled*/ + } + } + + break ; + + case KEY_MAIN_SIGNAL: + + parse_error_type(res->type,ENUM_KEY_SECTION_MAIN, idkey) ; + + if (!parse_clean_line(store)) + parse_error_return(0, 8, idsec, idkey) ; + + int t = 0 ; + if (!sig0_scan(store, &t)) + parse_error_return(0, 3, idsec, idkey) ; + + res->execute.downsignal = (uint32_t)t ; + + break ; + + case KEY_MAIN_T_KILL: + + parse_error_type(res->type,ENUM_KEY_SECTION_MAIN, idkey) ; + + if (!uint320_scan(store, &res->execute.timeout.kill)) + parse_error_return(0, 3, idsec, idkey) ; + + break ; + + case KEY_MAIN_T_FINISH: + + parse_error_type(res->type,ENUM_KEY_SECTION_MAIN, idkey) ; + + if (!uint320_scan(store, &res->execute.timeout.finish)) + parse_error_return(0, 3, idsec, idkey) ; + + break ; + + case KEY_MAIN_T_UP: + + parse_error_type(res->type,ENUM_KEY_SECTION_MAIN, idkey) ; + + if (!uint320_scan(store, &res->execute.timeout.up)) + parse_error_return(0, 3, idsec, idkey) ; + + break ; + + case KEY_MAIN_T_DOWN: + + parse_error_type(res->type,ENUM_KEY_SECTION_MAIN, idkey) ; + + if (!uint320_scan(store, &res->execute.timeout.down)) + parse_error_return(0, 3, idsec, idkey) ; + + break ; + + case KEY_MAIN_HIERCOPY: + + if (res->type == TYPE_BUNDLE) + log_warn_return(LOG_EXIT_ONE,"key: ", get_key_by_enum(ENUM_KEY_SECTION_MAIN, idkey), ": is not valid for type ", get_key_by_enum(ENUM_TYPE, res->type), " -- ignoring it") ; + + if (!parse_clean_list(&sa, store)) + parse_error_return(0, 8, idsec, idkey) ; + { + size_t len = sa.len ; + + char t[len + 1] ; + + sastr_to_char(t, &sa) ; + + sa.len = 0 ; + pos = 0 ; + + for (; pos < len ; pos += strlen(t + pos) + 1) { + if (!auto_stra(&sa, t + pos, " ")) + goto err ; + } + } + sa.len-- ; + if (!stralloc_0(&sa)) + goto err ; + + res->hiercopy = resolve_add_string(wres, sa.s) ; + + break ; + + case KEY_MAIN_OPTIONS: + + if (res->type == TYPE_BUNDLE) + log_warn_return(LOG_EXIT_ONE,"key: ", get_key_by_enum(ENUM_KEY_SECTION_MAIN, idkey), ": is not valid for type ", get_key_by_enum(ENUM_TYPE, res->type), " -- ignoring it") ; + + if (!parse_clean_list(&sa, store)) + parse_error_return(0, 8, idsec, idkey) ; + { + pos = 0 ; + FOREACH_SASTR(&sa, pos) { + + uint8_t reverse = sa.s[pos] == '!' ? 1 : 0 ; + + r = get_enum_by_key(sa.s + pos + reverse) ; + + if (r == -1) + parse_error_return(0, 0, idsec, idkey) ; + + /** do no set a logger by default */ + if (reverse && r == OPTS_LOGGER) + res->logger.want = 0 ; + + if (r == OPTS_ENVIR) + log_warn("options: env is deprecated -- simply set an [environment] section") ; + } + } + + break ; + + case KEY_MAIN_USER: + + if (!parse_clean_list(&sa, store)) + parse_error_return(0, 8, idsec, idkey) ; + + { + uid_t user[256] ; + memset(user, 0, 256*sizeof(uid_t)) ; + + uid_t owner = MYUID ; + if (!owner) { + + if (sastr_find(&sa, "root") == -1) + log_warnu_return(LOG_EXIT_ZERO, "use the service -- permission denied") ; + } + /** special case, we don't know which user want to use + * the service, we need a general name to allow the current owner + * of the process. The term "user" is took here to allow him */ + ssize_t p = sastr_cmp(&sa, "user") ; + size_t len = sa.len ; + pos = 0 ; + + char t[len + 1] ; + + sastr_to_char(t, &sa) ; + + sa.len = 0 ; + + for (; pos < len ; pos += strlen(t + pos) + 1) { + + if (pos == (size_t)p) { + + struct passwd *pw = getpwuid(owner); + if (!pw) { + + if (!errno) errno = ESRCH ; + log_warnu_return(LOG_EXIT_ZERO,"get user name") ; + } + + if (!scan_uidlist(pw->pw_name, user)) + parse_error_return(0, 0, idsec, idkey) ; + + if (!auto_stra(&sa, pw->pw_name, " ")) + log_warnu_return(LOG_EXIT_ZERO, "stralloc") ; + + continue ; + } + + if (!scan_uidlist(t + pos, user)) + parse_error_return(0, 0, idsec, idkey) ; + + if (!auto_stra(&sa, t + pos, " ")) + log_warnu_return(LOG_EXIT_ZERO, "stralloc") ; + + } + uid_t nb = user[0] ; + if (p == -1 && owner) { + + int e = 0 ; + for (int i = 1; i < nb+1; i++) { + if (user[i] == owner) { + e = 1 ; + break ; + } + } + if (!e) + log_warnu_return(LOG_EXIT_ZERO,"use the service -- permission denied") ; + } + } + + res->user = resolve_add_string(wres, sa.s) ; + + break ; + + case KEY_MAIN_DEPENDS: + + if (!parse_clean_list(&sa, store)) + parse_error_return(0, 8, idsec, idkey) ; + + res->dependencies.depends = parse_compute_list(wres, &sa, &res->dependencies.ndepends, 0) ; + + break ; + + case KEY_MAIN_REQUIREDBY: + + if (!parse_clean_list(&sa, store)) + parse_error_return(0, 8, idsec, idkey) ; + + res->dependencies.requiredby = parse_compute_list(wres, &sa, &res->dependencies.nrequiredby, 0) ; + + break ; + + case KEY_MAIN_OPTSDEPS: + + if (!parse_clean_list(&sa, store)) + parse_error_return(0, 8, idsec, idkey) ; + + res->dependencies.optsdeps = parse_compute_list(wres, &sa, &res->dependencies.noptsdeps, 1) ; + + break ; + + case KEY_MAIN_INTREE: + + if (!parse_clean_line(store)) + parse_error_return(0, 8, idsec, idkey) ; + + res->intree = resolve_add_string(wres, store) ; + + break ; + + default: + log_warn_return(LOG_EXIT_ZERO, "unknown key: ", get_key_by_key_all(idsec, idkey)) ; + } + + e = 1 ; + + err : + stralloc_free(&sa) ; + free(wres) ; + return e ; + +} diff --git a/src/lib66/parse/parse_store_regex.c b/src/lib66/parse/parse_store_regex.c new file mode 100644 index 00000000..253378c4 --- /dev/null +++ b/src/lib66/parse/parse_store_regex.c @@ -0,0 +1,78 @@ +/* + * parse_store_regex.c + * + * Copyright (c) 2018-2022 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 <stdlib.h> //free + +#include <oblibs/log.h> +#include <oblibs/sastr.h> + +#include <skalibs/stralloc.h> + +#include <66/parser.h> +#include <66/resolve.h> +#include <66/enum.h> + +int parse_store_regex(resolve_service_t *res, char *store, int idsec, int idkey) +{ + log_flow() ; + + stralloc sa = STRALLOC_ZERO ; + resolve_wrapper_t_ref wres = resolve_set_struct(DATA_SERVICE, res) ; + + switch(idkey) { + + case KEY_REGEX_CONFIGURE: + + if (!parse_clean_quotes(store)) + parse_error_return(0, 8, idsec, idkey) ; + + res->regex.configure = resolve_add_string(wres, store) ; + + break ; + + case KEY_REGEX_DIRECTORIES: + + if (!parse_clean_list(&sa, store)) + parse_error_return(0, 8, idsec, idkey) ; + + res->regex.directories = parse_compute_list(wres, &sa, &res->regex.ndirectories, 0) ; + + break ; + + case KEY_REGEX_FILES: + + if (!parse_clean_list(&sa, store)) + parse_error_return(0, 8, idsec, idkey) ; + + res->regex.files = parse_compute_list(wres, &sa, &res->regex.nfiles, 0) ; + + break ; + + case KEY_REGEX_INFILES: + + if (!parse_clean_list(&sa, store)) + parse_error_return(0, 8, idsec, idkey) ; + + res->regex.infiles = parse_compute_list(wres, &sa, &res->regex.ninfiles, 0) ; + + break ; + + default: + log_warn_return(LOG_EXIT_ZERO, "unknown key: ", get_key_by_key_all(idsec, idkey)) ; + } + + stralloc_free(&sa) ; + free(wres) ; + return 1 ; +} diff --git a/src/lib66/parse/parse_store_start_stop.c b/src/lib66/parse/parse_store_start_stop.c new file mode 100644 index 00000000..72d9cb9f --- /dev/null +++ b/src/lib66/parse/parse_store_start_stop.c @@ -0,0 +1,105 @@ +/* + * parse_store_start_stop.c + * + * Copyright (c) 2018-2022 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 <stdlib.h> //free + +#include <oblibs/log.h> + +#include <skalibs/stralloc.h> + +#include <66/parser.h> +#include <66/resolve.h> +#include <66/service.h> +#include <66/enum.h> + +int parse_store_start_stop(resolve_service_t *res, char *store, int idsec, int idkey) +{ + int e = 0 ; + stralloc sa = STRALLOC_ZERO ; + resolve_wrapper_t_ref wres = resolve_set_struct(DATA_SERVICE, res) ; + + switch(idkey) { + + case KEY_STARTSTOP_BUILD: + + if (!parse_clean_line(store)) + parse_error_return(0, 8, idsec, idkey) ; + + if (idsec == SECTION_START) + res->execute.run.build = resolve_add_string(wres, store) ; + else if (idsec == SECTION_STOP) + res->execute.finish.build = resolve_add_string(wres, store) ; + else if (idsec == SECTION_LOG) + res->logger.execute.run.build = resolve_add_string(wres, store) ; + + break ; + + case KEY_STARTSTOP_RUNAS: + + if (!parse_clean_line(store)) + parse_error_return(0, 8, idsec, idkey) ; + + if (!parse_clean_runas(store, idsec, idkey)) + goto err ; + + if (idsec == SECTION_START) + res->execute.run.runas = resolve_add_string(wres, store) ; + else if (idsec == SECTION_STOP) + res->execute.finish.runas = resolve_add_string(wres, store) ; + else if (idsec == SECTION_LOG) + res->logger.execute.run.runas = resolve_add_string(wres, store) ; + + break ; + + case KEY_STARTSTOP_SHEBANG: + + log_1_warn("deprecated key @shebang -- define your complete shebang directly inside your @execute key field") ; + + if (!parse_clean_quotes(store)) + parse_error_return(0, 8, idsec, idkey) ; + + if (store[0] != '/') + parse_error_return(0, 4, idsec, idkey) ; + + if (idsec == SECTION_START) + res->execute.run.shebang = resolve_add_string(wres, store) ; + else if (idsec == SECTION_STOP) + res->execute.finish.shebang = resolve_add_string(wres, store) ; + else if (idsec == SECTION_LOG) + res->logger.execute.run.shebang = resolve_add_string(wres, store) ; + + break ; + + case KEY_STARTSTOP_EXEC: + + if (idsec == SECTION_START) + res->execute.run.run_user = resolve_add_string(wres, store) ; + else if (idsec == SECTION_STOP) + res->execute.finish.run_user = resolve_add_string(wres, store) ; + else if (idsec == SECTION_LOG) + res->logger.execute.run.run_user = resolve_add_string(wres, store) ; + + break ; + + default: + log_warn_return(LOG_EXIT_ZERO, "unknown key: ", get_key_by_key_all(idsec, idkey)) ; + } + + e = 1 ; + + err : + stralloc_free(&sa) ; + free(wres) ; + return e ; +} -- GitLab