*** empty log message ***
[bpt/emacs.git] / src / sysdep.c
index c790901..cda2b8f 100644 (file)
@@ -104,21 +104,18 @@ extern char *sys_errlist[];
 #endif
 #endif /* not 4.1 bsd */
 
-/* Get DGUX definition for FASYNC - DJB */
-#ifdef DGUX
-#include <sys/file.h>
-#endif /* DGUX */
+#ifdef BROKEN_FASYNC
+/* On some systems (DGUX comes to mind real fast) FASYNC causes
+   background writes to the terminal to stop all processes in the
+   process group when invoked under the csh (and probably any shell
+   with job control). This stops Emacs dead in its tracks when coming
+   up under X11. */
+#undef FASYNC
+#endif
 
 #include <sys/ioctl.h>
 #include "systty.h"
-
-#ifdef BSD
-#ifdef BSD4_1
-#include <wait.h>
-#else /* not 4.1 */
-#include <sys/wait.h>
-#endif /* not 4.1 */
-#endif /* BSD */
+#include "syswait.h"
 
 #ifdef BROKEN_TIOCGWINSZ
 #undef TIOCGWINSZ
@@ -239,7 +236,7 @@ init_baud_rate ()
 
       sg.c_cflag = (sg.c_cflag & ~CBAUD) | B9600;
       tcgetattr (0, &sg);
-      ospeed = sg.c_cflag & CBAUD;
+      ospeed = cfgetospeed (&sg);
 #else /* neither VMS nor TERMIOS */
 #ifdef HAVE_TERMIO
       struct termio sg;
@@ -255,7 +252,8 @@ init_baud_rate ()
       struct sgttyb sg;
       
       sg.sg_ospeed = B9600;
-      ioctl (0, TIOCGETP, &sg);
+      if (ioctl (0, TIOCGETP, &sg) < 0)
+       abort ();
       ospeed = sg.sg_ospeed;
 #endif /* not HAVE_TERMIO */
 #endif /* not HAVE_TERMIOS */
@@ -334,11 +332,20 @@ wait_for_termination (pid)
       else
        sigpause (SIGEMPTYMASK);
 #else /* not BSD, and not HPUX version >= 6 */
-#ifdef UNIPLUS
+#if defined (UNIPLUS)
       if (0 > kill (pid, 0))
        break;
       wait (0);
 #else /* neither BSD nor UNIPLUS: random sysV */
+#ifdef POSIX_SIGNALS   /* would this work for LINUX as well? */
+      sigblock (sigmask (SIGCHLD));
+      if (0 > kill (pid, 0))
+       {
+         sigunblock (sigmask (SIGCHLD));
+         break;
+       }
+      sigpause (SIGEMPTYMASK);
+#else /* not POSIX_SIGNALS */
 #ifdef HAVE_SYSV_SIGPAUSE
       sighold (SIGCHLD);
       if (0 > kill (pid, 0))
@@ -355,6 +362,7 @@ wait_for_termination (pid)
         we lose just one second.  */
       sleep (1);
 #endif /* not HAVE_SYSV_SIGPAUSE */
+#endif /* not POSIX_SIGNALS */
 #endif /* not UNIPLUS */
 #endif /* not BSD, and not HPUX version >= 6 */
 #endif /* not VMS */
@@ -426,7 +434,7 @@ child_setup_tty (out)
   s.main.c_oflag &= ~OLCUC;    /* Disable map of lower case to upper on
                                   output */
 #if 0
-  /* Said to be unnecesary:  */
+  /* Said to be unnecessary:  */
   s.main.c_cc[VMIN] = 1;       /* minimum number of characters to accept  */
   s.main.c_cc[VTIME] = 0;      /* wait forever for at least 1 character  */
 #endif
@@ -450,11 +458,22 @@ 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;
+  /* 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[VEOL] = 0377;
   s.main.c_lflag &= ~ISIG;
+#endif /* no TIOCGPGRP or no TIOCGLTC or no TIOCGETC */
+  s.main.c_cc[VEOL] = 0377;
   s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
 #endif /* AIX */
 
@@ -545,7 +564,14 @@ sys_suspend ()
 #else
 #ifdef SIGTSTP
 
-  EMACS_KILLPG (getpgrp (0), SIGTSTP);
+  {
+#ifdef USG
+    int pgrp = getpgrp ();
+#else
+    int pgrp = getpgrp (0);
+#endif
+    EMACS_KILLPG (pgrp, SIGTSTP);
+  }
 
 #else /* No SIGTSTP */
 #ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
