Version 3.16
[bpt/emacs.git] / src / sysdep.c
index 96f8574..eae493b 100644 (file)
@@ -1,6 +1,6 @@
 /* Interfaces to system-dependent kernel and library entries.
-   Copyright (C) 1985, 86,87,88,93,94,95,1999,2000,01,2003
-   Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1999, 2000, 2001,
+                 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -16,8 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -47,13 +47,9 @@ extern void srandom P_ ((unsigned int));
 #endif
 
 #include "blockinput.h"
-#undef NULL
 
 #ifdef MAC_OS8
-/* It is essential to include stdlib.h so that this file picks up
-   the correct definitions of rand, srand, and RAND_MAX.
-   Otherwise random numbers will not work correctly.  */
-#include <stdlib.h>
+#include <sys/param.h>
 
 #ifndef subprocesses
 /* Nonzero means delete a process right away if it exits (process.c).  */
@@ -70,10 +66,6 @@ static int delete_exited_processes;
 #endif
 #endif /* not WINDOWSNT */
 
-#ifdef HAVE_CARBON
-#define read sys_read
-#endif
-
 /* Does anyone other than VMS need this? */
 #ifndef fwrite
 #define sys_fwrite fwrite
@@ -191,6 +183,7 @@ extern int quit_char;
 #define _P_WAIT 0
 int _CRTAPI1 _spawnlp (int, const char *, const char *, ...);
 int _CRTAPI1 _getpid (void);
+extern char *getwd (char *);
 #endif
 
 #ifdef NONSYSTEM_DIR_LIBRARY
@@ -262,6 +255,81 @@ void hft_reset ();
 
 SIGMASKTYPE sigprocmask_set;
 
+
+#ifndef HAVE_GET_CURRENT_DIR_NAME
+
+/* Return the current working directory.  Returns NULL on errors.
+   Any other returned value must be freed with free. This is used
+   only when get_current_dir_name is not defined on the system.  */
+char*
+get_current_dir_name ()
+{
+  char *buf;
+  char *pwd;
+  struct stat dotstat, pwdstat;
+  /* If PWD is accurate, use it instead of calling getwd.  PWD is
+     sometimes a nicer name, and using it may avoid a fatal error if a
+     parent directory is searchable but not readable.  */
+    if ((pwd = getenv ("PWD")) != 0
+      && (IS_DIRECTORY_SEP (*pwd) || (*pwd && IS_DEVICE_SEP (pwd[1])))
+      && stat (pwd, &pwdstat) == 0
+      && stat (".", &dotstat) == 0
+      && dotstat.st_ino == pwdstat.st_ino
+      && dotstat.st_dev == pwdstat.st_dev
+#ifdef MAXPATHLEN
+      && strlen (pwd) < MAXPATHLEN
+#endif
+      )
+    {
+      buf = (char *) malloc (strlen (pwd) + 1);
+      if (!buf)
+        return NULL;
+      strcpy (buf, pwd);
+    }
+#ifdef HAVE_GETCWD
+  else
+    {
+      size_t buf_size = 1024;
+      buf = (char *) malloc (buf_size);
+      if (!buf)
+        return NULL;
+      for (;;)
+        {
+          if (getcwd (buf, buf_size) == buf)
+            break;
+          if (errno != ERANGE)
+            {
+              int tmp_errno = errno;
+              free (buf);
+              errno = tmp_errno;
+              return NULL;
+            }
+          buf_size *= 2;
+          buf = (char *) realloc (buf, buf_size);
+          if (!buf)
+            return NULL;
+        }
+    }
+#else
+  else
+    {
+      /* We need MAXPATHLEN here.  */
+      buf = (char *) malloc (MAXPATHLEN + 1);
+      if (!buf)
+        return NULL;
+      if (getwd (buf) == NULL)
+        {
+          int tmp_errno = errno;
+          free (buf);
+          errno = tmp_errno;
+          return NULL;
+        }
+    }
+#endif
+  return buf;
+}
+#endif
+
 \f
 /* Specify a different file descriptor for further input operations.  */
 
@@ -614,6 +682,15 @@ child_setup_tty (out)
   s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
 #endif /* HPUX */
 
