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