@@ -670,7 +696,7 @@ reset_sigio ()
   unrequest_sigio ();
 }
 
-#ifdef FASYNC          /* F_SETFL does not imply existance of FASYNC */
+#ifdef FASYNC          /* F_SETFL does not imply existence of FASYNC */
 
 request_sigio ()
 {
@@ -725,6 +751,54 @@ unrequest_sigio ()
 #endif /* FASYNC */
 #endif /* F_SETFL */
 \f
+/* Saving and restoring the process group of Emacs's terminal.  */
+
+#ifdef BSD
+
+/* The process group of which Emacs was a member when it initially
+   started.
+
+   If Emacs was in its own process group (i.e. inherited_pgroup ==
+   getpid ()), then we know we're running under a shell with job
+   control (Emacs would never be run as part of a pipeline).
+   Everything is fine.
+
+   If Emacs was not in its own process group, then we know we're
+   running under a shell (or a caller) that doesn't know how to
+   separate itself from Emacs (like sh).  Emacs must be in its own
+   process group in order to receive SIGIO correctly.  In this
+   situation, we put ourselves in our own pgroup, forcibly set the
+   tty's pgroup to our pgroup, and make sure to restore and reinstate
+   the tty's pgroup just like any other terminal setting.  If
+   inherited_group was not the tty's pgroup, then we'll get a
+   SIGTTmumble when we try to change the tty's pgroup, and a CONT if
+   it goes foreground in the future, which is what should happen.  */
+int inherited_pgroup;
+
+/* Split off the foreground process group to Emacs alone.
+   When we are in the foreground, but not started in our own process
+   group, redirect the TTY to point to our own process group.  We need
+   to be in our own process group to receive SIGIO properly.  */
+narrow_foreground_group ()
+{
+  int me = getpid ();
+
+  setpgrp (0, inherited_pgroup);
+  if (inherited_pgroup != me)
+    EMACS_SET_TTY_PGRP (0, &me);
+  setpgrp (0, me);
+}
+
+/* Set the tty to our original foreground group.  */
+widen_foreground_group ()
+{
+  if (inherited_pgroup != getpid ())
+    EMACS_SET_TTY_PGRP (0, &inherited_pgroup);
+  setpgrp (0, inherited_pgroup);
+}
+
+#endif
+\f
 /* Getting and setting emacs_tty structures.  */
 
 /* Set *TC to the parameters associated with the terminal FD.
@@ -765,13 +839,13 @@ emacs_get_tty (fd, settings)
 #endif
 
   /* Suivant - Do we have to get struct ltchars data?  */
-#ifdef TIOCGLTC
+#ifdef HAVE_LTCHARS
   if (ioctl (fd, TIOCGLTC, &settings->ltchars) < 0)
     return -1;
 #endif
 
   /* How about a struct tchars and a wordful of lmode bits?  */
-#ifdef TIOCGETC
+#ifdef HAVE_TCHARS
   if (ioctl (fd, TIOCGETC, &settings->tchars) < 0
       || ioctl (fd, TIOCLGET, &settings->lmode) < 0)
     return -1;
@@ -795,6 +869,7 @@ emacs_set_tty (fd, settings, waitp)
 {
   /* Set the primary parameters - baud rate, character size, etcetera.  */
 #ifdef HAVE_TCATTR
+  int i;
   /* We have those nifty POSIX tcmumbleattr functions.
      William J. Smith <wjs@wiis.wang.com> writes:
      "POSIX 1003.1 defines tcsetattr() to return success if it was
@@ -802,7 +877,8 @@ emacs_set_tty (fd, settings, waitp)
      of the requested actions could not be performed.
      We must read settings back to ensure tty setup properly.
      AIX requires this to keep tty from hanging occasionally."  */
-  for (;;)
+  /* This make sure that we don't loop indefinitely in here.  */
+  for (i = 0 ; i < 10 ; i++)
     if (tcsetattr (fd, waitp ? TCSAFLUSH : TCSADRAIN, &settings->main) < 0)
       {
        if (errno == EINTR)
@@ -816,10 +892,18 @@ emacs_set_tty (fd, settings, waitp)
 
        /* Get the current settings, and see if they're what we asked for.  */
        tcgetattr (fd, &new);
-       if (memcmp (&new, &settings->main, sizeof (new)))
-         continue;
-       else
+       /* We cannot use memcmp on the whole structure here because under
+        * aix386 the termios structure has some reserved field that may
+        * not be filled in.
+        */
+       if (   new.c_iflag == settings->main.c_iflag
+           && new.c_oflag == settings->main.c_oflag
+           && new.c_cflag == settings->main.c_cflag
+           && new.c_lflag == settings->main.c_lflag
+           && memcmp(new.c_cc, settings->main.c_cc, NCCS) == 0)
          break;
+       else
+         continue;
       }
 
 #else
@@ -846,13 +930,13 @@ emacs_set_tty (fd, settings, waitp)
 #endif
 
   /* Suivant - Do we have to get struct ltchars data?  */
-#ifdef TIOCGLTC
+#ifdef HAVE_LTCHARS
   if (ioctl (fd, TIOCSLTC, &settings->ltchars) < 0)
     return -1;
 #endif
 
   /* How about a struct tchars and a wordful of lmode bits?  */
-#ifdef TIOCGETC
+#ifdef HAVE_TCHARS
   if (ioctl (fd, TIOCSETC, &settings->tchars) < 0
       || ioctl (fd, TIOCLSET, &settings->lmode) < 0)
     return -1;
@@ -874,9 +958,11 @@ int term_initted;          /* 1 if outer tty status has been recorded */
 int lmode;
 #endif
 
+#ifndef F_SETOWN_BUG
 #ifdef F_SETOWN
 int old_fcntl_owner;
 #endif /* F_SETOWN */
+#endif /* F_SETOWN_BUG */
 
 /* This may also be defined in stdio,
    but if so, this does no harm,
@@ -888,10 +974,10 @@ unsigned char _sobuf[BUFSIZ+8];
 char _sobuf[BUFSIZ];
 #endif
  
-#ifdef TIOCGLTC
+#ifdef HAVE_LTCHARS
 static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
 #endif
-#ifdef TIOCGETC
+#ifdef HAVE_TCHARS
   static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
 #endif 
 
@@ -941,6 +1027,11 @@ init_sys_modes ()
 #endif
 #endif /* not VMS */
 
+#ifdef BSD
+  if (! read_socket_hook && EQ (Vwindow_system, Qnil))
+    narrow_foreground_group ();
+#endif
+
   EMACS_GET_TTY (input_fd, &old_tty);
 
   if (!read_socket_hook && EQ (Vwindow_system, Qnil))
@@ -999,6 +1090,18 @@ init_sys_modes ()
 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP.  */
       tty.main.c_cc[VDSUSP] = CDISABLE;
 #endif /* VDSUSP */
+#ifdef VLNEXT
+      tty.main.c_cc[VLNEXT] = CDISABLE;
+#endif /* VLNEXT */
+#ifdef VREPRINT
+      tty.main.c_cc[VREPRINT] = CDISABLE;
+#endif /* VREPRINT */
+#ifdef VWERASE
+      tty.main.c_cc[VWERASE] = CDISABLE;
+#endif /* VWERASE */
+#ifdef VDISCARD
+      tty.main.c_cc[VDISCARD] = CDISABLE;
+#endif /* VDISCARD */
 #endif /* mips or HAVE_TCATTR */
 #ifdef AIX
 #ifndef IBMR2AIX
@@ -1042,7 +1145,7 @@ init_sys_modes ()
         control for user coming over network on 4.2; in this case,
         only t_stopc and t_startc really matter.  */
 #ifndef HAVE_TERMIO
-#ifdef TIOCGETC
+#ifdef HAVE_TCHARS
       /* Note: if not using CBREAK mode, it makes no difference how we
         set this */
       tty.tchars = new_tchars;
@@ -1063,17 +1166,22 @@ init_sys_modes ()
 #endif
 
       tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_tty.lmode;
+#ifdef ultrix
+      /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt
+        anything, and leaving it in breaks the meta key.  Go figure.  */
+      tty.lmode &= ~LLITOUT;
+#endif
       
 #ifdef BSD4_1
       lmode = tty.lmode;
 #endif
 
-#endif /* TIOCGETC */
+#endif /* HAVE_TCHARS */
 #endif /* not HAVE_TERMIO */
 
-#ifdef TIOCGLTC
+#ifdef HAVE_LTCHARS
       tty.ltchars = new_ltchars;
-#endif /* TIOCGLTC */
+#endif /* HAVE_LTCHARS */
 
       EMACS_SET_TTY (input_fd, &tty, 0);
 
@@ -1113,7 +1221,8 @@ init_sys_modes ()
     }
 
 #ifdef F_SETFL
-#ifdef F_GETOWN                /* F_SETFL does not imply existance of F_GETOWN */
+#ifndef F_SETOWN_BUG
+#ifdef F_GETOWN                /* F_SETFL does not imply existence of F_GETOWN */
   if (interrupt_input)
     {
       old_fcntl_owner = fcntl (0, F_GETOWN, 0);
@@ -1121,6 +1230,7 @@ init_sys_modes ()
       init_sigio ();
     }
 #endif /* F_GETOWN */
+#endif /* F_SETOWN_BUG */
 #endif /* F_SETFL */
 
 #ifdef BSD4_1
@@ -1262,13 +1372,15 @@ reset_sys_modes ()
 #endif
 
 #ifdef F_SETFL
-#ifdef F_SETOWN                /* F_SETFL does not imply existance of F_SETOWN */
+#ifndef F_SETOWN_BUG
+#ifdef F_SETOWN                /* F_SETFL does not imply existence of F_SETOWN */
   if (interrupt_input)
     {
       reset_sigio ();
       fcntl (0, F_SETOWN, old_fcntl_owner);
     }
 #endif /* F_SETOWN */
+#endif /* F_SETOWN_BUG */
 #endif /* F_SETFL */
 #ifdef BSD4_1
   if (interrupt_input)
@@ -1281,6 +1393,10 @@ reset_sys_modes ()
 #ifdef AIX
   hft_reset ();
 #endif
+
+#ifdef BSD
+  widen_foreground_group ();
+#endif
 }
 \f
 #ifdef HAVE_PTYS
