/* * 66-parser.c * * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org> * * All rights reserved. * * This file is part of Obarun. It is subject to the license terms in * the LICENSE file found in the top-level directory of this * distribution. * This file may not be copied, modified, propagated, or distributed * except according to the terms contained in the LICENSE file./ */ #include <stddef.h> #include <stdlib.h> #include <errno.h> #include <stdint.h> #include <oblibs/log.h> #include <oblibs/files.h> #include <oblibs/obgetopt.h> #include <oblibs/types.h> #include <oblibs/directory.h> #include <oblibs/string.h> #include <oblibs/sastr.h> #include <skalibs/stralloc.h> #include <skalibs/djbunix.h> #include <66/utils.h> #include <66/parser.h> #include <66/constants.h> #define USAGE "66-parser [ -h ] [ -z ] [ -v verbosity ] [ -f ] [ -I ] service destination" static inline void info_help (void) { DEFAULT_MSG = 0 ; static char const *help = "\n" "options :\n" " -h: print this help\n" " -z: use color\n" " -v: increase/decrease verbosity\n" " -f: force to overwrite existing destination\n" " -I: do not import modified configuration files from previous version\n" ; log_info(USAGE,"\n",help) ; } static void check_dir(char const *dir,uint8_t force,int main) { log_flow() ; int r ; r = scan_mode(dir,S_IFDIR) ; if (r < 0){ errno = ENOTDIR ; log_diesys(LOG_EXIT_SYS,"conflicting format of: ",dir) ; } if (r && force && main) { if ((rm_rf(dir) < 0) || !r ) log_dieusys(LOG_EXIT_SYS,"sanitize directory: ",dir) ; r = 0 ; } else if (r && !force && main) log_die(LOG_EXIT_SYS,"destination: ",dir," already exist") ; if (!r) if (!dir_create_parent(dir, 0755)) log_dieusys(LOG_EXIT_SYS,"create: ",dir) ; } int main(int argc, char const *const *argv,char const *const *envp) { int ista ; stralloc src = STRALLOC_ZERO ; stralloc dst = STRALLOC_ZERO ; stralloc insta = STRALLOC_ZERO ; sv_alltype service = SV_ALLTYPE_ZERO ; size_t srcdirlen, namelen ; char const *dir ; char const *sv ; char name[4095+1] ; char srcdir[4095+1] ; unsigned int type ; uint8_t force = 0 , conf = 0 ; log_color = &log_color_disable ; PROG = "66-parser" ; { subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { int opt = getopt_args(argc,argv, ">hv:fcCzI", &l) ; if (opt == -1) break ; if (opt == -2) log_die(LOG_EXIT_USER,"options must be set first") ; switch (opt) { case 'h' : info_help(); return 0 ; case 'v' : if (!uint0_scan(l.arg, &VERBOSITY)) log_usage(USAGE) ; break ; case 'f' : force = 1 ; break ; case 'c' : log_1_warn("deprecated option -- ignoring") ; break ; case 'm' : log_1_warn("deprecated option -- ignoring") ; break ; case 'C' : log_1_warn("deprecated option -- ignoring") ; break ; case 'I' : conf = 1 ; break ; case 'z' : log_color = !isatty(1) ? &log_color_disable : &log_color_enable ; break ; default : log_usage(USAGE) ; } } argc -= l.ind ; argv += l.ind ; } if (argc < 2) log_usage(USAGE) ; sv = argv[0] ; dir = argv[1] ; if (dir[0] != '/') log_die(LOG_EXIT_USER, "directory: ",dir," must be an absolute path") ; if (sv[0] != '/') log_die(LOG_EXIT_USER, "service: ",sv," must be an absolute path") ; if (!ob_basename(name,sv)) log_dieu(LOG_EXIT_SYS,"set name"); namelen = strlen(name) ; if (!ob_dirname(srcdir,sv)) log_dieu(LOG_EXIT_SYS,"set directory name") ; check_dir(dir,force,0) ; if (!auto_stra(&insta,name)) log_die_nomem("stralloc") ; ista = instance_check(insta.s) ; if (!ista) log_die(LOG_EXIT_SYS,"invalid instance name: ",insta.s) ; if (ista > 0) { if (!instance_splitname(&insta,name,ista,SS_INSTANCE_TEMPLATE)) log_dieu(LOG_EXIT_SYS,"split instance name of: ",name) ; } log_trace("read service file of: ",srcdir,insta.s) ; if (read_svfile(&src,insta.s,srcdir) <= 0) log_dieusys(LOG_EXIT_SYS,"open: ",sv) ; if (!get_svtype(&service,src.s)) log_dieu(LOG_EXIT_SYS,"get service type of: ",sv) ; if (ista > 0) { if (!instance_create(&src,name,SS_INSTANCE_REGEX,ista)) log_dieu(LOG_EXIT_SYS,"create instance service: ",name) ; } if (!get_svname(&service,src.s)) log_dieu(LOG_EXIT_SYS,"get name of service: ",sv) ; /** keep the name set by user * uniquely for instantiated service * The name must contain the template string */ if (ista > 0 && service.cname.name >= 0 ) { stralloc sainsta = STRALLOC_ZERO ; stralloc saname = STRALLOC_ZERO ; if (!stralloc_cats(&saname,keep.s + service.cname.name)) log_die_nomem("stralloc") ; if (!instance_splitname(&sainsta,name,ista,SS_INSTANCE_TEMPLATE)) log_dieu(LOG_EXIT_SYS,"split instance name") ; if (sastr_find(&saname,sainsta.s) == -1) log_die(LOG_EXIT_USER,"invalid instantiated service name: ", keep.s + service.cname.name) ; stralloc_free(&sainsta) ; stralloc_free(&saname) ; } else { service.cname.name = keep.len ; if (!stralloc_catb(&keep,name,namelen + 1)) log_die_nomem("stralloc") ; } if (!parser(&service,&src,sv,service.cname.itype)) log_dieu(LOG_EXIT_SYS,"parse service file: ",sv) ; if (!auto_stra(&dst,dir,"/",name)) log_die_nomem("stralloc") ; check_dir(dst.s,force,1) ; type = service.cname.itype ; srcdirlen = strlen(srcdir) ; service.src = keep.len ; if (!stralloc_catb(&keep,srcdir,srcdirlen + 1)) log_die_nomem("stralloc") ; /* save and prepare environment file */ if (service.opts[2]) { stralloc conf = STRALLOC_ZERO ; if (!stralloc_catb(&conf,dst.s,dst.len) || !stralloc_cats(&conf,"/env") || !stralloc_0(&conf)) log_die_nomem("stralloc") ; if (!scan_mode(conf.s,S_IFDIR)) { if (!dir_create_parent(conf.s,0755)) log_dieusys(LOG_EXIT_SYS,"environment directory: ",conf.s) ; } service.srconf = keep.len ; if (!stralloc_catb(&keep,conf.s,conf.len + 1)) log_die_nomem("stralloc") ; stralloc_free(&conf) ; } switch(type) { case TYPE_CLASSIC: if (!write_classic(&service, dst.s, force, conf)) log_dieu(LOG_EXIT_SYS,"write: ",name) ; break ; case TYPE_LONGRUN: if (!write_longrun(&service, dst.s, force, conf)) log_dieu(LOG_EXIT_SYS,"write: ",name) ; break ; case TYPE_ONESHOT: if (!write_oneshot(&service, dst.s, conf)) log_dieu(LOG_EXIT_SYS,"write: ",name) ; break ; case TYPE_MODULE: if (!write_common(&service,dst.s, conf)) log_warnu_return(LOG_EXIT_ZERO,"write common files") ; case TYPE_BUNDLE: if (!write_bundle(&service, dst.s)) log_dieu(LOG_EXIT_SYS,"write: ",name) ; break ; default: break ; } log_info("Written successfully: ",name, " at: ",dir) ; sv_alltype_free(&service) ; stralloc_free(&keep) ; stralloc_free(&deps) ; stralloc_free(&src) ; stralloc_free(&dst) ; return 0 ; }