]> code.delx.au - gnu-emacs/blobdiff - src/emacs.c
Keep w32 environment settings internal only
[gnu-emacs] / src / emacs.c
index e7cb4ea4aaae083f6c837840c317842102194abc..fa7ec017fb53a14f8422d87d5fa43cf768a16ece 100644 (file)
@@ -7,8 +7,8 @@ This file is part of GNU Emacs.
 
 GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -54,13 +54,18 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #ifdef MSDOS
 #include <binary-io.h>
+#include "dosfns.h"
+#endif
+
+#ifdef HAVE_LIBSYSTEMD
+# include <systemd/sd-daemon.h>
+# include <sys/socket.h>
 #endif
 
 #ifdef HAVE_WINDOW_SYSTEM
 #include TERM_HEADER
 #endif /* HAVE_WINDOW_SYSTEM */
 
-#include "coding.h"
 #include "intervals.h"
 #include "character.h"
 #include "buffer.h"
@@ -85,6 +90,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "systime.h"
 #include "puresize.h"
 
+#include "getpagesize.h"
 #include "gnutls.h"
 
 #if (defined PROFILING \
@@ -106,7 +112,7 @@ extern void moncontrol (int mode);
 #include <sys/resource.h>
 #endif
 
-#ifdef HAVE_PERSONALITY_LINUX32
+#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE
 #include <sys/personality.h>
 #endif
 
@@ -181,6 +187,9 @@ bool noninteractive;
 /* True means remove site-lisp directories from load-path.  */
 bool no_site_lisp;
 
+/* True means put details like time stamps into builds.  */
+bool build_details;
+
 /* Name for the server started by the daemon.*/
 static char *daemon_name;
 
@@ -222,6 +231,7 @@ Initialization options:\n\
 --display, -d DISPLAY       use X server DISPLAY\n\
 ",
     "\
+--no-build-details          do not add build details such as time stamps\n\
 --no-desktop                do not load a saved desktop\n\
 --no-init-file, -q          load neither ~/.emacs nor default.el\n\
 --no-loadup, -nl            do not load loadup.el into bare Emacs\n\
@@ -662,9 +672,6 @@ main (int argc, char **argv)
   bool do_initial_setlocale;
   bool dumping;
   int skip_args = 0;
-#ifdef HAVE_SETRLIMIT
-  struct rlimit rlim;
-#endif
   bool no_loadup = 0;
   char *junk = 0;
   char *dname_arg = 0;
@@ -717,6 +724,7 @@ main (int argc, char **argv)
     unexec_init_emacs_zone ();
 #endif
 
+  init_standard_fds ();
   atexit (close_output_streams);
 
 #ifdef HAVE_MODULES
@@ -788,24 +796,22 @@ main (int argc, char **argv)
   dumping = !initialized && (strcmp (argv[argc - 1], "dump") == 0
                             || strcmp (argv[argc - 1], "bootstrap") == 0);
 
-#ifdef HAVE_PERSONALITY_LINUX32
-  if (dumping && ! getenv ("EMACS_HEAP_EXEC"))
+#ifdef HAVE_PERSONALITY_ADDR_NO_RANDOMIZE
+  if (dumping)
     {
-      /* Set this so we only do this once.  */
-      xputenv ("EMACS_HEAP_EXEC=true");
-
-      /* A flag to turn off address randomization which is introduced
-         in linux kernel shipped with fedora core 4 */
-#define ADD_NO_RANDOMIZE 0x0040000
-      personality (PER_LINUX32 | ADD_NO_RANDOMIZE);
-#undef  ADD_NO_RANDOMIZE
-
-      execvp (argv[0], argv);
+      int pers = personality (0xffffffff);
+      if (! (pers & ADDR_NO_RANDOMIZE)
+         && 0 <= personality (pers | ADDR_NO_RANDOMIZE))
+       {
+         /* Address randomization was enabled, but is now disabled.
+            Re-execute Emacs to get a clean slate.  */
+         execvp (argv[0], argv);
 
-      /* If the exec fails, try to dump anyway.  */
-      emacs_perror (argv[0]);
+         /* If the exec fails, warn and then try without a clean slate.  */
+         perror (argv[0]);
+       }
     }
