1: /* Fully extensible Emacs, running on Unix, intended for GNU. 2: Copyright (C) 1985 Richard M. Stallman. 3: 4: This file is part of GNU Emacs. 5: 6: GNU Emacs is distributed in the hope that it will be useful, 7: but WITHOUT ANY WARRANTY. No author or distributor 8: accepts responsibility to anyone for the consequences of using it 9: or for whether it serves any particular purpose or works at all, 10: unless he says so in writing. Refer to the GNU Emacs General Public 11: License for full details. 12: 13: Everyone is granted permission to copy, modify and redistribute 14: GNU Emacs, but only under the conditions described in the 15: GNU Emacs General Public License. A copy of this license is 16: supposed to have been given to you along with GNU Emacs so you 17: can know your rights and responsibilities. It should be in a 18: file named COPYING. Among other things, the copyright notice 19: and this notice must be preserved on all copies. */ 20: 21: 22: #include <signal.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 USG5 34: #include <fcntl.h> 35: #endif 36: 37: #ifdef BSD 38: #include <sys/ioctl.h> 39: #endif 40: 41: #ifndef O_RDWR 42: #define O_RDWR 2 43: #endif 44: 45: #define PRIO_PROCESS 0 46: 47: /* Command line args from shell, as list of strings */ 48: Lisp_Object Vcommand_line_args; 49: 50: /* Set nonzero after Emacs has started up the first time. 51: Prevents reinitialization of the Lisp world and keymaps 52: on subsequent starts. */ 53: int initialized; 54: 55: /* Variable whose value is symbol giving operating system type */ 56: Lisp_Object Vsystem_type; 57: 58: /* Nonzero means running Emacs without interactive terminal. */ 59: 60: int noninteractive; 61: 62: /* Value of Lisp variable `noninteractive'. 63: Normally same as C variable `noninteractive' 64: but nothing terrible happens if user sets this one. */ 65: 66: int noninteractive1; 67: 68: /* Signal code for the fatal signal that was received */ 69: int fatal_error_code; 70: 71: /* Nonzero if handling a fatal error already */ 72: int fatal_error_in_progress; 73: 74: /* Handle bus errors, illegal instruction, etc. */ 75: fatal_error_signal (sig) 76: int sig; 77: { 78: #ifdef BSD 79: int tpgrp; 80: #endif /* BSD */ 81: 82: fatal_error_code = sig; 83: signal (sig, SIG_DFL); 84: 85: /* If fatal error occurs in code below, avoid infinite recursion. */ 86: if (fatal_error_in_progress) 87: kill (getpid (), fatal_error_code); 88: 89: fatal_error_in_progress = 1; 90: 91: /* If we are controlling the terminal, reset terminal modes */ 92: #ifdef BSD 93: if (ioctl(0, TIOCGPGRP, &tpgrp) == 0 94: && tpgrp == getpgrp (0)) 95: #endif /* BSD */ 96: { 97: reset_sys_modes (); 98: if (sig != SIGTERM) 99: fprintf (stderr, "Fatal error."); 100: } 101: 102: /* Clean up */ 103: #ifdef subprocesses 104: kill_buffer_processes (Qnil); 105: #endif 106: Fdo_auto_save (Qt); 107: 108: #ifdef CLASH_DETECTION 109: unlock_all_files (); 110: #endif /* CLASH_DETECTION */ 111: 112: /* Signal the same code; this time it will really be fatal. */ 113: kill (getpid (), fatal_error_code); 114: } 115: 116: /* Code for dealing with Lisp access to the Unix command line */ 117: 118: static 119: init_cmdargs (argc, argv, skip_args) 120: int argc; 121: char **argv; 122: int skip_args; 123: { 124: register int i; 125: 126: Vcommand_line_args = Qnil; 127: 128: for (i = argc - 1; i >= 0; i--) 129: { 130: if (i == 0 || i > skip_args) 131: Vcommand_line_args 132: = Fcons (build_string (argv[i]), Vcommand_line_args); 133: } 134: } 135: 136: /* ARGSUSED */ 137: main (argc, argv, envp) 138: int argc; 139: char **argv; 140: char **envp; 141: { 142: int skip_args = 0; 143: extern int errno; 144: clearerr (stdin); 145: 146: #ifdef APOLLO /* Reserve memory space for sbrk to get */ 147: set_sbrk_size (4000000); 148: #endif /* APOLLO */ 149: 150: signal (SIGHUP, fatal_error_signal); 151: signal (SIGQUIT, fatal_error_signal); 152: signal (SIGILL, fatal_error_signal); 153: signal (SIGTRAP, fatal_error_signal); 154: signal (SIGIOT, fatal_error_signal); 155: signal (SIGEMT, fatal_error_signal); 156: signal (SIGFPE, fatal_error_signal); 157: signal (SIGBUS, fatal_error_signal); 158: signal (SIGSEGV, fatal_error_signal); 159: signal (SIGSYS, fatal_error_signal); 160: signal (SIGTERM, fatal_error_signal); 161: #ifdef SIGXCPU 162: signal (SIGXCPU, fatal_error_signal); 163: #endif 164: #ifdef SIGXFSZ 165: signal (SIGXFSZ, fatal_error_signal); 166: #endif SIGXFSZ 167: 168: #ifdef HIGHPRI 169: setpriority(PRIO_PROCESS, getpid(), HIGHPRI); 170: setuid(getuid()); 171: #endif HIGHPRI 172: 173: /* Handle the -t switch, which specifies filename to use as terminal */ 174: if (2 < argc && !strcmp (argv[1], "-t")) 175: { 176: skip_args = 2; 177: close (0); 178: close (1); 179: open(argv[2], O_RDWR, 2 ); 180: dup (0); 181: fprintf (stderr, "Using %s\n", argv[2]); 182: } 183: 184: /* Handle the -batch switch, which means don't do interactive display. */ 185: noninteractive = 0; 186: if (1 < argc && !strcmp (argv[1], "-batch")) 187: { 188: skip_args = 1; 189: noninteractive = 1; 190: } 191: 192: noninteractive1 = noninteractive; 193: 194: /* Perform basic initializations (not merely interning symbols) */ 195: 196: if (!initialized) 197: { 198: init_alloc_once (); 199: init_obarray (); 200: init_eval_once (); 201: init_syntax_once (); /* Create standard syntax table. */ 202: /* Must be done before init_buffer */ 203: init_buffer_once (); /* Create buffer table and some buffers */ 204: init_minibuf_once (); /* Create list of minibuffers */ 205: /* Must precede init_window_once */ 206: init_window_once (); /* Init the window system */ 207: } 208: 209: init_alloc (); 210: init_eval (); 211: init_data (); 212: init_read (); 213: 214: init_cmdargs (argc, argv, skip_args); /* Create list Vcommand_line_args */ 215: init_buffer (); /* Init default directory of main buffer */ 216: if (!noninteractive) 217: init_display (); /* Determine terminal type. init_sys_modes uses results */ 218: init_keyboard (); /* This too must precede init_sys_modes */ 219: init_sys_modes (); /* Init system terminal modes (RAW or CBREAK, etc.) */ 220: init_xdisp (); 221: init_macros (); 222: init_editfns (); 223: init_callproc (); 224: #ifdef subprocesses 225: init_process (); 226: #endif subprocesses 227: 228: /* Intern the names of all standard functions and variables; define standard keys */ 229: 230: if (!initialized) 231: { 232: /* The basic levels of Lisp must come first */ 233: /* And data must come first of all 234: for the sake of symbols like error-message */ 235: syms_of_data (); 236: syms_of_alloc (); 237: syms_of_read (); 238: syms_of_print (); 239: syms_of_eval (); 240: syms_of_fns (); 241: 242: syms_of_abbrev (); 243: syms_of_buffer (); 244: syms_of_bytecode (); 245: syms_of_callint (); 246: syms_of_casefiddle (); 247: syms_of_callproc (); 248: syms_of_cmds (); 249: #ifndef NO_DIR_LIBRARY 250: syms_of_dired (); 251: #endif /* not NO_DIR_LIBRARY */ 252: syms_of_display (); 253: syms_of_doc (); 254: syms_of_editfns (); 255: syms_of_emacs (); 256: syms_of_fileio (); 257: #ifdef CLASH_DETECTION 258: syms_of_filelock (); 259: #endif /* CLASH_DETECTION */ 260: syms_of_indent (); 261: syms_of_keyboard (); 262: syms_of_keymap (); 263: syms_of_macros (); 264: syms_of_marker (); 265: syms_of_minibuf (); 266: syms_of_mocklisp (); 267: #ifdef subprocesses 268: syms_of_process (); 269: #endif /* subprocesses */ 270: syms_of_search (); 271: syms_of_syntax (); 272: syms_of_undo (); 273: syms_of_window (); 274: syms_of_xdisp (); 275: #ifdef HAVE_X_WINDOWS 276: syms_of_xfns (); 277: #endif /* HAVE_X_WINDOWS */ 278: 279: keys_of_casefiddle (); 280: keys_of_cmds (); 281: keys_of_buffer (); 282: keys_of_keyboard (); 283: keys_of_keymap (); 284: keys_of_macros (); 285: keys_of_minibuf (); 286: keys_of_window (); 287: } 288: 289: if (!initialized) 290: { 291: /* Handle -l loadup-and-dump, args passed by Makefile. */ 292: if (argc > 2 + skip_args && !strcmp (argv[1 + skip_args], "-l")) 293: Vtop_level = Fcons (intern ("load"), 294: Fcons (build_string (argv[2 + skip_args]), Qnil)); 295: #ifdef CANNOT_DUMP 296: /* Unless next switch is -nl, load "loadup.el" first thing. */ 297: if (!(argc > 1 + skip_args && !strcmp (argv[1 + skip_args], "-nl"))) 298: Vtop_level = Fcons (intern ("load"), 299: Fcons (build_string ("loadup.el"), Qnil)); 300: #endif /* CANNOT_DUMP */ 301: } 302: 303: initialized = 1; 304: 305: /* Enter editor command loop. This never returns. */ 306: Frecursive_edit (); 307: /* NOTREACHED */ 308: } 309: 310: DEFUN ("kill-emacs", Fkill_emacs, Skill_emacs, 0, 1, "P", 311: "Exit the Emacs job and kill it. ARG means no query.\n\ 312: If emacs is running noninteractively and ARG is an integer,\n\ 313: return ARG as the exit program code.") 314: (arg) 315: Lisp_Object arg; 316: { 317: Lisp_Object answer; 318: int i; 319: 320: if (feof (stdin)) 321: arg = Qt; 322: if (!noninteractive && NULL (arg)) 323: { 324: if ((i = ModExist()) 325: && (answer = Fyes_or_no_p (format1 ( 326: "%d modified buffer%s exist%s, do you really want to exit? ", 327: i, i == 1 ? "" : "s", 328: i == 1 ? "s" : "")), 329: NULL (answer))) 330: return Qnil; 331: 332: #ifdef subprocesses 333: if (count_active_processes() 334: && (answer = Fyes_or_no_p (format1 ( 335: "Subprocesses are executing; kill them and exit? ")), 336: NULL (answer))) 337: return Qnil; 338: #endif /* subprocesses */ 339: } 340: 341: #ifdef subprocesses 342: kill_buffer_processes (Qnil); 343: #endif /* subprocesses */ 344: 345: Fdo_auto_save (Qt); 346: 347: #ifdef CLASH_DETECTION 348: unlock_all_files (); 349: #endif /* CLASH_DETECTION */ 350: 351: fflush (stdout); 352: reset_sys_modes (); 353: stuff_buffered_input (arg); 354: exit ((XTYPE (arg) == Lisp_Int) ? XINT (arg) : 0); 355: /* NOTREACHED */ 356: } 357: 358: #ifndef CANNOT_DUMP 359: /* Nothing like this can be implemented on an Apollo. 360: What a loss! */ 361: 362: DEFUN ("dump-emacs", Fdump_emacs, Sdump_emacs, 2, 2, 0, 363: "Dump current state of Emacs into executable file FILENAME.\n\ 364: Take symbols from SYMFILE (presumably the file you executed to run Emacs).") 365: (intoname, symname) 366: Lisp_Object intoname, symname; 367: { 368: register unsigned char *a_name = 0; 369: extern int my_edata; 370: Lisp_Object tem; 371: extern _start (); 372: 373: CHECK_STRING (intoname, 0); 374: intoname = Fexpand_file_name (intoname, Qnil); 375: if (!NULL (symname)) 376: { 377: CHECK_STRING (symname, 0); 378: if (XSTRING (symname)->size) 379: { 380: symname = Fexpand_file_name (symname, Qnil); 381: a_name = XSTRING (symname)->data; 382: } 383: } 384: 385: tem = Vpurify_flag; 386: Vpurify_flag = Qnil; 387: 388: fflush (stdout); 389: malloc_init (&my_edata); /* Tell malloc where start of impure now is */ 390: unexec (XSTRING (intoname)->data, a_name, &my_edata, 0, _start); 391: 392: Vpurify_flag = tem; 393: 394: return Qnil; 395: } 396: 397: #endif /* not CANNOT_DUMP */ 398: 399: Lisp_Object 400: decode_env_path (evarname, defalt) 401: char *evarname, *defalt; 402: { 403: register char *path, *p; 404: extern char *index (); 405: 406: Lisp_Object lpath; 407: 408: path = (char *) getenv (evarname); 409: if (!path) 410: path = defalt; 411: lpath = Qnil; 412: while (1) 413: { 414: p = index (path, ':'); 415: if (!p) p = path + strlen (path); 416: lpath = Fcons (p - path ? make_string (path, p - path) : Qnil, 417: lpath); 418: if (*p) 419: path = p + 1; 420: else 421: break; 422: } 423: return Fnreverse (lpath); 424: } 425: 426: syms_of_emacs () 427: { 428: #ifndef CANNOT_DUMP 429: defsubr (&Sdump_emacs); 430: #endif /* not CANNOT_DUMP */ 431: 432: defsubr (&Skill_emacs); 433: 434: DefLispVar ("command-line-args", &Vcommand_line_args, 435: "Args passed by shell to Emacs, as a list of strings."); 436: 437: DefLispVar ("system-type", &Vsystem_type, 438: "Symbol indicating type of operating system you are using."); 439: Vsystem_type = intern (SYSTEM_TYPE); 440: 441: DefBoolVar ("noninteractive", &noninteractive1, 442: "Non-nil means Emacs is running without interactive terminal."); 443: }