diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-01-11 07:18:56 +0100 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-01-11 07:18:56 +0100 |
| commit | 658622eb5e1b81d394f066df44bc9f0abe9cc807 (patch) | |
| tree | a7b3fb997a47cbc6bd134b699bf6181cb74d2f8a /lib/Utils | |
| parent | b0abdde8871b0366868b917df040a8880165ba30 (diff) | |
| download | abrt-658622eb5e1b81d394f066df44bc9f0abe9cc807.tar.gz abrt-658622eb5e1b81d394f066df44bc9f0abe9cc807.tar.xz abrt-658622eb5e1b81d394f066df44bc9f0abe9cc807.zip | |
RunApp: safer chdir. Overhauled "sparn a child and get its output" in general
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'lib/Utils')
| -rw-r--r-- | lib/Utils/Makefile.am | 2 | ||||
| -rw-r--r-- | lib/Utils/popen_and_save_output.cpp | 30 | ||||
| -rw-r--r-- | lib/Utils/spawn.cpp | 121 | ||||
| -rw-r--r-- | lib/Utils/xfuncs.cpp | 6 |
4 files changed, 128 insertions, 31 deletions
diff --git a/lib/Utils/Makefile.am b/lib/Utils/Makefile.am index d5e9d98..a944d97 100644 --- a/lib/Utils/Makefile.am +++ b/lib/Utils/Makefile.am @@ -16,7 +16,7 @@ libABRTUtils_la_SOURCES = \ daemon.cpp \ skip_whitespace.cpp \ xatonum.cpp \ - popen_and_save_output.cpp \ + spawn.cpp \ stringops.cpp \ dirsize.cpp \ DebugDump.h DebugDump.cpp \ diff --git a/lib/Utils/popen_and_save_output.cpp b/lib/Utils/popen_and_save_output.cpp deleted file mode 100644 index 4bcbcac..0000000 --- a/lib/Utils/popen_and_save_output.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Utility routines. - * - * Licensed under GPLv2 or later, see file COPYING in this tarball for details. - */ -#include "abrtlib.h" - -using namespace std; - -string popen_and_save_output(const char *cmd) -{ - string result; - - FILE *fp = popen(cmd, "r"); - if (fp == NULL) /* fork or pipe failed; or out-of-mem */ - { - return result; - } - - size_t sz; - char buf[BUFSIZ + 1]; - while ((sz = fread(buf, 1, sizeof(buf)-1, fp)) > 0) - { - buf[sz] = '\0'; - result += buf; - } - pclose(fp); - - return result; -} diff --git a/lib/Utils/spawn.cpp b/lib/Utils/spawn.cpp new file mode 100644 index 0000000..4b0eecb --- /dev/null +++ b/lib/Utils/spawn.cpp @@ -0,0 +1,121 @@ +/* + * Utility routines. + * + * Licensed under GPLv2, see file COPYING in this tarball for details. + */ +#include "abrtlib.h" + +/* Returns pid */ +pid_t fork_execv_on_steroids(int flags, + char **argv, + int *pipefds, + char **unsetenv_vec, + const char *dir, + uid_t uid) +{ + pid_t child; + /* Reminder: [0] is read end, [1] is write end */ + int pipe_to_child[2]; + int pipe_fm_child[2]; + + /* Sanitize flags */ + if (!pipefds) + flags &= ~(EXECFLG_INPUT | EXECFLG_OUTPUT); + + if (flags & EXECFLG_INPUT) + xpipe(pipe_to_child); + if (flags & EXECFLG_OUTPUT) + xpipe(pipe_fm_child); + + child = fork(); + if (child == -1) { + perror_msg_and_die("fork"); + } + if (child == 0) { + /* Child */ + + /* Play with stdio descriptors */ + if (flags & EXECFLG_INPUT) { + xmove_fd(pipe_to_child[0], STDIN_FILENO); + } else if (flags & EXECFLG_INPUT_NUL) { + xmove_fd(xopen("/dev/null", O_RDWR), STDIN_FILENO); + } + if (flags & EXECFLG_OUTPUT) { + xmove_fd(pipe_fm_child[1], STDOUT_FILENO); + } else if (flags & EXECFLG_OUTPUT_NUL) { + xmove_fd(xopen("/dev/null", O_RDWR), STDOUT_FILENO); + } + if (flags & EXECFLG_ERR2OUT) { + /* Want parent to see errors in the same stream */ + xdup2(STDOUT_FILENO, STDERR_FILENO); + } else if (flags & EXECFLG_ERR_NUL) { + xmove_fd(xopen("/dev/null", O_RDWR), STDERR_FILENO); + } + + if (flags & EXECFLG_SETGUID) { + struct passwd* pw = getpwuid(uid); + gid_t gid = pw ? pw->pw_gid : uid; + setgroups(1, &gid); + xsetregid(gid, gid); + xsetreuid(uid, uid); + } + if (flags & EXECFLG_SETSID) + setsid(); + + if (unsetenv_vec) { + while (*unsetenv_vec) + unsetenv(*unsetenv_vec++); + } + + if (dir) + xchdir(dir); + + execvp(argv[0], argv); + if (!(flags & EXECFLG_QUIET)) + perror_msg("Can't execute '%s'", argv[0]); + exit(127); /* shell uses this exitcode in this case */ + } + + if (flags & EXECFLG_INPUT) { + close(pipe_to_child[0]); + pipefds[1] = pipe_to_child[1]; + } + if (flags & EXECFLG_OUTPUT) { + close(pipe_fm_child[1]); + pipefds[0] = pipe_fm_child[0]; + } + + return child; +} + +char *run_in_shell_and_save_output(int flags, + const char *cmd, + const char *dir, + size_t *size_p) +{ + flags |= EXECFLG_OUTPUT; + flags &= ~EXECFLG_INPUT; + + const char *argv[] = { "/bin/sh", "sh", "-c", cmd, NULL }; + int pipeout[2]; + pid_t child = fork_execv_on_steroids(flags, (char **)argv, pipeout, + /*unsetenv_vec:*/ NULL, dir, /*uid (unused):*/ 0); + + size_t pos = 0; + char *result = NULL; + while (1) { + result = (char*) xrealloc(result, pos + 4*1024 + 1); + size_t sz = safe_read(pipeout[0], result + pos, 4*1024); + if (sz <= 0) { + break; + } + pos += sz; + } + result[pos] = '\0'; + if (size_p) + *size_p = pos; + close(pipeout[0]); + waitpid(child, NULL, 0); + + return result; +} diff --git a/lib/Utils/xfuncs.cpp b/lib/Utils/xfuncs.cpp index 8621b5f..3ab3739 100644 --- a/lib/Utils/xfuncs.cpp +++ b/lib/Utils/xfuncs.cpp @@ -141,6 +141,12 @@ off_t xlseek(int fd, off_t offset, int whence) return off; } +void xchdir(const char *path) +{ + if (chdir(path)) + perror_msg_and_die("chdir(%s)", path); +} + char* xvasprintf(const char *format, va_list p) { int r; |
