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