diff --git a/src/include/66/ssexec.h b/src/include/66/ssexec.h index f3a6c717b4e2d45813062f0715e736266802b8c7..d00cc13f616d2cbf582a5218e0587d40a4d5b18f 100644 --- a/src/include/66/ssexec.h +++ b/src/include/66/ssexec.h @@ -260,7 +260,7 @@ extern char const *help_halt ; #define OPTS_SCANDIR_WRAPPER "ho:" #define OPTS_SCANCTL_WRAPPER_LEN (sizeof OPTS_SCANDIR_WRAPPER - 1) -#define OPTS_SCANDIR_SIGNAL "d:s:e:bB" +#define OPTS_SCANDIR_SIGNAL "d:s:e:bBf" #define OPTS_SCANDIR_SIGNAL_LEN (sizeof OPTS_SCANDIR_SIGNAL - 1) #define OPTS_SCANDIR_CREATE "bBs:cL:" #define OPTS_SCANDIR_CREATE_LEN (sizeof OPTS_SCANDIR_CREATE - 1) diff --git a/src/lib66/exec/ssexec_help.c b/src/lib66/exec/ssexec_help.c index b770ab9531dccb41f8ab44d7d0e98015ffb3d191..0d2c65d4bf3ee0674c01a1edc4723db94b7f9863 100644 --- a/src/lib66/exec/ssexec_help.c +++ b/src/lib66/exec/ssexec_help.c @@ -514,7 +514,7 @@ char const *help_scandir_remove = " -h: print this help\n" ; -char const *usage_scandir_start = "66 scandir start [ -h ] [ -d notif ] [ -s rescan ] [ -e environment ] [ -b|B ]" ; +char const *usage_scandir_start = "66 scandir start [ -h ] [ -d notif ] [ -s rescan ] [ -e environment ] [ -b|B ] [ -f ]" ; char const *help_scandir_start = "\nstart a scandir\n" @@ -526,6 +526,7 @@ char const *help_scandir_start = " -e: use environment as environment directory\n" " -b: create scandir (if it not exist yet) for a boot process\n" " -B: create scandir (if it not exist yet) for a boot process inside a container\n" +" -f: fork and become a daemon" ; char const *usage_scandir_stop = "66 scandir stop [ -h ]" ; diff --git a/src/lib66/exec/ssexec_scandir_signal.c b/src/lib66/exec/ssexec_scandir_signal.c index dfc1c56de896fb5ce0bff9623d4be28a6e26c26b..fb993390756fa8dd19b3a6b87deaebb21221b0bd 100644 --- a/src/lib66/exec/ssexec_scandir_signal.c +++ b/src/lib66/exec/ssexec_scandir_signal.c @@ -16,11 +16,13 @@ #include <fcntl.h> #include <unistd.h> #include <sys/types.h> +#include <sys/stat.h> #include <oblibs/log.h> #include <oblibs/string.h> #include <oblibs/environ.h> #include <oblibs/types.h> +#include <oblibs/directory.h> #include <skalibs/types.h> #include <skalibs/bytestr.h> @@ -32,6 +34,7 @@ #include <66/ssexec.h> #include <66/svc.h> #include <66/utils.h> +#include <66/constants.h> #include <s6/config.h> @@ -74,8 +77,14 @@ static int send_signal(char const *scandir, char const *signal) log_flow() ; unsigned int sig = 0 ; + uint8_t down = 0 ; char csig[3] ; sig = parse_signal(signal) ; + char fdholder[strlen(scandir) + 1 + SS_FDHOLDER_LEN + 1] ; + char oneshotd[strlen(scandir) + 1 + SS_FDHOLDER_LEN + 1] ; + + auto_strings(fdholder, scandir, "/", SS_FDHOLDER) ; + auto_strings(oneshotd, scandir, "/", SS_ONESHOTD) ; switch(sig) { @@ -94,12 +103,14 @@ static int send_signal(char const *scandir, char const *signal) csig[0] = 'h' ; csig[1] = 0 ; + down = 1 ; break ; case 3: // rescan csig[0] = 'a' ; csig[1] = 0 ; + down = 1 ; break ; case 4: // quit @@ -143,10 +154,21 @@ static int send_signal(char const *scandir, char const *signal) log_die(LOG_EXIT_SYS, "unknown signal: ", signal) ; } + if (!down) { + + svc_send_fdholder(fdholder, "dx") ; + svc_send_fdholder(oneshotd, "dx") ; + + } else { + + svc_send_fdholder(fdholder, "U") ; + svc_send_fdholder(oneshotd, "U") ; + } + return svc_scandir_send(scandir,csig) ; } -static void scandir_up(char const *scandir, unsigned int timeout, unsigned int notif, char const *const *envp, ssexec_t *info) +static void scandir_up(char const *scandir, unsigned int timeout, unsigned int notif, unsigned int foreground, char const *const *envp, ssexec_t *info) { uid_t uid = getuid() ; gid_t gid = getgid() ; @@ -169,6 +191,88 @@ static void scandir_up(char const *scandir, unsigned int timeout, unsigned int n newup[m++] = scandir ; newup[m++] = 0 ; + if (!foreground && info->owner) { + + int fd ; + char *target = "/dev/null" ; + char home[SS_MAX_PATH_LEN + 1] ; + gid_t gid = -1 ; + + if (!yourgid(&gid, info->owner)) + log_dieusys(LOG_EXIT_SYS, "get gid") ; + + if (!set_ownerhome_stack_byuid(home, info->owner)) + log_dieusys(LOG_EXIT_SYS,"set home directory") ; + + size_t homelen = strlen(home), loglen = strlen(SS_LOGGER_USERDIR) ; + char file[homelen + loglen + 1 + SS_SCANDIR_LEN + 1 + SS_TREE_CURRENT_LEN + 1] ; + + auto_strings(file, home, SS_LOGGER_USERDIR, "/", SS_SCANDIR) ; + + if (!dir_create_parent(file, 755)) + log_dieusys(LOG_EXIT_SYS, "create directory: ", file) ; + + file[homelen + loglen + 1] = 0 ; + + if (chown(file, info->owner, gid) < 0) + log_dieusys(LOG_EXIT_SYS, "chown: ", file) ; + + if (chmod(file, 0755) < 0) + log_dieusys(LOG_EXIT_SYS,"chmod: ", file) ; + + auto_strings(file + homelen + loglen + 1, SS_SCANDIR) ; + + if (chown(file, info->owner, gid) < 0) + log_dieusys(LOG_EXIT_SYS, "chown: ", file) ; + + if (chmod(file, 0755) < 0) + log_dieusys(LOG_EXIT_SYS,"chmod: ", file) ; + + auto_strings(file + homelen + loglen + 1 + SS_SCANDIR_LEN, "/", SS_TREE_CURRENT) ; + + pid_t pid = fork() ; + if (pid < 0) + log_dieusys(LOG_EXIT_SYS, "fork") ; + else if (pid) + _exit(0) ; + + if (setsid() < 0) + log_dieusys(LOG_EXIT_SYS, "setsid") ; + + pid = fork() ; + if (pid < 0) + log_dieusys(LOG_EXIT_SYS, "fork") ; + else if (pid) + _exit(0) ; + + if ((chdir("/")) < 0) + log_dieusys(LOG_EXIT_SYS,"chdir") ; + + fd = open(target,O_RDONLY) ; + if (fd < 0) + log_dieusys(LOG_EXIT_SYS, "open ",target) ; + + if (dup2(fd, 0) < 0) + log_dieusys(LOG_EXIT_SYS, "copy stdin to ", target) ; + + close(fd) ; + + fd = open(file, O_WRONLY|O_NONBLOCK|O_CREAT|O_APPEND, 0700) ; + if (fd < 0) + log_dieusys(LOG_EXIT_SYS, "open file: ", file) ; + + if (dup2(fd, 1) < 0) + log_dieusys(LOG_EXIT_SYS, "copy stdout to: ", file) ; + + close(fd) ; + + if (dup2(1, 2) < 0) + log_dieusys(LOG_EXIT_SYS, "copy stderr to stdout") ; + + if (chown(file, info->owner, gid) < 0) + log_dieusys(LOG_EXIT_SYS, "chown: ", file) ; + } + if (!uid && uid != info->owner) { /** -o <owner> was asked. Respect it * a start the s6-svscan process with the @@ -193,7 +297,7 @@ int ssexec_scandir_signal(int argc, char const *const *argv, ssexec_t *info) int r ; - unsigned int timeout = 0, notif = 0, sig = 0, container = 0, boot = 0 ; + unsigned int timeout = 0, notif = 0, sig = 0, container = 0, boot = 0, foreground = 0 ; char const *newenv[MAXENV+1] ; char const *const *genv = 0 ; @@ -251,6 +355,12 @@ int ssexec_scandir_signal(int argc, char const *const *argv, ssexec_t *info) break ; + case 'f' : + + foreground = 1 ; + + break ; + default : log_usage(info->usage, "\n", info->help) ; @@ -285,6 +395,8 @@ int ssexec_scandir_signal(int argc, char const *const *argv, ssexec_t *info) } else genv = genvp ; + stralloc_free(&envdir) ; + sig = parse_signal(signal) ; if (!sig) { @@ -327,16 +439,14 @@ int ssexec_scandir_signal(int argc, char const *const *argv, ssexec_t *info) return 0 ; } - stralloc_free(&envdir) ; - - scandir_up(scandir, timeout, notif, genv, info) ; + scandir_up(scandir, timeout, notif, foreground, genv, info) ; } r = svc_scandir_ok(info->scandir.s) ; if (r < 0) log_dieusys(LOG_EXIT_SYS, "check: ", info->scandir.s) ; else if (!r) - log_diesys(LOG_EXIT_SYS, "scandir: ", info->scandir.s, " is not running") ; + log_diesys(LOG_EXIT_SYS, "scandir: ", info->scandir.s, " is not running") ; if (send_signal(info->scandir.s, signal) <= 0) log_dieu(LOG_EXIT_SYS, "send signal to scandir: ", info->scandir.s) ;