瀏覽代碼

Use _NSGetEnviron() instead of environ where required

OS X would otherwise crash with a segfault when linked statically to
some libraries.
Sebastian Hahn 13 年之前
父節點
當前提交
efb7b9dec1
共有 4 個文件被更改,包括 30 次插入4 次删除
  1. 2 0
      configure.in
  2. 23 0
      src/common/compat.c
  3. 2 0
      src/common/compat.h
  4. 3 4
      src/or/transports.c

+ 2 - 0
configure.in

@@ -292,6 +292,7 @@ dnl Check for functions before libevent, since libevent-1.2 apparently
 dnl exports strlcpy without defining it in a header.
 
 AC_CHECK_FUNCS(
+        _NSGetEnviron \
         accept4 \
         clock_gettime \
         flock \
@@ -622,6 +623,7 @@ dnl These headers are not essential
 
 AC_CHECK_HEADERS(
         arpa/inet.h \
+        crt_externs.h \
         grp.h \
         ifaddrs.h \
         inttypes.h \

+ 23 - 0
src/common/compat.c

@@ -51,6 +51,9 @@
 #ifdef HAVE_ARPA_INET_H
 #include <arpa/inet.h>
 #endif
+#ifdef HAVE_CRT_EXTERNS_H
+#include <crt_externs.h>
+#endif
 
 #ifndef HAVE_GETTIMEOFDAY
 #ifdef HAVE_FTIME
@@ -1659,6 +1662,26 @@ make_path_absolute(char *fname)
 #endif
 }
 
+#ifndef HAVE__NSGETENVIRON
+/* FreeBSD needs this; it doesn't seem to hurt other platforms. */
+extern char **environ;
+#endif
+
+/** Return the current environment. This is a portable replacement for
+ * 'environ'. */
+char **
+get_environment(void)
+{
+#ifdef HAVE__NSGETENVIRON
+  /* This is for compatibility between OSX versions.  Otherwise (for example)
+   * when we do a mostly-static build on OSX 10.7, the resulting binary won't
+   * work on OSX 10.6. */
+  return *_NSGetEnviron();
+#else
+  return environ;
+#endif
+}
+
 /** Set *addr to the IP address (in dotted-quad notation) stored in c.
  * Return 1 on success, 0 if c is badly formatted.  (Like inet_aton(c,addr),
  * but works on Windows and Solaris.)

+ 2 - 0
src/common/compat.h

@@ -581,6 +581,8 @@ char *get_user_homedir(const char *username);
 int get_parent_directory(char *fname);
 char *make_path_absolute(char *fname);
 
+char **get_environment(void);
+
 int spawn_func(void (*func)(void *), void *data);
 void spawn_exit(void) ATTR_NORETURN;
 

+ 3 - 4
src/or/transports.c

@@ -1076,8 +1076,6 @@ set_managed_proxy_environment(LPVOID *envp, const managed_proxy_t *mp)
 
 #else /* _WIN32 */
 
-extern char **environ;
-
 /** Prepare the environment <b>envp</b> of managed proxy <b>mp</b>.
  *  <b>envp</b> is allocated on the heap and should be freed by the
  *  caller after its use. */
@@ -1090,7 +1088,8 @@ set_managed_proxy_environment(char ***envp, const managed_proxy_t *mp)
   char *transports_to_launch=NULL;
   char *bindaddr=NULL;
   int environ_size=0;
-  char **environ_tmp = environ;
+  char **environ_tmp = get_environment();
+  char **environ_save = environ_tmp;
 
   int n_envs = mp->is_server ? ENVIRON_SIZE_SERVER : ENVIRON_SIZE_CLIENT;
 
@@ -1098,7 +1097,7 @@ set_managed_proxy_environment(char ***envp, const managed_proxy_t *mp)
     environ_size++;
     environ_tmp++;
   }
-  environ_tmp = environ;
+  environ_tmp = environ_save;
 
   /* allocate enough space for our env. vars and a NULL pointer */
   *envp = tor_malloc(sizeof(char*)*(environ_size+n_envs+1));