-#endif /* HAVE_PERSONALITY_LINUX32 */
+#endif
 
 #if defined (HAVE_SETRLIMIT) && defined (RLIMIT_STACK) && !defined (CYGWIN)
   /* Extend the stack space available.  Don't do that if dumping,
@@ -814,38 +820,54 @@ main (int argc, char **argv)
      is built with an 8MB stack.  Moreover, the setrlimit call can
      cause problems on Cygwin
      (https://www.cygwin.com/ml/cygwin/2015-07/msg00096.html).  */
-  if (1
-#ifndef CANNOT_DUMP
-      && (!noninteractive || initialized)
-#endif
-      && !getrlimit (RLIMIT_STACK, &rlim))
+  struct rlimit rlim;
+  if (getrlimit (RLIMIT_STACK, &rlim) == 0
+      && 0 <= rlim.rlim_cur && rlim.rlim_cur <= LONG_MAX)
     {
-      long newlim;
-      /* Approximate the amount regex.c needs per unit of re_max_failures.  */
+      long lim = rlim.rlim_cur;
+
+      /* Approximate the amount regex.c needs per unit of
+        re_max_failures, then add 33% to cover the size of the
+        smaller stacks that regex.c successively allocates and
+        discards on its way to the maximum.  */
       int ratio = 20 * sizeof (char *);
-      /* Then add 33% to cover the size of the smaller stacks that regex.c
-        successively allocates and discards, on its way to the maximum.  */
       ratio += ratio / 3;
-      /* Add in some extra to cover
-        what we're likely to use for other reasons.  */
-      newlim = re_max_failures * ratio + 200000;
-#ifdef __NetBSD__
-      /* NetBSD (at least NetBSD 1.2G and former) has a bug in its
-       stack allocation routine for new process that the allocation
-       fails if stack limit is not on page boundary.  So, round up the
-       new limit to page boundary.  */
-      newlim = (newlim + getpagesize () - 1) / getpagesize () * getpagesize ();
-#endif
-      if (newlim > rlim.rlim_max)
+
+      /* Extra space to cover what we're likely to use for other reasons.  */
+      int extra = 200000;
+
+      bool try_to_grow_stack = true;
+#ifndef CANNOT_DUMP
+      try_to_grow_stack = !noninteractive || initialized;
+#endif
+
+      if (try_to_grow_stack)
        {
-         newlim = rlim.rlim_max;
-         /* Don't let regex.c overflow the stack we have.  */
-         re_max_failures = (newlim - 200000) / ratio;
+         long newlim = re_max_failures * ratio + extra;
+
+         /* Round the new limit to a page boundary; this is needed
+            for Darwin kernel 15.4.0 (see Bug#23622) and perhaps
+            other systems.  Do not shrink the stack and do not exceed
+            rlim_max.  Don't worry about exact values of
+            RLIM_INFINITY etc. since in practice when they are
+            nonnegative they are so large that the code does the
+            right thing anyway.  */
+         long pagesize = getpagesize ();
+         newlim += pagesize - 1;
+         if (0 <= rlim.rlim_max && rlim.rlim_max < newlim)
+           newlim = rlim.rlim_max;
+         newlim -= newlim % pagesize;
+
+         if (pagesize <= newlim - lim)
+           {
+             rlim.rlim_cur = newlim;
+             if (setrlimit (RLIMIT_STACK, &rlim) == 0)
+               lim = newlim;
+           }
        }
-      if (rlim.rlim_cur < newlim)
-       rlim.rlim_cur = newlim;
 
-      setrlimit (RLIMIT_STACK, &rlim);
+      /* Don't let regex.c overflow the stack.  */
+      re_max_failures = lim < extra ? 0 : min (lim - extra, SIZE_MAX) / ratio;
     }
 #endif /* HAVE_SETRLIMIT and RLIMIT_STACK and not CYGWIN */
 
@@ -872,9 +894,6 @@ main (int argc, char **argv)
   SET_BINARY (fileno (stdout));
 #endif /* MSDOS */
 
