Add changes file for bug40642.
[tor.git] / src / tools / tor_runner.c
blob360f9c57ac75d4c74290745ec74d0c568739291d
1 /* Copyright (c) 2001 Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 * Copyright (c) 2007-2021, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
7 /**
8 * @file tor_runner.c
9 * @brief Experimental module to emulate tor_run_main() API with fork+exec
11 * The functions here are meant to allow the application developer to
12 * use the tor_run_main() API without having to care whether Tor is
13 * running in-process or out-of-process. For in-process usage, the
14 * developer can link Tor as a library and call tor_run_main(); for
15 * out-of-process usage, the developer can link this library instead.
17 * This interface is EXPERIMENTAL; please let us know if you would like
18 * to depend on it. We don't know yet whether it will be reliable in
19 * practice.
22 /* NOTE: This module is supposed to work without the standard Tor utility
23 * functions. Don't add more dependencies!
26 #include "feature/api/tor_api.h"
27 #include "feature/api/tor_api_internal.h"
29 #include "orconfig.h"
30 #ifdef HAVE_UNISTD_H
31 #include <unistd.h>
32 #endif
33 #ifdef HAVE_SYS_WAIT_H
34 #include <sys/wait.h>
35 #endif
36 #ifdef HAVE_SYS_SOCKET_H
37 #include <sys/socket.h>
38 #endif
39 #include <stdlib.h>
40 #include <string.h>
42 #ifndef __GNUC__
43 #define __attribute__(x)
44 #endif
46 static void child(const tor_main_configuration_t *cfg)
47 __attribute__((noreturn));
49 const char *
50 tor_api_get_provider_version(void)
52 return "libtorrunner " VERSION;
55 int
56 tor_run_main(const tor_main_configuration_t *cfg)
58 pid_t pid = fork();
59 if (pid == 0) {
60 child(cfg);
61 exit(0); /* Unreachable */
64 pid_t stopped_pid;
65 int status = 0;
66 do {
67 stopped_pid = waitpid(pid, &status, 0);
68 } while (stopped_pid == -1);
70 /* Note: these return values are not documented. No return value is
71 * documented! */
73 if (stopped_pid != pid) {
74 return -99999;
76 if (WIFSTOPPED(status)) {
77 return WEXITSTATUS(status);
79 if (WIFSIGNALED(status)) {
80 return -WTERMSIG(status);
83 return -999988;
86 /* circumlocution to avoid getting warned about calling calloc instead of
87 * tor_calloc. */
88 #define real_calloc calloc
89 #define real_free free
91 static void
92 child(const tor_main_configuration_t *cfg)
94 /* XXXX Close unused file descriptors. */
96 char **args = real_calloc(cfg->argc + cfg->argc_owned+1, sizeof(char *));
97 memcpy(args, cfg->argv, cfg->argc * sizeof(char *));
98 if (cfg->argc_owned)
99 memcpy(args + cfg->argc, cfg->argv_owned,
100 cfg->argc_owned * sizeof(char *));
102 args[cfg->argc + cfg->argc_owned] = NULL;
104 int rv = execv(BINDIR "/tor", args);
106 if (rv < 0) {
107 real_free(args);
108 exit(254);
109 } else {
110 abort(); /* Unreachable */