Include <config.h> instead of "config.h".
[bpt/emacs.git] / src / emacs.c
index 38e5601..22d0929 100644 (file)
@@ -1,11 +1,11 @@
 /* Fully extensible Emacs, running on Unix, intended for GNU.
-   Copyright (C) 1985, 1986, 1987, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1993 Free Software Foundation, Inc.
 
 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 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -21,7 +21,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <signal.h>
 #include <errno.h>
 
-#include "config.h"
+#include <config.h>
 #include <stdio.h>
 
 #include <sys/types.h>
@@ -35,10 +35,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <sys/ioctl.h>
 #endif
 
-#ifdef HAVE_TERMIOS
-#include <termios.h>
-#endif
-
 #ifdef APOLLO
 #ifndef APOLLO_SR10
 #include <default_acl.h>
@@ -47,18 +43,26 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "lisp.h"
 #include "commands.h"
+#include "intervals.h"
 
-#include "systerm.h"
+#include "systty.h"
+#include "syssignal.h"
+#include "process.h"
 
 #ifndef O_RDWR
 #define O_RDWR 2
 #endif
 
-#define PRIO_PROCESS 0
-
 /* Command line args from shell, as list of strings */
 Lisp_Object Vcommand_line_args;
 
+/* The name under which Emacs was invoked, with any leading directory
+   names discarded.  */
+Lisp_Object Vinvocation_name;
+
+/* The directory name from which Emacs was invoked.  */
+Lisp_Object Vinvocation_directory;
+
 /* Hook run by `kill-emacs' before it does really anything.  */
 Lisp_Object Vkill_emacs_hook;
 
@@ -74,6 +78,16 @@ Lisp_Object Vsystem_type;
    but instead should use the virtual terminal under which it was started */
 int inhibit_window_system;
 
+/* If nonzero, set Emacs to run at this priority.  This is also used
+   in child_setup and sys_suspend to make sure subshells run at normal
+   priority; Those functions have their own extern declaration.  */
+int emacs_priority;
+
+#ifdef BSD
+/* See sysdep.c.  */
+extern int inherited_pgroup;
+#endif
+
 #ifdef HAVE_X_WINDOWS
 /* If non-zero, -d was specified, meaning we're using some window system. */
 int display_arg;
@@ -119,38 +133,21 @@ fatal_error_signal (sig)
   signal (sig, SIG_DFL);
 
   /* If fatal error occurs in code below, avoid infinite recursion.  */
-  if (fatal_error_in_progress)
-    kill (getpid (), fatal_error_code);
-
-  fatal_error_in_progress = 1;
-
-  /* If we are controlling the terminal, reset terminal modes */
-#ifdef EMACS_HAVE_TTY_PGRP
-  {
-    int tpgrp;
-    if (EMACS_GET_TTY_PGRP (0, &tpgrp) != -1
-       && tpgrp == getpgrp (0))
-      {
-       reset_sys_modes ();
-       if (sig != SIGTERM)
-         fprintf (stderr, "Fatal error (%d).", sig);
-      }
-  }
-#endif /* uses pgrp */
-
-  /* Clean up */
-  kill_buffer_processes (Qnil);
-  Fdo_auto_save (Qt, Qnil);
+  if (! fatal_error_in_progress)
+    {
+      fatal_error_in_progress = 1;
 
-#ifdef CLASH_DETECTION
-  unlock_all_files ();
-#endif /* CLASH_DETECTION */
+      shut_down_emacs (sig, 0, Qnil);
+    }
 
 #ifdef VMS
-  kill_vms_processes ();
   LIB$STOP (SS$_ABORT);
 #else
-  /* Signal the same code; this time it will really be fatal.  */
+  /* Signal the same code; this time it will really be fatal.
+     Remember that since we're in a signal handler, the signal we're
+     going to send is probably blocked, so we have to unblock it if we
+     want to really receive it.  */
+  sigunblock (sigmask (fatal_error_code));
   kill (getpid (), fatal_error_code);
 #endif /* not VMS */
 }