@@ -1712,6 +1828,17 @@ static struct utsname get_system_name_name;
 #endif /* not HAVE_GETHOSTNAME */
 #endif /* USG */
 
+#ifndef BSD4_1
+#ifndef USG
+#ifndef VMS
+#ifdef HAVE_SOCKETS
+#include <sys/socket.h>
+#include <netdb.h>
+#endif /* HAVE_SOCKETS */
+#endif /* not VMS */
+#endif /* not USG */
+#endif /* not BSD4_1 */
+
 char *
 get_system_name ()
 {
@@ -1742,6 +1869,20 @@ get_system_name ()
   strcpy (system_name_saved, sp);
 #else /* not VMS */
   gethostname (system_name_saved, sizeof (system_name_saved));
+#ifdef HAVE_SOCKETS
+  /* Turn the hostname into the official, fully-qualified hostname.
+     Don't do this if we're going to dump; this can confuse system
+     libraries on some machines and make the dumped emacs core dump. */
+#ifndef CANNOT_DUMP
+  if (initialized)
+#endif /* not CANNOT_DUMP */
+    {
+      struct hostent *hp;
+      hp = gethostbyname (system_name_saved);
+      if (hp && strlen (hp->h_name) < sizeof(system_name_saved))
+       strcpy (system_name_saved, hp->h_name);
+    }
+#endif /* HAVE_SOCKETS */
 #endif /* not VMS */
   return system_name_saved;
 #endif /* not USG, not 4.1 */
@@ -2088,7 +2229,7 @@ sys_signal (int signal_number, signal_handler_t action)
 #else
   sigemptyset (&new_action.sa_mask);
   new_action.sa_handler = action;
-  new_action.sa_flags = NULL;
+  new_action.sa_flags = 0;
   sigaction (signal_number, &new_action, &old_action);
   return (old_action.sa_handler);
 #endif /* DGUX */
@@ -2321,7 +2462,7 @@ sys_abort ()
 #ifdef VMS
 #ifdef LINK_CRTL_SHARE
 #ifdef SHAREABLE_LIB_BUG
-/* Variables declared noshare and initialized in shareable libraries
+/* Variables declared noshare and initialized in sharable libraries
    cannot be shared.  The VMS linker incorrectly forces you to use a private
    version which is uninitialized... If not for this "feature", we
    could use the C library definition of sys_nerr and sys_errlist. */
@@ -2431,6 +2572,19 @@ sys_write (fildes, buf, nbyte)
 
 #endif /* INTERRUPTIBLE_IO */
 \f
+#ifndef HAVE_VFORK
+
+/*
+ *     Substitute fork for vfork on USG flavors.
+ */
+
+vfork ()
+{
+  return (fork ());
+}
+
+#endif /* not HAVE_VFORK */
+\f
 #ifdef USG
 /*
  *     All of the following are for USG.
@@ -2442,7 +2596,7 @@ sys_write (fildes, buf, nbyte)
  *     to names for our own functions in sysdep.c that do the system call
  *     with retries.  Actually, for portability reasons, it is good
  *     programming practice, as this example shows, to limit all actual
- *     system calls to a single occurance in the source.  Sure, this
+ *     system calls to a single occurrence in the source.  Sure, this
  *     adds an extra level of function call overhead but it is almost
  *     always negligible.   Fred Fish, Unisoft Systems Inc.
  */
@@ -2508,7 +2662,7 @@ char *sys_siglist[NSIG + 1] =
 #endif /* not AIX */
   0
   };
