*** empty log message ***
[bpt/emacs.git] / src / emacs.c
1 /* Fully extensible Emacs, running on Unix, intended for GNU.
2 Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21 #include <signal.h>
22 #include <errno.h>
23
24 #include "config.h"
25 #include <stdio.h>
26
27 #include <sys/types.h>
28 #include <sys/file.h>
29
30 #ifdef VMS
31 #include <ssdef.h>
32 #endif
33
34 #ifdef USG5
35 #include <fcntl.h>
36 #endif
37
38 #ifdef BSD
39 #include <sys/ioctl.h>
40 #endif
41
42 #ifdef APOLLO
43 #ifndef APOLLO_SR10
44 #include <default_acl.h>
45 #endif
46 #endif
47
48 #undef NULL
49 #include "lisp.h"
50 #include "commands.h"
51
52 #ifndef O_RDWR
53 #define O_RDWR 2
54 #endif
55
56 #define PRIO_PROCESS 0
57
58 /* Command line args from shell, as list of strings */
59 Lisp_Object Vcommand_line_args;
60
61 /* Set nonzero after Emacs has started up the first time.
62 Prevents reinitialization of the Lisp world and keymaps
63 on subsequent starts. */
64 int initialized;
65
66 /* Variable whose value is symbol giving operating system type */
67 Lisp_Object Vsystem_type;
68
69 /* If non-zero, emacs should not attempt to use an window-specific code,
70 but instead should use the virtual terminal under which it was started */
71 int inhibit_window_system;
72
73 #ifdef HAVE_X_WINDOWS
74 /* If non-zero, -d was specified, meaning we're using some window system. */
75 int display_arg;
76 #endif
77
78 /* An address near the bottom of the stack.
79 Tells GC how to save a copy of the stack. */
80 char *stack_bottom;
81
82 #ifdef HAVE_X_WINDOWS
83 extern Lisp_Object Vwindow_system;
84 #endif /* HAVE_X_WINDOWS */
85
86 #ifdef USG_SHARED_LIBRARIES
87 /* If nonzero, this is the place to put the end of the writable segment
88 at startup. */
89
90 unsigned int bss_end = 0;
91 #endif
92
93 /* Nonzero means running Emacs without interactive terminal. */
94
95 int noninteractive;
96
97 /* Value of Lisp variable `noninteractive'.
98 Normally same as C variable `noninteractive'
99 but nothing terrible happens if user sets this one. */
100
101 int noninteractive1;
102 \f
103 /* Signal code for the fatal signal that was received */
104 int fatal_error_code;
105
106 /* Nonzero if handling a fatal error already */
107 int fatal_error_in_progress;
108
109 /* Handle bus errors, illegal instruction, etc. */
110 fatal_error_signal (sig)
111 int sig;
112 {
113 #ifdef BSD
114 int tpgrp;
115 #endif /* BSD */
116
117 fatal_error_code = sig;
118 signal (sig, SIG_DFL);
119
120 /* If fatal error occurs in code below, avoid infinite recursion. */
121 if (fatal_error_in_progress)
122 kill (getpid (), fatal_error_code);
123
124 fatal_error_in_progress = 1;
125
126 /* If we are controlling the terminal, reset terminal modes */
127 #ifdef BSD
128 if (ioctl(0, TIOCGPGRP, &tpgrp) == 0
129 && tpgrp == getpgrp (0))
130 #endif /* BSD */
131 {
132 reset_sys_modes ();
133 if (sig != SIGTERM)
134 fprintf (stderr, "Fatal error (%d).", sig);
135 }
136
137 /* Clean up */
138 #ifdef subprocesses
139 kill_buffer_processes (Qnil);
140 #endif
141 Fdo_auto_save (Qt, Qnil);
142
143 #ifdef CLASH_DETECTION
144 unlock_all_files ();
145 #endif /* CLASH_DETECTION */
146
147 #ifdef VMS
148 kill_vms_processes ();
149 LIB$STOP (SS$_ABORT);
150 #else
151 /* Signal the same code; this time it will really be fatal. */
152 kill (getpid (), fatal_error_code);
153 #endif /* not VMS */
154 }
155 \f
156 /* Code for dealing with Lisp access to the Unix command line */
157
158 static
159 init_cmdargs (argc, argv, skip_args)
160 int argc;
161 char **argv;
162 int skip_args;
163 {
164 register int i;
165
166 Vcommand_line_args = Qnil;
167
168 for (i = argc - 1; i >= 0; i--)
169 {
170 if (i == 0 || i > skip_args)
171 Vcommand_line_args
172 = Fcons (build_string (argv[i]), Vcommand_line_args);
173 }
174 }
175 \f
176 #ifdef VMS
177 #ifdef LINK_CRTL_SHARE
178 #ifdef SHAREABLE_LIB_BUG
179 extern noshare char **environ;
180 #endif /* SHAREABLE_LIB_BUG */
181 #endif /* LINK_CRTL_SHARE */
182 #endif /* VMS */
183
184 /* ARGSUSED */
185 main (argc, argv, envp)
186 int argc;
187 char **argv;
188 char **envp;
189 {
190 char stack_bottom_variable;
191 int skip_args = 0;
192 extern int errno;
193 extern sys_nerr;
194 extern char *sys_errlist[];
195 extern void malloc_warning ();
196
197 /* Map in shared memory, if we are using that. */
198 #ifdef HAVE_SHM
199 if (argc > 1 && !strcmp (argv[1], "-nl"))
200 {
201 map_in_data (0);
202 /* The shared memory was just restored, which clobbered this. */
203 skip_args = 1;
204 }
205 else
206 {
207 map_in_data (1);
208 /* The shared memory was just restored, which clobbered this. */
209 skip_args = 0;
210 }
211 #endif
212
213 #ifdef HAVE_X_WINDOWS
214 /* Stupid kludge to catch command-line display spec. We can't
215 handle this argument entirely in window system dependent code
216 because we don't even know which window system dependent code
217 to run until we've recognized this argument. */
218 {
219 int i;
220
221 for (i = 1; (i < argc && ! display_arg); i++)
222 if (!strcmp (argv[i], "-d"))
223 display_arg = 1;
224 }
225 #endif
226
227 #ifdef VMS
228 /* If -map specified, map the data file in */
229 if (argc > 2 && ! strcmp (argv[1], "-map"))
230 {
231 skip_args = 2;
232 mapin_data (argv[2]);
233 }
234
235 #ifdef LINK_CRTL_SHARE
236 #ifdef SHAREABLE_LIB_BUG
237 /* Bletcherous shared libraries! */
238 if (!stdin)
239 stdin = fdopen (0, "r");
240 if (!stdout)
241 stdout = fdopen (1, "w");
242 if (!stderr)
243 stderr = fdopen (2, "w");
244 if (!environ)
245 environ = envp;
246 #endif /* SHAREABLE_LIB_BUG */
247 #endif /* LINK_CRTL_SHARE */
248 #endif /* VMS */
249
250 /* Record (approximately) where the stack begins. */
251 stack_bottom = &stack_bottom_variable;
252
253 #ifdef RUN_TIME_REMAP
254 if (initialized)
255 run_time_remap (argv[0]);
256 #endif
257
258 #ifdef USG_SHARED_LIBRARIES
259 if (bss_end)
260 brk (bss_end);
261 #endif
262
263 clearerr (stdin);
264 #ifdef BSD
265 setpgrp (0, getpid ());
266 #endif
267
268 #ifdef APOLLO
269 #ifndef APOLLO_SR10
270 /* If USE_DOMAIN_ACLS environment variable exists,
271 use ACLs rather than UNIX modes. */
272 if (egetenv ("USE_DOMAIN_ACLS"))
273 default_acl (USE_DEFACL);
274 #endif
275 #endif /* APOLLO */
276
277 #ifndef SYSTEM_MALLOC
278 if (! initialized)
279 malloc_init (0, malloc_warning);
280 #endif /* not SYSTEM_MALLOC */
281
282 #ifdef HIGHPRI
283 setpriority (PRIO_PROCESS, getpid (), HIGHPRI);
284 setuid (getuid ());
285 #endif /* HIGHPRI */
286
287 #ifdef BSD
288 /* interrupt_input has trouble if we aren't in a separate process group. */
289 setpgrp (getpid (), getpid ());
290 #endif
291
292 inhibit_window_system = 0;
293
294 /* Handle the -t switch, which specifies filename to use as terminal */
295 if (skip_args + 2 < argc && !strcmp (argv[skip_args + 1], "-t"))
296 {
297 int result;
298 skip_args += 2;
299 close (0);
300 close (1);
301 result = open (argv[skip_args], O_RDWR, 2 );
302 if (result < 0)
303 {
304 char *errstring;
305
306 if (errno >= 0 && errno < sys_nerr)
307 errstring = sys_errlist[errno];
308 else
309 errstring = "undocumented error code";
310 fprintf (stderr, "emacs: %s: %s\n", argv[skip_args], errstring);
311 exit (1);
312 }
313 dup (0);
314 if (! isatty (0))
315 {
316 fprintf (stderr, "emacs: %s: not a tty\n", argv[skip_args]);
317 exit (1);
318 }
319 fprintf (stderr, "Using %s\n", argv[skip_args]);
320 #ifdef HAVE_X_WINDOWS
321 inhibit_window_system = 1; /* -t => -nw */
322 #endif
323 }
324
325 if (skip_args + 1 < argc
326 && (!strcmp (argv[skip_args + 1], "-nw")))
327 {
328 skip_args += 1;
329 inhibit_window_system = 1;
330 }
331
332 /* Handle the -batch switch, which means don't do interactive display. */
333 noninteractive = 0;
334 if (skip_args + 1 < argc && !strcmp (argv[skip_args + 1], "-batch"))
335 {
336 skip_args += 1;
337 noninteractive = 1;
338 }
339
340 #ifdef POSIX_SIGNALS
341 init_signals ();
342 #endif
343
344 if (
345 #ifndef CANNOT_DUMP
346 ! noninteractive || initialized
347 #else
348 1
349 #endif
350 )
351 {
352 /* Don't catch these signals in batch mode if not initialized.
353 On some machines, this sets static data that would make
354 signal fail to work right when the dumped Emacs is run. */
355 signal (SIGHUP, fatal_error_signal);
356 signal (SIGQUIT, fatal_error_signal);
357 signal (SIGILL, fatal_error_signal);
358 signal (SIGTRAP, fatal_error_signal);
359 signal (SIGIOT, fatal_error_signal);
360 #ifdef SIGEMT
361 signal (SIGEMT, fatal_error_signal);
362 #endif
363 signal (SIGFPE, fatal_error_signal);
364 signal (SIGBUS, fatal_error_signal);
365 signal (SIGSEGV, fatal_error_signal);
366 signal (SIGSYS, fatal_error_signal);
367 signal (SIGTERM, fatal_error_signal);
368 #ifdef SIGXCPU
369 signal (SIGXCPU, fatal_error_signal);
370 #endif
371 #ifdef SIGXFSZ
372 signal (SIGXFSZ, fatal_error_signal);
373 #endif /* SIGXFSZ */
374
375 #ifdef AIX
376 signal (SIGDANGER, fatal_error_signal);
377 signal (20, fatal_error_signal);
378 signal (21, fatal_error_signal);
379 signal (22, fatal_error_signal);
380 signal (23, fatal_error_signal);
381 signal (24, fatal_error_signal);
382 #ifdef SIGIO
383 signal (SIGAIO, fatal_error_signal);
384 signal (SIGPTY, fatal_error_signal);
385 #endif
386 signal (SIGIOINT, fatal_error_signal);
387 signal (SIGGRANT, fatal_error_signal);
388 signal (SIGRETRACT, fatal_error_signal);
389 signal (SIGSOUND, fatal_error_signal);
390 signal (SIGMSG, fatal_error_signal);
391 #endif /* AIX */
392 }
393
394 noninteractive1 = noninteractive;
395
396 /* Perform basic initializations (not merely interning symbols) */
397
398 if (!initialized)
399 {
400 init_alloc_once ();
401 init_obarray ();
402 init_eval_once ();
403 init_syntax_once (); /* Create standard syntax table. */
404 /* Must be done before init_buffer */
405 init_casetab_once ();
406 init_buffer_once (); /* Create buffer table and some buffers */
407 init_minibuf_once (); /* Create list of minibuffers */
408 /* Must precede init_window_once */
409 init_window_once (); /* Init the window system */
410 }
411
412 init_alloc ();
413 #ifdef MAINTAIN_ENVIRONMENT
414 init_environ ();
415 #endif
416 init_eval ();
417 init_data ();
418 init_lread ();
419
420 init_cmdargs (argc, argv, skip_args); /* Create list Vcommand_line_args */
421 init_buffer (); /* Init default directory of main buffer */
422 if (!noninteractive)
423 {
424 #ifdef VMS
425 init_vms_input ();/* init_display calls get_screen_size, that needs this */
426 #endif /* VMS */
427 init_display (); /* Determine terminal type. init_sys_modes uses results */
428 }
429 init_keyboard (); /* This too must precede init_sys_modes */
430 init_callproc (); /* And this too. */
431 #ifdef VMS
432 init_vmsproc (); /* And this too. */
433 #endif /* VMS */
434 init_sys_modes (); /* Init system terminal modes (RAW or CBREAK, etc.) */
435 init_xdisp ();
436 init_macros ();
437 init_editfns ();
438 #ifdef LISP_FLOAT_TYPE
439 init_floatfns ();
440 #endif
441 #ifdef VMS
442 init_vmsfns ();
443 #endif /* VMS */
444 #ifdef subprocesses
445 init_process ();
446 #endif /* subprocesses */
447
448 /* Intern the names of all standard functions and variables; define standard keys */
449
450 if (!initialized)
451 {
452 /* The basic levels of Lisp must come first */
453 /* And data must come first of all
454 for the sake of symbols like error-message */
455 syms_of_data ();
456 syms_of_alloc ();
457 #ifdef MAINTAIN_ENVIRONMENT
458 syms_of_environ ();
459 #endif /* MAINTAIN_ENVIRONMENT */
460 syms_of_lread ();
461 syms_of_print ();
462 syms_of_eval ();
463 syms_of_fns ();
464 #ifdef LISP_FLOAT_TYPE
465 syms_of_floatfns ();
466 #endif
467
468 syms_of_abbrev ();
469 syms_of_buffer ();
470 syms_of_bytecode ();
471 syms_of_callint ();
472 syms_of_casefiddle ();
473 syms_of_casetab ();
474 syms_of_callproc ();
475 syms_of_cmds ();
476 #ifndef NO_DIR_LIBRARY
477 syms_of_dired ();
478 #endif /* not NO_DIR_LIBRARY */
479 syms_of_display ();
480 syms_of_doc ();
481 syms_of_editfns ();
482 syms_of_emacs ();
483 syms_of_fileio ();
484 #ifdef CLASH_DETECTION
485 syms_of_filelock ();
486 #endif /* CLASH_DETECTION */
487 syms_of_indent ();
488 syms_of_keyboard ();
489 syms_of_keymap ();
490 syms_of_macros ();
491 syms_of_marker ();
492 syms_of_minibuf ();
493 syms_of_mocklisp ();
494 #ifdef subprocesses
495 syms_of_process ();
496 #endif /* subprocesses */
497 syms_of_search ();
498 #ifdef MULTI_SCREEN
499 syms_of_screen ();
500 #endif
501 syms_of_syntax ();
502 syms_of_undo ();
503 #ifdef VMS
504 syms_of_vmsproc ();
505 #endif /* VMS */
506 syms_of_window ();
507 syms_of_xdisp ();
508 #ifdef HAVE_X_WINDOWS
509 syms_of_xterm ();
510 syms_of_xfns ();
511 #ifdef HAVE_X11
512 syms_of_xselect ();
513 #endif
514 #ifdef HAVE_X_MENU
515 syms_of_xmenu ();
516 #endif /* HAVE_X_MENU */
517 #endif /* HAVE_X_WINDOWS */
518
519 #ifdef SYMS_SYSTEM
520 SYMS_SYSTEM;
521 #endif
522
523 #ifdef SYMS_MACHINE
524 SYMS_MACHINE;
525 #endif
526
527 keys_of_casefiddle ();
528 keys_of_cmds ();
529 keys_of_buffer ();
530 keys_of_keyboard ();
531 keys_of_keymap ();
532 keys_of_macros ();
533 keys_of_minibuf ();
534 keys_of_window ();
535 }
536
537 if (!initialized)
538 {
539 /* Handle -l loadup-and-dump, args passed by Makefile. */
540 if (argc > 2 + skip_args && !strcmp (argv[1 + skip_args], "-l"))
541 Vtop_level = Fcons (intern ("load"),
542 Fcons (build_string (argv[2 + skip_args]), Qnil));
543 #ifdef CANNOT_DUMP
544 /* Unless next switch is -nl, load "loadup.el" first thing. */
545 if (!(argc > 1 + skip_args && !strcmp (argv[1 + skip_args], "-nl")))
546 Vtop_level = Fcons (intern ("load"),
547 Fcons (build_string ("loadup.el"), Qnil));
548 #endif /* CANNOT_DUMP */
549 }
550
551 initialized = 1;
552
553 /* Enter editor command loop. This never returns. */
554 Frecursive_edit ();
555 /* NOTREACHED */
556 }
557 \f
558 DEFUN ("kill-emacs", Fkill_emacs, Skill_emacs, 0, 1, "P",
559 "Exit the Emacs job and kill it. Ask for confirmation, without argument.\n\
560 If ARG is an integer, return ARG as the exit program code.\n\
561 If ARG is a string, stuff it as keyboard input.\n\n\
562 The value of `kill-emacs-hook', if not void,\n\
563 is a list of functions (of no args),\n\
564 all of which are called before Emacs is actually killed.")
565 (arg)
566 Lisp_Object arg;
567 {
568 Lisp_Object hook, hook1;
569 int i;
570 struct gcpro gcpro1;
571
572 GCPRO1 (arg);
573
574 if (feof (stdin))
575 arg = Qt;
576
577 if (!NULL (Vrun_hooks) && !noninteractive)
578 call1 (Vrun_hooks, intern ("kill-emacs-hook"));
579
580 #ifdef subprocesses
581 kill_buffer_processes (Qnil);
582 #endif /* subprocesses */
583
584 #ifdef VMS
585 kill_vms_processes ();
586 #endif /* VMS */
587
588 Fdo_auto_save (Qt, Qnil);
589
590 #ifdef CLASH_DETECTION
591 unlock_all_files ();
592 #endif /* CLASH_DETECTION */
593
594 fflush (stdout);
595 reset_sys_modes ();
596
597 #ifdef HAVE_X_WINDOWS
598 if (!noninteractive && EQ (Vwindow_system, intern ("x")))
599 Fx_close_current_connection ();
600 #endif /* HAVE_X_WINDOWS */
601
602 UNGCPRO;
603
604 /* Is it really necessary to do this deassign
605 when we are going to exit anyway? */
606 /* #ifdef VMS
607 stop_vms_input ();
608 #endif */
609 stuff_buffered_input (arg);
610 #ifdef SIGIO
611 /* There is a tendency for a SIGIO signal to arrive within exit,
612 and cause a SIGHUP because the input descriptor is already closed. */
613 unrequest_sigio ();
614 signal (SIGIO, SIG_IGN);
615 #endif
616 exit ((XTYPE (arg) == Lisp_Int) ? XINT (arg)
617 #ifdef VMS
618 : 1
619 #else
620 : 0
621 #endif
622 );
623 /* NOTREACHED */
624 }
625 \f
626 #ifndef CANNOT_DUMP
627 /* Nothing like this can be implemented on an Apollo.
628 What a loss! */
629
630 #ifdef HAVE_SHM
631
632 DEFUN ("dump-emacs-data", Fdump_emacs_data, Sdump_emacs_data, 1, 1, 0,
633 "Dump current state of Emacs into data file FILENAME.\n\
634 This function exists on systems that use HAVE_SHM.")
635 (intoname)
636 Lisp_Object intoname;
637 {
638 extern int my_edata;
639 Lisp_Object tem;
640 extern void malloc_warning ();
641
642 CHECK_STRING (intoname, 0);
643 intoname = Fexpand_file_name (intoname, Qnil);
644
645 tem = Vpurify_flag;
646 Vpurify_flag = Qnil;
647
648 fflush (stdout);
649 /* Tell malloc where start of impure now is */
650 /* Also arrange for warnings when nearly out of space. */
651 #ifndef SYSTEM_MALLOC
652 malloc_init (&my_edata, malloc_warning);
653 #endif
654 map_out_data (XSTRING (intoname)->data);
655
656 Vpurify_flag = tem;
657
658 return Qnil;
659 }
660
661 #else /* not HAVE_SHM */
662
663 DEFUN ("dump-emacs", Fdump_emacs, Sdump_emacs, 2, 2, 0,
664 "Dump current state of Emacs into executable file FILENAME.\n\
665 Take symbols from SYMFILE (presumably the file you executed to run Emacs).\n\
666 This is used in the file `loadup.el' when building Emacs.\n\
667 \n\
668 Bind `command-line-processed' to nil before dumping,\n\
669 if you want the dumped Emacs to process its command line\n\
670 and announce itself normally when it is run.")
671 (intoname, symname)
672 Lisp_Object intoname, symname;
673 {
674 extern int my_edata;
675 Lisp_Object tem;
676 extern void malloc_warning ();
677
678 CHECK_STRING (intoname, 0);
679 intoname = Fexpand_file_name (intoname, Qnil);
680 if (!NULL (symname))
681 {
682 CHECK_STRING (symname, 0);
683 if (XSTRING (symname)->size)
684 symname = Fexpand_file_name (symname, Qnil);
685 }
686
687 tem = Vpurify_flag;
688 Vpurify_flag = Qnil;
689
690 fflush (stdout);
691 #ifdef VMS
692 mapout_data (XSTRING (intoname)->data);
693 #else
694 /* Tell malloc where start of impure now is */
695 /* Also arrange for warnings when nearly out of space. */
696 #ifndef SYSTEM_MALLOC
697 malloc_init (&my_edata, malloc_warning);
698 #endif
699 unexec (XSTRING (intoname)->data,
700 !NULL (symname) ? XSTRING (symname)->data : 0, &my_edata, 0, 0);
701 #endif /* not VMS */
702
703 Vpurify_flag = tem;
704
705 return Qnil;
706 }
707
708 #endif /* not HAVE_SHM */
709
710 #endif /* not CANNOT_DUMP */
711 \f
712 #ifdef VMS
713 #define SEPCHAR ','
714 #else
715 #define SEPCHAR ':'
716 #endif
717
718 Lisp_Object
719 decode_env_path (evarname, defalt)
720 char *evarname, *defalt;
721 {
722 register char *path, *p;
723 extern char *index ();
724
725 Lisp_Object lpath;
726
727 path = (char *) egetenv (evarname);
728 if (!path)
729 path = defalt;
730 lpath = Qnil;
731 while (1)
732 {
733 p = index (path, SEPCHAR);
734 if (!p) p = path + strlen (path);
735 lpath = Fcons (p - path ? make_string (path, p - path) : Qnil,
736 lpath);
737 if (*p)
738 path = p + 1;
739 else
740 break;
741 }
742 return Fnreverse (lpath);
743 }
744
745 syms_of_emacs ()
746 {
747 #ifdef HAVE_SHM
748 defsubr (&Sdump_emacs_data);
749 #else
750 defsubr (&Sdump_emacs);
751 #endif
752
753 defsubr (&Skill_emacs);
754
755 DEFVAR_LISP ("command-line-args", &Vcommand_line_args,
756 "Args passed by shell to Emacs, as a list of strings.");
757
758 DEFVAR_LISP ("system-type", &Vsystem_type,
759 "Value is symbol indicating type of operating system you are using.");
760 Vsystem_type = intern (SYSTEM_TYPE);
761
762 DEFVAR_BOOL ("noninteractive", &noninteractive1,
763 "Non-nil means Emacs is running without interactive terminal.");
764 }