mirror of https://github.com/Icinga/icinga2.git
Remove libpopen_noshell.
This commit is contained in:
parent
69a2842d4e
commit
d7492ab823
|
@ -130,7 +130,6 @@ third-party/Makefile
|
||||||
third-party/cJSON/Makefile
|
third-party/cJSON/Makefile
|
||||||
third-party/execvpe/Makefile
|
third-party/execvpe/Makefile
|
||||||
third-party/mmatch/Makefile
|
third-party/mmatch/Makefile
|
||||||
third-party/popen-noshell/Makefile
|
|
||||||
tools/Makefile
|
tools/Makefile
|
||||||
])
|
])
|
||||||
AC_OUTPUT([
|
AC_OUTPUT([
|
||||||
|
|
|
@ -92,8 +92,7 @@ libbase_la_CPPFLAGS = \
|
||||||
$(OPENSSL_INCLUDES) \
|
$(OPENSSL_INCLUDES) \
|
||||||
-I${top_srcdir}/third-party/execvpe \
|
-I${top_srcdir}/third-party/execvpe \
|
||||||
-I${top_srcdir}/third-party/mmatch \
|
-I${top_srcdir}/third-party/mmatch \
|
||||||
-I${top_srcdir}/third-party/cJSON \
|
-I${top_srcdir}/third-party/cJSON
|
||||||
-I${top_srcdir}/third-party/popen-noshell
|
|
||||||
|
|
||||||
libbase_la_LDFLAGS = \
|
libbase_la_LDFLAGS = \
|
||||||
$(BOOST_LDFLAGS) \
|
$(BOOST_LDFLAGS) \
|
||||||
|
@ -110,5 +109,4 @@ libbase_la_LIBADD = \
|
||||||
$(BOOST_SYSTEM_LIB) \
|
$(BOOST_SYSTEM_LIB) \
|
||||||
${top_builddir}/third-party/execvpe/libexecvpe.la \
|
${top_builddir}/third-party/execvpe/libexecvpe.la \
|
||||||
${top_builddir}/third-party/mmatch/libmmatch.la \
|
${top_builddir}/third-party/mmatch/libmmatch.la \
|
||||||
${top_builddir}/third-party/cJSON/libcJSON.la \
|
${top_builddir}/third-party/cJSON/libcJSON.la
|
||||||
${top_builddir}/third-party/popen-noshell/libpopen_noshell.la
|
|
||||||
|
|
|
@ -4,5 +4,4 @@ SUBDIRS = \
|
||||||
ltdl \
|
ltdl \
|
||||||
cJSON \
|
cJSON \
|
||||||
execvpe \
|
execvpe \
|
||||||
mmatch \
|
mmatch
|
||||||
popen-noshell
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
## Process this file with automake to produce Makefile.in
|
|
||||||
|
|
||||||
|
|
||||||
pkglib_LTLIBRARIES = \
|
|
||||||
libpopen_noshell.la
|
|
||||||
|
|
||||||
libpopen_noshell_la_SOURCES = \
|
|
||||||
popen_noshell.c \
|
|
||||||
popen_noshell.h
|
|
||||||
|
|
||||||
libpopen_noshell_la_LDFLAGS = \
|
|
||||||
-z now
|
|
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
* popen_noshell: A faster implementation of popen() and system() for Linux.
|
|
||||||
* Copyright (c) 2009 Ivan Zahariev (famzah)
|
|
||||||
* Copyright (c) 2012 Gunnar Beutner
|
|
||||||
* 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 <http://www.gnu.org/licenses>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
This is the faster popen() alternative implementation.
|
|
||||||
|
|
||||||
The package provides the following files:
|
|
||||||
* The C implementation of the library:
|
|
||||||
popen_noshell.c
|
|
||||||
popen_noshell.h
|
|
||||||
|
|
||||||
Compile instructions are included in each file.
|
|
|
@ -1,412 +0,0 @@
|
||||||
/*
|
|
||||||
* popen_noshell: A faster implementation of popen() and system() for Linux.
|
|
||||||
* Copyright (c) 2009 Ivan Zahariev (famzah)
|
|
||||||
* Copyright (c) 2012 Gunnar Beutner
|
|
||||||
* 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 <http://www.gnu.org/licenses>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "popen_noshell.h"
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <err.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void popen_noshell_child_process(
|
|
||||||
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);
|
|
||||||
|
|
||||||
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++
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
pid = vfork();
|
|
||||||
if (pid == -1) return NULL;
|
|
||||||
if (pid == 0) {
|
|
||||||
popen_noshell_child_process(pipefd[0], pipefd[1], read_pipe, ignore_stderr, file, argv);
|
|
||||||
errx(EXIT_FAILURE, "This must never happen");
|
|
||||||
} // child life ends here, for sure
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static 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); *free_this_buf = NULL; 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
/*
|
|
||||||
* popen_noshell: A faster implementation of popen() and system() for Linux.
|
|
||||||
* Copyright (c) 2009 Ivan Zahariev (famzah)
|
|
||||||
* Copyright (c) 2012 Gunnar Beutner
|
|
||||||
* 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 <http://www.gnu.org/licenses>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef POPEN_NOSHELL_H
|
|
||||||
#define POPEN_NOSHELL_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
struct popen_noshell_pass_to_pclose {
|
|
||||||
FILE *fp;
|
|
||||||
pid_t pid;
|
|
||||||
};
|
|
||||||
|
|
||||||
/***************************
|
|
||||||
* 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 */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif /* __cplusplus */
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in New Issue