#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
#include <utimens.h>
#include "lisp.h"
+#include "sheap.h"
#include "sysselect.h"
#include "blockinput.h"
#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. */
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;
}
return buf;
}
-#endif
\f
/* Discard pending input on all input descriptors. */
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
# 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);
}
/*