/* Fully extensible Emacs, running on Unix, intended for GNU.
- Copyright (C) 1985, 1986, 1987 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,
#include <signal.h>
#include <errno.h>
-#include "config.h"
+#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#include <ssdef.h>
#endif
-#ifdef USG5
-#include <fcntl.h>
-#endif
-
#ifdef BSD
#include <sys/ioctl.h>
#endif
#endif
#endif
-#undef NULL
#include "lisp.h"
#include "commands.h"
+#include "intervals.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;
+
/* Set nonzero after Emacs has started up the first time.
Prevents reinitialization of the Lisp world and keymaps
on subsequent starts. */
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;
int fatal_error_in_progress;
/* Handle bus errors, illegal instruction, etc. */
+SIGTYPE
fatal_error_signal (sig)
int sig;
{
-#ifdef BSD
- int tpgrp;
-#endif /* BSD */
-
fatal_error_code = 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 BSD
- if (ioctl(0, TIOCGPGRP, &tpgrp) == 0
- && tpgrp == getpgrp (0))
-#endif /* BSD */
+ if (! fatal_error_in_progress)
{
- reset_sys_modes ();
- if (sig != SIGTERM)
- fprintf (stderr, "Fatal error (%d).", sig);
- }
+ fatal_error_in_progress = 1;
- /* Clean up */
-#ifdef subprocesses
- kill_buffer_processes (Qnil);
-#endif
- Fdo_auto_save (Qt, Qnil);
-
-#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 */
}
{
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--)
= 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
#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;
}
#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. ask jla */
+ /* Stupid kludge to catch command-line display spec. We can't
+ handle this argument entirely in window system dependent code
+ because we don't even know which window system dependent code
+ to run until we've recognized this argument. */
{
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
#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,
#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;
-/* Handle the -t switch, which specifies filename to use as terminal */
+ /* Handle the -t switch, which specifies filename to use as terminal */
if (skip_args + 2 < argc && !strcmp (argv[skip_args + 1], "-t"))
{
int result;
noninteractive = 1;
}
+#ifdef POSIX_SIGNALS
+ init_signals ();
+#endif
+
if (
#ifndef CANNOT_DUMP
! noninteractive || initialized
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);
signal (22, fatal_error_signal);
signal (23, fatal_error_signal);
signal (24, fatal_error_signal);
+#ifdef SIGIO
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);
}
init_alloc ();
-#ifdef MAINTAIN_ENVIRONMENT
- init_environ ();
-#endif
init_eval ();
init_data ();
- init_read ();
- 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
- init_vms_input ();/* init_display calls get_screen_size, that needs this */
+ init_vms_input ();/* init_display calls get_frame_size, that needs this */
#endif /* VMS */
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 */
#ifdef VMS
init_vmsfns ();
#endif /* VMS */
-#ifdef subprocesses
init_process ();
-#endif /* subprocesses */
+#ifdef CLASH_DETECTION
+ init_filelock ();
+#endif /* CLASH_DETECTION */
/* Intern the names of all standard functions and variables; define standard keys */
for the sake of symbols like error-message */
syms_of_data ();
syms_of_alloc ();
-#ifdef MAINTAIN_ENVIRONMENT
- syms_of_environ ();
-#endif /* MAINTAIN_ENVIRONMENT */
- syms_of_read ();
+ syms_of_lread ();
syms_of_print ();
syms_of_eval ();
syms_of_fns ();
-#ifdef LISP_FLOAT_TYPE
syms_of_floatfns ();
-#endif
syms_of_abbrev ();
syms_of_buffer ();
syms_of_marker ();
syms_of_minibuf ();
syms_of_mocklisp ();
-#ifdef subprocesses
syms_of_process ();
-#endif /* subprocesses */
syms_of_search ();
-#ifdef MULTI_SCREEN
- syms_of_screen ();
-#endif
+ 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 */
syms_of_window ();
syms_of_xdisp ();
#ifdef HAVE_X_WINDOWS
+ syms_of_xterm ();
syms_of_xfns ();
+ syms_of_xfaces ();
+#ifdef HAVE_X11
+ syms_of_xselect ();
+#endif
#ifdef HAVE_X_MENU
syms_of_xmenu ();
#endif /* HAVE_X_MENU */
keys_of_macros ();
keys_of_minibuf ();
keys_of_window ();
+ keys_of_frame ();
}
if (!initialized)
initialized = 1;
+#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 /* defined (sun) || defined (LOCALTIME_CACHE) */
+
/* Enter editor command loop. This never returns. */
Frecursive_edit ();
/* NOTREACHED */
}
\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\
if (feof (stdin))
arg = Qt;
- if (!NULL (Vrun_hooks) && !noninteractive)
+ if (!NILP (Vrun_hooks) && !noninteractive)
call1 (Vrun_hooks, intern ("kill-emacs-hook"));
-#ifdef subprocesses
- kill_buffer_processes (Qnil);
-#endif /* subprocesses */
+ 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.
/* 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);
CHECK_STRING (intoname, 0);
intoname = Fexpand_file_name (intoname, Qnil);
- if (!NULL (symname))
+ if (!NILP (symname))
{
CHECK_STRING (symname, 0);
if (XSTRING (symname)->size)
/* 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,
- !NULL (symname) ? XSTRING (symname)->data : 0, &my_edata, 0, 0);
+ !NILP (symname) ? XSTRING (symname)->data : 0, &my_edata, 0, 0);
#endif /* not VMS */
Vpurify_flag = tem;
#endif /* not CANNOT_DUMP */
\f
-#ifdef VMS
-#define SEPCHAR ','
-#else
+#ifndef SEPCHAR
#define SEPCHAR ':'
#endif
Lisp_Object lpath;
- path = (char *) egetenv (evarname);
+ /* It's okay to use getenv here, because this function is only used
+ to initialize variables when Emacs starts up, and isn't called
+ after that. */
+ if (evarname != 0)
+ path = (char *) getenv (evarname);
+ else
+ path = 0;
if (!path)
path = defalt;
lpath = Qnil;
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.");
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_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;
}