-  if (DETERMINISTIC_DUMP)
-    Vdeterministic_dump = Qt;
-
   /* Skip initial setlocale if LC_ALL is "C", as it's not needed in that case.
      The build procedure uses this while dumping, to ensure that the
      dumped Emacs does not have its system locale tables initialized,
@@ -898,24 +917,25 @@ main (int argc, char **argv)
       char *term;
       if (argmatch (argv, argc, "-t", "--terminal", 4, &term, &skip_args))
        {
-         int result;
-         emacs_close (0);
-         emacs_close (1);
-         result = emacs_open (term, O_RDWR, 0);
-         if (result < 0 || fcntl (0, F_DUPFD_CLOEXEC, 1) < 0)
+         emacs_close (STDIN_FILENO);
+         emacs_close (STDOUT_FILENO);
+         int result = emacs_open (term, O_RDWR, 0);
+         if (result != STDIN_FILENO
+             || (fcntl (STDIN_FILENO, F_DUPFD_CLOEXEC, STDOUT_FILENO)
+                 != STDOUT_FILENO))
            {
              char *errstring = strerror (errno);
              fprintf (stderr, "%s: %s: %s\n", argv[0], term, errstring);
-             exit (1);
+             exit (EXIT_FAILURE);
            }
-         if (! isatty (0))
+         if (! isatty (STDIN_FILENO))
            {
              fprintf (stderr, "%s: %s: not a tty\n", argv[0], term);
-             exit (1);
+             exit (EXIT_FAILURE);
            }
          fprintf (stderr, "Using %s\n", term);
 #ifdef HAVE_WINDOW_SYSTEM
-         inhibit_window_system = 1; /* -t => -nw */
+         inhibit_window_system = true; /* -t => -nw */
 #endif
        }
       else
@@ -963,6 +983,9 @@ main (int argc, char **argv)
   w32_daemon_event = NULL;
 #endif
 
+
+  int sockfd = -1;
+
   if (argmatch (argv, argc, "-daemon", "--daemon", 5, NULL, &skip_args)
       || argmatch (argv, argc, "-daemon", "--daemon", 5, &dname_arg, &skip_args))
     {
@@ -996,6 +1019,21 @@ main (int argc, char **argv)
          exit (1);
        }
 
+#ifdef HAVE_LIBSYSTEMD
+      /* Read the number of sockets passed through by systemd.  */
+      int systemd_socket = sd_listen_fds (1);
+
+      if (systemd_socket > 1)
+        fprintf (stderr,
+                ("\n"
+                 "Warning: systemd passed more than one socket to Emacs.\n"
+                 "Try 'Accept=false' in the Emacs socket unit file.\n"));
+      else if (systemd_socket == 1
+              && (0 < sd_is_socket (SD_LISTEN_FDS_START,
+                                    AF_UNSPEC, SOCK_STREAM, 1)))
+       sockfd = SD_LISTEN_FDS_START;
+#endif /* HAVE_LIBSYSTEMD */
+
 #ifndef DAEMON_MUST_EXEC
 #ifdef USE_GTK
       fprintf (stderr, "\nWarning: due to a long standing Gtk+ bug\nhttp://bugzilla.gnome.org/show_bug.cgi?id=85715\n\
@@ -1192,6 +1230,9 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
   no_site_lisp
     = argmatch (argv, argc, "-nsl", "--no-site-lisp", 11, NULL, &skip_args);
 
+  build_details = ! argmatch (argv, argc, "-no-build-details",
+                             "--no-build-details", 7, NULL, &skip_args);
+
 #ifdef HAVE_NS
   ns_pool = ns_alloc_autorelease_pool ();
 #ifdef NS_IMPL_GNUSTEP
@@ -1205,7 +1246,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
       /* Started from GUI? */
       /* FIXME: Do the right thing if getenv returns NULL, or if
          chdir fails.  */
-      if (! inhibit_window_system && ! isatty (0) && ! ch_to_dir)
+      if (! inhibit_window_system && ! isatty (STDIN_FILENO) && ! ch_to_dir)
         chdir (getenv ("HOME"));
       if (skip_args < argc)
         {
@@ -1308,16 +1349,6 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
   globals_of_gfilenotify ();
 #endif
 
-#ifdef WINDOWSNT
-  globals_of_w32 ();
-#ifdef HAVE_W32NOTIFY
-  globals_of_w32notify ();
-#endif
-  /* Initialize environment from registry settings.  */
-  init_environment (argv);
-  init_ntproc (dumping); /* must precede init_editfns.  */
-#endif
-
 #ifdef HAVE_NS
   /* Initialize the locale from user defaults.  */
   ns_init_locale ();
@@ -1334,6 +1365,20 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
   if (! dumping)
     set_initial_environment ();
 
+#ifdef WINDOWSNT
+  globals_of_w32 ();
+#ifdef HAVE_W32NOTIFY
+  globals_of_w32notify ();
+#endif
+  /* Initialize environment from registry settings.  Make sure to do
+     this only after calling set_initial_environment so that
+     Vinitial_environment and Vprocess_environment will contain only
+     variables from the parent process without modifications from
+     Emacs.  */
+  init_environment (argv);
+  init_ntproc (dumping); /* must precede init_editfns.  */
+#endif
+
   /* AIX crashes are reported in system versions 3.2.3 and 3.2.4
      if this is not done.  Do it after set_global_environment so that we
      don't pollute Vglobal_environment.  */
@@ -1549,7 +1594,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
   /* This can create a thread that may call getenv, so it must follow
      all calls to putenv and setenv.  Also, this sets up
      add_keyboard_wait_descriptor, which init_display uses.  */
-  init_process_emacs ();
+  init_process_emacs (sockfd);
 
   init_keyboard ();    /* This too must precede init_sys_modes.  */
   if (!noninteractive)
@@ -1641,6 +1686,7 @@ static const struct standard_args standard_args[] =
   { "-help", "--help", 90, 0 },
   { "-nl", "--no-loadup", 70, 0 },
   { "-nsl", "--no-site-lisp", 65, 0 },
+  { "-no-build-details", "--no-build-details", 63, 0 },
   /* -d must come last before the options handled in startup.el.  */
   { "-d", "--display", 60, 1 },
   { "-display", 0, 60, 1 },
@@ -2181,6 +2227,15 @@ synchronize_system_messages_locale (void)
 #endif
 }
 #endif /* HAVE_SETLOCALE */
+
+/* Return a diagnostic string for ERROR_NUMBER, in the wording
+   and encoding appropriate for the current locale.  */
+char *
+emacs_strerror (int error_number)
+{
+  synchronize_system_messages_locale ();
+  return strerror (error_number);
+}
 \f
 
 Lisp_Object
@@ -2352,9 +2407,9 @@ from the parent process and its tty file descriptors.  */)
   /* Get rid of stdin, stdout and stderr.  */
   nfd = emacs_open ("/dev/null", O_RDWR, 0);
   err |= nfd < 0;
