Tor  0.4.6.0-alpha-dev
tor_runner.c
Go to the documentation of this file.
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-2020, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
6 
7 /**
8  * @file tor_runner.c
9  * @brief Experimental module to emulate tor_run_main() API with fork+exec
10  *
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.
16  *
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.
20  */
21 
22 /* NOTE: This module is supposed to work without the standard Tor utility
23  * functions. Don't add more dependencies!
24  */
25 
26 #include "feature/api/tor_api.h"
28 
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>
41 
42 #ifndef __GNUC__
43 #define __attribute__(x)
44 #endif
45 
46 static void child(const tor_main_configuration_t *cfg)
47  __attribute__((noreturn));
48 
49 const char *
51 {
52  return "libtorrunner " VERSION;
53 }
54 
55 int
57 {
58  pid_t pid = fork();
59  if (pid == 0) {
60  child(cfg);
61  exit(0); /* Unreachable */
62  }
63 
64  pid_t stopped_pid;
65  int status = 0;
66  do {
67  stopped_pid = waitpid(pid, &status, 0);
68  } while (stopped_pid == -1);
69 
70  /* Note: these return values are not documented. No return value is
71  * documented! */
72 
73  if (stopped_pid != pid) {
74  return -99999;
75  }
76  if (WIFSTOPPED(status)) {
77  return WEXITSTATUS(status);
78  }
79  if (WIFSIGNALED(status)) {
80  return -WTERMSIG(status);
81  }
82 
83  return -999988;
84 }
85 
86 /* circumlocution to avoid getting warned about calling calloc instead of
87  * tor_calloc. */
88 #define real_calloc calloc
89 #define real_free free
90 
91 static void
92 child(const tor_main_configuration_t *cfg)
93 {
94  /* XXXX Close unused file descriptors. */
95 
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 *));
101 
102  args[cfg->argc + cfg->argc_owned] = NULL;
103 
104  int rv = execv(BINDIR "/tor", args);
105 
106  if (rv < 0) {
107  real_free(args);
108  exit(254);
109  } else {
110  abort(); /* Unreachable */
111  }
112 }
tor_api_internal.h
Internal declarations for in-process Tor API.
tor_run_main
int tor_run_main(const tor_main_configuration_t *cfg)
Definition: tor_runner.c:56
tor_main_configuration_t::argv
char ** argv
Definition: tor_api_internal.h:23
tor_main_configuration_t::argc
int argc
Definition: tor_api_internal.h:21
tor_api.h
Public C API for the Tor network service.
tor_api_get_provider_version
const char * tor_api_get_provider_version(void)
Definition: tor_runner.c:50
tor_main_configuration_t::argv_owned
char ** argv_owned
Definition: tor_api_internal.h:28
tor_main_configuration_t::argc_owned
int argc_owned
Definition: tor_api_internal.h:26
tor_main_configuration_t
Definition: tor_api_internal.h:19