(get_system_name): Remove restriction on hostname size.
[bpt/emacs.git] / src / sysdep.c
index cc003ee..267016f 100644 (file)
@@ -1,11 +1,11 @@
 /* Interfaces to system-dependent kernel and library entries.
-   Copyright (C) 1985, 1986, 1987, 1988, 1993 Free Software Foundation, Inc.
+   Copyright (C) 1985, 86, 87, 88, 93, 94 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -21,7 +21,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <signal.h>
 #include <setjmp.h>
 
-#include "config.h"
+#include <config.h>
 #include "lisp.h"
 #include "blockinput.h"
 #undef NULL
@@ -64,11 +64,15 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <sys/stat.h>
 #include <errno.h>
 
-extern int errno;
-#ifndef VMS
-extern char *sys_errlist[];
+#ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
+#include <dos.h>
+#include "dosfns.h"
+#include "msdos.h"
+#include <sys/param.h>
 #endif
 
+extern int errno;
+
 #ifdef VMS
 #include <rms.h>
 #include <ttdef.h>
@@ -104,21 +108,20 @@ 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
 
+#ifndef MSDOS
 #include <sys/ioctl.h>
+#endif
 #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
@@ -158,6 +161,15 @@ extern int quit_char;
 #include "syssignal.h"
 #include "systime.h"
 
+/* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits.  */
+#ifndef LPASS8
+#define LPASS8 0
+#endif
+
+#ifdef BSD4_1
+#define LNOFLSH 0100000
+#endif
+
 static int baud_convert[] =
 #ifdef BAUD_CONVERT
   BAUD_CONVERT;
@@ -171,10 +183,21 @@ static int baud_convert[] =
 extern short ospeed;
 
 /* The file descriptor for Emacs's input terminal.
-   Under Unix, this is always left zero;
+   Under Unix, this is normaly zero except when using X;
    under VMS, we place the input channel number here.
    This allows us to write more code that works for both VMS and Unix.  */
 static int input_fd;
+\f
+/* Specify a different file descriptor for further input operations.  */
+
+void
+change_input_fd (fd)
+     int fd;
+{
+  input_fd = fd;
+}
+
+/* Discard pending input on descriptor input_fd.  */
 
 discard_tty_input ()
 {
@@ -197,36 +220,47 @@ discard_tty_input ()
 #ifdef APOLLO
   {
     int zero = 0;
-    ioctl (0, TIOCFLUSH, &zero);
+    ioctl (input_fd, TIOCFLUSH, &zero);
   }
 #else /* not Apollo */
+#ifdef MSDOS   /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
+  while (dos_keyread () != -1)
+       ;
+#else /* not MSDOS */
   EMACS_GET_TTY (input_fd, &buf);
   EMACS_SET_TTY (input_fd, &buf, 0);
+#endif /* not MSDOS */
 #endif /* not Apollo */
 #endif /* not VMS */
 }
 
 #ifdef SIGTSTP
 
+/* Arrange for character C to be read as the next input from
+   the terminal.  */
+
 stuff_char (c)
      char c;
 {
 /* Should perhaps error if in batch mode */
 #ifdef TIOCSTI
-  ioctl (0, TIOCSTI, &c);
+  ioctl (input_fd, TIOCSTI, &c);
 #else /* no TIOCSTI */
-  error ("Cannot stuff terminal input characters in this version of Unix.");
+  error ("Cannot stuff terminal input characters in this version of Unix");
 #endif /* no TIOCSTI */
 }
 
 #endif /* SIGTSTP */
