From 810a7a5fa0973451881a874a08594937a8274429 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Wed, 13 Jul 2011 18:59:52 +0200 Subject: [PATCH] Make some utility functions. * Create a function that will get input from a stream, so that we can communicate with the managed proxy. * Hackish change to tor_spawn_background() so that we can specify an environ for our spawn. --- src/common/util.c | 60 +++++++++++++++++++++++++++++++++++++++++--- src/common/util.h | 16 ++++++++++-- src/test/test_util.c | 3 ++- 3 files changed, 73 insertions(+), 6 deletions(-) diff --git a/src/common/util.c b/src/common/util.c index a5a6ea3e8b..5f4472bff3 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -2958,7 +2958,7 @@ format_helper_exit_status(unsigned char child_state, int saved_errno, */ int tor_spawn_background(const char *const filename, int *stdout_read, - int *stderr_read, const char **argv) + int *stderr_read, const char **argv, const char **envp) { #ifdef MS_WINDOWS (void) filename; (void) stdout_read; (void) stderr_read; (void) argv; @@ -3068,7 +3068,10 @@ tor_spawn_background(const char *const filename, int *stdout_read, /* Call the requested program. We need the cast because execvp doesn't define argv as const, even though it does not modify the arguments */ - execvp(filename, (char *const *) argv); + if (envp) + execve(filename, (char *const *) argv, (char*const*)envp); + else + execvp(filename, (char *const *) argv); /* If we got here, the exec or open(/dev/null) failed */ @@ -3128,6 +3131,57 @@ tor_spawn_background(const char *const filename, int *stdout_read, #endif } +/** Reads from stream and stores input in buf_out making + * sure it's below count bytes. + * If the string has a trailing newline, we strip it off. + * + * This function is specifically created to handle input from managed + * proxies, according to the pluggable transports spec. Make sure it + * fits your needs before using it. + * + * Returns: + * ST_CLOSED: If the stream is closed. + * ST_EAGAIN: If there is nothing to read and we should check back later. + * ST_TERM: If something is wrong with the stream. + * ST_OKAY: If everything went okay and we got a string in buf_out. */ +enum stream_status +get_string_from_pipe(FILE *stream, char *buf_out, size_t count) +{ + char *retval; + size_t len; + + retval = fgets(buf_out, count, stream); + + if (!retval) { + if (feof(stream)) { + /* Program has closed stream (probably it exited) */ + /* TODO: check error */ + return ST_CLOSED; + } else { + if (EAGAIN == errno) { + /* Nothing more to read, try again next time */ + return ST_EAGAIN; + } else { + /* There was a problem, abandon this child process */ + return ST_TERM; + } + } + } else { + len = strlen(buf_out); + tor_assert(len>0); + + if (buf_out[len - 1] == '\n') { + /* Remove the trailing newline */ + buf_out[len - 1] = '\0'; + } + + return ST_OKAY; + } + + /* We should never get here */ + return ST_TERM; +} + /** Read from stream, and send lines to log at the specified log level. * Returns 1 if stream is closed normally, -1 if there is a error reading, and * 0 otherwise. Handles lines from tor-fw-helper and @@ -3254,7 +3308,7 @@ tor_check_port_forwarding(const char *filename, int dir_port, int or_port, /* Assume tor-fw-helper will succeed, start it later*/ time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_SUCCESS; - child_pid = tor_spawn_background(filename, &fd_out, &fd_err, argv); + child_pid = tor_spawn_background(filename, &fd_out, &fd_err, argv, NULL); if (child_pid < 0) { log_warn(LD_GENERAL, "Failed to start port forwarding helper %s", filename); diff --git a/src/common/util.h b/src/common/util.h index 2974ab7538..1b81fa3149 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -279,6 +279,16 @@ char *rate_limit_log(ratelim_t *lim, time_t now); ssize_t write_all(tor_socket_t fd, const char *buf, size_t count,int isSocket); ssize_t read_all(tor_socket_t fd, char *buf, size_t count, int isSocket); +/** Status of an I/O stream. */ +enum stream_status { + ST_OKAY, + ST_EAGAIN, + ST_TERM, + ST_CLOSED +}; + +enum stream_status get_string_from_pipe(FILE *stream, char *buf, size_t count); + /** Return values from file_status(); see that function's documentation * for details. */ typedef enum { FN_ERROR, FN_NOENT, FN_FILE, FN_DIR } file_status_t; @@ -340,14 +350,16 @@ void write_pidfile(char *filename); void tor_check_port_forwarding(const char *filename, int dir_port, int or_port, time_t now); +int tor_spawn_background(const char *const filename, int *stdout_read, + int *stderr_read, const char **argv, + const char **envp); + #ifdef MS_WINDOWS HANDLE load_windows_system_library(const TCHAR *library_name); #endif #ifdef UTIL_PRIVATE /* Prototypes for private functions only used by util.c (and unit tests) */ -int tor_spawn_background(const char *const filename, int *stdout_read, - int *stderr_read, const char **argv); void format_helper_exit_status(unsigned char child_state, int saved_errno, char *hex_errno); diff --git a/src/test/test_util.c b/src/test/test_util.c index c4769e6407..c778faacab 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -1389,7 +1389,8 @@ run_util_spawn_background(const char *argv[], const char *expected_out, char stdout_buf[100], stderr_buf[100]; /* Start the program */ - retval = tor_spawn_background(argv[0], &stdout_pipe, &stderr_pipe, argv); + retval = tor_spawn_background(argv[0], &stdout_pipe, &stderr_pipe, + argv, NULL); tt_int_op(retval, >, 0); tt_int_op(stdout_pipe, >, 0); tt_int_op(stderr_pipe, >, 0);