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.
This commit is contained in:
George Kadianakis 2011-07-13 18:59:52 +02:00
parent 73a1e98cb9
commit 810a7a5fa0
3 changed files with 73 additions and 6 deletions

View file

@ -2958,7 +2958,7 @@ format_helper_exit_status(unsigned char child_state, int saved_errno,
*/ */
int int
tor_spawn_background(const char *const filename, int *stdout_read, 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 #ifdef MS_WINDOWS
(void) filename; (void) stdout_read; (void) stderr_read; (void) argv; (void) filename; (void) stdout_read; (void) stderr_read; (void) argv;
@ -3068,6 +3068,9 @@ tor_spawn_background(const char *const filename, int *stdout_read,
/* Call the requested program. We need the cast because /* Call the requested program. We need the cast because
execvp doesn't define argv as const, even though it execvp doesn't define argv as const, even though it
does not modify the arguments */ does not modify the arguments */
if (envp)
execve(filename, (char *const *) argv, (char*const*)envp);
else
execvp(filename, (char *const *) argv); execvp(filename, (char *const *) argv);
/* If we got here, the exec or open(/dev/null) failed */ /* 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 #endif
} }
/** Reads from <b>stream</b> and stores input in <b>buf_out</b> making
* sure it's below <b>count</b> 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 <b>buf_out</b>. */
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. /** 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 * Returns 1 if stream is closed normally, -1 if there is a error reading, and
* 0 otherwise. Handles lines from tor-fw-helper 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*/ /* Assume tor-fw-helper will succeed, start it later*/
time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_SUCCESS; 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) { if (child_pid < 0) {
log_warn(LD_GENERAL, "Failed to start port forwarding helper %s", log_warn(LD_GENERAL, "Failed to start port forwarding helper %s",
filename); filename);

View file

@ -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 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); 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 /** Return values from file_status(); see that function's documentation
* for details. */ * for details. */
typedef enum { FN_ERROR, FN_NOENT, FN_FILE, FN_DIR } file_status_t; 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, void tor_check_port_forwarding(const char *filename,
int dir_port, int or_port, time_t now); 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 #ifdef MS_WINDOWS
HANDLE load_windows_system_library(const TCHAR *library_name); HANDLE load_windows_system_library(const TCHAR *library_name);
#endif #endif
#ifdef UTIL_PRIVATE #ifdef UTIL_PRIVATE
/* Prototypes for private functions only used by util.c (and unit tests) */ /* 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, void format_helper_exit_status(unsigned char child_state,
int saved_errno, char *hex_errno); int saved_errno, char *hex_errno);

View file

@ -1389,7 +1389,8 @@ run_util_spawn_background(const char *argv[], const char *expected_out,
char stdout_buf[100], stderr_buf[100]; char stdout_buf[100], stderr_buf[100];
/* Start the program */ /* 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(retval, >, 0);
tt_int_op(stdout_pipe, >, 0); tt_int_op(stdout_pipe, >, 0);
tt_int_op(stderr_pipe, >, 0); tt_int_op(stderr_pipe, >, 0);