comparison src/emacs.c @ 284:03e467a3d92a

Initial revision
author Jim Blandy <jimb@redhat.com>
date Thu, 23 May 1991 23:18:53 +0000
parents
children 17ca8766781a
comparison
equal deleted inserted replaced
283:78fbe3043a5d 284:03e467a3d92a
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
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
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
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. ask jla */
215 {
216 int i;
217
218 for (i = 1; (i < argc && ! display_arg); i++)
219 if (!strcmp (argv[i], "-d"))
220 display_arg = 1;
221 }
222 #endif
223
224 #ifdef VMS
225 /* If -map specified, map the data file in */
226 if (argc > 2 && ! strcmp (argv[1], "-map"))
227 {
228 skip_args = 2;
229 mapin_data (argv[2]);
230 }
231
232 #ifdef LINK_CRTL_SHARE
233 #ifdef SHAREABLE_LIB_BUG
234 /* Bletcherous shared libraries! */
235 if (!stdin)
236 stdin = fdopen (0, "r");
237 if (!stdout)
238 stdout = fdopen (1, "w");
239 if (!stderr)
240 stderr = fdopen (2, "w");
241 if (!environ)
242 environ = envp;
243 #endif /* SHAREABLE_LIB_BUG */
244 #endif /* LINK_CRTL_SHARE */
245 #endif /* VMS */
246
247 /* Record (approximately) where the stack begins. */
248 stack_bottom = &stack_bottom_variable;
249
250 #ifdef RUN_TIME_REMAP
251 if (initialized)
252 run_time_remap (argv[0]);
253 #endif
254
255 #ifdef USG_SHARED_LIBRARIES
256 if (bss_end)
257 brk (bss_end);
258 #endif
259
260 clearerr (stdin);
261 #ifdef BSD
262 setpgrp (0, getpid ());
263 #endif
264
265 #ifdef APOLLO
266 #ifndef APOLLO_SR10
267 /* If USE_DOMAIN_ACLS environment variable exists,
268 use ACLs rather than UNIX modes. */
269 if (egetenv ("USE_DOMAIN_ACLS"))
270 default_acl (USE_DEFACL);
271 #endif
272 #endif /* APOLLO */
273
274 #ifndef SYSTEM_MALLOC
275 if (! initialized)
276 malloc_init (0, malloc_warning);
277 #endif /* not SYSTEM_MALLOC */
278
279 #ifdef HIGHPRI
280 setpriority (PRIO_PROCESS, getpid (), HIGHPRI);
281 setuid (getuid ());
282 #endif /* HIGHPRI */
283
284 #ifdef BSD
285 /* interrupt_input has trouble if we aren't in a separate process group. */
286 setpgrp (getpid (), getpid ());
287 #endif
288
289 inhibit_window_system = 0;
290
291 /* Handle the -t switch, which specifies filename to use as terminal */
292 if (skip_args + 2 < argc && !strcmp (argv[skip_args + 1], "-t"))
293 {
294 int result;
295 skip_args += 2;
296 close (0);
297 close (1);
298 result = open (argv[skip_args], O_RDWR, 2 );
299 if (result < 0)
300 {
301 char *errstring;
302
303 if (errno >= 0 && errno < sys_nerr)
304 errstring = sys_errlist[errno];
305 else
306 errstring = "undocumented error code";
307 fprintf (stderr, "emacs: %s: %s\n", argv[skip_args], errstring);
308 exit (1);
309 }
310 dup (0);
311 if (! isatty (0))
312 {
313 fprintf (stderr, "emacs: %s: not a tty\n", argv[skip_args]);
314 exit (1);
315 }
316 fprintf (stderr, "Using %s\n", argv[skip_args]);
317 #ifdef HAVE_X_WINDOWS
318 inhibit_window_system = 1; /* -t => -nw */
319 #endif
320 }
321
322 if (skip_args + 1 < argc
323 && (!strcmp (argv[skip_args + 1], "-nw")))
324 {
325 skip_args += 1;
326 inhibit_window_system = 1;
327 }
328
329 /* Handle the -batch switch, which means don't do interactive display. */
330 noninteractive = 0;
331 if (skip_args + 1 < argc && !strcmp (argv[skip_args + 1], "-batch"))
332 {
333 skip_args += 1;
334 noninteractive = 1;
335 }
336
337 if (
338 #ifndef CANNOT_DUMP
339 ! noninteractive || initialized
340 #else
341 1
342 #endif
343 )
344 {
345 /* Don't catch these signals in batch mode if not initialized.
346 On some machines, this sets static data that would make
347 signal fail to work right when the dumped Emacs is run. */
348 signal (SIGHUP, fatal_error_signal);
349 signal (SIGQUIT, fatal_error_signal);
350 signal (SIGILL, fatal_error_signal);
351 signal (SIGTRAP, fatal_error_signal);
352 signal (SIGIOT, fatal_error_signal);
353 #ifdef SIGEMT
354 signal (SIGEMT, fatal_error_signal);
355 #endif
356 signal (SIGFPE, fatal_error_signal);
357 signal (SIGBUS, fatal_error_signal);
358 signal (SIGSEGV, fatal_error_signal);
359 signal (SIGSYS, fatal_error_signal);
360 signal (SIGTERM, fatal_error_signal);
361 #ifdef SIGXCPU
362 signal (SIGXCPU, fatal_error_signal);
363 #endif
364 #ifdef SIGXFSZ
365 signal (SIGXFSZ, fatal_error_signal);
366 #endif /* SIGXFSZ */
367
368 #ifdef AIX
369 signal (SIGDANGER, fatal_error_signal);
370 signal (20, fatal_error_signal);
371 signal (21, fatal_error_signal);
372 signal (22, fatal_error_signal);
373 signal (23, fatal_error_signal);
374 signal (24, fatal_error_signal);
375 signal (SIGAIO, fatal_error_signal);
376 signal (SIGPTY, fatal_error_signal);
377 signal (SIGIOINT, fatal_error_signal);
378 signal (SIGGRANT, fatal_error_signal);
379 signal (SIGRETRACT, fatal_error_signal);
380 signal (SIGSOUND, fatal_error_signal);
381 signal (SIGMSG, fatal_error_signal);
382 #endif /* AIX */
383 }
384
385 noninteractive1 = noninteractive;
386
387 /* Perform basic initializations (not merely interning symbols) */
388
389 if (!initialized)
390 {
391 init_alloc_once ();
392 init_obarray ();
393 init_eval_once ();
394 init_syntax_once (); /* Create standard syntax table. */
395 /* Must be done before init_buffer */
396 init_casetab_once ();
397 init_buffer_once (); /* Create buffer table and some buffers */
398 init_minibuf_once (); /* Create list of minibuffers */
399 /* Must precede init_window_once */
400 init_window_once (); /* Init the window system */
401 }
402
403 init_alloc ();
404 #ifdef MAINTAIN_ENVIRONMENT
405 init_environ ();
406 #endif
407 init_eval ();
408 init_data ();
409 init_read ();
410
411 init_cmdargs (argc, argv, skip_args); /* Create list Vcommand_line_args */
412 init_buffer (); /* Init default directory of main buffer */
413 if (!noninteractive)
414 {
415 #ifdef VMS
416 init_vms_input ();/* init_display calls get_screen_size, that needs this */
417 #endif /* VMS */
418 init_display (); /* Determine terminal type. init_sys_modes uses results */
419 }
420 init_keyboard (); /* This too must precede init_sys_modes */
421 init_callproc (); /* And this too. */
422 #ifdef VMS
423 init_vmsproc (); /* And this too. */
424 #endif /* VMS */
425 init_sys_modes (); /* Init system terminal modes (RAW or CBREAK, etc.) */
426 init_xdisp ();
427 init_macros ();
428 init_editfns ();
429 #ifdef LISP_FLOAT_TYPE
430 init_floatfns ();
431 #endif
432 #ifdef VMS
433 init_vmsfns ();
434 #endif /* VMS */
435 #ifdef subprocesses
436 init_process ();
437 #endif /* subprocesses */
438
439 /* Intern the names of all standard functions and variables; define standard keys */
440
441 if (!initialized)
442 {
443 /* The basic levels of Lisp must come first */
444 /* And data must come first of all
445 for the sake of symbols like error-message */
446 syms_of_data ();
447 syms_of_alloc ();
448 #ifdef MAINTAIN_ENVIRONMENT
449 syms_of_environ ();
450 #endif /* MAINTAIN_ENVIRONMENT */
451 syms_of_read ();
452 syms_of_print ();
453 syms_of_eval ();
454 syms_of_fns ();
455 #ifdef LISP_FLOAT_TYPE
456 syms_of_floatfns ();
457 #endif
458
459 syms_of_abbrev ();
460 syms_of_buffer ();
461 syms_of_bytecode ();
462 syms_of_callint ();
463 syms_of_casefiddle ();
464 syms_of_casetab ();
465 syms_of_callproc ();
466 syms_of_cmds ();
467 #ifndef NO_DIR_LIBRARY
468 syms_of_dired ();
469 #endif /* not NO_DIR_LIBRARY */
470 syms_of_display ();
471 syms_of_doc ();
472 syms_of_editfns ();
473 syms_of_emacs ();
474 syms_of_fileio ();
475 #ifdef CLASH_DETECTION
476 syms_of_filelock ();
477 #endif /* CLASH_DETECTION */
478 syms_of_indent ();
479 syms_of_keyboard ();
480 syms_of_keymap ();
481 syms_of_macros ();
482 syms_of_marker ();
483 syms_of_minibuf ();
484 syms_of_mocklisp ();
485 #ifdef subprocesses
486 syms_of_process ();
487 #endif /* subprocesses */
488 syms_of_search ();
489 #ifdef MULTI_SCREEN
490 syms_of_screen ();
491 #endif
492 syms_of_syntax ();
493 syms_of_undo ();
494 #ifdef VMS
495 syms_of_vmsproc ();
496 #endif /* VMS */
497 syms_of_window ();
498 syms_of_xdisp ();
499 #ifdef HAVE_X_WINDOWS
500 syms_of_xfns ();
501 #ifdef HAVE_X_MENU
502 syms_of_xmenu ();
503 #endif /* HAVE_X_MENU */
504 #endif /* HAVE_X_WINDOWS */
505
506 #ifdef SYMS_SYSTEM
507 SYMS_SYSTEM;
508 #endif
509
510 #ifdef SYMS_MACHINE
511 SYMS_MACHINE;
512 #endif
513
514 keys_of_casefiddle ();
515 keys_of_cmds ();
516 keys_of_buffer ();
517 keys_of_keyboard ();
518 keys_of_keymap ();
519 keys_of_macros ();
520 keys_of_minibuf ();
521 keys_of_window ();
522 }
523
524 if (!initialized)
525 {
526 /* Handle -l loadup-and-dump, args passed by Makefile. */
527 if (argc > 2 + skip_args && !strcmp (argv[1 + skip_args], "-l"))
528 Vtop_level = Fcons (intern ("load"),
529 Fcons (build_string (argv[2 + skip_args]), Qnil));
530 #ifdef CANNOT_DUMP
531 /* Unless next switch is -nl, load "loadup.el" first thing. */
532 if (!(argc > 1 + skip_args && !strcmp (argv[1 + skip_args], "-nl")))
533 Vtop_level = Fcons (intern ("load"),
534 Fcons (build_string ("loadup.el"), Qnil));
535 #endif /* CANNOT_DUMP */
536 }
537
538 initialized = 1;
539
540 /* Enter editor command loop. This never returns. */
541 Frecursive_edit ();
542 /* NOTREACHED */
543 }
544
545 DEFUN ("kill-emacs", Fkill_emacs, Skill_emacs, 0, 1, "P",
546 "Exit the Emacs job and kill it. Ask for confirmation, without argument.\n\
547 If ARG is an integer, return ARG as the exit program code.\n\
548 If ARG is a string, stuff it as keyboard input.\n\n\
549 The value of `kill-emacs-hook', if not void,\n\
550 is a list of functions (of no args),\n\
551 all of which are called before Emacs is actually killed.")
552 (arg)
553 Lisp_Object arg;
554 {
555 Lisp_Object hook, hook1;
556 int i;
557 struct gcpro gcpro1;
558
559 GCPRO1 (arg);
560
561 if (feof (stdin))
562 arg = Qt;
563
564 if (!NULL (Vrun_hooks) && !noninteractive)
565 call1 (Vrun_hooks, intern ("kill-emacs-hook"));
566
567 #ifdef subprocesses
568 kill_buffer_processes (Qnil);
569 #endif /* subprocesses */
570
571 #ifdef VMS
572 kill_vms_processes ();
573 #endif /* VMS */
574
575 Fdo_auto_save (Qt, Qnil);
576
577 #ifdef CLASH_DETECTION
578 unlock_all_files ();
579 #endif /* CLASH_DETECTION */
580
581 fflush (stdout);
582 reset_sys_modes ();
583
584 #ifdef HAVE_X_WINDOWS
585 if (!noninteractive && EQ (Vwindow_system, intern ("x")))
586 Fx_close_current_connection ();
587 #endif /* HAVE_X_WINDOWS */
588
589 UNGCPRO;
590
591 /* Is it really necessary to do this deassign
592 when we are going to exit anyway? */
593 /* #ifdef VMS
594 stop_vms_input ();
595 #endif */
596 stuff_buffered_input (arg);
597 #ifdef SIGIO
598 /* There is a tendency for a SIGIO signal to arrive within exit,
599 and cause a SIGHUP because the input descriptor is already closed. */
600 unrequest_sigio ();
601 signal (SIGIO, SIG_IGN);
602 #endif
603 exit ((XTYPE (arg) == Lisp_Int) ? XINT (arg)
604 #ifdef VMS
605 : 1
606 #else
607 : 0
608 #endif
609 );
610 /* NOTREACHED */
611 }
612
613 #ifndef CANNOT_DUMP
614 /* Nothing like this can be implemented on an Apollo.
615 What a loss! */
616
617 #ifdef HAVE_SHM
618
619 DEFUN ("dump-emacs-data", Fdump_emacs_data, Sdump_emacs_data, 1, 1, 0,
620 "Dump current state of Emacs into data file FILENAME.\n\
621 This function exists on systems that use HAVE_SHM.")
622 (intoname)
623 Lisp_Object intoname;
624 {
625 extern int my_edata;
626 Lisp_Object tem;
627 extern void malloc_warning ();
628
629 CHECK_STRING (intoname, 0);
630 intoname = Fexpand_file_name (intoname, Qnil);
631
632 tem = Vpurify_flag;
633 Vpurify_flag = Qnil;
634
635 fflush (stdout);
636 /* Tell malloc where start of impure now is */
637 /* Also arrange for warnings when nearly out of space. */
638 #ifndef SYSTEM_MALLOC
639 malloc_init (&my_edata, malloc_warning);
640 #endif
641 map_out_data (XSTRING (intoname)->data);
642
643 Vpurify_flag = tem;
644
645 return Qnil;
646 }
647
648 #else /* not HAVE_SHM */
649
650 DEFUN ("dump-emacs", Fdump_emacs, Sdump_emacs, 2, 2, 0,
651 "Dump current state of Emacs into executable file FILENAME.\n\
652 Take symbols from SYMFILE (presumably the file you executed to run Emacs).\n\
653 This is used in the file `loadup.el' when building Emacs.\n\
654 \n\
655 Bind `command-line-processed' to nil before dumping,\n\
656 if you want the dumped Emacs to process its command line\n\
657 and announce itself normally when it is run.")
658 (intoname, symname)
659 Lisp_Object intoname, symname;
660 {
661 extern int my_edata;
662 Lisp_Object tem;
663 extern void malloc_warning ();
664
665 CHECK_STRING (intoname, 0);
666 intoname = Fexpand_file_name (intoname, Qnil);
667 if (!NULL (symname))
668 {
669 CHECK_STRING (symname, 0);
670 if (XSTRING (symname)->size)
671 symname = Fexpand_file_name (symname, Qnil);
672 }
673
674 tem = Vpurify_flag;
675 Vpurify_flag = Qnil;
676
677 fflush (stdout);
678 #ifdef VMS
679 mapout_data (XSTRING (intoname)->data);
680 #else
681 /* Tell malloc where start of impure now is */
682 /* Also arrange for warnings when nearly out of space. */
683 #ifndef SYSTEM_MALLOC
684 malloc_init (&my_edata, malloc_warning);
685 #endif
686 unexec (XSTRING (intoname)->data,
687 !NULL (symname) ? XSTRING (symname)->data : 0, &my_edata, 0, 0);
688 #endif /* not VMS */
689
690 Vpurify_flag = tem;
691
692 return Qnil;
693 }
694
695 #endif /* not HAVE_SHM */
696
697 #endif /* not CANNOT_DUMP */
698
699 #ifdef VMS
700 #define SEPCHAR ','
701 #else
702 #define SEPCHAR ':'
703 #endif
704
705 Lisp_Object
706 decode_env_path (evarname, defalt)
707 char *evarname, *defalt;
708 {
709 register char *path, *p;
710 extern char *index ();
711
712 Lisp_Object lpath;
713
714 path = (char *) egetenv (evarname);
715 if (!path)
716 path = defalt;
717 lpath = Qnil;
718 while (1)
719 {
720 p = index (path, SEPCHAR);
721 if (!p) p = path + strlen (path);
722 lpath = Fcons (p - path ? make_string (path, p - path) : Qnil,
723 lpath);
724 if (*p)
725 path = p + 1;
726 else
727 break;
728 }
729 return Fnreverse (lpath);
730 }
731
732 syms_of_emacs ()
733 {
734 #ifdef HAVE_SHM
735 defsubr (&Sdump_emacs_data);
736 #else
737 defsubr (&Sdump_emacs);
738 #endif
739
740 defsubr (&Skill_emacs);
741
742 DEFVAR_LISP ("command-line-args", &Vcommand_line_args,
743 "Args passed by shell to Emacs, as a list of strings.");
744
745 DEFVAR_LISP ("system-type", &Vsystem_type,
746 "Value is symbol indicating type of operating system you are using.");
747 Vsystem_type = intern (SYSTEM_TYPE);
748
749 DEFVAR_BOOL ("noninteractive", &noninteractive1,
750 "Non-nil means Emacs is running without interactive terminal.");
751 }