]> code.delx.au - gnu-emacs/blobdiff - src/sysdep.c
Merge from origin/emacs-25
[gnu-emacs] / src / sysdep.c
index e73acec733e6fc800c48e79a352d58875a4a7c27..a01bf1d7c100d1066257cf458f1c2492b5ca5b6c 100644 (file)
@@ -19,14 +19,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
-/* If HYBRID_GET_CURRENT_DIR_NAME is defined in conf_post.h, then we
-   need the following before including unistd.h, in order to pick up
-   the right prototype for gget_current_dir_name.  */
-#ifdef HYBRID_GET_CURRENT_DIR_NAME
-#undef get_current_dir_name
-#define get_current_dir_name gget_current_dir_name
-#endif
-
 #include <execinfo.h>
 #include "sysstdio.h"
 #ifdef HAVE_PWD_H
@@ -40,6 +32,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <utimens.h>
 
 #include "lisp.h"
+#include "sheap.h"
 #include "sysselect.h"
 #include "blockinput.h"
 
@@ -99,6 +92,16 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "process.h"
 #include "cm.h"
 
+#include "gnutls.h"
+/* MS-Windows loads GnuTLS at run time, if available; we don't want to
+   do that during startup just to call gnutls_rnd.  */
+#if 0x020c00 <= GNUTLS_VERSION_NUMBER && !defined WINDOWSNT
+# include <gnutls/crypto.h>
+#else
+# define emacs_gnutls_global_init() Qnil
+# define gnutls_rnd(level, data, len) (-1)
+#endif
+
 #ifdef WINDOWSNT
 #include <direct.h>
 /* In process.h which conflicts with the local copy.  */
@@ -127,14 +130,21 @@ static const int baud_convert[] =
     1800, 2400, 4800, 9600, 19200, 38400
   };
 
-#if !defined HAVE_GET_CURRENT_DIR_NAME || defined BROKEN_GET_CURRENT_DIR_NAME \
-  || (defined HYBRID_GET_CURRENT_DIR_NAME)
-/* Return the current working directory.  Returns NULL on errors.
-   Any other returned value must be freed with free. This is used
-   only when get_current_dir_name is not defined on the system.  */
+/* Return the current working directory.  The result should be freed
+   with 'free'.  Return NULL on errors.  */
 char *
-get_current_dir_name (void)
+emacs_get_current_dir_name (void)
 {
+# if HAVE_GET_CURRENT_DIR_NAME && !BROKEN_GET_CURRENT_DIR_NAME
+#  ifdef HYBRID_MALLOC
+  bool use_libc = bss_sbrk_did_unexec;
+#  else
+  bool use_libc = true;
+#  endif
+  if (use_libc)
+    return get_current_dir_name ();
+# endif
+
   char *buf;
   char *pwd = getenv ("PWD");
   struct stat dotstat, pwdstat;
@@ -182,7 +192,6 @@ get_current_dir_name (void)
     }
   return buf;
 }
-#endif
 
 \f
 /* Discard pending input on all input descriptors.  */
@@ -1399,6 +1408,12 @@ setup_pty (int fd)
 void
 init_system_name (void)
 {
+  if (!build_details)
+    {
+      /* Set system-name to nil so that the build is deterministic.  */
+      Vsystem_name = Qnil;
+      return;
+    }
   char *hostname_alloc = NULL;
   char *hostname;
 #ifndef HAVE_GETHOSTNAME
@@ -2071,36 +2086,56 @@ init_signals (bool dumping)
 # endif /* !HAVE_RANDOM */
 #endif /* !RAND_BITS */
 
+#ifdef HAVE_RANDOM
+typedef unsigned int random_seed;
+static void set_random_seed (random_seed arg) { srandom (arg); }
+#elif defined HAVE_LRAND48
+/* Although srand48 uses a long seed, this is unsigned long to avoid
+   undefined behavior on signed integer overflow in init_random.  */
+typedef unsigned long int random_seed;
+static void set_random_seed (random_seed arg) { srand48 (arg); }
+#else
+typedef unsigned int random_seed;
+static void set_random_seed (random_seed arg) { srand (arg); }
+#endif
+
 void
 seed_random (void *seed, ptrdiff_t seed_size)
 {
-#if defined HAVE_RANDOM || ! defined HAVE_LRAND48
-  unsigned int arg = 0;
-#else
-  long int arg = 0;
-#endif
+  random_seed arg = 0;
   unsigned char *argp = (unsigned char *) &arg;
   unsigned char *seedp = seed;
-  ptrdiff_t i;
-  for (i = 0; i < seed_size; i++)
+  for (ptrdiff_t i = 0; i < seed_size; i++)
     argp[i % sizeof arg] ^= seedp[i];
-#ifdef HAVE_RANDOM
-  srandom (arg);
-#else
-# ifdef HAVE_LRAND48
-  srand48 (arg);
-# else
-  srand (arg);
-# endif
-#endif
+  set_random_seed (arg);
 }
 
 void
 init_random (void)
 {
-  struct timespec t = current_timespec ();
-  uintmax_t v = getpid () ^ t.tv_sec ^ t.tv_nsec;
-  seed_random (&v, sizeof v);
+  random_seed v;
+  if (! (EQ (emacs_gnutls_global_init (), Qt)
+        && gnutls_rnd (GNUTLS_RND_NONCE, &v, sizeof v) == 0))
+    {
+      bool success = false;
+#ifndef WINDOWSNT
+      int fd = emacs_open ("/dev/urandom", O_RDONLY | O_BINARY, 0);
+      if (0 <= fd)
+       {
+         success = emacs_read (fd, &v, sizeof v) == sizeof v;
+         emacs_close (fd);
+       }
+#else
+      success = w32_init_random (&v, sizeof v) == 0;
+#endif
+      if (! success)
+       {
+         /* Fall back to current time value + PID.  */
+         struct timespec t = current_timespec ();
+         v = getpid () ^ t.tv_sec ^ t.tv_nsec;
+       }
+    }
+  set_random_seed (v);
 }
 
 /*