-  err |= dup2 (nfd, 0) < 0;
-  err |= dup2 (nfd, 1) < 0;
-  err |= dup2 (nfd, 2) < 0;
+  err |= dup2 (nfd, STDIN_FILENO) < 0;
+  err |= dup2 (nfd, STDOUT_FILENO) < 0;
+  err |= dup2 (nfd, STDERR_FILENO) < 0;
   err |= emacs_close (nfd) != 0;
 
   /* Closing the pipe will notify the parent that it can exit.
@@ -2414,8 +2469,8 @@ Special values:
   `ms-dos'       compiled as an MS-DOS application.
   `windows-nt'   compiled as a native W32 application.
   `cygwin'       compiled using the Cygwin library.
-Anything else (in Emacs 24.1, the possibilities are: aix, berkeley-unix,
-hpux, irix, usg-unix-v) indicates some sort of Unix system.  */);
+Anything else (in Emacs 26, the possibilities are: aix, berkeley-unix,
+hpux, usg-unix-v) indicates some sort of Unix system.  */);
   Vsystem_type = intern_c_string (SYSTEM_TYPE);
   /* See configure.ac for the possible SYSTEM_TYPEs.  */
 
@@ -2535,13 +2590,6 @@ libraries; only those already known by Emacs will be loaded.  */);
   Vdynamic_library_alist = Qnil;
   Fput (intern_c_string ("dynamic-library-alist"), Qrisky_local_variable, Qt);
 
-  DEFVAR_BOOL ("deterministic-dump", Vdeterministic_dump,
-    doc: /* If non-nil, attempt to make dumping deterministic by
-avoiding sources of nondeterminism such as absolute file names, the
-hostname, or timestamps.  */);
-  Vdeterministic_dump = DETERMINISTIC_DUMP ? Qt : Qnil;
-  XSYMBOL (intern_c_string ("deterministic-dump"))->constant = 1;
-
 #ifdef WINDOWSNT
   Vlibrary_cache = Qnil;
   staticpro (&Vlibrary_cache);