-
Eric Vidal authoredEric Vidal authored
ssexec_enable.c 6.25 KiB
/*
* ssexec_enable.c
*
* Copyright (c) 2018-2019 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 <errno.h>
//#include <stdio.h>
#include <oblibs/obgetopt.h>
#include <oblibs/error2.h>
#include <oblibs/string.h>
#include <oblibs/sastr.h>
#include <skalibs/stralloc.h>
#include <skalibs/genalloc.h>
#include <skalibs/djbunix.h>
#include <66/constants.h>
#include <66/utils.h>
#include <66/tree.h>
#include <66/db.h>
#include <66/parser.h>
#include <66/svc.h>
#include <66/resolve.h>
#include <66/ssexec.h>
/** force == 1, only rewrite the service
* force == 2, rewrite the service and it dependencies*/
static uint8_t FORCE = 0 ;
/** rewrite configuration file */
static uint8_t CONF = 0 ;
static void cleanup(char const *dst)
{
int e = errno ;
rm_rf(dst) ;
errno = e ;
}
static void check_identifier(char const *name)
{
if (!memcmp(name,SS_MASTER+1,6)) strerr_dief3x(111,"service: ",name,": starts with reserved prefix") ;
}
static void start_parser(stralloc *list,ssexec_t *info, unsigned int *nbsv)
{
int r ;
uint8_t exist = 0 ;
size_t i = 0, len = list->len ;
stralloc sasv = STRALLOC_ZERO ;
stralloc tmp = STRALLOC_ZERO ;
for (;i < len; i += strlen(list->s + i) + 1)
{
exist = 0 ;
char *name = list->s+i ;
size_t namelen = strlen(name) ;
char svname[namelen + 1] ;
if (!basename(svname,name)) strerr_diefu2sys(111,"get basename of: ", svname) ;
r = parse_service_check_enabled(info,svname,FORCE,&exist) ;
if (!r) strerr_diefu2x(111,"check enabled service: ",svname) ;
if (r == 2) continue ;
if (!parse_service_before(info,&tmp,name,nbsv,&sasv,FORCE,&exist))
strerr_diefu3x(111,"parse service file: ",svname,": or its dependencies") ;
}
stralloc_free(&sasv) ;
stralloc_free(&tmp) ;
}
int ssexec_enable(int argc, char const *const *argv,char const *const *envp,ssexec_t *info)
{
// be sure that the global var are set correctly
FORCE = 0 ;
CONF = 0 ;
int r ;
size_t pos = 0 ;
unsigned int nbsv, nlongrun, nclassic, start ;
stralloc home = STRALLOC_ZERO ;
stralloc workdir = STRALLOC_ZERO ;
stralloc sasrc = STRALLOC_ZERO ;
stralloc tostart = STRALLOC_ZERO ;
r = nbsv = nclassic = nlongrun = start = 0 ;
{
subgetopt_t l = SUBGETOPT_ZERO ;
for (;;)
{
int opt = getopt_args(argc,argv, ">cCfFS", &l) ;
if (opt == -1) break ;
if (opt == -2) strerr_dief1x(110,"options must be set first") ;
switch (opt)
{
case 'f' : if (FORCE) exitusage(usage_enable) ;
FORCE = 1 ; break ;
case 'F' : if (FORCE) exitusage(usage_enable) ;
FORCE = 2 ; break ;
case 'c' : if (CONF) exitusage(usage_enable) ; CONF = 1 ; break ;
case 'C' : if (CONF) exitusage(usage_enable) ; CONF = 2 ; break ;
case 'S' : start = 1 ; break ;
default : exitusage(usage_enable) ;
}
}
argc -= l.ind ; argv += l.ind ;
}
if (argc < 1) exitusage(usage_enable) ;
for(;*argv;argv++)
{
check_identifier(*argv) ;
if (!ss_resolve_src_path(&sasrc,*argv,info)) strerr_diefu2x(111,"resolve source path of: ",*argv) ;
}
start_parser(&sasrc,info,&nbsv) ;
if (!tree_copy(&workdir,info->tree.s,info->treename.s)) strerr_diefu1sys(111,"create tmp working directory") ;
for (unsigned int i = 0; i < genalloc_len(sv_alltype,&gasv); i++)
{
sv_alltype_ref sv = &genalloc_s(sv_alltype,&gasv)[i] ;
char *name = keep.s + sv->cname.name ;
r = write_services(info,sv, workdir.s,FORCE,CONF) ;
if (!r)
{
cleanup(workdir.s) ;
strerr_diefu2x(111,"write service: ",name) ;
}
if (r > 1) continue ; //service already added
VERBO2 strerr_warni2x("write resolve file of: ",name) ;
if (!ss_resolve_setnwrite(sv,info,workdir.s))
{
cleanup(workdir.s) ;
strerr_diefu2x(111,"write revolve file for: ",name) ;
}
VERBO2 strerr_warni2x("Service written successfully: ", name) ;
if (sastr_cmp(&tostart,name) == -1)
{
if (sv->cname.itype == CLASSIC) nclassic++ ;
else nlongrun++ ;
if (!sastr_add_string(&tostart,name))
{
cleanup(workdir.s) ;
retstralloc(111,"main") ;
}
}
}
if (nclassic)
{
if (!svc_switch_to(info,SS_SWBACK))
{
cleanup(workdir.s) ;
strerr_diefu3x(111,"switch ",info->treename.s," to backup") ;
}
}
if(nlongrun)
{
ss_resolve_graph_t graph = RESOLVE_GRAPH_ZERO ;
r = ss_resolve_graph_src(&graph,workdir.s,0,1) ;
if (!r)
{
cleanup(workdir.s) ;
strerr_diefu2x(111,"resolve source of graph for tree: ",info->treename.s) ;
}
r = ss_resolve_graph_publish(&graph,0) ;
if (r <= 0)
{
cleanup(workdir.s) ;
if (r < 0) strerr_dief1x(110,"cyclic graph detected") ;
strerr_diefu1sys(111,"publish service graph") ;
}
if (!ss_resolve_write_master(info,&graph,workdir.s,0))
{
cleanup(workdir.s) ;
strerr_diefu1sys(111,"update inner bundle") ;
}
ss_resolve_graph_free(&graph) ;
if (!db_compile(workdir.s,info->tree.s,info->treename.s,envp))
{
cleanup(workdir.s) ;
strerr_diefu4x(111,"compile ",workdir.s,"/",info->treename.s) ;
}
/** this is an important part, we call s6-rc-update here */
if (!db_switch_to(info,envp,SS_SWBACK))
{
cleanup(workdir.s) ;
strerr_diefu3x(111,"switch ",info->treename.s," to backup") ;
}
}
if (!tree_copy_tmp(workdir.s,info))
{
cleanup(workdir.s) ;
strerr_diefu4x(111,"copy: ",workdir.s," to: ", info->tree.s) ;
}
cleanup(workdir.s) ;
/** parser allocation*/
freed_parser() ;
/** inner allocation */
stralloc_free(&home) ;
stralloc_free(&workdir) ;
stralloc_free(&sasrc) ;
for (; pos < tostart.len; pos += strlen(tostart.s + pos) + 1)
VERBO1 strerr_warni2x("Enabled successfully: ", tostart.s + pos) ;
if (start && tostart.len)
{
int nargc = 2 + sastr_len(&tostart) ;
char const *newargv[nargc] ;
unsigned int m = 0 ;
newargv[m++] = "fake_name" ;
for (pos = 0 ; pos < tostart.len; pos += strlen(tostart.s + pos) + 1)
newargv[m++] = tostart.s + pos ;
newargv[m++] = 0 ;
if (ssexec_start(nargc,newargv,envp,info))
{
stralloc_free(&tostart) ;
return 111 ;
}
}
stralloc_free(&tostart) ;
return 0 ;
}