-
+\f
 init_baud_rate ()
 {
   if (noninteractive)
     ospeed = 0;
   else
     {
+#ifdef MSDOS
+    ospeed = 15;
+#else
 #ifdef VMS
       struct sensemode sg;
 
@@ -237,16 +271,16 @@ init_baud_rate ()
 #ifdef HAVE_TERMIOS
       struct termios sg;
 
-      sg.c_cflag = (sg.c_cflag & ~CBAUD) | B9600;
-      tcgetattr (0, &sg);
-      ospeed = sg.c_cflag & CBAUD;
+      sg.c_cflag = B9600;
+      tcgetattr (input_fd, &sg);
+      ospeed = cfgetospeed (&sg);
 #else /* neither VMS nor TERMIOS */
 #ifdef HAVE_TERMIO
       struct termio sg;
 
-      sg.c_cflag = (sg.c_cflag & ~CBAUD) | B9600;
+      sg.c_cflag = B9600;
 #ifdef HAVE_TCATTR
-      tcgetattr (0, &sg);
+      tcgetattr (input_fd, &sg);
 #else
       ioctl (input_fd, TCGETA, &sg);
 #endif
@@ -255,11 +289,13 @@ init_baud_rate ()
       struct sgttyb sg;
       
       sg.sg_ospeed = B9600;
-      ioctl (0, TIOCGETP, &sg);
+      if (ioctl (input_fd, TIOCGETP, &sg) < 0)
+       abort ();
       ospeed = sg.sg_ospeed;
 #endif /* not HAVE_TERMIO */
 #endif /* not HAVE_TERMIOS */
 #endif /* not VMS */
+#endif /* not MSDOS */
     }
    
   baud_rate = (ospeed < sizeof baud_convert / sizeof baud_convert[0]
@@ -277,7 +313,7 @@ set_exclusive_use (fd)
 #endif
   /* Ok to do nothing if this feature does not exist */
 }
-
+\f
 #ifndef subprocesses
 
 wait_without_blocking ()
@@ -314,7 +350,7 @@ wait_for_termination (pid)
       status = SYS$FORCEX (&pid, 0, 0);
       break;
 #else /* not VMS */
-#if (defined (BSD) && !defined (LINUX)) || (defined (HPUX) && !defined (HPUX_5))
+#if defined (BSD) || (defined (HPUX) && !defined (HPUX_5))
       /* Note that kill returns -1 even if the process is just a zombie now.
         But inevitably a SIGCHLD interrupt should be generated
         and child_sig will do wait3 and make the process go away. */
@@ -333,12 +369,21 @@ wait_for_termination (pid)
        sleep (1);
       else
        sigpause (SIGEMPTYMASK);
-#else /* not BSD, not LINUX, and not HPUX version >= 6 */
-#if defined (UNIPLUS) || defined (LINUX)
+#else /* not BSD, and not HPUX version >= 6 */
+#if defined (UNIPLUS)
       if (0 > kill (pid, 0))
        break;
       wait (0);
-#else /* neither BSD nor UNIPLUS nor LINUX: random sysV */
+#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 +400,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 */
@@ -400,7 +446,7 @@ flush_pending_output (channel)
 #endif
 #endif
 }
-
+\f
 #ifndef VMS
 /*  Set up the terminal at the other end of a pseudo-terminal that
     we will be controlling an inferior through.
@@ -410,6 +456,7 @@ flush_pending_output (channel)
 child_setup_tty (out)
      int out;
 {
+#ifndef MSDOS
   struct emacs_tty s;
 
   EMACS_GET_TTY (out, &s);
@@ -425,8 +472,9 @@ child_setup_tty (out)
                                   input */
   s.main.c_oflag &= ~OLCUC;    /* Disable map of lower case to upper on
                                   output */
+  s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
 #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 +498,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 */
 
@@ -462,8 +521,10 @@ child_setup_tty (out)
 
   s.main.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE
                       | CBREAK | TANDEM);
+  s.main.sg_flags |= LPASS8;
   s.main.sg_erase = 0377;
   s.main.sg_kill = 0377;
+  s.lmode = LLITOUT | s.lmode;        /* Don't strip 8th bit */
 
 #endif /* not HAVE_TERMIO */
 
@@ -479,6 +540,7 @@ child_setup_tty (out)
     ioctl (out, FIOASYNC, &zero);
   }
 #endif /* RTU */
+#endif /* not MSDOS */
 }
 #endif /* not VMS */
 
@@ -490,7 +552,7 @@ setpgrp_of_tty (pid)
 {
   EMACS_SET_TTY_PGRP (input_fd, &pid);
 }
