tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

tor_runner.c (2733B)


      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 */
      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"
     27 #include "feature/api/tor_api_internal.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 *
     50 tor_api_get_provider_version(void)
     51 {
     52  return "libtorrunner " VERSION;
     53 }
     54 
     55 int
     56 tor_run_main(const tor_main_configuration_t *cfg)
     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 }