home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / lucid / lemacs-19.6 / src / emacs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-14  |  30.6 KB  |  1,244 lines

  1. /* Fully extensible Emacs, running on Unix, intended for GNU.
  2.    Copyright (C) 1992, 1993 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 2, 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. #include "config.h"
  21. #include "lisp.h"
  22.  
  23. #include <signal.h>
  24. #include <sys/signal.h>
  25. #include <errno.h>
  26.  
  27. #include <stdio.h>
  28.  
  29. #include <sys/types.h>
  30. #include <sys/file.h>
  31. #include <sys/stat.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. #ifdef RUNNABLE_TEMACS
  52. #include <setjmp.h>
  53. #endif
  54.  
  55. #include "commands.h"
  56.  
  57. #ifndef O_RDWR
  58. #define O_RDWR 2
  59. #endif
  60.  
  61. #define PRIO_PROCESS 0
  62.  
  63. /* Command line args from shell, as list of strings */
  64. Lisp_Object Vcommand_line_args;
  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. extern Lisp_Object Vtop_level;
  75.  
  76. /* Variable holding the name used to invoke emacs, and the full path
  77.    used to get to the actual exec file. */
  78. Lisp_Object Vinvocation_name, Vexecution_path;
  79.  
  80. /* If non-zero, emacs should not attempt to use an window-specific code,
  81.    but instead should use the virtual terminal under which it was started */
  82. int inhibit_window_system;
  83.  
  84. /* An address near the bottom of the stack.
  85.    Tells GC how to save a copy of the stack.  */
  86. char *stack_bottom;
  87.  
  88. #ifdef HAVE_X_WINDOWS
  89. extern Lisp_Object Vwindow_system;
  90. #endif /* HAVE_X_WINDOWS */
  91.  
  92. #ifdef USG_SHARED_LIBRARIES
  93. /* If nonzero, this is the place to put the end of the writable segment
  94.    at startup.  */
  95.  
  96. unsigned int bss_end = 0;
  97. #endif
  98.  
  99. /* Nonzero means running Emacs without interactive terminal.  */
  100.  
  101. int noninteractive;
  102.  
  103. /* Value of Lisp variable `noninteractive'.
  104.    Normally same as C variable `noninteractive'
  105.    but nothing terrible happens if user sets this one.  */
  106.  
  107. int noninteractive1;
  108.  
  109. /* Signal code for the fatal signal that was received */
  110. static int fatal_error_code;
  111.  
  112. /* Nonzero if handling a fatal error already */
  113. static int fatal_error_in_progress;
  114.  
  115. extern void reset_sys_modes (void);
  116.  
  117. extern void report_pure_usage (void);
  118.  
  119. #ifdef subprocesses
  120. extern void kill_buffer_processes (Lisp_Object buffer);
  121. #endif
  122.  
  123. /* Handle bus errors, illegal instruction, etc. */
  124. SIGTYPE
  125. fatal_error_signal (sig)
  126.      int sig;
  127. {
  128. #ifdef BSD
  129.   int tpgrp;
  130. #endif /* BSD */
  131.  
  132.   fatal_error_code = sig;
  133.   signal (sig, SIG_DFL);
  134.  
  135.   /* If fatal error occurs in code below, avoid infinite recursion.  */
  136.   if (fatal_error_in_progress)
  137.     kill (getpid (), fatal_error_code);
  138.  
  139.   fatal_error_in_progress = 1;
  140.  
  141.   /* If we are controlling the terminal, reset terminal modes */
  142. #ifdef BSD
  143.   if (ioctl(0, TIOCGPGRP, &tpgrp) == 0
  144.       && tpgrp == getpgrp (0))
  145. #endif /* BSD */
  146.     {
  147.       reset_sys_modes ();
  148.       if (sig != SIGTERM)
  149.     fprintf (stderr, "Fatal error (%d).", sig);
  150.     }
  151.  
  152.   /* Clean up */
  153. #ifdef subprocesses
  154.   kill_buffer_processes (Qnil);
  155. #endif
  156.   Fdo_auto_save (Qt);
  157.  
  158. #ifdef CLASH_DETECTION
  159.   unlock_all_files ();
  160. #endif /* CLASH_DETECTION */
  161.  
  162. #ifdef VMS
  163.   kill_vms_processes ();
  164.   LIB$STOP (SS$_ABORT);
  165. #else
  166.   /* Signal the same code; this time it will really be fatal.  */
  167.   kill (getpid (), fatal_error_code);
  168. #endif /* not VMS */
  169. }
  170.  
  171. /* Code for dealing with Lisp access to the Unix command line */
  172.  
  173. static void
  174. init_cmdargs (argc, argv, skip_args)
  175.      int argc;
  176.      char **argv;
  177.      int skip_args;
  178. {
  179.   register int i;
  180.  
  181.   Vcommand_line_args = Qnil;
  182.  
  183.   for (i = argc - 1; i >= 0; i--)
  184.     {
  185.       if (i == 0 || i > skip_args)
  186.     Vcommand_line_args
  187.       = Fcons (build_string (argv[i]), Vcommand_line_args);
  188.     }
  189. }
  190.  
  191. /* DOT_FOUND_IN_SEARCH becomes non-zero when find_user_command ()
  192.    encounters a `.' as the directory pathname while scanning the
  193.    list of possible pathnames; i.e., if `.' comes before the directory
  194.    containing the file of interest. */
  195. static int dot_found_in_search;
  196.  
  197. #define savestring(x) ((char *)(strcpy ((char *)xmalloc (1 + strlen (x)), (x))))
  198.  
  199. #define u_mode_bits(x) (((x) & 0000700) >> 6)
  200. #define g_mode_bits(x) (((x) & 0000070) >> 3)
  201. #define o_mode_bits(x) (((x) & 0000007) >> 0)
  202. #define X_BIT(x) (x & 1)
  203.  
  204. /* Non-zero if the last call to executable_file () found
  205.    the file, but stated that it wasn't executable. */
  206. static int file_exists_p;
  207.  
  208. static int
  209. group_member (gid)
  210.      int gid;
  211. {
  212.   return ((gid == getgid ()) || (gid == getegid ()));
  213. }
  214.  
  215. /* Return non-zero if FILE is an executable file, otherwise 0.
  216.    Note that this function is the definition of what an
  217.    executable file is; do not change this unless YOU know
  218.    what an executable file is. */
  219. static int
  220. executable_file (file)
  221.      char *file;
  222. {
  223.   struct stat finfo;
  224.   static int user_id = -1;
  225.  
  226.   /* If the file doesn't exist, or is a directory, then we are
  227.      not interested. */
  228.   file_exists_p = !stat (file, &finfo);
  229.  
  230. #ifndef S_ISDIR
  231. #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
  232. #endif
  233.  
  234.   if (!file_exists_p || S_ISDIR (finfo.st_mode))
  235.     return (0);
  236.  
  237.   /* By definition, the only other criteria is that the file has
  238.      an execute bit set that we can use. */
  239.   if (user_id == -1)
  240.     user_id = geteuid ();
  241.  
  242.   /* Root only requires execute permission for any of owner, group or
  243.      others to be able to exec a file. */
  244.   if (user_id == 0)
  245.     {
  246.       int bits;
  247.  
  248.       bits = (u_mode_bits (finfo.st_mode) |
  249.           g_mode_bits (finfo.st_mode) |
  250.           o_mode_bits (finfo.st_mode));
  251.  
  252.       return (X_BIT (bits));
  253.     }
  254.  
  255.   /* If we are the owner of the file, the owner execute bit applies. */
  256.   if (user_id == finfo.st_uid)
  257.     return (X_BIT (u_mode_bits (finfo.st_mode)));
  258.  
  259.   /* If we are in the owning group, the group permissions apply. */
  260.   if (group_member (finfo.st_gid))
  261.     return (X_BIT (g_mode_bits (finfo.st_mode)));
  262.  
  263.   /* If `others' have execute permission to the file, then so do we,
  264.      since we are also `others'. */
  265.   return (X_BIT (o_mode_bits (finfo.st_mode)));
  266. }
  267.  
  268. /* Return 1 if PATH1 and PATH2 are the same file.  This is kind of
  269.    expensive.   If non-NULL STP1 and STP2 point to stat structures
  270.    corresponding to PATH1 and PATH2, respectively. */
  271. static int
  272. same_file (path1, path2, stp1, stp2)
  273.      char *path1, *path2;
  274.      struct stat *stp1, *stp2;
  275. {
  276.   struct stat st1, st2;
  277.  
  278.   if (stp1 == 0)
  279.     {
  280.       if (stat (path1, &st1) != 0)
  281.     return (0);
  282.       stp1 = &st1;
  283.     }
  284.  
  285.   if (stp2 == 0)
  286.     {
  287.       if (stat (path2, &st2) != 0)
  288.     return (0);
  289.       stp2 = &st2;
  290.     }
  291.  
  292.   return ((stp1->st_dev == stp2->st_dev) && (stp1->st_ino == stp2->st_ino));
  293. }
  294.  
  295. /* Return 1 if STRING is an absolute program name; it is absolute if it
  296.    contains any slashes.  This is used to decide whether or not to look
  297.    up through $PATH. */
  298. static int
  299. absolute_program (string)
  300.      char *string;
  301. {
  302.   return ((char *)strchr (string, '/') != 0);
  303. }
  304.  
  305. /* Given a string containing units of information separated by colons,
  306.    return the next one pointed to by INDEX, or NULL if there are no more.
  307.    Advance INDEX to the character after the colon. */
  308. static char *
  309. extract_colon_unit (string, index)
  310.      char *string;
  311.      int *index;
  312. {
  313.   int i, start;
  314.  
  315.   i = *index;
  316.  
  317.   if (!string || (i >= strlen (string)))
  318.     return 0;
  319.  
  320.   /*
  321.    * Each call to this routine leaves the index pointing at a colon if there
  322.    * is more to the path.  If i is > 0, then increment past the `:'.  (If i
  323.    * is 0, then the path has a leading colon.  If this is not done, the
  324.    * second call to this routine will always return NULL, which will be
  325.    * translated to  `.', even if `.' is not in the path.  Trailing colons
  326.    * are handled OK by the `else' part of the if statement; it returns a null
  327.    * string for the last component of a path with a trailing colon, and the
  328.    * routines that call this will translate that to `.'.
  329.    */
  330.  
  331.   if (i && string[i] == ':')
  332.     i++;
  333.  
  334.   start = i;
  335.  
  336.   while (string[i] && string[i] != ':') i++;
  337.  
  338.   *index = i;
  339.  
  340.   if (i == start)
  341.     {
  342.       if (!string[i])
  343.     return 0;
  344.  
  345.       (*index)++;
  346.  
  347.       return (savestring (""));
  348.     }
  349.   else
  350.     {
  351.       char *value;
  352.  
  353.       value = (char *)xmalloc (1 + (i - start));
  354.       strncpy (value, &string[start], (i - start));
  355.       value [i - start] = '\0';
  356.  
  357.       return (value);
  358.     }
  359. }
  360.  
  361. static char *
  362. find_executable_name ()
  363. {
  364.   extern char *getenv ();
  365.   struct Lisp_String *lname = XSTRING (Fcar (Vcommand_line_args));
  366.   int name_len = lname->size;
  367.   char *path_list = getenv ("PATH");
  368.   int must_be_executable = 1;
  369.   extern int file_exists_p;
  370.   char *full_path;
  371.   char *path;
  372.   int path_index = 0;
  373.   struct stat dot_stat_buf;
  374.   char *name = (char *) alloca (name_len + 1);
  375.   memcpy (name, lname->data, name_len);
  376.   name[name_len] = 0;
  377.  
  378.   /* We haven't started looking, so we certainly haven't seen
  379.      a `.' as the directory path yet. */
  380.   dot_found_in_search = 0;
  381.  
  382.   if (absolute_program (name))
  383.     {
  384.       full_path = (char *)xmalloc (1 + name_len);
  385.       strcpy (full_path, name);
  386.  
  387.       if (executable_file (full_path) || file_exists_p)
  388.     {
  389.       return (full_path);
  390.     }
  391.       else
  392.     {
  393.       xfree (full_path);
  394.       return 0;
  395.     }
  396.     }
  397.  
  398.   stat (".", &dot_stat_buf);   /* should set in get_working_directory */
  399.  
  400.   while (path_list && path_list[path_index])
  401.     {
  402.       path = extract_colon_unit (path_list, &path_index);
  403.       if (!path || !*path)
  404.     {
  405.       if (path)
  406.         xfree (path);
  407.       path = savestring ("."); /* by definition. */
  408.     }
  409.  
  410.       /* Remember the location of "." in the path, in all its forms (as long as
  411.      they begin with a `.', e.g. `./.') */
  412.       if ((*path == '.') && same_file (".", path, &dot_stat_buf, (struct stat *) 0))
  413.     dot_found_in_search = 1;
  414.  
  415.       full_path = (char *)xmalloc (2 + strlen (path) + name_len);
  416.       sprintf (full_path, "%s/%s", path, name);
  417.       xfree (path);
  418.  
  419.       if (executable_file (full_path) ||
  420.       (!must_be_executable && file_exists_p))
  421.     {
  422.       return (full_path);
  423.     }
  424.       else
  425.     xfree (full_path);
  426.     }
  427.  
  428.   return 0;
  429. }
  430.  
  431. #ifdef NeXT
  432. int malloc_cookie;
  433. #endif
  434.  
  435. extern void init_alloc_once (void);
  436. extern void init_obarray (void);
  437. extern void init_eval_once (void);
  438. extern void init_syntax_once (void);
  439. extern void init_casetab_once (void);
  440. extern void init_buffer_once (void);
  441. extern void init_minibuf_once (void);
  442. extern void init_window_once (void);
  443.  
  444. extern void init_alloc (void);
  445. #ifdef MAINTAIN_ENVIRONMENT
  446. extern void init_environ (void);
  447. #endif
  448. extern void init_eval (void);
  449. extern void init_data (void);
  450. extern void init_lread (void);
  451. extern void init_cmdargs ();
  452. extern void init_buffer (void);
  453. #ifdef VMS
  454. extern void init_vms_input (void);
  455. #endif /* VMS */
  456. extern void init_display (void);
  457. extern void init_keyboard (void);
  458. extern void init_callproc (void);
  459. #ifdef VMS
  460. extern void init_vmsproc (void);
  461. #endif /* VMS */
  462. extern void init_sys_modes (void);
  463. extern void init_xdisp (void);
  464. extern void init_macros (void);
  465. extern void init_editfns (void);
  466. #ifdef LISP_FLOAT_TYPE
  467. extern void init_floatfns (void);
  468. #endif
  469. #ifdef VMS
  470. extern void init_vmsfns (void);
  471. #endif /* VMS */
  472. #ifdef subprocesses
  473. extern void init_process (void);
  474. #endif /* subprocesses */
  475.  
  476. extern void syms_of_data (void);
  477. extern void syms_of_alloc (void);
  478. #ifdef MAINTAIN_ENVIRONMENT
  479. extern void syms_of_environ (void);
  480. #endif /* MAINTAIN_ENVIRONMENT */
  481. extern void syms_of_lread (void);
  482. extern void syms_of_print (void);
  483. extern void syms_of_eval (void);
  484. extern void syms_of_fns (void);
  485. #ifdef LISP_FLOAT_TYPE
  486. extern void syms_of_floatfns (void);
  487. #endif
  488. extern void syms_of_elhash (void);
  489. extern void syms_of_abbrev (void);
  490. extern void syms_of_buffer (void);
  491. extern void syms_of_bytecode (void);
  492. extern void syms_of_callint (void);
  493. extern void syms_of_casefiddle (void);
  494. extern void syms_of_casetab (void);
  495. extern void syms_of_callproc (void);
  496. extern void syms_of_cmds (void);
  497. #ifndef NO_DIR_LIBRARY
  498. extern void syms_of_dired (void);
  499. #endif /* not NO_DIR_LIBRARY */
  500. extern void syms_of_display (void);
  501. extern void syms_of_doc (void);
  502. extern void syms_of_editfns (void);
  503. extern void syms_of_fileio (void);
  504. #ifdef CLASH_DETECTION
  505. extern void syms_of_filelock (void);
  506. #endif /* CLASH_DETECTION */
  507. extern void syms_of_indent (void);
  508. extern void syms_of_keyboard (void);
  509. extern void syms_of_keymap (void);
  510. extern void syms_of_macros (void);
  511. extern void syms_of_marker (void);
  512. extern void syms_of_minibuf (void);
  513. extern void syms_of_mocklisp (void);
  514. #ifdef subprocesses
  515. extern void syms_of_process (void);
  516. #endif /* subprocesses */
  517. extern void syms_of_search (void);
  518. #ifdef MULTI_SCREEN
  519. extern void syms_of_screen (void);
  520. #endif
  521. extern void syms_of_extents (void);
  522. extern void syms_of_syntax (void);
  523. extern void syms_of_undo (void);
  524. #ifdef VMS
  525. extern void syms_of_vmsproc (void);
  526. #endif /* VMS */
  527. extern void syms_of_window (void);
  528. extern void syms_of_xdisp (void);
  529. #ifdef HAVE_X_WINDOWS
  530. extern void syms_of_xfns (void);
  531. extern void syms_of_xselect (void);
  532. extern void syms_of_menubar (void);
  533. #endif /* HAVE_X_WINDOWS */
  534. extern void syms_of_faces (void);
  535. extern void syms_of_events (void);
  536. extern void syms_of_event_alloc (void);
  537. extern void syms_of_event_stream (void);
  538. extern void syms_of_font_lock (void);
  539. #ifdef ENERGIZE
  540. extern void syms_of_editorside (void);
  541. #endif
  542. #ifdef EMACS_BTL
  543. extern void syms_of_cadillac_btl_emacs (void);
  544. #endif
  545. extern void keys_of_keymap (void);
  546.  
  547. static void syms_of_emacs (void);
  548.  
  549. #ifndef SYSTEM_MALLOC
  550. extern void malloc_init ();
  551. #endif
  552.  
  553. extern void malloc_warning ();
  554.  
  555. #ifdef BSD
  556. extern pid_t setpgrp ();
  557. #endif
  558.  
  559. #ifdef RUN_TIME_REMAP
  560. extern int run_time_remap ();
  561. #endif
  562.  
  563. /* ARGSUSED */
  564. #ifdef RUNNABLE_TEMACS
  565. static int main_1 (argc, argv, envp)
  566. #else
  567. int main (argc, argv, envp)
  568. #endif
  569.      int argc;
  570.      char **argv;
  571.      char **envp;
  572. {
  573.   char stack_bottom_variable;
  574.   int skip_args = 0;
  575.   extern int errno;
  576.   extern sys_nerr;
  577.   extern char *sys_errlist[];
  578.  
  579. #ifdef NeXT
  580.   /* this helps out unexNeXT.c */
  581.   if (initialized)
  582.     if (malloc_jumpstart (malloc_cookie) != 0)
  583.       printf ("malloc jumpstart failed!\n");
  584. #endif
  585.  
  586. #ifdef FREE_CHECKING
  587.   init_free_hook ();
  588. #endif
  589.  
  590. #ifdef VMS
  591. #ifdef LINK_CRTL_SHARE
  592. #ifdef SHAREABLE_LIB_BUG
  593.   extern noshare char **environ;
  594. #endif /* SHAREABLE_LIB_BUG */
  595. #endif /* LINK_CRTL_SHARE */
  596.  
  597.   /* If -map specified, map the data file in */
  598.   if (argc > 2 && ! strcmp (argv[1], "-map"))
  599.     {
  600.       skip_args = 2;
  601.       mapin_data (argv[2]);
  602.     }
  603.  
  604. #ifdef LINK_CRTL_SHARE
  605. #ifdef SHAREABLE_LIB_BUG
  606.   /* Bletcherous shared libraries! */
  607.   if (!stdin)
  608.     stdin = fdopen (0, "r");
  609.   if (!stdout)
  610.     stdout = fdopen (1, "w");
  611.   if (!stderr)
  612.     stderr = fdopen (2, "w");
  613.   if (!environ)
  614.     environ = envp;
  615. #endif /* SHAREABLE_LIB_BUG */
  616. #endif /* LINK_CRTL_SHARE */
  617. #endif /* VMS */
  618.  
  619.   /* Record (approximately) where the stack begins.  */
  620.   stack_bottom = &stack_bottom_variable;
  621.  
  622. #ifdef RUN_TIME_REMAP
  623.   if (initialized)
  624.     run_time_remap (argv[0]);
  625. #endif
  626.  
  627. #ifdef USG_SHARED_LIBRARIES
  628.   if (bss_end)
  629.     brk (bss_end);
  630. #endif
  631.  
  632.   clearerr (stdin);
  633. #ifdef BSD
  634.   setpgrp (0, getpid ());
  635. #endif
  636.  
  637. #ifdef APOLLO
  638. #ifndef APOLLO_SR10
  639.   /* If USE_DOMAIN_ACLS environment variable exists,
  640.      use ACLs rather than UNIX modes. */
  641.   if (egetenv ("USE_DOMAIN_ACLS"))
  642.     default_acl (USE_DEFACL);
  643. #endif
  644. #endif /* APOLLO */
  645.  
  646. #ifndef SYSTEM_MALLOC
  647.   if (! initialized)
  648.     malloc_init (0, malloc_warning);
  649. #endif    /* not SYSTEM_MALLOC */
  650.  
  651. #ifdef HIGHPRI
  652.   setpriority (PRIO_PROCESS, getpid (), HIGHPRI);
  653.   setuid (getuid ());
  654. #endif /* HIGHPRI */
  655.  
  656. #ifdef BSD
  657.   /* interrupt_input has trouble if we aren't in a separate process group.  */
  658.   setpgrp (getpid (), getpid ());
  659. #endif
  660.  
  661.   inhibit_window_system = 0;
  662.  
  663. /* Handle the -t switch, which specifies filename to use as terminal */
  664.   if (skip_args + 2 < argc && !strcmp (argv[skip_args + 1], "-t"))
  665.     {
  666.       int result;
  667.       char *name, *ttyname ();
  668.  
  669.       skip_args += 2;
  670.       close (0);
  671.       close (1);
  672.       result = open (argv[skip_args], O_RDWR, 2 );
  673.       if (result < 0)
  674.     {
  675.       char *errstring;
  676.  
  677.       if (errno >= 0 && errno < sys_nerr)
  678.         errstring = sys_errlist[errno];
  679.       else
  680.         errstring = "undocumented error code";
  681.       fprintf (stderr, "emacs: %s: %s\n", argv[skip_args], errstring);
  682.       exit (1);
  683.     }
  684.       dup (0);
  685.       if (! isatty (0))
  686.     {
  687.       fprintf (stderr, "emacs: %s: not a tty\n", argv[skip_args]);
  688.       exit (1);
  689.     }
  690.  
  691.       name = ttyname (0);
  692.       fprintf (stderr, "Using %s\n", name);
  693. #if 0
  694.       fprintf (stderr, "Using %s\n", argv[skip_args]);
  695. #endif
  696. #ifdef HAVE_X_WINDOWS
  697.       inhibit_window_system = 1;    /* -t => -nw */
  698. #endif
  699.     }
  700.  
  701.   if (skip_args + 1 < argc
  702.       && (!strcmp (argv[skip_args + 1], "-nw")))
  703.     {
  704.       skip_args += 1;
  705.       inhibit_window_system = 1;
  706.     }
  707.  
  708.   /* Handle the -batch switch, which means don't do interactive display.  */
  709.   noninteractive = 0;
  710.   if (skip_args + 1 < argc && !strcmp (argv[skip_args + 1], "-batch"))
  711.     {
  712.       skip_args += 1;
  713.       noninteractive = 1;
  714.     }
  715.  
  716.   /* Partially handle the -version and -help switches: they imply -batch,
  717.      but are not removed from the list.
  718.    */
  719.   if (skip_args + 1 < argc &&
  720.       (!strcmp (argv[skip_args + 1], "-version") ||
  721.        !strcmp (argv[skip_args + 1], "-help")))
  722.     noninteractive = 1;
  723.  
  724.   if (
  725. #ifndef CANNOT_DUMP
  726.       ! noninteractive || initialized
  727. #else
  728.       1
  729. #endif
  730.       )
  731.     {
  732.       /* Don't catch these signals in batch mode if not initialized.
  733.      On some machines, this sets static data that would make
  734.      signal fail to work right when the dumped Emacs is run.  */
  735.       signal (SIGHUP, fatal_error_signal);
  736.       signal (SIGQUIT, fatal_error_signal);
  737.       signal (SIGILL, fatal_error_signal);
  738.       signal (SIGTRAP, fatal_error_signal);
  739.       signal (SIGIOT, fatal_error_signal);
  740. #ifdef SIGEMT
  741.       signal (SIGEMT, fatal_error_signal);
  742. #endif
  743.       signal (SIGFPE, fatal_error_signal);
  744.       signal (SIGBUS, fatal_error_signal);
  745.       signal (SIGSEGV, fatal_error_signal);
  746.       signal (SIGSYS, fatal_error_signal);
  747.       signal (SIGTERM, fatal_error_signal);
  748. #ifdef SIGXCPU
  749.       signal (SIGXCPU, fatal_error_signal);
  750. #endif
  751. #ifdef SIGXFSZ
  752.       signal (SIGXFSZ, fatal_error_signal);
  753. #endif /* SIGXFSZ */
  754.  
  755. #ifdef IBMAIX
  756.       signal (SIGDANGER, fatal_error_signal);
  757.       signal (20, fatal_error_signal);
  758.       signal (21, fatal_error_signal);
  759.       signal (22, fatal_error_signal);
  760.       signal (23, fatal_error_signal);
  761.       signal (24, fatal_error_signal);
  762.       signal (SIGAIO, fatal_error_signal);
  763.       signal (SIGPTY, fatal_error_signal);
  764.       signal (SIGIOINT, fatal_error_signal);
  765.       signal (SIGGRANT, fatal_error_signal);
  766.       signal (SIGRETRACT, fatal_error_signal);
  767.       signal (SIGSOUND, fatal_error_signal);
  768.       signal (SIGMSG, fatal_error_signal);
  769. #endif
  770.     }
  771.  
  772.   noninteractive1 = noninteractive;
  773.  
  774. /* Perform basic initializations (not merely interning symbols) */
  775.  
  776.   if (!initialized)
  777.     {
  778.       init_alloc_once ();
  779.       init_obarray ();
  780.       init_eval_once ();
  781.       init_syntax_once ();    /* Create standard syntax table.
  782.                    Must be done before init_buffer */
  783.       init_casetab_once ();
  784.       init_buffer_once ();    /* Create buffer table and some buffers */
  785.       init_minibuf_once ();    /* Create list of minibuffers.
  786.                    Must precede init_window_once */
  787.       init_window_once ();    /* Init the window system */
  788.     }
  789.  
  790.   init_alloc ();
  791. #ifdef MAINTAIN_ENVIRONMENT
  792.   init_environ ();
  793. #endif
  794.   init_eval ();
  795.   init_data ();
  796.   init_lread ();
  797.  
  798.   init_cmdargs (argc, argv, skip_args);    /* Create list Vcommand_line_args */
  799.   init_buffer ();    /* Init default directory of main buffer */
  800.   if (!noninteractive)
  801.     {
  802. #ifdef VMS
  803.       init_vms_input ();/* init_display calls get_screen_size, that needs this */
  804. #endif /* VMS */
  805.       init_display ();    /* Determine terminal type.  init_sys_modes uses results */
  806.     }
  807.   init_keyboard ();    /* This too must precede init_sys_modes */
  808.   init_callproc ();    /* And this too. */
  809. #ifdef VMS
  810.   init_vmsproc ();    /* And this too. */
  811. #endif /* VMS */
  812.   init_sys_modes ();    /* Init system terminal modes (RAW or CBREAK, etc.) */
  813.   init_xdisp ();
  814.   init_macros ();
  815.   init_editfns ();
  816. #ifdef LISP_FLOAT_TYPE
  817.   init_floatfns ();
  818. #endif
  819. #ifdef VMS
  820.   init_vmsfns ();
  821. #endif /* VMS */
  822. #ifdef subprocesses
  823.   init_process ();
  824. #endif /* subprocesses */
  825.  
  826. /* Intern the names of all standard functions and variables; define standard keys */
  827.  
  828.   if (!initialized)
  829.     {
  830.       /* The basic levels of Lisp must come first */
  831.       /* And data must come first of all
  832.      for the sake of symbols like error-message */
  833.       syms_of_data ();
  834.       syms_of_alloc ();
  835. #ifdef MAINTAIN_ENVIRONMENT
  836.       syms_of_environ ();
  837. #endif /* MAINTAIN_ENVIRONMENT */
  838.       syms_of_lread ();
  839.       syms_of_print ();
  840.       syms_of_eval ();
  841.       syms_of_fns ();
  842. #ifdef LISP_FLOAT_TYPE
  843.       syms_of_floatfns ();
  844. #endif
  845.  
  846.       syms_of_elhash (); /* This has to be before any keymaps are made */
  847.  
  848.       syms_of_abbrev ();
  849.       syms_of_buffer ();
  850.       syms_of_bytecode ();
  851.       syms_of_callint ();
  852.       syms_of_casefiddle ();
  853.       syms_of_casetab ();
  854.       syms_of_callproc ();
  855.       syms_of_cmds ();
  856. #ifndef NO_DIR_LIBRARY
  857.       syms_of_dired ();
  858. #endif /* not NO_DIR_LIBRARY */
  859.       syms_of_display ();
  860.       syms_of_doc ();
  861.       syms_of_editfns ();
  862.       syms_of_emacs ();
  863.       syms_of_fileio ();
  864. #ifdef CLASH_DETECTION
  865.       syms_of_filelock ();
  866. #endif /* CLASH_DETECTION */
  867.       syms_of_indent ();
  868.       syms_of_keyboard ();
  869.       syms_of_keymap ();
  870.       syms_of_macros ();
  871.       syms_of_marker ();
  872.       syms_of_minibuf ();
  873.       syms_of_mocklisp ();
  874. #ifdef subprocesses
  875.       syms_of_process ();
  876. #endif /* subprocesses */
  877.       syms_of_search ();
  878. #ifdef MULTI_SCREEN
  879.       syms_of_screen ();
  880. #endif
  881.       syms_of_extents ();
  882.       syms_of_syntax ();
  883.       syms_of_undo ();
  884. #ifdef VMS
  885.       syms_of_vmsproc ();
  886. #endif /* VMS */
  887.       syms_of_window ();
  888.       syms_of_xdisp ();
  889. #ifdef HAVE_X_WINDOWS
  890.       syms_of_xfns ();
  891.       syms_of_xselect ();
  892.       syms_of_menubar ();
  893. #endif /* HAVE_X_WINDOWS */
  894.       syms_of_faces ();
  895.       syms_of_events ();
  896.       syms_of_event_alloc ();
  897.       syms_of_event_stream ();
  898.       syms_of_font_lock ();
  899.  
  900. #ifdef SYMS_SYSTEM
  901.       SYMS_SYSTEM;
  902. #endif
  903.  
  904. #ifdef SYMS_MACHINE
  905.       SYMS_MACHINE;
  906. #endif
  907.  
  908. #ifdef EMACS_BTL
  909.       syms_of_cadillac_btl_emacs ();  /* #### rename me */
  910. #endif
  911.  
  912. #ifdef ENERGIZE
  913.       syms_of_editorside ();
  914. #endif
  915.  
  916. #ifdef FREE_CHECKING
  917.       syms_of_free_hook();
  918. #endif
  919.       keys_of_keymap ();
  920.     }
  921.  
  922.   if (!initialized)
  923.     {
  924.       /* Handle -l loadup-and-dump, args passed by Makefile. */
  925.       if (argc > 2 + skip_args && !strcmp (argv[1 + skip_args], "-l"))
  926.     Vtop_level = Fcons (intern ("load"),
  927.                 Fcons (build_string (argv[2 + skip_args]), Qnil));
  928. #ifdef CANNOT_DUMP
  929.       /* Unless next switch is -nl, load "loadup.el" first thing.  */
  930.       if (!(argc > 1 + skip_args && !strcmp (argv[1 + skip_args], "-nl")))
  931.     Vtop_level = Fcons (intern ("load"),
  932.                 Fcons (build_string ("loadup.el"), Qnil));
  933. #endif /* CANNOT_DUMP */
  934.     }
  935.  
  936.   initialized = 1;
  937.  
  938.   /* try really hard to get the actually pathname of the exec file we
  939.      are running */
  940.   {
  941.     Lisp_Object full_program_name;
  942.     char *progname = find_executable_name ();
  943.     full_program_name = (progname
  944.              ? Fexpand_file_name (build_string (progname), Qnil)
  945.              : Fcar (Vcommand_line_args));
  946.     xfree (progname);
  947.  
  948.     Vexecution_path = full_program_name;
  949.     Vinvocation_name = Ffile_name_nondirectory (full_program_name);
  950.   }
  951.  
  952. #ifdef HAVE_TZSETWALL
  953.   {
  954.     /* fix for bug where emacs always thinks that it is in the
  955.        timezone wherein it was dumped
  956.      */
  957.     extern void tzsetwall ();
  958.     tzsetwall ();
  959.   }
  960. #endif
  961.  
  962.   /* Enter editor command loop.  This never returns.  */
  963.   Frecursive_edit ();
  964.   /* NOTREACHED */
  965.   return -1;
  966. }
  967.  
  968. #ifdef RUNNABLE_TEMACS
  969.  
  970. static jmp_buf run_temacs_catch;
  971. static char *run_temacs_argv[100];
  972. static char run_temacs_args[1000];
  973. static int run_temacs_argc; /* -1 if dump_emacs or run_emacs_from_temacs */
  974.  
  975. extern char **environ;
  976.  
  977. /* ARGSUSED */
  978. int
  979. main (argc, argv, envp)
  980.      int argc;
  981.      char **argv;
  982.      char **envp;
  983. {
  984.   if (!initialized)
  985.   {
  986.     run_temacs_argc = 0;
  987.     if (! _setjmp (run_temacs_catch))
  988.       main_1 (argc, argv, envp);
  989.     /* run-emacs-from-temacs called */
  990.     argc = run_temacs_argc;
  991.     run_temacs_argc = 0;
  992.     argv = run_temacs_argv;
  993.     envp = environ;
  994.   }
  995.   run_temacs_argc = -1;
  996.   return main_1 (argc, argv, envp);
  997. }
  998.  
  999. DEFUN ("run-emacs-from-temacs",
  1000.        Frun_emacs_from_temacs, Srun_emacs_from_temacs, 0, MANY, 0,
  1001.   "Do not call this.  It will reinitialize your Emacs.  You'll be sorry.")
  1002. /* If this function is called from startup.el, it will be possible to run
  1003.    temacs as an editor, instead of having to dump an emacs and then run that
  1004.    (when debugging emacs itself, this can be much faster.)
  1005.    This will "restart" emacs with the specified command-line arguments.
  1006.  */
  1007.   (int nargs, Lisp_Object *args)
  1008. {
  1009.   extern char **environ;
  1010.   extern int gc_in_progress, waiting_for_input;
  1011.   int ac;
  1012.   int namesize;
  1013.  
  1014.   if (gc_in_progress) abort ();
  1015.  
  1016.   if (run_temacs_argc < 0)
  1017.     error ("I've lost my temacs-hood.");
  1018.  
  1019.   namesize = XSTRING (Vexecution_path)->size + 1;
  1020.   if (namesize >= sizeof (run_temacs_args))
  1021.     error ("execution-path string is too long");
  1022.   if (nargs >= (sizeof (run_temacs_argv) / sizeof (run_temacs_argv [0])))
  1023.     error ("too many args");
  1024.   memcpy (run_temacs_args, (char *) XSTRING (Vexecution_path)->data, namesize);
  1025.   run_temacs_argv [0] = run_temacs_args;
  1026.   for (ac = 0; ac < nargs; ac++)
  1027.     {
  1028.       int s;
  1029.       CHECK_STRING (args[ac], ac);
  1030.       s = XSTRING (args[ac])->size + 1;
  1031.       if (s + namesize > sizeof (run_temacs_args))
  1032.         error ("lose lose");
  1033.       memcpy (run_temacs_args + namesize, XSTRING (args[ac])->data, s);
  1034.       run_temacs_argv [ac + 1] = run_temacs_args + namesize;
  1035.       namesize += s;
  1036.     }
  1037.   run_temacs_argv [nargs + 1] = 0;
  1038.   unbind_to (0, Qnil); /* this closes loadup.el */
  1039.   waiting_for_input = 0;
  1040.   Vpurify_flag = Qnil;
  1041.   run_temacs_argc = nargs + 1;
  1042.   report_pure_usage ();
  1043.   _longjmp (run_temacs_catch, 1);
  1044.   return Qnil; /* not reached; warning suppression */
  1045. }
  1046.  
  1047. #endif /* RUNNABLE_TEMACS */
  1048.  
  1049.  
  1050. DEFUN ("kill-emacs", Fkill_emacs, Skill_emacs, 0, 1, "P",
  1051.   "Exit the Emacs job and kill it.  Ask for confirmation, without argument.\n\
  1052. If ARG is an integer, return ARG as the exit program code.\n\
  1053. If ARG is a  string, stuff it as keyboard input.\n\n\
  1054. The value of `kill-emacs-hook', if not void,\n\
  1055. is a list of functions (of no args),\n\
  1056. all of which are called before Emacs is actually killed.")
  1057.   (arg)
  1058.      Lisp_Object arg;
  1059. {
  1060.   struct gcpro gcpro1;
  1061.  
  1062.   GCPRO1 (arg);
  1063.  
  1064.   if (feof (stdin))
  1065.     arg = Qt;
  1066.  
  1067.   if (!NILP (Vrun_hooks) && !noninteractive)
  1068.     call1 (Vrun_hooks, intern ("kill-emacs-hook"));
  1069.  
  1070. #ifdef subprocesses
  1071.   kill_buffer_processes (Qnil);
  1072. #endif /* subprocesses */
  1073.  
  1074. #ifdef VMS
  1075.   kill_vms_processes ();
  1076. #endif /* VMS */
  1077.  
  1078.   Fdo_auto_save (Qt);
  1079.  
  1080. #ifdef CLASH_DETECTION
  1081.   unlock_all_files ();
  1082. #endif /* CLASH_DETECTION */
  1083.  
  1084.   fflush (stdout);
  1085.   reset_sys_modes ();
  1086.  
  1087. #ifdef HAVE_X_WINDOWS
  1088.   if (!noninteractive && EQ (Vwindow_system, intern ("x")))
  1089.     Fx_close_current_connection ();
  1090. #endif /* HAVE_X_WINDOWS */
  1091.  
  1092.   UNGCPRO;
  1093.  
  1094. /* Is it really necessary to do this deassign
  1095.    when we are going to exit anyway?  */
  1096. /* #ifdef VMS
  1097.   stop_vms_input ();
  1098.  #endif  */
  1099.   stuff_buffered_input (arg);
  1100.   exit ((FIXNUMP (arg)) ? XINT (arg)
  1101. #ifdef VMS
  1102.     : 1
  1103. #else
  1104.     : 0
  1105. #endif
  1106.     );
  1107.   /* NOTREACHED */
  1108.   return Qnil; /* I'm sick of the compiler warning */
  1109. }
  1110.  
  1111. #ifndef CANNOT_DUMP
  1112. /* Nothing like this can be implemented on an Apollo.
  1113.    What a loss!  */
  1114.  
  1115. DEFUN ("dump-emacs", Fdump_emacs, Sdump_emacs, 2, 2, 0,
  1116.   "Dump current state of Emacs into executable file FILENAME.\n\
  1117. Take symbols from SYMFILE (presumably the file you executed to run Emacs).\n\
  1118. This is used in the file `loadup.el' when building Emacs.\n\
  1119. \n\
  1120. Bind `command-line-processed' to nil before dumping,\n\
  1121. if you want the dumped Emacs to process its command line\n\
  1122. and announce itself normally when it is run.")
  1123.   (intoname, symname)
  1124.      Lisp_Object intoname, symname;
  1125. {
  1126.   register unsigned char *a_name = 0;
  1127.   extern char my_edata;
  1128.   Lisp_Object tem;
  1129.  
  1130. #ifdef FREE_CHECKING
  1131.   Freally_free (Qnil);
  1132.  
  1133.   /* When we're dumping, we can't use the debugging free() */
  1134.  
  1135.   disable_free_hook ();
  1136. #endif
  1137.  
  1138.   CHECK_STRING (intoname, 0);
  1139.   intoname = Fexpand_file_name (intoname, Qnil);
  1140.   if (!NILP (symname))
  1141.     {
  1142.       CHECK_STRING (symname, 0);
  1143.       if (XSTRING (symname)->size)
  1144.     {
  1145.       symname = Fexpand_file_name (symname, Qnil);
  1146.       a_name = XSTRING (symname)->data;
  1147.     }
  1148.     }
  1149.  
  1150.   tem = Vpurify_flag;
  1151.   Vpurify_flag = Qnil;
  1152.  
  1153.   report_pure_usage ();
  1154.   fflush (stdout);
  1155. #ifdef VMS
  1156.   mapout_data (XSTRING (intoname)->data);
  1157. #else
  1158.   /* Tell malloc where start of impure now is */
  1159.   /* Also arrange for warnings when nearly out of space.  */
  1160. #ifndef SYSTEM_MALLOC
  1161.   malloc_init (&my_edata, malloc_warning);
  1162. #endif
  1163.   unexec (XSTRING (intoname)->data, a_name, &my_edata, 0, 0);
  1164. #endif /* not VMS */
  1165.  
  1166.   Vpurify_flag = tem;
  1167.  
  1168.   return Qnil;
  1169. }
  1170.  
  1171. #endif /* not CANNOT_DUMP */
  1172.  
  1173. #ifdef VMS
  1174. #define SEPCHAR ','
  1175. #else
  1176. #define SEPCHAR ':'
  1177. #endif
  1178.  
  1179. Lisp_Object
  1180. decode_env_path (evarname, defalt)
  1181.      const char *evarname, *defalt;
  1182. {
  1183.   register const char *path;
  1184.   register const char *p;
  1185.  
  1186.   Lisp_Object lpath;
  1187.  
  1188.   path = (char *) egetenv (evarname);
  1189.   if (!path)
  1190.     path = defalt;
  1191.   lpath = Qnil;
  1192.   while (1)
  1193.     {
  1194.       p = strchr (path, SEPCHAR);
  1195.       if (!p) p = path + strlen (path);
  1196.       lpath = Fcons (p - path ? make_string (path, p - path) : Qnil,
  1197.              lpath);
  1198.       if (*p)
  1199.     path = p + 1;
  1200.       else
  1201.     break;
  1202.     }
  1203.   return Fnreverse (lpath);
  1204. }
  1205.  
  1206. DEFUN ("noninteractive", Fnoninteractive, Snoninteractive, 0, 0, 0,
  1207.   "Non-nil return value means Emacs is running without interactive terminal.")
  1208.   ()
  1209. {
  1210.   return ((noninteractive) ? Qt : Qnil);
  1211. }
  1212.  
  1213. static void
  1214. syms_of_emacs ()
  1215. {
  1216. #ifndef CANNOT_DUMP
  1217.   defsubr (&Sdump_emacs);
  1218. #endif /* not CANNOT_DUMP */
  1219.  
  1220. #ifdef RUNNABLE_TEMACS
  1221.   defsubr (&Srun_emacs_from_temacs);
  1222. #endif
  1223.  
  1224.   defsubr (&Skill_emacs);
  1225.   defsubr (&Snoninteractive);
  1226.  
  1227.   DEFVAR_LISP ("command-line-args", &Vcommand_line_args,
  1228.     "Args passed by shell to Emacs, as a list of strings.");
  1229.  
  1230.   DEFVAR_LISP ("invocation-name", &Vinvocation_name,
  1231.     "Name of file used to invoke editing session.\n\
  1232. This is the same as `(file-name-nondirectory execution-path)'.");
  1233.  
  1234.   DEFVAR_LISP ("execution-path", &Vexecution_path,
  1235.     "Pathname of executable emacs program now running.");
  1236.  
  1237.   DEFVAR_LISP ("system-type", &Vsystem_type,
  1238.     "Value is symbol indicating type of operating system you are using.");
  1239.   Vsystem_type = intern (SYSTEM_TYPE);
  1240.  
  1241.   DEFVAR_BOOL ("noninteractive", &noninteractive1,
  1242.     "Non-nil means Emacs is running without interactive terminal.");
  1243. }
  1244.