-
+\f
 /* Record a signal code and the handler for it.  */
 struct save_signal
 {
@@ -502,6 +564,10 @@ struct save_signal
 
 sys_suspend ()
 {
+#ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida */
+  int st;
+  char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS.  */
+#endif
 #ifdef VMS
   /* "Foster" parentage allows emacs to return to a subprocess that attached
      to the current emacs as a cheaper than starting a whole new process.  This
@@ -543,9 +609,12 @@ sys_suspend ()
     }
   return -1;
 #else
-#ifdef SIGTSTP
+#if defined(SIGTSTP) && !defined(MSDOS)
 
-  EMACS_KILLPG (getpgrp (0), SIGTSTP);
+  {
+    int pgrp = EMACS_GETPGRP (0);
+    EMACS_KILLPG (pgrp, SIGTSTP);
+  }
 
 #else /* No SIGTSTP */
 #ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
@@ -576,9 +645,13 @@ sys_suspend ()
     {
       char *sh;
 
+#ifdef MSDOS   /* MW, Aug 1993 */
+      getwd (oldwd);
+#endif
       sh = (char *) egetenv ("SHELL");
       if (sh == 0)
        sh = "sh";
+
       /* Use our buffer's default directory for the subshell.  */
       {
        Lisp_Object dir;
@@ -589,7 +662,7 @@ sys_suspend ()
           which somehow wedges the hp compiler.  So instead... */
 
        dir = intern ("default-directory");
-       /* Can't use NULL */
+       /* Can't use NILP */
        if (XFASTINT (Fboundp (dir)) == XFASTINT (Qnil))
          goto xyzzy;
        dir = Fsymbol_value (dir);
@@ -617,9 +690,16 @@ sys_suspend ()
       }
 #endif
 
+#ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida */
+      st = system (sh);
+      chdir (oldwd);
+      if (st)
+        report_file_error ("Can't execute subshell", Fcons (build_string (sh), Qnil));
+#else /* not MSDOS */
       execlp (sh, sh, 0);
       write (1, "Can't execute subshell", 22);
       _exit (1);
+#endif /* not MSDOS */
     }
 
   save_signal_handlers (saved_handlers);
@@ -660,7 +740,7 @@ int old_fcntl_flags;
 init_sigio ()
 {
 #ifdef FASYNC
-  old_fcntl_flags = fcntl (0, F_GETFL, 0) & ~FASYNC;
+  old_fcntl_flags = fcntl (input_fd, F_GETFL, 0) & ~FASYNC;
 #endif
   request_sigio ();
 }
@@ -670,14 +750,14 @@ 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 ()
 {
 #ifdef SIGWINCH
   sigunblock (sigmask (SIGWINCH));
 #endif
-  fcntl (0, F_SETFL, old_fcntl_flags | FASYNC);
+  fcntl (input_fd, F_SETFL, old_fcntl_flags | FASYNC);
 
   interrupts_deferred = 0;
 }
@@ -687,7 +767,7 @@ unrequest_sigio ()
 #ifdef SIGWINCH
   sigblock (sigmask (SIGWINCH));
 #endif
-  fcntl (0, F_SETFL, old_fcntl_flags);
+  fcntl (input_fd, F_SETFL, old_fcntl_flags);
   interrupts_deferred = 1;
 }
 
@@ -697,7 +777,7 @@ unrequest_sigio ()
 request_sigio ()
 {
   int on = 1;
-  ioctl (0, FIOASYNC, &on);
+  ioctl (input_fd, FIOASYNC, &on);
   interrupts_deferred = 0;
 }
 
@@ -705,12 +785,38 @@ unrequest_sigio ()
 {
   int off = 0;
 
-  ioctl (0, FIOASYNC, &off);
+  ioctl (input_fd, FIOASYNC, &off);
   interrupts_deferred = 1;
 }
 
 #else /* not FASYNC, not STRIDE */
  
+#ifdef _CX_UX
+
+#include <termios.h>
+
+request_sigio ()
+{
+  int on = 1;
+  sigset_t st;
+
+  sigemptyset(&st);
+  sigaddset(&st, SIGIO);
+  ioctl (input_fd, FIOASYNC, &on);
+  interrupts_deferred = 0;
+  sigprocmask(SIG_UNBLOCK, &st, (sigset_t *)0);
+}
+
+unrequest_sigio ()
+{
+  int off = 0;
+
+  ioctl (input_fd, FIOASYNC, &off);
+  interrupts_deferred = 1;
+}
+
+#else /* ! _CX_UX */
+
 request_sigio ()
 {
   croak ("request_sigio");
@@ -721,10 +827,59 @@ unrequest_sigio ()
   croak ("unrequest_sigio");
 }
  
+#endif /* _CX_UX */
 #endif /* STRIDE */
 #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 (input_fd, &me);
+  setpgrp (0, me);
+}
+
+/* Set the tty to our original foreground group.  */
+widen_foreground_group ()
+{
+  if (inherited_pgroup != getpid ())
+    EMACS_SET_TTY_PGRP (input_fd, &inherited_pgroup);
+  setpgrp (0, inherited_pgroup);
+}
+
+#endif
+\f
 /* Getting and setting emacs_tty structures.  */
 
 /* Set *TC to the parameters associated with the terminal FD.
@@ -756,22 +911,23 @@ emacs_get_tty (fd, settings)
     return -1;
 
 #else
+#ifndef MSDOS
   /* I give up - I hope you have the BSD ioctls.  */
   if (ioctl (fd, TIOCGETP, &settings->main) < 0)
     return -1;
