tor_runner.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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-2017, 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 "tor_api.h"
  24. #include "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. int
  43. tor_run_main(const tor_main_configuration_t *cfg)
  44. {
  45. pid_t pid = fork();
  46. if (pid == 0) {
  47. child(cfg);
  48. exit(0); /* Unreachable */
  49. }
  50. pid_t stopped_pid;
  51. int status = 0;
  52. do {
  53. stopped_pid = waitpid(pid, &status, 0);
  54. } while (stopped_pid == -1);
  55. /* Note: these return values are not documented. No return value is
  56. * documented! */
  57. if (stopped_pid != pid) {
  58. return -99999;
  59. }
  60. if (WIFSTOPPED(status)) {
  61. return WEXITSTATUS(status);
  62. }
  63. if (WIFSIGNALED(status)) {
  64. return -WTERMSIG(status);
  65. }
  66. return -999988;
  67. }
  68. /* circumlocution to avoid getting warned about calling calloc instead of
  69. * tor_calloc. */
  70. #define real_calloc calloc
  71. static void
  72. child(const tor_main_configuration_t *cfg)
  73. {
  74. /* XXXX Close unused file descriptors. */
  75. char **args = real_calloc(cfg->argc+1, sizeof(char *));
  76. memcpy(args, cfg->argv, cfg->argc * sizeof(char *));
  77. args[cfg->argc] = NULL;
  78. int rv = execv(BINDIR "/tor", args);
  79. if (rv < 0) {
  80. exit(254);
  81. } else {
  82. abort(); /* Unreachable */
  83. }
  84. }