+#ifdef SIGNALS_VIA_CHARACTERS
+  /* the QUIT and INTR character are used in process_send_signal
+     so set them here to something useful.  */
+  if (s.main.c_cc[VQUIT] == CDISABLE)
+    s.main.c_cc[VQUIT] = '\\'&037;     /* Control-\ */
+  if (s.main.c_cc[VINTR] == CDISABLE)
+    s.main.c_cc[VINTR] = 'C'&037;      /* Control-C */
+#endif /* not SIGNALS_VIA_CHARACTERS */
+
 #ifdef AIX
 /* AIX enhanced edit loses NULs, so disable it */
 #ifndef IBMR2AIX
@@ -624,22 +701,16 @@ child_setup_tty (out)
      don't ignore break, but don't signal either, so it looks like NUL.  */
   s.main.c_iflag &= ~IGNBRK;
   s.main.c_iflag &= ~BRKINT;
+  /* rms: Formerly it set s.main.c_cc[VINTR] to 0377 here
+     unconditionally.  Then a SIGNALS_VIA_CHARACTERS conditional
+     would force it to 0377.  That looks like duplicated code.  */
+#ifndef SIGNALS_VIA_CHARACTERS
   /* QUIT and INTR work better as signals, so disable character forms */
-  s.main.c_cc[VINTR] = 0377;
-#ifdef SIGNALS_VIA_CHARACTERS
-  /* the QUIT and INTR character are used in process_send_signal
-     so set them here to something useful.  */
-  if (s.main.c_cc[VQUIT] == 0377)
-    s.main.c_cc[VQUIT] = '\\'&037;     /* Control-\ */
-  if (s.main.c_cc[VINTR] == 0377)
-    s.main.c_cc[VINTR] = 'C'&037;      /* Control-C */
-#else /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
-  /* QUIT and INTR work better as signals, so disable character forms */
-  s.main.c_cc[VQUIT] = 0377;
-  s.main.c_cc[VINTR] = 0377;
+  s.main.c_cc[VQUIT] = CDISABLE;
+  s.main.c_cc[VINTR] = CDISABLE;
   s.main.c_lflag &= ~ISIG;
 #endif /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
-  s.main.c_cc[VEOL] = 0377;
+  s.main.c_cc[VEOL] = CDISABLE;
   s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
 #endif /* AIX */
 
@@ -870,7 +941,7 @@ sys_subshell ()
       if (pid == -1)
        write (1, "Can't execute subshell", 22);
 #else   /* not WINDOWSNT */
-      execlp (sh, sh, 0);
+      execlp (sh, sh, (char *) 0);
       write (1, "Can't execute subshell", 22);
       _exit (1);
 #endif  /* not WINDOWSNT */
@@ -1480,10 +1551,10 @@ nil means don't delete them until `list-processes' is run.  */);
       tty.main.c_line = 0;
       tty.main.c_iflag &= ~ASCEDIT;
 #else
-      tty.main.c_cc[VSTRT] = 255;
-      tty.main.c_cc[VSTOP] = 255;
-      tty.main.c_cc[VSUSP] = 255;
-      tty.main.c_cc[VDSUSP] = 255;
+      tty.main.c_cc[VSTRT] = CDISABLE;
+      tty.main.c_cc[VSTOP] = CDISABLE;
+      tty.main.c_cc[VSUSP] = CDISABLE;
+      tty.main.c_cc[VDSUSP] = CDISABLE;
 #endif /* IBMR2AIX */
       if (flow_control)
        {
@@ -1719,10 +1790,16 @@ get_frame_size (widthp, heightp)
 #else
 #ifdef VMS
 
+  /* Use a fresh channel since the current one may have stale info
+     (for example, from prior to a suspend); and to avoid a dependency
+     in the init sequence.  */
+  int chan;
   struct sensemode tty;
 
-  SYS$QIOW (0, input_fd, IO$_SENSEMODE, &tty, 0, 0,
-           &tty.class, 12, 0, 0, 0, 0);
+  SYS$ASSIGN (&input_dsc, &chan, 0, 0);
+  SYS$QIOW (0, chan, IO$_SENSEMODE, &tty, 0, 0,
+            &tty.class, 12, 0, 0, 0, 0);
+  SYS$DASSGN (chan);
   *widthp = tty.scr_wid;
   *heightp = tty.scr_len;
 
@@ -2473,6 +2550,7 @@ select_alarm ()
 #else /* not BSD4_1 */
   signal (SIGALRM, SIG_IGN);
 #endif /* not BSD4_1 */
+  SIGNAL_THREAD_CHECK (SIGALRM);
   if (read_alarm_should_throw)
     longjmp (read_alarm_throw, 1);
 }
