Use putenv+unsetenv instead of modifying environ directly.
[bpt/emacs.git] / src / emacs.c
index eb83a0a..fbaf035 100644 (file)
@@ -27,21 +27,30 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <sys/file.h>
 #include <unistd.h>
 
+#include <close-stream.h>
 #include <ignore-value.h>
 
 #include "lisp.h"
 
-#ifdef HAVE_WINDOW_SYSTEM
-#include TERM_HEADER
-#endif /* HAVE_WINDOW_SYSTEM */
-
 #ifdef WINDOWSNT
 #include <fcntl.h>
-#include <windows.h> /* just for w32.h */
 #include "w32.h"
-#include "w32heap.h" /* for prototype of sbrk */
+#include "w32heap.h"
+#endif
+
+#if defined WINDOWSNT || defined HAVE_NTGUI
+#include "w32select.h"
+#include "w32font.h"
+#endif
+
+#if defined HAVE_NTGUI && defined CYGWIN
+#include "cygw32.h"
 #endif
 
+#ifdef HAVE_WINDOW_SYSTEM
+#include TERM_HEADER
+#endif /* HAVE_WINDOW_SYSTEM */
+
 #ifdef NS_IMPL_GNUSTEP
 /* At least under Debian, GSConfig is in a subdirectory.  --Stef  */
 #include <GNUstepBase/GSConfig.h>
@@ -86,16 +95,17 @@ extern void moncontrol (int mode);
 #include <sys/personality.h>
 #endif
 
-#ifndef O_RDWR
-#define O_RDWR 2
-#endif
-
 static const char emacs_version[] = VERSION;
 static const char emacs_copyright[] = COPYRIGHT;
 
 /* Empty lisp strings.  To avoid having to build any others.  */
 Lisp_Object empty_unibyte_string, empty_multibyte_string;
 
+#ifdef WINDOWSNT
+/* Cache for externally loaded libraries.  */
+Lisp_Object Vlibrary_cache;
+#endif
+
 /* Set after Emacs has started up the first time.
    Prevents reinitialization of the Lisp world and keymaps
    on subsequent starts.  */
@@ -151,6 +161,22 @@ static void *my_heap_start;
 static uprintmax_t heap_bss_diff;
 #endif
 
+/* To run as a daemon under Cocoa or Windows, we must do a fork+exec,
+   not a simple fork.
+
+   On Cocoa, CoreFoundation lib fails in forked process:
+   http://developer.apple.com/ReleaseNotes/
+   CoreFoundation/CoreFoundation.html)
+
+   On Windows, a Cygwin fork child cannot access the USER subsystem.
+
+   We mark being in the exec'd process by a daemon name argument of
+   form "--daemon=\nFD0,FD1\nNAME" where FD are the pipe file descriptors,
+   NAME is the original daemon name, if any. */
+#if defined NS_IMPL_COCOA || (defined HAVE_NTGUI && defined CYGWIN)
+# define DAEMON_MUST_EXEC
+#endif
+
 /* True means running Emacs without interactive terminal.  */
 bool noninteractive;
 
