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