-
+#endif /* not MSDOS */
 #endif
 #endif
 #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 +951,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 +959,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 +974,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
@@ -837,22 +1003,24 @@ emacs_set_tty (fd, settings, waitp)
     return -1;
 
 #else
+#ifndef MSDOS
   /* I give up - I hope you have the BSD ioctls.  */
   if (ioctl (fd, (waitp) ? TIOCSETP : TIOCSETN, &settings->main) < 0)
     return -1;
+#endif /* not MSDOS */
 
 #endif
 #endif
 #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 +1042,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 +1058,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 +1111,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 +1174,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
@@ -1029,10 +1216,12 @@ init_sys_modes ()
        tty.main.tt_char &= ~TT$M_TTSYNC;
       tty.main.tt2_char |= TT2$M_PASTHRU | TT2$M_XON;
 #else /* not VMS (BSD, that is) */
+#ifndef MSDOS
       tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS);
       if (meta_key)
        tty.main.sg_flags |= ANYP;
       tty.main.sg_flags |= interrupt_input ? RAW : CBREAK;
+#endif
 #endif /* not VMS (BSD, that is) */
 #endif /* not HAVE_TERMIO */
 
@@ -1042,7 +1231,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;
@@ -1053,27 +1242,27 @@ init_sys_modes ()
          tty.tchars.t_stopc = '\023';
        }
 
-/* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits.  */
-#ifndef LPASS8
-#define LPASS8 0
-#endif
-
-#ifdef BSD4_1
-#define LNOFLSH 0100000
-#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 */
+#ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */
+      internal_terminal_init ();
+      dos_ttraw ();
+#endif
 
       EMACS_SET_TTY (input_fd, &tty, 0);
 
@@ -1081,11 +1270,11 @@ init_sys_modes ()
         we have an unlocked terminal at the start. */
 
 #ifdef TCXONC
-      if (!flow_control) ioctl (0, TCXONC, 1);
+      if (!flow_control) ioctl (input_fd, TCXONC, 1);
 #endif
 #ifndef APOLLO
 #ifdef TIOCSTART
-      if (!flow_control) ioctl (0, TIOCSTART, 0);
+      if (!flow_control) ioctl (input_fd, TIOCSTART, 0);
 #endif
 #endif
 
@@ -1113,14 +1302,16 @@ 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);
-      fcntl (0, F_SETOWN, getpid ());
+      old_fcntl_owner = fcntl (input_fd, F_GETOWN, 0);
+      fcntl (input_fd, F_SETOWN, getpid ());
       init_sigio ();
     }
 #endif /* F_GETOWN */
+#endif /* F_SETOWN_BUG */
 #endif /* F_SETFL */
 
 #ifdef BSD4_1
@@ -1213,10 +1404,14 @@ get_frame_size (widthp, heightp)
   *widthp = tty.scr_wid;
   *heightp = tty.scr_len;
 
+#else
+#ifdef MSDOS
+  *widthp = ScreenCols ();
+  *heightp = ScreenRows ();
 #else /* system doesn't know size */
-
   *widthp = 0;
   *heightp = 0;
+#endif
 
 #endif /* not VMS */
 #endif /* not SunOS-style */
@@ -1262,13 +1457,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);
+      fcntl (input_fd, F_SETOWN, old_fcntl_owner);
     }
 #endif /* F_SETOWN */
+#endif /* F_SETOWN_BUG */
 #endif /* F_SETFL */
 #ifdef BSD4_1
   if (interrupt_input)
@@ -1278,9 +1475,17 @@ reset_sys_modes ()
   while (EMACS_SET_TTY (input_fd, &old_tty, 0) < 0 && errno == EINTR)
     ;
 
+#ifdef MSDOS   /* Demacs 1.1.2 91/10/20 Manabu Higashida */
+  dos_ttcooked ();
+#endif
+
 #ifdef AIX
   hft_reset ();
 #endif
