From: WaLyong Cho Date: Mon, 7 Nov 2016 07:54:43 +0000 (+0900) Subject: libsystem: exec: add do_fork_exec_redirect() X-Git-Tag: submit/tizen/20180322.062032~2^2~3^2~6 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=13fd341cd5069196125e4cb09b5c81c4d87f4299;p=platform%2Fcore%2Fsystem%2Flibsystem.git libsystem: exec: add do_fork_exec_redirect() To execute and redirect its output/error, add do_fork_exec_redirect(). This api is very similar to do_fork_exec() but additionally takes fd and flags. According to flags the child output or error redirected to fd. Change-Id: I8e6f2df5d812760138a429adec41bbd76645d6f3 Signed-off-by: WaLyong Cho --- diff --git a/src/libsystem/exec.c b/src/libsystem/exec.c index 05dc89c..272014d 100644 --- a/src/libsystem/exec.c +++ b/src/libsystem/exec.c @@ -32,7 +32,46 @@ #include "libsystem.h" -int do_fork_exec(char *const argv[], char * const envp[], int64_t timeout_msec) { +static int wait_child(pid_t pid, int64_t timeout_msec) { + struct timeval start, timeout; + int status; + + if (timeout_msec < 0) + return 0; + + if (timeout_msec > 0) { + msec_to_timeval((uint64_t) timeout_msec, &timeout); + + if (gettimeofday(&start, NULL) < 0) + return -errno; + } + + for (;;) { + struct timeval current, delta; + pid_t p; + + p = waitpid(pid, &status, WNOHANG); + if (p == pid) + break; + + if (timeout_msec == 0) + continue; + + if (gettimeofday(¤t, NULL) < 0) + return -errno; + + timersub(¤t, &start, &delta); + + if (timercmp(&timeout, &delta, <)) + return -ETIME; + + usleep(100000); + } + + return WEXITSTATUS(status); +} + +int do_fork_exec_redirect(char *const argv[], char * const envp[], int64_t timeout_msec, int fd, int flags) { pid_t pid; assert(argv); @@ -41,50 +80,29 @@ int do_fork_exec(char *const argv[], char * const envp[], int64_t timeout_msec) if (pid < 0) return -errno; else if (pid == 0) { + + if (fd >= 0) { + if (flags & EXEC_REDIRECT_OUTPUT) + dup2(fd, STDOUT_FILENO); + + if (flags & EXEC_REDIRECT_ERROR) + dup2(fd, STDERR_FILENO); + } + if (!envp) execv(*argv, argv); else execvpe(*argv, argv, envp); _exit(EXIT_FAILURE); - } else { - struct timeval start, timeout; - int status; - - if (timeout_msec < 0) - return 0; - - if (timeout_msec > 0) { - msec_to_timeval((uint64_t) timeout_msec, &timeout); - - if (gettimeofday(&start, NULL) < 0) - return -errno; - } - - for (;;) { - struct timeval current, delta; - pid_t p; - - p = waitpid(pid, &status, WNOHANG); - if (p == pid) - break; - - if (timeout_msec == 0) - continue; - - if (gettimeofday(¤t, NULL) < 0) - return -errno; - - timersub(¤t, &start, &delta); + } - if (timercmp(&timeout, &delta, <)) - return -ETIME; + return wait_child(pid, timeout_msec); +} - usleep(100000); - } +int do_fork_exec(char *const argv[], char * const envp[], int64_t timeout_msec) { - return WEXITSTATUS(status); - } + assert(argv); - return 0; + return do_fork_exec_redirect(argv, envp, timeout_msec, -1, EXEC_REDIRECT_NONE); } diff --git a/src/libsystem/libsystem.h b/src/libsystem/libsystem.h index 7819aa7..18220f6 100644 --- a/src/libsystem/libsystem.h +++ b/src/libsystem/libsystem.h @@ -832,6 +832,41 @@ bool mnt_is_mounted(const char *fsname, const char *dir, const char *type, const */ int do_fork_exec(char *const argv[], char * const envp[], int64_t timeout_msec); +enum { + EXEC_REDIRECT_NONE = 0x01 << 0, + EXEC_REDIRECT_OUTPUT = 0x01 << 1, + EXEC_REDIRECT_ERROR = 0x01 << 2, + EXEC_REDIRECT_ALL = (EXEC_REDIRECT_OUTPUT | EXEC_REDIRECT_ERROR), +}; + +/** + * @brief Traditional fork() and exec() helper. And additionally + * redirect child process standard output or standard error to given fd. + * + * @param argv array of pointers to null-terminated strings that + * represent the argument list available to the new program. The first + * argument should point to the filename associated with the file + * being executed. The array of pointers must be terminated by a NULL pointer. + * @param envp specify the environment of the executed program via the + * argument envp. The envp argument is an array of pointers to + * null-terminated strings and must be terminated by a NULL pointer. + * @param timeout_msec timeout millisecond to prevent infinite + * waiting. If negative is given, the parent will not wait the + * child. In other word, the parent will return immediately. If 0 is + * given, parent will wait the child infinitly. And if positive value + * is given parent will wait given milliseconds and expired return + * -1. If the child is exit within the tiemout millisecond return with + * child exit code. + * @param fd file descriptor to redirect child standard output or error. + * @param flags redirect flag. This flags is able to include + * #EXEC_REDIRECT_OUTPUT or EXEC_REDIRECT_ERROR. + * + * @return exit code of child. It is fully depend on the child + * process. If the child exit with 1 then this function also return 1. + * Negative errno on error. -ETIME on timer expired. + */ +int do_fork_exec_redirect(char *const argv[], char * const envp[], int64_t timeout_msec, int fd, int flags); + /** * @} */