2017-10-19 01:34:19 +02:00
|
|
|
/* Copyright (c) 2001 Matej Pfajfar.
|
|
|
|
* Copyright (c) 2001-2004, Roger Dingledine.
|
|
|
|
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
|
|
|
* Copyright (c) 2007-2017, The Tor Project, Inc. */
|
|
|
|
/* See LICENSE for licensing information */
|
|
|
|
|
2017-11-01 18:11:45 +01:00
|
|
|
/**
|
|
|
|
* @file tor_runner.c
|
|
|
|
* @brief Experimental module to emulate tor_run_main() API with fork+exec
|
|
|
|
*
|
|
|
|
* The functions here are meant to allow the application developer to
|
|
|
|
* use the tor_run_main() API without having to care whether Tor is
|
|
|
|
* running in-process or out-of-process. For in-process usage, the
|
|
|
|
* developer can link Tor as a library and call tor_run_main(); for
|
|
|
|
* out-of-process usage, the developer can link this library instead.
|
|
|
|
*
|
|
|
|
* This interface is EXPERIMENTAL; please let us know if you would like
|
|
|
|
* to depend on it. We don't know yet whether it will be reliable in
|
|
|
|
* practice.
|
|
|
|
*/
|
|
|
|
|
2017-11-01 18:21:11 +01:00
|
|
|
/* NOTE: This module is supposed to work without the standard Tor utility
|
|
|
|
* functions. Don't add more dependencies!
|
|
|
|
*/
|
|
|
|
|
2017-10-19 01:34:19 +02:00
|
|
|
#include "tor_api.h"
|
|
|
|
#include "tor_api_internal.h"
|
|
|
|
|
|
|
|
#include "orconfig.h"
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_WAIT_H
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_SOCKET_H
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#ifndef __GNUC__
|
|
|
|
#define __attribute__(x)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static void child(const tor_main_configuration_t *cfg)
|
|
|
|
__attribute__((noreturn));
|
|
|
|
|
|
|
|
int
|
|
|
|
tor_run_main(const tor_main_configuration_t *cfg)
|
|
|
|
{
|
|
|
|
pid_t pid = fork();
|
|
|
|
if (pid == 0) {
|
|
|
|
child(cfg);
|
|
|
|
exit(0); /* Unreachable */
|
|
|
|
}
|
|
|
|
|
|
|
|
pid_t stopped_pid;
|
|
|
|
int status = 0;
|
|
|
|
do {
|
|
|
|
stopped_pid = waitpid(pid, &status, 0);
|
|
|
|
} while (stopped_pid == -1);
|
|
|
|
|
|
|
|
/* Note: these return values are not documented. No return value is
|
|
|
|
* documented! */
|
|
|
|
|
|
|
|
if (stopped_pid != pid) {
|
|
|
|
return -99999;
|
|
|
|
}
|
|
|
|
if (WIFSTOPPED(status)) {
|
|
|
|
return WEXITSTATUS(status);
|
|
|
|
}
|
|
|
|
if (WIFSIGNALED(status)) {
|
|
|
|
return -WTERMSIG(status);
|
|
|
|
}
|
|
|
|
|
|
|
|
return -999988;
|
|
|
|
}
|
|
|
|
|
2017-11-01 18:21:11 +01:00
|
|
|
/* circumlocution to avoid getting warned about calling calloc instead of
|
|
|
|
* tor_calloc. */
|
|
|
|
#define real_calloc calloc
|
|
|
|
|
2017-10-19 01:34:19 +02:00
|
|
|
static void
|
|
|
|
child(const tor_main_configuration_t *cfg)
|
|
|
|
{
|
|
|
|
/* XXXX Close unused file descriptors. */
|
|
|
|
|
2017-11-01 18:21:11 +01:00
|
|
|
char **args = real_calloc(cfg->argc+1, sizeof(char *));
|
2017-10-19 01:34:19 +02:00
|
|
|
memcpy(args, cfg->argv, cfg->argc * sizeof(char *));
|
|
|
|
args[cfg->argc] = NULL;
|
|
|
|
|
|
|
|
int rv = execv(BINDIR "/tor", args);
|
|
|
|
|
|
|
|
if (rv < 0) {
|
2018-11-13 10:09:29 +01:00
|
|
|
free(args);
|
2017-10-19 01:34:19 +02:00
|
|
|
exit(254);
|
|
|
|
} else {
|
|
|
|
abort(); /* Unreachable */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|