+
+#ifdef BSD
+  widen_foreground_group ();
+#endif
 }
 \f
 #ifdef HAVE_PTYS
@@ -1462,6 +1667,7 @@ wait_for_kbd_input ()
          if (dsp)
            {
              update_mode_lines++;
+             prepare_menu_bars ();
              redisplay_preserve_echo_area ();
            }
        }
@@ -1695,7 +1901,7 @@ end_of_data ()
 
 #endif /* not CANNOT_DUMP */
 \f
-/* Get_system_name returns as its value
+/* get_system_name returns as its value
  a string for the Lisp function system-name to return. */
 
 #ifdef BSD4_1
@@ -1704,68 +1910,117 @@ end_of_data ()
 
 /* Can't have this within the function since `static' is #defined to 
    nothing for some USG systems.  */
-#ifdef USG
-#ifdef HAVE_GETHOSTNAME
-static char get_system_name_name[256];
-#else /* not HAVE_GETHOSTNAME */
-static struct utsname get_system_name_name;
-#endif /* not HAVE_GETHOSTNAME */
-#endif /* USG */
+static char *get_system_name_cache;
+static int get_system_name_predump_p;
+
+#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 ()
 {
-#ifdef USG
-#ifdef HAVE_GETHOSTNAME
-  gethostname (get_system_name_name, sizeof (get_system_name_name));
-  return get_system_name_name;
-#else /* not HAVE_GETHOSTNAME */
-  uname (&get_system_name_name);
-  return (get_system_name_name.nodename);
-#endif /* not HAVE_GETHOSTNAME */
-#else /* Not USG */
 #ifdef BSD4_1
   return sysname;
-#else /* not USG, not 4.1 */
-  static char system_name_saved[32];
-#ifdef VMS
-  char *sp;
-  if ((sp = egetenv ("SYS$NODE")) == 0)
-    sp = "vax-vms";
-  else
+#else
+#ifndef CANNOT_DUMP
+  /* If the cached value is from before the dump, and we've dumped
+     since then, then the cached value is no good. */
+  if (get_system_name_predump_p && initialized && get_system_name_cache)
     {
-      char *end;
-
-      if ((end = index (sp, ':')) != 0)
-       *end = '\0';
+      xfree (get_system_name_cache);
+      get_system_name_cache = 0;
     }
-  strcpy (system_name_saved, sp);
-#else /* not VMS */
-  gethostname (system_name_saved, sizeof (system_name_saved));
-#endif /* not VMS */
-  return system_name_saved;
-#endif /* not USG, not 4.1 */
-#endif /* not USG */
-}
-
+#endif
+  if (!get_system_name_cache)
+    {
+      /* No cached value, so get the name from the system.  */
 #ifdef VMS
+      char *sp;
+      if ((sp = egetenv ("SYS$NODE")) == 0)
+       sp = "vax-vms";
+      else
+       {
+         char *end;
+
+         if ((end = index (sp, ':')) != 0)
+           *end = '\0';
+       }
+      get_system_name_cache = (char *) xmalloc (strlen (sp) + 1);
+      strcpy (get_system_name_cache, sp);
+#else
 #ifndef HAVE_GETHOSTNAME
-void gethostname(buf, len)
-    char *buf;
-    int len;
-{
-    char *s;
-    s = getenv ("SYS$NODE");
-    if (s == NULL)
-        buf[0] = '\0';
-    else {
-        strncpy (buf, s, len - 2);
-        buf[len - 1] = '\0';
-    } /* else */
-} /* static void gethostname */
-#endif /* ! HAVE_GETHOSTNAME */
-#endif /* VMS */
+      struct utsname uts;
+      uname (&uts);
+      get_system_name_cache = (char *) xmalloc (strlen (uts.nodename) + 1);
+      strcpy (get_system_name_cache, uts.nodename);
+#else /* HAVE_GETHOSTNAME */
+      {
+       int hostname_size = 256;
+       char *hostname = (char *) xmalloc (hostname_size);
+
+       /* Try to get the host name; if the buffer is too short, try
+          again.  Apparently, the only indication gethostname gives of
+          whether the buffer was large enough is the presence or absence
+          of a '\0' in the string.  Eech.  */
+       for (;;)
+         {
+           gethostname (hostname, hostname_size - 1);
+           hostname[hostname_size - 1] = '\0';
+
+           /* Was the buffer large enough for the '\0'?  */
+           if (strlen (hostname) < hostname_size - 1)
+             break;
 
+           hostname_size <<= 1;
+           hostname = (char *) xrealloc (hostname, hostname_size);
+         }
+       get_system_name_cache = hostname;
+#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 = gethostbyname (hostname);
+           if (hp)
+             {
+               char *fqdn = hp->h_name;
+               if (!index (fqdn, '.'))
+                 {
+                   /* We still don't have a fully qualified domain name.
+                      Try to find one in the list of alternate names */
+                   char **alias = hp->h_aliases;
+                   while (*alias && !index (*alias, '.'))
+                     alias++;
+                   if (*alias)
+                     fqdn = *alias;
+                 }
+               hostname = (char *) xrealloc (hostname, strlen (fqdn) + 1);
+               strcpy (hostname, fqdn);
+             }
+         }
+#endif /* HAVE_SOCKETS */
+       get_system_name_cache = hostname;
+      }
+#endif /* HAVE_GETHOSTNAME */
+#endif /* VMS */
+#ifndef CANNOT_DUMP
+      get_system_name_predump_p = !initialized;
+#endif
+    }
+  return (get_system_name_cache);
+#endif /* BSD4_1 */
+}
 \f
 #ifndef VMS
 #ifndef HAVE_SELECT
