Browse Source

[core] remove proc_open.[ch], reduce stdio.h use

personal/stbuehler/fix-fdevent
Glenn Strauss 3 years ago
parent
commit
a46bc4f5de
  1. 1
      .gitignore
  2. 1
      src/CMakeLists.txt
  3. 10
      src/Makefile.am
  4. 2
      src/SConscript
  5. 5
      src/array.c
  6. 41
      src/configfile.c
  7. 1
      src/data_array.c
  8. 1
      src/meson.build
  9. 411
      src/proc_open.c
  10. 30
      src/proc_open.h

1
.gitignore

@ -43,7 +43,6 @@ m4/
missing
mod_ssi_exprparser.c
mod_ssi_exprparser.h
proc_open
scgi-responder
sconsbuild/
stamp-h1

1
src/CMakeLists.txt

@ -604,7 +604,6 @@ add_executable(lighttpd
configfile.c
configparser.c
request.c
proc_open.c
${COMMON_SRC}
)
set(L_INSTALL_TARGETS ${L_INSTALL_TARGETS} lighttpd)

10
src/Makefile.am

@ -1,6 +1,6 @@
AM_CFLAGS = $(FAM_CFLAGS) $(LIBUNWIND_CFLAGS)
noinst_PROGRAMS=proc_open test_buffer test_base64 test_configfile test_request
noinst_PROGRAMS=test_buffer test_base64 test_configfile test_request
sbin_PROGRAMS=lighttpd lighttpd-angel
LEMON=$(top_builddir)/src/lemon$(BUILD_EXEEXT)
@ -84,7 +84,7 @@ src = server.c response.c connections.c \
inet_ntop_cache.c \
network.c \
network_write.c \
configfile.c configparser.c proc_open.c
configfile.c configparser.c
lib_LTLIBRARIES =
@ -397,7 +397,7 @@ hdr = server.h base64.h buffer.h network.h log.h http_kv.h keyvalue.h \
rand.h \
sys-endian.h sys-mmap.h sys-socket.h sys-strings.h \
mod_cml.h mod_cml_funcs.h \
safe_memclear.h sock_addr.h splaytree.h proc_open.h status_counter.h \
safe_memclear.h sock_addr.h splaytree.h status_counter.h \
mod_magnet_cache.h
@ -511,10 +511,6 @@ lighttpd_LDFLAGS = -export-dynamic
endif
proc_open_SOURCES = proc_open.c buffer.c
proc_open_LDADD = $(LIBUNWIND_LIBS)
proc_open_CPPFLAGS= -DDEBUG_PROC_OPEN
test_buffer_SOURCES = test_buffer.c buffer.c
test_buffer_LDADD = $(LIBUNWIND_LIBS)

2
src/SConscript

@ -83,7 +83,7 @@ src = Split("server.c response.c connections.c \
inet_ntop_cache.c \
network.c \
network_write.c \
configfile.c configparser.c request.c proc_open.c")
configfile.c configparser.c request.c")
lemon = env.Program('lemon', 'lemon.c', LIBS = GatherLibs(env))

5
src/array.c