@@ -165,6 +162,19 @@ init_cmdargs (argc, argv, skip_args)
 {
   register int i;
 
+  Vinvocation_name = Ffile_name_nondirectory (build_string (argv[0]));
+  Vinvocation_directory = Ffile_name_directory (build_string (argv[0]));
+  /* If we got no directory in argv[0], search PATH to find where
+     Emacs actually came from.  */
+  if (NILP (Vinvocation_directory))
+    {
+      Lisp_Object found;
+      int yes = openp (Vexec_path, Vinvocation_name,
+                      EXEC_SUFFIXES, &found, 1);
+      if (yes == 1)
+       Vinvocation_directory = Ffile_name_directory (found);
+    }
+
   Vcommand_line_args = Qnil;
 
   for (i = argc - 1; i >= 0; i--)
@@ -174,6 +184,23 @@ init_cmdargs (argc, argv, skip_args)
          = Fcons (build_string (argv[i]), Vcommand_line_args);
     }
 }
+
+DEFUN ("invocation-name", Finvocation_name, Sinvocation_name, 0, 0, 0,
+  "Return the program name that was used to run Emacs.\n\
+Any directory names are omitted.")
+  ()
+{
+  return Fcopy_sequence (Vinvocation_name);
+}
+
+DEFUN ("invocation-directory", Finvocation_directory, Sinvocation_directory,
+  0, 0, 0,
+  "Return the directory name in which the Emacs executable was located")
+  ()
+{
+  return Fcopy_sequence (Vinvocation_directory);
+}
+
 \f
 #ifdef VMS
 #ifdef LINK_CRTL_SHARE
@@ -183,6 +210,28 @@ extern noshare char **environ;
 #endif /* LINK_CRTL_SHARE */
 #endif /* VMS */
 
+#ifndef ORDINARY_LINK
+/* We don't include crtbegin.o and crtend.o in the link,
+   so these functions and variables might be missed.
+   Provide dummy definitions to avoid error.
+   (We don't have any real constructors or destructors.)  */
+#ifdef __GNUC__
+__do_global_ctors ()
+{}
+__do_global_ctors_aux ()
+{}
+__do_global_dtors ()
+{}
+/* Linux has a bug in its library; avoid an error.  */
+#ifndef LINUX
+char * __CTOR_LIST__[2] = { (char *) (-1), 0 };
+#endif
+char * __DTOR_LIST__[2] = { (char *) (-1), 0 };
+__main ()
+{}
+#endif /* __GNUC__ */
+#endif /* ORDINARY_LINK */
+
 /* ARGSUSED */
 main (argc, argv, envp)
      int argc;
@@ -212,6 +261,15 @@ main (argc, argv, envp)
     }
 #endif
 
+#ifdef NeXT
+  extern int malloc_cookie;
+
+  /* This helps out unexnext.c.  */
+  if (initialized)
+    if (malloc_jumpstart (malloc_cookie) != 0)
+      printf ("malloc jumpstart failed!\n");
+#endif /* NeXT */
+
 #ifdef HAVE_X_WINDOWS
   /* Stupid kludge to catch command-line display spec.  We can't
      handle this argument entirely in window system dependent code
@@ -221,7 +279,7 @@ main (argc, argv, envp)
     int i;
 
     for (i = 1; (i < argc && ! display_arg); i++)
-      if (!strcmp (argv[i], "-d"))
+      if (!strcmp (argv[i], "-d") || !strcmp (argv[i], "-display"))
        display_arg = 1;
   }
 #endif
@@ -263,10 +321,15 @@ main (argc, argv, envp)
 #endif
 
   clearerr (stdin);
+
 #ifdef BSD
-  setpgrp (0, getpid ());
+  {
+    inherited_pgroup = getpgrp (0);
+    setpgrp (0, getpid ());
+  }
 #endif
 
+
 #ifdef APOLLO
 #ifndef APOLLO_SR10
   /* If USE_DOMAIN_ACLS environment variable exists,
@@ -278,18 +341,21 @@ main (argc, argv, envp)
 
 #ifndef SYSTEM_MALLOC
   if (! initialized)
-    malloc_init (0, malloc_warning);
+    {
+      /* Arrange to get warning messages as memory fills up.  */
+      memory_warnings (0, malloc_warning);
+
+      /* Arrange to disable interrupt input while malloc and friends are
+        running.  */
+      uninterrupt_malloc ();
+    }
 #endif /* not SYSTEM_MALLOC */
 