@@ -1866,6 +2121,9 @@ select (nfds, rfds, wfds, efds, timeout)
 #ifdef FIONREAD
                      status = ioctl (fd, FIONREAD, &avail);
 #else /* no FIONREAD */
+#ifdef MSDOS
+                     abort (); /* I don't think we need it.  */
+#else /* not MSDOS */
                      /* Hoping it will return -1 if nothing available
                         or 0 if all 0 chars requested are read.  */
                      if (proc_buffered_char[fd] >= 0)
@@ -1876,6 +2134,7 @@ select (nfds, rfds, wfds, efds, timeout)
                          if (avail > 0)
                            proc_buffered_char[fd] = buf;
                        }
+#endif /* not MSDOS */
 #endif /* no FIONREAD */
                    }
                  if (status >= 0 && avail > 0)
@@ -1896,6 +2155,10 @@ select (nfds, rfds, wfds, efds, timeout)
       while (select_alarmed == 0 && *local_timeout != 0
             && process_tick == update_tick)
        {
+#ifdef MSDOS
+         sleep_or_kbd_hit (SELECT_PAUSE, (orfds & 1) != 0);
+         select_alarm ();
+#else /* not MSDOS */
          /* If we are interested in terminal input,
             wait by reading the terminal.
             That makes instant wakeup for terminal input at least.  */
@@ -1907,6 +2170,7 @@ select (nfds, rfds, wfds, efds, timeout)
            }
          else
            pause ();
+#endif /* not MSDOS */
        }
       (*local_timeout) -= SELECT_PAUSE;
       /* Reset the old alarm if there was one */
@@ -1939,34 +2203,60 @@ select (nfds, rfds, wfds, efds, timeout)
 
 read_input_waiting ()
 {
-  char buf[256 * BUFFER_SIZE_FACTOR];
   struct input_event e;
   int nread, i;
   extern int quit_char;
 
   if (read_socket_hook)
     {
+      struct input_event buf[256];
+
       read_alarm_should_throw = 0;
       if (! setjmp (read_alarm_throw))
-       nread = (*read_socket_hook) (0, buf, 256 * BUFFER_SIZE_FACTOR, 1, 0);
+       nread = (*read_socket_hook) (0, buf, 256, 1, 0);
       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
+             && XINT(buf[i].code) == quit_char)
+           break;
+       }
     }
   else
