diff --git a/package/deps.mak b/package/deps.mak
index e9dfd77b212f0ca190e7517560915e97e7e1e821..e7e7905bc465a4edc8ac16947808b9b77340592e 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -3,32 +3,36 @@
 #
 
 src/include/66/66.h: src/include/66/backup.h src/include/66/config.h src/include/66/constants.h src/include/66/db.h src/include/66/enum.h src/include/66/graph.h src/include/66/parser.h src/include/66/svc.h src/include/66/tree.h src/include/66/utils.h
+src/include/66/backup.h: src/include/66/ssexec.h
 src/include/66/constants.h: src/include/66/config.h
-src/include/66/db.h: src/include/66/graph.h
+src/include/66/db.h: src/include/66/graph.h src/include/66/ssexec.h
 src/include/66/parser.h: src/include/66/enum.h
+src/include/66/svc.h: src/include/66/ssexec.h
+src/include/66/tree.h: src/include/66/ssexec.h
+src/include/66/utils.h: src/include/66/ssexec.h
 src/66/66-all.o src/66/66-all.lo: src/66/66-all.c src/include/66/config.h src/include/66/constants.h src/include/66/tree.h src/include/66/utils.h
-src/66/66-dbctl.o src/66/66-dbctl.lo: src/66/66-dbctl.c src/include/66/constants.h src/include/66/db.h src/include/66/enum.h src/include/66/tree.h src/include/66/utils.h
-src/66/66-disable.o src/66/66-disable.lo: src/66/66-disable.c src/include/66/backup.h src/include/66/constants.h src/include/66/db.h src/include/66/enum.h src/include/66/graph.h src/include/66/tree.h src/include/66/utils.h
-src/66/66-enable.o src/66/66-enable.lo: src/66/66-enable.c src/include/66/backup.h src/include/66/constants.h src/include/66/db.h src/include/66/enum.h src/include/66/graph.h src/include/66/parser.h src/include/66/svc.h src/include/66/tree.h src/include/66/utils.h
+src/66/66-dbctl.o src/66/66-dbctl.lo: src/66/66-dbctl.c src/include/66/ssexec.h
+src/66/66-disable.o src/66/66-disable.lo: src/66/66-disable.c src/include/66/ssexec.h
+src/66/66-enable.o src/66/66-enable.lo: src/66/66-enable.c src/include/66/ssexec.h
 src/66/66-info.o src/66/66-info.lo: src/66/66-info.c src/include/66/constants.h src/include/66/enum.h src/include/66/graph.h src/include/66/tree.h src/include/66/utils.h
-src/66/66-init.o src/66/66-init.lo: src/66/66-init.c src/include/66/backup.h src/include/66/constants.h src/include/66/db.h src/include/66/enum.h src/include/66/svc.h src/include/66/tree.h src/include/66/utils.h
+src/66/66-init.o src/66/66-init.lo: src/66/66-init.c src/include/66/ssexec.h
 src/66/66-scandir.o src/66/66-scandir.lo: src/66/66-scandir.c src/include/66/config.h src/include/66/constants.h src/include/66/utils.h
-src/66/66-start.o src/66/66-start.lo: src/66/66-start.c src/include/66/backup.h src/include/66/config.h src/include/66/constants.h src/include/66/db.h src/include/66/enum.h src/include/66/svc.h src/include/66/tree.h src/include/66/utils.h
-src/66/66-stop.o src/66/66-stop.lo: src/66/66-stop.c src/include/66/backup.h src/include/66/config.h src/include/66/constants.h src/include/66/db.h src/include/66/enum.h src/include/66/svc.h src/include/66/tree.h src/include/66/utils.h
-src/66/66-svctl.o src/66/66-svctl.lo: src/66/66-svctl.c src/include/66/constants.h src/include/66/svc.h src/include/66/tree.h src/include/66/utils.h
+src/66/66-start.o src/66/66-start.lo: src/66/66-start.c src/include/66/ssexec.h
+src/66/66-stop.o src/66/66-stop.lo: src/66/66-stop.c src/include/66/ssexec.h
+src/66/66-svctl.o src/66/66-svctl.lo: src/66/66-svctl.c src/include/66/ssexec.h
 src/66/66-tree.o src/66/66-tree.lo: src/66/66-tree.c src/include/66/config.h src/include/66/constants.h src/include/66/db.h src/include/66/tree.h src/include/66/utils.h
 src/extra-tools/66-envfile.o src/extra-tools/66-envfile.lo: src/extra-tools/66-envfile.c src/include/66/parser.h
 src/extra-tools/execl-cmdline.o src/extra-tools/execl-cmdline.lo: src/extra-tools/execl-cmdline.c
-src/lib66/backup_cmd_switcher.o src/lib66/backup_cmd_switcher.lo: src/lib66/backup_cmd_switcher.c src/include/66/constants.h src/include/66/enum.h src/include/66/utils.h
+src/lib66/backup_cmd_switcher.o src/lib66/backup_cmd_switcher.lo: src/lib66/backup_cmd_switcher.c src/include/66/constants.h src/include/66/enum.h src/include/66/ssexec.h src/include/66/utils.h
 src/lib66/backup_make_new.o src/lib66/backup_make_new.lo: src/lib66/backup_make_new.c src/include/66/constants.h src/include/66/db.h src/include/66/enum.h src/include/66/tree.h src/include/66/utils.h
 src/lib66/backup_realpath_sym.o src/lib66/backup_realpath_sym.lo: src/lib66/backup_realpath_sym.c src/include/66/constants.h src/include/66/enum.h src/include/66/utils.h
 src/lib66/db_cmd_master.o src/lib66/db_cmd_master.lo: src/lib66/db_cmd_master.c src/include/66/constants.h src/include/66/db.h src/include/66/graph.h src/include/66/parser.h src/include/66/utils.h
-src/lib66/db_compile.o src/lib66/db_compile.lo: src/lib66/db_compile.c src/include/66/constants.h src/include/66/db.h src/include/66/utils.h
+src/lib66/db_compile.o src/lib66/db_compile.lo: src/lib66/db_compile.c src/include/66/constants.h src/include/66/db.h src/include/66/ssexec.h src/include/66/utils.h
 src/lib66/db_find_compiled_state.o src/lib66/db_find_compiled_state.lo: src/lib66/db_find_compiled_state.c src/include/66/constants.h src/include/66/utils.h
 src/lib66/db_get_permissions.o src/lib66/db_get_permissions.lo: src/lib66/db_get_permissions.c src/include/66/constants.h src/include/66/utils.h
 src/lib66/db_ok.o src/lib66/db_ok.lo: src/lib66/db_ok.c src/include/66/constants.h
-src/lib66/db_switch_to.o src/lib66/db_switch_to.lo: src/lib66/db_switch_to.c src/include/66/backup.h src/include/66/constants.h src/include/66/db.h src/include/66/enum.h src/include/66/utils.h
-src/lib66/db_update.o src/lib66/db_update.lo: src/lib66/db_update.c src/include/66/constants.h src/include/66/db.h src/include/66/utils.h
+src/lib66/db_switch_to.o src/lib66/db_switch_to.lo: src/lib66/db_switch_to.c src/include/66/backup.h src/include/66/constants.h src/include/66/db.h src/include/66/enum.h src/include/66/ssexec.h src/include/66/utils.h
+src/lib66/db_update.o src/lib66/db_update.lo: src/lib66/db_update.c src/include/66/constants.h src/include/66/db.h src/include/66/ssexec.h src/include/66/utils.h
 src/lib66/dir_cmpndel.o src/lib66/dir_cmpndel.lo: src/lib66/dir_cmpndel.c src/include/66/utils.h
 src/lib66/get_enum.o src/lib66/get_enum.lo: src/lib66/get_enum.c src/include/66/enum.h
 src/lib66/get_uidgid.o src/lib66/get_uidgid.lo: src/lib66/get_uidgid.c
@@ -40,18 +44,29 @@ src/lib66/parser_write.o src/lib66/parser_write.lo: src/lib66/parser_write.c src
 src/lib66/resolve.o src/lib66/resolve.lo: src/lib66/resolve.c src/include/66/constants.h src/include/66/enum.h src/include/66/utils.h
 src/lib66/scandir_ok.o src/lib66/scandir_ok.lo: src/lib66/scandir_ok.c src/include/66/utils.h
 src/lib66/scandir_send_signal.o src/lib66/scandir_send_signal.lo: src/lib66/scandir_send_signal.c src/include/66/utils.h
+src/lib66/set_info.o src/lib66/set_info.lo: src/lib66/set_info.c src/include/66/config.h src/include/66/utils.h
 src/lib66/set_livedir.o src/lib66/set_livedir.lo: src/lib66/set_livedir.c src/include/66/config.h src/include/66/utils.h
 src/lib66/set_livescan.o src/lib66/set_livescan.lo: src/lib66/set_livescan.c src/include/66/config.h src/include/66/utils.h
 src/lib66/set_livetree.o src/lib66/set_livetree.lo: src/lib66/set_livetree.c src/include/66/config.h src/include/66/utils.h
 src/lib66/set_ownerhome.o src/lib66/set_ownerhome.lo: src/lib66/set_ownerhome.c src/include/66/config.h src/include/66/utils.h
 src/lib66/set_ownersysdir.o src/lib66/set_ownersysdir.lo: src/lib66/set_ownersysdir.c src/include/66/config.h src/include/66/utils.h
+src/lib66/ssexec_dbctl.o src/lib66/ssexec_dbctl.lo: src/lib66/ssexec_dbctl.c src/include/66/constants.h src/include/66/db.h src/include/66/enum.h src/include/66/tree.h src/include/66/utils.h
+src/lib66/ssexec_disable.o src/lib66/ssexec_disable.lo: src/lib66/ssexec_disable.c src/include/66/backup.h src/include/66/constants.h src/include/66/db.h src/include/66/enum.h src/include/66/graph.h src/include/66/tree.h src/include/66/utils.h
+src/lib66/ssexec_enable.o src/lib66/ssexec_enable.lo: src/lib66/ssexec_enable.c src/include/66/backup.h src/include/66/constants.h src/include/66/db.h src/include/66/enum.h src/include/66/graph.h src/include/66/parser.h src/include/66/svc.h src/include/66/tree.h src/include/66/utils.h
+src/lib66/ssexec_free.o src/lib66/ssexec_free.lo: src/lib66/ssexec_free.c src/include/66/ssexec.h
+src/lib66/ssexec_help.o src/lib66/ssexec_help.lo: src/lib66/ssexec_help.c src/include/66/ssexec.h
+src/lib66/ssexec_init.o src/lib66/ssexec_init.lo: src/lib66/ssexec_init.c src/include/66/backup.h src/include/66/constants.h src/include/66/db.h src/include/66/enum.h src/include/66/svc.h src/include/66/tree.h src/include/66/utils.h
+src/lib66/ssexec_main.o src/lib66/ssexec_main.lo: src/lib66/ssexec_main.c src/include/66/ssexec.h src/include/66/tree.h src/include/66/utils.h
+src/lib66/ssexec_start.o src/lib66/ssexec_start.lo: src/lib66/ssexec_start.c src/include/66/backup.h src/include/66/config.h src/include/66/constants.h src/include/66/db.h src/include/66/enum.h src/include/66/ssexec.h src/include/66/svc.h src/include/66/tree.h src/include/66/utils.h
+src/lib66/ssexec_stop.o src/lib66/ssexec_stop.lo: src/lib66/ssexec_stop.c src/include/66/backup.h src/include/66/config.h src/include/66/constants.h src/include/66/db.h src/include/66/enum.h src/include/66/ssexec.h src/include/66/svc.h src/include/66/tree.h src/include/66/utils.h
+src/lib66/ssexec_svctl.o src/lib66/ssexec_svctl.lo: src/lib66/ssexec_svctl.c src/include/66/constants.h src/include/66/ssexec.h src/include/66/svc.h src/include/66/tree.h src/include/66/utils.h
 src/lib66/sv_alltype_zero.o src/lib66/sv_alltype_zero.lo: src/lib66/sv_alltype_zero.c src/include/66/parser.h
 src/lib66/svc_init.o src/lib66/svc_init.lo: src/lib66/svc_init.c src/include/66/svc.h src/include/66/utils.h
 src/lib66/svc_init_pipe.o src/lib66/svc_init_pipe.lo: src/lib66/svc_init_pipe.c src/include/66/svc.h src/include/66/utils.h
-src/lib66/svc_switch_to.o src/lib66/svc_switch_to.lo: src/lib66/svc_switch_to.c src/include/66/backup.h src/include/66/enum.h src/include/66/utils.h
+src/lib66/svc_switch_to.o src/lib66/svc_switch_to.lo: src/lib66/svc_switch_to.c src/include/66/backup.h src/include/66/enum.h src/include/66/ssexec.h src/include/66/utils.h
 src/lib66/tree_cmd_state.o src/lib66/tree_cmd_state.lo: src/lib66/tree_cmd_state.c src/include/66/constants.h src/include/66/utils.h
 src/lib66/tree_copy.o src/lib66/tree_copy.lo: src/lib66/tree_copy.c src/include/66/constants.h src/include/66/tree.h src/include/66/utils.h
-src/lib66/tree_copy_tmp.o src/lib66/tree_copy_tmp.lo: src/lib66/tree_copy_tmp.c src/include/66/constants.h src/include/66/enum.h src/include/66/tree.h src/include/66/utils.h
+src/lib66/tree_copy_tmp.o src/lib66/tree_copy_tmp.lo: src/lib66/tree_copy_tmp.c src/include/66/constants.h src/include/66/enum.h src/include/66/ssexec.h src/include/66/tree.h src/include/66/utils.h
 src/lib66/tree_find_current.o src/lib66/tree_find_current.lo: src/lib66/tree_find_current.c src/include/66/constants.h src/include/66/utils.h
 src/lib66/tree_get_permissions.o src/lib66/tree_get_permissions.lo: src/lib66/tree_get_permissions.c src/include/66/constants.h src/include/66/utils.h
 src/lib66/tree_sethome.o src/lib66/tree_sethome.lo: src/lib66/tree_sethome.c src/include/66/constants.h src/include/66/tree.h
@@ -63,15 +78,15 @@ src/lib66/tree_switch_current.o src/lib66/tree_switch_current.lo: src/lib66/tree
 66-dbctl: EXTRA_LIBS :=
 66-dbctl: src/66/66-dbctl.o ${LIB66} -loblibs -ls6 -lskarnet -ls6rc ${LIBS6RC}
 66-disable: EXTRA_LIBS :=
-66-disable: src/66/66-disable.o ${LIB66} -loblibs -lskarnet 
+66-disable: src/66/66-disable.o ${LIB66} -loblibs -lexecline -ls6 -lskarnet 
 66-enable: EXTRA_LIBS :=
-66-enable: src/66/66-enable.o ${LIB66} -loblibs -lskarnet -lexecline -ls6
+66-enable: src/66/66-enable.o ${LIB66} -loblibs -lexecline -ls6 -lskarnet 
 66-info: EXTRA_LIBS :=
 66-info: src/66/66-info.o ${LIB66} -loblibs -ls6 -lskarnet
 66-init: EXTRA_LIBS :=
 66-init: src/66/66-init.o ${LIB66} -loblibs -ls6 -lskarnet
 66-scandir: EXTRA_LIBS :=
-66-scandir: src/66/66-scandir.o ${LIB66} -loblibs -lskarnet -ls6 
+66-scandir: src/66/66-scandir.o ${LIB66} -loblibs -ls6 -lskarnet  
 66-start: EXTRA_LIBS :=
 66-start: src/66/66-start.o ${LIB66} -loblibs -ls6 -lskarnet 
 66-stop: EXTRA_LIBS :=
@@ -85,9 +100,9 @@ src/lib66/tree_switch_current.o src/lib66/tree_switch_current.lo: src/lib66/tree
 execl-cmdline: EXTRA_LIBS :=
 execl-cmdline: src/extra-tools/execl-cmdline.o -lexecline -loblibs -lskarnet
 ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)
-lib66.a.xyzzy: src/lib66/backup_cmd_switcher.o src/lib66/backup_make_new.o src/lib66/backup_realpath_sym.o src/lib66/db_cmd_master.o src/lib66/db_compile.o src/lib66/db_find_compiled_state.o src/lib66/db_get_permissions.o src/lib66/db_ok.o src/lib66/db_switch_to.o src/lib66/db_update.o src/lib66/dir_cmpndel.o src/lib66/get_enum.o src/lib66/get_uidgid.o src/lib66/get_userhome.o src/lib66/graph.o src/lib66/parser.o src/lib66/parser_utils.o src/lib66/parser_write.o src/lib66/resolve.o src/lib66/scandir_ok.o src/lib66/scandir_send_signal.o src/lib66/set_livedir.o src/lib66/set_livescan.o src/lib66/set_livetree.o src/lib66/set_ownerhome.o src/lib66/set_ownersysdir.o src/lib66/sv_alltype_zero.o src/lib66/svc_init.o src/lib66/svc_init_pipe.o src/lib66/svc_switch_to.o src/lib66/tree_cmd_state.o src/lib66/tree_copy.o src/lib66/tree_copy_tmp.o src/lib66/tree_find_current.o src/lib66/tree_get_permissions.o src/lib66/tree_sethome.o src/lib66/tree_setname.o src/lib66/tree_switch_current.o
+lib66.a.xyzzy: src/lib66/backup_cmd_switcher.o src/lib66/backup_make_new.o src/lib66/backup_realpath_sym.o src/lib66/db_cmd_master.o src/lib66/db_compile.o src/lib66/db_find_compiled_state.o src/lib66/db_get_permissions.o src/lib66/db_ok.o src/lib66/db_switch_to.o src/lib66/db_update.o src/lib66/dir_cmpndel.o src/lib66/get_enum.o src/lib66/get_uidgid.o src/lib66/get_userhome.o src/lib66/graph.o src/lib66/parser.o src/lib66/parser_utils.o src/lib66/parser_write.o src/lib66/resolve.o src/lib66/scandir_ok.o src/lib66/scandir_send_signal.o src/lib66/set_livedir.o src/lib66/set_livescan.o src/lib66/set_livetree.o src/lib66/set_ownerhome.o src/lib66/set_ownersysdir.o src/lib66/ssexec_dbctl.o src/lib66/ssexec_enable.o src/lib66/ssexec_disable.o src/lib66/ssexec_free.o src/lib66/ssexec_help.o src/lib66/ssexec_init.o src/lib66/ssexec_main.o src/lib66/ssexec_start.o src/lib66/ssexec_stop.o src/lib66/ssexec_svctl.o src/lib66/sv_alltype_zero.o src/lib66/svc_init.o src/lib66/svc_init_pipe.o src/lib66/svc_switch_to.o src/lib66/tree_cmd_state.o src/lib66/tree_copy.o src/lib66/tree_copy_tmp.o src/lib66/tree_find_current.o src/lib66/tree_get_permissions.o src/lib66/tree_sethome.o src/lib66/tree_setname.o src/lib66/tree_switch_current.o
 else
-lib66.a.xyzzy: src/lib66/backup_cmd_switcher.lo src/lib66/backup_make_new.lo src/lib66/backup_realpath_sym.lo src/lib66/db_cmd_master.lo src/lib66/db_compile.lo src/lib66/db_find_compiled_state.lo src/lib66/db_get_permissions.lo src/lib66/db_ok.lo src/lib66/db_switch_to.lo src/lib66/db_update.lo src/lib66/dir_cmpndel.lo src/lib66/get_enum.lo src/lib66/get_uidgid.lo src/lib66/get_userhome.lo src/lib66/graph.lo src/lib66/parser.lo src/lib66/parser_utils.lo src/lib66/parser_write.lo src/lib66/resolve.lo src/lib66/scandir_ok.lo src/lib66/scandir_send_signal.lo src/lib66/set_livedir.lo src/lib66/set_livescan.lo src/lib66/set_livetree.lo src/lib66/set_ownerhome.lo src/lib66/set_ownersysdir.lo src/lib66/sv_alltype_zero.lo src/lib66/svc_init.lo src/lib66/svc_init_pipe.lo src/lib66/svc_switch_to.lo src/lib66/tree_cmd_state.lo src/lib66/tree_copy.lo src/lib66/tree_copy_tmp.lo src/lib66/tree_find_current.lo src/lib66/tree_get_permissions.lo src/lib66/tree_sethome.lo src/lib66/tree_setname.lo src/lib66/tree_switch_current.lo
+lib66.a.xyzzy: src/lib66/backup_cmd_switcher.lo src/lib66/backup_make_new.lo src/lib66/backup_realpath_sym.lo src/lib66/db_cmd_master.lo src/lib66/db_compile.lo src/lib66/db_find_compiled_state.lo src/lib66/db_get_permissions.lo src/lib66/db_ok.lo src/lib66/db_switch_to.lo src/lib66/db_update.lo src/lib66/dir_cmpndel.lo src/lib66/get_enum.lo src/lib66/get_uidgid.lo src/lib66/get_userhome.lo src/lib66/graph.lo src/lib66/parser.lo src/lib66/parser_utils.lo src/lib66/parser_write.lo src/lib66/resolve.lo src/lib66/scandir_ok.lo src/lib66/scandir_send_signal.lo src/lib66/set_livedir.lo src/lib66/set_livescan.lo src/lib66/set_livetree.lo src/lib66/set_ownerhome.lo src/lib66/set_ownersysdir.lo src/lib66/ssexec_dbctl.lo src/lib66/ssexec_enable.lo src/lib66/ssexec_disable.lo src/lib66/ssexec_free.lo src/lib66/ssexec_help.lo src/lib66/ssexec_init.lo src/lib66/ssexec_main.lo src/lib66/ssexec_start.lo src/lib66/ssexec_stop.lo src/lib66/ssexec_svctl.lo src/lib66/sv_alltype_zero.lo src/lib66/svc_init.lo src/lib66/svc_init_pipe.lo src/lib66/svc_switch_to.lo src/lib66/tree_cmd_state.lo src/lib66/tree_copy.lo src/lib66/tree_copy_tmp.lo src/lib66/tree_find_current.lo src/lib66/tree_get_permissions.lo src/lib66/tree_sethome.lo src/lib66/tree_setname.lo src/lib66/tree_switch_current.lo
 endif
 lib66.so.xyzzy: EXTRA_LIBS := -loblibs -lskarnet
-lib66.so.xyzzy: src/lib66/backup_cmd_switcher.lo src/lib66/backup_make_new.lo src/lib66/backup_realpath_sym.lo src/lib66/db_cmd_master.lo src/lib66/db_compile.lo src/lib66/db_find_compiled_state.lo src/lib66/db_get_permissions.lo src/lib66/db_ok.lo src/lib66/db_switch_to.lo src/lib66/db_update.lo src/lib66/dir_cmpndel.lo src/lib66/get_enum.lo src/lib66/get_uidgid.lo src/lib66/get_userhome.lo src/lib66/graph.lo src/lib66/parser.lo src/lib66/parser_utils.lo src/lib66/parser_write.lo src/lib66/resolve.lo src/lib66/scandir_ok.lo src/lib66/scandir_send_signal.lo src/lib66/set_livedir.lo src/lib66/set_livescan.lo src/lib66/set_livetree.lo src/lib66/set_ownerhome.lo src/lib66/set_ownersysdir.lo src/lib66/sv_alltype_zero.lo src/lib66/svc_init.lo src/lib66/svc_init_pipe.lo src/lib66/svc_switch_to.lo src/lib66/tree_cmd_state.lo src/lib66/tree_copy.lo src/lib66/tree_copy_tmp.lo src/lib66/tree_find_current.lo src/lib66/tree_get_permissions.lo src/lib66/tree_sethome.lo src/lib66/tree_setname.lo src/lib66/tree_switch_current.lo
+lib66.so.xyzzy: src/lib66/backup_cmd_switcher.lo src/lib66/backup_make_new.lo src/lib66/backup_realpath_sym.lo src/lib66/db_cmd_master.lo src/lib66/db_compile.lo src/lib66/db_find_compiled_state.lo src/lib66/db_get_permissions.lo src/lib66/db_ok.lo src/lib66/db_switch_to.lo src/lib66/db_update.lo src/lib66/dir_cmpndel.lo src/lib66/get_enum.lo src/lib66/get_uidgid.lo src/lib66/get_userhome.lo src/lib66/graph.lo src/lib66/parser.lo src/lib66/parser_utils.lo src/lib66/parser_write.lo src/lib66/resolve.lo src/lib66/scandir_ok.lo src/lib66/scandir_send_signal.lo src/lib66/set_livedir.lo src/lib66/set_livescan.lo src/lib66/set_livetree.lo src/lib66/set_ownerhome.lo src/lib66/set_ownersysdir.lo src/lib66/ssexec_dbctl.lo src/lib66/ssexec_enable.lo src/lib66/ssexec_disable.lo src/lib66/ssexec_free.lo src/lib66/ssexec_help.lo src/lib66/ssexec_init.lo src/lib66/ssexec_main.lo src/lib66/ssexec_start.lo src/lib66/ssexec_stop.lo src/lib66/ssexec_svctl.lo src/lib66/sv_alltype_zero.lo src/lib66/svc_init.lo src/lib66/svc_init_pipe.lo src/lib66/svc_switch_to.lo src/lib66/tree_cmd_state.lo src/lib66/tree_copy.lo src/lib66/tree_copy_tmp.lo src/lib66/tree_find_current.lo src/lib66/tree_get_permissions.lo src/lib66/tree_sethome.lo src/lib66/tree_setname.lo src/lib66/tree_switch_current.lo
diff --git a/src/66/66-all.c b/src/66/66-all.c
index 8d292ac69c728c7772942845853e8436dded7f48..7c2d025e9d0ee9cf94d084e665a5d597896a3ce3 100644
--- a/src/66/66-all.c
+++ b/src/66/66-all.c
@@ -191,24 +191,24 @@ int main(int argc, char const *const *argv,char const *const *envp)
 			switch (opt)
 			{
 				case 'h' : 	info_help(); return 0 ;
-				case 'v' :  if (!uint0_scan(l.arg, &VERBOSITY)) exitusage() ; break ;
+				case 'v' :  if (!uint0_scan(l.arg, &VERBOSITY)) exitusage(USAGE) ; break ;
 				case 'l' : 	if (!stralloc_cats(&live,l.arg)) retstralloc(111,"main") ;
 							if (!stralloc_0(&live)) retstralloc(111,"main") ;
 							break ;
-				case 'T' :	if (!uint0_scan(l.arg, &DEADLINE)) exitusage() ; break ;
+				case 'T' :	if (!uint0_scan(l.arg, &DEADLINE)) exitusage(USAGE) ; break ;
 				case 't' : 	treename = l.arg ; break ;
 				case 'f' : 	shut = 1 ; break ;
-				default : exitusage() ; 
+				default : exitusage(USAGE) ; 
 			}
 		}
 		argc -= l.ind ; argv += l.ind ;
 	}
 
-	if (argc != 1) exitusage() ;
+	if (argc != 1) exitusage(USAGE) ;
 	
 	if (*argv[0] == 'u') what = 1 ;
 	else if (*argv[0] == 'd') what = 0 ;
-	else exitusage() ;
+	else exitusage(USAGE) ;
 	
 	owner = MYUID ;
 
@@ -234,7 +234,6 @@ int main(int argc, char const *const *argv,char const *const *envp)
 	
 	size_t statesize ;
 	/** /system/state */
-	base.len-- ;
 	size_t statelen ;
 	char state[base.len + SS_SYSTEM_LEN + SS_STATE_LEN + 1] ;
 	memcpy(state,base.s,base.len) ;
@@ -304,10 +303,10 @@ int main(int argc, char const *const *argv,char const *const *envp)
 		if(!stralloc_cats(&tree,treename)) retstralloc(111,"main") ;
 		if(!stralloc_0(&tree)) retstralloc(111,"main") ;
 		
-		r = tree_sethome(&tree,base.s) ;
+		r = tree_sethome(&tree,base.s,owner) ;
 		if (r < 0 || !r) strerr_diefu2sys(111,"find tree: ", tree.s) ;
 	
-		if (!tree_get_permissions(tree.s))
+		if (!tree_get_permissions(tree.s,owner))
 			strerr_dief2x(110,"You're not allowed to use the tree: ",tree.s) ;
 		
 		if (what)
@@ -345,15 +344,17 @@ int main(int argc, char const *const *argv,char const *const *envp)
 		if (!doit(tree.s,treename,live.s,what,envp)) strerr_warnwu3x((what) ? "start" : "stop" , " service for tree: ",treename) ;
 	}
 	end:
-		while((fd = open("/dev/tty",O_RDWR|O_NOCTTY)) >= 0)
+		if (shut)
 		{
-			if (fd >= 3) break ;
+			while((fd = open("/dev/tty",O_RDWR|O_NOCTTY)) >= 0)
+			{
+				if (fd >= 3) break ;
+			}
+			dup2 (fd,0) ;
+			dup2 (fd,1) ;
+			dup2 (fd,2) ;
+			fd_close(fd) ;
 		}
-		dup2 (fd,0) ;
-		dup2 (fd,1) ;
-		dup2 (fd,2) ;
-		fd_close(fd) ;
-
 		stralloc_free(&base) ;
 		stralloc_free(&live) ;
 		stralloc_free(&tree) ;
diff --git a/src/66/66-dbctl.c b/src/66/66-dbctl.c
index 6620080e147c60e0c8b0ce19fdbf01963fad03be..a3b90107e75f1e93fc320c8721dba46eeb6c0c03 100644
--- a/src/66/66-dbctl.c
+++ b/src/66/66-dbctl.c
@@ -12,281 +12,23 @@
  * except according to the terms contained in the LICENSE file./
  */
 
-#include <string.h>
-#include <sys/stat.h>
-#include <stdlib.h>
+#include <skalibs/strerr2.h>
 
-#include <oblibs/obgetopt.h>
-#include <oblibs/error2.h>
-#include <oblibs/directory.h>
-#include <oblibs/types.h>
-#include <oblibs/string.h>
-#include <oblibs/stralist.h>
-
-#include <skalibs/buffer.h>
-#include <skalibs/types.h>
-#include <skalibs/stralloc.h>
-#include <skalibs/djbunix.h>
-#include <skalibs/selfpipe.h>
-#include <skalibs/iopause.h>
-#include <skalibs/sig.h>
-
-#include <s6-rc/config.h>
-#include <s6/s6-supervise.h>
-
-#include <66/utils.h>
-#include <66/constants.h>
-#include <66/db.h>
-#include <66/tree.h>
-#include <66/enum.h>
-
-//#include <stdio.h>
+#include <66/ssexec.h>
 
 unsigned int VERBOSITY = 1 ;
-static unsigned int DEADLINE = 0 ;
-stralloc saresolve = STRALLOC_ZERO ;
-
-#define USAGE "66-dbctl [ -h ] [ -v verbosity ] [ -T timeout ] [ -l live ] [ -t tree ] [ -u | d | r ] service(s)"
-
-static inline void info_help (void)
-{
-  static char const *help =
-"66-dbctl <options> tree\n"
-"\n"
-"options :\n"
-"	-h: print this help\n" 
-"	-v: increase/decrease verbosity\n"
-"	-T: timeout\n"
-"	-l: live directory\n"
-"	-t: tree to use\n"
-"	-u: bring up service in database of tree\n"
-"	-d: bring down service in database of tree\n"
-"	-r: reload service\n"
-;
-
- if (buffer_putsflush(buffer_1, help) < 0)
-    strerr_diefu1sys(111, "write to stdout") ;
-}
-static pid_t send(genalloc *gasv, char const *livetree, char const *signal,char const *const *envp)
-{
-	char const *newargv[10 + genalloc_len(stralist,gasv)] ;
-	unsigned int m = 0 ;
-	char fmt[UINT_FMT] ;
-	fmt[uint_fmt(fmt, VERBOSITY)] = 0 ;
-	
-	char tt[UINT32_FMT] ;
-	tt[uint32_fmt(tt,DEADLINE)] = 0 ;
-	
-	newargv[m++] = S6RC_BINPREFIX "s6-rc" ;
-	newargv[m++] = "-v" ;
-	newargv[m++] = fmt ;
-	newargv[m++] = "-t" ;
-	newargv[m++] = tt ;
-	newargv[m++] = "-l" ;
-	newargv[m++] = livetree ;
-	newargv[m++] = signal ;
-	newargv[m++] = "change" ;
-	
-	for (unsigned int i = 0 ; i<genalloc_len(stralist,gasv); i++)
-		newargv[m++] = gaistr(gasv,i) ;
-	
-	newargv[m++] = 0 ;
-	
-	
-	return child_spawn0(newargv[0],newargv,envp) ;
-	
-}
 
 int main(int argc, char const *const *argv,char const *const *envp)
 {
-	int r ;
-	unsigned int up, down, reload ;
-	
-	int wstat ;
-	pid_t pid ;
-	
-	uid_t owner ;
-	
-	char *treename = 0 ;
-	char *signal = 0 ;
-	char *mainsv = "Master" ;
-	
-	stralloc base = STRALLOC_ZERO ;
-	stralloc tree = STRALLOC_ZERO ;
-	stralloc live = STRALLOC_ZERO ;
-	stralloc livetree = STRALLOC_ZERO ;
-	stralloc scandir = STRALLOC_ZERO ;
-	
-	genalloc gasv = GENALLOC_ZERO ; //stralist
-	
-	up = down = reload = 0 ;
-		
 	PROG = "66-dbctl" ;
-	{
-		subgetopt_t l = SUBGETOPT_ZERO ;
-
-		for (;;)
-		{
-			int opt = getopt_args(argc,argv, "hv:l:t:udT:r", &l) ;
-			if (opt == -1) break ;
-			if (opt == -2) strerr_dief1x(110,"options must be set first") ;
-			switch (opt)
-			{
-				case 'h' : 	info_help(); return 0 ;
-				case 'v' :  if (!uint0_scan(l.arg, &VERBOSITY)) exitusage() ; break ;
-				case 'l' : 	if (!stralloc_cats(&live,l.arg)) retstralloc(111,"main") ;
-							if (!stralloc_0(&live)) retstralloc(111,"main") ;
-							break ;
-				case 'T' :	if (!uint0_scan(l.arg, &DEADLINE)) exitusage() ; break ;
-				case 't' : 	if(!stralloc_cats(&tree,l.arg)) retstralloc(111,"main") ;
-							if(!stralloc_0(&tree)) retstralloc(111,"main") ;
-							break ;
-				case 'u' :	up = 1 ; if (down) exitusage() ; break ;
-				case 'd' : 	down = 1 ; if (up) exitusage() ; break ;
-				case 'r' : 	reload = 1 ; if (down || up) exitusage() ; break ;
-				default : exitusage() ; 
-			}
-		}
-		argc -= l.ind ; argv += l.ind ;
-	}
-
-	if (argc < 1) if (!stra_add(&gasv,mainsv)) strerr_diefu1sys(111,"add: Master as service to handle") ;
-	
-	owner = MYUID ;
-
-	if (!set_ownersysdir(&base,owner)) strerr_diefu1sys(111, "set owner directory") ;
-	
-	r = tree_sethome(&tree,base.s) ;
-	if (r < 0) strerr_diefu1x(110,"find the current tree. You must use -t options") ;
-	if (!r) strerr_diefu2sys(111,"find tree: ", tree.s) ;
-	
-	treename = tree_setname(tree.s) ;
-	if (!treename) strerr_diefu1x(111,"set the tree name") ;
-		
-	if (!tree_get_permissions(tree.s))
-		strerr_dief2x(110,"You're not allowed to use the tree: ",tree.s) ;
-		
-	r = set_livedir(&live) ;
-	if (!r) retstralloc(111,"main") ;
-	if (r < 0 ) strerr_dief3x(111,"live: ",live.s," must be an absolute path") ;
-	
-	if (!stralloc_copy(&scandir,&live)) retstralloc(111,"main") ;
-	
-	r = set_livescan(&scandir,owner) ;
-	if (!r) retstralloc(111,"main") ;
-	if (r < 0 ) strerr_dief3x(111,"scandir: ",scandir.s," must be an absolute path") ;
-	
-	if ((scandir_ok(scandir.s)) !=1 ) strerr_dief3sys(111,"scandir: ", scandir.s," is not running") ;
-	
-	if (!stralloc_copy(&livetree,&live)) retstralloc(111,"main") ;
-	
-	r = set_livetree(&livetree,owner) ;
-	if (!r) retstralloc(111,"main") ;
-	if (r < 0 ) strerr_dief3x(111,"livetree: ",livetree.s," must be an absolute path") ;
-	
-	if (!db_ok(livetree.s,treename))
-		strerr_dief5sys(111,"db: ",livetree.s,"/",treename," is not running") ;
-
-	for(;*argv;argv++)
-		if (!stra_add(&gasv,*argv)) strerr_diefu3sys(111,"add: ",*argv," as service to handle") ;
-	
-	livetree.len-- ;
-	if (!stralloc_cats(&livetree,"/")) retstralloc(111,"main") ;
-	if (!stralloc_cats(&livetree,treename)) retstralloc(111,"main") ;
-	if (!stralloc_0(&livetree)) retstralloc(111,"main") ;
-	
-	if (reload)
-	{
-		pid = send(&gasv,livetree.s,"-d",envp) ;
-		
-		if (waitpid_nointr(pid,&wstat, 0) < 0)
-			strerr_diefu1sys(111,"wait for s6-rc") ;
-		
-		if (wstat)
-		{
-			if (down)
-				strerr_diefu1x(111,"bring down services list") ;
-			else
-				strerr_diefu1x(111,"bring up services list") ;
-		}
-	}
-	
-	if (down) signal = "-d" ;
-	else signal = "-u" ;
-	
-	pid = send(&gasv,livetree.s,signal,envp) ;
-	
-	if (waitpid_nointr(pid,&wstat, 0) < 0)
-		strerr_diefu1sys(111,"wait for s6-rc") ;
-	
-	if (wstat)
-	{
-		if (down)
-			strerr_diefu1x(111,"bring down services list") ;
-		else
-			strerr_diefu1x(111,"bring up services list") ;
-	}
-	/** we are forced to do this ugly check cause of the design
-	 * of s6-rc(generally s6-svc) which is launch and forgot. So
-	 * s6-rc will not warn us if the daemon fail when we don't use
-	 * readiness which is rarely used on DESKTOP configuration due of
-	 * the bad design of the majority of daemon.
-	 * The result of the check is not guaranted due of the rapidity of the code.
-	 * between the end of the s6-rc process and the check of the daemon status,
-	 * the real value of the status can be not written yet,so we can hit
-	 * this window.*/
-	s6_svstatus_t status = S6_SVSTATUS_ZERO ;
-	stralloc stat = STRALLOC_ZERO ;
-	if (!stralloc_catb(&stat,livetree.s,livetree.len - 1)) retstralloc(111,"main") ; 
-	
-	if (!stralloc_cats(&stat,SS_SVDIRS)) retstralloc(111,"main") ; 
-	if (!stralloc_cats(&stat,"/")) retstralloc(111,"main") ; 
-	size_t newlen = stat.len ;
 	
-	if (!resolve_pointo(&saresolve,base.s,live.s,tree.s,treename,0,SS_RESOLVE_SRC))
-		strerr_diefu1x(111,"set revolve pointer to source") ;
+	ssexec_t info = SSEXEC_ZERO ;
 	
-	stralloc type = STRALLOC_ZERO ;
-		
-	for (unsigned int i = 0; i < genalloc_len(stralist,&gasv) ; i++)
-	{
-		char *svname = gaistr(&gasv,i) ;
-		if (resolve_read(&type,saresolve.s,svname,"type") <= 0)
-			strerr_diefu2sys(111,"read type of: ",svname) ;
-		
-		if (get_enumbyid(type.s,key_enum_el) == LONGRUN)
-		{
-			stat.len = newlen ;
-			
-			if (!stralloc_cats(&stat,svname)) retstralloc(111,"main") ; 
-			if (!stralloc_0(&stat)) retstralloc(111,"main") ; 
-			
-			if (!s6_svstatus_read(stat.s,&status)) strerr_diefu2sys(111,"read status of: ",stat.s) ;
-					
-			if (down)
-			{
-				if (WEXITSTATUS(status.wstat) && WIFEXITED(status.wstat) && status.pid)
-					strerr_diefu2x(111,"stop: ",svname) ;
-			}
-			if (up)
-			{
-				if (WEXITSTATUS(status.wstat) && WIFEXITED(status.wstat))
-					strerr_diefu2x(111,"start: ",svname) ;
-			}
-		}
-	}
-		
-	stralloc_free(&base) ;
-	stralloc_free(&live) ;
-	stralloc_free(&tree) ;
-	stralloc_free(&livetree) ;
-	stralloc_free(&scandir) ;
-	stralloc_free(&stat) ;
-	stralloc_free(&type) ;
-	stralloc_free(&saresolve) ;
-	free(treename) ;
+	info.prog = PROG ;
+	info.help = help_dbctl ;
+	info.usage = usage_dbctl ;
 	
-	return 0 ;
+	return ssexec_main(argc,argv,envp,&ssexec_dbctl,&info) ;
 }
 	
 
diff --git a/src/66/66-disable.c b/src/66/66-disable.c
index cd700b4269247dc4fddc25010a4fb787858e6d88..1fa3a1f413b934bfeeb83089ca730254f66ad1fd 100644
--- a/src/66/66-disable.c
+++ b/src/66/66-disable.c
@@ -12,497 +12,23 @@
  * except according to the terms contained in the LICENSE file./
  */
 
-#include <string.h>
-#include <sys/stat.h>
-#include <stdlib.h>
+#include <skalibs/strerr2.h>
 
-#include <oblibs/obgetopt.h>
-#include <oblibs/error2.h>
-#include <oblibs/directory.h>
-#include <oblibs/types.h>
-#include <oblibs/string.h>
-#include <oblibs/files.h>
-#include <oblibs/stralist.h>
-
-#include <skalibs/stralloc.h>
-#include <skalibs/genalloc.h>
-#include <skalibs/djbunix.h>
-#include <skalibs/buffer.h>
-#include <skalibs/unix-transactional.h>
-#include <skalibs/direntry.h>
-#include <skalibs/diuint32.h>
- 
-#include <66/constants.h>
-#include <66/utils.h>
-#include <66/enum.h>
-#include <66/tree.h>
-#include <66/db.h>
-#include <66/backup.h>
-#include <66/graph.h>
-
-//#include <stdio.h>
-
-static stralloc saresolve = STRALLOC_ZERO ;
+#include <66/ssexec.h>
 
 unsigned int VERBOSITY = 1 ;
 
-#define USAGE "66-disable [ -h help ] [ -v verbosity ] [ - l live ] [ -t tree ] [ -S ] service(s)"
-
-static inline void info_help (void)
-{
-  static char const *help =
-"66-disable <options> service(s)\n"
-"\n"
-"options :\n"
-"	-h: print this help\n" 
-"	-v: increase/decrease verbosity\n"
-"	-l: live directory\n"
-"	-t: name of the tree to use\n"
-"	-S: disable and stop the service\n"
-;
-
- if (buffer_putsflush(buffer_1, help) < 0)
-    strerr_diefu1sys(111, "write to stdout") ;
-}
-
-static void cleanup(char const *dst)
-{
-	int e = errno ;
-	rm_rf(dst) ;
-	errno = e ;
-}
-
-int find_logger(genalloc *ga, char const *name, char const *src)
-{
-	stralloc sa = STRALLOC_ZERO ;
-	if (resolve_read(&sa,src,name,"logger"))
-	{
-		if (!stra_add(ga,sa.s))
-		{
-			stralloc_free(&sa) ;
-			return 0 ;
-		}
-	}
-	stralloc_free(&sa) ;
-	return 1 ;
-}
-
-int remove_sv(genalloc *toremove, char const *name, char const *src, unsigned int type)
-{
-	int r ;
-
-	size_t namelen = strlen(name) ;
-	size_t srclen = strlen(src) ;
-	size_t newlen ;
-		
-	/** classic service */
-	if (type == CLASSIC)
-	{
-		char dst[srclen + SS_SVC_LEN + 1 + namelen + 1] ;
-		memcpy(dst,src,srclen) ;
-		memcpy(dst + srclen, SS_SVC, SS_SVC_LEN) ;
-		dst[srclen + SS_SVC_LEN]  =  '/' ;
-		memcpy(dst + srclen + SS_SVC_LEN + 1, name, namelen) ;
-		dst[srclen + SS_SVC_LEN + 1 + namelen] = 0 ;
-		
-		VERBO3 strerr_warnt3x("Removing ",dst + srclen + 1," service ... ") ;
-		if (rm_rf(dst) < 0)
-		{
-			VERBO3 strerr_warnwu2sys("remove: ", dst) ;
-			return 0 ;
-		}
-				
-		return 1 ;
-	}
-	
-	stralloc sa = STRALLOC_ZERO ;
-	genalloc gatmp = GENALLOC_ZERO ;// type stralist
-	
-	graph_t g = GRAPH_ZERO ;
-	stralloc sagraph = STRALLOC_ZERO ;
-	genalloc tokeep = GENALLOC_ZERO ;
-	
-	/** rc services */
-	{
-		/** build dependencies graph*/
-		r = graph_type_src(&tokeep,src,1) ;
-		if (r <= 0)
-		{
-			strerr_warnwu2x("resolve source of graph for tree: ",src) ;
-			goto err ;
-		}
-		if (!graph_build(&g,&sagraph,&tokeep,src))
-		{
-			strerr_warnwu1x("make dependencies graph") ;
-			goto err ;
-		}
-	
-		if (!stra_add(toremove,name)) 
-		{	 
-			VERBO3 strerr_warnwu3x("add: ",name," as dependency to remove") ;
-			goto err ;
-		}
-		
-		r = graph_rdepends(toremove,&g,name,src) ;
-		if (!r) 
-		{
-			VERBO3 strerr_warnwu2x("find services depending for: ",name) ;
-			goto err ;
-		}
-		if(r == 2) VERBO3 strerr_warnt2x("any services don't depends of: ",name) ;
-		
-		if (!stralloc_catb(&sa,src,srclen)) retstralloc(0,"remove_sv") ;
-		if (!stralloc_cats(&sa,SS_DB SS_SRC)) retstralloc(0,"remove_sv") ;
-		if (!stralloc_cats(&sa, "/")) retstralloc(0,"remove_sv") ;
-		newlen = sa.len ;
-		if (genalloc_len(stralist,toremove))
-			if (!find_logger(toremove,name,src)) goto err ;
-			
-		for (unsigned int i = 0; i < genalloc_len(stralist,toremove); i++)
-		{
-			sa.len = newlen ;
-			if (!stralloc_cats(&sa,gaistr(toremove,i))) retstralloc(0,"remove_sv") ;
-			if (!stralloc_0(&sa)) retstralloc(0,"remove_sv") ;
-			VERBO3 strerr_warnt3x("Removing ",sa.s + srclen + 1," service ...") ;
-			if (rm_rf(sa.s) < 0)
-			{
-				VERBO3 strerr_warnwu2sys("remove: ", sa.s) ;
-				goto err ;
-			}
-		}
-
-	}
-	
-	genalloc_free(vertex_graph_t,&g.stack) ;
-	genalloc_free(vertex_graph_t,&g.vertex) ;
-	stralloc_free(&sagraph) ;
-	stralloc_free(&sa) ;
-	genalloc_deepfree(stralist,&gatmp,stra_free) ;
-	
-	return 1 ;
-	
-	err:
-		genalloc_free(vertex_graph_t,&g.stack) ;
-		genalloc_free(vertex_graph_t,&g.vertex) ;
-		stralloc_free(&sagraph) ;
-		stralloc_free(&sa) ;
-		genalloc_deepfree(stralist,&gatmp,stra_free) ;
-		return 0 ;
-}
-		
 int main(int argc, char const *const *argv,char const *const *envp)
 {
-	int r,rb ;
-	unsigned int nlongrun, nclassic, stop ;
-	
-	uid_t owner ;
-	
-	char *treename = 0 ;
-	
-	stralloc base = STRALLOC_ZERO ;
-	stralloc tree = STRALLOC_ZERO ;
-	stralloc workdir = STRALLOC_ZERO ;
-	stralloc live = STRALLOC_ZERO ;
-	stralloc livetree = STRALLOC_ZERO ;
-	
-	genalloc ganlong = GENALLOC_ZERO ; //name of longrun service, type stralist
-	genalloc ganclassic = GENALLOC_ZERO ; //name of classic service, stralist
-	genalloc gadepstoremove = GENALLOC_ZERO ;
-	
-	graph_t g = GRAPH_ZERO ;
-	stralloc sagraph = STRALLOC_ZERO ;
-	genalloc tokeep = GENALLOC_ZERO ;
-	genalloc master = GENALLOC_ZERO ;
-	
-	r = nclassic = nlongrun = stop = 0 ;
-		
 	PROG = "66-disable" ;
-	{
-		subgetopt_t l = SUBGETOPT_ZERO ;
-
-		for (;;)
-		{
-			int opt = getopt_args(argc,argv, ">hv:l:t:S", &l) ;
-			if (opt == -1) break ;
-			if (opt == -2) strerr_dief1x(110,"options must be set first") ;
-			switch (opt)
-			{
-				case 'h' : 	info_help(); return 0 ;
-				case 'v' :  if (!uint0_scan(l.arg, &VERBOSITY)) exitusage() ; break ;
-				case 'l' :  if(!stralloc_cats(&live,l.arg)) retstralloc(111,"main") ;
-							if(!stralloc_0(&live)) retstralloc(111,"main") ;
-							break ;
-				case 't' : 	if(!stralloc_cats(&tree,l.arg)) retstralloc(111,"main") ;
-							if(!stralloc_0(&tree)) retstralloc(111,"main") ;
-							break ;
-				case 'S' :	stop = 1 ;	break ;
-				default : exitusage() ; 
-			}
-		}
-		argc -= l.ind ; argv += l.ind ;
-	}
-	
-	if (argc < 1) exitusage() ;
-	
-	owner = MYUID ;
-	if (!set_ownersysdir(&base,owner)) strerr_diefu1sys(111, "set owner directory") ;
-	
-	r = tree_sethome(&tree,base.s) ;
-	if (r < 0) strerr_diefu1x(110,"find the current tree. You must use -t options") ;
-	if (!r) strerr_diefu2sys(111,"find tree: ", tree.s) ;
-	
-	treename = tree_setname(tree.s) ;
-	if (!treename) strerr_diefu1x(111,"set the tree name") ;
-		
-	if (!tree_get_permissions(tree.s))
-		strerr_dief2x(110,"You're not allowed to use the tree: ",tree.s) ;
 	
-	r = set_livedir(&live) ;
-	if (!r) retstralloc(111,"main") ;
-	if(r < 0) strerr_dief3x(111,"live: ",live.s," must be an absolute path") ;
-	
-	if (!stralloc_copy(&livetree,&live)) retstralloc(111,"main") ;
-		
-	r = set_livetree(&livetree,owner) ;
-	if (!r) retstralloc(111,"main") ;
-	if(r < 0) strerr_dief3x(111,"livetree: ",livetree.s," must be an absolute path") ;
-	
-	
-	if (!tree_copy(&workdir,tree.s,treename)) strerr_diefu1sys(111,"create tmp working directory") ;
-	
-	{
-		stralloc type = STRALLOC_ZERO ;
-		
-		for(;*argv;argv++)
-		{
-			if (!resolve_pointo(&saresolve,base.s,live.s,tree.s,treename,0,SS_RESOLVE_SRC))
-			{
-				cleanup(workdir.s) ;
-				strerr_diefu1x(111,"set revolve pointer to source") ;
-			}
-			rb = resolve_read(&type,saresolve.s,*argv,"remove") ;
-			if (rb) 
-			{
-				strerr_warni2x(*argv,": is already disabled") ;
-				continue ;
-			}
-			rb = resolve_read(&type,saresolve.s,*argv,"type") ;
-			if (rb < -1)
-			{
-				cleanup(workdir.s) ;
-				strerr_dief2x(111,"invalid .resolve directory: ",saresolve.s) ;
-			}
-			if (rb <= 0)
-			{
-				cleanup(workdir.s) ;
-				strerr_dief2x(111,*argv,": is not enabled") ;
-			}
-			
-			if (get_enumbyid(type.s,key_enum_el) == CLASSIC)
-			{
-				if (!stra_add(&ganclassic,*argv)) retstralloc(111,"main") ;
-				nclassic++ ;
-			}					
-			if (get_enumbyid(type.s,key_enum_el) >= BUNDLE)
-			{
-				if (!stra_add(&ganlong,*argv)) retstralloc(111,"main") ;
-				nlongrun++ ;
-			}
-		}
-		stralloc_free(&type) ;
-	}
-
-	if (nclassic)
-	{
-		VERBO2 strerr_warni1x("remove svc services ... ") ;
-		for (unsigned int i = 0 ; i < genalloc_len(stralist,&ganclassic) ; i++)
-		{
-			char *name = gaistr(&ganclassic,i) ;
-			
-			if (!remove_sv(&gadepstoremove,name,workdir.s,CLASSIC))
-			{
-				cleanup(workdir.s) ;
-				strerr_diefu2x(111,"disable: ",name) ;
-			}
-			
-			/** modify the resolve file for 66-stop*/
-			if (!resolve_write(workdir.s,gaistr(&ganclassic,i),"remove","",1))
-			{
-				cleanup(workdir.s) ;
-				strerr_diefu2sys(111,"write resolve file: remove for service: ",gaistr(&ganclassic,i)) ;
-			}
-		}
-		char type[UINT_FMT] ;
-		size_t typelen = uint_fmt(type, CLASSIC) ;
-		type[typelen] = 0 ;
-		size_t cmdlen ;
-		char cmd[typelen + 6 + 1] ;
-		memcpy(cmd,"-t",2) ;
-		memcpy(cmd + 2,type,typelen) ;
-		cmdlen = 2 + typelen ;
-		memcpy(cmd + cmdlen," -b",3) ;
-		cmd[cmdlen + 3] = 0 ;
-		r = backup_cmd_switcher(VERBOSITY,cmd,treename) ;
-		if (r < 0)
-		{
-			cleanup(workdir.s) ;
-			strerr_diefu2sys(111,"find origin of svc: ",treename) ;
-		}
-		// point to origin
-		if (!r)
-		{
-			stralloc sv = STRALLOC_ZERO ;
-			VERBO2 strerr_warni2x("make backup svc of ",treename) ;
-			if (!backup_make_new(base.s,tree.s,treename,CLASSIC))
-			{
-				cleanup(workdir.s) ;
-				strerr_diefu2sys(111,"make a backup of db: ",treename) ;
-			}
-			memcpy(cmd + cmdlen," -s1",4) ;
-			cmd[cmdlen + 4] = 0 ;
-			r = backup_cmd_switcher(VERBOSITY,cmd,treename) ;
-			if (r < 0)
-			{
-				cleanup(workdir.s) ;
-				strerr_diefu3sys(111,"switch current db: ",treename," to source") ;
-			}
-			/** creer le fichier torelaod*/
-			stralloc_free(&sv) ;
-		}
-		gadepstoremove = genalloc_zero ;
-	}
-	
-	if (nlongrun)
-	{	
-		
-		VERBO2 strerr_warni1x("remove rc services ... ") ;
-		for (unsigned int i = 0 ; i < genalloc_len(stralist,&ganlong) ; i++)
-		{
-			char *name = gaistr(&ganlong,i) ;
-			
-			if (!remove_sv(&gadepstoremove,name,workdir.s,LONGRUN))
-			{
-				cleanup(workdir.s) ;
-				strerr_diefu2x(111,"disable: ",name) ;
-			}
-		}
-
-		for (unsigned int i = 0 ; i < genalloc_len(stralist,&gadepstoremove) ; i++ )
-		{
-			// modify the resolve file for 66-stop*/
-			if (!resolve_write(workdir.s,gaistr(&gadepstoremove,i),"remove","",1))
-			{
-				cleanup(workdir.s) ;
-				strerr_diefu2sys(111,"write resolve file: remove for service: ",gaistr(&gadepstoremove,i)) ;
-			}
-		}
-		
-		r = graph_type_src(&tokeep,workdir.s,1) ;
-		if (!r)
-		{
-			cleanup(workdir.s) ;
-			strerr_diefu2x(111,"resolve source of graph for tree: ",treename) ;
-		}
-		if (r < 0)
-		{
-			if (!stra_add(&master,"")) retstralloc(111,"main") ;
-		}
-		else 
-		{
-			if (!graph_build(&g,&sagraph,&tokeep,workdir.s))
-			{
-				cleanup(workdir.s) ;
-				strerr_diefu1x(111,"make dependencies graph") ;
-			}
-			if (!graph_sort(&g))
-			{
-				cleanup(workdir.s) ;
-				strerr_dief1x(111,"cyclic graph detected") ;
-			}
-			if (!graph_master(&master,&g))
-			{
-				cleanup(workdir.s) ;
-				strerr_dief1x(111,"find master service") ;
-			}
-		}
-		
-		
-		if (!db_write_contents(&master,SS_MASTER + 1,workdir.s))
-		{
-			cleanup(workdir.s) ;
-			strerr_diefu2x(111,"update bundle: ", SS_MASTER) ;
-		}
-			
-		if (!db_compile(workdir.s,tree.s,treename,envp))
-		{
-			cleanup(workdir.s) ;
-			strerr_diefu4x(111,"compile ",workdir.s,"/",treename) ; 
-		}
-		
-		/** this is an important part, we call s6-rc-update here */
-		if (!db_switch_to(base.s,livetree.s,tree.s,treename,envp,SS_SWBACK))
-		{
-			cleanup(workdir.s) ;
-			strerr_diefu3x(111,"switch ",treename," to backup") ;
-		}
-		
-	}
-	
-	if (!tree_copy_tmp(workdir.s,base.s,live.s,tree.s,treename))
-	{
-		cleanup(workdir.s) ;
-		strerr_diefu4x(111,"copy: ",workdir.s," to: ", tree.s) ;
-	}
-	
-	if (stop)
-	{
-		size_t arglen = 9 + genalloc_len(stralist,&ganclassic) + genalloc_len(stralist,&ganlong) ;
-		char const *newstop[arglen] ;
-		unsigned int m = 0 ;
-		char fmt[UINT_FMT] ;
-		fmt[uint_fmt(fmt, VERBOSITY)] = 0 ;
-		
-		newstop[m++] = SS_BINPREFIX "66-stop" ;
-		newstop[m++] = "-v" ;
-		newstop[m++] = fmt ;
-		newstop[m++] = "-l" ;
-		newstop[m++] = live.s ;
-		newstop[m++] = "-t" ;
-		newstop[m++] = treename ;
-		newstop[m++] = "-u" ;
-		/** classic */
-		for (unsigned int i = 0 ; i<genalloc_len(stralist,&ganclassic); i++)
-			newstop[m++] = gaistr(&ganclassic,i) ;
-		/** rc */
-		for (unsigned int i = 0 ; i<genalloc_len(stralist,&ganlong); i++)
-			newstop[m++] = gaistr(&ganlong,i) ;
-		
-		newstop[m++] = 0 ;
-		
-		xpathexec_run (newstop[0], newstop, envp) ;
-	}
-	
-	cleanup(workdir.s) ;
-
-	stralloc_free(&base) ;
-	stralloc_free(&tree) ;
-	stralloc_free(&workdir) ;
-	stralloc_free(&live) ;
-	stralloc_free(&livetree) ;
+	ssexec_t info = SSEXEC_ZERO ;
 	
-	genalloc_deepfree(stralist,&ganlong,stra_free) ;
-	genalloc_deepfree(stralist,&ganclassic,stra_free) ;
-	genalloc_deepfree(stralist,&gadepstoremove,stra_free) ;
-	free(treename) ;
-		
-	/** graph stuff */
-	genalloc_free(vertex_graph_t,&g.stack) ;
-	genalloc_free(vertex_graph_t,&g.vertex) ;
-	stralloc_free(&sagraph) ;	
-	genalloc_deepfree(stralist,&master,stra_free) ;
-	genalloc_deepfree(stralist,&tokeep,stra_free) ;
+	info.prog = PROG ;
+	info.help = help_disable ;
+	info.usage = usage_disable ;
 	
-	return 0 ;		
+	return ssexec_main(argc,argv,envp,&ssexec_disable,&info) ;
 }
 	
 
diff --git a/src/66/66-enable.c b/src/66/66-enable.c
index ae7ccf7c53d38aa20e62737e729749b7f09cdb2f..d653fd67356bab0b814bddf95e510e8ab3d34fd0 100644
--- a/src/66/66-enable.c
+++ b/src/66/66-enable.c
@@ -12,327 +12,23 @@
  * except according to the terms contained in the LICENSE file./
  */
 
-#include <string.h>
-#include <sys/stat.h>
-#include <stdlib.h>
+#include <skalibs/strerr2.h>
 
-#include <oblibs/obgetopt.h>
-#include <oblibs/error2.h>
-#include <oblibs/directory.h>
-#include <oblibs/files.h>
-#include <oblibs/string.h>
-#include <oblibs/types.h>
-#include <oblibs/stralist.h>
+#include <66/ssexec.h>
 
-#include <skalibs/stralloc.h>
-#include <skalibs/genalloc.h>
-#include <skalibs/djbunix.h>
-#include <skalibs/buffer.h>
-#include <skalibs/direntry.h>
-#include <skalibs/unix-transactional.h>
-#include <skalibs/diuint32.h>
-
-#include <66/constants.h>
-#include <66/utils.h>
-#include <66/enum.h>
-#include <66/tree.h>
-#include <66/db.h>
-#include <66/parser.h>
-#include <66/backup.h>
-#include <66/svc.h>
-#include <66/graph.h>
-
-//#include <stdio.h>
-
-static unsigned int FORCE = 0 ;
 unsigned int VERBOSITY = 1 ;
 
-stralloc saresolve = STRALLOC_ZERO ;
-
-#define USAGE "66-enable [ -h help ] [ -v verbosity ] [ - l live ] [ -t tree ] [ -f ] [ -S ] service(s)"
-
-static inline void info_help (void)
-{
-  static char const *help =
-"66-enable <options> service(s)\n"
-"\n"
-"options :\n"
-"	-h: print this help\n" 
-"	-v: increase/decrease verbosity\n"
-"	-l: live directory\n"
-"	-t: name of the tree to use\n"
-"	-f: overwrite service(s)\n"
-"	-S: enable and start the service\n"
-;
-
- if (buffer_putsflush(buffer_1, help) < 0)
-    strerr_diefu1sys(111, "write to stdout") ;
-}
-
-static void cleanup(char const *dst)
-{
-	int e = errno ;
-	rm_rf(dst) ;
-	errno = e ;
-}
-
-static int start_parser(char const *src,char const *svname,char const *tree, unsigned int *nbsv)
-{
-	stralloc sasv = STRALLOC_ZERO ;
-	
-	if (!parse_service_before(src,svname,tree,nbsv,&sasv)) strerr_dief4x(111,"invalid service file: ",src,"/",svname) ;
-	
-	stralloc_free(&sasv) ;
-	
-	return 1 ;
-}
-
 int main(int argc, char const *const *argv,char const *const *envp)
 {
-	int r ;
-	unsigned int nbsv, nlongrun, nclassic, start ;
-	
-	uid_t owner ;
-	
-	char const *src = SS_SERVICE_DIR ;
-	char *treename = 0 ;
-	
-	stralloc base = STRALLOC_ZERO ;//SS_SYSTEM
-	stralloc tree = STRALLOC_ZERO ;//-t options
-	stralloc workdir = STRALLOC_ZERO ;//working dir directory
-	stralloc live = STRALLOC_ZERO ;
-	stralloc livetree = STRALLOC_ZERO ;
-	stralloc sasrc = STRALLOC_ZERO ;
-	genalloc gasrc = GENALLOC_ZERO ; //type diuint32
-	genalloc ganlong = GENALLOC_ZERO ; // type stralist
-	genalloc ganclassic = GENALLOC_ZERO ; // name of classic service, type stralist
-	
-	graph_t g = GRAPH_ZERO ;
-	stralloc sagraph = STRALLOC_ZERO ;
-	genalloc master = GENALLOC_ZERO ;
-	genalloc tokeep = GENALLOC_ZERO ;
-	
-	r = nbsv = nclassic = nlongrun = start = 0 ;
-		
 	PROG = "66-enable" ;
-	{
-		subgetopt_t l = SUBGETOPT_ZERO ;
-
-		for (;;)
-		{
-			int opt = getopt_args(argc,argv, ">hv:l:t:fS", &l) ;
-			if (opt == -1) break ;
-			if (opt == -2) strerr_dief1x(110,"options must be set first") ;
-			switch (opt)
-			{
-				case 'h' : 	info_help(); return 0 ;
-				case 'v' :  if (!uint0_scan(l.arg, &VERBOSITY)) exitusage() ; break ;
-				case 'l' :  if(!stralloc_cats(&live,l.arg)) retstralloc(111,"main") ;
-							if(!stralloc_0(&live)) retstralloc(111,"main") ;
-							break ;
-				case 't' : 	if(!stralloc_cats(&tree,l.arg)) retstralloc(111,"main") ;
-							if(!stralloc_0(&tree)) retstralloc(111,"main") ;
-							break ;
-				case 'f' : 	FORCE = 1 ; break ;
-				case 'S' :	start = 1 ;	break ;
-				default : exitusage() ; 
-			}
-		}
-		argc -= l.ind ; argv += l.ind ;
-	}
-	
-	if (argc < 1) exitusage() ;
-	
-	owner = MYUID ;
-	
-	if (!set_ownersysdir(&base,owner)) strerr_diefu1sys(111, "set owner directory") ;
-	
-	r = tree_sethome(&tree,base.s) ;
-	if (r < 0) strerr_diefu1x(110,"find the current tree. You must use -t options") ;
-	if (!r) strerr_diefu2sys(111,"find tree: ", tree.s) ;
-	
-	
-	treename = tree_setname(tree.s) ;
-	if (!treename) strerr_diefu1x(111,"set the tree name") ;
-	
-	if (!tree_get_permissions(tree.s))
-		strerr_dief2x(110,"You're not allowed to use the tree: ",tree.s) ;
-	
-	r = set_livedir(&live) ;
-	if (!r) retstralloc(111,"main") ;
-	if(r < 0) strerr_dief3x(111,"live: ",live.s," must be an absolute path") ;
-	
-	if (!stralloc_copy(&livetree,&live)) retstralloc(111,"main") ;
-		
-	r = set_livetree(&livetree,owner) ;
-	if (!r) retstralloc(111,"main") ;
-	if(r < 0) strerr_dief3x(111,"livetree: ",livetree.s," must be an absolute path") ;
-	
-	for(;*argv;argv++)
-	{
-		unsigned int found = 0 ;
-		if (!resolve_src(&gasrc,&sasrc,*argv,src,&found)) strerr_diefu2x(111,"resolve source of service file: ",*argv) ;
-	}
-	
-	for (unsigned int i = 0 ; i < genalloc_len(diuint32,&gasrc) ; i++)
-		start_parser(sasrc.s + genalloc_s(diuint32,&gasrc)[i].right,sasrc.s + genalloc_s(diuint32,&gasrc)[i].left,tree.s,&nbsv) ;
-	
-	sv_alltype svblob[nbsv] ;
-	
-	for (int i = 0;i < nbsv;i++)
-		svblob[i] =  genalloc_s(sv_alltype,&gasv)[i] ;
-	
-	sv_db before = {
-		.services = svblob, 
-		.nsv = nbsv ,
-		.string = keep.s ,
-		.stringlen = keep.len ,
-		.ndeps = genalloc_len(unsigned int,&gadeps) 
-	} ;
-	
-	{
-		if (!tree_copy(&workdir,tree.s,treename)) strerr_diefu1sys(111,"create tmp working directory") ;
-		for (unsigned int i = 0; i < before.nsv; i++)
-		{
-			r = write_services(&before.services[i], workdir.s,FORCE) ;
-			if (!r)
-			{
-				cleanup(workdir.s) ;
-				strerr_diefu2x(111,"write service: ",keep.s+before.services[i].cname.name) ;
-			}
-			if (r > 1) continue ; //service already added
-			
-			if (before.services[i].cname.itype > CLASSIC)
-			{
-				if (!stra_add(&ganlong,keep.s + before.services[i].cname.name)) retstralloc(111,"main") ;
-				nlongrun++ ;
-			}
-			else if (before.services[i].cname.itype == CLASSIC) 
-			{
-				if (!stra_add(&ganclassic,keep.s + before.services[i].cname.name)) retstralloc(111,"main") ;
-				nclassic++ ;
-			}
-		}
-		
-	}
-	
-	if (nclassic)
-	{
-		if (!svc_switch_to(base.s,tree.s,treename,SS_SWBACK))
-		{
-			cleanup(workdir.s) ;
-			strerr_diefu3x(111,"switch ",treename," to backup") ;
-		}	
-	}
-	
-	if(nlongrun)
-	{
-		r = graph_type_src(&tokeep,workdir.s,1) ;
-		if (!r)
-		{
-			cleanup(workdir.s) ;
-			strerr_diefu2x(111,"resolve source of graph for tree: ",treename) ;
-		}
-		if (r < 0)
-		{
-			if (!stra_add(&master,"")) retstralloc(111,"main") ;
-		}
-		else 
-		{
-			if (!graph_build(&g,&sagraph,&tokeep,workdir.s))
-			{
-				cleanup(workdir.s) ;
-				strerr_diefu1x(111,"make dependencies graph") ;
-			}
-			if (!graph_sort(&g))
-			{
-				cleanup(workdir.s) ;
-				strerr_dief1x(111,"cyclic graph detected") ;
-			}
-			if (!graph_master(&master,&g))
-			{
-				cleanup(workdir.s) ;
-				strerr_dief1x(111,"find master service") ;
-			}
-		}
-
-		if (!db_write_contents(&master,SS_MASTER + 1,workdir.s))
-		{
-			cleanup(workdir.s) ;
-			strerr_diefu2x(111,"update bundle: ", SS_MASTER + 1) ;
-		}
-				
-		if (!db_compile(workdir.s,tree.s,treename,envp))
-		{
-				cleanup(workdir.s) ;
-				strerr_diefu4x(111,"compile ",workdir.s,"/",treename) ;
-		}
-		
-		/** this is an important part, we call s6-rc-update here */
-		if (!db_switch_to(base.s,livetree.s,tree.s,treename,envp,SS_SWBACK))
-		{
-			cleanup(workdir.s) ;
-			strerr_diefu3x(111,"switch ",treename," to backup") ;
-		}		
-	}
-
-	if (!tree_copy_tmp(workdir.s,base.s,live.s,tree.s,treename))
-	{
-		cleanup(workdir.s) ;
-		strerr_diefu4x(111,"copy: ",workdir.s," to: ", tree.s) ;
-	}
-	
-	if (start)
-	{
-		size_t arglen = 8 + genalloc_len(stralist,&ganclassic) + genalloc_len(stralist,&ganlong) ;
-		char const *newup[arglen] ;
-		unsigned int m = 0 ;
-		char fmt[UINT_FMT] ;
-		fmt[uint_fmt(fmt, VERBOSITY)] = 0 ;
-		
-		newup[m++] = SS_BINPREFIX "66-start" ;
-		newup[m++] = "-v" ;
-		newup[m++] = fmt ;
-		newup[m++] = "-l" ;
-		newup[m++] = live.s ;
-		newup[m++] = "-t" ;
-		newup[m++] = treename ;
-		/** classic */
-		for (unsigned int i = 0 ; i<genalloc_len(stralist,&ganclassic); i++)
-			newup[m++] = gaistr(&ganclassic,i) ;
-		/** rc */
-		for (unsigned int i = 0 ; i<genalloc_len(stralist,&ganlong); i++)
-			newup[m++] = gaistr(&ganlong,i) ;
-		
-		newup[m++] = 0 ;
-		
-		xpathexec_run (newup[0], newup, envp) ;
-	}
-	
-	cleanup(workdir.s) ;
 	
-	/** general allocation*/
-	freed_parser() ;
-	/** inner allocation */
-	stralloc_free(&base) ;
-	stralloc_free(&tree) ;
-	stralloc_free(&workdir) ;
-	stralloc_free(&live) ;
-	stralloc_free(&livetree) ;
-	stralloc_free(&sasrc) ;
-	genalloc_free(sv_src_t,&gasrc) ;
-	genalloc_deepfree(stralist,&ganclassic,stra_free) ;
-	genalloc_deepfree(stralist,&ganlong,stra_free) ;
-	free(treename) ;
+	ssexec_t info = SSEXEC_ZERO ;
 	
-	/** graph stuff */
-	genalloc_free(vertex_graph_t,&g.stack) ;
-	genalloc_free(vertex_graph_t,&g.vertex) ;
-	genalloc_deepfree(stralist,&master,stra_free) ;
-	stralloc_free(&sagraph) ;
-	genalloc_deepfree(stralist,&tokeep,stra_free) ;
+	info.prog = PROG ;
+	info.help = help_enable ;
+	info.usage = usage_enable ;
 	
-	return 0 ;		
+	return ssexec_main(argc,argv,envp,&ssexec_enable,&info) ;
 }
 	
 
diff --git a/src/66/66-info.c b/src/66/66-info.c
index 29f73ddb1cb1778b639f4a386f023f4fd97722a3..e324f743a383aaf53f6aceb19fdd8bbca492c927 100644
--- a/src/66/66-info.c
+++ b/src/66/66-info.c
@@ -57,9 +57,9 @@ static uid_t owner ;
 #define USAGE "66-info [ -h ] [ -T ] [ -S ] sub-options (use -h as sub-options for futher informations)"
 
 #define TREE_USAGE "66-info -T [ -h ] [ -v verbosity ] [ -r ] [ -d depth ] tree "
-#define exit_tree_usage() strerr_dieusage(100, TREE_USAGE)
+#define exit_tree_usage() exitusage(TREE_USAGE)
 #define SV_USAGE "66-info -S [ -h ] [ -v verbosity ] [ -l live ] [ -p n lines ] [ -r ] [ -d depth ] service"
-#define exit_sv_usage() strerr_dieusage(100, SV_USAGE)
+#define exit_sv_usage() exitusage(SV_USAGE)
 
 unsigned int REVERSE = 0 ;
 
@@ -181,14 +181,14 @@ int print_status(char const *svname,char const *type,char const *treename, char
 	
 	if (get_enumbyid(type,key_enum_el) == CLASSIC)
 	{
-		size_t scanlen = SCANDIR.len - 1 ;
+		size_t scanlen = SCANDIR.len ;
 		if (!stralloc_catb(&svok,SCANDIR.s,scanlen)) retstralloc(0,"print_status") ;
 		if (!stralloc_cats(&svok,"/")) retstralloc(0,"print_status") ;
 		if (!stralloc_cats(&svok,svname)) retstralloc(0,"print_status") ;
 	}
 	else if (get_enumbyid(type,key_enum_el) == LONGRUN)
 	{
-		size_t livelen = livetree.len -1 ;
+		size_t livelen = livetree.len ;
 		if (!stralloc_catb(&svok,livetree.s,livelen)) retstralloc(0,"print_status") ;
 		if (!stralloc_cats(&svok,"/")) retstralloc(0,"print_status") ;
 		if (!stralloc_cats(&svok,treename)) retstralloc(0,"print_status") ;
@@ -332,14 +332,14 @@ int tree_args(int argc, char const *const *argv)
 	
 	if (argv[0]) todisplay = 1 ;
 	
-	r = tree_find_current(&sacurrent,base.s) ;
+	r = tree_find_current(&sacurrent,base.s,MYUID) ;
 	if (r)
 	{
 		currname = tree_setname(sacurrent.s) ;
 		if (!currname) strerr_diefu1x(111,"set the tree name") ;
 	}
 	
-	size_t baselen = base.len - 1 ;
+	size_t baselen = base.len ;
 	char src[baselen + SS_SYSTEM_LEN + 1] ;
 	memcpy(src,base.s,baselen) ;
 	memcpy(src + baselen,SS_SYSTEM, SS_SYSTEM_LEN) ;
@@ -368,7 +368,7 @@ int tree_args(int argc, char const *const *argv)
 			if(!stralloc_cats(&tree,treename)) retstralloc(0,"tree_args") ;
 			if(!stralloc_0(&tree)) retstralloc(0,"tree_args") ;
 	
-			r = tree_sethome(&tree,base.s) ;
+			r = tree_sethome(&tree,base.s,MYUID) ;
 			if (!r) strerr_diefu2sys(111,"find tree: ", tree.s) ;
 			
 			r = graph_display(tree.s,treename,"",2) ;
@@ -430,9 +430,9 @@ int sv_args(int argc, char const *const *argv,char const *const *envp)
 				case 'l' : 	if (!stralloc_cats(&live,l.arg)) retstralloc(0,"sv_args") ;
 							if (!stralloc_0(&live)) retstralloc(0,"sv_args") ;
 							break ;
-				case 'p' :	if (!uint0_scan(l.arg, &nlog)) exitusage() ; break ;
+				case 'p' :	if (!uint0_scan(l.arg, &nlog)) exit_sv_usage() ; break ;
 				case 'r' : 	REVERSE = 1 ; break ;
-				case 'd' : 	if (!uint0_scan(l.arg, &MAXDEPTH)) exit_tree_usage(); break ;
+				case 'd' : 	if (!uint0_scan(l.arg, &MAXDEPTH)) exit_sv_usage(); break ;
 				default : exit_sv_usage() ; 
 			}
 		}
@@ -446,7 +446,7 @@ int sv_args(int argc, char const *const *argv,char const *const *envp)
 	if (!r) retstralloc(0,"sv_args") ;
 	if (r < 0 ) strerr_dief3x(111,"live: ",live.s," must be an absolute path") ;
 	
-	size_t baselen = base.len - 1 ;
+	size_t baselen = base.len ;
 	size_t newlen ;
 	char src[MAXSIZE] ;
 	memcpy(src,base.s,baselen) ;
@@ -485,7 +485,7 @@ int sv_args(int argc, char const *const *argv,char const *const *envp)
 		return 1 ;
 	}
 	
-	r = tree_sethome(&tree,base.s) ;
+	r = tree_sethome(&tree,base.s,MYUID) ;
 	if (!r) strerr_diefu2sys(111,"find tree: ", tree.s) ;
 	
 	if (!bprintf(buffer_1,"%s%s%s\n","[",svname,"]")) goto err ;
@@ -595,11 +595,11 @@ int main(int argc, char const *const *argv, char const *const *envp)
 				case 'h' : 	info_help(); return 0 ;
 				case 'T' : 	what = 0 ; break ;
 				case 'S' :	what = 1 ; break ;
-				default : exitusage() ; 
+				default : exitusage(USAGE) ; 
 			}
 		}
 	}
-	if (what<0) exitusage() ;
+	if (what<0) exitusage(USAGE) ;
 	
 	owner = MYUID ;
 		
diff --git a/src/66/66-init.c b/src/66/66-init.c
index f1cbceb860f501eb9358f5f4829c2679fe4dc993..1a96377e73a84dec2abeaeafaae7612bcb75b82f 100644
--- a/src/66/66-init.c
+++ b/src/66/66-init.c
@@ -12,285 +12,23 @@
  * except according to the terms contained in the LICENSE file./
  */
 
-#include <string.h>
-#include <sys/stat.h>
+#include <skalibs/strerr2.h>
 
-#include <oblibs/obgetopt.h>
-#include <oblibs/error2.h>
-#include <oblibs/directory.h>
-#include <oblibs/types.h>//scan_mode
-#include <oblibs/stralist.h>
-
-#include <skalibs/buffer.h>
-#include <skalibs/types.h>
-#include <skalibs/stralloc.h>
-#include <skalibs/djbunix.h>
-#include <skalibs/direntry.h>
-
-#include <s6/config.h>
-#include <s6-rc/config.h>
-#include <s6/s6-supervise.h>
-
-#include <66/utils.h>
-#include <66/enum.h>
-#include <66/constants.h>
-#include <66/tree.h>
-#include <66/backup.h>
-#include <66/db.h>
-#include <66/svc.h>
-
-//#include <stdio.h>
-
-#define USAGE "66-init [ -h ] [ -v verbosity ] [ -l live ] [ -c | d | B ] tree"
+#include <66/ssexec.h>
 
 unsigned int VERBOSITY = 1 ;
 
-static inline void info_help (void)
+int main(int argc, char const *const *argv,char const *const *envp)
 {
-  static char const *help =
-"66-init <options> tree\n"
-"\n"
-"options :\n"
-"	-h: print this help\n" 
-"	-v: increase/decrease verbosity\n"
-"	-l: live directory\n" 
-"	-c: init classic service\n"
-"	-d: init database service\n"
-"	-B: init classic and database service\n"
-;
-
- if (buffer_putsflush(buffer_1, help) < 0)
-    strerr_diefu1sys(111, "write to stdout") ;
-}
-
-int main(int argc, char const *const *argv, char const *const *envp)
-{
-	int r, db, classic, earlier ;
-	
-	uid_t owner ;
-	int wstat ;
-	pid_t pid ;
-	
-	char const *treename = 0 ;
-	size_t treenamelen ;
-	
-	stralloc base = STRALLOC_ZERO ;
-	stralloc tree = STRALLOC_ZERO ;
-	stralloc live = STRALLOC_ZERO ;
-	stralloc scandir = STRALLOC_ZERO ;
-	stralloc livetree = STRALLOC_ZERO ;
-	stralloc saresolve = STRALLOC_ZERO ;
-	stralloc type = STRALLOC_ZERO ;
-	genalloc gasvc = GENALLOC_ZERO ; //stralist type
-	
-	svstat_t svstat = SVSTAT_ZERO ;
-	genalloc gasvstat = GENALLOC_ZERO ; //svstat_t type
-	classic = db = earlier = 0 ;
-	
 	PROG = "66-init" ;
-	{
-		subgetopt_t l = SUBGETOPT_ZERO ;
-
-		for (;;)
-		{
-			int opt = getopt_args(argc,argv, "hv:l:cdB", &l) ;
-			if (opt == -1) break ;
-			if (opt == -2) strerr_dief1x(110,"options must be set first") ;
-			switch (opt)
-			{
-				case 'h' : info_help(); return 0 ;
-				case 'v' : if (!uint0_scan(l.arg, &VERBOSITY)) exitusage() ; break ;
-				case 'l' : if(!stralloc_cats(&live,l.arg)) retstralloc(111,"main") ;
-						   if(!stralloc_0(&live)) retstralloc(111,"main") ;
-						   break ;
-				case 'c' : classic = 1 ; break ;
-				case 'd' : db = 1 ; break ;
-				case 'B' : classic = 1 ; db = 1 ; break ;
-				default : exitusage() ; 
-			}
-		}
-		argc -= l.ind ; argv += l.ind ;
-	}
 	
-	if (argc != 1) exitusage() ;
+	ssexec_t info = SSEXEC_ZERO ;
 	
-	owner = MYUID ;
-	treename = *argv ;
-	treenamelen = strlen(treename) ;
+	info.prog = PROG ;
+	info.help = help_init ;
+	info.usage = usage_init ;
 	
-	if (!set_ownersysdir(&base,owner)) strerr_diefu1sys(111, "set owner directory") ;
-	
-	r = set_livedir(&live) ;
-	if (!r) retstralloc(111,"main") ;
-	if(r < 0) strerr_dief3x(111,"live: ",live.s," must be an absolute path") ;
-	
-	if (!stralloc_cats(&tree,treename)) retstralloc(111,"main") ;
-	if (!stralloc_0(&tree)) retstralloc(111,"main") ;
-	
-	r = tree_sethome(&tree,base.s) ;
-	if (!r) strerr_diefu2sys(111,"find tree: ", tree.s) ;
-	
-	if (!tree_get_permissions(tree.s))
-		strerr_dief2x(110,"You're not allowed to use the tree: ",tree.s) ;
-		
-	if (!stralloc_copy(&scandir,&live)) retstralloc(111,"main") ;
-	
-	r = set_livescan(&scandir,owner) ;
-	if (!r) retstralloc(111,"main") ;
-	if (r < 0) strerr_dief3x(111,"scandir: ",scandir.s," must be an absolute path") ;
-	
-	r = scan_mode(scandir.s,S_IFDIR) ;
-	if (r < 0) strerr_dief2x(111,scandir.s," conflicted format") ;
-	if (!r) strerr_dief3x(110,"scandir: ",scandir.s," doesn't exist") ;
-	
-	r = scandir_ok(scandir.s) ;
-	if (r != 1) earlier = 1 ; 
-	
-	if (!stralloc_copy(&livetree,&live)) retstralloc(111,"main") ;
-	r = set_livetree(&livetree,owner) ;
-	if (!r) retstralloc(111,"main") ;
-	if (r < 0) strerr_dief3x(111,"livetree: ",livetree.s," must be an absolute path") ;
-	
-	r = scan_mode(livetree.s,S_IFDIR) ;
-	if (r < 0) strerr_dief2x(111,livetree.s," is not a directory") ;
-	if (!r)
-	{
-		VERBO2 strerr_warni2x("create directory: ",livetree.s) ;
-		r = dir_create(livetree.s,0700) ;
-		if (!r) strerr_diefu2sys(111,"create directory: ",livetree.s) ;
-	}
-	
-	tree.len-- ;
-	size_t svdirlen ;
-	char svdir[tree.len + SS_SVDIRS_LEN + SS_DB_LEN + treenamelen + 1 + 1] ;
-	memcpy(svdir,tree.s,tree.len) ;
-	memcpy(svdir + tree.len ,SS_SVDIRS ,SS_SVDIRS_LEN) ;
-	svdirlen = tree.len + SS_SVDIRS_LEN ;
-	memcpy(svdir + svdirlen, SS_SVC ,SS_SVC_LEN) ;
-	svdir[svdirlen +  SS_SVC_LEN] = 0 ;
-	
-	/** svc already initiated */
-	if (classic)
-	{
-		int i ;
-		if (!dir_cmp(svdir,scandir.s,"",&gasvc)) strerr_diefu4x(111,"compare ",svdir," to ",scandir.s) ;
-		if (!earlier)
-		{
-			for (i = 0 ; i < genalloc_len(stralist,&gasvc) ; i++)
-			{
-				char *name = gaistr(&gasvc,i) ;
-				size_t namelen = gaistrlen(&gasvc,i) ;
-			
-				if (!resolve_pointo(&saresolve,base.s,live.s,tree.s,treename,0,SS_RESOLVE_SRC))
-					strerr_diefu1x(111,"set revolve pointer to source") ;
-				r = resolve_read(&type,saresolve.s,name,"type") ;
-				if (r < -1) strerr_dief2x(111,"invalid .resolve directory: ",saresolve.s) ;
-				if (r && type.len && get_enumbyid(type.s,key_enum_el) == CLASSIC)
-				{
-					svstat.down = 0 ;
-					svstat.name = name ;
-					svstat.namelen = namelen ;
-					r = resolve_read(&type,saresolve.s,name,"down") ;
-					if (r > 0) svstat.down = 1 ;
-					if (!genalloc_append(svstat_t,&gasvstat,&svstat)) strerr_diefu3x(111,"add: ",name," on genalloc") ;
-				}
-			}
-			if (genalloc_len(svstat_t,&gasvstat))
-			{
-				if (!svc_init(scandir.s,svdir,&gasvstat)) strerr_diefu2x(111,"initiate service of tree: ",treename) ;
-			}
-			else strerr_warni3x("svc service of tree: ",treename," already initiated") ;
-		}
-		else
-		{
-			size_t dirlen = strlen(svdir) ;
-			for (i = 0 ; i < genalloc_len(stralist,&gasvc) ; i++)
-			{
-				char *name = gaistr(&gasvc,i) ;
-				size_t namelen = gaistrlen(&gasvc,i) ;
-				size_t scanlen = scandir.len - 1 ;
-				char svscan[scanlen + 1 + namelen + 1] ;
-				memcpy(svscan,scandir.s,scanlen) ;
-				svscan[scanlen] = '/' ;
-				memcpy(svscan + scanlen + 1, name,namelen) ;
-				svscan[scanlen + 1 + namelen] = 0 ;
-				char tocopy[dirlen + 1 + namelen + 1] ;
-				memcpy(tocopy,svdir,dirlen) ;
-				tocopy[dirlen] = '/' ;
-				memcpy(tocopy + dirlen + 1, name, namelen) ;
-				tocopy[dirlen + 1 + namelen] = 0 ;
-				if (!hiercopy(tocopy,svscan)) strerr_diefu4sys(111,"to copy: ",tocopy," to: ",svscan) ;
-			}
-		}
-	}
-	genalloc_deepfree(stralist,&gasvc,stra_free) ;
-	genalloc_free(svstat_t,&gasvstat) ;
-	stralloc_free(&saresolve) ;
-	stralloc_free(&type) ;
-	
-	/** db already initiated? */
-	if (db)
-	{
-		if (!earlier)
-		{
-			if (db_ok(livetree.s,treename))
-			{
-				strerr_warni3x(" db of tree: ",treename," already initiated") ;
-				goto end ;
-			}
-		}else strerr_dief3x(110,"scandir: ",scandir.s," is not running") ;
-	}else goto end ;
-	
-	{
-		livetree.len--;
-		if (!stralloc_cats(&livetree,"/")) retstralloc(111,"main") ;
-		if (!stralloc_cats(&livetree,treename)) retstralloc(111,"main") ;
-		if (!stralloc_0(&livetree)) retstralloc(111,"main") ;
-		
-		memcpy(svdir + svdirlen,SS_DB,SS_DB_LEN) ;
-		memcpy(svdir + svdirlen + SS_DB_LEN, "/", 1) ;
-		memcpy(svdir + svdirlen + SS_DB_LEN + 1, treename,treenamelen) ;
-		svdir[svdirlen + SS_DB_LEN + 1 + treenamelen] = 0 ;
-		
-		char prefix[treenamelen + 1 + 1] ;
-		memcpy(prefix,treename,treenamelen) ;
-		memcpy(prefix + treenamelen, "-",1) ;
-		prefix[treenamelen + 1] = 0 ;
-		
-		{
-			char const *newargv[10] ;
-			unsigned int m = 0 ;
-			
-			newargv[m++] = S6RC_BINPREFIX "s6-rc-init" ;
-			newargv[m++] = "-l" ;
-			newargv[m++] = livetree.s ;
-			newargv[m++] = "-c" ;
-			newargv[m++] = svdir ;
-			newargv[m++] = "-p" ;
-			newargv[m++] = prefix ;
-			newargv[m++] = "--" ;
-			newargv[m++] = scandir.s ;
-			newargv[m++] = 0 ;
-			
-			VERBO2 strerr_warni3x("initiate db ",svdir," ...") ;
-			
-			pid = child_spawn0(newargv[0],newargv,envp) ;
-			if (waitpid_nointr(pid,&wstat, 0) < 0)
-				strerr_diefu2sys(111,"wait for ",newargv[0]) ;
-				
-			if (wstat)
-				strerr_diefu2x(111,"init db: ",svdir) ;
-		}
-	}
-		
-	end:
-		stralloc_free(&base) ;
-		stralloc_free(&tree) ;
-		stralloc_free(&live) ;
-		stralloc_free(&scandir) ;
-		stralloc_free(&livetree) ;
-
-	return 0 ;
+	return ssexec_main(argc,argv,envp,&ssexec_init,&info) ;
 }
 	
 
diff --git a/src/66/66-scandir.c b/src/66/66-scandir.c
index e72721affeba891d315983e193a2214162f9f1ad..d8af82c58832b0a25b7b69a8972f1d1016f39bd3 100644
--- a/src/66/66-scandir.c
+++ b/src/66/66-scandir.c
@@ -237,7 +237,7 @@ int write_log(char const *scandir, char const *scanname)
 			VERBO3 strerr_warnwu1x("set owner path") ;
 			return 0 ;
 		}
-		path.len-- ;
+		//path.len-- ;
 		if (!stralloc_cats(&path,SS_LOGGER_USER_DIRECTORY)) retstralloc(0,"write_log") ;
 	}
 	pathless = path.len ;
@@ -854,7 +854,7 @@ int main(int argc, char const *const *argv, char const *const *envp)
 			switch (opt)
 			{
 				case 'h' : info_help(); return 0 ;
-				case 'v' : if (!uint0_scan(l.arg, &VERBOSITY)) exitusage() ; break ;
+				case 'v' : if (!uint0_scan(l.arg, &VERBOSITY)) exitusage(USAGE) ; break ;
 				case 'b' : BOOT = 1 ; break ;
 				case 'l' : if(!stralloc_cats(&live,l.arg)) retstralloc(111,"main") ;
 						   if(!stralloc_0(&live)) retstralloc(111,"main") ;
@@ -866,20 +866,20 @@ int main(int argc, char const *const *argv, char const *const *envp)
 				case 'e' : if(!stralloc_cats(&envdir,l.arg)) retstralloc(111,"main") ;
 						   if(!stralloc_0(&envdir)) retstralloc(111,"main") ;
 						   break ;
-				case 'c' : create = 1 ; if (remove) exitusage() ; break ;
-				case 'r' : remove = 1 ; if (create) exitusage() ; break ;
-				case 'u' : up = 1 ; if (down) exitusage() ; break ;
-				case 's' : down = 1 ; if (up) exitusage() ; 
+				case 'c' : create = 1 ; if (remove) exitusage(USAGE) ; break ;
+				case 'r' : remove = 1 ; if (create) exitusage(USAGE) ; break ;
+				case 'u' : up = 1 ; if (down) exitusage(USAGE) ; break ;
+				case 's' : down = 1 ; if (up) exitusage(USAGE) ; 
 						   if(!stralloc_cats(&signal,l.arg)) retstralloc(111,"main") ;
 						   if(!stralloc_0(&signal)) retstralloc(111,"main") ;
 						   break ;
-				default : exitusage() ; 
+				default : exitusage(USAGE) ; 
 			}
 		}
 		argc -= l.ind ; argv += l.ind ;
 	}
 	
-	if (argc > 1) exitusage() ;
+	if (argc > 1) exitusage(USAGE) ;
 	
 	if (!argc) OWNER = MYUID ;
 	else 
diff --git a/src/66/66-start.c b/src/66/66-start.c
index 5cbf8d223ebda2fd337b9561f6486ea3df0a3632..bbd22e9111b7366735b786997a61909f1001a403 100644
--- a/src/66/66-start.c
+++ b/src/66/66-start.c
@@ -12,729 +12,23 @@
  * except according to the terms contained in the LICENSE file./
  */
 
-#include <string.h>
-#include <sys/stat.h>
-#include <stdlib.h>
+#include <skalibs/strerr2.h>
 
-#include <oblibs/obgetopt.h>
-#include <oblibs/error2.h>
-#include <oblibs/string.h>
-#include <oblibs/types.h>
-#include <oblibs/directory.h>
-#include <oblibs/files.h>
-#include <oblibs/stralist.h>
+#include <66/ssexec.h>
 
-#include <skalibs/buffer.h>
-#include <skalibs/types.h>
-#include <skalibs/stralloc.h>
-#include <skalibs/genalloc.h>
-#include <skalibs/djbunix.h>
-#include <skalibs/unix-transactional.h>
-#include <skalibs/tai.h>
-
-#include <skalibs/selfpipe.h>
-#include <skalibs/iopause.h>
-#include <skalibs/sig.h>
-
-#include <s6/s6-supervise.h>//s6_svstatus_t
-#include <s6/ftrigw.h>
-#include <s6/config.h>
-
-#include <66/tree.h>
-#include <66/db.h>
-#include <66/config.h>
-#include <66/utils.h>
-#include <66/constants.h>
-#include <66/enum.h>
-#include <66/backup.h>
-#include <66/svc.h>
-
-//#include <stdio.h>
 unsigned int VERBOSITY = 1 ;
 
-static unsigned int RELOAD = 0 ;
-static unsigned int DEADLINE = 0 ;
-static stralloc saresolve = STRALLOC_ZERO ;
-static char *SIG = "-U" ;
-static genalloc DOWNFILE = GENALLOC_ZERO ; //stralist
-
-#define USAGE "66-start [ -h ] [ -v verbosity ] [ -l live ] [ -t tree ] [ -T timeout ] [ -r | R ] service(s)"
-
-static inline void info_help (void)
-{
-  static char const *help =
-"66-start <options> service(s)\n"
-"\n"
-"options :\n"
-"	-h: print this help\n" 
-"	-v: increase/decrease verbosity\n"
-"	-l: live directory\n"
-"	-t: tree to use\n"
-"	-T: timeout\n"
-"	-r: reload the service(s)\n"
-"	-R: reload service(s) file(s) and the service(s) itself\n"
-;
-
- if (buffer_putsflush(buffer_1, help) < 0)
-    strerr_diefu1sys(111, "write to stdout") ;
-}
-
-int svc_shutnremove(char const *base,char const *scandir,char const *live,char const *tree,char const *treename, genalloc *ga, char const *const *envp)
-{
-	int r ;
-	int wstat ;
-	pid_t pid ; 
-	
-	size_t scanlen = strlen(scandir) ;
-	
-	stralloc log = STRALLOC_ZERO ;
-	genalloc tot = GENALLOC_ZERO ; //stralist
-	
-	for (unsigned int i = 0 ; i < genalloc_len(svstat_t,ga) ; i++) 
-	{
-		
-		char const *svname = genalloc_s(svstat_t,ga)[i].name ;
-		
-		if (!stra_add(&tot,svname))
-		{
-			VERBO3 strerr_warnwu3x("add: ",svname," as service to shutdown") ;
-			return 0 ;
-		}
-		if (!resolve_pointo(&saresolve,base,live,tree,treename,0,SS_RESOLVE_SRC))
-		{
-			VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
-			return 0 ;
-		}
-		r = resolve_read(&saresolve,saresolve.s,svname,"logger") ;
-		
-		if (r) 
-		{
-			if (!stra_add(&tot,saresolve.s))
-			{
-				VERBO3 strerr_warnwu3x("add logger of: ",svname," as service to shutdown") ;
-				return 0 ;
-			}
-			
-		}
-	}	
-	
-	char const *newargv[11 + genalloc_len(stralist,&tot)] ;
-	unsigned int m = 0 ;
-	char fmt[UINT_FMT] ;
-	fmt[uint_fmt(fmt, VERBOSITY)] = 0 ;
-
-	char tt[UINT32_FMT] ;
-	tt[uint32_fmt(tt,DEADLINE)] = 0 ;
-
-	newargv[m++] = SS_BINPREFIX "66-svctl" ;
-	newargv[m++] = "-v" ;
-	newargv[m++] = fmt ;
-	newargv[m++] = "-T" ;
-	newargv[m++] = tt ;
-	newargv[m++] = "-l" ;
-	newargv[m++] = live ;
-	newargv[m++] = "-t" ;
-	newargv[m++] = treename ;
-	newargv[m++] = "-D" ;
-	for (unsigned int i = 0 ; i < genalloc_len(stralist,&tot) ; i++) 
-		newargv[m++] = gaistr(&tot,i) ;
-			
-	newargv[m++] = 0 ;
-	
-	pid = child_spawn0(newargv[0],newargv,envp) ;
-	if (waitpid_nointr(pid,&wstat, 0) < 0)
-	{
-		VERBO3 strerr_warnwu2sys("wait for ",newargv[0]) ;
-		return 0 ;
-	}
-	if (wstat)
-	{
-		VERBO3 strerr_warnwu1x("shutdown list of services") ;
-		return 0 ;
-	}
-	
-	for (unsigned int i = 0 ; i < genalloc_len(stralist,&tot) ; i++) 
-	{
-		size_t namelen = gaistrlen(&tot,i) ;
-		char const *name = gaistr(&tot,i)  ;
-		char svscan[scanlen + 1 + namelen + 1] ;
-		memcpy(svscan,scandir,scanlen) ;
-		svscan[scanlen] = '/' ;
-		memcpy(svscan + scanlen + 1,name, namelen) ;
-		svscan[scanlen + 1 + namelen] = 0 ;
-		
-		VERBO3 strerr_warnt2x("delete: ", svscan) ;
-		if (rm_rf(svscan) < 0)
-		{
-			VERBO3 strerr_warnwu2sys("delete: ",svscan) ;
-			return 0 ;
-		}
-	}
-	stralloc_free(&log) ;
-	genalloc_deepfree(stralist,&tot,stra_free) ;
-	
-	return 1 ;
-}
-		
-int svc_start(char const *base,char const *scandir,char const *live,char const *tree, char const *treename,genalloc *ga,char const *const *envp)
-{
-	int wstat ;
-	pid_t pid ; 
-	
-	genalloc tot = genalloc_zero ; //stralist
-	
-	for (unsigned int i = 0; i < genalloc_len(svstat_t,ga) ; i++)
-	{	
-		if (!stra_add(&tot,genalloc_s(svstat_t,ga)[i].name))
-		{
-			VERBO3 strerr_warnwu3x("add: ",genalloc_s(svstat_t,ga)[i].name," as service to start") ;
-			return 0 ;
-		}
-		
-		if (!resolve_pointo(&saresolve,base,live,tree,treename,0,SS_RESOLVE_SRC))
-		{
-			VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
-			return 0 ;
-		}
-		if (resolve_read(&saresolve,saresolve.s,genalloc_s(svstat_t,ga)[i].name,"logger"))
-		{
-			if (!stra_add(&tot,saresolve.s))
-			{
-				VERBO3 strerr_warnwu3x("add: ",saresolve.s," as service to shutdown") ;
-				return 0 ;
-			}
-		}
-	}
-	char const *newargv[11 + genalloc_len(stralist,&tot)] ;
-	unsigned int m = 0 ;
-	char fmt[UINT_FMT] ;
-	fmt[uint_fmt(fmt, VERBOSITY)] = 0 ;
-
-	char tt[UINT32_FMT] ;
-	tt[uint32_fmt(tt,DEADLINE)] = 0 ;
-	
-	newargv[m++] = SS_BINPREFIX "66-svctl" ;
-	newargv[m++] = "-v" ;
-	newargv[m++] = fmt ;
-	newargv[m++] = "-T" ;
-	newargv[m++] = tt ;
-	newargv[m++] = "-l" ;
-	newargv[m++] = live ;
-	newargv[m++] = "-t" ;
-	newargv[m++] = treename ;
-	newargv[m++] = SIG ;
-	
-	for (unsigned int i = 0 ; i < genalloc_len(stralist,&tot) ; i++) 
-		newargv[m++] = gaistr(&tot,i) ;
-	
-	newargv[m++] = 0 ;
-	
-	pid = child_spawn0(newargv[0],newargv,envp) ;
-	if (waitpid_nointr(pid,&wstat, 0) < 0)
-	{
-		VERBO3 strerr_warnwu2sys("wait for ",newargv[0]) ;
-		return 0 ;
-	}
-	if (wstat)
-	{
-		VERBO3 strerr_warnwu1x("bring up services") ;
-		return 0 ;
-	}
-	if (!resolve_pointo(&saresolve,base,live,tree,treename,0,SS_RESOLVE_SRC))
-	{
-		VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
-		return 0 ;
-	}
-
-	for (unsigned int i = 0; i < genalloc_len(svstat_t,ga) ; i++)
-	{
-		if (genalloc_s(svstat_t,ga)[i].reload)
-		{
-			VERBO3 strerr_warnt2x("delete reload resolve file for: ",genalloc_s(svstat_t,ga)[i].name) ;
-			if (!resolve_remove(saresolve.s,genalloc_s(svstat_t,ga)[i].name,"reload"))
-			{
-				VERBO3 strerr_warnwu3sys("delete resolve file",saresolve.s,"/reload") ;
-				return 0 ;
-			}
-		}
-	}
-
-	return 1 ;
-}
-
-int svc_sanitize(char const *base,char const *scandir,char const *live,char const *tree,char const *treename, genalloc *ga, char const *const *envp)
-{
-	genalloc toreload = GENALLOC_ZERO ; //svstat_t
-	genalloc toinit = GENALLOC_ZERO ; //svstat_t
-	
-	for (unsigned int i = 0; i < genalloc_len(svstat_t,ga) ; i++)
-	{
-		if (genalloc_s(svstat_t,ga)[i].reload)
-		{
-			if (!genalloc_cat(svstat_t,&toreload,ga))
-			{
-				VERBO3 strerr_warnwu1x("append genalloc") ;
-				return 0 ;
-			}
-		}
-		if (genalloc_s(svstat_t,ga)[i].init)
-		{
-			if (!genalloc_cat(svstat_t,&toinit,ga))
-			{
-				VERBO3 strerr_warnwu1x("append genalloc") ;
-				return 0 ;
-			}
-		}
-	}
-	if (genalloc_len(svstat_t,&toinit))
-	{
-		if (!resolve_pointo(&saresolve,base,live,tree,treename,CLASSIC,SS_RESOLVE_SRC))		
-		{
-			VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
-			return 0 ;
-		}
-		VERBO3 strerr_warnt1x("initiate svc service list ...") ;
-		if (!svc_init(scandir, saresolve.s, &toinit))
-		{
-			VERBO3 strerr_warnwu1x("iniatiate svc service list") ;
-			return 0 ;
-		}
-	}
-	if (genalloc_len(svstat_t,&toreload))
-	{
-		VERBO3 strerr_warnt1x("shutdown service before reload it ...") ;
-		if (!svc_shutnremove(base,scandir,live,tree,treename,&toreload,envp))
-		{
-			VERBO3 strerr_warnwu1x("down list of service") ;
-			return 0 ;
-		}
-		if (!resolve_pointo(&saresolve,base,live,tree,treename,CLASSIC,SS_RESOLVE_SRC))		
-		{
-			VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
-			return 0 ;
-		}
-		VERBO3 strerr_warnt1x("initiate svc services list ...") ;
-		if (!svc_init(scandir, saresolve.s, &toreload))
-		{
-			VERBO3 strerr_warnwu1x("iniatiate svc service list") ;
-			return 0 ;
-		}
-	}
-	
-	return 1 ;
-}
-
-int rc_init(char const *scandir, char const *live, char const *treename, char const *const *envp)
-{
-	pid_t pid ;
-	int r, wstat ;
-	
-	char const *newargv[8] ;
-	unsigned int m = 0 ;
-	char fmt[UINT_FMT] ;
-	fmt[uint_fmt(fmt, VERBOSITY)] = 0 ;
-				
-	newargv[m++] = SS_BINPREFIX "66-init" ;
-	newargv[m++] = "-v" ;
-	newargv[m++] = fmt ;
-	newargv[m++] = "-l" ;
-	newargv[m++] = live ;
-	newargv[m++] = "-d" ;
-	newargv[m++] = treename ;
-	newargv[m++] = 0 ;
-				
-	pid = child_spawn0(newargv[0],newargv,envp) ;
-	if (waitpid_nointr(pid,&wstat, 0) < 0)
-	{
-		strerr_warnwu2sys("wait for ",newargv[0]) ;
-		return 0 ;
-	}
-	
-	if (wstat)
-	{
-		strerr_warnwu2x("init rc services for tree: ",treename) ;
-		return 0 ;
-	}
-	
-	VERBO3 strerr_warnt2x("reload scandir: ",scandir) ;
-	r = s6_svc_writectl(scandir, S6_SVSCAN_CTLDIR, "an", 2) ;
-	if (r < 0)
-	{
-		VERBO3 strerr_warnw3sys("something is wrong with the ",scandir, "/" S6_SVSCAN_CTLDIR " directory. errno reported") ;
-		return 0 ;
-	}
-	
-	return 1 ;
-}
-
-int rc_sanitize(char const *base, char const *scandir, char const *live, char const *livetree, char const *tree, char const *treename,genalloc *ga, char const *const *envp)
-{
-	pid_t pid ;
-	int wstat ;
-	genalloc toreload = GENALLOC_ZERO ; //stralist
-	
-	size_t livetreelen = strlen(livetree) ;
-	size_t namelen = strlen(treename) ;
-	
-	char db[livetreelen + 1 + namelen + 1] ;
-	memcpy(db,livetree,livetreelen) ;
-	db[livetreelen] = '/' ;
-	memcpy(db + livetreelen + 1, treename, namelen) ;
-	db[livetreelen + 1 + namelen] = 0 ;
-	
-	if (!db_ok(livetree, treename))
-		if (!rc_init(scandir,live,treename,envp)) return 0 ;
-	
-		
-	for (unsigned int i = 0; i < genalloc_len(svstat_t,ga) ; i++)
-	{
-		if (genalloc_s(svstat_t,ga)[i].reload)
-		{
-			if (!stra_add(&toreload,genalloc_s(svstat_t,ga)[i].name))
-			{
-				VERBO3 strerr_warnwu3x("add: ",genalloc_s(svstat_t,ga)[i].name," as service to reload") ;
-				return 0 ;
-			}
-		}
-	}
-	if (genalloc_len(stralist,&toreload))
-	{
-		
-		if (!db_switch_to(base,livetree,tree,treename,envp,SS_SWBACK))
-		{
-			VERBO3 strerr_warnwu3x("switch ",treename," to backup") ;
-			return 0 ;
-		}
-		if (!resolve_pointo(&saresolve,base,live,tree,treename,0,SS_RESOLVE_SRC))		
-		{
-			VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
-			return 0 ;
-		}
-		if (!db_compile(saresolve.s,tree,treename,envp))
-		{
-			VERBO3 strerr_diefu4x(111,"compile ",saresolve.s,"/",treename) ;
-			return 0 ;
-		}
-		if (!db_switch_to(base,livetree,tree,treename,envp,SS_SWSRC))
-		{
-			VERBO3 strerr_warnwu3x("switch ",treename," to backup") ;
-			return 0 ;
-		}
-	
-		char const *newargv[11 + genalloc_len(stralist,&toreload)] ;
-		unsigned int m = 0 ;
-		char fmt[UINT_FMT] ;
-		fmt[uint_fmt(fmt, VERBOSITY)] = 0 ;	
-
-		char tt[UINT32_FMT] ;
-		tt[uint32_fmt(tt,DEADLINE)] = 0 ;
-			
-		newargv[m++] = SS_BINPREFIX "66-dbctl" ;
-		newargv[m++] = "-v" ;
-		newargv[m++] = fmt ;
-		newargv[m++] = "-T" ;
-		newargv[m++] = tt ;
-		newargv[m++] = "-l" ;
-		newargv[m++] = live ;
-		newargv[m++] = "-t" ;
-		newargv[m++] = treename ;
-		newargv[m++] = "-d" ;
-
-		for (unsigned int i = 0; i < genalloc_len(stralist,&toreload) ; i++)
-			newargv[m++] = gaistr(&toreload,i) ;
-				
-		newargv[m++] = 0 ;
-			
-		pid = child_spawn0(newargv[0],newargv,envp) ;
-		if (waitpid_nointr(pid,&wstat, 0) < 0)
-		{
-			VERBO3 strerr_warnwu2sys("wait for ",newargv[0]) ;
-			goto err ;
-		}
-	
-		if (wstat)
-		{
-			VERBO3 strerr_warnwu1x("bring down service list") ;
-			goto err ;
-		}
-	}
-
-	return 1 ;
-	
-	err:
-		genalloc_deepfree(stralist,&toreload,stra_free) ;
-		return 0 ;
-}
-
-int rc_start(char const *base,char const *live, char const *livetree,char const *tree, char const *treename,genalloc *ga,char const *const *envp)
-{
-
-	int wstat ;
-	pid_t pid ;
-	
-	if (!db_switch_to(base,livetree,tree,treename,envp,SS_SWSRC))
-		strerr_diefu3x(111,"switch: ",treename," to source") ;
-	
-	char const *newargv[11 + genalloc_len(stralist,ga)] ;
-	unsigned int m = 0 ;
-	char fmt[UINT_FMT] ;
-	fmt[uint_fmt(fmt, VERBOSITY)] = 0 ;	
-
-	char tt[UINT32_FMT] ;
-	tt[uint32_fmt(tt,DEADLINE)] = 0 ;
-		
-	newargv[m++] = SS_BINPREFIX "66-dbctl" ;
-	newargv[m++] = "-v" ;
-	newargv[m++] = fmt ;
-	newargv[m++] = "-T" ;
-	newargv[m++] = tt ;
-	newargv[m++] = "-l" ;
-	newargv[m++] = live ;
-	newargv[m++] = "-t" ;
-	newargv[m++] = treename ;
-	if (RELOAD == 1) 
-		newargv[m++] = "-r" ;
-	else
-		newargv[m++] = "-u" ;
-		
-	for (unsigned int i = 0; i < genalloc_len(svstat_t,ga) ; i++)
-		newargv[m++] = genalloc_s(svstat_t,ga)[i].name ; ;
-		
-	newargv[m++] = 0 ;
-	
-	tain_t deadline ;
-	tain_from_millisecs(&deadline, DEADLINE) ;
-	
-	tain_now_g() ;
-	tain_add_g(&deadline, &deadline) ;
-	
-	
-	pid = child_spawn0(newargv[0],newargv,envp) ;
-	if (waitpid_nointr(pid,&wstat, 0) < 0)
-	{
-		VERBO3 strerr_warnwu2sys("wait for ",newargv[0]) ;
-		goto err ;
-	}
-
-	if (wstat)
-	{
-		VERBO3 strerr_warnwu1x("bring up service list") ;
-		goto err ;
-	}
-		
-	if (!resolve_pointo(&saresolve,base,live,tree,treename,0,SS_RESOLVE_SRC))
-	{
-		VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
-		return 0 ;
-	}
-
-	for (unsigned int i = 0; i < genalloc_len(svstat_t,ga) ; i++)
-	{
-		VERBO3 strerr_warnt2x("delete reload resolve file for: ",genalloc_s(svstat_t,ga)[i].name) ;
-		if (!resolve_remove(saresolve.s,genalloc_s(svstat_t,ga)[i].name,"reload"))
-		{
-			VERBO3 strerr_warnwu3sys("delete resolve file",saresolve.s,"/reload") ;
-			return 0 ;
-		}
-	}
-
-	return 1 ;
-	
-	err: 
-		return 0 ;
-}
-
 int main(int argc, char const *const *argv,char const *const *envp)
 {
-	int r,rb ;
-	
-	uid_t owner ;
-	
-	char *treename = 0 ;
-	
-	stralloc base = STRALLOC_ZERO ;
-	stralloc tree = STRALLOC_ZERO ;
-	stralloc scandir = STRALLOC_ZERO ;
-	stralloc live = STRALLOC_ZERO ;
-	stralloc livetree = STRALLOC_ZERO ;
-	stralloc svok = STRALLOC_ZERO ;
-	
-	genalloc nclassic = GENALLOC_ZERO ; //svstat_t type
-	genalloc nrc = GENALLOC_ZERO ; //svstat_t type
-		
 	PROG = "66-start" ;
-	{
-		subgetopt_t l = SUBGETOPT_ZERO ;
-
-		for (;;)
-		{
-			int opt = getopt_args(argc,argv, ">hv:l:t:rRT:", &l) ;
-			if (opt == -1) break ;
-			if (opt == -2) strerr_dief1x(110,"options must be set first") ;
-
-			switch (opt)
-			{
-				case 'h' : 	info_help(); return 0 ;
-				case 'v' :  if (!uint0_scan(l.arg, &VERBOSITY)) exitusage() ; break ;
-				case 'T' :	if (!uint0_scan(l.arg, &DEADLINE)) exitusage() ; break ;
-				case 'r' : 	if (RELOAD) exitusage() ; RELOAD = 1 ; SIG = "-R" ; break ;
-				case 'R' : 	if (RELOAD) exitusage() ; RELOAD = 2 ; SIG = "-R" ; break ;
-				case 'l' : 	if(!stralloc_cats(&live,l.arg)) retstralloc(111,"main") ;
-							if(!stralloc_0(&live)) retstralloc(111,"main") ;
-							break ;
-				case 't' : 	if(!stralloc_cats(&tree,l.arg)) retstralloc(111,"main") ;
-							if(!stralloc_0(&tree)) retstralloc(111,"main") ;
-							break ;
-				default : exitusage() ; 
-			}
-		}
-		argc -= l.ind ; argv += l.ind ;
-	}
-	
-	if (argc < 1) exitusage() ;
-	
-	owner = MYUID ;
-	
-	if (!set_ownersysdir(&base,owner)) strerr_diefu1sys(111, "set owner directory") ;
 	
-	r = tree_sethome(&tree,base.s) ;
-	if (r < 0) strerr_diefu1x(110,"find the current tree. You must use -t options") ;
-	if (!r) strerr_diefu2sys(111,"find tree: ", tree.s) ;
-	
-	treename = tree_setname(tree.s) ;
-	if (!treename) strerr_diefu1x(111,"set the tree name") ;
-	
-	if (!tree_get_permissions(tree.s))
-		strerr_dief2x(110,"You're not allowed to use the tree: ",tree.s) ;
-	
-	r = set_livedir(&live) ;
-	if (!r) retstralloc(111,"main") ;
-	if(r < 0) strerr_dief3x(111,"live: ",live.s," must be an absolute path") ;
-	
-	if (!stralloc_copy(&livetree,&live)) retstralloc(111,"main") ;
-	if (!stralloc_copy(&scandir,&live)) retstralloc(111,"main") ;
-	
-	r = set_livetree(&livetree,owner) ;
-	if (!r) retstralloc(111,"main") ;
-	if(r < 0) strerr_dief3x(111,"livetree: ",livetree.s," must be an absolute path") ;
-
-	r = set_livescan(&scandir,owner) ;
-	if (!r) retstralloc(111,"main") ;
-	if(r < 0) strerr_dief3x(111,"scandir: ",scandir.s," must be an absolute path") ;
-	
-	if ((scandir_ok(scandir.s)) !=1 ) strerr_dief3sys(111,"scandir: ", scandir.s," is not running") ;
-	
-	if (!stralloc_catb(&svok,scandir.s,scandir.len - 1)) retstralloc(111,"main") ; 
-	if (!stralloc_cats(&svok,"/")) retstralloc(111,"main") ; 
-	size_t svoklen = svok.len ;
-
-	{
-		stralloc type = STRALLOC_ZERO ;
-		svstat_t svsrc = SVSTAT_ZERO ;
-		
-		for(;*argv;argv++)
-		{
-			
-			svsrc.type = 0 ;
-			svsrc.name = 0 ;
-			svsrc.namelen = 0 ;
-			svsrc.down = 0 ;
-			svsrc.reload = 0 ;
-			svsrc.init = 0 ;
-			svok.len = svoklen ;
-			
-			if (!resolve_pointo(&saresolve,base.s,live.s,tree.s,treename,0,SS_RESOLVE_SRC))
-				strerr_diefu1x(111,"set revolve pointer to source") ;
-			rb = resolve_read(&type,saresolve.s,*argv,"type") ;
-			if (rb < -1) strerr_dief2x(111,"invalid .resolve directory: ",saresolve.s) ;
-			if (rb < 0)
-			{
-				if (!resolve_pointo(&saresolve,base.s,live.s,tree.s,treename,0,SS_RESOLVE_BACK))
-					strerr_diefu1x(111,"set revolve pointer to back") ;
-				r = resolve_read(&type,saresolve.s,*argv,"type") ;
-				if (r < -1) strerr_diefu2sys(111,"invalid .resolve directory: ",saresolve.s) ; 
-				if (r > 0) strerr_dief3x(111,"orphan service: ",*argv," :you can only stop it") ;
-				if (r <= 0) strerr_dief2x(111,*argv,": is not enabled") ;
-			}
-			if (rb > 0)
-			{
-				svsrc.type = get_enumbyid(type.s,key_enum_el) ;
-				svsrc.name = *argv ;
-				svsrc.namelen = strlen(*argv) ;
-				r = resolve_read(&type,saresolve.s,*argv,"reload") ;
-				if (r < -1) strerr_diefu2sys(111,"invalid .resolve directory: ",saresolve.s) ;
-				if (r > 0) svsrc.reload = 1 ;
-				r = resolve_read(&type,saresolve.s,*argv,"down") ;
-				if (r < -1) strerr_diefu2sys(111,"invalid .resolve directory: ",saresolve.s) ;
-				if (r > 0) svsrc.down = 1 ;
-				r = resolve_read(&type,saresolve.s,*argv,"remove") ;
-				if (r > 0) strerr_dief3x(111,"service: ",*argv," was disabled, you can only stop it") ;
-			}
-			if (svsrc.type == CLASSIC)
-			{
-				if (!stralloc_cats(&svok,*argv)) retstralloc(111,"main") ; 
-				if (!stralloc_0(&svok)) retstralloc(111,"main") ; 
-				r = s6_svc_ok(svok.s) ;
-				if (r < 0) strerr_diefu2sys(111,"check ", svok.s) ;
-				if (!r)	svsrc.init = 1 ;
-			}
-
-			if (RELOAD > 1) svsrc.reload = 1 ;
-			if (svsrc.init) svsrc.reload = 0 ;
-			
-			if (svsrc.type == CLASSIC)
-			{
-				if (!resolve_pointo(&saresolve,base.s,live.s,tree.s,treename,CLASSIC,SS_RESOLVE_SRC))
-					strerr_diefu1x(111,"set revolve pointer to source") ;
-				if (dir_search(saresolve.s,*argv,S_IFDIR) !=1) strerr_dief2x(111,*argv,": is not enabled") ;
-				if (!genalloc_append(svstat_t,&nclassic,&svsrc)) strerr_diefu3x(111,"add: ",*argv," on genalloc") ;				
-			}
-			else
-			{
-				if (!genalloc_append(svstat_t,&nrc,&svsrc)) strerr_diefu3x(111,"add: ",*argv," on genalloc") ;
-			}
-		}
-		stralloc_free(&type) ;
-		stralloc_free(&svok) ;
-	}
-
-	if (genalloc_len(svstat_t,&nclassic))
-	{
-		VERBO2 strerr_warni1x("sanitize svc services ...") ;
-		if(!svc_sanitize(base.s,scandir.s,live.s,tree.s,treename,&nclassic,envp)) 
-			strerr_diefu1x(111,"sanitize s6-svc services") ;
-		VERBO2 strerr_warni1x("start svc services ...") ;
-		if(!svc_start(base.s,scandir.s,live.s,tree.s,treename,&nclassic,envp)) 
-			strerr_diefu1x(111,"start s6-svc services") ;
-		VERBO2 strerr_warni3x("switch svc service of: ",treename," to source") ;
-		if (!svc_switch_to(base.s,tree.s,treename,SS_SWSRC))
-			strerr_diefu3x(111,"switch svc service of: ",treename," to source") ;
-	} 
-	if (genalloc_len(svstat_t,&nrc))
-	{
-		VERBO2 strerr_warni1x("sanitize rc services ...") ;
-		if (!rc_sanitize(base.s,scandir.s,live.s,livetree.s,tree.s,treename,&nrc,envp)) 
-			strerr_diefu1x(111,"sanitize s6-rc services") ;
-		VERBO2 strerr_warni1x("start rc services ...") ;
-		if (!rc_start(base.s,live.s,livetree.s,tree.s,treename,&nrc,envp)) 
-			strerr_diefu1x(111,"update s6-rc services") ;
-		VERBO2 strerr_warni3x("switch rc services of: ",treename," to source") ;
-		if (!db_switch_to(base.s,livetree.s,tree.s,treename,envp,SS_SWSRC))
-			strerr_diefu5x(111,"switch",livetree.s,"/",treename," to source") ;
-	}
+	ssexec_t info = SSEXEC_ZERO ;
 	
-	stralloc_free(&base) ;
-	stralloc_free(&tree) ;
-	stralloc_free(&scandir) ;
-	stralloc_free(&live) ;
-	stralloc_free(&livetree) ;
-	stralloc_free(&saresolve) ;
-	genalloc_free(svstat_t,&nclassic) ;
-	genalloc_free(svstat_t,&nrc) ;
-	genalloc_deepfree(stralist,&DOWNFILE,stra_free) ;
-	free(treename) ;
+	info.prog = PROG ;
+	info.help = help_start ;
+	info.usage = usage_start ;
 	
-	return 0 ;		
+	return ssexec_main(argc,argv,envp,&ssexec_start,&info) ;
 }
 	
 
diff --git a/src/66/66-stop.c b/src/66/66-stop.c
index c0d2840b8ad9a54f391b90f8fb561cfae0fc7e03..474839af2f48fe9e95abb22fa5c58616e1e09da6 100644
--- a/src/66/66-stop.c
+++ b/src/66/66-stop.c
@@ -12,586 +12,23 @@
  * except according to the terms contained in the LICENSE file./
  */
 
-#include <string.h>
-#include <sys/stat.h>
-#include <stdlib.h>
+#include <skalibs/strerr2.h>
 
-#include <oblibs/obgetopt.h>
-#include <oblibs/error2.h>
-#include <oblibs/string.h>
-#include <oblibs/types.h>
-#include <oblibs/directory.h>
-#include <oblibs/stralist.h>
-
-#include <skalibs/buffer.h>
-#include <skalibs/types.h>
-#include <skalibs/stralloc.h>
-#include <skalibs/genalloc.h>
-#include <skalibs/djbunix.h>
-#include <skalibs/unix-transactional.h>
-#include <skalibs/selfpipe.h>
-#include <skalibs/sig.h>
-
-#include <s6/s6-supervise.h>//s6_svc_ok
-#include <s6/config.h>
-
-
-#include <66/tree.h>
-#include <66/db.h>
-#include <66/config.h>
-#include <66/utils.h>
-#include <66/constants.h>
-#include <66/enum.h>
-#include <66/svc.h>
-#include <66/backup.h>
-
-//#include <stdio.h>
+#include <66/ssexec.h>
 
 unsigned int VERBOSITY = 1 ;
-static unsigned int DEADLINE = 0 ;
-unsigned int UNSUP = 0 ;
-static char *SIG = "-D" ;
-stralloc saresolve = STRALLOC_ZERO ;
-genalloc gatoremove = GENALLOC_ZERO ;//stralist
-genalloc gaunsup = GENALLOC_ZERO ; //stralist
-
-#define USAGE "66-stop [ -h ] [ -v verbosity ] [ -T timeout ] [ -l live ] [ -t tree ] [ -u ] [ -X ] [ -K ] service(s)"
-
-static inline void info_help (void)
-{
-  static char const *help =
-"66-stop <options> service(s)\n"
-"\n"
-"options :\n"
-"	-h: print this help\n" 
-"	-v: increase/decrease verbosity\n"
-"	-l: live directory\n"
-"	-T: timeout\n"
-"	-t: tree to use\n"
-"	-u: unsupervise service(s)\n"
-"	-X: bring down the service(s) and kill his supervisor\n"
-"	-K: kill the service(s) and keep it down\n"
-
-;
-
- if (buffer_putsflush(buffer_1, help) < 0)
-    strerr_diefu1sys(111, "write to stdout") ;
-}
-
-int svc_release(char const *base, char const *scandir, char const *live, char const *tree, char const *treename)
-{
-	size_t scanlen = strlen(scandir) ;
-	
-	if (genalloc_len(stralist,&gaunsup))
-	{
-		for (unsigned int i = 0; i < genalloc_len(stralist,&gaunsup); i++)
-		{
-			char const *svname = gaistr(&gaunsup,i) ;
-			size_t svnamelen = gaistrlen(&gaunsup,i) ;
-	
-			char rm[scanlen + 1 + svnamelen + 1] ;
-			memcpy(rm,scandir,scanlen) ;
-			rm[scanlen] = '/' ;
-			memcpy(rm + scanlen + 1, svname,svnamelen) ;
-			rm[scanlen + 1 + svnamelen] = 0 ;
-			VERBO3 strerr_warnt2x("unsupervise: ",rm) ;
-			if (rm_rf(rm) < 0)
-			{
-				VERBO3 strerr_warnwu2sys("delete directory: ",rm) ;
-				return 0 ;
-			}
-		}
-	}
-	if (!resolve_pointo(&saresolve,base,live,tree,treename,0,SS_RESOLVE_SRC))
-	{
-		VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
-		return 0 ;
-	}
-	if (genalloc_len(stralist,&gatoremove))
-	{
-		for (unsigned int i = 0; i < genalloc_len(stralist,&gatoremove); i++)
-		{
-			char const *svname = gaistr(&gatoremove,i) ;
-			
-			if (!resolve_remove_service(saresolve.s,svname))
-			{
-				VERBO3 strerr_warnwu4sys("delete resolve service file: ",saresolve.s,"/.resolve/",svname) ;
-				return 0 ;
-			}
-		}
-	}
-	
-	return 1 ;
-}
-int svc_down(char const *base,char const *scandir,char const *live,char const *tree, char const *treename,genalloc *ga,char const *const *envp)
-{
-	int wstat ;
-	pid_t pid ; 
-	
-	genalloc tot = GENALLOC_ZERO ; //stralist
-		
-	for (unsigned int i = 0 ; i < genalloc_len(svstat_t,ga) ; i++) 
-	{
-		char const *svname = genalloc_s(svstat_t,ga)[i].name ;
-		int torm = genalloc_s(svstat_t,ga)[i].remove ;
-		int unsup = genalloc_s(svstat_t,ga)[i].unsupervise ;
-		
-		if (!stra_add(&tot,svname))
-		{
-			VERBO3 strerr_warnwu3x("add: ",svname," as service to shutdown") ;
-			return 0 ;
-		}
-		
-		/** need to remove?*/
-		if (torm)
-		{
-			if (!stra_add(&gatoremove,svname))
-			{
-				VERBO3 strerr_warnwu3x("add: ",svname," as service to delete") ;
-				return 0 ;
-			}
-		}
-		/** unsupervise */
-		if (unsup)
-		{
-			if (!stra_add(&gaunsup,svname))
-			{
-				VERBO3 strerr_warnwu3x("add: ",svname," as service to unsupervise") ;
-				return 0 ;
-			}
-		}
-		/** logger */
-		if (!resolve_pointo(&saresolve,base,live,tree,treename,0,SS_RESOLVE_SRC))
-		{
-			VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
-			return 0 ;
-		}
-		if (resolve_read(&saresolve,saresolve.s,svname,"logger"))
-		{
-			if (!stra_add(&tot,saresolve.s))
-			{
-				VERBO3 strerr_warnwu3x("add: ",saresolve.s," as service to shutdown") ;
-				return 0 ;
-			}
-			if (torm)
-			{
-				if (!stra_add(&gatoremove,saresolve.s))
-				{
-					VERBO3 strerr_warnwu3x("add logger of: ",saresolve.s," as service to delete") ;
-					return 0 ;
-				}
-			}
-			if (unsup)
-			{
-				if (!stra_add(&gaunsup,svname))
-				{
-					VERBO3 strerr_warnwu3x("add: ",saresolve.s," as service to unsupervise") ;
-					return 0 ;
-				}
-			}
-		}
-	}
-	char const *newargv[11 + genalloc_len(stralist,&tot)] ;
-	unsigned int m = 0 ;
-	char fmt[UINT_FMT] ;
-	fmt[uint_fmt(fmt, VERBOSITY)] = 0 ;
-
-	char tt[UINT32_FMT] ;
-	tt[uint32_fmt(tt,DEADLINE)] = 0 ;
-
-	newargv[m++] = SS_BINPREFIX "66-svctl" ;
-	newargv[m++] = "-v" ;
-	newargv[m++] = fmt ;
-	newargv[m++] = "-T" ;
-	newargv[m++] = tt ;
-	newargv[m++] = "-l" ;
-	newargv[m++] = live ;
-	newargv[m++] = "-t" ;
-	newargv[m++] = treename ;
-	newargv[m++] = SIG ;
-	for (unsigned int i = 0 ; i < genalloc_len(stralist,&tot) ; i++) 
-		newargv[m++] = gaistr(&tot,i) ;
-	
-	newargv[m++] = 0 ;
-	
-	pid = child_spawn0(newargv[0],newargv,envp) ;
-	if (waitpid_nointr(pid,&wstat, 0) < 0)
-	{
-		VERBO3 strerr_warnwu2sys("wait for ",newargv[0]) ;
-		return 0 ;
-	}
-	if (wstat)
-	{
-		VERBO3 strerr_warnwu1x("shutdown list of services") ;
-		return 0 ;
-	}
-	
-	
-	if (!resolve_pointo(&saresolve,base,live,tree,treename,0,SS_RESOLVE_SRC))
-	{
-		VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
-		return 0 ;
-	}
-	for (unsigned int i = 0; i < genalloc_len(svstat_t,ga) ; i++)
-	{
-		VERBO3 strerr_warnt2x("delete remove resolve file for: ",genalloc_s(svstat_t,ga)[i].name) ;
-		if (!resolve_remove(saresolve.s,genalloc_s(svstat_t,ga)[i].name,"remove"))
-		{
-			VERBO3 strerr_warnwu3sys("delete resolve file",saresolve.s,"/remove") ;
-			return 0 ;
-		}
-	}
-	genalloc_deepfree(stralist,&tot,stra_free) ;
-	
-	return 1 ;
-	
-}
-int rc_release(char const *base, char const *scandir, char const *live,char const *tree, char const *treename)
-{
-
-	if (!resolve_pointo(&saresolve,base,live,tree,treename,0,SS_RESOLVE_SRC))
-	{
-		VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
-		return 0 ;
-	}
-	if (genalloc_len(stralist,&gatoremove))
-	{
-		for (unsigned int i = 0; i < genalloc_len(stralist,&gatoremove); i++)
-		{
-			char const *svname = gaistr(&gatoremove,i) ;
-			
-			if (!resolve_remove_service(saresolve.s,svname))
-			{
-				VERBO3 strerr_warnwu4sys("delete resolve service file: ",saresolve.s,"/.resolve/",svname) ;
-				return 0 ;
-			}
-		}
-	}
-	
-	return 1 ;
-}
-
-int rc_down(char const *base, char const *scandir, char const *live, char const *livetree,char const *tree, char const *treename,genalloc *ga,char const *const *envp)
-{
-	int wstat ;
-	pid_t pid ;
-	
-	size_t livetreelen = strlen(livetree) ;
-	size_t treenamelen = strlen(treename) ;
-
-	genalloc tot = GENALLOC_ZERO ; //stralist
-
-	for (unsigned int i = 0 ; i < genalloc_len(svstat_t,ga) ; i++) 
-	{
-		
-		char const *svname = genalloc_s(svstat_t,ga)[i].name ;
-		int torm = genalloc_s(svstat_t,ga)[i].remove ;
-		
-		if (!stra_add(&tot,svname))
-		{
-			VERBO3 strerr_warnwu3x("add: ",svname," as service to shutdown") ;
-			return 0 ;
-		}
-		
-		/** need to remove?*/
-		if (torm)
-		{
-			if (!stra_add(&gatoremove,svname))
-			{
-				VERBO3 strerr_warnwu3x("add: ",svname," as service to delete") ;
-				return 0 ;
-			}
-		}
-		/** logger */
-		if (!resolve_pointo(&saresolve,base,live,tree,treename,0,SS_RESOLVE_SRC))
-		{
-			VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
-			return 0 ;
-		}
-		if (resolve_read(&saresolve,saresolve.s,svname,"logger"))
-		{
-			if (!stra_add(&tot,saresolve.s))
-			{
-				VERBO3 strerr_warnwu3x("add: ",saresolve.s," as service to shutdown") ;
-				return 0 ;
-			}
-			if (torm)
-			{
-				if (!stra_add(&gatoremove,saresolve.s))
-				{
-					VERBO3 strerr_warnwu3x("add logger of: ",saresolve.s," as service to delete") ;
-					return 0 ;
-				}
-			}
-		}
-	}
-	
-	
-	
-	char db[livetreelen + 1 + treenamelen + 1] ;
-	memcpy(db,livetree,livetreelen) ;
-	db[livetreelen] = '/' ;
-	memcpy(db + livetreelen + 1, treename, treenamelen) ;
-	db[livetreelen + 1 + treenamelen] = 0 ;
-	
-	if (!db_ok(livetree, treename))
-		strerr_dief2x(111,db," is not initialized") ;
-			
-	char const *newargv[11 + genalloc_len(stralist,&tot)] ;
-	unsigned int m = 0 ;
-	char fmt[UINT_FMT] ;
-	fmt[uint_fmt(fmt, VERBOSITY)] = 0 ;	
-
-	char tt[UINT32_FMT] ;
-	tt[uint32_fmt(tt,DEADLINE)] = 0 ;
-
-	newargv[m++] = SS_BINPREFIX "66-dbctl" ;
-	newargv[m++] = "-v" ;
-	newargv[m++] = fmt ;
-	newargv[m++] = "-T" ;
-	newargv[m++] = tt ;
-	newargv[m++] = "-l" ;
-	newargv[m++] = live ;
-	newargv[m++] = "-t" ;
-	newargv[m++] = treename ;
-	newargv[m++] = "-d" ;
-	
-	for (unsigned int i = 0; i < genalloc_len(stralist,&tot) ; i++)
-			newargv[m++] = gaistr(&tot,i) ;
-		
-	newargv[m++] = 0 ;
-	
-	pid = child_spawn0(newargv[0],newargv,envp) ;
-	if (waitpid_nointr(pid,&wstat, 0) < 0)
-	{
-		VERBO3 strerr_warnwu2sys("wait for ",newargv[0]) ;
-		return 0 ;
-	}
-	if (wstat)
-	{
-		VERBO3 strerr_warnwu1x("bring down service list") ;
-		return 0 ;
-	}
-	
-	if (!resolve_pointo(&saresolve,base,live,tree,treename,0,SS_RESOLVE_SRC))
-	{
-		VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
-		return 0 ;
-	}
-	for (unsigned int i = 0; i < genalloc_len(svstat_t,ga) ; i++)
-	{
-		VERBO3 strerr_warnt2x("delete remove resolve file for: ",genalloc_s(svstat_t,ga)[i].name) ;
-		if (!resolve_remove(saresolve.s,genalloc_s(svstat_t,ga)[i].name,"remove"))
-		{
-			VERBO3 strerr_warnwu3sys("delete resolve file",saresolve.s,"/remove") ;
-			return 0 ;
-		}
-	}
-
-	
-	genalloc_deepfree(stralist,&tot,stra_free) ;
-	
-	return 1 ;
-}
 
 int main(int argc, char const *const *argv,char const *const *envp)
 {
-	int r, rb, sigopt ;
-		
-	uid_t owner ;
-	
-	char *treename = 0 ;
-	
-	stralloc base = STRALLOC_ZERO ;
-	stralloc tree = STRALLOC_ZERO ;
-	stralloc scandir = STRALLOC_ZERO ;
-	stralloc live = STRALLOC_ZERO ;
-	stralloc livetree = STRALLOC_ZERO ;
-	stralloc svok = STRALLOC_ZERO ;
-	
-	genalloc nclassic = GENALLOC_ZERO ;
-	genalloc nrc = GENALLOC_ZERO ;
-	
-	sigopt = 0 ;
-	
 	PROG = "66-stop" ;
-	{
-		subgetopt_t l = SUBGETOPT_ZERO ;
-
-		for (;;)
-		{
-			int opt = getopt_args(argc,argv, ">hv:l:t:T:uXK", &l) ;
-			if (opt == -1) break ;
-			if (opt == -2) strerr_dief1x(110,"options must be set first") ;
-
-			switch (opt)
-			{
-				case 'h' : 	info_help(); return 0 ;
-				case 'v' :  if (!uint0_scan(l.arg, &VERBOSITY)) exitusage() ; break ;
-				case 'l' : 	if(!stralloc_cats(&live,l.arg)) retstralloc(111,"main") ;
-							if(!stralloc_0(&live)) retstralloc(111,"main") ;
-							break ;
-				case 'T' :	if (!uint0_scan(l.arg, &DEADLINE)) exitusage() ; break ;
-				case 't' : 	if(!stralloc_cats(&tree,l.arg)) retstralloc(111,"main") ;
-							if(!stralloc_0(&tree)) retstralloc(111,"main") ;
-							break ;
-				case 'u' :	UNSUP = 1 ; break ;
-				case 'X' :	if (sigopt) exitusage() ; sigopt = 1 ; SIG = "-X" ; break ;
-				case 'K' :	if (sigopt) exitusage() ; sigopt = 1 ; SIG = "-K" ; break ;
-				default : exitusage() ; 
-			}
-		}
-		argc -= l.ind ; argv += l.ind ;
-	}
-	
-	if (argc < 1) exitusage() ;
-	
-	owner = MYUID ;
-	
-	if (!set_ownersysdir(&base,owner)) strerr_diefu1sys(111, "set owner directory") ;
-
-	r = tree_sethome(&tree,base.s) ;
-	if (r < 0) strerr_diefu1x(110,"find the current tree. You must use -t options") ;
-	if (!r) strerr_diefu2sys(111,"find tree: ", tree.s) ;
-	
-	treename = tree_setname(tree.s) ;
-	if (!treename) strerr_diefu1x(111,"set the tree name") ;
 	
-	if (!tree_get_permissions(tree.s))
-		strerr_dief2x(110,"You're not allowed to use the tree: ",tree.s) ;
+	ssexec_t info = SSEXEC_ZERO ;
 	
-	r = set_livedir(&live) ;
-	if (!r) retstralloc(111,"main") ;
-	if(r < 0) strerr_dief3x(111,"live: ",live.s," must be an absolute path") ;
+	info.prog = PROG ;
+	info.help = help_stop ;
+	info.usage = usage_stop ;
 	
-	if (!stralloc_copy(&livetree,&live)) retstralloc(111,"main") ;
-	if (!stralloc_copy(&scandir,&live)) retstralloc(111,"main") ;
-		
-	r = set_livetree(&livetree,owner) ;
-	if (!r) retstralloc(111,"main") ;
-	if(r < 0) strerr_dief3x(111,"livetree: ",livetree.s," must be an absolute path") ;
-
-	r = set_livescan(&scandir,owner) ;
-	if (!r) retstralloc(111,"main") ;
-	if(r < 0) strerr_dief3x(111,"scandir: ",scandir.s," must be an absolute path") ;
-	
-	if ((scandir_ok(scandir.s)) !=1 ) strerr_dief3sys(111,"scandir: ", scandir.s," is not running") ;
-	
-	if (!stralloc_catb(&svok,scandir.s,scandir.len - 1)) retstralloc(111,"main") ; 
-	if (!stralloc_cats(&svok,"/")) retstralloc(111,"main") ; 
-	size_t svoklen = svok.len ;
-	
-	{
-		stralloc type = STRALLOC_ZERO ;
-		svstat_t svsrc = SVSTAT_ZERO ;
-		
-		for(;*argv;argv++)
-		{
-			svsrc.type = 0 ;
-			svsrc.name = 0 ;
-			svsrc.namelen = 0 ;
-			svsrc.remove = 0 ;
-			svsrc.unsupervise = 0 ;
-			svok.len = svoklen ;
-			
-			if (!resolve_pointo(&saresolve,base.s,live.s,tree.s,treename,0,SS_RESOLVE_SRC))
-				strerr_diefu1x(111,"set revolve pointer to source") ;
-			rb = resolve_read(&type,saresolve.s,*argv,"type") ;
-			if (rb < -1) strerr_dief2x(111,"invalid .resolve directory: ",saresolve.s) ;
-			if (rb < 0)
-			{
-				if (!resolve_pointo(&saresolve,base.s,live.s,tree.s,treename,0,SS_RESOLVE_BACK))
-					strerr_diefu1x(111,"set revolve pointer to backup") ;
-				r = resolve_read(&type,saresolve.s,*argv,"type") ;
-				if (r < -1) strerr_diefu2sys(111,"invalid .resolve directory: ",saresolve.s) ; 
-				if (r > 0) svsrc.remove = 1 ;
-				if (r <= 0) strerr_dief2x(111,*argv,": is not enabled") ;
-			}
-			if (rb > 0)
-			{
-				svsrc.type = get_enumbyid(type.s,key_enum_el) ;
-				svsrc.name = *argv ;
-				svsrc.namelen = strlen(*argv) ;
-				r = resolve_read(&type,saresolve.s,*argv,"remove") ;
-				if (r < -1) strerr_diefu2sys(111,"invalid .resolve directory: ",saresolve.s) ;
-				if (r > 0) svsrc.remove = 1 ;
-			/*	if (!resolve_pointo(&saresolve,base.s,live.s,tree.s,treename,0,SS_RESOLVE_BACK))
-					strerr_diefu1x(111,"set revolve pointer to backup") ;
-				r = resolve_read(&type,saresolve.s,*argv,"type") ;
-				if (r <= 0 && !UNSUP) strerr_dief3x(111,"service: ",*argv," is not running, you can only start it") ;*/
-			}
-			if (svsrc.type == CLASSIC)
-			{
-				if (!stralloc_cats(&svok,*argv)) retstralloc(111,"main") ; 
-				if (!stralloc_0(&svok)) retstralloc(111,"main") ; 
-				r = s6_svc_ok(svok.s) ;
-				if (r < 0) strerr_diefu2sys(111,"check ", svok.s) ;
-				//if (!r)	svsrc.remove = 1 ;
-				if (!r) strerr_dief3x(111,"service: ",*argv," is not running, you can only start it") ;
-			}
-			
-			if (UNSUP) svsrc.unsupervise = 1 ;
-			if (svsrc.remove) svsrc.unsupervise = 1 ;
-			
-			if (svsrc.type == CLASSIC)
-			{
-				if (!genalloc_append(svstat_t,&nclassic,&svsrc)) strerr_diefu3x(111,"add: ",*argv," on genalloc") ;				
-			}
-			else
-			{
-				if (!genalloc_append(svstat_t,&nrc,&svsrc)) strerr_diefu3x(111,"add: ",*argv," on genalloc") ;
-			}
-		}
-		stralloc_free(&type) ;
-		stralloc_free(&svok) ;
-	}
-	
-	/** rc work */
-	if (genalloc_len(svstat_t,&nrc))
-	{
-		VERBO2 strerr_warni1x("stop rc services ...") ;
-		if (!rc_down(base.s, scandir.s, live.s,livetree.s,tree.s,treename,&nrc,envp))
-			strerr_diefu1x(111,"update rc services") ;
-		VERBO2 strerr_warni1x("release rc services ...") ;
-		if (!rc_release(base.s,scandir.s, live.s,tree.s,treename))
-			strerr_diefu1x(111,"release rc services") ;
-		VERBO2 strerr_warni3x("switch rc services of: ",treename," to source") ;
-		if (!db_switch_to(base.s,livetree.s,tree.s,treename,envp,SS_SWSRC))
-			strerr_diefu5x(111,"switch",livetree.s,"/",treename," to source") ;
-	}
-	
-	/** svc work */
-	if (genalloc_len(svstat_t,&nclassic))
-	{
-		VERBO2 strerr_warni1x("stop svc services ...") ;
-		if (!svc_down(base.s,scandir.s,live.s,tree.s,treename,&nclassic,envp))
-			strerr_diefu1x(111,"update svc services") ;
-		VERBO2 strerr_warni1x("release svc services ...") ;
-		if (!svc_release(base.s,scandir.s,live.s,tree.s,treename))
-			strerr_diefu1x(111,"release svc services ...") ;
-		VERBO2 strerr_warni3x("switch svc services of: ",treename," to source") ;
-		if (!svc_switch_to(base.s,tree.s,treename,SS_SWSRC))
-			strerr_diefu3x(111,"switch svc service of: ",treename," to source") ;
-		
-	}
-		
-	if (UNSUP || genalloc_len(stralist,&gatoremove))
-	{
-		VERBO2 strerr_warnt2x("send signal -an to scandir: ",scandir.s) ;
-		if (scandir_send_signal(scandir.s,"an") <= 0)
-			strerr_diefu2sys(111,"send signal to scandir: ", scandir.s) ;
-	}
-	
-	stralloc_free(&base) ;
-	stralloc_free(&tree) ;
-	stralloc_free(&scandir) ;
-	stralloc_free(&live) ;
-	stralloc_free(&livetree) ;
-	genalloc_free(svstat_t,&nrc) ;
-	genalloc_free(svstat_t,&nclassic) ;
-	free(treename) ;
-
-	return 0 ;		
+	return ssexec_main(argc,argv,envp,&ssexec_stop,&info) ;
 }
 	
 
diff --git a/src/66/66-svctl.c b/src/66/66-svctl.c
index 6f54bbb9f9590a2f2dca1b4234229364c6f116e2..dde1ba90a754f23d98282a12326e50b97407eb0f 100644
--- a/src/66/66-svctl.c
+++ b/src/66/66-svctl.c
@@ -11,590 +11,24 @@
  * This file may not be copied, modified, propagated, or distributed
  * except according to the terms contained in the LICENSE file./
  */
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
 
-#include <oblibs/obgetopt.h>
-#include <oblibs/error2.h>
-#include <oblibs/types.h>
-#include <oblibs/string.h>
-#include <oblibs/stralist.h>
+#include <skalibs/strerr2.h>
 
-#include <skalibs/buffer.h>
-#include <skalibs/types.h>
-#include <skalibs/stralloc.h>
-#include <skalibs/genalloc.h>
-#include <skalibs/djbunix.h>
-#include <skalibs/bytestr.h>
-#include <skalibs/selfpipe.h>
-#include <skalibs/iopause.h>
-#include <skalibs/sig.h>
-
-#include <s6/s6-supervise.h>//s6_svstatus_t
-#include <s6/ftrigr.h>
-
-#include <66/svc.h>
-#include <66/constants.h>
-#include <66/utils.h>
-#include <66/tree.h>
-
-//#include <stdio.h>
+#include <66/ssexec.h>
 
 unsigned int VERBOSITY = 1 ;
-stralloc svkeep = STRALLOC_ZERO ;
-genalloc gakeep = GENALLOC_ZERO ; //type svc_sig_s
-stralloc saresolve = STRALLOC_ZERO ;
-
-unsigned int SV_DEADLINE = 3000 ;
-unsigned int DEATHSV = 10 ;
-
-int SIGNAL = -1 ;
-
-#define USAGE "66-svctl [ -h ] [ -v verbosity ] [ -l live ] [ -t tree ] [ -T timeout ] [ -n death ] [ -u | U | d | D | r | R | K | X ] service(s)"
-
-static inline void info_help (void)
-{
-  static char const *help =
-"66-svctl <options> tree\n"
-"\n"
-"options :\n"
-"	-h: print this help\n" 
-"	-v: increase/decrease verbosity\n"
-"	-l: live directory\n"
-"	-t: tree to use\n"
-"	-T: service timeout\n"
-"	-n: number of death\n"
-"	-u: bring up the service(s)\n"
-"	-U: really up\n"
-"	-d: bring down the service(s)\n"
-"	-D: really down\n"
-"	-r: reload\n"
-"	-R: reload and really up\n"
-"	-X: bring down the service(s) and the kill his supervisor\n"
-"	-K: kill the service(s) and keep it down\n"
-;
-
- if (buffer_putsflush(buffer_1, help) < 0)
-    strerr_diefu1sys(111, "write to stdout") ;
-}
-
-static int read_file (char const *file, char *buf, size_t n)
-{
-	ssize_t r = openreadnclose_nb(file, buf, n) ;
-	if (r < 0)
-	{
-		if (errno != ENOENT) VERBO3 strerr_warnwu2sys("open: ", file) ;
-		return 0 ;
-	}
-	buf[byte_chr(buf, r, '\n')] = 0 ;
-	return 1 ;
-}
-
-static int read_uint (char const *file, unsigned int *fd)
-{
-	char buf[UINT_FMT + 1] ;
-	if (!read_file(file, buf, UINT_FMT)) return 0 ;
-	if (!uint0_scan(buf, fd))
-	{
-		VERBO3 strerr_warnw2x("invalid: ", file) ;
-		return 0 ;
-	}
-	return 1 ;
-}
-
-/** @Return 0 on fail
- * @Return 1 on success */
-int handle_signal_svc(svc_sig *sv_signal)
-{
-	s6_svstatus_t status = S6_SVSTATUS_ZERO ;
-	char *sv = svkeep.s + sv_signal->scan ;
-	if (!s6_svstatus_read(sv,&status))
-	{ 
-		VERBO3 strerr_warnwu2sys("read status of: ",sv) ;
-		return 0 ;
-	}
-	
-	int exitcode, exitstatus ;
-	exitcode = WIFEXITED(status.wstat) ;
-	exitstatus = WEXITSTATUS(status.wstat) ;
-	if (exitcode && exitstatus <= 1) return 1 ;
-	else return 0 ;
-}
-
-
-static unsigned char const actions[9][9] = 
-{
- //signal receive:
- //  c->u		U		r/u		R/U		d		D		x		O		s						
-																				//signal wanted
-    { GOTIT,	DONE,	GOTIT,	DONE,	DEAD,	DEAD,	PERM,	PERM,	UKNOW },// SIGUP 
-    { WAIT,		GOTIT,	WAIT,	GOTIT,	DEAD,	DEAD,	PERM,	PERM,	UKNOW },// SIGRUP
-    { GOTIT,	DONE,	GOTIT,	DONE,	WAIT,	WAIT,	PERM,	PERM,	UKNOW },// SIGR
-    { WAIT,		GOTIT,	WAIT,	GOTIT,	WAIT,	WAIT,	PERM,	PERM,	UKNOW },// SIGRR
-    { DEAD,		DEAD,	DEAD,	DEAD,	GOTIT,	DONE,	PERM,	PERM,	UKNOW },// SIGDOWN
-    { DEAD,		DEAD,	DEAD,	DEAD,	WAIT,	GOTIT,	PERM,	PERM,	UKNOW },// SIGRDOWN
-    { DEAD,		DEAD,	DEAD,	DEAD,	WAIT,	WAIT,	GOTIT,	WAIT, 	UKNOW },// SIGX
-    { WAIT,		WAIT,	WAIT,	WAIT,	WAIT,	WAIT,	PERM,	GOTIT, 	UKNOW },// SIGO
-    { UKNOW,	UKNOW,	UKNOW,	UKNOW,	UKNOW,	UKNOW,	UKNOW,	UKNOW, 	DONE },	// SIGSUP
-    
-} ;
-//	convert signal receive into enum number
-static const uint8_t chtenum[128] = 
-{	
-	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //8
-	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //16
-	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //24
-	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //32
-	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //40
-	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //48
-	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //56
-	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //64
-	0 ,  0 ,  0 ,  0 ,  5 ,  0 ,  0 ,  0 , //72
-	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  7 , //80
-	0 ,  0 ,  0 ,  0 ,  0 ,  1,   0 ,  0 , //88
-	6 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //96
-	0 ,  0 ,  0 ,  0 ,  4 ,  0 ,  0 ,  0 , //104
-	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //112
-	0 ,  0 ,  0 ,  8 ,  0 ,  0 ,  0 ,  0 , //120
-	6 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0   //128
-} ;
-/** we use three file more than s6-svc program :
- * 	 
- *	 timeout-up and timeout-down will define the deadline for the iopause
- * 		each service contain his deadline into the sv_signal.deadline key.
- * 		If thoses files doesn't exit 3000 millisec is set by default.
- * 		This deadline value can be set on commandline by the -T options.
- *	 max-death-tally
- * 		We let s6-supervise make what it need to do with this file but
- * 		we take the same number to set the sv_signal.death value
- * 		accepted for every daemon before exiting if the SIGNAL is not reached.
- * 		If this file doesn't exist a number of 3 death (death -> number 
- * 		of wrong signal received) is set by default.
- * 		This ndeath value can be set on commandline by the -n options.
- *
- * In all case the loop is broken to avoids infinite iopause 
- * 
- * The notication-fd file is used as the original one. If the file 
- * doesn't exist and the SIGNAL is U , we change SIGNAL to u and warn
- * the user about it.
- *
- * In the send_svc function a reached timeout is not an absolute error
- * because we can have a notification-file in the servicedirs of the
- * service with a deamon which doesn't support readiness notification. 
- * In this case, we send U and only receive u as event, the daemon is
- * running but not notified by the daemon itself.
- * We accept this case as an "half" success. We exit with success but
- * the user is warned about the state. */
- 	
-/**@Return 0 on success
- * @Return 1 on if signal is not complete (e.g. want U receive only u)
- * @Return 2 on fail
- * @Return 3 for PERMANENT failure */
-
-int handle_case(char c, svc_sig *sv_signal)
-{
-	int p, h, err ;
-	unsigned int state ;
-	state = sv_signal->sig ;
-	err = 2 ;
-	
-	p = chtenum[(unsigned char)c] ;
-	
-	unsigned char action = actions[state][p] ;
-	
-	switch (action)
-	{
-		case GOTIT:
-					h = handle_signal_svc(sv_signal) ;
-					
-					if (!h)
-					{
-						err = 1 ;
-						break ;
-					}
-					err = 0 ;
-					break ;
-		case WAIT:
-					err = 1 ;
-					break ;
-		case DEAD:
-					err = 2 ;
-					break ;
-		case DONE:
-					err = 0 ;
-					break ;
-		case PERM:
-					err = 3 ;
-					break ;
-		case UKNOW:
-		default:
-					VERBO3 strerr_warnw1x("invalid state, make a bug report");
-					err = 2 ;
-					break ;
-	}
-	
-	return err ;
-}
-
-static int handle_signal_pipe(svc_sig *svc)
-{
-	char *sv = svkeep.s + svc->scan ;
-	for (;;)
-	{
-		switch (selfpipe_read())
-		{
-			case -1 : strerr_warnwu1sys("selfpipe_read") ; return 0 ;
-			case 0 : return 1 ;
-			case SIGTERM: 		
-			case SIGINT: 		
-					// TODO, little ugly for me
-					VERBO2 strerr_warnw1x("received SIGINT, aborting service transition") ;
-					if (svc->sig <= SIGRR)
-						s6_svc_writectl(sv, S6_SUPERVISE_CTLDIR, "d", 1) ;
-					return 0 ;
-			default : strerr_warn1x("unexpected data in selfpipe") ; return 0 ;
-		}
-	}
-}
-static void announce(svc_sig *sv_signal)
-{
-
-	int r = sv_signal->state ;
-	char *sv = svkeep.s + sv_signal->scan ;
-	if (r == 3) { VERBO2 strerr_warnw3x(sv," report permanent failure to bring ",(sv_signal->sig > 1) ? "down" : "up") ; }
-	else if (r == 2) { VERBO2 strerr_warnwu3x("bring ", (sv_signal->sig > 3) ? "down " : "up ", sv) ; }
-	else if (r == 1) { VERBO2 strerr_warni4x(sv," is ",(sv_signal->sig > 3) ? "down" : "up"," but not notified by the daemon itself") ; }
-	else if (!r) { VERBO2 strerr_warni4x(sv,": ",(sv_signal->sig > 3) ? "stopped" : "started"," successfully") ; }
-}
-
-int svc_listen(genalloc *gasv, ftrigr_t *fifo,int spfd,svc_sig *svc)
-{
-	int r ;
-	iopause_fd x[2] = { { .fd = ftrigr_fd(fifo), .events = IOPAUSE_READ } , { .fd = spfd, .events = IOPAUSE_READ, .revents = 0 } } ;
-		
-	tain_t t ;
-	tain_now_g() ;
-	tain_add_g(&t,&svc->deadline) ;
-	
-	VERBO3 strerr_warnt2x("start iopause for: ",svkeep.s + svc->name) ;
-	
-	for(;;)
-	{
-		char receive ;
-		r = ftrigr_check(fifo,svc->ids, &receive) ;
-		if (r < 0) { VERBO3 strerr_warnwu1sys("ftrigr_check") ; return 0 ; } 
-		if (r)
-		{
-			svc->state = handle_case(receive, svc) ;
-			if (svc->state < 0) return 0 ;
-			if (!svc->state){ announce(svc) ; break ; }
-			else if (svc->state > 2){ announce(svc) ; break ; }
-		}
-		if (!(svc->ndeath))
-		{
-			VERBO2 strerr_warnw2x("number of try exceeded for: ",svkeep.s + svc->scan) ;
-			announce(svc) ;
-			break ;
-		}
-		
-		r = iopause_g(x, 2, &t) ;
-		if (r < 0){ VERBO3 strerr_warnwu1sys("iopause") ; return 0 ; }
-		/** timeout is not a error , the iopause process did right */
-		else if (!r) { VERBO3 strerr_warnt2x("timed out reached for: ",svkeep.s + svc->name) ; announce(svc) ; break ; } 
-		
-		if (x[1].revents & IOPAUSE_READ) return handle_signal_pipe(svc) ? 1 : 0 ;
-				
-		if (x[0].revents & IOPAUSE_READ)  
-		{	
-			if (ftrigr_update(fifo) < 0){ VERBO3 strerr_warnwu1sys("ftrigr_update") ; return 0 ; }
-			svc->ndeath--;
-		}
-	}
-
-	return 1 ;
-}
 
 int main(int argc, char const *const *argv,char const *const *envp)
 {
-	int r, e, isup ;
-	unsigned int death, tsv ;
-	uid_t owner ;
-	
-	
-	svc_sig sv_signal = SVC_SIG_ZERO ;
-	
-	char *treename = 0 ;
-	char *sig = 0 ;
-	
-	stralloc base = STRALLOC_ZERO ;
-	stralloc tree = STRALLOC_ZERO ;
-	stralloc live = STRALLOC_ZERO ;
-	stralloc scandir = STRALLOC_ZERO ;
-		
-	ftrigr_t fifo = FTRIGR_ZERO ;
-	s6_svstatus_t status = S6_SVSTATUS_ZERO ;
-	
-	tsv = death = 0 ;
-	
 	PROG = "66-svctl" ;
-	{
-		subgetopt_t l = SUBGETOPT_ZERO ;
-
-		for (;;)
-		{
-			int opt = getopt_args(argc,argv, "hv:l:t:T:n:udUDXrRK", &l) ;
-			if (opt == -1) break ;
-			if (opt == -2) strerr_dief1x(110,"options must be set first") ;
-			switch (opt)
-			{
-				case 'h' : 	info_help(); return 0 ;
-				case 'v' :  if (!uint0_scan(l.arg, &VERBOSITY)) exitusage() ; break ;
-				case 'l' : 	if (!stralloc_cats(&live,l.arg)) retstralloc(111,"main") ;
-							if (!stralloc_0(&live)) retstralloc(111,"main") ;
-							break ;
-				case 't' : 	if(!stralloc_cats(&tree,l.arg)) retstralloc(111,"main") ;
-							if(!stralloc_0(&tree)) retstralloc(111,"main") ;
-							break ;
-				case 'T' : 	if (!uint0_scan(l.arg, &tsv)) exitusage() ; break ;
-				case 'n' :	if (!uint0_scan(l.arg, &death)) exitusage() ; break ;
-				case 'u' :	if (SIGNAL > 0) exitusage() ; SIGNAL = SIGUP ; sig ="u" ; break ;
-				case 'U' :	if (SIGNAL > 0) exitusage() ; SIGNAL = SIGRUP ; sig = "u" ; break ;
-				case 'd' : 	if (SIGNAL > 0) ; SIGNAL = SIGDOWN ; sig = "d" ; break ;
-				case 'D' :	if (SIGNAL > 0) ; SIGNAL = SIGRDOWN ; sig = "d" ; break ;
-				case 'X' :	if (SIGNAL > 0) ; SIGNAL = SIGX ; sig = "dx" ; break ;
-				case 'K' :	if (SIGNAL > 0) ; SIGNAL = SIGRDOWN ; sig = "kd" ; break ;
-				case 'r' :	if (SIGNAL > 0) ; SIGNAL = SIGR ; sig = "r" ; break ;
-				case 'R' :	if (SIGNAL > 0) ; SIGNAL = SIGRR ; sig = "r" ; break ;
-				
-				default : exitusage() ; 
-			}
-		}
-		argc -= l.ind ; argv += l.ind ;
-	}
-	
-	if (argc < 1 || (SIGNAL < 0)) exitusage() ;
-	
-	owner = MYUID ;
-	
-	if (!set_ownersysdir(&base,owner)) strerr_diefu1sys(111, "set owner directory") ;
-	
-	r = tree_sethome(&tree,base.s) ;
-	if (r < 0) strerr_diefu1x(110,"find the current tree. You must use -t options") ;
-	if (!r) strerr_diefu2sys(111,"find tree: ", tree.s) ;
-	
-	treename = tree_setname(tree.s) ;
-	if (!treename) strerr_diefu1x(111,"set the tree name") ;
-		
-	if (!tree_get_permissions(tree.s))
-		strerr_dief2x(110,"You're not allowed to use the tree: ",tree.s) ;
-		
-	r = set_livedir(&live) ;
-	if (!r) retstralloc(111,"main") ;
-	if (r < 0 ) strerr_dief3x(111,"live: ",live.s," must be an absolute path") ;
-	
-	if (!stralloc_copy(&scandir,&live)) retstralloc(111,"main") ;
 	
-	r = set_livescan(&scandir,owner) ;
-	if (!r) retstralloc(111,"main") ;
-	if (r < 0 ) strerr_dief3x(111,"scandir: ",scandir.s," must be an absolute path") ;
-	
-	if ((scandir_ok(scandir.s)) !=1 ) strerr_dief3sys(111,"scandir: ", scandir.s," is not running") ;
-	
-
-	for(;*argv;argv++)
-	{
-		char const *svname = *argv ;
-		size_t namelen = strlen(*argv) ;
-		size_t srclen = tree.len - 1 ;
-		char src[srclen + SS_SVDIRS_LEN + SS_SVC_LEN + 1 + namelen + 16 + 1] ;
-		memcpy(src,tree.s,srclen) ;
-		memcpy(src + srclen,SS_SVDIRS, SS_SVDIRS_LEN) ;
-		memcpy(src + srclen + SS_SVDIRS_LEN, SS_SVC, SS_SVC_LEN) ;
-		src[srclen + SS_SVDIRS_LEN + SS_SVC_LEN] = '/' ;
-		memcpy(src + srclen + SS_SVDIRS_LEN + SS_SVC_LEN + 1,*argv,namelen) ;
-		src[srclen + SS_SVDIRS_LEN + SS_SVC_LEN + 1 + namelen ] = 0 ;
-		srclen = srclen + SS_SVDIRS_LEN + SS_SVC_LEN + 1 + namelen ;
-		
-		size_t svoklen = scandir.len - 1  ;
-		char svok[svoklen + 1 + namelen + 1] ;
-		memcpy(svok,scandir.s,svoklen) ;
-		svok[svoklen] = '/' ;
-		memcpy(svok + svoklen + 1 ,svname,namelen + 1) ;
-		svoklen = svoklen + 1 + namelen ;
-					
-		/** do not check the logger*/
-		if (!resolve_pointo(&saresolve,base.s,live.s,tree.s,treename,0,SS_RESOLVE_SRC))
-		{
-			VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
-			return 0 ;
-		}
-		if (resolve_read(&saresolve,saresolve.s,svname,"logger"))
-		{
-			if (str_diff(saresolve.s,svname))
-			{
-				r = s6_svc_ok(svok) ;
-				if (r < 0) strerr_diefu2sys(111,"check ", svok) ;
-				if (!r)	strerr_dief2x(110,svok," is not initialized") ;
-			}
-		}
-		
-		if (!s6_svstatus_read(svok,&status)) strerr_diefu2sys(111,"read status of: ",svok) ;
-		isup = status.pid && !status.flagfinishing ;
-			
-		if (isup && (SIGNAL <= SIGRUP))
-		{
-			VERBO2 strerr_warni2x(svok,": already up") ;
-			continue ;
-		}
-		else if (!isup && (SIGNAL >= SIGDOWN))
-		{
-			VERBO2 strerr_warni2x(svok,": already down") ;
-			continue ;
-		}
-		
-		sv_signal.scan = svkeep.len ;
-		if (!stralloc_catb(&svkeep, svok, svoklen + 1)) retstralloc(111,"main") ;
-		sv_signal.scanlen = svoklen ;
-				
-		sv_signal.name = svkeep.len ;
-		if (!stralloc_catb(&svkeep, svname, namelen + 1)) retstralloc(111,"main") ;
-		sv_signal.namelen = namelen ;
-		
-		sv_signal.src = svkeep.len ;
-		if (!stralloc_catb(&svkeep, src, srclen + 1)) retstralloc(111,"main") ;
-		sv_signal.srclen = srclen ;
-		
-		sv_signal.sigtosend = sig ;
-		sv_signal.sig = SIGNAL ;
-		
-		/** notification-fd */
-		memcpy(svok + svoklen,"/notification-fd",16) ;
-		svok[svoklen + 16] = 0 ;
-		e = errno ;
-		errno = 0 ;
-		if (access(svok, F_OK) < 0)
-		{
-			if (errno != ENOENT) strerr_diefu2sys(111, "access ", svok) ;
-			if (SIGNAL == SIGRUP)
-			{
-				sv_signal.sig = SIGUP ;
-				sv_signal.sigtosend = "uwu" ;
-				VERBO2 strerr_warnw2x(svok, " is not present - ignoring request for readiness notification") ;
-			}
-			if (SIGNAL == SIGRR)
-			{
-				sv_signal.sig = SIGR ;
-				sv_signal.sigtosend = "uwr" ;
-				VERBO2 strerr_warnw2x(svok, " is not present - ignoring request for readiness notification") ;
-			}
-			if (SIGNAL == SIGRDOWN)
-			{
-				sv_signal.sig = SIGDOWN ;
-				sv_signal.sigtosend = "dwd" ;
-				VERBO2 strerr_warnw2x(svok, " is not present - ignoring request for readiness notification") ;
-			}		
-		}
-		else
-		{
-			if (!read_uint(svok,&sv_signal.notify)) strerr_diefu2sys(111,"read: ",svok) ;
-		}
-		
-		/** max-death-tally */
-		if (!death)
-		{
-			memcpy(svok + svoklen,"/max-death-tally", 16) ;
-			svok[svoklen + 16] = 0 ;
-			errno = 0 ;
-			if (access(svok, F_OK) < 0)
-			{
-				if (errno != ENOENT) strerr_diefu2sys(111, "access ", svok) ;
-			}
-			if (errno == ENOENT)
-			{
-				sv_signal.ndeath = DEATHSV ;
-			}
-			else
-			{
-				if (!read_uint(svok,&sv_signal.ndeath)) strerr_diefu2sys(111,"read: ",svok) ;
-			}
-		}
-		else sv_signal.ndeath = death ;
-		
-		tain_t tcheck ;
-		tain_from_millisecs(&tcheck,tsv) ;
-		int check = tain_to_millisecs(&tcheck) ;
-		if (check > 0) tain_from_millisecs(&sv_signal.deadline, tsv) ;
-			
-		else
-		{
-			/** timeout-{up/down} */
-			{
-				char *tm = NULL ;
-				unsigned int t ;
-				if (SIGNAL <= SIGRR)
-				{
-					tm="/timeout-up" ;
-				}
-				else
-				{
-					tm="/timeout-down" ;
-				}
-				errno = 0 ;
-				memcpy(svok + svoklen,tm, strlen(tm) + 1) ;
-				if (access(svok, F_OK) < 0)
-				{
-					if (errno != ENOENT) strerr_diefu2sys(111, "access ", svok) ;
-				}
-				if (errno == ENOENT)
-				{
-					tain_from_millisecs(&sv_signal.deadline, SV_DEADLINE) ;
-				}
-				else
-				{
-					if (!read_uint(svok,&t)) strerr_diefu2sys(111,"read: ",svok) ;
-					tain_from_millisecs(&sv_signal.deadline, t) ;
-				}
-			}
-		}
-		
-		errno = e ;
-		
-		if (!genalloc_append(svc_sig,&gakeep,&sv_signal)) strerr_diefu1sys(111,"append genalloc") ;
-				
-	}
-	
-	stralloc_free(&base) ;
-	stralloc_free(&live) ;
-	stralloc_free(&tree) ;
-	stralloc_free(&scandir) ;
-	
-	/** nothing to do */
-	if (!genalloc_len(svc_sig,&gakeep))	goto finish ;
-	
-	int spfd = selfpipe_init() ;
-	if (spfd < 0) strerr_diefu1sys(111, "selfpipe_trap") ;
-	if (selfpipe_trap(SIGINT) < 0) strerr_diefu1sys(111, "selfpipe_trap") ;
-	if (selfpipe_trap(SIGTERM) < 0) strerr_diefu1sys(111, "selfpipe_trap") ;
-	if (sig_ignore(SIGPIPE) < 0) strerr_diefu1sys(111,"ignore SIGPIPE") ;
-		
-	if (!svc_init_pipe(&fifo,&gakeep,&svkeep)) strerr_diefu1x(111,"init pipe") ;
-
-	for (unsigned int i = 0 ; i < genalloc_len(svc_sig,&gakeep) ; i++)
-	{ 
-		svc_sig *sv = &genalloc_s(svc_sig,&gakeep)[i] ;
-		if (!svc_listen(&gakeep,&fifo,spfd,sv)) strerr_diefu1x(111,"listen pipe") ;
-	}
+	ssexec_t info = SSEXEC_ZERO ;
 	
-	finish:
-		ftrigr_end(&fifo) ;
-		selfpipe_finish() ;
-		stralloc_free(&svkeep) ;
-		genalloc_free(svc_sig,&gakeep) ;
-		free(treename) ;
+	info.prog = PROG ;
+	info.help = help_svctl ;
+	info.usage = usage_svctl ;
 	
-	return 0 ;		
+	return ssexec_main(argc,argv,envp,&ssexec_svctl,&info) ;
 }
 	
 
diff --git a/src/66/66-tree.c b/src/66/66-tree.c
index a4affc09d0c7e48b2012c50566bdc055d0526b2b..ceac290363b042280fd5c1aed2225c6548b24de1 100644
--- a/src/66/66-tree.c
+++ b/src/66/66-tree.c
@@ -35,7 +35,7 @@
 
 //#include <stdio.h>
 
-#define USAGE "66-tree [ -h ] [ -v verbosity ] [ -n | R ] [ -a ] [ -d ] [ -c ] [ -E | D ] [ -C ] tree"
+#define USAGE "66-tree [ -h ] [ -v verbosity ] [ -n | R ] [ -a ] [ -d ] [ -c ] [ -E | D ] [ -C ] tree" 
 
 unsigned int VERBOSITY = 1 ;
 
@@ -427,31 +427,31 @@ int main(int argc, char const *const *argv,char const *const *envp)
 			switch (opt)
 			{
 				case 'h' : info_help(); return 0 ;
-				case 'v' : if (!uint0_scan(l.arg, &VERBOSITY)) exitusage() ; break ;
+				case 'v' : if (!uint0_scan(l.arg, &VERBOSITY)) exitusage(USAGE) ; break ;
 				case 'n' : create = 1 ; break ;
-				case 'a' : if (!scan_uidlist_wdelim(l.arg,auids,',')) exitusage() ; 
+				case 'a' : if (!scan_uidlist_wdelim(l.arg,auids,',')) exitusage(USAGE) ; 
 						   auidn = auids[0] ;
 						   allow = 1 ;
 						   break ;
-				case 'd' : if (!scan_uidlist_wdelim(l.arg,duids,',')) exitusage() ; 
+				case 'd' : if (!scan_uidlist_wdelim(l.arg,duids,',')) exitusage(USAGE) ; 
 						   duidn = duids[0] ;
 						   deny = 1 ;
 						   break ;
 				case 'c' : current = 1 ; break ;
-				case 'E' : enable = 1 ; if (disable) exitusage() ; break ;
-				case 'D' : disable = 1 ; if (enable) exitusage () ; break ;
-				case 'R' : remove = 1 ; if (create) exitusage() ; break ;
+				case 'E' : enable = 1 ; if (disable) exitusage(USAGE) ; break ;
+				case 'D' : disable = 1 ; if (enable) exitusage (USAGE) ; break ;
+				case 'R' : remove = 1 ; if (create) exitusage(USAGE) ; break ;
 				case 'C' : if (!stralloc_cats(&clone,l.arg)) retstralloc(111,"main") ;
 						   if (!stralloc_0(&clone)) retstralloc(111,"main") ;
 						   snap = 1 ;
 						   break ;
-				default : exitusage() ; 
+				default : exitusage(USAGE) ; 
 			}
 		}
 		argc -= l.ind ; argv += l.ind ;
 	}
 	
-	if (argc != 1) exitusage() ;
+	if (argc != 1) exitusage(USAGE) ;
 	
 	tree = argv[0] ;
 	owner = MYUID ;
@@ -540,7 +540,7 @@ int main(int argc, char const *const *argv,char const *const *envp)
 		if (rm_rf(dstree.s) < 0) strerr_diefu2sys(111,"remove ", dstree.s) ;
 				
 		size_t treelen = strlen(tree) ;
-		size_t baselen = base.len - 1 ;
+		size_t baselen = base.len ;
 		char treetmp[baselen + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treelen  + 1] ;
 		memcpy(treetmp, base.s, baselen) ;
 		memcpy(treetmp + baselen, SS_SYSTEM, SS_SYSTEM_LEN) ;
diff --git a/src/66/deps-exe/66-disable b/src/66/deps-exe/66-disable
index aab9549bafa42e417a07b6e56e39cc289fb8325e..222df79835c0df91ab8f0cd037d27203a558679f 100644
--- a/src/66/deps-exe/66-disable
+++ b/src/66/deps-exe/66-disable
@@ -1,4 +1,6 @@
 ${LIB66}
 -loblibs
+-lexecline
+-ls6
 -lskarnet
 
diff --git a/src/66/deps-exe/66-enable b/src/66/deps-exe/66-enable
index 1bfa2831f3142c8eec696865445510b5e3eb4abf..222df79835c0df91ab8f0cd037d27203a558679f 100644
--- a/src/66/deps-exe/66-enable
+++ b/src/66/deps-exe/66-enable
@@ -1,5 +1,6 @@
 ${LIB66}
 -loblibs
--lskarnet
 -lexecline
 -ls6
+-lskarnet
+
diff --git a/src/66/deps-exe/66-scandir b/src/66/deps-exe/66-scandir
index a34c23f5c1879764a8b12b605bf766089bd272f6..4bd4547314b4b6853893b44851c036f40a245f7f 100644
--- a/src/66/deps-exe/66-scandir
+++ b/src/66/deps-exe/66-scandir
@@ -1,5 +1,6 @@
 ${LIB66}
 -loblibs
--lskarnet
 -ls6
+-lskarnet
+
 
diff --git a/src/extra-tools/66-envfile.c b/src/extra-tools/66-envfile.c
index dc980d2ed78528092cdc6ca5a94940e02733e4cc..1aede98a266083df89cc8e93aa6248520276deae 100644
--- a/src/extra-tools/66-envfile.c
+++ b/src/extra-tools/66-envfile.c
@@ -177,13 +177,13 @@ int main (int argc, char const *const *argv, char const *const *envp)
 				case 'h' : 	info_help(); return 0 ;
 				case 'f' :  file = l.arg ; one = 1 ; break ;
 				case 'l' : 	insist = 0 ; break ;
-				default : exitusage() ; 
+				default : exitusage(USAGE) ; 
 			}
 		}
 		argc -= l.ind ; argv += l.ind ;
 	}
 	
-	if (argc < 2) exitusage() ;
+	if (argc < 2) exitusage(USAGE) ;
 	
 	path = *argv ;
 	
diff --git a/src/extra-tools/execl-cmdline.c b/src/extra-tools/execl-cmdline.c
index 4f8fc2fc49794927bacf51798dfd9161d3def6ea..634645a2d42fce21be393744e842e2c92970a894 100644
--- a/src/extra-tools/execl-cmdline.c
+++ b/src/extra-tools/execl-cmdline.c
@@ -48,7 +48,7 @@ int main(int argc, char const **argv, char const *const *envp)
 		  switch (opt)
 		  {
 			case 's' : split = 1 ; break ;
-			default : exitusage() ;
+			default : exitusage(USAGE) ;
 		  }
 		}
 		argc -= l.ind ; argv += l.ind ;
diff --git a/src/include/66/backup.h b/src/include/66/backup.h
index b8e34d345eb1324f158d5b329ee4ebf24520500e..acfe93bda9ba03f15fae55b6e4eb974ff4178083 100644
--- a/src/include/66/backup.h
+++ b/src/include/66/backup.h
@@ -17,10 +17,12 @@
 
 #include <skalibs/stralloc.h>
 
-extern int backup_make_new(char const *base, char const *tree, char const *treename,unsigned int type) ;
+#include <66/ssexec.h>
 
-extern int backup_cmd_switcher(unsigned int verbosity,char const *cmd, char const *tree) ;
-extern int backup_switcher(int argc, char const *const *argv) ;
+extern int backup_make_new(ssexec_t *info,unsigned int type) ;
 
-extern int backup_realpath_sym(stralloc *sa,char const *sym,unsigned int type) ;
+extern int backup_cmd_switcher(unsigned int verbosity,char const *cmd, ssexec_t *info) ;
+extern int backup_switcher(int argc, char const *const *argv,ssexec_t *info) ;
+
+extern int backup_realpath_sym(stralloc *sa,ssexec_t *info,unsigned int type) ;
 #endif
diff --git a/src/include/66/db.h b/src/include/66/db.h
index 9a911e1eb388d2d111b663a6c1a46ed539d42a73..802b784b78e97fd79db88cce1dc5aa40014c69db 100644
--- a/src/include/66/db.h
+++ b/src/include/66/db.h
@@ -18,6 +18,7 @@
 #include <skalibs/stralloc.h>
 #include <skalibs/genalloc.h>
 #include <66/graph.h>
+#include <66/ssexec.h>
 
 extern int db_cmd_master(unsigned int verbosity,char const *cmd) ;
 extern int db_update_master(int argc, char const *const *argv) ;
@@ -31,10 +32,10 @@ extern int db_find_compiled_state(char const *livetree, char const *treename) ;
 
 extern int db_get_permissions(stralloc *uid, char const *tree) ;
 
-extern int db_update(char const *newdb, char const *tree, char const *live,char const *const *envp) ;
+extern int db_update(char const *newdb, ssexec_t *info,char const *const *envp) ;
 
 extern int db_ok(char const *livetree, char const *treename) ;
 
-extern int db_switch_to(char const *base, char const *livetree, char const *tree, char const *treename, char const *const *envp,unsigned int where) ;
+extern int db_switch_to(ssexec_t *info, char const *const *envp,unsigned int where) ;
 
 #endif
diff --git a/src/include/66/ssexec.h b/src/include/66/ssexec.h
new file mode 100644
index 0000000000000000000000000000000000000000..c7fa4777aa453db38322adc0c3b1ae24b8036d0c
--- /dev/null
+++ b/src/include/66/ssexec.h
@@ -0,0 +1,83 @@
+/* 
+ * ssexec.h
+ * 
+ * Copyright (c) 2018 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./
+ */
+ 
+#ifndef SSEXEC_H
+#define SSEXEC_H
+
+#include <skalibs/stralloc.h>
+#include <skalibs/types.h>
+
+typedef struct ssexec_s ssexec_t , *ssexec_t_ref ;
+struct ssexec_s
+{
+	stralloc base ;
+	stralloc live ;
+	stralloc tree ;
+	stralloc livetree ;
+	stralloc scandir ;
+	char *treename ;
+	int treeallow ; //1 yes , 0 no
+	uid_t owner ;
+	unsigned int timeout ;
+	char const *prog ;
+	char const *help ;
+	char const *usage ;
+} ;
+
+#define SSEXEC_ZERO { 	.base = STRALLOC_ZERO , \
+						.live = STRALLOC_ZERO , \
+						.tree = STRALLOC_ZERO , \
+						.live = STRALLOC_ZERO , \
+						.scandir = STRALLOC_ZERO , \
+						.treename = 0 , \
+						.treeallow = 0 , \
+						.owner = 0 , \
+						.timeout = 0 , \
+						.prog = 0 , \
+						.help = 0 , \
+						.usage = 0 }
+
+typedef int ssexec_func_t(int, char const *const *argv, char const *const *envp, ssexec_t *info) ;
+typedef ssexec_func_t *ssexec_func_t_ref ;
+
+extern void ssexec_free(ssexec_t *info) ;
+extern ssexec_t const ssexec_zero ;
+extern int set_ssinfo(ssexec_t *info) ;
+
+extern ssexec_func_t ssexec_init ;
+extern ssexec_func_t ssexec_enable ;
+extern ssexec_func_t ssexec_disable ;
+extern ssexec_func_t ssexec_start ;
+extern ssexec_func_t ssexec_stop ;
+extern ssexec_func_t ssexec_svctl ;
+extern ssexec_func_t ssexec_dbctl ;
+
+extern char const *usage_enable ;
+extern char const *help_enable ;
+extern char const *usage_disable ;
+extern char const *help_disable ;
+extern char const *usage_dbctl ;
+extern char const *help_dbctl ;
+extern char const *usage_svctl ;
+extern char const *help_svctl ;
+extern char const *usage_start ;
+extern char const *help_start ;
+extern char const *usage_stop ;
+extern char const *help_stop ;
+extern char const *usage_init ;
+extern char const *help_init ;
+
+extern int ssexec_main(int argc, char const *const *argv, char const *const *envp,ssexec_func_t *func,ssexec_t *info) ;
+
+#endif
diff --git a/src/include/66/svc.h b/src/include/66/svc.h
index 1f72dd8191fcf286990c46284b6074f21d16833a..6b0ee94d1ed91b5dc95757ef7e69182cd5dc3621 100644
--- a/src/include/66/svc.h
+++ b/src/include/66/svc.h
@@ -20,6 +20,8 @@
 #include <skalibs/genalloc.h>
 #include <s6/ftrigr.h>
 
+#include <66/ssexec.h>
+
 typedef struct svstat_s svstat_t, *svstat_t_ref ;
 struct svstat_s
 {
@@ -104,7 +106,7 @@ enum sigactions_e
 } ;
 
 
-extern int svc_switch_to(char const *base, char const *tree,char const *treename,unsigned int where) ;
+extern int svc_switch_to(ssexec_t *info,unsigned int where) ;
 extern int svc_init(char const *scandir,char const *src, genalloc *ga) ;
 extern int svc_init_pipe(ftrigr_t *fifo,genalloc *gasv,stralloc *sasv) ;
 
diff --git a/src/include/66/tree.h b/src/include/66/tree.h
index c80e2ceec0fe82d9350f47355ceaec8949a22e57..64b2f6bd6067f1f2acc385aeb494d6f4b5418d0a 100644
--- a/src/include/66/tree.h
+++ b/src/include/66/tree.h
@@ -18,13 +18,14 @@
 #include <sys/types.h>
 
 #include <skalibs/stralloc.h>
+#include <66/ssexec.h>
 
 extern int tree_cmd_state(unsigned int verbosity,char const *cmd,char const *tree) ;
 extern int tree_state(int argc, char const *const *argv) ;
 
 extern int tree_copy(stralloc *dir, char const *tree,char const *treename) ;
 
-extern int tree_copy_tmp(char const *workdir, char const *base, char const *live, char const *tree,char const *treename) ;
+extern int tree_copy_tmp(char const *workdir, ssexec_t *info) ;
 
 /** Set the tree to use as current for 66 tools
  * This is avoid to use the -t options for all 66 tools
@@ -32,12 +33,12 @@ extern int tree_copy_tmp(char const *workdir, char const *base, char const *live
  * with the path.
  * @Return 1 on success
  * @Return 0 on fail */
-extern int tree_find_current(stralloc *tree, char const *base) ;
+extern int tree_find_current(stralloc *tree, char const *base,uid_t owner) ;
 
 
-extern int tree_get_permissions(char const *tree) ;
+extern int tree_get_permissions(char const *tree, uid_t owner) ;
 
-extern int tree_sethome(stralloc *tree, char const *base) ;
+extern int tree_sethome(stralloc *tree, char const *base,uid_t owner) ;
 
 extern char *tree_setname(char const *tree) ;
 
diff --git a/src/include/66/utils.h b/src/include/66/utils.h
index ed384f3318b5c8fc7a773511736f4cd755e0fb02..09b5bce7e8981ce7a889b975d6cd5303ba4f47c4 100644
--- a/src/include/66/utils.h
+++ b/src/include/66/utils.h
@@ -21,6 +21,8 @@
 #include <skalibs/stralloc.h>
 #include <skalibs/genalloc.h>
 
+#include <66/ssexec.h>
+
 extern unsigned int VERBOSITY ;
 
 #define VERBO1 if(VERBOSITY >= 1) 
@@ -33,8 +35,6 @@ extern unsigned int VERBOSITY ;
 #define YOURGID(passto,owner) yourgid(passto,owner)
 
 
-
-
 extern int dir_cmpndel(char const *src, char const *dst,char const *exclude) ;
 
 /** get_uidgid.c */
@@ -67,7 +67,7 @@ extern int resolve_remove_service(char const *dst, char const *svname) ;
 
 extern int resolve_symlive(char const *live, char const *tree, char const *treename) ;
 
-extern int resolve_pointo(stralloc *sa,char const *base, char const *live,char const *tree,char const *treename,unsigned int type, unsigned int what) ;
+extern int resolve_pointo(stralloc *sa,ssexec_t *info,unsigned int type, unsigned int what) ;
 
 extern int resolve_src(genalloc *ga, stralloc *sasrc, char const *name, char const *src,unsigned int *found) ;
 
diff --git a/src/lib66/backup_cmd_switcher.c b/src/lib66/backup_cmd_switcher.c
index 19f07e2752c90ea244c69211dd967105194f6900..8fc629e4a363d5c0696202e6de8412d59d352fd2 100644
--- a/src/lib66/backup_cmd_switcher.c
+++ b/src/lib66/backup_cmd_switcher.c
@@ -30,24 +30,21 @@
 #include <66/utils.h>
 #include <66/constants.h>
 #include <66/enum.h>
+#include <66/ssexec.h>
 
 //#include <stdio.h>
 //USAGE "backup_switcher [ -v verbosity ] [ -t type ] [ -b backup ] [ -s switch ] tree"
 // for -b: return 0 if point to original source, return 1 if point to backup
 // for -s: -s0 -> origin, -s1 -> backup ;
-int backup_switcher(int argc, char const *const *argv)
+int backup_switcher(int argc, char const *const *argv,ssexec_t *info)
 {
 	unsigned int r, change, back, verbosity, type ;
 	uint32_t what = -1 ;
-	
+		
 	struct stat st ;
 	
 	char const *tree = NULL ;
-	
-	uid_t owner = MYUID ;
-	
-	stralloc base = STRALLOC_ZERO ;
-	
+			
 	verbosity = 1 ;
 	
 	change =  back = type = 0 ;
@@ -83,13 +80,9 @@ int backup_switcher(int argc, char const *const *argv)
 	tree = *argv ;
 	size_t treelen = strlen(tree) ;
 	
-	if (!set_ownersysdir(&base,owner))
-	{
-		VERBO3 strerr_warnwu1sys("set owner directory") ;
-		return -1 ;
-	}
+	
 	/** $HOME/66/system/tree/servicedirs */
-	base.len-- ;
+	//base.len-- ;
 	size_t psymlen ;
 	char *psym = NULL ;
 	if (type == CLASSIC)
@@ -102,15 +95,15 @@ int backup_switcher(int argc, char const *const *argv)
 		psym = SS_SYM_DB ;
 		psymlen = SS_SYM_DB_LEN ;
 	}
-	char sym[base.len + SS_SYSTEM_LEN + 1 + treelen + SS_SVDIRS_LEN + 1 + psymlen + 1] ;
-	memcpy(sym,base.s,base.len) ;
-	memcpy(sym + base.len, SS_SYSTEM,SS_SYSTEM_LEN) ;
-	sym[base.len + SS_SYSTEM_LEN] = '/' ;
-	memcpy(sym + base.len + SS_SYSTEM_LEN + 1, tree, treelen) ;
-	memcpy(sym + base.len + SS_SYSTEM_LEN + 1 + treelen, SS_SVDIRS, SS_SVDIRS_LEN) ;
-	sym[base.len + SS_SYSTEM_LEN + 1 + treelen + SS_SVDIRS_LEN] = '/' ;
-	memcpy(sym + base.len + SS_SYSTEM_LEN + 1 + treelen + SS_SVDIRS_LEN + 1 ,psym,psymlen) ;
-	sym[base.len + SS_SYSTEM_LEN + 1 + treelen + SS_SVDIRS_LEN + 1 + psymlen] = 0 ;
+	char sym[info->base.len + SS_SYSTEM_LEN + 1 + treelen + SS_SVDIRS_LEN + 1 + psymlen + 1] ;
+	memcpy(sym,info->base.s,info->base.len) ;
+	memcpy(sym + info->base.len, SS_SYSTEM,SS_SYSTEM_LEN) ;
+	sym[info->base.len + SS_SYSTEM_LEN] = '/' ;
+	memcpy(sym + info->base.len + SS_SYSTEM_LEN + 1, tree, treelen) ;
+	memcpy(sym + info->base.len + SS_SYSTEM_LEN + 1 + treelen, SS_SVDIRS, SS_SVDIRS_LEN) ;
+	sym[info->base.len + SS_SYSTEM_LEN + 1 + treelen + SS_SVDIRS_LEN] = '/' ;
+	memcpy(sym + info->base.len + SS_SYSTEM_LEN + 1 + treelen + SS_SVDIRS_LEN + 1 ,psym,psymlen) ;
+	sym[info->base.len + SS_SYSTEM_LEN + 1 + treelen + SS_SVDIRS_LEN + 1 + psymlen] = 0 ;
 	
 	if (back)
 	{
@@ -132,7 +125,6 @@ int backup_switcher(int argc, char const *const *argv)
 		b = memmem(symreal.s,symreal.len,SS_BACKUP,SS_BACKUP_LEN) ;
 		
 		stralloc_free(&symreal) ;
-		stralloc_free(&base) ;
 		if (!b) return SS_SWSRC ;
 		
 		return SS_SWBACK ;
@@ -162,24 +154,24 @@ int backup_switcher(int argc, char const *const *argv)
 			pbacklen = SS_DB_LEN ;
 		}
 	
-		char dstsrc[base.len + SS_SYSTEM_LEN + 1 + treelen + SS_SVDIRS_LEN + psrclen + 1] ;
-		char dstback[base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treelen + pbacklen + 1] ;
+		char dstsrc[info->base.len + SS_SYSTEM_LEN + 1 + treelen + SS_SVDIRS_LEN + psrclen + 1] ;
+		char dstback[info->base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treelen + pbacklen + 1] ;
 			
-		memcpy(dstsrc, base.s, base.len) ;
-		memcpy(dstsrc + base.len, SS_SYSTEM, SS_SYSTEM_LEN) ;
-		dstsrc[base.len + SS_SYSTEM_LEN] = '/' ;
-		memcpy(dstsrc + base.len + SS_SYSTEM_LEN + 1, tree, treelen) ;
-		memcpy(dstsrc + base.len + SS_SYSTEM_LEN + 1 + treelen, SS_SVDIRS,SS_SVDIRS_LEN) ;
-		memcpy(dstsrc + base.len + SS_SYSTEM_LEN + 1 + treelen + SS_SVDIRS_LEN,psrc,psrclen) ;
-		dstsrc[base.len + SS_SYSTEM_LEN + 1 + treelen + SS_SVDIRS_LEN + psrclen] = 0 ;
+		memcpy(dstsrc, info->base.s, info->base.len) ;
+		memcpy(dstsrc + info->base.len, SS_SYSTEM, SS_SYSTEM_LEN) ;
+		dstsrc[info->base.len + SS_SYSTEM_LEN] = '/' ;
+		memcpy(dstsrc + info->base.len + SS_SYSTEM_LEN + 1, tree, treelen) ;
+		memcpy(dstsrc + info->base.len + SS_SYSTEM_LEN + 1 + treelen, SS_SVDIRS,SS_SVDIRS_LEN) ;
+		memcpy(dstsrc + info->base.len + SS_SYSTEM_LEN + 1 + treelen + SS_SVDIRS_LEN,psrc,psrclen) ;
+		dstsrc[info->base.len + SS_SYSTEM_LEN + 1 + treelen + SS_SVDIRS_LEN + psrclen] = 0 ;
 					
-		memcpy(dstback, base.s, base.len) ;
-		memcpy(dstback + base.len, SS_SYSTEM, SS_SYSTEM_LEN) ;
-		memcpy(dstback + base.len + SS_SYSTEM_LEN, SS_BACKUP, strlen(SS_BACKUP)) ;
-		dstback[base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN] = '/' ;
-		memcpy(dstback + base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1, tree, treelen) ;
-		memcpy(dstback + base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treelen, pback,pbacklen) ;
-		dstback[base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treelen + pbacklen] = 0 ;
+		memcpy(dstback, info->base.s, info->base.len) ;
+		memcpy(dstback + info->base.len, SS_SYSTEM, SS_SYSTEM_LEN) ;
+		memcpy(dstback + info->base.len + SS_SYSTEM_LEN, SS_BACKUP, strlen(SS_BACKUP)) ;
+		dstback[info->base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN] = '/' ;
+		memcpy(dstback + info->base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1, tree, treelen) ;
+		memcpy(dstback + info->base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treelen, pback,pbacklen) ;
+		dstback[info->base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treelen + pbacklen] = 0 ;
 				
 		
 		
@@ -211,12 +203,10 @@ int backup_switcher(int argc, char const *const *argv)
 		}	
 	}
 	
-	stralloc_free(&base) ;
-	
 	return 1 ;		
 }
 	
-int backup_cmd_switcher(unsigned int verbosity,char const *cmd, char const *tree)
+int backup_cmd_switcher(unsigned int verbosity,char const *cmd,ssexec_t *info)
 {	
 	int r ;
 	
@@ -240,10 +230,10 @@ int backup_cmd_switcher(unsigned int verbosity,char const *cmd, char const *tree
 	for (unsigned int i = 0; i < genalloc_len(stralist,&opts); i++)
 		newargv[m++] = gaistr(&opts,i) ;
 		
-	newargv[m++] = tree ;
+	newargv[m++] = info->treename ;
 	newargv[m++] = 0 ;
 	
-	r = backup_switcher(newopts,newargv) ;
+	r = backup_switcher(newopts,newargv,info) ;
 
 	genalloc_deepfree(stralist,&opts,stra_free) ;
 	
diff --git a/src/lib66/backup_make_new.c b/src/lib66/backup_make_new.c
index e9d523c910fed19ec8ee29abf7bfd7539d36b5a8..02d1a183b22b5ab5a9055a9b223b5cbb354090ce 100644
--- a/src/lib66/backup_make_new.c
+++ b/src/lib66/backup_make_new.c
@@ -29,12 +29,11 @@
 #include <66/enum.h>
 
 // force: 0->check, 1->remove and create
-int backup_make_new(char const *base, char const *tree, char const *treename, unsigned int type)
+int backup_make_new(ssexec_t *info, unsigned int type)
 {
 	int r ;
 	
-	size_t baselen = strlen(base) ;
-	size_t treenamelen = strlen(treename) ;
+	size_t treenamelen = strlen(info->treename) ;
 	size_t newsrc ;
 	size_t newback ;
 	size_t typelen ;
@@ -51,25 +50,25 @@ int backup_make_new(char const *base, char const *tree, char const *treename, un
 		typelen = SS_DB_LEN ;
 	}
 	
-	char src[baselen + SS_SYSTEM_LEN + 1 + treenamelen + SS_SVDIRS_LEN + SS_RESOLVE_LEN + 1] ;
-	memcpy(src,base,baselen) ;
-	memcpy(src + baselen, SS_SYSTEM, SS_SYSTEM_LEN) ;
-	src[baselen + SS_SYSTEM_LEN] = '/' ;
-	memcpy(src + baselen + SS_SYSTEM_LEN + 1,treename,treenamelen) ;
-	memcpy(src+ baselen + SS_SYSTEM_LEN + 1 + treenamelen,SS_SVDIRS, SS_SVDIRS_LEN) ;
-	newsrc = baselen + SS_SYSTEM_LEN + 1 + treenamelen + SS_SVDIRS_LEN ;
-	memcpy(src+ baselen + SS_SYSTEM_LEN + 1 + treenamelen + SS_SVDIRS_LEN, ptype,typelen) ;
-	src[baselen + SS_SYSTEM_LEN + 1 + treenamelen + SS_SVDIRS_LEN +  typelen] = 0 ;
+	char src[info->base.len + SS_SYSTEM_LEN + 1 + treenamelen + SS_SVDIRS_LEN + SS_RESOLVE_LEN + 1] ;
+	memcpy(src,info->base.s,info->base.len) ;
+	memcpy(src + info->base.len, SS_SYSTEM, SS_SYSTEM_LEN) ;
+	src[info->base.len + SS_SYSTEM_LEN] = '/' ;
+	memcpy(src + info->base.len + SS_SYSTEM_LEN + 1,info->treename,treenamelen) ;
+	memcpy(src+ info->base.len + SS_SYSTEM_LEN + 1 + treenamelen,SS_SVDIRS, SS_SVDIRS_LEN) ;
+	newsrc = info->base.len + SS_SYSTEM_LEN + 1 + treenamelen + SS_SVDIRS_LEN ;
+	memcpy(src+ info->base.len + SS_SYSTEM_LEN + 1 + treenamelen + SS_SVDIRS_LEN, ptype,typelen) ;
+	src[info->base.len + SS_SYSTEM_LEN + 1 + treenamelen + SS_SVDIRS_LEN +  typelen] = 0 ;
 	
-	char back[baselen + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treenamelen + SS_RESOLVE_LEN + 1] ;
-	memcpy(back, base, baselen) ;
-	memcpy(back + baselen, SS_SYSTEM, SS_SYSTEM_LEN) ;
-	memcpy(back + baselen + SS_SYSTEM_LEN, SS_BACKUP, SS_BACKUP_LEN) ;
-	back[baselen + SS_SYSTEM_LEN + SS_BACKUP_LEN] = '/' ;
-	memcpy(back + baselen + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1, treename, treenamelen) ;
-	newback = baselen + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treenamelen ;
-	memcpy(back + baselen + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treenamelen, ptype,typelen) ;
-	back[baselen + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treenamelen + typelen] = 0 ;
+	char back[info->base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treenamelen + SS_RESOLVE_LEN + 1] ;
+	memcpy(back, info->base.s, info->base.len) ;
+	memcpy(back + info->base.len, SS_SYSTEM, SS_SYSTEM_LEN) ;
+	memcpy(back + info->base.len + SS_SYSTEM_LEN, SS_BACKUP, SS_BACKUP_LEN) ;
+	back[info->base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN] = '/' ;
+	memcpy(back + info->base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1, info->treename, treenamelen) ;
+	newback = info->base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treenamelen ;
+	memcpy(back + info->base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treenamelen, ptype,typelen) ;
+	back[info->base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treenamelen + typelen] = 0 ;
 	
 	r = scan_mode(back,S_IFDIR) ;
 	if (r || (r < 0))
diff --git a/src/lib66/backup_realpath_sym.c b/src/lib66/backup_realpath_sym.c
index a11b62b05e3d7be888483d7755ac829e8f44b237..1606f6caa750b2b4cee274177f2de23114251e07 100644
--- a/src/lib66/backup_realpath_sym.c
+++ b/src/lib66/backup_realpath_sym.c
@@ -27,10 +27,9 @@
 #include <66/constants.h>
 #include <66/enum.h>
 
-int backup_realpath_sym(stralloc *sa, char const *tree,unsigned int type)
+int backup_realpath_sym(stralloc *sa, ssexec_t *info,unsigned int type)
 {
 	ssize_t r ;
-	size_t treelen = strlen(tree) ;
 	size_t typelen ;
 	char *ptype = NULL ;
 	
@@ -45,13 +44,13 @@ int backup_realpath_sym(stralloc *sa, char const *tree,unsigned int type)
 		typelen = SS_SYM_DB_LEN;
 	}
 	
-	char sym[treelen + SS_SVDIRS_LEN + 1 + typelen + 1] ;
-	memcpy(sym,tree,treelen) ;
-	memcpy(sym + treelen, SS_SVDIRS, SS_SVDIRS_LEN) ;
-	sym[treelen + SS_SVDIRS_LEN] = '/' ;
-	memcpy(sym + treelen + SS_SVDIRS_LEN + 1, ptype,typelen) ;
-	sym[treelen + SS_SVDIRS_LEN + 1 + typelen] = '/' ;
-	sym[treelen + SS_SVDIRS_LEN + 1 + typelen + 1] = 0 ;
+	char sym[info->tree.len + SS_SVDIRS_LEN + 1 + typelen + 1] ;
+	memcpy(sym,info->tree.s,info->tree.len) ;
+	memcpy(sym + info->tree.len, SS_SVDIRS, SS_SVDIRS_LEN) ;
+	sym[info->tree.len + SS_SVDIRS_LEN] = '/' ;
+	memcpy(sym + info->tree.len + SS_SVDIRS_LEN + 1, ptype,typelen) ;
+	sym[info->tree.len + SS_SVDIRS_LEN + 1 + typelen] = '/' ;
+	sym[info->tree.len + SS_SVDIRS_LEN + 1 + typelen + 1] = 0 ;
 	
 	r = scan_mode(sym,S_IFDIR) ;
 	if(r <= 0) return 0 ; 
diff --git a/src/lib66/db_compile.c b/src/lib66/db_compile.c
index 8cd3ecb808f1b5101133b814c0ebb560bdbbcd0a..f722d704ae2d16566862eccda1e8e80da68037d1 100644
--- a/src/lib66/db_compile.c
+++ b/src/lib66/db_compile.c
@@ -29,9 +29,10 @@
 
 #include <66/utils.h>
 #include <66/constants.h>
+#include <66/ssexec.h>
 
 #include <stdio.h>
-int db_compile(char const *workdir, char const *tree, char const *treename,char const *const *envp)
+int db_compile(char const *workdir, char const *tree, char const *treename, char const *const *envp)
 {
 	int wstat, r ;
 	pid_t pid ;
diff --git a/src/lib66/db_switch_to.c b/src/lib66/db_switch_to.c
index b256e8d58bdd7bf5214c89379a81ccaf20619879..1d654ab0de827fa7ac477a45e1f3bc44207f4d3d 100644
--- a/src/lib66/db_switch_to.c
+++ b/src/lib66/db_switch_to.c
@@ -23,10 +23,11 @@
 #include <66/backup.h>
 #include <66/utils.h>
 #include <66/enum.h>
+#include <66/ssexec.h>
 
 /** 1-> backup
  * 0-> ori */
-int db_switch_to(char const *base, char const *livetree, char const *tree, char const *treename, char const *const *envp,unsigned int where)
+int db_switch_to(ssexec_t *info, char const *const *envp,unsigned int where)
 {
 	int r ;
 	
@@ -43,57 +44,57 @@ int db_switch_to(char const *base, char const *livetree, char const *tree, char
 	memcpy(cmd + cmdlen," -b",3) ;
 	cmd[cmdlen + 3] = 0 ;
 	
-	r = backup_cmd_switcher(VERBOSITY,cmd,treename) ;
+	r = backup_cmd_switcher(VERBOSITY,cmd,info) ;
 	if (r < 0)
 	{
-		VERBO3 strerr_warnwu2sys("find origin of db service for: ",treename) ;
+		VERBO3 strerr_warnwu2sys("find origin of db service for: ",info->treename) ;
 		goto err ;
 	}
 	// point to origin
 	if (!r && where)
 	{
-		VERBO3 strerr_warnt2x("make a backup of db service for: ",treename) ;
-		if (!backup_make_new(base,tree,treename,LONGRUN))
+		VERBO3 strerr_warnt2x("make a backup of db service for: ",info->treename) ;
+		if (!backup_make_new(info,LONGRUN))
 		{
-			VERBO3 strerr_warnwu2sys("make a backup of db service for: ",treename) ;
+			VERBO3 strerr_warnwu2sys("make a backup of db service for: ",info->treename) ;
 			goto err ;
 		}
-		VERBO3 strerr_warnt3x("switch db service for tree: ",treename," to backup") ;
+		VERBO3 strerr_warnt3x("switch db service for tree: ",info->treename," to backup") ;
 		memcpy(cmd + cmdlen," -s1",4) ;
 		cmd[cmdlen + 4] = 0 ;
-		r = backup_cmd_switcher(VERBOSITY,cmd,treename) ;
+		r = backup_cmd_switcher(VERBOSITY,cmd,info) ;
 		if (r < 0)
 		{
-			VERBO3 strerr_warnwu3sys("switch db service for: ",treename," to backup") ;
+			VERBO3 strerr_warnwu3sys("switch db service for: ",info->treename," to backup") ;
 			goto err ;
 		}
-		if (db_ok(livetree,treename))
+		if (db_ok(info->livetree.s, info->treename))
 		{
-			if (!backup_realpath_sym(&db,tree,LONGRUN))
+			if (!backup_realpath_sym(&db,info,LONGRUN))
 			{
 				VERBO3 strerr_warnwu2sys("find path of db: ",db.s) ;
 			}
-			VERBO3 strerr_warnt4x("update ",livetree," to ",db.s) ;
-			if (!db_update(db.s, treename,livetree,envp))
+			VERBO3 strerr_warnt4x("update ",info->livetree.s," to ",db.s) ;
+			if (!db_update(db.s, info,envp))
 			{	
-				VERBO3 strerr_warnt2x("rollback db service: ", treename) ;
+				VERBO3 strerr_warnt2x("rollback db service: ", info->treename) ;
 				memcpy(cmd + cmdlen," -s0",4) ;
 				cmd[cmdlen + 4] = 0 ;
-				r = backup_cmd_switcher(VERBOSITY,cmd,treename) ;
+				r = backup_cmd_switcher(VERBOSITY,cmd,info) ;
 				if (r < 0)
 				{
-					VERBO3 strerr_warnwu3sys("switch db service for: ",treename," to source") ;
+					VERBO3 strerr_warnwu3sys("switch db service for: ",info->treename," to source") ;
 					goto err ;
 				}
 				db = stralloc_zero ;
-				if (!backup_realpath_sym(&db,tree,LONGRUN))
+				if (!backup_realpath_sym(&db,info,LONGRUN))
 				{
-					VERBO3 strerr_warnwu2sys("find path of db service for: ",treename) ;
+					VERBO3 strerr_warnwu2sys("find path of db service for: ",info->treename) ;
 					goto err ;
 				}
-				if (!db_update(db.s, treename,livetree,envp))
+				if (!db_update(db.s,info,envp))
 				{
-					VERBO3 strerr_warnwu3sys("switch: ",treename," to source") ;
+					VERBO3 strerr_warnwu3sys("switch: ",info->treename," to source") ;
 					VERBO3 strerr_warnwu1sys("unable to rollback the db state, please make a bug report") ;
 					goto err ;
 				}
@@ -102,53 +103,53 @@ int db_switch_to(char const *base, char const *livetree, char const *tree, char
 	}
 	else if (r > 0 && !where)
 	{
-		VERBO3 strerr_warnt3x("switch db service for tree: ",treename," to source") ;
+		VERBO3 strerr_warnt3x("switch db service for tree: ",info->treename," to source") ;
 		memcpy(cmd + cmdlen," -s0",4) ;
 		cmd[cmdlen + 4] = 0 ;
-		r = backup_cmd_switcher(VERBOSITY,cmd,treename) ;
+		r = backup_cmd_switcher(VERBOSITY,cmd,info) ;
 		if (r < 0)
 		{
-			VERBO3 strerr_warnwu3sys("switch db service for: ",treename," to source") ;
+			VERBO3 strerr_warnwu3sys("switch db service for: ",info->treename," to source") ;
 			goto err ;
 		}
 		
-		if (db_ok(livetree,treename))
+		if (db_ok(info->livetree.s,info->treename))
 		{
-			if (!backup_realpath_sym(&db,tree,LONGRUN))
+			if (!backup_realpath_sym(&db,info,LONGRUN))
 			{
 				VERBO3 strerr_warnwu2sys("find path of db: ",db.s) ;
 				goto err ;
 			}
-			VERBO3 strerr_warnt4x("update ",livetree," to ",db.s) ;
-			if (!db_update(db.s, treename,livetree,envp))
+			VERBO3 strerr_warnt4x("update ",info->livetree.s," to ",db.s) ;
+			if (!db_update(db.s, info,envp))
 			{	
-				VERBO3 strerr_warnt2x("rollback db: ", treename) ;
+				VERBO3 strerr_warnt2x("rollback db: ", info->treename) ;
 				memcpy(cmd + cmdlen," -s1",4) ;
 				cmd[cmdlen + 4] = 0 ;
-				r = backup_cmd_switcher(VERBOSITY,cmd,treename) ;
+				r = backup_cmd_switcher(VERBOSITY,cmd,info) ;
 				if (r < 0)
 				{
-					VERBO3 strerr_warnwu3sys("switch db service for: ",treename," to backup") ;
+					VERBO3 strerr_warnwu3sys("switch db service for: ",info->treename," to backup") ;
 					goto err ;
 				}
 				db = stralloc_zero ;
-				if (!backup_realpath_sym(&db,tree,LONGRUN))
+				if (!backup_realpath_sym(&db,info,LONGRUN))
 				{
-					VERBO3 strerr_warnwu2sys("find path of db: ",treename) ;
+					VERBO3 strerr_warnwu2sys("find path of db: ",info->treename) ;
 					goto err ;
 				}
-				if (!db_update(db.s, treename,livetree,envp))
+				if (!db_update(db.s, info,envp))
 				{
-					VERBO3 strerr_warnwu3sys("switch: ",treename," to source") ;
+					VERBO3 strerr_warnwu3sys("switch: ",info->treename," to source") ;
 					VERBO3 strerr_warnwu1sys("unable to rollback the db state, please make a bug report") ;
 					goto err ;
 				}
 			}
 		}
-		VERBO3 strerr_warnt2x("make a backup of db service for: ",treename) ;
-		if (!backup_make_new(base,tree,treename,LONGRUN))
+		VERBO3 strerr_warnt2x("make a backup of db service for: ",info->treename) ;
+		if (!backup_make_new(info,LONGRUN))
 		{
-			VERBO3 strerr_warnwu2sys("make a backup of db service for: ",treename) ;
+			VERBO3 strerr_warnwu2sys("make a backup of db service for: ",info->treename) ;
 			goto err ;
 		}
 	}
diff --git a/src/lib66/db_update.c b/src/lib66/db_update.c
index 6538375ce8f15ddecfeeffc579cc4f4b70a370ba..7ff937a538163dae6e983845601d838cd2fd4586 100644
--- a/src/lib66/db_update.c
+++ b/src/lib66/db_update.c
@@ -25,27 +25,26 @@
 
 #include <66/constants.h>
 #include <66/utils.h>
+#include <66/ssexec.h>
 
-int db_update(char const *newdb, char const *tree, char const *live,char const *const *envp)
+int db_update(char const *newdb, ssexec_t *info,char const *const *envp)
 {
 	
 	pid_t pid ;
 	int wstat ;
-	size_t treelen = strlen(tree) ;
 	size_t newdblen = strlen(newdb) ;
-	size_t livelen = strlen(live) ;
 	
-	char db[newdblen + 1 + treelen + 1] ; 
+	char db[newdblen + 1 + info->tree.len + 1] ; 
 	memcpy(db, newdb, newdblen) ;
 	memcpy(db + newdblen, "/", 1) ;
-	memcpy(db + newdblen + 1, tree, treelen) ;
-	db[newdblen + 1 + treelen] = 0 ;
+	memcpy(db + newdblen + 1, info->tree.s, info->tree.len) ;
+	db[newdblen + 1 + info->tree.len] = 0 ;
 		
-	char newlive[livelen + 1 + treelen + 1] ;
-	memcpy(newlive, live,livelen) ;
-	memcpy(newlive + livelen , "/", 1) ;
-	memcpy(newlive + livelen + 1, tree,treelen) ;
-	newlive[livelen + 1 + treelen] = 0 ;
+	char newlive[info->live.len + 1 + info->tree.len + 1] ;
+	memcpy(newlive, info->live.s,info->live.len) ;
+	memcpy(newlive + info->live.len , "/", 1) ;
+	memcpy(newlive + info->live.len + 1, info->tree.s,info->tree.len) ;
+	newlive[info->live.len + 1 + info->tree.len] = 0 ;
 	
 	char const *newargv[10] ;
 	unsigned int m = 0 ;
diff --git a/src/lib66/deps-lib/66 b/src/lib66/deps-lib/66
index 4acfa46269454cd90206b839e5fae4fbe13e76ea..642f017720db335430dfd75e68e572dfe124db58 100644
--- a/src/lib66/deps-lib/66
+++ b/src/lib66/deps-lib/66
@@ -24,6 +24,16 @@ set_livescan.o
 set_livetree.o
 set_ownerhome.o
 set_ownersysdir.o
+ssexec_dbctl.o
+ssexec_enable.o
+ssexec_disable.o
+ssexec_free.o
+ssexec_help.o
+ssexec_init.o
+ssexec_main.o
+ssexec_start.o
+ssexec_stop.o
+ssexec_svctl.o
 sv_alltype_zero.o
 svc_init.o
 svc_init_pipe.o
diff --git a/src/lib66/parser_write.c b/src/lib66/parser_write.c
index 385af8f9330712f8a803c33c20913b8f1e0bd762..125742acddec7898edb096092ea9c0d20566c79b 100644
--- a/src/lib66/parser_write.c
+++ b/src/lib66/parser_write.c
@@ -760,7 +760,7 @@ int write_common(sv_alltype *sv, char const *dst)
 		}
 		
 		/** /etc/env/sv_name*/
-		size_t sslen = sa.len - 2 ;//-2 remove 0 and '/'
+		size_t sslen = sa.len - 1 ;//-1 for last '/'
 		char *name = keep.s + sv->cname.name ;
 		char dst[sslen + SS_ENVDIR_LEN + 1] ;
 		memcpy(dst,sa.s,sslen) ;
@@ -816,7 +816,7 @@ int write_exec(sv_alltype *sv, sv_exec *exec,char const *file,char const *dst,in
 		VERBO3 strerr_warnwu1sys("get home system directory") ;
 		return 0 ;
 	}
-	size_t envdstlen = sa.len - 2 ;//-2 0 of stra and last '/'
+	size_t envdstlen = sa.len - 1 ;//-1 last '/'
 	char envdata[envdstlen + SS_ENVDIR_LEN + 1] ;
 	memcpy(envdata,sa.s,envdstlen) ;
 	memcpy(envdata + envdstlen, SS_ENVDIR,SS_ENVDIR_LEN) ;
diff --git a/src/lib66/resolve.c b/src/lib66/resolve.c
index 12c7e490bc9e9c05b7a8518eafce7d9534999150..ea9d6fdfaeb7beba1a475a5fe88e1c10ef981309 100644
--- a/src/lib66/resolve.c
+++ b/src/lib66/resolve.c
@@ -212,7 +212,7 @@ int resolve_symlive(char const *live, char const *tree, char const *treename)
 {
 	int r ;
 	
-	size_t livelen = strlen(live) - 1 ;
+	size_t livelen = strlen(live) ;
 	size_t treelen = strlen(tree) ;
 	size_t treenamelen = strlen(treename) ;
 	size_t newlen ;
@@ -281,44 +281,42 @@ int resolve_symlive(char const *live, char const *tree, char const *treename)
 	return 1 ;
 }
 
-int resolve_pointo(stralloc *sa,char const *base, char const *live,char const *tree,char const *treename,unsigned int type, unsigned int what)
+int resolve_pointo(stralloc *sa,ssexec_t *info,unsigned int type, unsigned int what)
 {
-	size_t baselen = strlen(base)  ;
-	size_t treelen = strlen(tree) ;
-	size_t livelen = strlen(live) - 1 ;
-	size_t treenamelen = strlen(treename) ;
+	size_t treenamelen = strlen(info->treename) ;
+	size_t livelen = info->live.len - 1 ;
 	size_t sourcelen ;
 	size_t backlen ;
 	size_t psrclen ;
 	
 	char *r = NULL ;
-	uid_t owner = MYUID ;
+	
 	char ownerstr[256] ;
-	size_t ownerlen = uid_fmt(ownerstr,owner) ;
+	size_t ownerlen = uid_fmt(ownerstr,info->owner) ;
 	ownerstr[ownerlen] = 0 ;
 
 	char resolve[livelen + SS_RESOLVE_LEN + 1 + ownerlen + 1 + treenamelen + 1] ;
-	memcpy(resolve, live,livelen) ;
+	memcpy(resolve, info->live.s,livelen) ;
 	memcpy(resolve + livelen, SS_RESOLVE, SS_RESOLVE_LEN) ;
 	resolve[livelen + SS_RESOLVE_LEN] = '/' ;
 	memcpy(resolve + livelen + SS_RESOLVE_LEN + 1, ownerstr,ownerlen) ;
 	resolve[livelen + SS_RESOLVE_LEN + 1 + ownerlen] = '/' ;
-	memcpy(resolve + livelen + SS_RESOLVE_LEN + 1 + ownerlen + 1, treename,treenamelen) ;
+	memcpy(resolve + livelen + SS_RESOLVE_LEN + 1 + ownerlen + 1, info->treename,treenamelen) ;
 	resolve[livelen + SS_RESOLVE_LEN + 1 + ownerlen + 1 + treenamelen] = 0 ;
 	
-	char source[treelen + SS_SVDIRS_LEN + SS_SVC_LEN + 1] ;
-	memcpy(source,tree,treelen) ;
-	memcpy(source + treelen, SS_SVDIRS, SS_SVDIRS_LEN) ;
-	sourcelen = treelen + SS_SVDIRS_LEN ;
+	char source[info->tree.len + SS_SVDIRS_LEN + SS_SVC_LEN + 1] ;
+	memcpy(source,info->tree.s,info->tree.len) ;
+	memcpy(source + info->tree.len, SS_SVDIRS, SS_SVDIRS_LEN) ;
+	sourcelen = info->tree.len + SS_SVDIRS_LEN ;
 	source[sourcelen] = 0 ;
 	
-	char backup[baselen + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treenamelen + SS_SVC_LEN + 1] ;
-	memcpy(backup,base,baselen) ;
-	memcpy(backup + baselen, SS_SYSTEM, SS_SYSTEM_LEN) ;
-	memcpy(backup + baselen + SS_SYSTEM_LEN, SS_BACKUP, SS_BACKUP_LEN) ;
-	backup[baselen + SS_SYSTEM_LEN + SS_BACKUP_LEN] = '/' ;
-	memcpy(backup + baselen + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1, treename,treenamelen) ;
-	backlen = baselen + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treenamelen ;
+	char backup[info->base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treenamelen + SS_SVC_LEN + 1] ;
+	memcpy(backup,info->base.s,info->base.len) ;
+	memcpy(backup + info->base.len, SS_SYSTEM, SS_SYSTEM_LEN) ;
+	memcpy(backup + info->base.len + SS_SYSTEM_LEN, SS_BACKUP, SS_BACKUP_LEN) ;
+	backup[info->base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN] = '/' ;
+	memcpy(backup + info->base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1, info->treename,treenamelen) ;
+	backlen = info->base.len + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treenamelen ;
 	backup[backlen] = 0 ;
 	
 	if (type && what)
diff --git a/src/lib66/set_info.c b/src/lib66/set_info.c
new file mode 100644
index 0000000000000000000000000000000000000000..3ce95f5007b69b8a2187862096b93e669343b6b0
--- /dev/null
+++ b/src/lib66/set_info.c
@@ -0,0 +1,29 @@
+/* 
+ * set_info.c
+ * 
+ * Copyright (c) 2018 Eric Vidal <eric@obarun.org>
+ * 
+ * All rights reserved.
+ * 
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+ 
+#include <66/utils.h>
+ 
+#include <oblibs/error2.h>
+#include <oblibs/directory.h>
+
+#include <skalibs/stralloc.h>
+
+#include <66/config.h>
+
+int set_info(ssexec_t *info)
+{
+	
+	
+	return 1 ;
+}
diff --git a/src/lib66/set_livedir.c b/src/lib66/set_livedir.c
index a0b9ebe31b00ba864f314e155893f5df7706ce01..7f9da6c7578db71de220b5bfadb337eab65621ff 100644
--- a/src/lib66/set_livedir.c
+++ b/src/lib66/set_livedir.c
@@ -23,12 +23,10 @@
 
 int set_livedir(stralloc *live)
 {
-	int r ;
 	
 	if (live->len)
 	{
-		r = dir_scan_absopath(live->s) ;
-		if(r < 0) return -1 ;
+		if (live->s[0] != '/') return -1 ;
 		if (live->s[live->len - 2] != '/')
 		{
 			live->len-- ;
@@ -41,6 +39,6 @@ int set_livedir(stralloc *live)
 		if (!stralloc_cats(live,SS_LIVE)) retstralloc(0,"set_livedir") ;
 		if (!stralloc_0(live)) retstralloc(0,"set_livedir") ;
 	}
-	
+	live->len--;
 	return 1 ;
 }
diff --git a/src/lib66/set_livescan.c b/src/lib66/set_livescan.c
index 9f8cff88abf3f7418ccd14f3c45e62692f5af459..23425ae5242c10f68cc18c76f0a52e22ab9e5553 100644
--- a/src/lib66/set_livescan.c
+++ b/src/lib66/set_livescan.c
@@ -22,22 +22,21 @@
 
 #include <66/config.h>
 
-int set_livescan(stralloc *live,uid_t owner)
+int set_livescan(stralloc *scandir,uid_t owner)
 {
 	int r ;
 	char ownerpack[256] ;
 		
-	r = set_livedir(live) ;
+	r = set_livedir(scandir) ;
 	if (r < 0) return -1 ;
 	if (!r) return 0 ;
 		
 	size_t ownerlen = uid_fmt(ownerpack,owner) ;
 	ownerpack[ownerlen] = 0 ;
 	
-	live->len--;
-	if (!stralloc_cats(live,"scandir/")) retstralloc(0,"set_livedir") ;
-	if (!stralloc_cats(live,ownerpack)) retstralloc(0,"set_livedir") ;
-	if (!stralloc_0(live)) retstralloc(0,"set_livedir") ;
-	
+	if (!stralloc_cats(scandir,"scandir/")) retstralloc(0,"set_livedir") ;
+	if (!stralloc_cats(scandir,ownerpack)) retstralloc(0,"set_livedir") ;
+	if (!stralloc_0(scandir)) retstralloc(0,"set_livedir") ;
+	scandir->len--;
 	return 1 ;
 }
diff --git a/src/lib66/set_livetree.c b/src/lib66/set_livetree.c
index 6809d9417e7719be304ad74d83b4cbb5c26394a7..c6a28a91e41cfae5b9846485e00ce2b71f41a1c3 100644
--- a/src/lib66/set_livetree.c
+++ b/src/lib66/set_livetree.c
@@ -22,23 +22,22 @@
 
 #include <66/config.h>
 
-int set_livetree(stralloc *live,uid_t owner)
+int set_livetree(stralloc *livetree,uid_t owner)
 {
 	int r ;
 	char ownerpack[256] ;
 	
 	
-	r = set_livedir(live) ;
+	r = set_livedir(livetree) ;
 	if (r < 0) return -1 ;
 	if (!r) return 0 ;
 		
 	size_t ownerlen = uid_fmt(ownerpack,owner) ;
 	ownerpack[ownerlen] = 0 ;
 	
-	live->len-- ;
-	if (!stralloc_cats(live,"tree/")) retstralloc(0,"set_livedir") ;
-	if (!stralloc_cats(live,ownerpack)) retstralloc(0,"set_livedir") ;
-	if (!stralloc_0(live)) retstralloc(0,"set_livedir") ;
-	
+	if (!stralloc_cats(livetree,"tree/")) retstralloc(0,"set_livedir") ;
+	if (!stralloc_cats(livetree,ownerpack)) retstralloc(0,"set_livedir") ;
+	if (!stralloc_0(livetree)) retstralloc(0,"set_livedir") ;
+	livetree->len--;
 	return 1 ;
 }
diff --git a/src/lib66/set_ownerhome.c b/src/lib66/set_ownerhome.c
index cc87c70330efc7ed3e6a9570fff0758cfe6d05d7..bd9ced878bce172adb86288ce1455cfb30a05ab8 100644
--- a/src/lib66/set_ownerhome.c
+++ b/src/lib66/set_ownerhome.c
@@ -40,8 +40,8 @@ int set_ownerhome(stralloc *base,uid_t owner)
 	if (!user_home) return 0 ;
 	
 	if (!stralloc_cats(base,user_home))	retstralloc(0,"set_ownerhome") ;
-	if (!stralloc_catb(base,"/",1))	retstralloc(0,"set_ownerhome") ;
+	if (!stralloc_cats(base,"/"))	retstralloc(0,"set_ownerhome") ;
 	if (!stralloc_0(base)) retstralloc(0,"set_ownerhome") ;
-		
+	base->len--;
 	return 1 ;
 }
diff --git a/src/lib66/set_ownersysdir.c b/src/lib66/set_ownersysdir.c
index 1036bfa4d68306b251ccf1dbb658ff0df06377e1..b3fcefaa8e843a500af096a4ac58ad792a7f99a8 100644
--- a/src/lib66/set_ownersysdir.c
+++ b/src/lib66/set_ownersysdir.c
@@ -39,7 +39,7 @@ int set_ownersysdir(stralloc *base, uid_t owner)
 	errno = e ;
 	if (user_home == NULL) return 0 ;
 	
-	if(MYUID > 0){
+	if(owner > 0){
 		if (!stralloc_cats(base,user_home))	retstralloc(0,"set_ownersysdir") ;
 		if (!stralloc_cats(base,"/"))	retstralloc(0,"set_ownersysdir") ;
 		if (!stralloc_cats(base,SS_USER_DIRECTORY))	retstralloc(0,"set_ownersysdir") ;
@@ -50,5 +50,6 @@ int set_ownersysdir(stralloc *base, uid_t owner)
 		if (!stralloc_cats(base,SS_SYSTEM_DIRECTORY)) retstralloc(0,"set_ownersysdir") ;
 		if (!stralloc_0(base)) retstralloc(0,"set_ownersysdir") ;
 	}
+	base->len--;
 	return 1 ;
 }
diff --git a/src/lib66/ssexec_dbctl.c b/src/lib66/ssexec_dbctl.c
new file mode 100644
index 0000000000000000000000000000000000000000..d69af8a26520df2e95964f93291fc04ea551bfe8
--- /dev/null
+++ b/src/lib66/ssexec_dbctl.c
@@ -0,0 +1,218 @@
+/* 
+ * ssexec_dbctl.c
+ * 
+ * Copyright (c) 2018 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/stat.h>
+#include <stdlib.h>
+
+#include <oblibs/obgetopt.h>
+#include <oblibs/error2.h>
+#include <oblibs/directory.h>
+#include <oblibs/types.h>
+#include <oblibs/string.h>
+#include <oblibs/stralist.h>
+
+#include <skalibs/buffer.h>
+#include <skalibs/types.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/selfpipe.h>
+#include <skalibs/iopause.h>
+#include <skalibs/sig.h>
+
+#include <s6-rc/config.h>
+#include <s6/s6-supervise.h>
+
+#include <66/utils.h>
+#include <66/constants.h>
+#include <66/db.h>
+#include <66/tree.h>
+#include <66/enum.h>
+
+//#include <stdio.h>
+
+static unsigned int DEADLINE = 0 ;
+static stralloc saresolve = STRALLOC_ZERO ;
+
+static pid_t send(genalloc *gasv, char const *livetree, char const *signal,char const *const *envp)
+{
+	char const *newargv[10 + genalloc_len(stralist,gasv)] ;
+	unsigned int m = 0 ;
+	char fmt[UINT_FMT] ;
+	fmt[uint_fmt(fmt, VERBOSITY)] = 0 ;
+	
+	char tt[UINT32_FMT] ;
+	tt[uint32_fmt(tt,DEADLINE)] = 0 ;
+	
+	newargv[m++] = S6RC_BINPREFIX "s6-rc" ;
+	newargv[m++] = "-v" ;
+	newargv[m++] = fmt ;
+	newargv[m++] = "-t" ;
+	newargv[m++] = tt ;
+	newargv[m++] = "-l" ;
+	newargv[m++] = livetree ;
+	newargv[m++] = signal ;
+	newargv[m++] = "change" ;
+	
+	for (unsigned int i = 0 ; i<genalloc_len(stralist,gasv); i++)
+		newargv[m++] = gaistr(gasv,i) ;
+	
+	newargv[m++] = 0 ;
+		
+	return child_spawn0(newargv[0],newargv,envp) ;
+	
+}
+
+int ssexec_dbctl(int argc, char const *const *argv,char const *const *envp,ssexec_t *info)
+{
+	
+	// be sure that the global var are set correctly
+	DEADLINE = 0 ;
+	saresolve = stralloc_zero ;
+
+	unsigned int up, down, reload ;
+	
+	int wstat ;
+	pid_t pid ;
+	
+	char *signal = 0 ;
+	char *mainsv = "Master" ;
+	
+	genalloc gasv = GENALLOC_ZERO ; //stralist
+	stralloc tmp = STRALLOC_ZERO ;
+	
+	up = down = reload = 0 ;
+	
+	//PROG = "66-dbctl" ;
+	{
+		subgetopt_t l = SUBGETOPT_ZERO ;
+
+		for (;;)
+		{
+			int opt = getopt_args(argc,argv, ">udr", &l) ;
+			if (opt == -1) break ;
+			if (opt == -2) strerr_dief1x(110,"options must be set first") ;
+			switch (opt)
+			{
+				case 'u' :	up = 1 ; if (down) exitusage(usage_dbctl) ; break ;
+				case 'd' : 	down = 1 ; if (up) exitusage(usage_dbctl) ; break ;
+				case 'r' : 	reload = 1 ; if (down || up) exitusage(usage_dbctl) ; break ;
+				default : exitusage(usage_dbctl) ; 
+			}
+		}
+		argc -= l.ind ; argv += l.ind ;
+	}
+	
+	if (argc < 1) if (!stra_add(&gasv,mainsv)) strerr_diefu1sys(111,"add: Master as service to handle") ;
+	
+	if (info->timeout) DEADLINE = info->timeout ;
+	
+	if (!db_ok(info->livetree.s,info->treename))
+		strerr_dief5sys(111,"db: ",info->livetree.s,"/",info->treename," is not running") ;
+
+	for(;*argv;argv++)
+		if (!stra_add(&gasv,*argv)) strerr_diefu3sys(111,"add: ",*argv," as service to handle") ;
+	
+	if (!stralloc_cats(&tmp,info->livetree.s)) retstralloc(111,"main") ;
+	if (!stralloc_cats(&tmp,"/")) retstralloc(111,"main") ;
+	if (!stralloc_cats(&tmp,info->treename)) retstralloc(111,"main") ;
+	if (!stralloc_0(&tmp)) retstralloc(111,"main") ;
+	
+	if (reload)
+	{
+		pid = send(&gasv,tmp.s,"-d",envp) ;
+		
+		if (waitpid_nointr(pid,&wstat, 0) < 0)
+			strerr_diefu1sys(111,"wait for s6-rc") ;
+		
+		if (wstat)
+		{
+			if (down)
+				strerr_diefu1x(111,"bring down services list") ;
+			else
+				strerr_diefu1x(111,"bring up services list") ;
+		}
+	}
+	
+	if (down) signal = "-d" ;
+	else signal = "-u" ;
+	
+	pid = send(&gasv,tmp.s,signal,envp) ;
+	
+	if (waitpid_nointr(pid,&wstat, 0) < 0)
+		strerr_diefu1sys(111,"wait for s6-rc") ;
+	
+	if (wstat)
+	{
+		if (down)
+			strerr_diefu1x(111,"bring down services list") ;
+		else
+			strerr_diefu1x(111,"bring up services list") ;
+	}
+	/** we are forced to do this ugly check cause of the design
+	 * of s6-rc(generally s6-svc) which is launch and forgot. So
+	 * s6-rc will not warn us if the daemon fail when we don't use
+	 * readiness which is rarely used on DESKTOP configuration due of
+	 * the bad design of the majority of daemon.
+	 * The result of the check is not guaranted due of the rapidity of the code.
+	 * between the end of the s6-rc process and the check of the daemon status,
+	 * the real value of the status can be not written yet,so we can hit
+	 * this window.*/
+	s6_svstatus_t status = S6_SVSTATUS_ZERO ;
+	tmp.len-- ;
+	if (!stralloc_cats(&tmp,SS_SVDIRS)) retstralloc(111,"main") ; 
+	if (!stralloc_cats(&tmp,"/")) retstralloc(111,"main") ; 
+	size_t newlen = tmp.len ;
+	
+	if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+		strerr_diefu1x(111,"set revolve pointer to source") ;
+	
+	stralloc type = STRALLOC_ZERO ;
+		
+	for (unsigned int i = 0; i < genalloc_len(stralist,&gasv) ; i++)
+	{
+		char *svname = gaistr(&gasv,i) ;
+		if (resolve_read(&type,saresolve.s,svname,"type") <= 0)
+			strerr_diefu2sys(111,"read type of: ",svname) ;
+		
+		if (get_enumbyid(type.s,key_enum_el) == LONGRUN)
+		{
+			tmp.len = newlen ;
+			
+			if (!stralloc_cats(&tmp,svname)) retstralloc(111,"main") ; 
+			
+			if (!s6_svstatus_read(tmp.s,&status)) strerr_diefu2sys(111,"read status of: ",tmp.s) ;
+					
+			if (down)
+			{
+				if (WEXITSTATUS(status.wstat) && WIFEXITED(status.wstat) && status.pid)
+					strerr_diefu2x(111,"stop: ",svname) ;
+			}
+			if (up)
+			{
+				if (WEXITSTATUS(status.wstat) && WIFEXITED(status.wstat))
+					strerr_diefu2x(111,"start: ",svname) ;
+			}
+		}
+	}
+	
+	stralloc_free(&tmp) ;	
+	stralloc_free(&type) ;
+	stralloc_free(&saresolve) ;
+	
+	return 0 ;
+}
+
+	
+
diff --git a/src/lib66/ssexec_disable.c b/src/lib66/ssexec_disable.c
new file mode 100644
index 0000000000000000000000000000000000000000..79c5bb4c76152853b1c08ede50b7dcb3c72b0500
--- /dev/null
+++ b/src/lib66/ssexec_disable.c
@@ -0,0 +1,460 @@
+/* 
+ * ssexec_disable.c
+ * 
+ * Copyright (c) 2018 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/stat.h>
+#include <stdlib.h>
+
+#include <oblibs/obgetopt.h>
+#include <oblibs/error2.h>
+#include <oblibs/directory.h>
+#include <oblibs/types.h>
+#include <oblibs/string.h>
+#include <oblibs/files.h>
+#include <oblibs/stralist.h>
+
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/buffer.h>
+#include <skalibs/unix-transactional.h>
+#include <skalibs/direntry.h>
+#include <skalibs/diuint32.h>
+ 
+#include <66/constants.h>
+#include <66/utils.h>
+#include <66/enum.h>
+#include <66/tree.h>
+#include <66/db.h>
+#include <66/backup.h>
+#include <66/graph.h>
+
+//#include <stdio.h>
+
+static stralloc saresolve = STRALLOC_ZERO ;
+
+static void cleanup(char const *dst)
+{
+	int e = errno ;
+	rm_rf(dst) ;
+	errno = e ;
+}
+
+int find_logger(genalloc *ga, char const *name, char const *src)
+{
+	stralloc sa = STRALLOC_ZERO ;
+	if (resolve_read(&sa,src,name,"logger"))
+	{
+		if (!stra_add(ga,sa.s))
+		{
+			stralloc_free(&sa) ;
+			return 0 ;
+		}
+	}
+	stralloc_free(&sa) ;
+	return 1 ;
+}
+
+int remove_sv(genalloc *toremove, char const *name, char const *src, unsigned int type)
+{
+	int r ;
+
+	size_t namelen = strlen(name) ;
+	size_t srclen = strlen(src) ;
+	size_t newlen ;
+		
+	/** classic service */
+	if (type == CLASSIC)
+	{
+		char dst[srclen + SS_SVC_LEN + 1 + namelen + 1] ;
+		memcpy(dst,src,srclen) ;
+		memcpy(dst + srclen, SS_SVC, SS_SVC_LEN) ;
+		dst[srclen + SS_SVC_LEN]  =  '/' ;
+		memcpy(dst + srclen + SS_SVC_LEN + 1, name, namelen) ;
+		dst[srclen + SS_SVC_LEN + 1 + namelen] = 0 ;
+		
+		VERBO3 strerr_warnt3x("Removing ",dst + srclen + 1," service ... ") ;
+		if (rm_rf(dst) < 0)
+		{
+			VERBO3 strerr_warnwu2sys("remove: ", dst) ;
+			return 0 ;
+		}
+				
+		return 1 ;
+	}
+	
+	stralloc sa = STRALLOC_ZERO ;
+	genalloc gatmp = GENALLOC_ZERO ;// type stralist
+	
+	graph_t g = GRAPH_ZERO ;
+	stralloc sagraph = STRALLOC_ZERO ;
+	genalloc tokeep = GENALLOC_ZERO ;
+	
+	/** rc services */
+	{
+		/** build dependencies graph*/
+		r = graph_type_src(&tokeep,src,1) ;
+		if (r <= 0)
+		{
+			strerr_warnwu2x("resolve source of graph for tree: ",src) ;
+			goto err ;
+		}
+		if (!graph_build(&g,&sagraph,&tokeep,src))
+		{
+			strerr_warnwu1x("make dependencies graph") ;
+			goto err ;
+		}
+	
+		if (!stra_add(toremove,name)) 
+		{	 
+			VERBO3 strerr_warnwu3x("add: ",name," as dependency to remove") ;
+			goto err ;
+		}
+		
+		r = graph_rdepends(toremove,&g,name,src) ;
+		if (!r) 
+		{
+			VERBO3 strerr_warnwu2x("find services depending for: ",name) ;
+			goto err ;
+		}
+		if(r == 2) VERBO3 strerr_warnt2x("any services don't depends of: ",name) ;
+		
+		if (!stralloc_catb(&sa,src,srclen)) retstralloc(0,"remove_sv") ;
+		if (!stralloc_cats(&sa,SS_DB SS_SRC)) retstralloc(0,"remove_sv") ;
+		if (!stralloc_cats(&sa, "/")) retstralloc(0,"remove_sv") ;
+		newlen = sa.len ;
+		if (genalloc_len(stralist,toremove))
+			if (!find_logger(toremove,name,src)) goto err ;
+			
+		for (unsigned int i = 0; i < genalloc_len(stralist,toremove); i++)
+		{
+			sa.len = newlen ;
+			if (!stralloc_cats(&sa,gaistr(toremove,i))) retstralloc(0,"remove_sv") ;
+			if (!stralloc_0(&sa)) retstralloc(0,"remove_sv") ;
+			VERBO3 strerr_warnt3x("Removing ",sa.s + srclen + 1," service ...") ;
+			if (rm_rf(sa.s) < 0)
+			{
+				VERBO3 strerr_warnwu2sys("remove: ", sa.s) ;
+				goto err ;
+			}
+		}
+
+	}
+	
+	genalloc_free(vertex_graph_t,&g.stack) ;
+	genalloc_free(vertex_graph_t,&g.vertex) ;
+	stralloc_free(&sagraph) ;
+	stralloc_free(&sa) ;
+	genalloc_deepfree(stralist,&gatmp,stra_free) ;
+	
+	return 1 ;
+	
+	err:
+		genalloc_free(vertex_graph_t,&g.stack) ;
+		genalloc_free(vertex_graph_t,&g.vertex) ;
+		stralloc_free(&sagraph) ;
+		stralloc_free(&sa) ;
+		genalloc_deepfree(stralist,&gatmp,stra_free) ;
+		return 0 ;
+}
+
+int ssexec_disable(int argc, char const *const *argv,char const *const *envp,ssexec_t *info)
+{
+	// be sure that the global var are set correctly
+	saresolve = stralloc_zero ;
+	
+	int r,rb ;
+	unsigned int nlongrun, nclassic, stop ;
+	
+	
+	stralloc workdir = STRALLOC_ZERO ;
+	
+	genalloc ganlong = GENALLOC_ZERO ; //name of longrun service, type stralist
+	genalloc ganclassic = GENALLOC_ZERO ; //name of classic service, stralist
+	genalloc gadepstoremove = GENALLOC_ZERO ;
+	
+	graph_t g = GRAPH_ZERO ;
+	stralloc sagraph = STRALLOC_ZERO ;
+	genalloc tokeep = GENALLOC_ZERO ;
+	genalloc master = GENALLOC_ZERO ;
+	
+	r = nclassic = nlongrun = stop = 0 ;
+	
+	//PROG = "66-disable" ;	
+	{
+		subgetopt_t l = SUBGETOPT_ZERO ;
+
+		for (;;)
+		{
+			int opt = getopt_args(argc,argv, ">S", &l) ;
+			if (opt == -1) break ;
+			if (opt == -2) strerr_dief1x(110,"options must be set first") ;
+			switch (opt)
+			{
+				case 'S' :	stop = 1 ;	break ;
+				default : exitusage(usage_disable) ; 
+			}
+		}
+		argc -= l.ind ; argv += l.ind ;
+	}
+	
+	if (argc < 1) exitusage(usage_disable) ;
+	
+	if (!tree_copy(&workdir,info->tree.s,info->treename)) strerr_diefu1sys(111,"create tmp working directory") ;
+	
+	{
+		stralloc type = STRALLOC_ZERO ;
+		
+		for(;*argv;argv++)
+		{
+			if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+			{
+				cleanup(workdir.s) ;
+				strerr_diefu1x(111,"set revolve pointer to source") ;
+			}
+			rb = resolve_read(&type,saresolve.s,*argv,"remove") ;
+			if (rb) 
+			{
+				strerr_warni2x(*argv,": is already disabled") ;
+				continue ;
+			}
+			
+			rb = resolve_read(&type,saresolve.s,*argv,"type") ;
+			if (rb < -1)
+			{
+				cleanup(workdir.s) ;
+				strerr_dief2x(111,"invalid .resolve directory: ",saresolve.s) ;
+			}
+			if (rb <= 0)
+			{
+				cleanup(workdir.s) ;
+				strerr_dief2x(111,*argv,": is not enabled") ;
+			}
+			
+			if (get_enumbyid(type.s,key_enum_el) == CLASSIC)
+			{
+				if (!stra_add(&ganclassic,*argv)) retstralloc(111,"main") ;
+				nclassic++ ;
+			}					
+			if (get_enumbyid(type.s,key_enum_el) >= BUNDLE)
+			{
+				if (!stra_add(&ganlong,*argv)) retstralloc(111,"main") ;
+				nlongrun++ ;
+			}
+		}
+		stralloc_free(&type) ;
+	}
+
+	if (nclassic)
+	{
+		VERBO2 strerr_warni1x("remove svc services ... ") ;
+		for (unsigned int i = 0 ; i < genalloc_len(stralist,&ganclassic) ; i++)
+		{
+			char *name = gaistr(&ganclassic,i) ;
+			
+			if (!remove_sv(&gadepstoremove,name,workdir.s,CLASSIC))
+			{
+				cleanup(workdir.s) ;
+				strerr_diefu2x(111,"disable: ",name) ;
+			}
+			
+			/** modify the resolve file for 66-stop*/
+			if (!resolve_write(workdir.s,gaistr(&ganclassic,i),"remove","",1))
+			{
+				cleanup(workdir.s) ;
+				strerr_diefu2sys(111,"write resolve file: remove for service: ",gaistr(&ganclassic,i)) ;
+			}
+		}
+		char type[UINT_FMT] ;
+		size_t typelen = uint_fmt(type, CLASSIC) ;
+		type[typelen] = 0 ;
+		size_t cmdlen ;
+		char cmd[typelen + 6 + 1] ;
+		memcpy(cmd,"-t",2) ;
+		memcpy(cmd + 2,type,typelen) ;
+		cmdlen = 2 + typelen ;
+		memcpy(cmd + cmdlen," -b",3) ;
+		cmd[cmdlen + 3] = 0 ;
+		r = backup_cmd_switcher(VERBOSITY,cmd,info) ;
+		if (r < 0)
+		{
+			cleanup(workdir.s) ;
+			strerr_diefu2sys(111,"find origin of tree: ",info->treename) ;
+		}
+		// point to origin
+		if (!r)
+		{
+			stralloc sv = STRALLOC_ZERO ;
+			VERBO2 strerr_warni2x("make backup of tree: ",info->treename) ;
+			if (!backup_make_new(info,CLASSIC))
+			{
+				cleanup(workdir.s) ;
+				strerr_diefu2sys(111,"make a backup of db: ",info->treename) ;
+			}
+			memcpy(cmd + cmdlen," -s1",4) ;
+			cmd[cmdlen + 4] = 0 ;
+			r = backup_cmd_switcher(VERBOSITY,cmd,info) ;
+			if (r < 0)
+			{
+				cleanup(workdir.s) ;
+				strerr_diefu3sys(111,"switch current db: ",info->treename," to source") ;
+			}
+			/** creer le fichier torelaod*/
+			stralloc_free(&sv) ;
+		}
+		gadepstoremove = genalloc_zero ;
+	}
+	
+	if (nlongrun)
+	{	
+		
+		VERBO2 strerr_warni1x("remove rc services ... ") ;
+		for (unsigned int i = 0 ; i < genalloc_len(stralist,&ganlong) ; i++)
+		{
+			char *name = gaistr(&ganlong,i) ;
+			
+			if (!remove_sv(&gadepstoremove,name,workdir.s,LONGRUN))
+			{
+				cleanup(workdir.s) ;
+				strerr_diefu2x(111,"disable: ",name) ;
+			}
+		}
+
+		for (unsigned int i = 0 ; i < genalloc_len(stralist,&gadepstoremove) ; i++ )
+		{
+			// modify the resolve file for 66-stop*/
+			if (!resolve_write(workdir.s,gaistr(&gadepstoremove,i),"remove","",1))
+			{
+				cleanup(workdir.s) ;
+				strerr_diefu2sys(111,"write resolve file: remove for service: ",gaistr(&gadepstoremove,i)) ;
+			}
+		}
+		
+		r = graph_type_src(&tokeep,workdir.s,1) ;
+		if (!r)
+		{
+			cleanup(workdir.s) ;
+			strerr_diefu2x(111,"resolve source of graph for tree: ",info->treename) ;
+		}
+		if (r < 0)
+		{
+			if (!stra_add(&master,"")) retstralloc(111,"main") ;
+		}
+		else 
+		{
+			if (!graph_build(&g,&sagraph,&tokeep,workdir.s))
+			{
+				cleanup(workdir.s) ;
+				strerr_diefu1x(111,"make dependencies graph") ;
+			}
+			if (!graph_sort(&g))
+			{
+				cleanup(workdir.s) ;
+				strerr_dief1x(111,"cyclic graph detected") ;
+			}
+			if (!graph_master(&master,&g))
+			{
+				cleanup(workdir.s) ;
+				strerr_dief1x(111,"find master service") ;
+			}
+		}
+		
+		
+		if (!db_write_contents(&master,SS_MASTER + 1,workdir.s))
+		{
+			cleanup(workdir.s) ;
+			strerr_diefu2x(111,"update bundle: ", SS_MASTER) ;
+		}
+			
+		if (!db_compile(workdir.s,info->tree.s, info->treename,envp))
+		{
+			cleanup(workdir.s) ;
+			strerr_diefu4x(111,"compile ",workdir.s,"/",info->treename) ; 
+		}
+		
+		/** 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," 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) ;
+	workdir = stralloc_zero ;
+	
+	for (int i = 0 ; i < genalloc_len(stralist,&ganclassic) ; i++)
+	{
+		if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+			strerr_diefu1x(111,"set revolve pointer to source") ;
+		
+		if (resolve_read(&workdir,saresolve.s,gaistr(&ganclassic,i),"remove")) 
+			if (!resolve_remove(saresolve.s,gaistr(&ganclassic,i),"reload"))
+				strerr_diefu3sys(111,"delete resolve file",saresolve.s,"/reload") ;
+	}
+	
+	for (int i = 0 ; i < genalloc_len(stralist,&ganlong) ; i++)
+	{
+		if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+			strerr_diefu1x(111,"set revolve pointer to source") ;
+		
+		if (resolve_read(&workdir,saresolve.s,gaistr(&ganlong,i),"remove")) 
+			if (!resolve_remove(saresolve.s,gaistr(&ganlong,i),"reload"))
+				strerr_diefu3sys(111,"delete resolve file",saresolve.s,"/reload") ;
+	}
+	
+	if (stop && ((nclassic) || (nlongrun)))
+	{
+		int nargc = 3 + genalloc_len(stralist,&ganclassic) + genalloc_len(stralist,&ganlong) ;
+		char const *newargv[nargc] ;
+		unsigned int m = 0 ;
+		
+		newargv[m++] = "fake_name" ;
+		newargv[m++] = "-u" ;
+		/** classic */
+		for (unsigned int i = 0 ; i<genalloc_len(stralist,&ganclassic); i++)
+			newargv[m++] = gaistr(&ganclassic,i) ;
+		/** rc */
+		for (unsigned int i = 0 ; i<genalloc_len(stralist,&ganlong); i++)
+			newargv[m++] = gaistr(&ganlong,i) ;
+		
+		newargv[m++] = 0 ;
+		
+		if (ssexec_stop(nargc,newargv,envp,info))
+			return 111 ;
+		
+	}
+	
+	stralloc_free(&workdir) ;
+	genalloc_deepfree(stralist,&ganlong,stra_free) ;
+	genalloc_deepfree(stralist,&ganclassic,stra_free) ;
+	genalloc_deepfree(stralist,&gadepstoremove,stra_free) ;
+		
+	/** graph stuff */
+	genalloc_free(vertex_graph_t,&g.stack) ;
+	genalloc_free(vertex_graph_t,&g.vertex) ;
+	stralloc_free(&sagraph) ;	
+	genalloc_deepfree(stralist,&master,stra_free) ;
+	genalloc_deepfree(stralist,&tokeep,stra_free) ;
+	
+	return 0 ;		
+}
+	
diff --git a/src/lib66/ssexec_enable.c b/src/lib66/ssexec_enable.c
new file mode 100644
index 0000000000000000000000000000000000000000..861ebbd1d43992f5ed306f2c38f80ece7fa2f005
--- /dev/null
+++ b/src/lib66/ssexec_enable.c
@@ -0,0 +1,289 @@
+/* 
+ * ssexec_enable.c
+ * 
+ * Copyright (c) 2018 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/stat.h>
+#include <stdlib.h>
+
+#include <oblibs/obgetopt.h>
+#include <oblibs/error2.h>
+#include <oblibs/directory.h>
+#include <oblibs/files.h>
+#include <oblibs/string.h>
+#include <oblibs/types.h>
+#include <oblibs/stralist.h>
+
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/buffer.h>
+#include <skalibs/direntry.h>
+#include <skalibs/unix-transactional.h>
+#include <skalibs/diuint32.h>
+
+#include <66/constants.h>
+#include <66/utils.h>
+#include <66/enum.h>
+#include <66/tree.h>
+#include <66/db.h>
+#include <66/parser.h>
+#include <66/backup.h>
+#include <66/svc.h>
+#include <66/graph.h>
+
+//#include <stdio.h>
+
+static unsigned int FORCE = 0 ;
+
+static void cleanup(char const *dst)
+{
+	int e = errno ;
+	rm_rf(dst) ;
+	errno = e ;
+}
+
+static int start_parser(char const *src,char const *svname,char const *tree, unsigned int *nbsv)
+{
+	stralloc sasv = STRALLOC_ZERO ;
+	
+	if (!parse_service_before(src,svname,tree,nbsv,&sasv)) strerr_dief4x(111,"invalid service file: ",src,"/",svname) ;
+	
+	stralloc_free(&sasv) ;
+	
+	return 1 ;
+}
+
+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 ;
+	
+	int r ;
+	unsigned int nbsv, nlongrun, nclassic, start ;
+	
+	char const *src = SS_SERVICE_DIR ;
+	
+	stralloc workdir = STRALLOC_ZERO ;//working dir directory
+	stralloc sasrc = STRALLOC_ZERO ;
+	stralloc saresolve = STRALLOC_ZERO ;
+	genalloc gasrc = GENALLOC_ZERO ; //type diuint32
+	genalloc ganlong = GENALLOC_ZERO ; // type stralist
+	genalloc ganclassic = GENALLOC_ZERO ; // name of classic service, type stralist
+	
+	graph_t g = GRAPH_ZERO ;
+	stralloc sagraph = STRALLOC_ZERO ;
+	genalloc master = GENALLOC_ZERO ;
+	genalloc tokeep = GENALLOC_ZERO ;
+	
+	r = nbsv = nclassic = nlongrun = start = 0 ;
+	
+	//PROG = "66-enable" ;
+	{
+		subgetopt_t l = SUBGETOPT_ZERO ;
+
+		for (;;)
+		{
+			int opt = getopt_args(argc,argv, ">fS", &l) ;
+			if (opt == -1) break ;
+			if (opt == -2) strerr_dief1x(110,"options must be set first") ;
+			switch (opt)
+			{
+				case 'f' : 	FORCE = 1 ; 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++)
+	{
+		unsigned int found = 0 ;
+		if (!resolve_src(&gasrc,&sasrc,*argv,src,&found)) strerr_diefu2x(111,"resolve source of service file: ",*argv) ;
+	}
+	
+	for (unsigned int i = 0 ; i < genalloc_len(diuint32,&gasrc) ; i++)
+		start_parser(sasrc.s + genalloc_s(diuint32,&gasrc)[i].right,sasrc.s + genalloc_s(diuint32,&gasrc)[i].left,info->tree.s,&nbsv) ;
+	
+	sv_alltype svblob[nbsv] ;
+	
+	for (int i = 0;i < nbsv;i++)
+		svblob[i] =  genalloc_s(sv_alltype,&gasv)[i] ;
+	
+	sv_db before = {
+		.services = svblob, 
+		.nsv = nbsv ,
+		.string = keep.s ,
+		.stringlen = keep.len ,
+		.ndeps = genalloc_len(unsigned int,&gadeps) 
+	} ;
+	
+	{
+		if (!tree_copy(&workdir,info->tree.s,info->treename)) strerr_diefu1sys(111,"create tmp working directory") ;
+		for (unsigned int i = 0; i < before.nsv; i++)
+		{
+			r = write_services(&before.services[i], workdir.s,FORCE) ;
+			if (!r)
+			{
+				cleanup(workdir.s) ;
+				strerr_diefu2x(111,"write service: ",keep.s+before.services[i].cname.name) ;
+			}
+			if (r > 1) continue ; //service already added
+			
+			if (before.services[i].cname.itype > CLASSIC)
+			{
+				if (!stra_add(&ganlong,keep.s + before.services[i].cname.name)) retstralloc(111,"main") ;
+				nlongrun++ ;
+			}
+			else if (before.services[i].cname.itype == CLASSIC) 
+			{
+				if (!stra_add(&ganclassic,keep.s + before.services[i].cname.name)) retstralloc(111,"main") ;
+				nclassic++ ;
+			}
+		}
+		
+	}
+	
+	if (nclassic)
+	{
+		if (!svc_switch_to(info,SS_SWBACK))
+		{
+			cleanup(workdir.s) ;
+			strerr_diefu3x(111,"switch ",info->treename," to backup") ;
+		}	
+	}
+	
+	if(nlongrun)
+	{
+		r = graph_type_src(&tokeep,workdir.s,1) ;
+		if (!r)
+		{
+			cleanup(workdir.s) ;
+			strerr_diefu2x(111,"resolve source of graph for tree: ",info->treename) ;
+		}
+		if (r < 0)
+		{
+			if (!stra_add(&master,"")) retstralloc(111,"main") ;
+		}
+		else 
+		{
+			if (!graph_build(&g,&sagraph,&tokeep,workdir.s))
+			{
+				cleanup(workdir.s) ;
+				strerr_diefu1x(111,"make dependencies graph") ;
+			}
+			if (!graph_sort(&g))
+			{
+				cleanup(workdir.s) ;
+				strerr_dief1x(111,"cyclic graph detected") ;
+			}
+			if (!graph_master(&master,&g))
+			{
+				cleanup(workdir.s) ;
+				strerr_dief1x(111,"find master service") ;
+			}
+		}
+
+		if (!db_write_contents(&master,SS_MASTER + 1,workdir.s))
+		{
+			cleanup(workdir.s) ;
+			strerr_diefu2x(111,"update bundle: ", SS_MASTER + 1) ;
+		}
+				
+		if (!db_compile(workdir.s,info->tree.s,info->treename,envp))
+		{
+				cleanup(workdir.s) ;
+				strerr_diefu4x(111,"compile ",workdir.s,"/",info->treename) ;
+		}
+		
+		/** 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," 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) ;
+	workdir = stralloc_zero ;
+	
+	for (int i = 0 ; i < genalloc_len(stralist,&ganclassic) ; i++)
+	{
+		if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+			strerr_diefu1x(111,"set revolve pointer to source") ;
+		
+		if (resolve_read(&workdir,saresolve.s,gaistr(&ganclassic,i),"remove")) 
+			if (!resolve_remove(saresolve.s,gaistr(&ganclassic,i),"remove"))
+				strerr_diefu3sys(111,"delete resolve file",saresolve.s,"/remove") ;
+	}
+	
+	for (int i = 0 ; i < genalloc_len(stralist,&ganlong) ; i++)
+	{
+		if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+			strerr_diefu1x(111,"set revolve pointer to source") ;
+		
+		if (resolve_read(&workdir,saresolve.s,gaistr(&ganlong,i),"remove")) 
+			if (!resolve_remove(saresolve.s,gaistr(&ganlong,i),"remove"))
+				strerr_diefu3sys(111,"delete resolve file",saresolve.s,"/remove") ;
+	}
+				
+	if (start && ((nclassic) || (nlongrun)))
+	{
+		int nargc = 2 + genalloc_len(stralist,&ganclassic) + genalloc_len(stralist,&ganlong) ;
+		char const *newargv[nargc] ;
+		unsigned int m = 0 ;
+		
+		newargv[m++] = "fake_name" ;
+		/** classic */
+		for (unsigned int i = 0 ; i<genalloc_len(stralist,&ganclassic); i++)
+			newargv[m++] = gaistr(&ganclassic,i) ;
+		/** rc */
+		for (unsigned int i = 0 ; i<genalloc_len(stralist,&ganlong); i++)
+			newargv[m++] = gaistr(&ganlong,i) ;
+		
+		newargv[m++] = 0 ;
+		
+		if (ssexec_start(nargc,newargv,envp,info))
+			return 111 ;
+		
+	}
+	
+	
+	/** general allocation*/
+	freed_parser() ;
+	/** inner allocation */
+	stralloc_free(&workdir) ;
+	stralloc_free(&sasrc) ;
+	stralloc_free(&saresolve) ;
+	genalloc_free(sv_src_t,&gasrc) ;
+	genalloc_deepfree(stralist,&ganclassic,stra_free) ;
+	genalloc_deepfree(stralist,&ganlong,stra_free) ;
+	
+	/** graph stuff */
+	genalloc_free(vertex_graph_t,&g.stack) ;
+	genalloc_free(vertex_graph_t,&g.vertex) ;
+	genalloc_deepfree(stralist,&master,stra_free) ;
+	stralloc_free(&sagraph) ;
+	genalloc_deepfree(stralist,&tokeep,stra_free) ;
+	
+	return 0 ;		
+}
diff --git a/src/lib66/ssexec_free.c b/src/lib66/ssexec_free.c
new file mode 100644
index 0000000000000000000000000000000000000000..c27b993a105a07953a3e532ffa3ee5ce0abcdf20
--- /dev/null
+++ b/src/lib66/ssexec_free.c
@@ -0,0 +1,31 @@
+/* 
+ * ssexec_free.c
+ * 
+ * Copyright (c) 2018 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 <skalibs/stralloc.h>
+
+#include <66/ssexec.h>
+
+ssexec_t const ssexec_zero = SSEXEC_ZERO ; 
+
+void ssexec_free(ssexec_t *info)
+{
+	stralloc_free(&info->base) ;
+	stralloc_free(&info->live) ;
+	stralloc_free(&info->tree) ;
+	stralloc_free(&info->livetree) ;
+	stralloc_free(&info->scandir) ;
+}
+	
+
diff --git a/src/lib66/ssexec_help.c b/src/lib66/ssexec_help.c
new file mode 100644
index 0000000000000000000000000000000000000000..e756ae4eae0413c01ffa52a8cf6398afcc1d6014
--- /dev/null
+++ b/src/lib66/ssexec_help.c
@@ -0,0 +1,125 @@
+/* 
+ * ssexec_help.c
+ * 
+ * Copyright (c) 2018 Eric Vidal <eric@obarun.org>
+ * 
+ * All rights reserved.
+ * 
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <66/ssexec.h>
+
+char const *usage_enable = "66-enable [ -h help ] [ -v verbosity ] [ - l live ] [ -t tree ] [ -f ] [ -S ] service(s)" ;
+
+char const *help_enable =
+"66-enable <options> service(s)\n"
+"\n"
+"options :\n"
+"	-h: print this help\n" 
+"	-v: increase/decrease verbosity\n"
+"	-l: live directory\n"
+"	-t: name of the tree to use\n"
+"	-f: overwrite service(s)\n"
+"	-S: enable and start the service\n"
+;
+
+char const *usage_dbctl = "66-dbctl [ -h ] [ -v verbosity ] [ -T timeout ] [ -l live ] [ -t tree ] [ -u | d | r ] service(s)" ;
+
+char const *help_dbctl =
+"66-dbctl <options> tree\n"
+"\n"
+"options :\n"
+"	-h: print this help\n" 
+"	-v: increase/decrease verbosity\n"
+"	-T: timeout\n"
+"	-l: live directory\n"
+"	-t: tree to use\n"
+"	-u: bring up service in database of tree\n"
+"	-d: bring down service in database of tree\n"
+"	-r: reload service\n"
+;
+
+char const *usage_disable = "66-disable [ -h help ] [ -v verbosity ] [ - l live ] [ -t tree ] [ -S ] service(s)" ;
+
+char const *help_disable =
+"66-disable <options> service(s)\n"
+"\n"
+"options :\n"
+"	-h: print this help\n" 
+"	-v: increase/decrease verbosity\n"
+"	-l: live directory\n"
+"	-t: name of the tree to use\n"
+"	-S: disable and stop the service\n"
+;
+
+char const *usage_init = "66-init [ -h ] [ -v verbosity ] [ -l live ] [ -c | d | B ] tree" ;
+
+char const *help_init =
+"66-init <options> tree\n"
+"\n"
+"options :\n"
+"	-h: print this help\n" 
+"	-v: increase/decrease verbosity\n"
+"	-l: live directory\n" 
+"	-c: init classic service\n"
+"	-d: init database service\n"
+"	-B: init classic and database service\n"
+;
+
+char const *usage_start = "66-start [ -h ] [ -v verbosity ] [ -l live ] [ -t tree ] [ -T timeout ] [ -r | R ] service(s)" ;
+
+char const *help_start =
+"66-start <options> service(s)\n"
+"\n"
+"options :\n"
+"	-h: print this help\n" 
+"	-v: increase/decrease verbosity\n"
+"	-l: live directory\n"
+"	-t: tree to use\n"
+"	-T: timeout\n"
+"	-r: reload the service(s)\n"
+"	-R: reload service(s) file(s) and the service(s) itself\n"
+;
+
+char const *usage_stop = "66-stop [ -h ] [ -v verbosity ] [ -T timeout ] [ -l live ] [ -t tree ] [ -u ] [ -X ] [ -K ] service(s)" ;
+
+char const *help_stop =
+"66-stop <options> service(s)\n"
+"\n"
+"options :\n"
+"	-h: print this help\n" 
+"	-v: increase/decrease verbosity\n"
+"	-l: live directory\n"
+"	-T: timeout\n"
+"	-t: tree to use\n"
+"	-u: unsupervise service(s)\n"
+"	-X: bring down the service(s) and kill his supervisor\n"
+"	-K: kill the service(s) and keep it down\n"
+;
+
+char const *usage_svctl = "66-svctl [ -h ] [ -v verbosity ] [ -l live ] [ -t tree ] [ -T timeout ] [ -n death ] [ -u | U | d | D | r | R | K | X ] service(s)" ;
+
+char const *help_svctl =
+"66-svctl <options> tree\n"
+"\n"
+"options :\n"
+"	-h: print this help\n" 
+"	-v: increase/decrease verbosity\n"
+"	-l: live directory\n"
+"	-t: tree to use\n"
+"	-T: service timeout\n"
+"	-n: number of death\n"
+"	-u: bring up the service(s)\n"
+"	-U: really up\n"
+"	-d: bring down the service(s)\n"
+"	-D: really down\n"
+"	-r: reload\n"
+"	-R: reload and really up\n"
+"	-X: bring down the service(s) and the kill his supervisor\n"
+"	-K: kill the service(s) and keep it down\n"
+;
diff --git a/src/lib66/ssexec_init.c b/src/lib66/ssexec_init.c
new file mode 100644
index 0000000000000000000000000000000000000000..737ea9e0464a7f3975d8d7520bdfbc3e2f290f5e
--- /dev/null
+++ b/src/lib66/ssexec_init.c
@@ -0,0 +1,237 @@
+/* 
+ * ssexec_init.c
+ * 
+ * Copyright (c) 2018 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/stat.h>
+
+#include <oblibs/obgetopt.h>
+#include <oblibs/error2.h>
+#include <oblibs/directory.h>
+#include <oblibs/types.h>//scan_mode
+#include <oblibs/stralist.h>
+
+#include <skalibs/buffer.h>
+#include <skalibs/types.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/direntry.h>
+
+#include <s6/config.h>
+#include <s6-rc/config.h>
+#include <s6/s6-supervise.h>
+
+#include <66/utils.h>
+#include <66/enum.h>
+#include <66/constants.h>
+#include <66/tree.h>
+#include <66/backup.h>
+#include <66/db.h>
+#include <66/svc.h>
+
+//#include <stdio.h>
+
+int ssexec_init(int argc, char const *const *argv,char const *const *envp,ssexec_t *info)
+{
+	int r, db, classic, earlier ;
+	
+	int wstat ;
+	pid_t pid ;
+	
+	char const *treename = 0 ;
+	size_t treenamelen ;
+	
+	stralloc tree = STRALLOC_ZERO ;
+	stralloc saresolve = STRALLOC_ZERO ;
+	stralloc type = STRALLOC_ZERO ;
+	genalloc gasvc = GENALLOC_ZERO ; //stralist type
+	
+	svstat_t svstat = SVSTAT_ZERO ;
+	genalloc gasvstat = GENALLOC_ZERO ; //svstat_t type
+	classic = db = earlier = 0 ;
+	
+	//PROG = "66-init" ;
+	{
+		subgetopt_t l = SUBGETOPT_ZERO ;
+
+		for (;;)
+		{
+			int opt = getopt_args(argc,argv, ">cdB", &l) ;
+			if (opt == -1) break ;
+			if (opt == -2) strerr_dief1x(110,"options must be set first") ;
+			switch (opt)
+			{
+				case 'c' : classic = 1 ; break ;
+				case 'd' : db = 1 ; break ;
+				case 'B' : classic = 1 ; db = 1 ; break ;
+				default : exitusage(usage_init) ; 
+			}
+		}
+		argc -= l.ind ; argv += l.ind ;
+	}
+	
+	if (argc != 1) exitusage(usage_init) ;
+	
+	treename = *argv ;
+	treenamelen = strlen(treename) ;
+		
+	if (!stralloc_cats(&tree,treename)) retstralloc(111,"main") ;
+		
+	r = tree_sethome(&tree,info->base.s,info->owner) ;
+	if (!r) strerr_diefu2sys(111,"find tree: ", tree.s) ;
+	
+	if (!tree_get_permissions(tree.s,info->owner))
+		strerr_dief2x(110,"You're not allowed to use the tree: ",tree.s) ;
+	
+	r = scan_mode(info->scandir.s,S_IFDIR) ;
+	if (r < 0) strerr_dief2x(111,info->scandir.s," conflicted format") ;
+	if (!r) strerr_dief3x(110,"scandir: ",info->scandir.s," doesn't exist") ;
+	
+	r = scandir_ok(info->scandir.s) ;
+	if (r != 1) earlier = 1 ; 
+	
+	r = scan_mode(info->livetree.s,S_IFDIR) ;
+	if (r < 0) strerr_dief2x(111,info->livetree.s," conflicting format") ;
+	if (!r)
+	{
+		VERBO2 strerr_warni2x("create directory: ",info->livetree.s) ;
+		r = dir_create(info->livetree.s,0700) ;
+		if (!r) strerr_diefu2sys(111,"create directory: ",info->livetree.s) ;
+	}
+	
+	
+	size_t svdirlen ;
+	char svdir[tree.len + SS_SVDIRS_LEN + SS_DB_LEN + treenamelen + 1 + 1] ;
+	memcpy(svdir,tree.s,tree.len) ;
+	memcpy(svdir + tree.len ,SS_SVDIRS ,SS_SVDIRS_LEN) ;
+	svdirlen = tree.len + SS_SVDIRS_LEN ;
+	memcpy(svdir + svdirlen, SS_SVC ,SS_SVC_LEN) ;
+	svdir[svdirlen +  SS_SVC_LEN] = 0 ;
+	
+	/** svc already initiated */
+	if (classic)
+	{
+		int i ;
+		if (!dir_cmp(svdir,info->scandir.s,"",&gasvc)) strerr_diefu4x(111,"compare ",svdir," to ",info->scandir.s) ;
+		if (!earlier)
+		{
+			for (i = 0 ; i < genalloc_len(stralist,&gasvc) ; i++)
+			{
+				char *name = gaistr(&gasvc,i) ;
+				size_t namelen = gaistrlen(&gasvc,i) ;
+			
+				if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+					strerr_diefu1x(111,"set revolve pointer to source") ;
+				r = resolve_read(&type,saresolve.s,name,"type") ;
+				if (r < -1) strerr_dief2x(111,"invalid .resolve directory: ",saresolve.s) ;
+				if (r && type.len && get_enumbyid(type.s,key_enum_el) == CLASSIC)
+				{
+					svstat.down = 0 ;
+					svstat.name = name ;
+					svstat.namelen = namelen ;
+					r = resolve_read(&type,saresolve.s,name,"down") ;
+					if (r > 0) svstat.down = 1 ;
+					if (!genalloc_append(svstat_t,&gasvstat,&svstat)) strerr_diefu3x(111,"add: ",name," on genalloc") ;
+				}
+			}
+			if (genalloc_len(svstat_t,&gasvstat))
+			{
+				if (!svc_init(info->scandir.s,svdir,&gasvstat)) strerr_diefu2x(111,"initiate service of tree: ",treename) ;
+			}
+			else strerr_warni3x("svc service of tree: ",treename," already initiated") ;
+		}
+		else
+		{
+			size_t dirlen = strlen(svdir) ;
+			for (i = 0 ; i < genalloc_len(stralist,&gasvc) ; i++)
+			{
+				char *name = gaistr(&gasvc,i) ;
+				size_t namelen = gaistrlen(&gasvc,i) ;
+				char svscan[info->scandir.len + 1 + namelen + 1] ;
+				memcpy(svscan,info->scandir.s,info->scandir.len) ;
+				svscan[info->scandir.len] = '/' ;
+				memcpy(svscan + info->scandir.len + 1, name,namelen) ;
+				svscan[info->scandir.len + 1 + namelen] = 0 ;
+				char tocopy[dirlen + 1 + namelen + 1] ;
+				memcpy(tocopy,svdir,dirlen) ;
+				tocopy[dirlen] = '/' ;
+				memcpy(tocopy + dirlen + 1, name, namelen) ;
+				tocopy[dirlen + 1 + namelen] = 0 ;
+				if (!hiercopy(tocopy,svscan)) strerr_diefu4sys(111,"to copy: ",tocopy," to: ",svscan) ;
+			}
+		}
+	}
+	genalloc_deepfree(stralist,&gasvc,stra_free) ;
+	genalloc_free(svstat_t,&gasvstat) ;
+	stralloc_free(&saresolve) ;
+	stralloc_free(&type) ;
+	stralloc_free(&tree) ;
+	
+	/** db already initiated? */
+	if (db)
+	{
+		if (!earlier)
+		{
+			if (db_ok(info->livetree.s,treename))
+			{
+				strerr_warni3x(" db of tree: ",treename," already initiated") ;
+				goto end ;
+			}
+		}else strerr_dief3x(110,"scandir: ",info->scandir.s," is not running") ;
+	}else goto end ;
+	
+	{
+		char ltree[info->livetree.len + 4 + treenamelen] ;
+		memcpy(ltree,info->livetree.s,info->livetree.len) ;
+		ltree[info->livetree.len] = '/' ;
+		memcpy(ltree + info->livetree.len + 1, treename, treenamelen) ;
+		ltree[info->livetree.len + 1 + treenamelen] = 0 ;
+		
+		memcpy(svdir + svdirlen,SS_DB,SS_DB_LEN) ;
+		memcpy(svdir + svdirlen + SS_DB_LEN, "/", 1) ;
+		memcpy(svdir + svdirlen + SS_DB_LEN + 1, treename,treenamelen) ;
+		svdir[svdirlen + SS_DB_LEN + 1 + treenamelen] = 0 ;
+		
+		char prefix[treenamelen + 1 + 1] ;
+		memcpy(prefix,treename,treenamelen) ;
+		memcpy(prefix + treenamelen, "-",1) ;
+		prefix[treenamelen + 1] = 0 ;
+		
+		{
+			char const *newargv[10] ;
+			unsigned int m = 0 ;
+			
+			newargv[m++] = S6RC_BINPREFIX "s6-rc-init" ;
+			newargv[m++] = "-l" ;
+			newargv[m++] = ltree ;
+			newargv[m++] = "-c" ;
+			newargv[m++] = svdir ;
+			newargv[m++] = "-p" ;
+			newargv[m++] = prefix ;
+			newargv[m++] = "--" ;
+			newargv[m++] = info->scandir.s ;
+			newargv[m++] = 0 ;
+			
+			VERBO2 strerr_warni3x("initiate db ",svdir," ...") ;
+			
+			pid = child_spawn0(newargv[0],newargv,envp) ;
+			if (waitpid_nointr(pid,&wstat, 0) < 0)
+				strerr_diefu2sys(111,"wait for ",newargv[0]) ;
+				
+			if (wstat)
+				strerr_diefu2x(111,"init db: ",svdir) ;
+		}
+	}
+	end:	
+	return 0 ;
+}
diff --git a/src/lib66/ssexec_main.c b/src/lib66/ssexec_main.c
new file mode 100644
index 0000000000000000000000000000000000000000..fa86ebbbdc8ae07f91d563b1c1bc89d09a7ca32d
--- /dev/null
+++ b/src/lib66/ssexec_main.c
@@ -0,0 +1,125 @@
+/* 
+ * ssexec_main.c
+ * 
+ * Copyright (c) 2018 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/obgetopt.h>
+#include <oblibs/error2.h>
+#include <oblibs/string.h>
+
+#include <skalibs/buffer.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/types.h>
+
+#include <66/ssexec.h>
+#include <66/utils.h>
+#include <66/tree.h>
+
+#include <stdio.h>
+
+int set_ssinfo(ssexec_t *info)
+{
+	int r ;
+	
+	info->owner = MYUID ;
+	
+	if (!set_ownersysdir(&info->base,info->owner)) strerr_diefu1sys(111, "set owner directory") ;
+	
+	r = tree_sethome(&info->tree,info->base.s,info->owner) ;
+	if (r < 0) strerr_diefu1x(110,"find the current tree. You must use -t options") ;
+	if (!r) strerr_diefu2sys(111,"find tree: ", info->tree.s) ;
+	
+	info->treename = tree_setname(info->tree.s) ;
+	if (!info->treename) strerr_diefu1x(111,"set the tree name") ;
+	
+	if (!tree_get_permissions(info->tree.s,info->owner))
+		strerr_dief2x(110,"You're not allowed to use the tree: ",info->tree.s) ;
+	else info->treeallow = 1 ;
+
+	r = set_livedir(&info->live) ;
+	if (!r) retstralloc(111,"main") ;
+	if(r < 0) strerr_dief3x(111,"live: ",info->live.s," must be an absolute path") ;
+	
+	if (!stralloc_copy(&info->livetree,&info->live)) retstralloc(111,"main") ;
+	if (!stralloc_copy(&info->scandir,&info->live)) retstralloc(111,"main") ;
+	
+	r = set_livetree(&info->livetree,info->owner) ;
+	if (!r) retstralloc(111,"main") ;
+	if(r < 0) strerr_dief3x(111,"livetree: ",info->livetree.s," must be an absolute path") ;
+	
+	r = set_livescan(&info->scandir,info->owner) ;
+	if (!r) retstralloc(111,"main") ;
+	if(r < 0) strerr_dief3x(111,"scandir: ",info->scandir.s," must be an absolute path") ;
+	
+	return 0 ;
+}
+
+static inline void info_help (char const *help)
+{
+	if (buffer_putsflush(buffer_1, help) < 0)
+		strerr_diefu1sys(111, "write to stdout") ;
+}
+
+
+
+int ssexec_main(int argc, char const *const *argv,char const *const *envp,ssexec_func_t *func, ssexec_t *info)
+{
+	int r ;
+	int n = 0 ;
+	char const *nargv[argc + 1] ;
+	
+	nargv[n++] = "fake_name" ;
+	{
+		subgetopt_t l = SUBGETOPT_ZERO ;
+		int f = 0 ;
+		for (;;)
+		{
+			int opt = subgetopt_r(argc,argv, "hv:l:t:T:", &l) ;
+			if (opt == -1) break ;
+			switch (opt)
+			{
+				case 'h' : 	info_help(info->help); return 0 ;
+				case 'v' :  if (!uint0_scan(l.arg, &VERBOSITY)) exitusage(info->usage) ; break ;
+				case 'l' : 	if (!stralloc_cats(&info->live,l.arg)) retstralloc(111,"main") ;
+							if (!stralloc_0(&info->live)) retstralloc(111,"main") ;
+							break ;
+				case 't' : 	if(!stralloc_cats(&info->tree,l.arg)) retstralloc(111,"main") ;
+							if(!stralloc_0(&info->tree)) retstralloc(111,"main") ;
+							break ;
+				case 'T' :	if (!uint0_scan(l.arg, &info->timeout)) exitusage(info->usage) ; break ;
+				default	:	for (int i = 0 ; i < n ; i++)
+							{ 
+								if (obstr_equal(nargv[i],argv[l.ind]))
+									f = 1 ;
+							}
+							if (!f) nargv[n++] = argv[l.ind] ;  
+							f = 0 ;
+							break ;
+			}
+		}
+		argc -= l.ind ; argv += l.ind ;
+	}
+	set_ssinfo(info) ;
+	
+	for (int i = 0 ; i < argc ; i++ , argv++)
+			nargv[n++] = *argv ;
+	
+	nargv[n] = 0 ;
+	
+	r = (*func)(n,nargv,envp,info) ;
+	
+	ssexec_free(info) ;
+		
+	return r ;
+}
+	
+
diff --git a/src/lib66/ssexec_start.c b/src/lib66/ssexec_start.c
new file mode 100644
index 0000000000000000000000000000000000000000..b60386c9b682d0c26a355ecc268445f767e700d5
--- /dev/null
+++ b/src/lib66/ssexec_start.c
@@ -0,0 +1,572 @@
+/* 
+ * ssexec_start.c
+ * 
+ * Copyright (c) 2018 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/stat.h>
+#include <stdlib.h>
+
+#include <oblibs/obgetopt.h>
+#include <oblibs/error2.h>
+#include <oblibs/string.h>
+#include <oblibs/types.h>
+#include <oblibs/directory.h>
+#include <oblibs/files.h>
+#include <oblibs/stralist.h>
+
+#include <skalibs/buffer.h>
+#include <skalibs/types.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/unix-transactional.h>
+#include <skalibs/tai.h>
+
+#include <skalibs/selfpipe.h>
+#include <skalibs/iopause.h>
+#include <skalibs/sig.h>
+
+#include <s6/s6-supervise.h>//s6_svstatus_t
+#include <s6/ftrigw.h>
+#include <s6/config.h>
+
+#include <66/tree.h>
+#include <66/db.h>
+#include <66/config.h>
+#include <66/utils.h>
+#include <66/constants.h>
+#include <66/enum.h>
+#include <66/backup.h>
+#include <66/svc.h>
+#include <66/ssexec.h>
+
+//#include <stdio.h>
+
+static unsigned int RELOAD = 0 ;
+static unsigned int DEADLINE = 0 ;
+static stralloc saresolve = STRALLOC_ZERO ;
+static char *SIG = "-U" ;
+static genalloc DOWNFILE = GENALLOC_ZERO ; //stralist
+
+int svc_shutnremove(ssexec_t *info, genalloc *ga, char const *const *envp)
+{
+	int r ;
+
+	stralloc log = STRALLOC_ZERO ;
+	genalloc tot = GENALLOC_ZERO ; //stralist
+	
+	for (unsigned int i = 0 ; i < genalloc_len(svstat_t,ga) ; i++) 
+	{
+		
+		char const *svname = genalloc_s(svstat_t,ga)[i].name ;
+		
+		if (!stra_add(&tot,svname))
+		{
+			VERBO3 strerr_warnwu3x("add: ",svname," as service to shutdown") ;
+			return 0 ;
+		}
+		if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+		{
+			VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
+			return 0 ;
+		}
+		r = resolve_read(&saresolve,saresolve.s,svname,"logger") ;
+		
+		if (r) 
+		{
+			if (!stra_add(&tot,saresolve.s))
+			{
+				VERBO3 strerr_warnwu3x("add logger of: ",svname," as service to shutdown") ;
+				return 0 ;
+			}
+			
+		}
+	}	
+	
+	int nargc = 3 + genalloc_len(stralist,&tot) ;
+	char const *newargv[nargc] ;
+	unsigned int m = 0 ;
+	char fmt[UINT_FMT] ;
+	fmt[uint_fmt(fmt, VERBOSITY)] = 0 ;
+
+	newargv[m++] = "fake_name" ;
+	newargv[m++] = "-D" ;
+	
+	for (unsigned int i = 0 ; i < genalloc_len(stralist,&tot) ; i++) 
+		newargv[m++] = gaistr(&tot,i) ;
+			
+	newargv[m++] = 0 ;
+	
+	if (ssexec_svctl(nargc,newargv,envp,info))
+	{
+		VERBO3 strerr_warnwu1x("shutdown list of services") ;
+		return 0 ;
+	}
+	
+	for (unsigned int i = 0 ; i < genalloc_len(stralist,&tot) ; i++) 
+	{
+		size_t namelen = gaistrlen(&tot,i) ;
+		char const *name = gaistr(&tot,i)  ;
+		char svscan[info->scandir.len + 1 + namelen + 1] ;
+		memcpy(svscan,info->scandir.s,info->scandir.len) ;
+		svscan[info->scandir.len] = '/' ;
+		memcpy(svscan + info->scandir.len + 1,name, namelen) ;
+		svscan[info->scandir.len + 1 + namelen] = 0 ;
+		
+		VERBO3 strerr_warnt2x("delete: ", svscan) ;
+		if (rm_rf(svscan) < 0)
+		{
+			VERBO3 strerr_warnwu2sys("delete: ",svscan) ;
+			return 0 ;
+		}
+	}
+	stralloc_free(&log) ;
+	genalloc_deepfree(stralist,&tot,stra_free) ;
+	
+	return 1 ;
+}
+		
+int svc_start(ssexec_t *info,genalloc *ga,char const *const *envp)
+{	
+	genalloc tot = genalloc_zero ; //stralist
+	
+	for (unsigned int i = 0; i < genalloc_len(svstat_t,ga) ; i++)
+	{	
+		if (!stra_add(&tot,genalloc_s(svstat_t,ga)[i].name))
+		{
+			VERBO3 strerr_warnwu3x("add: ",genalloc_s(svstat_t,ga)[i].name," as service to start") ;
+			return 0 ;
+		}
+		
+		if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+		{
+			VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
+			return 0 ;
+		}
+		if (resolve_read(&saresolve,saresolve.s,genalloc_s(svstat_t,ga)[i].name,"logger"))
+		{
+			if (!stra_add(&tot,saresolve.s))
+			{
+				VERBO3 strerr_warnwu3x("add: ",saresolve.s," as service to shutdown") ;
+				return 0 ;
+			}
+		}
+	}
+	int nargc = 3 + genalloc_len(stralist,&tot) ;
+	char const *newargv[nargc] ;
+	unsigned int m = 0 ;
+	
+	newargv[m++] = "fake_name" ;
+	newargv[m++] = SIG ;
+	
+	for (unsigned int i = 0 ; i < genalloc_len(stralist,&tot) ; i++) 
+		newargv[m++] = gaistr(&tot,i) ;
+	
+	newargv[m++] = 0 ;
+
+	if (ssexec_svctl(nargc,newargv,envp,info))
+	{
+		VERBO3 strerr_warnwu1x("bring up services") ;
+		return 0 ;
+	}
+	if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+	{
+		VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
+		return 0 ;
+	}
+
+	for (unsigned int i = 0; i < genalloc_len(svstat_t,ga) ; i++)
+	{
+		if (genalloc_s(svstat_t,ga)[i].reload)
+		{
+			VERBO3 strerr_warnt2x("delete reload resolve file for: ",genalloc_s(svstat_t,ga)[i].name) ;
+			if (!resolve_remove(saresolve.s,genalloc_s(svstat_t,ga)[i].name,"reload"))
+			{
+				VERBO3 strerr_warnwu3sys("delete resolve file",saresolve.s,"/reload") ;
+				return 0 ;
+			}
+		}
+	}
+
+	return 1 ;
+}
+
+int svc_sanitize(ssexec_t *info, genalloc *ga, char const *const *envp)
+{
+	genalloc toreload = GENALLOC_ZERO ; //svstat_t
+	genalloc toinit = GENALLOC_ZERO ; //svstat_t
+	
+	for (unsigned int i = 0; i < genalloc_len(svstat_t,ga) ; i++)
+	{
+		if (genalloc_s(svstat_t,ga)[i].reload)
+		{
+			if (!genalloc_cat(svstat_t,&toreload,ga))
+			{
+				VERBO3 strerr_warnwu1x("append genalloc") ;
+				return 0 ;
+			}
+		}
+		if (genalloc_s(svstat_t,ga)[i].init)
+		{
+			if (!genalloc_cat(svstat_t,&toinit,ga))
+			{
+				VERBO3 strerr_warnwu1x("append genalloc") ;
+				return 0 ;
+			}
+		}
+	}
+	if (genalloc_len(svstat_t,&toinit))
+	{
+		if (!resolve_pointo(&saresolve,info,CLASSIC,SS_RESOLVE_SRC))		
+		{
+			VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
+			return 0 ;
+		}
+		VERBO3 strerr_warnt1x("initiate svc service list ...") ;
+		if (!svc_init(info->scandir.s, saresolve.s, &toinit))
+		{
+			VERBO3 strerr_warnwu1x("iniatiate svc service list") ;
+			return 0 ;
+		}
+	}
+	if (genalloc_len(svstat_t,&toreload))
+	{
+		VERBO3 strerr_warnt1x("shutdown service before reload it ...") ;
+		if (!svc_shutnremove(info,&toreload,envp))
+		{
+			VERBO3 strerr_warnwu1x("down list of service") ;
+			return 0 ;
+		}
+		if (!resolve_pointo(&saresolve,info,CLASSIC,SS_RESOLVE_SRC))		
+		{
+			VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
+			return 0 ;
+		}
+		VERBO3 strerr_warnt1x("initiate svc services list ...") ;
+		if (!svc_init(info->scandir.s, saresolve.s, &toreload))
+		{
+			VERBO3 strerr_warnwu1x("iniatiate svc service list") ;
+			return 0 ;
+		}
+	}
+	
+	return 1 ;
+}
+
+int rc_init(ssexec_t *info, char const *const *envp)
+{
+	int r ;
+	
+	int nargc = 4 ;
+	char const *newargv[nargc] ;
+	unsigned int m = 0 ;
+	
+	newargv[m++] = "fake_name" ;
+	newargv[m++] = "-d" ;
+	newargv[m++] = info->treename ;
+	newargv[m++] = 0 ;
+				
+	if (ssexec_init(nargc,newargv,envp,info))
+	{
+		strerr_warnwu2x("init rc services for tree: ",info->treename) ;
+		return 0 ;
+	}
+	
+	VERBO3 strerr_warnt2x("reload scandir: ",info->scandir.s) ;
+	r = s6_svc_writectl(info->scandir.s, S6_SVSCAN_CTLDIR, "an", 2) ;
+	if (r < 0)
+	{
+		VERBO3 strerr_warnw3sys("something is wrong with the ",info->scandir.s, "/" S6_SVSCAN_CTLDIR " directory. errno reported") ;
+		return 0 ;
+	}
+	
+	return 1 ;
+}
+
+int rc_sanitize(ssexec_t *info,genalloc *ga, char const *const *envp)
+{
+	genalloc toreload = GENALLOC_ZERO ; //stralist
+	
+	size_t treenamelen = strlen(info->treename) ;
+	
+	char db[info->livetree.len + 1 + treenamelen + 1] ;
+	memcpy(db,info->livetree.s,info->livetree.len) ;
+	db[info->livetree.len] = '/' ;
+	memcpy(db + info->livetree.len + 1, info->treename, treenamelen) ;
+	db[info->livetree.len + 1 + treenamelen] = 0 ;
+	
+	if (!db_ok(info->livetree.s,info->treename))
+		if (!rc_init(info,envp)) return 0 ;
+	
+		
+	for (unsigned int i = 0; i < genalloc_len(svstat_t,ga) ; i++)
+	{
+		if (genalloc_s(svstat_t,ga)[i].reload)
+		{
+			if (!stra_add(&toreload,genalloc_s(svstat_t,ga)[i].name))
+			{
+				VERBO3 strerr_warnwu3x("add: ",genalloc_s(svstat_t,ga)[i].name," as service to reload") ;
+				return 0 ;
+			}
+		}
+	}
+	if (genalloc_len(stralist,&toreload))
+	{
+		
+		if (!db_switch_to(info,envp,SS_SWBACK))
+		{
+			VERBO3 strerr_warnwu3x("switch ",info->treename," to backup") ;
+			return 0 ;
+		}
+		if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))		
+		{
+			VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
+			return 0 ;
+		}
+		if (!db_compile(saresolve.s,info->tree.s, info->treename,envp))
+		{
+			VERBO3 strerr_diefu4x(111,"compile ",saresolve.s,"/",info->treename) ;
+			return 0 ;
+		}
+		if (!db_switch_to(info,envp,SS_SWSRC))
+		{
+			VERBO3 strerr_warnwu3x("switch ",info->treename," to backup") ;
+			return 0 ;
+		}
+		
+		int nargc = 3 + genalloc_len(stralist,&toreload) ;
+		char const *newargv[nargc] ;
+		unsigned int m = 0 ;
+		
+		newargv[m++] = "fake_name" ;
+		newargv[m++] = "-d" ;
+
+		for (unsigned int i = 0; i < genalloc_len(stralist,&toreload) ; i++)
+			newargv[m++] = gaistr(&toreload,i) ;
+				
+		newargv[m++] = 0 ;
+			
+		if (ssexec_dbctl(nargc,newargv,envp,info))
+		{
+			VERBO3 strerr_warnwu1x("bring down service list") ;
+			goto err ;
+		}
+	}
+
+	return 1 ;
+	
+	err:
+		genalloc_deepfree(stralist,&toreload,stra_free) ;
+		return 0 ;
+}
+
+int rc_start(ssexec_t *info,genalloc *ga,char const *const *envp)
+{
+	if (!db_switch_to(info,envp,SS_SWSRC))
+		strerr_diefu3x(111,"switch: ",info->treename," to source") ;
+	
+	
+	int nargc = 3 + genalloc_len(svstat_t,ga) ;
+	char const *newargv[nargc] ;
+	unsigned int m = 0 ;
+	
+	newargv[m++] = "fake_name" ;
+	if (RELOAD == 1) 
+		newargv[m++] = "-r" ;
+	else
+		newargv[m++] = "-u" ;
+		
+	for (unsigned int i = 0; i < genalloc_len(svstat_t,ga) ; i++)
+		newargv[m++] = genalloc_s(svstat_t,ga)[i].name ; ;
+		
+	newargv[m++] = 0 ;
+	
+	if (ssexec_dbctl(nargc,newargv,envp,info))
+	{
+		VERBO3 strerr_warnwu1x("bring up service list") ;
+		goto err ;
+	}
+	
+	if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+	{
+		VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
+		return 0 ;
+	}
+
+	for (unsigned int i = 0; i < genalloc_len(svstat_t,ga) ; i++)
+	{
+		VERBO3 strerr_warnt2x("delete reload resolve file for: ",genalloc_s(svstat_t,ga)[i].name) ;
+		if (!resolve_remove(saresolve.s,genalloc_s(svstat_t,ga)[i].name,"reload"))
+		{
+			VERBO3 strerr_warnwu3sys("delete resolve file",saresolve.s,"/reload") ;
+			return 0 ;
+		}
+	}
+
+	return 1 ;
+	
+	err: 
+		return 0 ;
+}
+
+int ssexec_start(int argc, char const *const *argv,char const *const *envp,ssexec_t *info)
+{
+	
+	// be sure that the global var are set correctly
+	RELOAD = 0 ;
+	DEADLINE = 0 ;
+	saresolve = stralloc_zero ;
+	SIG = "-U" ;
+	DOWNFILE = genalloc_zero ; //stralist
+	
+	int r,rb ;
+	
+	stralloc svok = STRALLOC_ZERO ;
+	
+	genalloc nclassic = GENALLOC_ZERO ; //svstat_t type
+	genalloc nrc = GENALLOC_ZERO ; //svstat_t type
+	
+	//PROG = "66-start" ;
+	{
+		subgetopt_t l = SUBGETOPT_ZERO ;
+
+		for (;;)
+		{
+			int opt = getopt_args(argc,argv, ">rR", &l) ;
+			if (opt == -1) break ;
+			if (opt == -2) strerr_dief1x(110,"options must be set first") ;
+			
+			switch (opt)
+			{
+				case 'r' : 	if (RELOAD) exitusage(usage_start) ; RELOAD = 1 ; SIG = "-R" ; break ;
+				case 'R' : 	if (RELOAD) exitusage(usage_start) ; RELOAD = 2 ; SIG = "-R" ; break ;
+				default : exitusage(usage_start) ; 
+			}
+		}
+		argc -= l.ind ; argv += l.ind ;
+	}
+
+	if (argc < 1) exitusage(usage_start) ;
+	
+	if (info->timeout) DEADLINE = info->timeout ;
+	
+	if ((scandir_ok(info->scandir.s)) !=1 ) strerr_dief3sys(111,"scandir: ", info->scandir.s," is not running") ;
+	if (!stralloc_cats(&svok,info->scandir.s)) retstralloc(111,"main") ; 
+	if (!stralloc_cats(&svok,"/")) retstralloc(111,"main") ; 
+	size_t svoklen = svok.len ;
+	{
+		stralloc type = STRALLOC_ZERO ;
+		svstat_t svsrc = SVSTAT_ZERO ;
+		
+		for(;*argv;argv++)
+		{
+			
+			svsrc.type = 0 ;
+			svsrc.name = 0 ;
+			svsrc.namelen = 0 ;
+			svsrc.down = 0 ;
+			svsrc.reload = 0 ;
+			svsrc.init = 0 ;
+			svok.len = svoklen ;
+			
+			if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+				strerr_diefu1x(111,"set revolve pointer to source") ;
+			rb = resolve_read(&type,saresolve.s,*argv,"type") ;
+			if (rb < -1) strerr_dief2x(111,"invalid .resolve directory: ",saresolve.s) ;
+			if (rb < 0)
+			{
+				if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_BACK))
+					strerr_diefu1x(111,"set revolve pointer to back") ;
+				r = resolve_read(&type,saresolve.s,*argv,"type") ;
+				if (r < -1) strerr_diefu2sys(111,"invalid .resolve directory: ",saresolve.s) ; 
+				if (r > 0) strerr_dief3x(111,"orphan service: ",*argv," :you can only stop it") ;
+				if (r <= 0) strerr_dief2x(111,*argv,": is not enabled") ;
+			}
+			if (rb > 0)
+			{
+				svsrc.type = get_enumbyid(type.s,key_enum_el) ;
+				svsrc.name = *argv ;
+				svsrc.namelen = strlen(*argv) ;
+				r = resolve_read(&type,saresolve.s,*argv,"reload") ;
+				if (r < -1) strerr_diefu2sys(111,"invalid .resolve directory: ",saresolve.s) ;
+				if (r > 0) svsrc.reload = 1 ;
+				r = resolve_read(&type,saresolve.s,*argv,"down") ;
+				if (r < -1) strerr_diefu2sys(111,"invalid .resolve directory: ",saresolve.s) ;
+				if (r > 0) svsrc.down = 1 ;
+				r = resolve_read(&type,saresolve.s,*argv,"remove") ;
+				if (r > 0) strerr_dief3x(111,"service: ",*argv," was disabled, you can only stop it") ;
+			}
+			if (svsrc.type == CLASSIC)
+			{
+				
+				if (!stralloc_cats(&svok,*argv)) retstralloc(111,"main") ; 
+				if (!stralloc_0(&svok)) retstralloc(111,"main") ; 
+				r = s6_svc_ok(svok.s) ;
+				if (r < 0) strerr_diefu2sys(111,"check ", svok.s) ;
+				if (!r)	svsrc.init = 1 ;
+			}
+
+			if (RELOAD > 1) svsrc.reload = 1 ;
+			if (svsrc.init) svsrc.reload = 0 ;
+			
+			if (svsrc.type == CLASSIC)
+			{
+				if (!resolve_pointo(&saresolve,info,CLASSIC,SS_RESOLVE_SRC))
+					strerr_diefu1x(111,"set revolve pointer to source") ;
+				if (dir_search(saresolve.s,*argv,S_IFDIR) !=1) strerr_dief2x(111,*argv,": is not enabled") ;
+				if (!genalloc_append(svstat_t,&nclassic,&svsrc)) strerr_diefu3x(111,"add: ",*argv," on genalloc") ;				
+			}
+			else
+			{
+				if (!genalloc_append(svstat_t,&nrc,&svsrc)) strerr_diefu3x(111,"add: ",*argv," on genalloc") ;
+			}
+		}
+		stralloc_free(&type) ;
+		stralloc_free(&svok) ;
+	}
+
+	if (genalloc_len(svstat_t,&nclassic))
+	{
+		VERBO2 strerr_warni1x("sanitize svc services ...") ;
+		if(!svc_sanitize(info,&nclassic,envp)) 
+			strerr_diefu1x(111,"sanitize s6-svc services") ;
+		VERBO2 strerr_warni1x("start svc services ...") ;
+		if(!svc_start(info,&nclassic,envp)) 
+			strerr_diefu1x(111,"start s6-svc services") ;
+		VERBO2 strerr_warni3x("switch svc service of: ",info->treename," to source") ;
+		if (!svc_switch_to(info,SS_SWSRC))
+			strerr_diefu3x(111,"switch svc service of: ",info->treename," to source") ;
+	} 
+	if (genalloc_len(svstat_t,&nrc))
+	{
+		VERBO2 strerr_warni1x("sanitize rc services ...") ;
+		if (!rc_sanitize(info,&nrc,envp)) 
+			strerr_diefu1x(111,"sanitize s6-rc services") ;
+		VERBO2 strerr_warni1x("start rc services ...") ;
+		if (!rc_start(info,&nrc,envp)) 
+			strerr_diefu1x(111,"update s6-rc services") ;
+		VERBO2 strerr_warni3x("switch rc services of: ",info->treename," to source") ;
+		if (!db_switch_to(info,envp,SS_SWSRC))
+			strerr_diefu5x(111,"switch",info->livetree.s,"/",info->treename," to source") ;
+	}
+	
+	stralloc_free(&saresolve) ;
+	genalloc_free(svstat_t,&nclassic) ;
+	genalloc_free(svstat_t,&nrc) ;
+	genalloc_deepfree(stralist,&DOWNFILE,stra_free) ;
+	
+	return 0 ;		
+}
+
+	
+
diff --git a/src/lib66/ssexec_stop.c b/src/lib66/ssexec_stop.c
new file mode 100644
index 0000000000000000000000000000000000000000..ed3413833e67b6fc94aa56d090fb1d59cd194e87
--- /dev/null
+++ b/src/lib66/ssexec_stop.c
@@ -0,0 +1,485 @@
+/* 
+ * ssexec_stop.c
+ * 
+ * Copyright (c) 2018 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/stat.h>
+#include <stdlib.h>
+
+#include <oblibs/obgetopt.h>
+#include <oblibs/error2.h>
+#include <oblibs/string.h>
+#include <oblibs/types.h>
+#include <oblibs/directory.h>
+#include <oblibs/stralist.h>
+
+#include <skalibs/buffer.h>
+#include <skalibs/types.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/unix-transactional.h>
+#include <skalibs/selfpipe.h>
+#include <skalibs/sig.h>
+
+#include <s6/s6-supervise.h>//s6_svc_ok
+#include <s6/config.h>
+
+
+#include <66/tree.h>
+#include <66/db.h>
+#include <66/config.h>
+#include <66/utils.h>
+#include <66/constants.h>
+#include <66/enum.h>
+#include <66/svc.h>
+#include <66/backup.h>
+#include <66/ssexec.h>
+
+#include <stdio.h>
+
+
+static unsigned int DEADLINE = 0 ;
+static unsigned int UNSUP = 0 ;
+static char *SIG = "-D" ;
+static stralloc saresolve = STRALLOC_ZERO ;
+genalloc gatoremove = GENALLOC_ZERO ;//stralist
+genalloc gaunsup = GENALLOC_ZERO ; //stralist
+
+int svc_release(ssexec_t *info)
+{
+	if (genalloc_len(stralist,&gaunsup))
+	{
+		for (unsigned int i = 0; i < genalloc_len(stralist,&gaunsup); i++)
+		{
+			char const *svname = gaistr(&gaunsup,i) ;
+			size_t svnamelen = gaistrlen(&gaunsup,i) ;
+	
+			char rm[info->scandir.len + 1 + svnamelen + 1] ;
+			memcpy(rm,info->scandir.s,info->scandir.len) ;
+			rm[info->scandir.len] = '/' ;
+			memcpy(rm + info->scandir.len + 1, svname,svnamelen) ;
+			rm[info->scandir.len + 1 + svnamelen] = 0 ;
+			VERBO3 strerr_warnt2x("unsupervise: ",rm) ;
+			if (rm_rf(rm) < 0)
+			{
+				VERBO3 strerr_warnwu2sys("delete directory: ",rm) ;
+				return 0 ;
+			}
+		}
+	}
+	
+	if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+	{
+		VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
+		return 0 ;
+	}
+	
+	if (genalloc_len(stralist,&gatoremove))
+	{
+		for (unsigned int i = 0; i < genalloc_len(stralist,&gatoremove); i++)
+		{
+			char const *svname = gaistr(&gatoremove,i) ;
+			
+			if (!resolve_remove_service(saresolve.s,svname))
+			{
+				VERBO3 strerr_warnwu4sys("delete resolve service file: ",saresolve.s,"/.resolve/",svname) ;
+				return 0 ;
+			}
+		}
+	}
+	
+	return 1 ;
+}
+
+int svc_down(ssexec_t *info,genalloc *ga,char const *const *envp)
+{
+	genalloc tot = GENALLOC_ZERO ; //stralist
+		
+	for (unsigned int i = 0 ; i < genalloc_len(svstat_t,ga) ; i++) 
+	{
+		char const *svname = genalloc_s(svstat_t,ga)[i].name ;
+		int torm = genalloc_s(svstat_t,ga)[i].remove ;
+		int unsup = genalloc_s(svstat_t,ga)[i].unsupervise ;
+		
+		if (!stra_add(&tot,svname))
+		{
+			VERBO3 strerr_warnwu3x("add: ",svname," as service to shutdown") ;
+			return 0 ;
+		}
+		
+		/** need to remove?*/
+		if (torm)
+		{
+			if (!stra_add(&gatoremove,svname))
+			{
+				VERBO3 strerr_warnwu3x("add: ",svname," as service to delete") ;
+				return 0 ;
+			}
+		}
+		/** unsupervise */
+		if (unsup)
+		{
+			if (!stra_add(&gaunsup,svname))
+			{
+				VERBO3 strerr_warnwu3x("add: ",svname," as service to unsupervise") ;
+				return 0 ;
+			}
+		}
+		/** logger */
+		if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+		{
+			VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
+			return 0 ;
+		}
+		if (resolve_read(&saresolve,saresolve.s,svname,"logger"))
+		{
+			if (!stra_add(&tot,saresolve.s))
+			{
+				VERBO3 strerr_warnwu3x("add: ",saresolve.s," as service to shutdown") ;
+				return 0 ;
+			}
+			if (torm)
+			{
+				if (!stra_add(&gatoremove,saresolve.s))
+				{
+					VERBO3 strerr_warnwu3x("add logger of: ",saresolve.s," as service to delete") ;
+					return 0 ;
+				}
+			}
+			if (unsup)
+			{
+				if (!stra_add(&gaunsup,svname))
+				{
+					VERBO3 strerr_warnwu3x("add: ",saresolve.s," as service to unsupervise") ;
+					return 0 ;
+				}
+			}
+		}
+	}
+	int nargc = 3 + genalloc_len(stralist,&tot) ;
+	char const *newargv[nargc] ;
+	unsigned int m = 0 ;
+
+	newargv[m++] = "fake_name" ;
+	newargv[m++] = SIG ;
+	for (unsigned int i = 0 ; i < genalloc_len(stralist,&tot) ; i++) 
+		newargv[m++] = gaistr(&tot,i) ;
+	
+	newargv[m++] = 0 ;
+	
+	if (ssexec_svctl(nargc,newargv,envp,info))
+	{
+		VERBO3 strerr_warnwu1x("shutdown list of services") ;
+		return 0 ;
+	}
+		
+	if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+	{
+		VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
+		return 0 ;
+	}
+	for (unsigned int i = 0; i < genalloc_len(svstat_t,ga) ; i++)
+	{
+		VERBO3 strerr_warnt2x("delete remove resolve file for: ",genalloc_s(svstat_t,ga)[i].name) ;
+		if (!resolve_remove(saresolve.s,genalloc_s(svstat_t,ga)[i].name,"remove"))
+		{
+			VERBO3 strerr_warnwu3sys("delete resolve file",saresolve.s,"/remove") ;
+			return 0 ;
+		}
+	}
+	
+	genalloc_deepfree(stralist,&tot,stra_free) ;
+	
+	return 1 ;
+	
+}
+int rc_release(ssexec_t *info)
+{
+
+	if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+	{
+		VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
+		return 0 ;
+	}
+	if (genalloc_len(stralist,&gatoremove))
+	{
+		for (unsigned int i = 0; i < genalloc_len(stralist,&gatoremove); i++)
+		{
+			char const *svname = gaistr(&gatoremove,i) ;
+			
+			if (!resolve_remove_service(saresolve.s,svname))
+			{
+				VERBO3 strerr_warnwu4sys("delete resolve service file: ",saresolve.s,"/.resolve/",svname) ;
+				return 0 ;
+			}
+		}
+	}
+	
+	return 1 ;
+}
+
+int rc_down(ssexec_t *info,genalloc *ga,char const *const *envp)
+{
+	size_t treenamelen = strlen(info->treename) ;
+	
+	genalloc tot = GENALLOC_ZERO ; //stralist
+
+	for (unsigned int i = 0 ; i < genalloc_len(svstat_t,ga) ; i++) 
+	{
+		
+		char const *svname = genalloc_s(svstat_t,ga)[i].name ;
+		int torm = genalloc_s(svstat_t,ga)[i].remove ;
+		
+		if (!stra_add(&tot,svname))
+		{
+			VERBO3 strerr_warnwu3x("add: ",svname," as service to shutdown") ;
+			return 0 ;
+		}
+		
+		/** need to remove?*/
+		if (torm)
+		{
+			if (!stra_add(&gatoremove,svname))
+			{
+				VERBO3 strerr_warnwu3x("add: ",svname," as service to delete") ;
+				return 0 ;
+			}
+		}
+		/** logger */
+		if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+		{
+			VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
+			return 0 ;
+		}
+		if (resolve_read(&saresolve,saresolve.s,svname,"logger"))
+		{
+			if (!stra_add(&tot,saresolve.s))
+			{
+				VERBO3 strerr_warnwu3x("add: ",saresolve.s," as service to shutdown") ;
+				return 0 ;
+			}
+			if (torm)
+			{
+				if (!stra_add(&gatoremove,saresolve.s))
+				{
+					VERBO3 strerr_warnwu3x("add logger of: ",saresolve.s," as service to delete") ;
+					return 0 ;
+				}
+			}
+		}
+	}
+	
+	char db[info->livetree.len + 1 + treenamelen + 1] ;
+	memcpy(db,info->livetree.s,info->livetree.len) ;
+	db[info->livetree.len] = '/' ;
+	memcpy(db + info->livetree.len + 1, info->treename, treenamelen) ;
+	db[info->livetree.len + 1 + treenamelen] = 0 ;
+	
+	if (!db_ok(info->livetree.s, info->treename))
+		strerr_dief2x(111,db," is not initialized") ;
+		
+	int nargc = 3 + genalloc_len(stralist,&tot) ;
+	char const *newargv[nargc] ;
+	unsigned int m = 0 ;
+	
+	newargv[m++] = "fake_name" ;
+	newargv[m++] = "-d" ;
+	
+	for (unsigned int i = 0; i < genalloc_len(stralist,&tot) ; i++)
+			newargv[m++] = gaistr(&tot,i) ;
+		
+	newargv[m++] = 0 ;
+	
+	if (ssexec_dbctl(nargc,newargv,envp,info))
+	{
+		VERBO3 strerr_warnwu1x("bring down service list") ;
+		return 0 ;
+	}
+	
+	if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+	{
+		VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
+		return 0 ;
+	}
+	for (unsigned int i = 0; i < genalloc_len(svstat_t,ga) ; i++)
+	{
+		VERBO3 strerr_warnt2x("delete remove resolve file for: ",genalloc_s(svstat_t,ga)[i].name) ;
+		if (!resolve_remove(saresolve.s,genalloc_s(svstat_t,ga)[i].name,"remove"))
+		{
+			VERBO3 strerr_warnwu3sys("delete resolve file",saresolve.s,"/remove") ;
+			return 0 ;
+		}
+	}
+
+	genalloc_deepfree(stralist,&tot,stra_free) ;
+	
+	return 1 ;
+}
+
+int ssexec_stop(int argc, char const *const *argv,char const *const *envp,ssexec_t *info)
+{
+	// be sure that the global var are set correctly
+	DEADLINE = 0 ;
+	UNSUP = 0 ;
+	SIG = "-D" ;
+	saresolve = stralloc_zero ;
+	gatoremove = genalloc_zero ;//stralist
+	gaunsup = genalloc_zero ; //stralist
+
+	int r, rb, sigopt ;
+		
+	stralloc svok = STRALLOC_ZERO ;
+	
+	genalloc nclassic = GENALLOC_ZERO ;
+	genalloc nrc = GENALLOC_ZERO ;
+	
+	sigopt = 0 ;
+	
+	//PROG = "66-stop" ;
+	{
+		subgetopt_t l = SUBGETOPT_ZERO ;
+
+		for (;;)
+		{
+			int opt = getopt_args(argc,argv, ">uXK", &l) ;
+			if (opt == -1) break ;
+			if (opt == -2) strerr_dief1x(110,"options must be set first") ;
+
+			switch (opt)
+			{
+				case 'u' :	UNSUP = 1 ; break ;
+				case 'X' :	if (sigopt) exitusage(usage_stop) ; sigopt = 1 ; SIG = "-X" ; break ;
+				case 'K' :	if (sigopt) exitusage(usage_stop) ; sigopt = 1 ; SIG = "-K" ; break ;
+				default : exitusage(usage_stop) ; 
+			}
+		}
+		argc -= l.ind ; argv += l.ind ;
+	}
+	
+	if (argc < 1) exitusage(usage_stop) ;
+	
+	if (info->timeout) DEADLINE = info->timeout ;
+	
+	if ((scandir_ok(info->scandir.s)) !=1 ) strerr_dief3sys(111,"scandir: ", info->scandir.s," is not running") ;
+	
+	if (!stralloc_catb(&svok,info->scandir.s,info->scandir.len)) retstralloc(111,"main") ; 
+	if (!stralloc_cats(&svok,"/")) retstralloc(111,"main") ; 
+	size_t svoklen = svok.len ;
+	
+	{
+		stralloc type = STRALLOC_ZERO ;
+		svstat_t svsrc = SVSTAT_ZERO ;
+		
+		for(;*argv;argv++)
+		{
+			svsrc.type = 0 ;
+			svsrc.name = 0 ;
+			svsrc.namelen = 0 ;
+			svsrc.remove = 0 ;
+			svsrc.unsupervise = 0 ;
+			svok.len = svoklen ;
+			
+			if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+				strerr_diefu1x(111,"set revolve pointer to source") ;
+			rb = resolve_read(&type,saresolve.s,*argv,"type") ;
+			if (rb < -1) strerr_dief2x(111,"invalid .resolve directory: ",saresolve.s) ;
+			if (rb < 0)
+			{
+				if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_BACK))
+					strerr_diefu1x(111,"set revolve pointer to backup") ;
+				r = resolve_read(&type,saresolve.s,*argv,"type") ;
+				if (r < -1) strerr_diefu2sys(111,"invalid .resolve directory: ",saresolve.s) ; 
+				if (r > 0) svsrc.remove = 1 ;
+				if (r <= 0) strerr_dief2x(111,*argv,": is not enabled") ;
+			}
+			if (rb > 0)
+			{
+				svsrc.type = get_enumbyid(type.s,key_enum_el) ;
+				svsrc.name = *argv ;
+				svsrc.namelen = strlen(*argv) ;
+				r = resolve_read(&type,saresolve.s,*argv,"remove") ;
+				if (r < -1) strerr_diefu2sys(111,"invalid .resolve directory: ",saresolve.s) ;
+				if (r > 0) svsrc.remove = 1 ;
+			/*	if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_BACK))
+					strerr_diefu1x(111,"set revolve pointer to backup") ;
+				r = resolve_read(&type,saresolve.s,*argv,"type") ;
+				if (r <= 0 && !UNSUP) strerr_dief3x(111,"service: ",*argv," is not running, you can only start it") ;*/
+			}
+			if (svsrc.type == CLASSIC)
+			{
+				if (!stralloc_cats(&svok,*argv)) retstralloc(111,"main") ; 
+				if (!stralloc_0(&svok)) retstralloc(111,"main") ; 
+				r = s6_svc_ok(svok.s) ;
+				if (r < 0) strerr_diefu2sys(111,"check ", svok.s) ;
+				//if (!r)	svsrc.remove = 1 ;
+				if (!r) strerr_dief3x(111,"service: ",*argv," is not running, you can only start it") ;
+			}
+			
+			if (UNSUP) svsrc.unsupervise = 1 ;
+			if (svsrc.remove) svsrc.unsupervise = 1 ;
+			
+			if (svsrc.type == CLASSIC)
+			{
+				if (!genalloc_append(svstat_t,&nclassic,&svsrc)) strerr_diefu3x(111,"add: ",*argv," on genalloc") ;				
+			}
+			else
+			{
+				if (!genalloc_append(svstat_t,&nrc,&svsrc)) strerr_diefu3x(111,"add: ",*argv," on genalloc") ;
+			}
+		}
+		stralloc_free(&type) ;
+		stralloc_free(&svok) ;
+	}
+	
+	/** rc work */
+	if (genalloc_len(svstat_t,&nrc))
+	{
+		VERBO2 strerr_warni1x("stop rc services ...") ;
+		if (!rc_down(info,&nrc,envp))
+			strerr_diefu1x(111,"update rc services") ;
+		VERBO2 strerr_warni1x("release rc services ...") ;
+		if (!rc_release(info))
+			strerr_diefu1x(111,"release rc services") ;
+		VERBO2 strerr_warni3x("switch rc services of: ",info->treename," to source") ;
+		if (!db_switch_to(info,envp,SS_SWSRC))
+			strerr_diefu5x(111,"switch",info->livetree.s,"/",info->treename," to source") ;
+	}
+	
+	/** svc work */
+	if (genalloc_len(svstat_t,&nclassic))
+	{
+		VERBO2 strerr_warni1x("stop svc services ...") ;
+		if (!svc_down(info,&nclassic,envp))
+			strerr_diefu1x(111,"update svc services") ;
+		VERBO2 strerr_warni1x("release svc services ...") ;
+		if (!svc_release(info))
+			strerr_diefu1x(111,"release svc services ...") ;
+		VERBO2 strerr_warni3x("switch svc services of: ",info->treename," to source") ;
+		if (!svc_switch_to(info,SS_SWSRC))
+			strerr_diefu3x(111,"switch svc service of: ",info->treename," to source") ;
+		
+	}
+		
+	if (UNSUP || genalloc_len(stralist,&gatoremove))
+	{
+		VERBO2 strerr_warnt2x("send signal -an to scandir: ",info->scandir.s) ;
+		if (scandir_send_signal(info->scandir.s,"an") <= 0)
+			strerr_diefu2sys(111,"send signal to scandir: ", info->scandir.s) ;
+	}
+	
+	genalloc_free(svstat_t,&nrc) ;
+	genalloc_free(svstat_t,&nclassic) ;
+	
+	return 0 ;		
+}
diff --git a/src/lib66/ssexec_svctl.c b/src/lib66/ssexec_svctl.c
new file mode 100644
index 0000000000000000000000000000000000000000..bb48f3ef0d524b415ee9b7ba838b6564af3e1f9e
--- /dev/null
+++ b/src/lib66/ssexec_svctl.c
@@ -0,0 +1,538 @@
+/* 
+ * ssexec_svctl.c
+ * 
+ * Copyright (c) 2018 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 <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <oblibs/obgetopt.h>
+#include <oblibs/error2.h>
+#include <oblibs/types.h>
+#include <oblibs/string.h>
+#include <oblibs/stralist.h>
+
+#include <skalibs/buffer.h>
+#include <skalibs/types.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/genalloc.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/selfpipe.h>
+#include <skalibs/iopause.h>
+#include <skalibs/sig.h>
+
+#include <s6/s6-supervise.h>//s6_svstatus_t
+#include <s6/ftrigr.h>
+
+#include <66/svc.h>
+#include <66/constants.h>
+#include <66/utils.h>
+#include <66/tree.h>
+#include <66/ssexec.h>
+
+//#include <stdio.h>
+
+
+static stralloc svkeep = STRALLOC_ZERO ;
+static genalloc gakeep = GENALLOC_ZERO ; //type svc_sig_s
+static stralloc saresolve = STRALLOC_ZERO ;
+
+unsigned int SV_DEADLINE = 3000 ;
+unsigned int DEATHSV = 10 ;
+
+
+static int read_file (char const *file, char *buf, size_t n)
+{
+	ssize_t r = openreadnclose_nb(file, buf, n) ;
+	if (r < 0)
+	{
+		if (errno != ENOENT) VERBO3 strerr_warnwu2sys("open: ", file) ;
+		return 0 ;
+	}
+	buf[byte_chr(buf, r, '\n')] = 0 ;
+	return 1 ;
+}
+
+static int read_uint (char const *file, unsigned int *fd)
+{
+	char buf[UINT_FMT + 1] ;
+	if (!read_file(file, buf, UINT_FMT)) return 0 ;
+	if (!uint0_scan(buf, fd))
+	{
+		VERBO3 strerr_warnw2x("invalid: ", file) ;
+		return 0 ;
+	}
+	return 1 ;
+}
+
+/** @Return 0 on fail
+ * @Return 1 on success */
+int handle_signal_svc(svc_sig *sv_signal)
+{
+	s6_svstatus_t status = S6_SVSTATUS_ZERO ;
+	char *sv = svkeep.s + sv_signal->scan ;
+	if (!s6_svstatus_read(sv,&status))
+	{ 
+		VERBO3 strerr_warnwu2sys("read status of: ",sv) ;
+		return 0 ;
+	}
+	
+	int exitcode, exitstatus ;
+	exitcode = WIFEXITED(status.wstat) ;
+	exitstatus = WEXITSTATUS(status.wstat) ;
+	if (exitcode && exitstatus <= 1) return 1 ;
+	else return 0 ;
+}
+
+
+static unsigned char const actions[9][9] = 
+{
+ //signal receive:
+ //  c->u		U		r/u		R/U		d		D		x		O		s						
+																				//signal wanted
+    { GOTIT,	DONE,	GOTIT,	DONE,	DEAD,	DEAD,	PERM,	PERM,	UKNOW },// SIGUP 
+    { WAIT,		GOTIT,	WAIT,	GOTIT,	DEAD,	DEAD,	PERM,	PERM,	UKNOW },// SIGRUP
+    { GOTIT,	DONE,	GOTIT,	DONE,	WAIT,	WAIT,	PERM,	PERM,	UKNOW },// SIGR
+    { WAIT,		GOTIT,	WAIT,	GOTIT,	WAIT,	WAIT,	PERM,	PERM,	UKNOW },// SIGRR
+    { DEAD,		DEAD,	DEAD,	DEAD,	GOTIT,	DONE,	PERM,	PERM,	UKNOW },// SIGDOWN
+    { DEAD,		DEAD,	DEAD,	DEAD,	WAIT,	GOTIT,	PERM,	PERM,	UKNOW },// SIGRDOWN
+    { DEAD,		DEAD,	DEAD,	DEAD,	WAIT,	WAIT,	GOTIT,	WAIT, 	UKNOW },// SIGX
+    { WAIT,		WAIT,	WAIT,	WAIT,	WAIT,	WAIT,	PERM,	GOTIT, 	UKNOW },// SIGO
+    { UKNOW,	UKNOW,	UKNOW,	UKNOW,	UKNOW,	UKNOW,	UKNOW,	UKNOW, 	DONE },	// SIGSUP
+    
+} ;
+//	convert signal receive into enum number
+static const uint8_t chtenum[128] = 
+{	
+	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //8
+	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //16
+	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //24
+	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //32
+	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //40
+	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //48
+	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //56
+	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //64
+	0 ,  0 ,  0 ,  0 ,  5 ,  0 ,  0 ,  0 , //72
+	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  7 , //80
+	0 ,  0 ,  0 ,  0 ,  0 ,  1,   0 ,  0 , //88
+	6 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //96
+	0 ,  0 ,  0 ,  0 ,  4 ,  0 ,  0 ,  0 , //104
+	0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , //112
+	0 ,  0 ,  0 ,  8 ,  0 ,  0 ,  0 ,  0 , //120
+	6 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0   //128
+} ;
+/** we use three file more than s6-svc program :
+ * 	 
+ *	 timeout-up and timeout-down will define the deadline for the iopause
+ * 		each service contain his deadline into the sv_signal.deadline key.
+ * 		If thoses files doesn't exit 3000 millisec is set by default.
+ * 		This deadline value can be set on commandline by the -T options.
+ *	 max-death-tally
+ * 		We let s6-supervise make what it need to do with this file but
+ * 		we take the same number to set the sv_signal.death value
+ * 		accepted for every daemon before exiting if the SIGNAL is not reached.
+ * 		If this file doesn't exist a number of 3 death (death -> number 
+ * 		of wrong signal received) is set by default.
+ * 		This ndeath value can be set on commandline by the -n options.
+ *
+ * In all case the loop is broken to avoids infinite iopause 
+ * 
+ * The notication-fd file is used as the original one. If the file 
+ * doesn't exist and the SIGNAL is U , we change SIGNAL to u and warn
+ * the user about it.
+ *
+ * In the send_svc function a reached timeout is not an absolute error
+ * because we can have a notification-file in the servicedirs of the
+ * service with a deamon which doesn't support readiness notification. 
+ * In this case, we send U and only receive u as event, the daemon is
+ * running but not notified by the daemon itself.
+ * We accept this case as an "half" success. We exit with success but
+ * the user is warned about the state. */
+ 	
+/**@Return 0 on success
+ * @Return 1 on if signal is not complete (e.g. want U receive only u)
+ * @Return 2 on fail
+ * @Return 3 for PERMANENT failure */
+
+int handle_case(char c, svc_sig *sv_signal)
+{
+	int p, h, err ;
+	unsigned int state ;
+	state = sv_signal->sig ;
+	err = 2 ;
+	
+	p = chtenum[(unsigned char)c] ;
+	
+	unsigned char action = actions[state][p] ;
+	
+	switch (action)
+	{
+		case GOTIT:
+					h = handle_signal_svc(sv_signal) ;
+					
+					if (!h)
+					{
+						err = 1 ;
+						break ;
+					}
+					err = 0 ;
+					break ;
+		case WAIT:
+					err = 1 ;
+					break ;
+		case DEAD:
+					err = 2 ;
+					break ;
+		case DONE:
+					err = 0 ;
+					break ;
+		case PERM:
+					err = 3 ;
+					break ;
+		case UKNOW:
+		default:
+					VERBO3 strerr_warnw1x("invalid state, make a bug report");
+					err = 2 ;
+					break ;
+	}
+	
+	return err ;
+}
+
+static int handle_signal_pipe(svc_sig *svc)
+{
+	char *sv = svkeep.s + svc->scan ;
+	for (;;)
+	{
+		switch (selfpipe_read())
+		{
+			case -1 : strerr_warnwu1sys("selfpipe_read") ; return 0 ;
+			case 0 : return 1 ;
+			case SIGTERM: 		
+			case SIGINT: 		
+					// TODO, little ugly for me
+					VERBO2 strerr_warnw1x("received SIGINT, aborting service transition") ;
+					if (svc->sig <= SIGRR)
+						s6_svc_writectl(sv, S6_SUPERVISE_CTLDIR, "d", 1) ;
+					return 0 ;
+			default : strerr_warn1x("unexpected data in selfpipe") ; return 0 ;
+		}
+	}
+}
+static void announce(svc_sig *sv_signal)
+{
+
+	int r = sv_signal->state ;
+	char *sv = svkeep.s + sv_signal->scan ;
+	if (r == 3) { VERBO2 strerr_warnw3x(sv," report permanent failure to bring ",(sv_signal->sig > 1) ? "down" : "up") ; }
+	else if (r == 2) { VERBO2 strerr_warnwu3x("bring ", (sv_signal->sig > 3) ? "down " : "up ", sv) ; }
+	else if (r == 1) { VERBO2 strerr_warni4x(sv," is ",(sv_signal->sig > 3) ? "down" : "up"," but not notified by the daemon itself") ; }
+	else if (!r) { VERBO2 strerr_warni4x(sv,": ",(sv_signal->sig > 3) ? "stopped" : "started"," successfully") ; }
+}
+
+int svc_listen(genalloc *gasv, ftrigr_t *fifo,int spfd,svc_sig *svc)
+{
+	int r ;
+	iopause_fd x[2] = { { .fd = ftrigr_fd(fifo), .events = IOPAUSE_READ } , { .fd = spfd, .events = IOPAUSE_READ, .revents = 0 } } ;
+		
+	tain_t t ;
+	tain_now_g() ;
+	tain_add_g(&t,&svc->deadline) ;
+	
+	VERBO3 strerr_warnt2x("start iopause for: ",svkeep.s + svc->name) ;
+	
+	for(;;)
+	{
+		char receive ;
+		r = ftrigr_check(fifo,svc->ids, &receive) ;
+		if (r < 0) { VERBO3 strerr_warnwu1sys("ftrigr_check") ; return 0 ; } 
+		if (r)
+		{
+			svc->state = handle_case(receive, svc) ;
+			if (svc->state < 0) return 0 ;
+			if (!svc->state){ announce(svc) ; break ; }
+			else if (svc->state > 2){ announce(svc) ; break ; }
+		}
+		if (!(svc->ndeath))
+		{
+			VERBO2 strerr_warnw2x("number of try exceeded for: ",svkeep.s + svc->scan) ;
+			announce(svc) ;
+			break ;
+		}
+		
+		r = iopause_g(x, 2, &t) ;
+		if (r < 0){ VERBO3 strerr_warnwu1sys("iopause") ; return 0 ; }
+		/** timeout is not a error , the iopause process did right */
+		else if (!r) { VERBO3 strerr_warnt2x("timed out reached for: ",svkeep.s + svc->name) ; announce(svc) ; break ; } 
+		
+		if (x[1].revents & IOPAUSE_READ) return handle_signal_pipe(svc) ? 1 : 0 ;
+				
+		if (x[0].revents & IOPAUSE_READ)  
+		{	
+			if (ftrigr_update(fifo) < 0){ VERBO3 strerr_warnwu1sys("ftrigr_update") ; return 0 ; }
+			svc->ndeath--;
+		}
+	}
+
+	return 1 ;
+}
+
+int ssexec_svctl(int argc, char const *const *argv,char const *const *envp,ssexec_t *info)
+{
+	
+	// be sure that the global var are set correctly
+	svkeep = stralloc_zero ;
+	gakeep = genalloc_zero ; //type svc_sig_s
+	saresolve = stralloc_zero ;
+	SV_DEADLINE = 3000 ;
+	DEATHSV = 10 ;
+	
+	int r, e, isup ;
+	unsigned int death, tsv ;
+	int SIGNAL = -1 ;
+	
+	svc_sig sv_signal = SVC_SIG_ZERO ;
+	
+	char *sig = 0 ;
+	
+	ftrigr_t fifo = FTRIGR_ZERO ;
+	s6_svstatus_t status = S6_SVSTATUS_ZERO ;
+	
+	tsv = death = 0 ;
+	
+	//PROG = "66-svctl" ;
+	{
+		subgetopt_t l = SUBGETOPT_ZERO ;
+
+		for (;;)
+		{
+			int opt = getopt_args(argc,argv, "n:udUDXrRK", &l) ;
+			if (opt == -1) break ;
+			if (opt == -2) strerr_dief1x(110,"options must be set first") ;
+			switch (opt)
+			{
+				case 'n' :	if (!uint0_scan(l.arg, &death)) exitusage(usage_svctl) ; break ;
+				case 'u' :	if (SIGNAL > 0) exitusage(usage_svctl) ; SIGNAL = SIGUP ; sig ="u" ; break ;
+				case 'U' :	if (SIGNAL > 0) exitusage(usage_svctl) ; SIGNAL = SIGRUP ; sig = "u" ; break ;
+				case 'd' : 	if (SIGNAL > 0) ; SIGNAL = SIGDOWN ; sig = "d" ; break ;
+				case 'D' :	if (SIGNAL > 0) ; SIGNAL = SIGRDOWN ; sig = "d" ; break ;
+				case 'r' :	if (SIGNAL > 0) ; SIGNAL = SIGR ; sig = "r" ; break ;
+				case 'R' :	if (SIGNAL > 0) ; SIGNAL = SIGRR ; sig = "r" ; break ;
+				case 'X' :	if (SIGNAL > 0) ; SIGNAL = SIGX ; sig = "dx" ; break ;
+				case 'K' :	if (SIGNAL > 0) ; SIGNAL = SIGRDOWN ; sig = "kd" ; break ;
+				
+				default : exitusage(usage_svctl) ; 
+			}
+		}
+		argc -= l.ind ; argv += l.ind ;
+	}
+	
+	if (argc < 1 || (SIGNAL < 0)) exitusage(usage_svctl) ;
+	
+	if (info->timeout) tsv = info->timeout ;
+	
+		
+	if ((scandir_ok(info->scandir.s)) !=1 ) strerr_dief3sys(111,"scandir: ", info->scandir.s," is not running") ;
+	
+
+	for(;*argv;argv++)
+	{
+		char const *svname = *argv ;
+		size_t namelen = strlen(*argv) ;
+		size_t srclen ;
+		char src[info->tree.len + SS_SVDIRS_LEN + SS_SVC_LEN + 1 + namelen + 16 + 1] ;
+		memcpy(src,info->tree.s,info->tree.len) ;
+		memcpy(src + info->tree.len,SS_SVDIRS, SS_SVDIRS_LEN) ;
+		memcpy(src + info->tree.len + SS_SVDIRS_LEN, SS_SVC, SS_SVC_LEN) ;
+		src[info->tree.len + SS_SVDIRS_LEN + SS_SVC_LEN] = '/' ;
+		memcpy(src + info->tree.len + SS_SVDIRS_LEN + SS_SVC_LEN + 1,*argv,namelen) ;
+		src[info->tree.len + SS_SVDIRS_LEN + SS_SVC_LEN + 1 + namelen ] = 0 ;
+		srclen = info->tree.len + SS_SVDIRS_LEN + SS_SVC_LEN + 1 + namelen ;
+		
+		size_t svoklen ;
+		char svok[info->scandir.len + 1 + namelen + 1] ;
+		memcpy(svok,info->scandir.s,info->scandir.len) ;
+		svok[info->scandir.len] = '/' ;
+		memcpy(svok + info->scandir.len + 1 ,svname,namelen + 1) ;
+		svoklen = info->scandir.len + 1 + namelen ;
+					
+		/** do not check the logger*/
+		if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
+		{
+			VERBO3 strerr_warnwu1x("set revolve pointer to source") ;
+			return 0 ;
+		}
+		if (resolve_read(&saresolve,saresolve.s,svname,"logger"))
+		{
+			if (str_diff(saresolve.s,svname))//0 mean equal
+			{
+				r = s6_svc_ok(svok) ;
+				if (r < 0) strerr_diefu2sys(111,"check ", svok) ;
+				if (!r)	strerr_dief2x(110,svok," is not initialized") ;
+			}
+		}
+		
+		if (!s6_svstatus_read(svok,&status)) strerr_diefu2sys(111,"read status of: ",svok) ;
+		isup = status.pid && !status.flagfinishing ;
+			
+		if (isup && (SIGNAL <= SIGRUP))
+		{
+			VERBO2 strerr_warni2x(svok,": already up") ;
+			continue ;
+		}
+		else if (!isup && (SIGNAL >= SIGDOWN))
+		{
+			VERBO2 strerr_warni2x(svok,": already down") ;
+			continue ;
+		}
+		
+		sv_signal.scan = svkeep.len ;
+		if (!stralloc_catb(&svkeep, svok, svoklen + 1)) retstralloc(111,"main") ;
+		sv_signal.scanlen = svoklen ;
+				
+		sv_signal.name = svkeep.len ;
+		if (!stralloc_catb(&svkeep, svname, namelen + 1)) retstralloc(111,"main") ;
+		sv_signal.namelen = namelen ;
+		
+		sv_signal.src = svkeep.len ;
+		if (!stralloc_catb(&svkeep, src, srclen + 1)) retstralloc(111,"main") ;
+		sv_signal.srclen = srclen ;
+		
+		sv_signal.sigtosend = sig ;
+		sv_signal.sig = SIGNAL ;
+		
+		/** notification-fd */
+		memcpy(svok + svoklen,"/notification-fd",16) ;
+		svok[svoklen + 16] = 0 ;
+		e = errno ;
+		errno = 0 ;
+		if (access(svok, F_OK) < 0)
+		{
+			if (errno != ENOENT) strerr_diefu2sys(111, "access ", svok) ;
+			if (SIGNAL == SIGRUP)
+			{
+				sv_signal.sig = SIGUP ;
+				sv_signal.sigtosend = "uwu" ;
+				VERBO2 strerr_warnw2x(svok, " is not present - ignoring request for readiness notification") ;
+			}
+			if (SIGNAL == SIGRR)
+			{
+				sv_signal.sig = SIGR ;
+				sv_signal.sigtosend = "uwr" ;
+				VERBO2 strerr_warnw2x(svok, " is not present - ignoring request for readiness notification") ;
+			}
+			if (SIGNAL == SIGRDOWN)
+			{
+				sv_signal.sig = SIGDOWN ;
+				sv_signal.sigtosend = "dwd" ;
+				VERBO2 strerr_warnw2x(svok, " is not present - ignoring request for readiness notification") ;
+			}		
+		}
+		else
+		{
+			if (!read_uint(svok,&sv_signal.notify)) strerr_diefu2sys(111,"read: ",svok) ;
+		}
+		
+		/** max-death-tally */
+		if (!death)
+		{
+			memcpy(svok + svoklen,"/max-death-tally", 16) ;
+			svok[svoklen + 16] = 0 ;
+			errno = 0 ;
+			if (access(svok, F_OK) < 0)
+			{
+				if (errno != ENOENT) strerr_diefu2sys(111, "access ", svok) ;
+			}
+			if (errno == ENOENT)
+			{
+				sv_signal.ndeath = DEATHSV ;
+			}
+			else
+			{
+				if (!read_uint(svok,&sv_signal.ndeath)) strerr_diefu2sys(111,"read: ",svok) ;
+			}
+		}
+		else sv_signal.ndeath = death ;
+		
+		tain_t tcheck ;
+		tain_from_millisecs(&tcheck,tsv) ;
+		int check = tain_to_millisecs(&tcheck) ;
+		if (check > 0) tain_from_millisecs(&sv_signal.deadline, tsv) ;
+			
+		else
+		{
+			/** timeout-{up/down} */
+			{
+				char *tm = NULL ;
+				unsigned int t ;
+				if (SIGNAL <= SIGRR)
+				{
+					tm="/timeout-up" ;
+				}
+				else
+				{
+					tm="/timeout-down" ;
+				}
+				errno = 0 ;
+				memcpy(svok + svoklen,tm, strlen(tm) + 1) ;
+				if (access(svok, F_OK) < 0)
+				{
+					if (errno != ENOENT) strerr_diefu2sys(111, "access ", svok) ;
+				}
+				if (errno == ENOENT)
+				{
+					tain_from_millisecs(&sv_signal.deadline, SV_DEADLINE) ;
+				}
+				else
+				{
+					if (!read_uint(svok,&t)) strerr_diefu2sys(111,"read: ",svok) ;
+					tain_from_millisecs(&sv_signal.deadline, t) ;
+				}
+			}
+		}
+		
+		errno = e ;
+		
+		if (!genalloc_append(svc_sig,&gakeep,&sv_signal)) strerr_diefu1sys(111,"append genalloc") ;
+				
+	}
+	
+	/** nothing to do */
+	if (!genalloc_len(svc_sig,&gakeep))	goto finish ;
+	
+	int spfd = selfpipe_init() ;
+	if (spfd < 0) strerr_diefu1sys(111, "selfpipe_trap") ;
+	if (selfpipe_trap(SIGINT) < 0) strerr_diefu1sys(111, "selfpipe_trap") ;
+	if (selfpipe_trap(SIGTERM) < 0) strerr_diefu1sys(111, "selfpipe_trap") ;
+	if (sig_ignore(SIGPIPE) < 0) strerr_diefu1sys(111,"ignore SIGPIPE") ;
+		
+	if (!svc_init_pipe(&fifo,&gakeep,&svkeep)) strerr_diefu1x(111,"init pipe") ;
+
+	for (unsigned int i = 0 ; i < genalloc_len(svc_sig,&gakeep) ; i++)
+	{ 
+		svc_sig *sv = &genalloc_s(svc_sig,&gakeep)[i] ;
+		if (!svc_listen(&gakeep,&fifo,spfd,sv)) strerr_diefu1x(111,"listen pipe") ;
+	}
+	
+	finish:
+		ftrigr_end(&fifo) ;
+		selfpipe_finish() ;
+		stralloc_free(&svkeep) ;
+		genalloc_free(svc_sig,&gakeep) ;
+	
+	return 0 ;		
+}
+
+	
+
diff --git a/src/lib66/svc_switch_to.c b/src/lib66/svc_switch_to.c
index affab5a2245866349cfe41fd4c8b294ceed10608..a6cd7bef371f49f81eace467527ed4c66bfaaf8a 100644
--- a/src/lib66/svc_switch_to.c
+++ b/src/lib66/svc_switch_to.c
@@ -20,10 +20,11 @@
 #include <66/backup.h>
 #include <66/utils.h>
 #include <66/enum.h>
+#include <66/ssexec.h>
 
 /** 1-> backup
  * 0-> ori */
-int svc_switch_to(char const *base, char const *tree,char const *treename,unsigned int where)
+int svc_switch_to(ssexec_t *info,unsigned int where)
 {
 	int r ;
 	
@@ -38,44 +39,44 @@ int svc_switch_to(char const *base, char const *tree,char const *treename,unsign
 	memcpy(cmd + cmdlen," -b",3) ;
 	cmd[cmdlen + 3] = 0 ;
 	
-	r = backup_cmd_switcher(VERBOSITY,cmd,treename) ;
+	r = backup_cmd_switcher(VERBOSITY,cmd,info) ;
 	if (r < 0)
 	{
-		VERBO3 strerr_warnwu2sys("find origin of svc service for: ",treename) ;
+		VERBO3 strerr_warnwu2sys("find origin of svc service for: ",info->treename) ;
 		return 0 ;
 	}
 	// point to origin
 	if (!r && where)
 	{
-		VERBO3 strerr_warnt2x("make a backup of svc service for: ",treename) ;
-		if (!backup_make_new(base,tree,treename,CLASSIC))
+		VERBO3 strerr_warnt2x("make a backup of svc service for: ",info->treename) ;
+		if (!backup_make_new(info,CLASSIC))
 		{
-			VERBO3 strerr_warnwu2sys("make a backup of svc service for: ",treename) ;
+			VERBO3 strerr_warnwu2sys("make a backup of svc service for: ",info->treename) ;
 			return 0 ;
 		}
-		VERBO3 strerr_warnt3x("switch svc service for tree: ",treename," to backup") ;
+		VERBO3 strerr_warnt3x("switch svc service for tree: ",info->treename," to backup") ;
 		memcpy(cmd + cmdlen," -s1",4) ;
 		cmd[cmdlen + 4] = 0 ;
-		r = backup_cmd_switcher(VERBOSITY,cmd,treename) ;
+		r = backup_cmd_switcher(VERBOSITY,cmd,info) ;
 		if (r < 0)
 		{
-			VERBO3 strerr_warnwu3sys("switch svc service for: ",treename," to backup") ;
+			VERBO3 strerr_warnwu3sys("switch svc service for: ",info->treename," to backup") ;
 		}
 	}
 	else if (r > 0 && !where)
 	{
-		VERBO3 strerr_warnt3x("switch svc service for tree: ",treename," to source") ;
+		VERBO3 strerr_warnt3x("switch svc service for tree: ",info->treename," to source") ;
 		memcpy(cmd + cmdlen," -s0",4) ;
 		cmd[cmdlen + 4] = 0 ;
-		r = backup_cmd_switcher(VERBOSITY,cmd,treename) ;
+		r = backup_cmd_switcher(VERBOSITY,cmd,info) ;
 		if (r < 0)
 		{
-			VERBO3 strerr_warnwu3sys("switch svc service for: ",treename," to source") ;
+			VERBO3 strerr_warnwu3sys("switch svc service for: ",info->treename," to source") ;
 		}
-		VERBO3 strerr_warnt2x("make a backup of svc service for: ",treename) ;
-		if (!backup_make_new(base,tree,treename,CLASSIC))
+		VERBO3 strerr_warnt2x("make a backup of svc service for: ",info->treename) ;
+		if (!backup_make_new(info,CLASSIC))
 		{
-			VERBO3 strerr_warnwu2sys("make a backup of svc service for: ",treename) ;
+			VERBO3 strerr_warnwu2sys("make a backup of svc service for: ",info->treename) ;
 			return 0 ;
 		}
 	}
diff --git a/src/lib66/tree_cmd_state.c b/src/lib66/tree_cmd_state.c
index 75c033841dfca4ec7fd8fc28b7a0f468367c3ca5..46583a0b685168c1f761c1049cf725b6ba420343 100644
--- a/src/lib66/tree_cmd_state.c
+++ b/src/lib66/tree_cmd_state.c
@@ -82,7 +82,7 @@ int tree_state(int argc, char const *const *argv)
 	}
 	size_t statesize ;
 	/** /system/state */
-	base.len-- ;
+	//base.len-- ;
 	size_t statelen ;
 	char state[base.len + SS_SYSTEM_LEN + SS_STATE_LEN + 1] ;
 	memcpy(state,base.s,base.len) ;
diff --git a/src/lib66/tree_copy_tmp.c b/src/lib66/tree_copy_tmp.c
index 852c31a894795924d049e845b749f2a2f9b86af0..d71e5032593e8aa4de490f7dc1529f018a1b996a 100644
--- a/src/lib66/tree_copy_tmp.c
+++ b/src/lib66/tree_copy_tmp.c
@@ -25,7 +25,7 @@
 #include <66/constants.h>
 #include <66/enum.h>
 #include <66/utils.h>
-
+#include <66/ssexec.h>
 
 void err(unsigned int *e, unsigned int msg,char const *resolve,char const *swap, char const *svdir)
 {
@@ -44,29 +44,29 @@ void err(unsigned int *e, unsigned int msg,char const *resolve,char const *swap,
 	*e = 0 ;
 }
 
-int tree_copy_tmp(char const *workdir, char const *base, char const *live, char const *tree,char const *treename)
+int tree_copy_tmp(char const *workdir, ssexec_t *info)
 {
 	stralloc saresolve = STRALLOC_ZERO ;
 	stralloc swap = STRALLOC_ZERO ;
 	unsigned int e = 1 ;
 	size_t svdirlen ;
-	size_t treelen = strlen(tree) ;	
-	char svdir[treelen + SS_SVDIRS_LEN + SS_RESOLVE_LEN + 1] ;
-	memcpy(svdir,tree,treelen) ;
-	memcpy(svdir + treelen,SS_SVDIRS,SS_SVDIRS_LEN) ;
-	svdirlen = treelen + SS_SVDIRS_LEN ;
+	
+	char svdir[info->tree.len + SS_SVDIRS_LEN + SS_RESOLVE_LEN + 1] ;
+	memcpy(svdir,info->tree.s,info->tree.len) ;
+	memcpy(svdir + info->tree.len,SS_SVDIRS,SS_SVDIRS_LEN) ;
+	svdirlen = info->tree.len + SS_SVDIRS_LEN ;
 	memcpy(svdir + svdirlen,SS_SVC, SS_SVC_LEN) ;
 	svdir[svdirlen + SS_SVC_LEN] = 0 ;
 	
 	/** svc */
 	if (rm_rf(svdir) < 0)
 	{
-		if (!resolve_pointo(&saresolve,base,live,tree,treename,CLASSIC,SS_RESOLVE_SRC))
+		if (!resolve_pointo(&saresolve,info,CLASSIC,SS_RESOLVE_SRC))
 		{
 			err(&e,0,saresolve.s,swap.s,svdir) ;
 			goto err ;
 		}
-		if (!resolve_pointo(&swap,base,live,tree,treename,CLASSIC,SS_RESOLVE_BACK))
+		if (!resolve_pointo(&swap,info,CLASSIC,SS_RESOLVE_BACK))
 		{
 			err(&e,1,saresolve.s,swap.s,svdir) ;
 			goto err ;
@@ -85,12 +85,12 @@ int tree_copy_tmp(char const *workdir, char const *base, char const *live, char
 	svdir[svdirlen + SS_DB_LEN] = 0 ;
 	if (rm_rf(svdir) < 0)
 	{
-		if (!resolve_pointo(&saresolve,base,live,tree,treename,LONGRUN,SS_RESOLVE_SRC))
+		if (!resolve_pointo(&saresolve,info,LONGRUN,SS_RESOLVE_SRC))
 		{
 			err(&e,0,saresolve.s,swap.s,svdir) ;
 			goto err ;
 		}
-		if (!resolve_pointo(&swap,base,live,tree,treename,LONGRUN,SS_RESOLVE_BACK))
+		if (!resolve_pointo(&swap,info,LONGRUN,SS_RESOLVE_BACK))
 		{
 			err(&e,1,saresolve.s,swap.s,svdir) ;
 			goto err ;
@@ -110,7 +110,7 @@ int tree_copy_tmp(char const *workdir, char const *base, char const *live, char
 	
 	if (rm_rf(svdir) < 0)
 	{
-		if (!resolve_pointo(&saresolve,base,live,tree,treename,0,SS_RESOLVE_SRC))
+		if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
 		{
 			err(&e,0,saresolve.s,swap.s,svdir) ;
 			goto err ;
@@ -119,7 +119,7 @@ int tree_copy_tmp(char const *workdir, char const *base, char const *live, char
 		if (!stralloc_cats(&saresolve,SS_RESOLVE)) retstralloc(0,"tree_copy_tmp") ;
 		if (!stralloc_0(&saresolve)) retstralloc(0,"tree_copy_tmp") ;
 		
-		if (!resolve_pointo(&swap,base,live,tree,treename,0,SS_RESOLVE_BACK))
+		if (!resolve_pointo(&swap,info,0,SS_RESOLVE_BACK))
 		{
 			err(&e,1,saresolve.s,swap.s,svdir) ;
 			goto err ;
@@ -140,12 +140,12 @@ int tree_copy_tmp(char const *workdir, char const *base, char const *live, char
 		
 	if (!hiercopy(workdir,svdir))
 	{
-		if (!resolve_pointo(&saresolve,base,live,tree,treename,0,SS_RESOLVE_SRC))
+		if (!resolve_pointo(&saresolve,info,0,SS_RESOLVE_SRC))
 		{	
 			err(&e,0,saresolve.s,swap.s,svdir) ;
 			goto err ;
 		}
-		if (!resolve_pointo(&swap,base,live,tree,treename,0,SS_RESOLVE_BACK))
+		if (!resolve_pointo(&swap,info,0,SS_RESOLVE_BACK))
 		{
 			err(&e,1,saresolve.s,swap.s,svdir) ;
 			goto err ;
diff --git a/src/lib66/tree_find_current.c b/src/lib66/tree_find_current.c
index ea3974ed05744e16a0eb804873eaec16fbaa46fe..86a6737bf4e5a36e0a89f72a398348fc409c75ca 100644
--- a/src/lib66/tree_find_current.c
+++ b/src/lib66/tree_find_current.c
@@ -26,15 +26,14 @@
 
 #include <66/constants.h>
 
-
-int tree_find_current(stralloc *tree, char const *base)
+int tree_find_current(stralloc *tree, char const *base,uid_t owner)
 {
 	ssize_t r ;
 	size_t baselen = strlen(base) ;
 	char pack[256] ;
 	
-	uint32_pack(pack,MYUID) ;
-	size_t packlen = uint_fmt(pack,MYUID) ;
+	uint32_pack(pack,owner) ;
+	size_t packlen = uint_fmt(pack,owner) ;
 	pack[packlen] = 0 ;
 	
 	char sa[baselen + SS_TREE_CURRENT_LEN + 1 + packlen + 1 + SS_TREE_CURRENT_LEN + 1] ;
@@ -48,10 +47,9 @@ int tree_find_current(stralloc *tree, char const *base)
 	
 	r = scan_mode(sa,S_IFDIR) ;
 	if(r <= 0) return 0 ; 
-	//	strerr_warni2x("sa tree_find_current",sa) ;
 	r = sarealpath(tree,sa) ;
 	if (r < 0 ) return 0 ; 
 	if (!stralloc_0(tree)) retstralloc(0,"find_current") ;
-	
+	tree->len--;
 	return 1 ;
 }
diff --git a/src/lib66/tree_get_permissions.c b/src/lib66/tree_get_permissions.c
index df8a9a36102d3bd78c91096c6ca817f60d1dbfc4..e03ac00d3f0bfb381ad20650377d7f71874c1be9 100644
--- a/src/lib66/tree_get_permissions.c
+++ b/src/lib66/tree_get_permissions.c
@@ -27,15 +27,15 @@
 #include <66/constants.h>
 #include <66/utils.h>
 
-int tree_get_permissions(char const *tree)
+int tree_get_permissions(char const *tree,uid_t owner)
 {
 	ssize_t r ;
 	size_t treelen = strlen(tree) ;
 	char pack[256] ;
 	char tmp[treelen + SS_RULES_LEN + 1] ;
 	
-	uint32_pack(pack,MYUID) ;
-	pack[uint_fmt(pack,MYUID)] = 0 ;
+	uint32_pack(pack,owner) ;
+	pack[uint_fmt(pack,owner)] = 0 ;
 	
 	memcpy(tmp,tree,treelen) ;
 	memcpy(tmp + treelen,SS_RULES,SS_RULES_LEN) ;
diff --git a/src/lib66/tree_sethome.c b/src/lib66/tree_sethome.c
index 8c8c9fa56fc3f16f03d754ad826c9831be62ef94..3dba26097a81984db0037348c98769972a7d2683 100644
--- a/src/lib66/tree_sethome.c
+++ b/src/lib66/tree_sethome.c
@@ -25,19 +25,19 @@
 
 #include <66/constants.h>
 
-int tree_sethome(stralloc *tree, char const *base)
+int tree_sethome(stralloc *tree, char const *base,uid_t owner)
 {
 	int r ;
 	
 	if (!tree->len)
 	{
-		if (!tree_find_current(tree, base)) return -1 ;
+		if (!tree_find_current(tree, base,owner)) return -1 ;
 	}
 	else
 	{
 		char treename[tree->len + 1] ;
-		memcpy(treename,tree->s,tree->len - 1) ;
-		treename[tree->len - 1] = 0 ;
+		memcpy(treename,tree->s,tree->len) ;
+		treename[tree->len] = 0 ;
 		tree->len = 0 ;
 		if (!stralloc_cats(tree,base)) retstralloc(0,"main") ;
 		if (!stralloc_cats(tree,SS_SYSTEM "/")) retstralloc(0,"main") ;
@@ -46,6 +46,7 @@ int tree_sethome(stralloc *tree, char const *base)
 		r = scan_mode(tree->s,S_IFDIR) ;
 		if (r < 0) errno = EEXIST ;
 		if (r != 1) return 0 ;
+		tree->len--;
 	}
 	
 	return 1 ;