-#endif HAVE_SYS_SIGLIST
+#endif /* HAVE_SYS_SIGLIST */
 
 /*
  *     Warning, this function may not duplicate 4.2 action properly
@@ -2552,8 +2706,8 @@ getwd (pathname)
 #ifndef HAVE_RENAME
 
 rename (from, to)
-     char *from;
-     char *to;
+     const char *from;
+     const char *to;
 {
   if (access (from, 0) == 0)
     {
@@ -2567,19 +2721,6 @@ rename (from, to)
 
 #endif
 
-#ifndef HAVE_VFORK
-
-/*
- *     Substitute fork for vfork on USG flavors.
- */
-
-vfork ()
-{
-  return (fork ());
-}
-
-#endif /* not HAVE_VFORK */
-
 #ifdef MISSING_UTIMES
 
 /* HPUX (among others) sets HAVE_TIMEVAL but does not implement utimes.  */
@@ -2679,7 +2820,8 @@ gettimeofday (tp, tzp)
 
   tp->tv_sec = time ((long *)0);    
   tp->tv_usec = 0;
-  tzp->tz_minuteswest = -1;
+  if (tzp != 0)
+    tzp->tz_minuteswest = -1;
 }
  
 #endif
@@ -2727,7 +2869,7 @@ char *sys_siglist[NSIG + 1] =
   "power-fail restart",                         /* 19 SIGPWR    */
   "window size changed",                /* 20 SIGWINCH  */
   "undefined",                          /* 21           */