@ -4,7 +4,6 @@
#include "buffer.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
@ -317,6 +316,10 @@ int array_is_kvstring(array *a) {
return 1;
}
#include <stdio.h>
void array_print_indent(int depth) {
int i;
for (i = 0; i < depth; i ++) {

41
src/configfile.c

@ -7,7 +7,6 @@
#include "configparser.h"
#include "configfile.h"
#include "proc_open.h"
#include "request.h"
#include "stat_cache.h"
@ -1103,9 +1102,7 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
return 1;
} else if (t->offset < t->size) {
fprintf(stderr, "%s.%d: %d, %s\n",
__FILE__, __LINE__,
tid, token->ptr);
log_error_write(srv, __FILE__, __LINE__, "Dsb", tid, ",", token);
}
return 0;
}
@ -1261,9 +1258,10 @@ static char* getCWD(void) {
int config_parse_cmd(server *srv, config_t *context, const char *cmd) {
tokenizer_t t;
int ret;
int ret = 0;
FILE *fp;
buffer *source;
buffer *out;
buffer *out = srv->tmp_buf;
char *oldpwd;
if (NULL == (oldpwd = getCWD())) {
@ -1282,19 +1280,38 @@ int config_parse_cmd(server *srv, config_t *context, const char *cmd) {
}
source = buffer_init_string(cmd);
out = buffer_init();
if (0 != proc_open_buffer(cmd, NULL, out, NULL)) {
log_error_write(srv, __FILE__, __LINE__, "sbss",
"opening", source, "failed:", strerror(errno));
fp = popen(cmd, "r");
if (NULL == fp) {
log_error_write(srv, __FILE__, __LINE__, "SSss",
"popen \"", cmd, "\"failed:", strerror(errno));
ret = -1;
} else {
}
else {
size_t rd;
buffer_string_set_length(out, 0);
do {
rd = fread(buffer_string_prepare_append(out, 1023), 1, 1023, fp);
buffer_commit(out, rd);
} while (0 != rd && !ferror(fp));
if (0 != rd || !feof(fp)) {
log_error_write(srv, __FILE__, __LINE__, "SSss",
"fread \"", cmd, "\"failed:", strerror(errno));
ret = -1;
}
if (0 != pclose(fp)) {
log_error_write(srv, __FILE__, __LINE__, "SSss",
"pclose \"", cmd, "\"failed:", strerror(errno));
ret = -1;
}
}
if (-1 != ret) {
tokenizer_init(&t, source, CONST_BUF_LEN(out));
ret = config_parse(srv, context, &t);
}
buffer_free(source);
buffer_free(out);
if (0 != chdir(oldpwd)) {
log_error_write(srv, __FILE__, __LINE__, "sss",
"cannot change directory to", oldpwd, strerror(errno));

1
src/data_array.c

@ -3,7 +3,6 @@
#include "array.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
static data_unset *data_array_copy(const data_unset *s) {

1
src/meson.build

@ -585,7 +585,6 @@ main_src = [
'inet_ntop_cache.c',
'network_write.c',
'network.c',
'proc_open.c',
'request.c',
'response.c',
'server.c',

411
src/proc_open.c

@ -1,411 +0,0 @@
#include "first.h"
#include "proc_open.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#ifdef WIN32
# include <io.h>
# include <fcntl.h>
#else
# include <sys/wait.h>
# include <unistd.h>
#endif
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifdef WIN32
/* {{{ win32 stuff */
# define SHELLENV "ComSpec"
# define SECURITY_DC , SECURITY_ATTRIBUTES *security
# define SECURITY_CC , security
# define pipe(pair) (CreatePipe(&pair[0], &pair[1], security, 2048L) ? 0 : -1)
static inline HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
{
HANDLE copy, self = GetCurrentProcess();
if (!DuplicateHandle(self, src, self, &copy, 0, inherit, DUPLICATE_SAME_ACCESS |
(closeorig ? DUPLICATE_CLOSE_SOURCE : 0)))
return NULL;
return copy;
}
# define close_descriptor(fd) CloseHandle(fd)
static void pipe_close_parent(pipe_t *p) {
/* don't let the child inherit the parent side of the pipe */
p->parent = dup_handle(p->parent, FALSE, TRUE);
}
static void pipe_close_child(pipe_t *p) {
close_descriptor(p->child);
p->fd = _open_osfhandle((long)p->parent,
(p->fd == 0 ? O_RDONLY : O_WRONLY)|O_BINARY);
}
/* }}} */
#else /* WIN32 */
/* {{{ unix way */
# define SHELLENV "SHELL"
# define SECURITY_DC
# define SECURITY_CC
# define close_descriptor(fd) close(fd)
static void pipe_close_parent(pipe_t *p) {
/* don't close stdin */
close_descriptor(p->parent);
if (dup2(p->child, p->fd) != p->fd) {
perror("pipe_child dup2");
} else {
close_descriptor(p->child);
p->child = p->fd;
}
}
static void pipe_close_child(pipe_t *p) {
close_descriptor(p->child);
p->fd = p->parent;
}
/* }}} */
#endif /* WIN32 */
/* {{{ pipe_close */
static void pipe_close(pipe_t *p) {
close_descriptor(p->parent);
close_descriptor(p->child);
#ifdef WIN32
close(p->fd);
#endif
}
/* }}} */
/* {{{ pipe_open */
static int pipe_open(pipe_t *p, int fd SECURITY_DC) {
descriptor_t newpipe[2];
if (0 != pipe(newpipe)) {
fprintf(stderr, "can't open pipe");
return -1;
}
if (0 == fd) {
p->parent = newpipe[1]; /* write */
p->child = newpipe[0]; /* read */
} else {
p->parent = newpipe[0]; /* read */
p->child = newpipe[1]; /* write */
}
p->fd = fd;
return 0;
}
/* }}} */
/* {{{ proc_open_pipes */
static int proc_open_pipes(proc_handler_t *proc SECURITY_DC) {
if (pipe_open(&(proc->in), 0 SECURITY_CC) != 0) {
return -1;
}
if (pipe_open(&(proc->out), 1 SECURITY_CC) != 0) {
return -1;
}
if (pipe_open(&(proc->err), 2 SECURITY_CC) != 0) {
return -1;
}
return 0;
}
/* }}} */
/* {{{ proc_close_pipes */
static void proc_close_pipes(proc_handler_t *proc) {
pipe_close(&proc->in);
pipe_close(&proc->out);
pipe_close(&proc->err);
}
/* }}} */
/* {{{ proc_close_parents */
static void proc_close_parents(proc_handler_t *proc) {
pipe_close_parent(&proc->in);
pipe_close_parent(&proc->out);
pipe_close_parent(&proc->err);
}
/* }}} */
/* {{{ proc_close_childs */
static void proc_close_childs(proc_handler_t *proc) {
pipe_close_child(&proc->in);
pipe_close_child(&proc->out);
pipe_close_child(&proc->err);
}
/* }}} */
#ifdef WIN32
/* {{{ proc_close */
int proc_close(proc_handler_t *proc) {
proc_pid_t child = proc->child;
DWORD wstatus;
proc_close_pipes(proc);
WaitForSingleObject(child, INFINITE);
GetExitCodeProcess(child, &wstatus);
CloseHandle(child);
return wstatus;
}
/* }}} */
/* {{{ proc_open */
int proc_open(proc_handler_t *proc, const char *command) {
PROCESS_INFORMATION pi;
STARTUPINFO si;
BOOL procok;
SECURITY_ATTRIBUTES security;
const char *shell = NULL;
const char *windir = NULL;
buffer *cmdline;
if (NULL == (shell = getenv(SHELLENV)) &&
NULL == (windir = getenv("SystemRoot")) &&
NULL == (windir = getenv("windir"))) {
fprintf(stderr, "One of %s,%%SystemRoot,%%windir is required", SHELLENV);
return -1;
}
/* we use this to allow the child to inherit handles */
memset(&security, 0, sizeof(security));
security.nLength = sizeof(security);
security.bInheritHandle = TRUE;
security.lpSecurityDescriptor = NULL;
if (proc_open_pipes(proc, &security) != 0) {
return -1;
}
proc_close_parents(proc);
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = proc->in.child;
si.hStdOutput = proc->out.child;
si.hStdError = proc->err.child;
memset(&pi, 0, sizeof(pi));
cmdline = buffer_init();
if (shell) {
buffer_append_string(cmdline, shell);
} else {
buffer_append_string(cmdline, windir);
buffer_append_string_len(cmdline, CONST_STR_LEN("\\system32\\cmd.exe"));
}
buffer_append_string_len(cmdline, CONST_STR_LEN(" /c "));
buffer_append_string(cmdline, command);
procok = CreateProcess(NULL, cmdline->ptr, &security, &security, TRUE,
NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
if (FALSE == procok) {
fprintf(stderr, "failed to CreateProcess: %s", cmdline->ptr);
buffer_free(cmdline);
return -1;
}
buffer_free(cmdline);
proc->child = pi.hProcess;
CloseHandle(pi.hThread);
proc_close_childs(proc);
return 0;
}
/* }}} */
#else /* WIN32 */
/* {{{ proc_close */
int proc_close(proc_handler_t *proc) {
pid_t child = proc->child;
int wstatus;
pid_t wait_pid;
proc_close_pipes(proc);
do {
wait_pid = waitpid(child, &wstatus, 0);
} while (wait_pid == -1 && errno == EINTR);
if (wait_pid == -1) {
return -1;
} else {
if (WIFEXITED(wstatus))
wstatus = WEXITSTATUS(wstatus);
}
return wstatus;
}
/* }}} */
/* {{{ proc_open */
int proc_open(proc_handler_t *proc, const char *command) {
pid_t child;
const char *shell;
if (NULL == (shell = getenv(SHELLENV))) {
shell = "/bin/sh";
}
if (proc_open_pipes(proc) != 0) {
return -1;
}
/* the unix way */
child = fork();
if (child == 0) {
/* this is the child process */
/* close those descriptors that we just opened for the parent stuff,
* dup new descriptors into required descriptors and close the original
* cruft
*/
proc_close_parents(proc);
execl(shell, shell, "-c", command, (char *)NULL);
fprintf(stderr, "failed to execute shell: %s -c %s: %s\n", shell, command, strerror(errno));
_exit(127);
} else if (child < 0) {
fprintf(stderr, "failed to forking");
proc_close(proc);
return -1;
} else {
proc->child = child;
proc_close_childs(proc);
return 0;
}
}
/* }}} */
#endif /* WIN32 */
/* {{{ proc_read_fd_to_buffer */
static void proc_read_fd_to_buffer(int fd, buffer *b) {
ssize_t s;
for (;;) {
buffer_string_prepare_append(b, 1024);
if ((s = read(fd, (void *)(b->ptr + buffer_string_length(b)), buffer_string_space(b))) <= 0) {
break;
}
buffer_commit(b, s);
}
}
/* }}} */
/* {{{ proc_open_buffer */
int proc_open_buffer(const char *command, buffer *in, buffer *out, buffer *err) {
proc_handler_t proc;
if (proc_open(&proc, command) != 0) {
return -1;
}
if (in) {
if (write(proc.in.fd, CONST_BUF_LEN(in)) < 0) {
perror("error writing pipe");
return -1;
}
}
pipe_close(&proc.in);
if (out) {
proc_read_fd_to_buffer(proc.out.fd, out);
}
pipe_close(&proc.out);
if (err) {
proc_read_fd_to_buffer(proc.err.fd, err);
} else {
buffer *tmp = buffer_init();
proc_read_fd_to_buffer(proc.err.fd, tmp);
if (!buffer_string_is_empty(tmp) && write(2, CONST_BUF_LEN(tmp)) < 0) {
perror("error writing pipe");
buffer_free(tmp);
return -1;
}
buffer_free(tmp);
}
pipe_close(&proc.err);
proc_close(&proc);
return 0;
}
/* }}} */
/* {{{ test */
#ifdef DEBUG_PROC_OPEN
int main(void) {
proc_handler_t proc;
buffer *in = buffer_init(), *out = buffer_init(), *err = buffer_init();
int wstatus;
#define FREE() do { \
buffer_free(in); \
buffer_free(out); \
buffer_free(err); \
} while (0)
#define RESET() do { \
buffer_reset(in); \
buffer_reset(out); \
buffer_reset(err); \
wstatus = proc_close(&proc); \
if (0&&wstatus != 0) { \
fprintf(stdout, "exitstatus %d\n", wstatus); \
return __LINE__ - 200; \
} \
} while (0)
#define ERROR_OUT() do { \
fprintf(stdout, "failed opening proc\n"); \
wstatus = proc_close(&proc); \
fprintf(stdout, "exitstatus %d\n", wstatus); \
FREE(); \
return __LINE__ - 300; \
} while (0)
#ifdef WIN32
#define CMD_CAT "pause"
#else
#define CMD_CAT "cat"
#endif
do {
fprintf(stdout, "test: echo 123 without read\n");
if (proc_open(&proc, "echo 321") != 0) {
ERROR_OUT();
}
close_descriptor(proc.in.parent);
close_descriptor(proc.out.parent);
close_descriptor(proc.err.parent);
RESET();
fprintf(stdout, "test: echo 321 with read\n"); fflush(stdout);
if (proc_open_buffer("echo 321", NULL, out, err) != 0) {
ERROR_OUT();
}
fprintf(stdout, "result: ->%s<-\n\n", out->ptr); fflush(stdout);
RESET();
fprintf(stdout, "test: echo 123 | " CMD_CAT "\n"); fflush(stdout);
buffer_copy_string_len(in, CONST_STR_LEN("123\n"));
if (proc_open_buffer(CMD_CAT, in, out, err) != 0) {
ERROR_OUT();
}
fprintf(stdout, "result: ->%s<-\n\n", out->ptr); fflush(stdout);
RESET();
} while (0);
#undef RESET
#undef ERROR_OUT
fprintf(stdout, "ok\n");
FREE();
return 0;
}
#endif /* DEBUG_PROC_OPEN */
/* }}} */

30
src/proc_open.h

@ -1,30 +0,0 @@
#ifndef LI_PROC_OPEN_H
#define LI_PROC_OPEN_H
#include "first.h"
#include "buffer.h"
#ifdef WIN32
#include <windows.h>
typedef HANDLE descriptor_t;
typedef HANDLE proc_pid_t;
#else
typedef int descriptor_t;
typedef pid_t proc_pid_t;
#endif
typedef struct {
descriptor_t parent, child;
int fd;
} pipe_t;
typedef struct {
pipe_t in, out, err;
proc_pid_t child;
} proc_handler_t;
int proc_close(proc_handler_t *ht);
int proc_open(proc_handler_t *ht, const char *command);
int proc_open_buffer(const char *command, buffer *in, buffer *out, buffer *err);
#endif
Loading…
Cancel
Save