diff --git a/src/lib66/exec/ssexec_help.c b/src/lib66/exec/ssexec_help.c index 7c6ec02a3783e952ebb2a6574c80c158b66af643..b770ab9531dccb41f8ab44d7d0e98015ffb3d191 100644 --- a/src/lib66/exec/ssexec_help.c +++ b/src/lib66/exec/ssexec_help.c @@ -248,13 +248,14 @@ char const *help_state = " -h: print this help\n" ; -char const *usage_remove = "66 remove [ -h ] service" ; +char const *usage_remove = "66 remove [ -h ] [ -P ] service" ; char const *help_remove = "\nremove services and cleanup all files belong to it from the system\n" "\n" "options :\n" " -h: print this help\n" +" -P: do not propagate signal to its dependencies at stop process\n" ; char const *usage_signal = "66 signal [ -h ] [ -wu | -wU | -wd | -wD | -wr | -wR ] [ -abqHkti12pcyodDuUxOr ] service..." ; diff --git a/src/lib66/exec/ssexec_remove.c b/src/lib66/exec/ssexec_remove.c index 6e152a66458b897ef05cd51261e8baa6084f4a47..44208157b3c7490bf3220358d7b300a0cf897f94 100644 --- a/src/lib66/exec/ssexec_remove.c +++ b/src/lib66/exec/ssexec_remove.c @@ -12,10 +12,220 @@ * except according to the terms contained in the LICENSE file./ */ +#include <string.h> +#include <stdint.h> +#include <stdlib.h> + +#include <oblibs/log.h> +#include <oblibs/string.h> +#include <oblibs/types.h> +#include <oblibs/sastr.h> +#include <oblibs/directory.h> + +#include <skalibs/posixplz.h> +#include <skalibs/stralloc.h> +#include <skalibs/sgetopt.h> + +#include <66/state.h> +#include <66/enum.h> #include <66/ssexec.h> +#include <66/resolve.h> +#include <66/service.h> +#include <66/tree.h> +#include <66/config.h> +#include <66/constants.h> + +static void auto_remove(char const *path) +{ + log_trace("remove directory: ", path) ; + if (!dir_rm_rf(path)) + log_dieusys(LOG_EXIT_SYS, "remove directory: ", path) ; +} + +static void remove_service(resolve_service_t *res, ssexec_t *info) +{ + int r ; + char *path = 0 ; + char sym[strlen(res->sa.s + res->path.home) + SS_SYSTEM_LEN + SS_RESOLVE_LEN + SS_SERVICE_LEN + 1 + SS_MAX_SERVICE_NAME + 1] ; + + path = realpath(res->sa.s + res->path.servicedir, 0) ; + if (!path) + log_dieusys(LOG_EXIT_SYS, "retrieve real path of: ", res->sa.s + res->path.servicedir) ; + + auto_remove(path) ; + + free(path) ; + + tree_service_remove(info->base.s, res->sa.s + res->treename, res->sa.s + res->name) ; + + if (res->logger.want && res->type == TYPE_CLASSIC) { + + resolve_service_t lres = RESOLVE_SERVICE_ZERO ; + resolve_wrapper_t_ref lwres = resolve_set_struct(DATA_SERVICE, &lres) ; + + r = resolve_read_g(lwres, info->base.s, res->sa.s + res->logger.name) ; + if (r <= 0) + log_dieusys(LOG_EXIT_SYS, "read resolve file of: ", res->sa.s + res->logger.name) ; + + path = realpath(lres.sa.s + lres.path.servicedir, 0) ; + if (!path) + log_dieusys(LOG_EXIT_SYS, "retrieve real path of: ", lres.sa.s + lres.path.servicedir) ; + + auto_remove(path) ; + + free(path) ; + + auto_remove(lres.sa.s + lres.logger.destination) ; + + tree_service_remove(info->base.s, lres.sa.s + lres.treename, lres.sa.s + lres.name) ; + + auto_strings(sym, lres.sa.s + lres.path.home, SS_SYSTEM, SS_RESOLVE, SS_SERVICE, "/", lres.sa.s + lres.name) ; + + log_trace("remove symlink: ", sym) ; + unlink_void(sym) ; + + log_info("removed successfully: ", lres.sa.s + lres.name) ; + + resolve_free(lwres) ; + } + + auto_strings(sym, res->sa.s + res->path.home, SS_SYSTEM, SS_RESOLVE, SS_SERVICE, "/", res->sa.s + res->name) ; + + log_trace("remove symlink: ", sym) ; + unlink_void(sym) ; + + log_info("removed successfully: ", res->sa.s + res->name) ; +} + int ssexec_remove(int argc, char const *const *argv, ssexec_t *info) { + log_flow() ; + + int r ; + size_t pos = 0 ; + uint32_t flag = 0 ; + uint8_t siglen = 0 ; + unsigned int areslen = 0 ; + ss_state_t ste = STATE_ZERO ; + stralloc sa = STRALLOC_ZERO ; + resolve_wrapper_t_ref wres = 0 ; + + FLAGS_SET(flag, STATE_FLAGS_TOPROPAGATE|STATE_FLAGS_ISSUPERVISED|STATE_FLAGS_TOUNSUPERVISE|STATE_FLAGS_WANTDOWN) ; + + { + subgetopt l = SUBGETOPT_ZERO ; + + for (;;) { + + int opt = subgetopt_r(argc,argv, OPTS_START, &l) ; + if (opt == -1) break ; + + switch (opt) { + + case 'h' : + + info_help(info->help, info->usage) ; + return 0 ; + + case 'P' : + + FLAGS_CLEAR(flag, STATE_FLAGS_TOPROPAGATE) ; + siglen++ ; + break ; + + default : + + log_usage(info->usage, "\n", info->help) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + + if (argc < 1) + log_usage(info->usage, "\n", info->help) ; + + resolve_service_t ares[argc] ; + + for(; pos < argc ; pos++) { + + resolve_service_t res = RESOLVE_SERVICE_ZERO ; + wres = resolve_set_struct(DATA_SERVICE, &res) ; + + r = resolve_read_g(wres, info->base.s, argv[pos]) ; + if (r < 0) + log_dieusys(LOG_EXIT_SYS, "read resolve file of: ", argv[pos]) ; + + if (!r) + log_dieu(LOG_EXIT_USER, "find service: ", argv[pos], " -- did you parsed it ?") ; + + if (!state_read(&ste, &res)) + log_dieusys(LOG_EXIT_SYS, "read state file of: ", argv[pos], " -- please make a bug report") ; + + if (service_is(&ste, STATE_FLAGS_ISSUPERVISED) == STATE_FLAGS_TRUE) + if (!sastr_add_string(&sa, argv[pos])) + log_dieusys(LOG_EXIT_SYS, "add service: ", argv[pos], " to selection") ; + + ares[areslen++] = res ; + } + + if (sa.len) { + + pos = 0 ; + char const *prog = PROG ; + int nargc = 2 + siglen + sastr_nelement(&sa) ; + char const *newargv[nargc] ; + unsigned int m = 0 ; + + newargv[m++] = "stop" ; + newargv[m++] = "-u" ; + if (siglen) + newargv[m++] = "-P" ; + + FOREACH_SASTR(&sa, pos) + newargv[m++] = sa.s + pos ; + + newargv[m] = 0 ; + + PROG = "stop" ; + if (ssexec_stop(nargc, newargv, info)) + log_dieu(LOG_EXIT_SYS, "stop service selection") ; + PROG = prog ; + } + + for (pos = 0 ; pos < areslen ; pos++) { + + remove_service(&ares[pos], info) ; + + if (ares[pos].type == TYPE_MODULE) { + + if (ares[pos].dependencies.ncontents) { + + size_t pos = 0 ; + sa.len = 0 ; + resolve_service_t mres = RESOLVE_SERVICE_ZERO ; + resolve_wrapper_t_ref mwres = resolve_set_struct(DATA_SERVICE, &mres) ; + + if (!sastr_clean_string(&sa, ares[pos].sa.s + ares[pos].dependencies.contents)) + log_dieu(LOG_EXIT_SYS, "clean string") ; + + FOREACH_SASTR(&sa, pos) { + + r = resolve_read_g(mwres, info->base.s, sa.s + pos) ; + if (r <= 0) + log_dieusys(LOG_EXIT_SYS, "read resolve file of: ", sa.s + pos) ; + + remove_service(&mres, info) ; + } + + resolve_free(mwres) ; + } + } + } + stralloc_free(&sa) ; + service_resolve_array_free(ares, areslen) ; + free(wres) ; + return 0 ; }