@@ -2614,13 +2692,6 @@ sys_select (nfds, rfds, wfds, efds, timeout)
 /* Read keyboard input into the standard buffer,
    waiting for at least one character.  */
 
-/* Make all keyboard buffers much bigger when using a window system.  */
-#ifdef HAVE_WINDOW_SYSTEM
-#define BUFFER_SIZE_FACTOR 16
-#else
-#define BUFFER_SIZE_FACTOR 1
-#endif
-
 void
 read_input_waiting ()
 {
@@ -2629,26 +2700,19 @@ read_input_waiting ()
 
   if (read_socket_hook)
     {
-      struct input_event buf[256];
-      for (i = 0; i < 256; i++)
-       EVENT_INIT (buf[i]);
-      
+      struct input_event hold_quit;
+
+      EVENT_INIT (hold_quit);
+      hold_quit.kind = NO_EVENT;
+
       read_alarm_should_throw = 0;
       if (! setjmp (read_alarm_throw))
-       nread = (*read_socket_hook) (0, buf, 256, 1);
+       nread = (*read_socket_hook) (0, 1, &hold_quit);
       else
        nread = -1;
 
-      /* Scan the chars for C-g and store them in kbd_buffer.  */
-      for (i = 0; i < nread; i++)
-       {
-         kbd_buffer_store_event (&buf[i]);
-         /* Don't look at input that follows a C-g too closely.
-            This reduces lossage due to autorepeat on C-g.  */
-         if (buf[i].kind == ASCII_KEYSTROKE_EVENT
-             && buf[i].code == quit_char)
-           break;
-       }
+      if (hold_quit.kind != NO_EVENT)
+       kbd_buffer_store_event (&hold_quit);
     }
   else
     {
@@ -2783,12 +2847,16 @@ sys_signal (int signal_number, signal_handler_t action)
   struct sigaction new_action, old_action;
   sigemptyset (&new_action.sa_mask);
   new_action.sa_handler = action;
-#if defined (SA_RESTART) && ! defined (BROKEN_SA_RESTART)
+#if defined (SA_RESTART) && ! defined (BROKEN_SA_RESTART) && !defined(SYNC_INPUT)
   /* Emacs mostly works better with restartable system services. If this
      flag exists, we probably want to turn it on here.
      However, on some systems this resets the timeout of `select'
      which means that `select' never finishes if it keeps getting signals.
      BROKEN_SA_RESTART is defined on those systems.  */
+  /* It's not clear why the comment above says "mostly works better".  --Stef
+     When SYNC_INPUT is set, we don't want SA_RESTART because we need to poll
+     for pending input so we need long-running syscalls to be interrupted
+     after a signal that sets the interrupt_input_pending flag.  */
   new_action.sa_flags = SA_RESTART;
 #else
   new_action.sa_flags = 0;
@@ -3240,7 +3308,8 @@ emacs_open (path, oflag, mode)
 #endif
 
   while ((rtnval = open (path, oflag, mode)) == -1
-        && (errno == EINTR));
+        && (errno == EINTR))
+    QUIT;
   return (rtnval);
 }
 
@@ -3273,7 +3342,8 @@ emacs_read (fildes, buf, nbyte)
   register int rtnval;
 
   while ((rtnval = read (fildes, buf, nbyte)) == -1
-        && (errno == EINTR));
+        && (errno == EINTR))
+    QUIT;
   return (rtnval);
 }
 
@@ -3294,7 +3364,15 @@ emacs_write (fildes, buf, nbyte)
       if (rtnval == -1)
        {
          if (errno == EINTR)
-           continue;
+           {
+#ifdef SYNC_INPUT
+             /* I originally used `QUIT' but that might causes files to
+                be truncated if you hit C-g in the middle of it.  --Stef  */
+             if (interrupt_input_pending)
+               handle_async_input ();
+#endif
+             continue;
+           }
          else
            return (bytes_written ? bytes_written : -1);
        }
@@ -3803,7 +3881,6 @@ rmdir (dpath)
 \f
 /* Functions for VMS */
 #ifdef VMS
-#include "vms-pwd.h"
 #include <acldef.h>
 #include <chpdef.h>
 #include <jpidef.h>