diff options
Diffstat (limited to 'src/proc_open.c')
-rw-r--r-- | src/proc_open.c | 395 |
1 files changed, 0 insertions, 395 deletions
diff --git a/src/proc_open.c b/src/proc_open.c deleted file mode 100644 index 7e010922..00000000 --- a/src/proc_open.c +++ /dev/null @@ -1,395 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> -#include <ctype.h> -#include <errno.h> -#include "proc_open.h" - -#ifdef _WIN32 -#include <io.h> -#include <fcntl.h> -#else -#include <sys/wait.h> -#include <unistd.h> -#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 HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig) -{ - HANDLE copy, self = GetCurrentProcess(); - - if (!DuplicateHandle(self, src, self, ©, 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); - _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) { - int s; /* win32 has not ssize_t */ - - for (;;) { - buffer_prepare_append(b, 512); - if ((s = read(fd, (void *)(b->ptr + b->used), 512 - 1)) <= 0) { - break; - } - b->used += s; - } - b->ptr[b->used] = '\0'; -} -/* }}} */ -/* {{{ 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, (void *)in->ptr, in->used) < 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); - } - pipe_close(&proc.err); - - proc_close(&proc); - - return 0; -} -/* }}} */ - -/* {{{ test */ -#ifdef DEBUG_PROC_OPEN -int main() { - 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 */ -/* }}} */ - |