tor_runner.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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-2019, The Tor Project, Inc. */
  5. /* See LICENSE for licensing information */
  6. /**
  7. * @file tor_runner.c
  8. * @brief Experimental module to emulate tor_run_main() API with fork+exec
  9. *
  10. * The functions here are meant to allow the application developer to
  11. * use the tor_run_main() API without having to care whether Tor is
  12. * running in-process or out-of-process. For in-process usage, the
  13. * developer can link Tor as a library and call tor_run_main(); for
  14. * out-of-process usage, the developer can link this library instead.
  15. *
  16. * This interface is EXPERIMENTAL; please let us know if you would like
  17. * to depend on it. We don't know yet whether it will be reliable in
  18. * practice.
  19. */
  20. /* NOTE: This module is supposed to work without the standard Tor utility
  21. * functions. Don't add more dependencies!
  22. */
  23. #include "feature/api/tor_api.h"
  24. #include "feature/api/tor_api_internal.h"
  25. #include "orconfig.h"
  26. #ifdef HAVE_UNISTD_H
  27. #include <unistd.h>
  28. #endif
  29. #ifdef HAVE_SYS_WAIT_H
  30. #include <sys/wait.h>
  31. #endif
  32. #ifdef HAVE_SYS_SOCKET_H
  33. #include <sys/socket.h>
  34. #endif
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #ifndef __GNUC__
  38. #define __attribute__(x)
  39. #endif
  40. static void child(const tor_main_configuration_t *cfg)
  41. __attribute__((noreturn));
  42. const char *
  43. tor_api_get_provider_version(void)
  44. {
  45. return "libtorrunner " VERSION;
  46. }
  47. int
  48. tor_run_main(const tor_main_configuration_t *cfg)
  49. {
  50. pid_t pid = fork();
  51. if (pid == 0) {
  52. child(cfg);
  53. exit(0); /* Unreachable */
  54. }
  55. pid_t stopped_pid;
  56. int status = 0;
  57. do {
  58. stopped_pid = waitpid(pid, &status, 0);
  59. } while (stopped_pid == -1);
  60. /* Note: these return values are not documented. No return value is
  61. * documented! */
  62. if (stopped_pid != pid) {
  63. return -99999;
  64. }
  65. if (WIFSTOPPED(status)) {
  66. return WEXITSTATUS(status);
  67. }
  68. if (WIFSIGNALED(status)) {
  69. return -WTERMSIG(status);
  70. }
  71. return -999988;
  72. }
  73. /* circumlocution to avoid getting warned about calling calloc instead of
  74. * tor_calloc. */
  75. #define real_calloc calloc
  76. #define real_free free
  77. static void
  78. child(const tor_main_configuration_t *cfg)
  79. {
  80. /* XXXX Close unused file descriptors. */
  81. char **args = real_calloc(cfg->argc + cfg->argc_owned+1, sizeof(char *));
  82. memcpy(args, cfg->argv, cfg->argc * sizeof(char *));
  83. if (cfg->argc_owned)
  84. memcpy(args + cfg->argc, cfg->argv_owned,
  85. cfg->argc_owned * sizeof(char *));
  86. args[cfg->argc + cfg->argc_owned] = NULL;
  87. int rv = execv(BINDIR "/tor", args);
  88. if (rv < 0) {
  89. real_free(args);
  90. exit(254);
  91. } else {
  92. abort(); /* Unreachable */
  93. }
  94. }