-  "pollable event occured",             /* 22 SIGPOLL   */
+  "pollable event occurred",            /* 22 SIGPOLL   */
   "sendable stop signal not from tty",  /* 23 SIGSTOP   */
   "stop signal from tty",               /* 24 SIGSTP    */
   "continue a stopped process",                 /* 25 SIGCONT   */
@@ -2781,16 +2923,22 @@ char *sys_siglist[NSIG + 1] =
 
 #include <dirent.h>
 
-#ifndef AIX
+#ifndef HAVE_CLOSEDIR
 int
 closedir (dirp)
      register DIR *dirp;              /* stream from opendir */
 {
   sys_close (dirp->dd_fd);
-  xfree ((char *) dirp->dd_buf);       /* directory block defined in <dirent.h> */
+
+  /* Some systems (like Solaris) allocate the buffer and the DIR all
+     in one block.  Why in the world are we freeing this ourselves
+     anyway?  */
+#if ! (defined (sun) && defined (USG5_4))
+  xfree ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
+#endif
   xfree ((char *) dirp);
 }
-#endif /* not AIX */
+#endif /* not HAVE_CLOSEDIR */
 #endif /* SYSV_SYSTEM_DIR */
 
 #ifdef NONSYSTEM_DIR_LIBRARY
@@ -2936,6 +3084,134 @@ readdirver (dirp)
 #endif /* VMS */
 
 #endif /* NONSYSTEM_DIR_LIBRARY */