@@ -285,6 +311,7 @@ static void *ns_pool;
 _Noreturn void
 terminate_due_to_signal (int sig, int backtrace_limit)
 {
+  signal (sig, SIG_DFL);
   totally_unblock_input ();
 
   /* If fatal error occurs in code below, avoid infinite recursion.  */
@@ -508,7 +535,7 @@ DEFUN ("invocation-directory", Finvocation_directory, Sinvocation_directory,
 #ifdef HAVE_TZSET
 /* A valid but unlikely value for the TZ environment value.
    It is OK (though a bit slower) if the user actually chooses this value.  */
-static char dump_tz[] = "UtC0";
+static char const dump_tz[] = "UtC0";
 #endif
 
 #ifndef ORDINARY_LINK
@@ -645,6 +672,22 @@ void (*__malloc_initialize_hook) (void) EXTERNALLY_VISIBLE = malloc_initialize_h
 
 #endif /* DOUG_LEA_MALLOC */
 
+/* Close standard output and standard error, reporting any write
+   errors as best we can.  This is intended for use with atexit.  */
+static void
+close_output_streams (void)
+{
+  if (close_stream (stdout) != 0)
+    {
+      fprintf (stderr, "Write error to standard output: %s\n",
+              strerror (errno));
+      fflush (stderr);
+      _exit (EXIT_FAILURE);
+    }
+
+   if (close_stream (stderr) != 0)
+     _exit (EXIT_FAILURE);
+}
 
 /* ARGSUSED */
 int
@@ -663,7 +706,7 @@ main (int argc, char **argv)
   bool no_loadup = 0;
   char *junk = 0;
   char *dname_arg = 0;
-#ifdef NS_IMPL_COCOA
+#ifdef DAEMON_MUST_EXEC
   char dname_arg2[80];
 #endif
   char *ch_to_dir;
@@ -672,9 +715,9 @@ main (int argc, char **argv)
   stack_base = &dummy;
 #endif
 
-#if defined (USE_GTK) && defined (G_SLICE_ALWAYS_MALLOC)
+#ifdef G_SLICE_ALWAYS_MALLOC
   /* This is used by the Cygwin build.  */
-  setenv ("G_SLICE", "always-malloc", 1);
+  xputenv ("G_SLICE=always-malloc");
 #endif
 
 #ifdef GNU_LINUX
@@ -701,6 +744,8 @@ main (int argc, char **argv)
     unexec_init_emacs_zone ();
 #endif
 
+  atexit (close_output_streams);
+
   sort_args (argc, argv);
   argc = 0;
   while (argv[argc]) argc++;
@@ -758,9 +803,8 @@ main (int argc, char **argv)
 #ifdef HAVE_PERSONALITY_LINUX32
   if (dumping && ! getenv ("EMACS_HEAP_EXEC"))
     {
-      static char heapexec[] = "EMACS_HEAP_EXEC=true";
       /* Set this so we only do this once.  */
-      putenv (heapexec);
+      xputenv ("EMACS_HEAP_EXEC=true");
 
       /* A flag to turn off address randomization which is introduced
          in linux kernel shipped with fedora core 4 */
@@ -958,25 +1002,19 @@ main (int argc, char **argv)
          exit (1);
        }
 
-#ifndef NS_IMPL_COCOA
+#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\
 Emacs might crash when run in daemon mode and the X11 connection is unexpectedly lost.\n\
 Using an Emacs configured with --with-x-toolkit=lucid does not have this problem.\n");
-#endif
+#endif /* USE_GTK */
       f = fork ();
-#else /* NS_IMPL_COCOA */
-      /* Under Cocoa we must do fork+exec as CoreFoundation lib fails in
-         forked process: http://developer.apple.com/ReleaseNotes/
-                                  CoreFoundation/CoreFoundation.html)
-         We mark being in the exec'd process by a daemon name argument of
-         form "--daemon=\nFD0,FD1\nNAME" where FD are the pipe file descriptors,
-         NAME is the original daemon name, if any. */
+#else /* DAEMON_MUST_EXEC */
       if (!dname_arg || !strchr (dname_arg, '\n'))
          f = fork ();  /* in orig */
       else
          f = 0;  /* in exec'd */
-#endif /* NS_IMPL_COCOA */
+#endif /* !DAEMON_MUST_EXEC */
       if (f > 0)
        {
          int retval;
@@ -1012,7 +1050,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
          exit (1);
        }
 
-#ifdef NS_IMPL_COCOA
+#ifdef DAEMON_MUST_EXEC
       {
         /* In orig process, forked as child, OR in exec'd. */
         if (!dname_arg || !strchr (dname_arg, '\n'))
@@ -1048,7 +1086,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
                 dname_arg2);
         dname_arg = *dname_arg2 ? dname_arg2 : NULL;
       }
-#endif /* NS_IMPL_COCOA */
+#endif /* DAEMON_MUST_EXEC */
 
       if (dname_arg)
                daemon_name = xstrdup (dname_arg);
@@ -1058,28 +1096,21 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
         that it is not accessible to programs started from .emacs.  */
       fcntl (daemon_pipe[1], F_SETFD, FD_CLOEXEC);
 
-#ifdef HAVE_SETSID
       setsid ();
-#endif
 #else /* DOS_NT */
       fprintf (stderr, "This platform does not support the -daemon flag.\n");
       exit (1);
 #endif /* DOS_NT */
     }
 
+#if defined (HAVE_PTHREAD) && !defined (SYSTEM_MALLOC) && !defined (DOUG_LEA_MALLOC)
   if (! noninteractive)
     {
-#if defined (USG5) && defined (INTERRUPT_INPUT)
-      setpgrp ();
-#endif
-#if defined (HAVE_PTHREAD) && !defined (SYSTEM_MALLOC) && !defined (DOUG_LEA_MALLOC)
-      {
-        extern void malloc_enable_thread (void);
+      extern void malloc_enable_thread (void);
 
-       malloc_enable_thread ();
-      }
-#endif
+      malloc_enable_thread ();
     }
+#endif
 
   init_signals (dumping);
 
@@ -1118,6 +1149,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
 
       /* Called before syms_of_fileio, because it sets up Qerror_condition.  */
       syms_of_data ();
+      syms_of_fns ();     /* Before syms_of_charset which uses hashtables.  */
       syms_of_fileio ();
       /* Before syms_of_coding to initialize Vgc_cons_threshold.  */
       syms_of_alloc ();
@@ -1129,7 +1161,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
 
       init_window_once ();     /* Init the window system.  */
 #ifdef HAVE_WINDOW_SYSTEM
-      init_fringe_once ();     /* Swap bitmaps if necessary. */
+      init_fringe_once ();     /* Swap bitmaps if necessary.  */
 #endif /* HAVE_WINDOW_SYSTEM */
     }
 
@@ -1257,7 +1289,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
   globals_of_w32 ();
   /* Initialize environment from registry settings.  */
   init_environment (argv);