-    nread = read (fileno (stdin), buf, 1);
-
-  /* Scan the chars for C-g and store them in kbd_buffer.  */
-  e.kind = ascii_keystroke;
-  e.frame_or_window = selected_frame;
-  e.modifiers = 0;
-  for (i = 0; i < nread; i++)
     {
-      XSET (e.code, Lisp_Int, buf[i]);
-      kbd_buffer_store_event (&e);
-      /* Don't look at input that follows a C-g too closely.
-        This reduces lossage due to autorepeat on C-g.  */
-      if (buf[i] == quit_char)
-       break;
+      char buf[3];
+      nread = read (fileno (stdin), buf, 1);
+
+      /* Scan the chars for C-g and store them in kbd_buffer.  */
+      e.kind = ascii_keystroke;
+      e.frame_or_window = selected_frame;
+      e.modifiers = 0;
+      for (i = 0; i < nread; i++)
+       {
+         /* Convert chars > 0177 to meta events if desired.
+            We do this under the same conditions that read_avail_input does.  */
+         if (read_socket_hook == 0)
+           {
+             /* If the user says she has a meta key, then believe her. */
+             if (meta_key == 1 && (buf[i] & 0x80))
+               e.modifiers = meta_modifier;
+             if (meta_key != 2)
+               buf[i] &= ~0x80;
+           }
+
+         XSET (e.code, Lisp_Int, buf[i]);
+         kbd_buffer_store_event (&e);
+         /* Don't look at input that follows a C-g too closely.
+            This reduces lossage due to autorepeat on C-g.  */
+         if (buf[i] == quit_char)
+           break;
+       }
     }
 }
 
@@ -2088,7 +2378,14 @@ 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;
+#ifdef SA_RESTART
+  /* Emacs mostly works better with restartable system services. If this
+   * flag exists, we probably want to turn it on here.
+   */
+  new_action.sa_flags = SA_RESTART;
+#else
+  new_action.sa_flags = 0;
+#endif
   sigaction (signal_number, &new_action, &old_action);
   return (old_action.sa_handler);
 #endif /* DGUX */
@@ -2148,6 +2445,8 @@ sys_sigsetmask (sigset_t new_mask)
 \f
 #ifndef BSTRING
 
+#ifndef bzero
+
 void
 bzero (b, length)
      register char *b;
@@ -2170,6 +2469,9 @@ bzero (b, length)
 #endif /* not VMS */
 }
 
+#endif /* no bzero */
+
+#ifndef bcopy
 /* Saying `void' requires a declaration, above, where bcopy is used
    and that declaration causes pain for systems where bcopy is a macro.  */
 bcopy (b1, b2, length)
@@ -2193,7 +2495,9 @@ bcopy (b1, b2, length)
     *b2++ = *b1++;
 #endif /* not VMS */
 }
+#endif /* no bcopy */
 
+#ifndef bcmp
 int
 bcmp (b1, b2, length)  /* This could be a macro! */
      register char *b1;
@@ -2213,6 +2517,8 @@ bcmp (b1, b2, length)     /* This could be a macro! */
   return 0;
 #endif /* not VMS */
 }
+#endif /* no bcmp */
+
 #endif /* not BSTRING */
 \f
 #ifndef HAVE_RANDOM
@@ -2321,7 +2627,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. */
@@ -2369,6 +2675,21 @@ char *sys_errlist[] =
 #endif /* SHAREABLE_LIB_BUG */
 #endif /* LINK_CRTL_SHARE */
 #endif /* VMS */
+
+#ifndef HAVE_STRERROR
+char *
+strerror (errnum)
+     int errnum;
+{
+  extern char *sys_errlist[];
+  extern int sys_nerr;
+
+  if (errnum >= 0 && errnum < sys_nerr)
+    return sys_errlist[errnum];
+  return (char *) "Unknown error";
+}
+
+#endif /* ! HAVE_STRERROR */
 \f
 #ifdef INTERRUPTIBLE_OPEN
 
@@ -2422,15 +2743,44 @@ sys_write (fildes, buf, nbyte)
      char *buf;
      unsigned int nbyte;
 {
-  register int rtnval;
+  register int rtnval, bytes_written;
 
-  while ((rtnval = write (fildes, buf, nbyte)) == -1
-        && (errno == EINTR));
-  return (rtnval);
+  bytes_written = 0;
+
+  while (nbyte > 0)
+    {
+      rtnval = write (fildes, buf, nbyte);
+
+      if (rtnval == -1)
+       {
+         if (errno == EINTR)
+           continue;
+         else
+           return (-1);
+       }
+
+      buf += rtnval;
+      nbyte -= rtnval;
+      bytes_written += rtnval;
+    }
+  return (bytes_written);
 }
 
 #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 +2792,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.
  */
@@ -2505,10 +2855,28 @@ char *sys_siglist[NSIG + 1] =
   "user defined signal 2",             /* 17 SIGUSR2 */
   "death of a child",                  /* 18 SIGCLD */
   "power-fail restart",                        /* 19 SIGPWR */
