From 10c9b3a58cf2ed707f37ac8786783ba019cf9871 Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Tue, 2 Oct 2012 23:30:12 +0200 Subject: [PATCH] Fetch popen_noshell during fetchthirdparty, don't bundle it in our repo --- Makefile | 3 + popen-noshell/Makefile | 15 - popen-noshell/README | 21 - popen-noshell/popen_noshell-buildfix.patch | 84 ++++ popen-noshell/popen_noshell.c | 550 --------------------- popen-noshell/popen_noshell.h | 69 --- 6 files changed, 87 insertions(+), 655 deletions(-) delete mode 100644 popen-noshell/Makefile delete mode 100644 popen-noshell/README create mode 100644 popen-noshell/popen_noshell-buildfix.patch delete mode 100644 popen-noshell/popen_noshell.c delete mode 100644 popen-noshell/popen_noshell.h diff --git a/Makefile b/Makefile index 4fb4aa0a6..dc758236f 100644 --- a/Makefile +++ b/Makefile @@ -168,6 +168,9 @@ fetchthirdparty: patch -N -p0 < ../../../kpvcrlib/jpeg_decompress_struct_size.patch # MuPDF patch: use external fonts cd mupdf && patch -N -p1 < ../mupdf.patch + svn co http://popen-noshell.googlecode.com/svn/trunk/ popen-noshell + # popen_noshell patch: Make it build on recent TCs, and implement a simple Makefile for building it as a static lib + cd popen-noshell && patch -N -p0 < popen_noshell-buildfix.patch clean: rm -f *.o kpdfview slider_watcher diff --git a/popen-noshell/Makefile b/popen-noshell/Makefile deleted file mode 100644 index facd99021..000000000 --- a/popen-noshell/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -SRCS=popen_noshell.c - -OBJS:=$(SRCS:%.c=%.o) - -%.o: %.c - $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< - -all: libpopen_noshell.a - -libpopen_noshell.a: $(OBJS) - $(AR) rcs $@ $(OBJS) - -clean: - rm -rf *.o - rm -rf libpopen_noshell.a diff --git a/popen-noshell/README b/popen-noshell/README deleted file mode 100644 index 7b829d130..000000000 --- a/popen-noshell/README +++ /dev/null @@ -1,21 +0,0 @@ -/* - * popen_noshell: A faster implementation of popen() and system() for Linux. - * Copyright (c) 2009 Ivan Zahariev (famzah) - * Version: 1.0 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; under version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -This is the faster popen() alternative implementation. - -Taken from http://code.google.com/p/popen-noshell/ diff --git a/popen-noshell/popen_noshell-buildfix.patch b/popen-noshell/popen_noshell-buildfix.patch new file mode 100644 index 000000000..6f9ba1bf8 --- /dev/null +++ b/popen-noshell/popen_noshell-buildfix.patch @@ -0,0 +1,84 @@ +Index: CREDITS +=================================================================== +--- CREDITS (revision 0) ++++ CREDITS (working copy) +@@ -0,0 +1 @@ ++Taken from http://code.google.com/p/popen-noshell/ + +Property changes on: CREDITS +___________________________________________________________________ +Added: svn:keywords +## -0,0 +1 ## ++Id +\ No newline at end of property +Index: Makefile +=================================================================== +--- Makefile (revision 0) ++++ Makefile (working copy) +@@ -0,0 +1,15 @@ ++SRCS=popen_noshell.c ++ ++OBJS:=$(SRCS:%.c=%.o) ++ ++%.o: %.c ++ $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< ++ ++all: libpopen_noshell.a ++ ++libpopen_noshell.a: $(OBJS) ++ $(AR) rcs $@ $(OBJS) ++ ++clean: ++ rm -rf *.o ++ rm -rf libpopen_noshell.a + +Property changes on: Makefile +___________________________________________________________________ +Added: svn:keywords +## -0,0 +1 ## ++Id +\ No newline at end of property +Index: popen_noshell.c +=================================================================== +--- popen_noshell.c (revision 8) ++++ popen_noshell.c (working copy) +@@ -16,6 +16,10 @@ + * along with this program. If not, see . + */ + ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE ++#endif ++ + #include "popen_noshell.h" + #include + #include +@@ -28,10 +32,6 @@ + #include + #include + #include +- +-#ifndef _GNU_SOURCE +-#define _GNU_SOURCE +-#endif + #include + + /* +@@ -249,7 +249,7 @@ + * The above malloc() + align implementation is taken from: + * http://stackoverflow.com/questions/227897/solve-the-memory-alignment-in-c-interview-question-that-stumped-me + */ +- ++ + #ifndef POPEN_NOSHELL_VALGRIND_DEBUG + pid = clone(fn, stack_aligned, CLONE_VM | SIGCHLD, arg); + #else +@@ -358,7 +358,7 @@ + + pclose_arg->fp = fp; + pclose_arg->pid = pid; +- ++ + return fp; // we should never end up here + } + diff --git a/popen-noshell/popen_noshell.c b/popen-noshell/popen_noshell.c deleted file mode 100644 index ed37d07d5..000000000 --- a/popen-noshell/popen_noshell.c +++ /dev/null @@ -1,550 +0,0 @@ -/* - * popen_noshell: A faster implementation of popen() and system() for Linux. - * Copyright (c) 2009 Ivan Zahariev (famzah) - * Version: 1.0 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; under version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#include "popen_noshell.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Wish-list: - * 1) Make the "ignore_stderr" parameter a mode - ignore, leave unchanged, redirect to stdout (the last is not implemented yet) - * 2) Code a faster system(): system_noshell(), system_noshell_compat() - */ - -//#define POPEN_NOSHELL_DEBUG - -// because of C++, we can't call err() or errx() within the child, because they call exit(), and _exit() is what must be called; so we wrap -#define _ERR(EVAL, FMT, ...) \ - { \ - warn(FMT, ##__VA_ARGS__); \ - _exit(EVAL); \ - } -#define _ERRX(EVAL, FMT, ...) \ - { \ - warnx(FMT, ##__VA_ARGS__); \ - _exit(EVAL); \ - } - -int _popen_noshell_fork_mode = POPEN_NOSHELL_MODE_CLONE; - -void popen_noshell_set_fork_mode(int mode) { // see "popen_noshell.h" POPEN_NOSHELL_MODE_* constants - _popen_noshell_fork_mode = mode; -} - -int popen_noshell_reopen_fd_to_dev_null(int fd) { - int dev_null_fd; - - dev_null_fd = open("/dev/null", O_RDWR); - if (dev_null_fd < 0) return -1; - - if (close(fd) != 0) { - return -1; - } - if (dup2(dev_null_fd, fd) == -1) { - return -1; - } - if (close(dev_null_fd) != 0) { - return -1; - } - - return 0; -} - -int _popen_noshell_close_and_dup(int pipefd[2], int closed_pipefd, int target_fd) { - int dupped_pipefd; - - dupped_pipefd = (closed_pipefd == 0 ? 1 : 0); // get the FD of the other end of the pipe - - if (close(pipefd[closed_pipefd]) != 0) { - return -1; - } - - if (close(target_fd) != 0) { - return -1; - } - if (dup2(pipefd[dupped_pipefd], target_fd) == -1) { - return -1; - } - if (close(pipefd[dupped_pipefd]) != 0) { - return -1; - } - - return 0; -} - -void _pclose_noshell_free_clone_arg_memory(struct popen_noshell_clone_arg *func_args) { - char **cmd_argv; - - free((char *)func_args->file); - cmd_argv = (char **)func_args->argv; - while (*cmd_argv) { - free(*cmd_argv); - ++cmd_argv; - } - free((char **)func_args->argv); - free(func_args); -} - -void _popen_noshell_child_process( - /* We need the pointer *arg_ptr only to free whatever we reference if exec() fails and we were fork()'ed (thus memory was copied), - * not clone()'d */ - struct popen_noshell_clone_arg *arg_ptr, /* NULL if we were called by pure fork() (not because of Valgrind) */ - int pipefd_0, int pipefd_1, int read_pipe, int ignore_stderr, const char *file, const char * const *argv) { - - int closed_child_fd; - int closed_pipe_fd; - int dupped_child_fd; - int pipefd[2] = {pipefd_0, pipefd_1}; - - if (ignore_stderr) { /* ignore STDERR completely? */ - if (popen_noshell_reopen_fd_to_dev_null(STDERR_FILENO) != 0) _ERR(255, "popen_noshell_reopen_fd_to_dev_null(%d)", STDERR_FILENO); - } - - if (read_pipe) { - closed_child_fd = STDIN_FILENO; /* re-open STDIN to /dev/null */ - closed_pipe_fd = 0; /* close read end of pipe */ - dupped_child_fd = STDOUT_FILENO; /* dup the other pipe end to STDOUT */ - } else { - closed_child_fd = STDOUT_FILENO; /* ignore STDOUT completely */ - closed_pipe_fd = 1; /* close write end of pipe */ - dupped_child_fd = STDIN_FILENO; /* dup the other pipe end to STDIN */ - } - if (popen_noshell_reopen_fd_to_dev_null(closed_child_fd) != 0) { - _ERR(255, "popen_noshell_reopen_fd_to_dev_null(%d)", closed_child_fd); - } - if (_popen_noshell_close_and_dup(pipefd, closed_pipe_fd, dupped_child_fd) != 0) { - _ERR(255, "_popen_noshell_close_and_dup(%d ,%d)", closed_pipe_fd, dupped_child_fd); - } - - execvp(file, (char * const *)argv); - - /* if we are here, exec() failed */ - - warn("exec(\"%s\") inside the child", file); - -#ifdef POPEN_NOSHELL_VALGRIND_DEBUG - if (arg_ptr) { /* not NULL if we were called by clone() */ - /* but Valgrind does not support clone(), so we were actually called by fork(), thus memory was copied... */ - /* free this copied memory; if it was not Valgrind, this memory would have been shared and would belong to the parent! */ - _pclose_noshell_free_clone_arg_memory(arg_ptr); - } -#endif - - if (fflush(stdout) != 0) _ERR(255, "fflush(stdout)"); - if (fflush(stderr) != 0) _ERR(255, "fflush(stderr)"); - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); - - _exit(255); // call _exit() and not exit(), or you'll have troubles in C++ -} - -int popen_noshell_child_process_by_clone(void *raw_arg) { - struct popen_noshell_clone_arg *arg; - - arg = (struct popen_noshell_clone_arg *)raw_arg; - _popen_noshell_child_process(arg, arg->pipefd_0, arg->pipefd_1, arg->read_pipe, arg->ignore_stderr, arg->file, arg->argv); - - return 0; -} - -char ** popen_noshell_copy_argv(const char * const *argv_orig) { - int size = 1; /* there is at least one NULL element */ - char **argv; - char **argv_new; - int n; - - argv = (char **) argv_orig; - while (*argv) { - ++size; - ++argv; - } - - argv_new = (char **)malloc(sizeof(char *) * size); - if (!argv_new) return NULL; - - argv = (char **)argv_orig; - n = 0; - while (*argv) { - argv_new[n] = strdup(*argv); - if (!argv_new[n]) return NULL; - ++argv; - ++n; - } - argv_new[n] = (char *)NULL; - - return argv_new; -} - -/* - * Similar to vfork() and threading. - * Starts a process which behaves like a thread (shares global variables in memory with the parent) but - * has a different PID and can call exec(), unlike traditional threads which are not allowed to call exec(). - * - * This fork function is very resource-light because it does not copy any memory from the parent, but shares it. - * - * Like standard threads, you have to provide a start function *fn and arguments to it *arg. The life of the - * new vmfork()'ed process starts from this function. - * - * After you have reaped the child via waitpid(), you have to free() the memory at "*memory_to_free_on_child_exit". - * - * When the *fn function returns, the child process terminates. The integer returned by *fn is the exit code for the child process. - * The child process may also terminate explicitly by calling exit(2) or after receiving a fatal signal. - * - * Returns -1 on error. On success returns the PID of the newly created child. - */ -pid_t popen_noshell_vmfork(int (*fn)(void *), void *arg, void **memory_to_free_on_child_exit) { - void *stack, *stack_aligned; - pid_t pid; - - stack = malloc(POPEN_NOSHELL_STACK_SIZE + 15); - if (!stack) return -1; - *memory_to_free_on_child_exit = stack; - - /* - * On all supported Linux platforms the stack grows down, except for HP-PARISC. - * You can grep the kernel source for "STACK_GROWSUP", in order to get this information. - */ - // stack grows down, set pointer at the end of the block - stack_aligned = (void *) ((char * /*byte*/)stack + POPEN_NOSHELL_STACK_SIZE/*bytes*/); - - /* - * On all supported platforms by GNU libc, the stack is aligned to 16 bytes, except for the SuperH platform which is aligned to 8 bytes. - * You can grep the glibc source for "STACK_ALIGN", in order to get this information. - */ - stack_aligned = (void *) ( ((uintptr_t)stack_aligned+15) & ~ 0x0F ); // align to 16 bytes - - /* - * Maybe we could have used posix_memalign() here... - * Our implementation seems a bit more portable though - I've read somewhere that posix_memalign() is not supported on all platforms. - * The above malloc() + align implementation is taken from: - * http://stackoverflow.com/questions/227897/solve-the-memory-alignment-in-c-interview-question-that-stumped-me - */ - -#ifndef POPEN_NOSHELL_VALGRIND_DEBUG - pid = clone(fn, stack_aligned, CLONE_VM | SIGCHLD, arg); -#else - pid = fork(); // Valgrind does not support arbitrary clone() calls, so we use fork for the tests -#endif - if (pid == -1) return -1; - - if (pid == 0) { // child -#ifdef POPEN_NOSHELL_VALGRIND_DEBUG - free(stack); // this is a copy because of the fork(), we are not using it at all - _exit(fn(arg)); // if we used fork() because of Valgrind, invoke the child function manually; always use _exit() -#endif - errx(EXIT_FAILURE, "This must never happen"); - } // child life ends here, for sure - - return pid; -} - -/* - * Pipe stream to or from process. Similar to popen(), only much faster. - * - * "file" is the command to be executed. It is searched within the PATH environment variable. - * "argv[]" is an array to "char *" elements which are passed as command-line arguments. - * Note: The first element must be the same string as "file". - * Note: The last element must be a (char *)NULL terminating element. - * "type" specifies if we are reading from the STDOUT or writing to the STDIN of the executed command "file". Use "r" for reading, "w" for writing. - * "pid" is a pointer to an interger. The PID of the child process is stored there. - * "ignore_stderr" has the following meaning: - * 0: leave STDERR of the child process attached to the current STDERR of the parent process - * 1: ignore the STDERR of the child process - * - * This function is not very sustainable on failures. This means that if it fails for some reason (out of memory, no such executable, etc.), - * you are probably in trouble, because the function allocated some memory or file descriptors and never released them. - * Normally, this function should never fail. - * - * Returns NULL on any error, "errno" is set appropriately. - * On success, a stream pointer is returned. - * When you are done working with the stream, you have to close it by calling pclose_noshell(), or else you will leave zombie processes. - */ -FILE *popen_noshell(const char *file, const char * const *argv, const char *type, struct popen_noshell_pass_to_pclose *pclose_arg, int ignore_stderr) { - int read_pipe; - int pipefd[2]; // 0 -> READ, 1 -> WRITE ends - pid_t pid; - FILE *fp; - - memset(pclose_arg, 0, sizeof(struct popen_noshell_pass_to_pclose)); - - if (strcmp(type, "r") == 0) { - read_pipe = 1; - } else if (strcmp(type, "w") == 0) { - read_pipe = 0; - } else { - errno = EINVAL; - return NULL; - } - - if (pipe(pipefd) != 0) return NULL; - - if (_popen_noshell_fork_mode) { // use fork() - - pid = fork(); - if (pid == -1) return NULL; - if (pid == 0) { - _popen_noshell_child_process(NULL, pipefd[0], pipefd[1], read_pipe, ignore_stderr, file, argv); - errx(EXIT_FAILURE, "This must never happen"); - } // child life ends here, for sure - - } else { // use clone() - - struct popen_noshell_clone_arg *arg = NULL; - - arg = (struct popen_noshell_clone_arg*) malloc(sizeof(struct popen_noshell_clone_arg)); - if (!arg) return NULL; - - /* Copy memory structures, so that nobody can free() our memory while we use it in the child! */ - arg->pipefd_0 = pipefd[0]; - arg->pipefd_1 = pipefd[1]; - arg->read_pipe = read_pipe; - arg->ignore_stderr = ignore_stderr; - arg->file = strdup(file); - if (!arg->file) return NULL; - arg->argv = (const char * const *)popen_noshell_copy_argv(argv); - if (!arg->argv) return NULL; - - pclose_arg->free_clone_mem = 1; - pclose_arg->func_args = arg; - pclose_arg->stack = NULL; // we will populate it below - - pid = popen_noshell_vmfork(&popen_noshell_child_process_by_clone, arg, &(pclose_arg->stack)); - if (pid == -1) return NULL; - - } // done: using clone() - - /* parent process */ - - if (read_pipe) { - if (close(pipefd[1/*write*/]) != 0) return NULL; - fp = fdopen(pipefd[0/*read*/], "r"); - } else { // write_pipe - if (close(pipefd[0/*read*/]) != 0) return NULL; - fp = fdopen(pipefd[1/*write*/], "w"); - } - if (fp == NULL) { - return NULL; // fdopen() failed - } - - pclose_arg->fp = fp; - pclose_arg->pid = pid; - - return fp; // we should never end up here -} - -int popen_noshell_add_ptr_to_argv(char ***argv, int *count, char *start) { - *count += 1; - *argv = (char **) realloc(*argv, *count * sizeof(char **)); - if (*argv == NULL) { - return -1; - } - *(*argv + *count - 1) = start; - return 0; -} - -int _popen_noshell_add_token(char ***argv, int *count, char *start, char *command, int *j) { - if (start != NULL && command + *j - 1 - start >= 0) { - command[*j] = '\0'; // terminate the token in memory - *j += 1; -#ifdef POPEN_NOSHELL_DEBUG - printf("Token: %s\n", start); -#endif - if (popen_noshell_add_ptr_to_argv(argv, count, start) != 0) { - return -1; - } - } - return 0; -} - -#define _popen_noshell_split_return_NULL { if (argv != NULL) free(argv); if (command != NULL) free(command); return NULL; } -char ** popen_noshell_split_command_to_argv(const char *command_original, char **free_this_buf) { - char *command; - size_t i, len; - char *start = NULL; - char c; - char **argv = NULL; - int count = 0; - const char _popen_bash_meta_characters[] = "!\\$`\n|&;()<>"; - int in_sq = 0; - int in_dq = 0; - int j = 0; -#ifdef POPEN_NOSHELL_DEBUG - char **tmp; -#endif - - command = (char *)calloc(strlen(command_original) + 1, sizeof(char)); - if (!command) _popen_noshell_split_return_NULL; - - *free_this_buf = command; - - len = strlen(command_original); // get the original length - j = 0; - for (i = 0; i < len; ++i) { - if (!start) start = command + j; - c = command_original[i]; - - if (index(_popen_bash_meta_characters, c) != NULL) { - errno = EINVAL; - _popen_noshell_split_return_NULL; - } - - if (c == ' ' || c == '\t') { - if (in_sq || in_dq) { - command[j++] = c; - continue; - } - - // new token - if (_popen_noshell_add_token(&argv, &count, start, command, &j) != 0) { - _popen_noshell_split_return_NULL; - } - start = NULL; - continue; - } - - if (c == '\'' && !in_dq) { - in_sq = !in_sq; - continue; - } - if (c == '"' && !in_sq) { - in_dq = !in_dq; - continue; - } - - command[j++] = c; - } - if (in_sq || in_dq) { // unmatched single/double quote - errno = EINVAL; - _popen_noshell_split_return_NULL; - } - - if (_popen_noshell_add_token(&argv, &count, start, command, &j) != 0) { - _popen_noshell_split_return_NULL; - } - - if (count == 0) { - errno = EINVAL; - _popen_noshell_split_return_NULL; - } - - if (popen_noshell_add_ptr_to_argv(&argv, &count, NULL) != 0) { // NULL-terminate the list - _popen_noshell_split_return_NULL; - } - -#ifdef POPEN_NOSHELL_DEBUG - tmp = argv; - while (*tmp) { - printf("ARGV: |%s|\n", *tmp); - ++tmp; - } -#endif - - return argv; - - /* Example test strings: - "a'zz bb edd" - " abc ff " - " abc ff" - "' abc ff ' " - "" - " " - " '" - "ab\\c" - "ls -la /proc/self/fd 'z' 'ab'g'z\" zz' \" abc'd\" ' ab\"c def '" - */ -} - -/* - * Pipe stream to or from process. Similar to popen(), only much faster. - * - * This is simpler than popen_noshell() but is more INSECURE. - * Since shells have very complicated expansion, quoting and word splitting algorithms, we do NOT try to re-implement them here. - * This function does NOT support any special characters. It will immediately return an error if such symbols are encountered in "command". - * The "command" is split only by space and tab delimiters. The special symbols are pre-defined in _popen_bash_meta_characters[]. - * The only special characters supported are single and double quotes. You can enclose arguments in quotes and they should be splitted correctly. - * - * If possible, use popen_noshell() because of its better security. - * - * "command" is the command and its arguments to be executed. The command is searched within the PATH environment variable. - * The whole "command" string is parsed and splitted, so that it can be directly given to popen_noshell() and resp. to exec(). - * This parsing is very simple and may contain bugs (see above). If possible, use popen_noshell() directly. - * "type" specifies if we are reading from the STDOUT or writing to the STDIN of the executed command. Use "r" for reading, "w" for writing. - * "pid" is a pointer to an interger. The PID of the child process is stored there. - * - * Returns NULL on any error, "errno" is set appropriately. - * On success, a stream pointer is returned. - * When you are done working with the stream, you have to close it by calling pclose_noshell(), or else you will leave zombie processes. - */ -FILE *popen_noshell_compat(const char *command, const char *type, struct popen_noshell_pass_to_pclose *pclose_arg) { - char **argv; - FILE *fp; - char *to_free; - - argv = popen_noshell_split_command_to_argv(command, &to_free); - if (!argv) { - if (to_free) free(to_free); - return NULL; - } - - fp = popen_noshell(argv[0], (const char * const *)argv, type, pclose_arg, 0); - - free(to_free); - free(argv); - - return fp; -} - -/* - * You have to call this function after you have done working with the FILE pointer "fp" returned by popen_noshell() or by popen_noshell_compat(). - * - * Returns -1 on any error, "errno" is set appropriately. - * Returns the "status" of the child process as returned by waitpid(). - */ -int pclose_noshell(struct popen_noshell_pass_to_pclose *arg) { - int status; - - if (fclose(arg->fp) != 0) { - return -1; - } - - if (waitpid(arg->pid, &status, 0) != arg->pid) { - return -1; - } - - if (arg->free_clone_mem) { - free(arg->stack); - _pclose_noshell_free_clone_arg_memory(arg->func_args); - } - - return status; -} diff --git a/popen-noshell/popen_noshell.h b/popen-noshell/popen_noshell.h deleted file mode 100644 index a2eeb3c6e..000000000 --- a/popen-noshell/popen_noshell.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * popen_noshell: A faster implementation of popen() and system() for Linux. - * Copyright (c) 2009 Ivan Zahariev (famzah) - * Version: 1.0 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; under version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -#ifndef POPEN_NOSHELL_H -#define POPEN_NOSHELL_H - -#include -#include -#include - -/* stack for the child process before it does exec() */ -#define POPEN_NOSHELL_STACK_SIZE 8*1024*1024 /* currently most Linux distros set this to 8 MBytes */ - -/* constants to use with popen_noshell_set_fork_mode() */ -#define POPEN_NOSHELL_MODE_CLONE 0 /* default, faster */ -#define POPEN_NOSHELL_MODE_FORK 1 /* slower */ - -struct popen_noshell_clone_arg { - int pipefd_0; - int pipefd_1; - int read_pipe; - int ignore_stderr; - const char *file; - const char * const *argv; -}; - -struct popen_noshell_pass_to_pclose { - FILE *fp; - pid_t pid; - int free_clone_mem; - void *stack; - struct popen_noshell_clone_arg *func_args; -}; - -/*************************** - * PUBLIC FUNCTIONS FOLLOW * - ***************************/ - -/* this is the native function call */ -FILE *popen_noshell(const char *file, const char * const *argv, const char *type, struct popen_noshell_pass_to_pclose *pclose_arg, int ignore_stderr); - -/* more insecure, but more compatible with popen() */ -FILE *popen_noshell_compat(const char *command, const char *type, struct popen_noshell_pass_to_pclose *pclose_arg); - -/* call this when you have finished reading and writing from/to the child process */ -int pclose_noshell(struct popen_noshell_pass_to_pclose *arg); /* the pclose() equivalent */ - -/* this is the innovative faster vmfork() which shares memory with the parent and is very resource-light; see the source code for documentation */ -pid_t popen_noshell_vmfork(int (*fn)(void *), void *arg, void **memory_to_free_on_child_exit); - -/* used only for benchmarking purposes */ -void popen_noshell_set_fork_mode(int mode); - -#endif