-  init_ntproc ();      /* must precede init_editfns.  */
+  init_ntproc (dumping); /* must precede init_editfns.  */
 #endif
 
   /* Initialize and GC-protect Vinitial_environment and
@@ -1276,7 +1308,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
      don't pollute Vglobal_environment.  */
   /* Setting LANG here will defeat the startup locale processing...  */
 #ifdef AIX
-  putenv ("LANG=C");
+  xputenv ("LANG=C");
 #endif
 
   init_buffer ();      /* Init default directory of main buffer.  */
@@ -1312,7 +1344,6 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
       syms_of_lread ();
       syms_of_print ();
       syms_of_eval ();
-      syms_of_fns ();
       syms_of_floatfns ();
 
       syms_of_buffer ();
@@ -1351,6 +1382,9 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
 #ifdef WINDOWSNT
       syms_of_ntproc ();
 #endif /* WINDOWSNT */
+#if defined CYGWIN && defined HAVE_NTGUI
+      syms_of_cygw32 ();
+#endif
       syms_of_window ();
       syms_of_xdisp ();
       syms_of_font ();
@@ -1381,11 +1415,14 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
 #ifdef HAVE_NTGUI
       syms_of_w32term ();
       syms_of_w32fns ();
-      syms_of_w32select ();
       syms_of_w32menu ();
       syms_of_fontset ();
 #endif /* HAVE_NTGUI */
 
+#if defined WINDOWSNT || defined HAVE_NTGUI
+      syms_of_w32select ();
+#endif
+
 #ifdef MSDOS
       syms_of_xmenu ();
       syms_of_dosfns ();
@@ -1413,6 +1450,8 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
       syms_of_ntterm ();
 #endif /* WINDOWSNT */
 
+      syms_of_profiler ();
+
       keys_of_casefiddle ();
       keys_of_cmds ();
       keys_of_buffer ();
@@ -1428,8 +1467,11 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
       globals_of_w32font ();
       globals_of_w32fns ();
       globals_of_w32menu ();
-      globals_of_w32select ();
 #endif  /* HAVE_NTGUI */
+
+#if defined WINDOWSNT || defined HAVE_NTGUI
+      globals_of_w32select ();
+#endif
     }
 
   init_charset ();
@@ -1837,8 +1879,6 @@ all of which are called before Emacs is actually killed.  */)
     exit_code = (XINT (arg) < 0
                 ? XINT (arg) | INT_MIN
                 : XINT (arg) & INT_MAX);
-  else if (noninteractive && (fflush (stdout) || ferror (stdout)))
-    exit_code = EXIT_FAILURE;
   else
     exit_code = EXIT_SUCCESS;
   exit (exit_code);
@@ -1868,8 +1908,8 @@ shut_down_emacs (int sig, Lisp_Object stuff)
   /* If we are controlling the terminal, reset terminal modes.  */
 #ifndef DOS_NT
   {
-    int pgrp = EMACS_GETPGRP (0);
-    int tpgrp = tcgetpgrp (0);
+    pid_t pgrp = getpgrp ();
+    pid_t tpgrp = tcgetpgrp (0);
     if ((tpgrp != -1) && tpgrp == pgrp)
       {
        reset_all_sys_modes ();
@@ -1878,7 +1918,7 @@ shut_down_emacs (int sig, Lisp_Object stuff)
            static char const format[] = "Fatal error %d: ";
            char buf[sizeof format - 2 + INT_STRLEN_BOUND (int)];
            int buflen = sprintf (buf, format, sig);
-           char const *sig_desc = strsignal (sig);
+           char const *sig_desc = safe_strsignal (sig);
            ignore_value (write (STDERR_FILENO, buf, buflen));
            ignore_value (write (STDERR_FILENO, sig_desc, strlen (sig_desc)));
          }
@@ -1904,10 +1944,6 @@ shut_down_emacs (int sig, Lisp_Object stuff)
   unrequest_sigio ();
   ignore_sigio ();
 
-#ifdef WINDOWSNT
-  term_ntproc ();
-#endif
-
   /* Do this only if terminating normally, we want glyph matrices
      etc. in a core dump.  */
   if (sig == 0 || sig == SIGTERM)
@@ -1927,6 +1963,10 @@ shut_down_emacs (int sig, Lisp_Object stuff)
 #ifdef HAVE_LIBXML2
   xml_cleanup_parser ();
 #endif
+
+#ifdef WINDOWSNT
+  term_ntproc (0);
+#endif
 }
 
 
@@ -2024,6 +2064,13 @@ You must run Emacs in batch mode in order to dump it.  */)
   free (malloc_state_ptr);
 #endif
 
+#ifdef WINDOWSNT
+  Vlibrary_cache = Qnil;
+#endif
+#ifdef HAVE_WINDOW_SYSTEM
+  reset_image_types ();
+#endif
+
   Vpurify_flag = tem;
 
   return unbind_to (count, Qnil);
@@ -2356,6 +2403,11 @@ 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);
 
+#ifdef WINDOWSNT
+  Vlibrary_cache = Qnil;
+  staticpro (&Vlibrary_cache);
+#endif
+
   /* Make sure IS_DAEMON starts up as false.  */
   daemon_pipe[1] = 0;
 }