-#ifdef HIGHPRI
-  setpriority (PRIO_PROCESS, getpid (), HIGHPRI);
+#ifdef PRIO_PROCESS
+  if (emacs_priority)
+    nice (emacs_priority);
   setuid (getuid ());
-#endif /* HIGHPRI */
-
-#ifdef BSD
-  /* interrupt_input has trouble if we aren't in a separate process group.  */
-  setpgrp (getpid (), getpid ());
-#endif
+#endif /* PRIO_PROCESS */
 
   inhibit_window_system = 0;
 
@@ -358,14 +424,21 @@ main (argc, argv, envp)
       signal (SIGQUIT, fatal_error_signal);
       signal (SIGILL, fatal_error_signal);
       signal (SIGTRAP, fatal_error_signal);
+#ifdef SIGIOT
+      /* This is missing on some systems - OS/2, for example.  */
       signal (SIGIOT, fatal_error_signal);
+#endif
 #ifdef SIGEMT
       signal (SIGEMT, fatal_error_signal);
 #endif
       signal (SIGFPE, fatal_error_signal);
+#ifdef SIGBUS
       signal (SIGBUS, fatal_error_signal);
+#endif
       signal (SIGSEGV, fatal_error_signal);
+#ifdef SIGSYS
       signal (SIGSYS, fatal_error_signal);
+#endif
       signal (SIGTERM, fatal_error_signal);
 #ifdef SIGXCPU
       signal (SIGXCPU, fatal_error_signal);
@@ -385,7 +458,9 @@ main (argc, argv, envp)
       signal (SIGAIO, fatal_error_signal);
       signal (SIGPTY, fatal_error_signal);
 #endif
+#ifndef _I386
       signal (SIGIOINT, fatal_error_signal);
+#endif
       signal (SIGGRANT, fatal_error_signal);
       signal (SIGRETRACT, fatal_error_signal);
       signal (SIGSOUND, fatal_error_signal);
@@ -414,10 +489,18 @@ main (argc, argv, envp)
   init_alloc ();
   init_eval ();
   init_data ();
-  init_lread ();
 
-  init_cmdargs (argc, argv, skip_args);        /* Create list Vcommand_line_args */
+  /* egetenv is a pretty low-level facility, which may get called in
+     many circumstances; it seems flimsy to put off initializing it
+     until calling init_callproc.  */
+  set_process_environment ();
+
   init_buffer ();      /* Init default directory of main buffer */
+
+  init_callproc ();    /* Must precede init_cmdargs and init_sys_modes.  */
+  init_cmdargs (argc, argv, skip_args);        /* Must precede init_lread.  */
+  init_lread ();
+
   if (!noninteractive)
     {
 #ifdef VMS
@@ -426,7 +509,6 @@ main (argc, argv, envp)
       init_display (); /* Determine terminal type.  init_sys_modes uses results */
     }
   init_keyboard ();    /* This too must precede init_sys_modes */
-  init_callproc ();    /* And this too. */
 #ifdef VMS
   init_vmsproc ();     /* And this too. */
 #endif /* VMS */
@@ -458,9 +540,7 @@ main (argc, argv, envp)
       syms_of_print ();
       syms_of_eval ();
       syms_of_fns ();
-#ifdef LISP_FLOAT_TYPE
       syms_of_floatfns ();
-#endif
 
       syms_of_abbrev ();
       syms_of_buffer ();
@@ -493,6 +573,9 @@ main (argc, argv, envp)
       syms_of_frame ();
       syms_of_syntax ();
       syms_of_undo ();
+
+      /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
+      syms_of_textprop ();
 #ifdef VMS
       syms_of_vmsproc ();
 #endif /* VMS */
@@ -501,6 +584,7 @@ main (argc, argv, envp)
 #ifdef HAVE_X_WINDOWS
       syms_of_xterm ();
       syms_of_xfns ();
+      syms_of_xfaces ();
 #ifdef HAVE_X11
       syms_of_xselect ();
 #endif
@@ -525,6 +609,7 @@ main (argc, argv, envp)
       keys_of_macros ();
       keys_of_minibuf ();
       keys_of_window ();