+
+\f
+/* mkdir and rmdir functions, for systems which don't have them.  */
+
+#ifndef HAVE_MKDIR
+/*
+ * Written by Robert Rother, Mariah Corporation, August 1985.
+ *
+ * If you want it, it's yours.  All I ask in return is that if you
+ * figure out how to do this in a Bourne Shell script you send me
+ * a copy.
+ *                                     sdcsvax!rmr or rmr@uscd
+ *
+ * Severely hacked over by John Gilmore to make a 4.2BSD compatible
+ * subroutine. 11Mar86; hoptoad!gnu
+ *
+ * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
+ * subroutine didn't return EEXIST.  It does now.
+ */
+
+/*
+ * Make a directory.
+ */
+int
+mkdir (dpath, dmode)
+     char *dpath;
+     int dmode;
+{
+  int cpid, status, fd;
+  struct stat statbuf;
+
+  if (stat (dpath, &statbuf) == 0)
+    {
+      errno = EEXIST;          /* Stat worked, so it already exists */
+      return -1;
+    }
+
+  /* If stat fails for a reason other than non-existence, return error */
+  if (errno != ENOENT)
+    return -1;
+
+  synch_process_alive = 1;
+  switch (cpid = fork ())
+    {
+
+    case -1:                   /* Error in fork */
+      return (-1);             /* Errno is set already */
+
+    case 0:                    /* Child process */
+      /*
+                * Cheap hack to set mode of new directory.  Since this
+                * child process is going away anyway, we zap its umask.
+                * FIXME, this won't suffice to set SUID, SGID, etc. on this
+                * directory.  Does anybody care?
+                */
+      status = umask (0);      /* Get current umask */
+      status = umask (status | (0777 & ~dmode));       /* Set for mkdir */
+      fd = sys_open("/dev/null", 2);
+      if (fd >= 0)
+        {
+         dup2 (fd, 0);
+         dup2 (fd, 1);
+         dup2 (fd, 2);
+        }
+      execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
+      _exit (-1);              /* Can't exec /bin/mkdir */
+
+    default:                   /* Parent process */
+      wait_for_termination (cpid);
+    }
+
+  if (synch_process_death != 0 || synch_process_retcode != 0)
+    {
+      errno = EIO;             /* We don't know why, but */
+      return -1;               /* /bin/mkdir failed */
+    }
+
+  return 0;
+}
+#endif /* not HAVE_MKDIR */
+
+#ifndef HAVE_RMDIR
+int
+rmdir (dpath)
+     char *dpath;
+{
+  int cpid, status, fd;
+  struct stat statbuf;
+
+  if (stat (dpath, &statbuf) != 0)
+    {
+      /* Stat just set errno.  We don't have to */
+      return -1;
+    }
+
+  synch_process_alive = 1;
+  switch (cpid = fork ())
+    {
+
+    case -1:                   /* Error in fork */
+      return (-1);             /* Errno is set already */
+
+    case 0:                    /* Child process */
+      fd = sys_open("/dev/null", 2);
+      if (fd >= 0)
+        {
+         dup2 (fd, 0);
+         dup2 (fd, 1);
+         dup2 (fd, 2);
+        }
+      execl ("/bin/rmdir", "rmdir", dpath, (char *) 0);
+      _exit (-1);              /* Can't exec /bin/mkdir */
+
+    default:                   /* Parent process */
+      wait_for_termination (cpid);
+    }
+
+  if (synch_process_death != 0 || synch_process_retcode != 0)
+    {
+      errno = EIO;             /* We don't know why, but */
+      return -1;               /* /bin/rmdir failed */
+    }
+
+  return 0;
+}
+#endif /* !HAVE_RMDIR */
+
+
 \f
 /* Functions for VMS */
 #ifdef VMS
@@ -3499,7 +3775,7 @@ creat_copy_attrs (old, new)
 sys_creat (va_alist)
      va_dcl
 {
-  va_list list_incrementor;
+  va_list list_incrementer;
   char *name;
   int mode;
   int rfd;                     /* related file descriptor */
@@ -3513,12 +3789,12 @@ sys_creat (va_alist)
   extern int vms_stmlf_recfm;
 
   va_count (count);
-  va_start (list_incrementor);
-  name = va_arg (list_incrementor, char *);
-  mode = va_arg (list_incrementor, int);
+  va_start (list_incrementer);
+  name = va_arg (list_incrementer, char *);
+  mode = va_arg (list_incrementer, int);
   if (count > 2)
-    rfd = va_arg (list_incrementor, int);
-  va_end (list_incrementor);
+    rfd = va_arg (list_incrementer, int);
+  va_end (list_incrementer);
   if (count > 2)
     {
       /* Use information from the related file descriptor to set record
@@ -4027,7 +4303,7 @@ rename (from, to)
    are renaming.
 
    We could use the chmod function, but Eunichs uses 3 bits per user category
-   to describe the protection, and VMS uses 4 (write and delete are seperate
+   to describe the protection, and VMS uses 4 (write and delete are separate
    bits).  To maintain portability, the VMS implementation of `chmod' wires
    the W and D bits together.  */