+#ifdef sun
+  "window size change",                            /* 20 SIGWINCH */
+  "urgent socket condition",               /* 21 SIGURG */
+  "pollable event occured",                /* 22 SIGPOLL */
+  "stop (cannot be caught or ignored)", /*  23 SIGSTOP */
+  "user stop requested from tty",          /* 24 SIGTSTP */
+  "stopped process has been continued",        /* 25 SIGCONT */
+  "background tty read attempted",         /* 26 SIGTTIN */
+  "background tty write attempted",    /* 27 SIGTTOU */
+  "virtual timer expired",                 /* 28 SIGVTALRM */
+  "profiling timer expired",               /* 29 SIGPROF */
+  "exceeded cpu limit",                            /* 30 SIGXCPU */
+  "exceeded file size limit",              /* 31 SIGXFSZ */
+  "process's lwps are blocked",            /*  32 SIGWAITING */
+  "special signal used by thread library", /* 33 SIGLWP */
+  "Special Signal Used By CPR",            /* 34 SIGFREEZE */
+  "Special Signal Used By CPR",            /* 35 SIGTHAW */
+#endif /* sun */
 #endif /* not AIX */
   0
   };
-#endif HAVE_SYS_SIGLIST
+#endif /* HAVE_SYS_SIGLIST */
 
 /*
  *     Warning, this function may not duplicate 4.2 action properly
@@ -2531,6 +2899,8 @@ getwd (pathname)
 
   BLOCK_INPUT;                 /* getcwd uses malloc */
   spath = npath = getcwd ((char *) 0, MAXPATHLEN);
+  if (spath == 0)
+    return spath;
   /* On Altos 3068, getcwd can return @hostname/dir, so discard
      up to first slash.  Should be harmless on other systems.  */
   while (*npath && *npath != '/')
@@ -2552,8 +2922,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 +2937,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.  */
@@ -2644,7 +3001,7 @@ dup2 (oldd, newd)
 #ifdef F_DUPFD
   fd = fcntl (oldd, F_DUPFD, newd);
   if (fd != newd)
-    error ("can't dup2 (%i,%i) : %s", oldd, newd, sys_errlist[errno]);
+    error ("can't dup2 (%i,%i) : %s", oldd, newd, strerror (errno));
 #else
   fd = dup (old);
   if (fd == -1)
@@ -2679,7 +3036,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 +3085,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 +3139,27 @@ char *sys_siglist[NSIG + 1] =
 
 #include <dirent.h>
 
-#ifndef AIX
+#if defined(BROKEN_CLOSEDIR) || !defined(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> */
+  int rtnval;
+
+  rtnval = sys_close (dirp->dd_fd);
+
+  /* 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);
+
+  return rtnval;
 }
-#endif /* not AIX */
+#endif /* BROKEN_CLOSEDIR or not HAVE_CLOSEDIR */
 #endif /* SYSV_SYSTEM_DIR */
 
 #ifdef NONSYSTEM_DIR_LIBRARY
@@ -2936,6 +3305,138 @@ 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.
+ */
+#ifdef MKDIR_PROTOTYPE
+MKDIR_PROTOTYPE
+#else
+int
+mkdir (dpath, dmode)
+     char *dpath;
+     int dmode;
+#endif
+{
+  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);
+        }
+      wait_for_termination (cpid);
+  if (synch_process_death != 0 || synch_process_retcode != 0)
+      return -1;               /* /bin/rmdir failed */
+    default:                   /* Parent process */
+      while (cpid != wait (&status));  /* Wait for kid to finish */
+    }
+
+  if (WIFSIGNALED (status) || WEXITSTATUS (status) != 0)
+    {
+      errno = EIO;             /* We don't know why, but */
+      return -1;               /* /bin/mkdir failed */
+    }
+
+  return 0;
+}
+#endif /* !HAVE_RMDIR */
+
+
 \f
 /* Functions for VMS */
 #ifdef VMS
@@ -3288,13 +3789,18 @@ char *
 getwd (pathname)
      char *pathname;
 {
-  char *ptr;
+  char *ptr, *val;
   extern char *getcwd ();
 
 #define MAXPATHLEN 1024
 
   ptr = xmalloc (MAXPATHLEN);
-  getcwd (ptr, MAXPATHLEN);
+  val = getcwd (ptr, MAXPATHLEN);
+  if (val == 0)
+    {
+      xfree (ptr);
+      return val;
+    }
   strcpy (pathname, ptr);
   xfree (ptr);
   
@@ -3499,7 +4005,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 +4019,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 +4533,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.  */