+      keys_of_frame ();
     }
 
   if (!initialized)
@@ -543,14 +628,14 @@ main (argc, argv, envp)
 
   initialized = 1;
 
-#ifdef sun
-  /* sun's localtime() has a bug.  it caches the value of the time
+#if defined (sun) || defined (LOCALTIME_CACHE)
+  /* sun's localtime has a bug.  it caches the value of the time
      zone rather than looking it up every time.  Since localtime() is
      called to bolt the undumping time into the undumped emacs, this
-     results in localtime() ignoring the TZ environment variable.
-     This flushes the new TZ value into localtime(). */
-  tzset();
-#endif /* sun */
+     results in localtime ignoring the TZ environment variable.
+     This flushes the new TZ value into localtime. */
+  tzset ();
+#endif /* defined (sun) || defined (LOCALTIME_CACHE) */
 
   /* Enter editor command loop.  This never returns.  */
   Frecursive_edit ();
@@ -558,7 +643,7 @@ main (argc, argv, envp)
 }
 \f
 DEFUN ("kill-emacs", Fkill_emacs, Skill_emacs, 0, 1, "P",
-  "Exit the Emacs job and kill it.  Ask for confirmation, without argument.\n\
+  "Exit the Emacs job and kill it.\n\
 If ARG is an integer, return ARG as the exit program code.\n\
 If ARG is a  string, stuff it as keyboard input.\n\n\
 The value of `kill-emacs-hook', if not void,\n\
@@ -579,49 +664,93 @@ all of which are called before Emacs is actually killed.")
   if (!NILP (Vrun_hooks) && !noninteractive)
     call1 (Vrun_hooks, intern ("kill-emacs-hook"));
 
-  kill_buffer_processes (Qnil);
+  UNGCPRO;
+
+/* Is it really necessary to do this deassign
+   when we are going to exit anyway?  */
+/* #ifdef VMS
+  stop_vms_input ();
+ #endif  */
+
+  shut_down_emacs (0, 0, STRINGP (arg) ? arg : Qnil);
 
+  exit ((XTYPE (arg) == Lisp_Int) ? XINT (arg)
 #ifdef VMS
-  kill_vms_processes ();
-#endif /* VMS */
+       : 1
+#else
+       : 0
+#endif
+       );
+  /* NOTREACHED */
+}
+
+
+/* Perform an orderly shutdown of Emacs.  Autosave any modified
+   buffers, kill any child processes, clean up the terminal modes (if
+   we're in the foreground), and other stuff like that.  Don't perform
+   any redisplay; this may be called when Emacs is shutting down in
+   the background, or after its X connection has died.
+
+   If SIG is a signal number, print a message for it.
+
+   This is called by fatal signal handlers, X protocol error handlers,
+   and Fkill_emacs.  */
+
+void
+shut_down_emacs (sig, no_x, stuff)
+     int sig, no_x;
+     Lisp_Object stuff;
+{
+  /* If we are controlling the terminal, reset terminal modes */
+#ifdef EMACS_HAVE_TTY_PGRP
+  {
+#ifdef USG
+    int pgrp = getpgrp ();
+#else
+    int pgrp = getpgrp (0);
+#endif
+    int tpgrp;
+    if (EMACS_GET_TTY_PGRP (0, &tpgrp) != -1
+       && tpgrp == pgrp)
+      {
+       fflush (stdout);
+       reset_sys_modes ();
+       if (sig && sig != SIGTERM)
+         fprintf (stderr, "Fatal error (%d).", sig);
+      }
+  }
+#else
+  fflush (stdout);
+  reset_sys_modes ();
+#endif
+
+  stuff_buffered_input (stuff);
 
+  kill_buffer_processes (Qnil);
   Fdo_auto_save (Qt, Qnil);
 
 #ifdef CLASH_DETECTION
   unlock_all_files ();
-#endif /* CLASH_DETECTION */
+#endif
 
-  fflush (stdout);
-  reset_sys_modes ();
+#ifdef VMS
+  kill_vms_processes ();
+#endif
 
 #ifdef HAVE_X_WINDOWS
-  if (!noninteractive && EQ (Vwindow_system, intern ("x")))
+  if (!noninteractive && EQ (Vwindow_system, intern ("x")) && ! no_x)
     Fx_close_current_connection ();
 #endif /* HAVE_X_WINDOWS */
 
-  UNGCPRO;
-
-/* Is it really necessary to do this deassign
-   when we are going to exit anyway?  */
-/* #ifdef VMS
-  stop_vms_input ();
- #endif  */
-  stuff_buffered_input (arg);
 #ifdef SIGIO
   /* There is a tendency for a SIGIO signal to arrive within exit,
      and cause a SIGHUP because the input descriptor is already closed.  */
   unrequest_sigio ();
   signal (SIGIO, SIG_IGN);
 #endif
-  exit ((XTYPE (arg) == Lisp_Int) ? XINT (arg)
-#ifdef VMS
-       : 1
-#else
-       : 0
-#endif
-       );
-  /* NOTREACHED */
 }
+
+
 \f
 #ifndef CANNOT_DUMP
 /* Nothing like this can be implemented on an Apollo.
@@ -649,7 +778,7 @@ This function exists on systems that use HAVE_SHM.")
   /* Tell malloc where start of impure now is */
   /* Also arrange for warnings when nearly out of space.  */
 #ifndef SYSTEM_MALLOC
-  malloc_init (&my_edata, malloc_warning);
+  memory_warnings (&my_edata, malloc_warning);
 #endif
   map_out_data (XSTRING (intoname)->data);
 
@@ -694,7 +823,7 @@ and announce itself normally when it is run.")
   /* Tell malloc where start of impure now is */
   /* Also arrange for warnings when nearly out of space.  */
 #ifndef SYSTEM_MALLOC
-  malloc_init (&my_edata, malloc_warning);
+  memory_warnings (&my_edata, malloc_warning);
 #endif
   unexec (XSTRING (intoname)->data,
          !NILP (symname) ? XSTRING (symname)->data : 0, &my_edata, 0, 0);
@@ -709,9 +838,7 @@ and announce itself normally when it is run.")
 
 #endif /* not CANNOT_DUMP */
 \f
-#ifdef VMS
-#define SEPCHAR ','
-#else
+#ifndef SEPCHAR
 #define SEPCHAR ':'
 #endif
 
@@ -750,14 +877,19 @@ decode_env_path (evarname, defalt)
 
 syms_of_emacs ()
 {
+#ifndef CANNOT_DUMP
 #ifdef HAVE_SHM
   defsubr (&Sdump_emacs_data);
 #else
   defsubr (&Sdump_emacs);
+#endif
 #endif
 
   defsubr (&Skill_emacs);
 
+  defsubr (&Sinvocation_name);
+  defsubr (&Sinvocation_directory);
+
   DEFVAR_LISP ("command-line-args", &Vcommand_line_args,
     "Args passed by shell to Emacs, as a list of strings.");
 
@@ -768,8 +900,22 @@ syms_of_emacs ()
   DEFVAR_BOOL ("noninteractive", &noninteractive1,
     "Non-nil means Emacs is running without interactive terminal.");
 
+  DEFVAR_LISP ("kill-emacs-hook", &Vkill_emacs_hook,
+    "Hook to be run whenever kill-emacs is called.\n\
+Since kill-emacs may be invoked when the terminal is disconnected (or\n\
+in other similar situations), functions placed on this hook should not\n\
+expect to be able to interact with the user.");
   Vkill_emacs_hook = Qnil;
 
-  DEFVAR_LISP ("kill-emacs-hook", &Vkill_emacs_hook,
-    "Hook to be run whenever kill-emacs is called.");
+  DEFVAR_INT ("emacs-priority", &emacs_priority,
+    "Priority for Emacs to run at.\n\
+This value is effective only if set before Emacs is dumped,\n\
+and only if the Emacs executable is installed with setuid to permit\n\
+it to change priority.  (Emacs sets its uid back to the real uid.)");
+  emacs_priority = 0;
+
+  staticpro (&Vinvocation_name);
+  Vinvocation_name = Qnil;
+  staticpro (&Vinvocation_directory);
+  Vinvocation_directory = Qnil;
 }