|
|
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.