changeset 491:77c38d1bc8a8

Initial revision
author Jim Blandy <jimb@redhat.com>
date Tue, 14 Jan 1992 07:27:56 +0000
parents a54a07015253
children 7d92947cce7d
files Makefile.in build-ins.in src/sysdep.c
diffstat 3 files changed, 4376 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile.in	Tue Jan 14 07:27:56 1992 +0000
@@ -0,0 +1,160 @@
+# This is the distribution Makefile for Emacs.  config.emacs can make
+# most of the changes to this file you might want, so try that first.
+
+# make all	to compile and build Emacs
+# make install	to install it
+# make install.sysv  to install on system V.
+# make install.xenix  to install on Xenix
+# make tags	to update tags tables
+#
+# make distclean	to delete everything that wasn't in the distribution
+#	This is a very dangerous thing to do!
+# make clean
+#       This is a little less dangerous.
+
+SHELL = /bin/sh
+
+# ==================== Where to install things ====================
+# Note that on system V you must change MANDIR to /usr/local/man/man1.
+
+# Where to install all of Emacs's data files - the lisp code,
+# documentation tree, and the architecture-dependent and -independent
+# libraries.  If this is not the directory we're building under
+# already, the `install' targets will move or copy it there.  The
+# default definitions for the variables below are expressed in terms
+# of this one, so you may not need to change them.
+LIBROOT=/u/emacs
+
+# This is where the `install' make target should place the binaries
+# people will want to run directly (like etags and Emacs itself).
+INSTALLBIN=/usr/local/bin
+
+# Emacs will search this path to find its elisp files.  This should be
+# a colon-separated list of directories.  Strictly speaking, all the
+# elisp files should go under DATADIR (below), since both elisp source
+# and compiled elisp are completely portable, but it's traditional to
+# give the lisp files their own subdirectory.
+LISPPATH=/u/emacs/lisp
+
+# Emacs will look here for its architecture-independent files (like
+# the tutorial and the zippy database).
+DATADIR=/u/emacs/share-lib
+
+# Emacs will look here for its architecture-dependent files, like
+# executables for its utilities.
+LIBDIR=/u/emacs/arch-lib
+
+# The locking directory, where the Emacs locking code keeps track of
+# which files are currently being edited.
+LOCKDIR=/u/emacs/lock
+
+# This is where the `install' make target should place the man pages
+# for the binaries it installs.
+MANDIR= /usr/man/man1
+
+
+
+# Flags passed down to subdirectory makefiles.
+MFLAGS=
+
+# Subdirectories to make recursively.  `lisp' is not included
+# because the compiled lisp files are part of the distribution
+# and you cannot remake them without installing Emacs first.
+SUBDIR= lib-src src
+
+# Subdirectories to install
+COPYDIR= arch-lib share-lib info lisp
+
+# Subdirectories to clean
+CLEANDIR= ${COPYDIR} lisp/term
+
+all:	src/paths.h ${SUBDIR}
+
+src/paths.h: Makefile src/paths.h-dist
+	/bin/sed < src/paths.h-dist > src/paths.h			\
+	-e 's;/usr/local/lib/emacs;${LIBROOT};g'			\
+	-e 's;\(#.*PATH_LOADSEARCH\).*$$;\1 "$(LISPPATH)";'		\
+	-e 's;\(#.*PATH_EXEC\).*$$;\1 "$(LIBDIR)";'			\
+	-e 's;\(#.*PATH_DATA\).*$$;\1 "$(DATADIR)";'			\
+	-e 's;\(#.*LOCK\).*$$;\1 "$(LOCKDIR)/";'
+
+src:	lib-src
+
+.RECURSIVE: ${SUBDIR}
+
+${SUBDIR}: FRC
+	cd $@; make ${MFLAGS} all
+
+install: all mkdir lockdir
+	-if [ `/bin/pwd` != `(cd ${LIBROOT}; /bin/pwd)` ] ; then \
+		tar cf - ${COPYDIR} | (cd ${LIBROOT}; umask 0; tar xBf - ) ;\
+		for i in ${CLEANDIR}; do \
+			(rm -rf ${LIBROOT}/$$i/RCS; \
+			 rm -f ${LIBROOT}/$$i/\#*; \
+			 rm -f ${LIBROOT}/$$i/*~); \
+		done \
+	else true; \
+	fi
+	install -c -s arch-lib/emacsclient ${INSTALLBIN}/emacsclient
+	install -c -s arch-lib/etags ${INSTALLBIN}/etags
+	install -c -s arch-lib/ctags ${INSTALLBIN}/ctags
+	install -c -s -m 1755 src/xemacs ${INSTALLBIN}/xemacs
+	install -c -m 444 share-lib/emacs.1 ${MANDIR}/emacs.1
+	-rm -f ${INSTALLBIN}/emacs
+	mv ${INSTALLBIN}/xemacs ${INSTALLBIN}/emacs
+
+install.sysv: all mkdir lockdir
+	-if [ `/bin/pwd` != `(cd ${LIBROOT}; /bin/pwd)` ] ; then \
+		find ${COPYDIR} -print | cpio -pdum ${LIBROOT} ;\
+		for i in ${CLEANDIR}; do \
+			(rm -rf ${LIBROOT}/$$i/RCS; \
+			 rm -f ${LIBROOT}/$$i/\#*; \
+			 rm -f ${LIBROOT}/$$i/*~); \
+		done \
+	else true; \
+	fi
+	-cpset arch-lib/emacsclient ${INSTALLBIN}/emacsclient 755 bin bin
+	-cpset arch-lib/etags ${INSTALLBIN}/etags 755 bin bin
+	-cpset arch-lib/ctags ${INSTALLBIN}/ctags 755 bin bin
+	-cpset share-lib/emacs.1 ${MANDIR}/emacs.1 444 bin bin
+	-/bin/rm -f ${INSTALLBIN}/emacs
+	-cpset src/xemacs ${INSTALLBIN}/emacs 1755 bin bin
+  
+install.xenix: all mkdir lockdir
+	if [ `pwd` != `(cd ${LIBROOT}; pwd)` ] ; then \
+		tar cf - ${COPYDIR} | (cd ${LIBROOT}; umask 0; tar xpf - ) ;\
+		for i in ${CLEANDIR}; do \
+			(rm -rf ${LIBROOT}/$$i/RCS; \
+			 rm -f ${LIBROOT}/$$i/\#*; \
+			 rm -f ${LIBROOT}/$$i/*~); \
+		done \
+	else true; \
+	fi
+	cp arch-lib/etags arch-lib/ctags arch-lib/emacsclient ${INSTALLBIN}
+	chmod 755 ${INSTALLBIN}/etags ${INSTALLBIN}/ctags ${INSTALLBIN}/emacsclient
+	cp share-lib/emacs.1 ${MANDIR}/emacs.1
+	chmod 444 ${MANDIR}/emacs.1
+	-mv -f ${INSTALLBIN}/emacs ${INSTALLBIN}/emacs.old
+	cp src/xemacs ${INSTALLBIN}/emacs
+	chmod 1755 ${INSTALLBIN}/emacs
+	-rm -f ${INSTALLBIN}/emacs.old
+
+mkdir: FRC
+	-mkdir ${LIBROOT}
+	-chmod 777 ${LIBROOT}
+
+distclean:
+	for i in ${SUBDIR}; do (cd $$i; make ${MFLAGS} distclean); done
+
+clean:
+	cd src; make clean
+	cd lib-src; make clean
+
+lockdir:
+	-mkdir ${LOCKDIR}
+	-chmod 777 ${LOCKDIR}
+
+FRC:
+
+tags:	lib-src
+	cd src; ../arch-lib/etags *.[ch] ../lisp/*.el ../lisp/term/*.el
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build-ins.in	Tue Jan 14 07:27:56 1992 +0000
@@ -0,0 +1,64 @@
+#!/bin/csh -fx
+#
+#Shell script for building and installing Emacs.
+
+# Where to install all of Emacs's data files - the lisp code,
+# documentation tree, and the architecture-dependent and -independent
+# libaries.  The default definitions for the variables below are
+# expressed in terms of this one, so you may not need to change them.
+# set LIBROOT=/usr/local/lib/emacs-19.0
+set LIBROOT=/u/emacs
+
+# Emacs will search this path to find its elisp files.  This should be
+# a colon-separated list of directories.  Strictly speaking, all the
+# elisp files should go under DATADIR (below), since both elisp source
+# and compiled elisp are completely portable, but it's traditional to
+# give the lisp files their own subdirectory.
+set LISPPATH=/u/emacs/lisp
+
+# Emacs will look here for its architecture-independent files (like
+# the tutorial and the zippy database).
+set DATADIR=/u/emacs/share-lib
+
+# Emacs will look here for its architecture-dependent files, like
+# executables for its utilities.
+set LIBDIR=/u/emacs/arch-lib
+
+# The locking directory, where the Emacs locking code keeps track of
+# which files are currently being edited.
+# set LOCKDIR=${LIBROOT}/lock
+set LOCKDIR=/u/emacs/lock
+
+# This is where build-install should place the binaries people will
+# want to run directly (like etags and Emacs itself).
+set BINDIR=/usr/local/bin
+
+/bin/sed < src/paths.h-dist > src/paths.h			\
+-e 's;/usr/local/emacs;'${LIBDIR}';g'				\
+-e 's;\(#.*PATH_LOADSEARCH\).*$$;\1 "'${LISPPATH}'";'		\
+-e 's;\(#.*PATH_EXEC\).*$$;\1 "'${LIBDIR}'";'			\
+-e 's;\(#.*PATH_DATA\).*$$;\1 "'${DATADIR}'";'			\
+-e 's;\(#.*LOCK\).*$$;\1 "'${LOCKDIR}'/";'
+
+exit 1
+
+(cd lib-src; make) || exit 1
+(cd src; make) || exit 1
+
+if (`pwd` != `(cd ${LIBROOT}; pwd)`) then
+  mv `pwd` ${LIBROOT}
+  if ($status) then
+    mkdir ${LIBROOT}
+    echo mv `pwd` to ${LIBROOT} failed--using tar to copy.
+    tar cf - . | (cd ${LIBROOT}; umask 0; tar xf -)
+    if ($status) then
+      echo tar-copying `pwd` to ${LIBROOT} failed.
+      exit 1
+    endif
+  endif
+endif
+
+cp ${LIBROOT}/etc/{ctags,etags} ${BINDIR}
+mv ${LIBROOT}/src/xemacs ${BINDIR}/emacs
+rm ${LIBROOT}/src/temacs
+chmod 777 ${BINDIR}/{ctags,etags,emacs}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sysdep.c	Tue Jan 14 07:27:56 1992 +0000
@@ -0,0 +1,4152 @@
+/* Interfaces to system-dependent kernel and library entries.
+   Copyright (C) 1985, 1986, 1987, 1988 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)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+#include <signal.h>
+#include <setjmp.h>
+
+#include "config.h"
+#include "lisp.h"
+#undef NULL
+
+#define min(x,y) ((x) > (y) ? (y) : (x))
+
+/* In this file, open, read and write refer to the system calls,
+   not our sugared interfaces  sys_open, sys_read and sys_write.
+   Contrariwise, for systems where we use the system calls directly,
+   define sys_read, etc. here as aliases for them.  */
+#ifndef read
+#define sys_read read
+#define sys_write write
+#endif /* `read' is not a macro */
+
+#undef read
+#undef write
+
+#ifndef close
+#define sys_close close
+#else 
+#undef close
+#endif
+
+#ifndef open
+#define sys_open open
+#else /* `open' is a macro */
+#undef open
+#endif /* `open' is a macro */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+extern int errno;
+#ifndef VMS
+extern char *sys_errlist[];
+#endif
+
+#ifdef VMS
+#include <rms.h>
+#include <ttdef.h>
+#include <tt2def.h>
+#include <iodef.h>
+#include <ssdef.h>
+#include <descrip.h>
+#include <fibdef.h>
+#include <atrdef.h>
+#include <ctype.h>
+#include <string.h>
+#ifdef __GNUC__
+#include <sys/file.h>
+#else
+#include <file.h>
+#endif
+#undef F_SETFL
+#ifndef RAB$C_BID
+#include <rab.h>
+#endif
+#define	MAXIOSIZE ( 32 * PAGESIZE )	/* Don't I/O more than 32 blocks at a time */
+#endif /* VMS */
+
+#ifndef BSD4_1
+#ifdef BSD /* this is done this way to avoid defined (BSD) || defined (USG)
+	      because the vms compiler doesn't grok `defined' */
+#include <fcntl.h>
+#endif
+#ifdef USG
+#include <fcntl.h>
+#endif
+#endif /* not 4.1 bsd */
+
+/* Get DGUX definition for FASYNC - DJB */
+#ifdef DGUX
+#include <sys/file.h>
+#endif /* DGUX */
+
+#include <sys/ioctl.h>
+
+#ifdef APOLLO
+#undef TIOCSTART
+#endif
+
+#ifdef BSD
+#ifdef BSD4_1
+#include <wait.h>
+#else /* not 4.1 */
+#include <sys/wait.h>
+#endif /* not 4.1 */
+#endif /* BSD */
+
+#ifdef AIX
+/* Get files for keyboard remapping */
+#define HFNKEYS 2
+#include <sys/hft.h>
+#include <sys/devinfo.h>
+#endif
+
+/* Get rid of LLITOUT in 4.1, since it is said to stimulate kernel bugs.  */
+#ifdef BSD4_1
+#undef LLITOUT
+#define LLITOUT 0
+#endif /* 4.1 */
+
+#ifdef HAVE_TERMIOS
+#include <termio.h>
+#include <termios.h>
+#ifdef TIOCGETP
+#undef TIOCGETP
+#endif
+#define TIOCGETP TCGETS
+#undef TIOCSETN
+#define TIOCSETN TCSETSW
+#undef TIOCSETP
+#define TIOCSETP TCSETSF
+#undef TCSETAW
+#define TCSETAW TCSETS
+#define TERMINAL struct termios
+#define OSPEED(str) (str.c_cflag & CBAUD)
+#define SETOSPEED(str,new) (str.c_cflag = (str.c_cflag & ~CBAUD) | (new))
+#define TABS_OK(str) ((str.c_oflag & TABDLY) != TAB3)
+#else
+#define tcgetattr(fd, addr) ioctl (fd, TIOCGETP, addr)
+#endif /* HAVE_TERMIOS */
+
+#ifdef HAVE_TERMIO
+#include <termio.h>
+#undef TIOCGETP
+#define TIOCGETP TCGETA
+#undef TIOCSETN
+/* Wait for output to finish before switching modes.
+   Otherwise screen can be garbaged.  */
+#define TIOCSETN TCSETAW
+#undef TIOCSETP
+#define TIOCSETP TCSETAF
+#define TERMINAL struct termio
+#define OSPEED(str) (str.c_cflag & CBAUD)
+#define SETOSPEED(str,new) (str.c_cflag = (str.c_cflag & ~CBAUD) | (new))
+#define TABS_OK(str) ((str.c_oflag & TABDLY) != TAB3)
+#endif /* HAVE_TERMIO */
+
+#ifdef BROKEN_TIOCGETC
+#undef TIOCGETC  /* Avoid confusing some conditionals that test this.  */
+#endif
+
+#ifdef BROKEN_TIOCGWINSZ
+#undef TIOCGWINSZ
+#endif
+
+#ifndef HAVE_TERMIO
+#ifndef VMS
+#include <sgtty.h>
+#define TERMINAL struct sgttyb
+#define OSPEED(str) str.sg_ospeed
+#define SETOSPEED(str,new) (str.sg_ospeed = (new))
+#define TABS_OK(str) ((str.sg_flags & XTABS) != XTABS)
+#undef TCSETAW
+#define TCSETAW TIOCSETN
+#endif /* not VMS */
+#endif /* not HAVE_TERMIO */
+
+#ifdef USG
+#include <sys/utsname.h>
+#include <string.h>
+#ifndef MEMORY_IN_STRING_H
+#include <memory.h>
+#endif
+#ifdef TIOCGWINSZ
+#ifdef NEED_SIOCTL
+#include <sys/sioctl.h>
+#endif
+#ifdef NEED_PTEM_H
+#include <sys/stream.h>
+#include <sys/ptem.h>
+#endif
+#endif /* TIOCGWINSZ */
+#ifdef NEED_TIME_H
+#include <time.h>
+#else /* not NEED_TIME_H */
+#ifdef HAVE_TIMEVAL
+#include <sys/time.h>
+#endif /* HAVE_TIMEVAL */
+#endif /* not NEED_TIME_H */
+#endif /* USG */
+
+#ifdef NEED_BSDTTY
+#include <sys/bsdtty.h>
+#endif 
+
+#if defined (HPUX) && defined (HAVE_PTYS)
+#include <sys/ptyio.h>
+#endif
+  
+#ifdef AIX
+#include <sys/pty.h>
+#include <unistd.h>
+#endif /* AIX */
+
+#ifdef SYSV_PTYS
+#include <sys/tty.h>
+#include <sys/pty.h>
+#endif
+
+#ifdef BROKEN_FIONREAD
+#undef FIONREAD
+#undef FASYNC
+#endif
+
+extern int quit_char;
+
+#include "screen.h"
+#include "window.h"
+#include "termhooks.h"
+#include "termchar.h"
+#include "termopts.h"
+#include "dispextern.h"
+#include "process.h"
+
+#ifdef NONSYSTEM_DIR_LIBRARY
+#include "ndir.h"
+#endif /* NONSYSTEM_DIR_LIBRARY */
+
+#include "emacssignal.h"
+
+#ifndef sigunblock
+#define sigunblock(SIG) \
+{ SIGMASKTYPE omask = sigblock (SIGEMPTYMASK); sigsetmask (omask & ~SIG); }
+#endif
+
+/* Define SIGCHLD as an alias for SIGCLD.  There are many conditionals
+   testing SIGCHLD.  */
+
+#ifndef VMS
+#ifdef SIGCLD
+#ifndef SIGCHLD
+#define SIGCHLD SIGCLD
+#endif /* not SIGCHLD */
+#endif /* SIGCLD */
+#endif /* not VMS */
+
+static int baud_convert[] =
+#ifdef BAUD_CONVERT
+  BAUD_CONVERT;
+#else
+  {
+    0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
+    1800, 2400, 4800, 9600, 19200, 38400
+  };
+#endif
+
+extern short ospeed;
+
+#ifdef VMS
+static struct iosb
+{
+  short status;
+  short offset;
+  short termlen;
+  short term;
+} input_iosb;
+
+int kbd_input_ast ();
+
+int waiting_for_ast;
+int stop_input;
+int input_ef = 0;
+int timer_ef = 0;
+int process_ef = 0;
+int input_eflist;
+int timer_eflist;
+
+static int input_chan;
+static $DESCRIPTOR (input_dsc, "TT");
+static int terminator_mask[2] = { 0, 0 };
+
+static struct sensemode {
+  short status;
+  unsigned char xmit_baud;
+  unsigned char rcv_baud;
+  unsigned char crfill;
+  unsigned char lffill;
+  unsigned char parity;
+  unsigned char unused;
+  char class;
+  char type;
+  short scr_wid;
+  unsigned long tt_char : 24, scr_len : 8;
+  unsigned long tt2_char;
+} sensemode_iosb;
+#define TERMINAL struct sensemode
+#define OSPEED(str) (str.xmit_baud)
+#define TABS_OK(str) ((str.tt_char & TT$M_MECHTAB) != 0)
+#endif /* VMS */
+
+discard_tty_input ()
+{
+  TERMINAL buf;
+
+  if (noninteractive)
+    return;
+
+  /* Discarding input is not safe when the input could contain
+     replies from the X server.  So don't do it.  */
+  if (read_socket_hook)
+    return;
+
+#ifdef VMS
+  end_kbd_input ();
+  SYS$QIOW (0, input_chan, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
+	    &buf, 0, 0, terminator_mask, 0, 0);
+  queue_kbd_input ();
+#else /* not VMS */
+#ifdef APOLLO
+  {
+    int zero = 0;
+    ioctl (0, TIOCFLUSH, &zero);
+  }
+#else /* not Apollo */
+  tcgetattr (0, &buf);
+#ifndef HAVE_TCATTR
+  ioctl (0, TIOCSETP, &buf);
+#else
+  tcsetattr (0, TCSAFLUSH, &buf);
+#endif
+#endif /* not Apollo */
+#endif /* not VMS */
+}
+
+#ifdef SIGTSTP
+
+stuff_char (c)
+     char c;
+{
+/* Should perhaps error if in batch mode */
+#ifdef TIOCSTI
+  ioctl (0, TIOCSTI, &c);
+#else /* no TIOCSTI */
+  error ("Cannot stuff terminal input characters in this version of Unix.");
+#endif /* no TIOCSTI */
+}
+
+#endif /* SIGTSTP */
+
+init_baud_rate ()
+{
+  TERMINAL sg;
+
+  if (noninteractive)
+    ospeed = 0;
+  else
+    {
+#ifdef VMS
+      SYS$QIOW (0, input_chan, IO$_SENSEMODE, &sg, 0, 0,
+		&sg.class, 12, 0, 0, 0, 0 );
+#else
+      SETOSPEED (sg, B9600);
+      tcgetattr (0, &sg);
+#endif /* not VMS */
+      ospeed = OSPEED (sg);
+    }
+   
+  baud_rate = (ospeed < sizeof baud_convert / sizeof baud_convert[0]
+ 	       ? baud_convert[ospeed] : 9600);
+  if (baud_rate == 0)
+    baud_rate = 1200;
+}
+
+/*ARGSUSED*/
+set_exclusive_use (fd)
+     int fd;
+{
+#ifdef FIOCLEX
+  ioctl (fd, FIOCLEX, 0);
+#endif
+  /* Ok to do nothing if this feature does not exist */
+}
+
+#ifndef subprocesses
+
+wait_without_blocking ()
+{
+#ifdef BSD
+  wait3 (0, WNOHANG | WUNTRACED, 0);
+#else
+  croak ("wait_without_blocking");
+#endif
+  synch_process_alive = 0;
+}
+
+#endif /* not subprocesses */
+
+int wait_debugging;   /* Set nonzero to make following function work under dbx
+		         (at least for bsd).  */
+
+SIGTYPE
+wait_for_termination_signal ()
+{}
+
+/* Wait for subprocess with process id `pid' to terminate and
+   make sure it will get eliminated (not remain forever as a zombie) */
+
+wait_for_termination (pid)
+     int pid;
+{
+  while (1)
+    {
+#ifdef subprocesses
+#ifdef VMS
+      int status;
+
+      status = sys$forcex (&pid, 0, 0);
+      break;
+#else /* not VMS */
+
+      /* Exit if the process has terminated.  */
+      if (!synch_process_alive)
+	break;
+      /* Otherwise wait 1 second or until a signal comes in.  */
+      signal (SIGALRM, wait_for_termination_signal);
+      alarm (1);
+      pause ();
+      alarm (0);
+      signal (SIGALRM, SIG_IGN);
+#endif /* not VMS */
+#else /* not subprocesses */
+#ifndef BSD4_1
+      if (kill (pid, 0) < 0)
+	break;
+      wait (0);
+#else /* BSD4_1 */
+      int status;
+      status = wait (0);
+      if (status == pid || status == -1)
+	break;
+#endif /* BSD4_1 */
+#endif /* not subprocesses */
+    }
+}
+
+#ifdef subprocesses
+
+/*
+ *	flush any pending output
+ *      (may flush input as well; it does not matter the way we use it)
+ */
+ 
+flush_pending_output (channel)
+     int channel;
+{
+#ifdef HAVE_TERMIOS
+  /* If we try this, we get hit with SIGTTIN, because
+     the child's tty belongs to the child's pgrp. */
+#else
+#ifdef TCFLSH
+  ioctl (channel, TCFLSH, 1);
+#else
+#ifdef TIOCFLUSH
+  int zero = 0;
+  /* 3rd arg should be ignored
+     but some 4.2 kernels actually want the address of an int
+     and nonzero means something different.  */
+  ioctl (channel, TIOCFLUSH, &zero);
+#endif
+#endif
+#endif
+}
+
+#ifndef VMS
+/*  Set up the terminal at the other end of a pseudo-terminal that
+    we will be controlling an inferior through.
+    It should not echo or do line-editing, since that is done
+    in Emacs.  No padding needed for insertion into an Emacs buffer.  */
+
+child_setup_tty (out)
+     int out;
+{
+  TERMINAL s;
+
+  tcgetattr (out, &s);
+#ifdef HAVE_TERMIO
+  s.c_oflag |= OPOST;		/* Enable output postprocessing */
+  s.c_oflag &= ~ONLCR;		/* Disable map of NL to CR-NL on output */
+  s.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);	/* No output delays */
+  s.c_lflag &= ~ECHO;		/* Disable echo */
+  s.c_lflag |= ISIG;		/* Enable signals */
+  s.c_iflag &= ~IUCLC;		/* Disable map of upper case to lower on input */
+  s.c_oflag &= ~OLCUC;		/* Disable map of lower case to upper on output */
+/* said to be unnecesary
+  s.c_cc[VMIN] = 1;		/* minimum number of characters to accept
+  s.c_cc[VTIME] = 0;		/* wait forever for at least 1 character
+*/
+  s.c_lflag |= ICANON;		/* Enable erase/kill and eof processing */
+  s.c_cc[VEOF] = 04;		/* insure that EOF is Control-D */
+  s.c_cc[VERASE] = 0377;	/* disable erase processing */
+  s.c_cc[VKILL] = 0377;		/* disable kill processing */
+#ifdef HPUX
+  s.c_cflag = (s.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
+#endif /* HPUX */
+#ifdef AIX
+/* AIX enhanced edit loses NULs, so disable it */
+#ifndef IBMR2AIX
+  s.c_line = 0;
+  s.c_iflag &= ~ASCEDIT;
+#endif
+  /* Also, PTY overloads NUL and BREAK.
+     don't ignore break, but don't signal either, so it looks like NUL.  */
+  s.c_iflag &= ~IGNBRK;
+  s.c_iflag &= ~BRKINT;
+/* QUIT and INTR work better as signals, so disable character forms */
+  s.c_cc[VQUIT] = 0377;
+  s.c_cc[VINTR] = 0377;
+  s.c_cc[VEOL] = 0377;
+  s.c_lflag &= ~ISIG;
+  s.c_cflag = (s.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
+#endif /* AIX */
+
+#else /* not HAVE_TERMIO */
+  s.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE | CBREAK | TANDEM);
+  s.sg_erase = 0377;
+  s.sg_kill = 0377;
+#endif /* not HAVE_TERMIO */
+
+#ifndef HAVE_TCATTR
+  ioctl (out, TIOCSETN, &s);
+#else
+  tcsetattr (out, TCSADRAIN, &s);
+#endif
+
+#ifdef BSD4_1
+  if (interrupt_input)
+    reset_sigio ();
+#endif /* BSD4_1 */
+#ifdef RTU
+  {
+    int zero = 0;
+    ioctl (out, FIOASYNC, &zero);
+  }
+#endif /* RTU */
+}
+#endif /* not VMS */
+
+#endif /* subprocesses */
+
+/*ARGSUSED*/
+setpgrp_of_tty (pid)
+     int pid;
+{
+#ifdef IBMR2AIX
+  tcsetpgrp ( 0, pid);
+#else
+#ifdef TIOCSPGRP
+  ioctl (0, TIOCSPGRP, &pid);
+#else
+  /* Just ignore this for now and hope for the best */
+#endif
+#endif
+}
+
+/* Record a signal code and the handler for it.  */
+struct save_signal
+{
+  int code;
+  SIGTYPE (*handler) ();
+};
+
+/* Suspend the Emacs process; give terminal to its superior.  */
+
+sys_suspend ()
+{
+#ifdef VMS
+  unsigned long parent_id;
+
+  parent_id = getppid ();
+  if (parent_id && parent_id != 0xffffffff)
+    {
+      SIGTYPE (*oldsig)() = (int) signal (SIGINT, SIG_IGN);
+      int status = LIB$ATTACH (&parent_id) & 1;
+      signal (SIGINT, oldsig);
+      return status;
+    }
+  else
+    {
+      struct {
+	int	l;
+	char	*a;
+      } d_prompt;
+      d_prompt.l = sizeof ("Emacs: ");		/* Our special prompt */
+      d_prompt.a = "Emacs: ";			/* Just a reminder */
+      lib$spawn (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &d_prompt, 0);
+      return 1;
+    }
+  return -1;
+#else
+#ifdef SIGTSTP
+
+#ifdef BSD
+  killpg (getpgrp (0), SIGTSTP);
+#else
+  kill (-getpgrp (0), SIGTSTP);
+#endif
+
+#else /* No SIGTSTP */
+#ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
+  ptrace (0, 0, 0, 0);		/* set for ptrace - caught by csh */
+  kill (getpid (), SIGQUIT);
+
+#else /* No SIGTSTP or USG_JOBCTRL */
+
+/* On a system where suspending is not implemented,
+   instead fork a subshell and let it talk directly to the terminal
+   while we wait.  */
+  int pid = fork ();
+  struct save_signal saved_handlers[5];
+
+  saved_handlers[0].code = SIGINT;
+  saved_handlers[1].code = SIGQUIT;
+  saved_handlers[2].code = SIGTERM;
+#ifdef SIGIO
+  saved_handlers[3].code = SIGIO;
+  saved_handlers[4].code = 0;
+#else
+  saved_handlers[3].code = 0;
+#endif
+
+  if (pid == -1)
+    error ("Can't spawn subshell");
+  if (pid == 0)
+    {
+      char *sh;
+
+      sh = (char *) egetenv ("SHELL");
+      if (sh == 0)
+	sh = "sh";
+      /* Use our buffer's default directory for the subshell.  */
+      {
+	Lisp_Object dir;
+	unsigned char *str;
+	int len;
+
+	/* mentioning current_buffer->buffer would mean including buffer.h,
+	   which somehow wedges the hp compiler.  So instead... */
+
+	dir = intern ("default-directory");
+	/* Can't use NULL */
+	if (XFASTINT (Fboundp (dir)) == XFASTINT (Qnil))
+	  goto xyzzy;
+	dir = Fsymbol_value (dir);
+	if (XTYPE (dir) != Lisp_String)
+	  goto xyzzy;
+
+	str = (unsigned char *) alloca (XSTRING (dir)->size + 2);
+	len = XSTRING (dir)->size;
+	bcopy (XSTRING (dir)->data, str, len);
+	if (str[len - 1] != '/') str[len++] = '/';
+	str[len] = 0;
+	chdir (str);
+      }
+    xyzzy:
+#ifdef subprocesses
+      close_process_descs ();	/* Close Emacs's pipes/ptys */
+#endif
+      nice (-nice (0));		/* Give the new shell the default piority */ 
+      execlp (sh, sh, 0);
+      write (1, "Can't execute subshell", 22);
+      _exit (1);
+    }
+
+  save_signal_handlers (saved_handlers);
+  wait_for_termination (pid);
+  restore_signal_handlers (saved_handlers);
+
+#endif /* no USG_JOBCTRL */
+#endif /* no SIGTSTP */
+#endif /* not VMS */
+}
+
+save_signal_handlers (saved_handlers)
+     struct save_signal *saved_handlers;
+{
+  while (saved_handlers->code)
+    {
+      saved_handlers->handler = signal (saved_handlers->code, SIG_IGN);
+      saved_handlers++;
+    }
+}
+
+restore_signal_handlers (saved_handlers)
+     struct save_signal *saved_handlers;
+{
+  while (saved_handlers->code)
+    {
+      signal (saved_handlers->code, saved_handlers->handler);
+      saved_handlers++;
+    }
+}
+
+#ifdef F_SETFL
+
+int old_fcntl_flags;
+
+init_sigio ()
+{
+#ifdef FASYNC
+  old_fcntl_flags = fcntl (0, F_GETFL, 0) & ~FASYNC;
+#endif
+  request_sigio ();
+}
+
+reset_sigio ()
+{
+  unrequest_sigio ();
+}
+
+#ifdef FASYNC		/* F_SETFL does not imply existance of FASYNC */
+
+request_sigio ()
+{
+#ifdef SIGWINCH
+  sigunblock (sigmask (SIGWINCH));
+#endif
+  fcntl (0, F_SETFL, old_fcntl_flags | FASYNC);
+
+  interrupts_deferred = 0;
+}
+
+unrequest_sigio ()
+{
+#ifdef SIGWINCH
+  sigblock (sigmask (SIGWINCH));
+#endif
+  fcntl (0, F_SETFL, old_fcntl_flags);
+  interrupts_deferred = 1;
+}
+
+#else /* no FASYNC */
+#ifdef STRIDE		/* Stride doesn't have FASYNC - use FIOASYNC */
+
+request_sigio ()
+{
+  int on = 1;
+  ioctl (0, FIOASYNC, &on);
+  interrupts_deferred = 0;
+}
+
+unrequest_sigio ()
+{
+  int off = 0;
+
+  ioctl (0, FIOASYNC, &off);
+  interrupts_deferred = 1;
+}
+
+#else /* not FASYNC, not STRIDE */
+ 
+request_sigio ()
+{
+  croak ("request_sigio");
+}
+ 
+unrequest_sigio ()
+{
+  croak ("unrequest_sigio");
+}
+ 
+#endif /* STRIDE */
+#endif /* FASYNC */
+#endif /* F_SETFL */
+
+TERMINAL old_gtty;		/* The initial tty mode bits */
+
+int term_initted;		/* 1 if outer tty status has been recorded */
+
+#ifdef F_SETOWN
+int old_fcntl_owner;
+#endif /* F_SETOWN */
+
+#ifdef TIOCGLTC
+struct ltchars old_ltchars;
+#endif /* TIOCGLTC */
+
+#ifdef TIOCGETC
+struct tchars old_tchars;
+int old_lmode;
+
+int lmode;			/* Current lmode value. */
+				/* Needed as global for 4.1 */
+#endif /* TIOCGETC */
+
+/* This may also be defined in stdio,
+   but if so, this does no harm,
+   and using the same name avoids wasting the other one's space.  */
+
+#if defined (USG) || defined (DGUX)
+unsigned char _sobuf[BUFSIZ+8];
+#else
+char _sobuf[BUFSIZ];
+#endif
+ 
+#ifdef TIOCGLTC
+static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
+#endif
+#ifdef TIOCGETC
+  static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
+#endif 
+
+init_sys_modes ()
+{
+  TERMINAL tty;
+#ifdef TIOCGETC
+  struct tchars tchars;
+#endif
+#ifdef VMS
+#if 0
+  static int oob_chars[2] = {0, 1 << 7}; /* catch C-g's */
+  extern int (*interrupt_signal) ();
+#endif
+#endif
+
+  if (noninteractive)
+    return;
+
+#ifdef VMS
+  if (!input_ef)
+    input_ef = get_kbd_event_flag ();
+    /* LIB$GET_EF (&input_ef); */
+  SYS$CLREF (input_ef);
+  waiting_for_ast = 0;
+  if (!timer_ef)
+    timer_ef = get_timer_event_flag ();
+    /* LIB$GET_EF (&timer_ef); */
+  SYS$CLREF (timer_ef);
+  if (!process_ef)
+    {
+      LIB$GET_EF (&process_ef);
+      SYS$CLREF (process_ef);
+    }
+  if (input_ef / 32 != process_ef / 32)
+    croak ("Input and process event flags in different clusters.");
+  if (input_ef / 32 != timer_ef / 32)
+    croak ("Input and process event flags in different clusters.");
+  input_eflist = ((unsigned) 1 << (input_ef % 32)) |
+    ((unsigned) 1 << (process_ef % 32));
+  timer_eflist = ((unsigned) 1 << (input_ef % 32)) |
+    ((unsigned) 1 << (timer_ef % 32));
+  SYS$QIOW (0, input_chan, IO$_SENSEMODE, &old_gtty, 0, 0,
+	    &old_gtty.class, 12, 0, 0, 0, 0);
+#ifndef VMS4_4
+  sys_access_reinit ();
+#endif
+#else /* not VMS */
+  tcgetattr (0, &old_gtty);
+#endif /* not VMS */
+  if (!read_socket_hook && EQ (Vwindow_system, Qnil))
+    {
+      tty = old_gtty;
+
+#ifdef HAVE_TERMIO
+      tty.c_iflag |= (IGNBRK);	/* Ignore break condition */
+      tty.c_iflag &= ~ICRNL;	/* Disable map of CR to NL on input */
+#ifdef ISTRIP
+      tty.c_iflag &= ~ISTRIP;	/* don't strip 8th bit on input */
+#endif
+      tty.c_lflag &= ~ECHO;	/* Disable echo */
+      tty.c_lflag &= ~ICANON;	/* Disable erase/kill processing */
+      tty.c_lflag |= ISIG;	/* Enable signals */
+      if (flow_control)
+	{
+	  tty.c_iflag |= IXON;	/* Enable start/stop output control */
+#ifdef IXANY
+	  tty.c_iflag &= ~IXANY;
+#endif /* IXANY */
+	}
+      else
+	tty.c_iflag &= ~IXON;	/* Disable start/stop output control */
+      tty.c_oflag &= ~ONLCR;	/* Disable map of NL to CR-NL on output */
+      tty.c_oflag &= ~TAB3;	/* Disable tab expansion */
+#ifdef CS8
+      if (meta_key)
+	{
+	  tty.c_cflag |= CS8;	/* allow 8th bit on input */
+	  tty.c_cflag &= ~PARENB;/* Don't check parity */
+	}
+#endif
+      tty.c_cc[VINTR] = quit_char;	/* C-g (usually) gives SIGINT */
+      /* Set up C-g for both SIGQUIT and SIGINT.
+	 We don't know which we will get, but we handle both alike
+	 so which one it really gives us does not matter.  */
+      tty.c_cc[VQUIT] = quit_char;
+      tty.c_cc[VMIN] = 1;	/* Input should wait for at least 1 char */
+      tty.c_cc[VTIME] = 0;	/* no matter how long that takes.  */
+#ifdef VSWTCH
+      tty.c_cc[VSWTCH] = CDEL;	/* Turn off shell layering use of C-z */
+#endif /* VSWTCH */
+#if defined (mips) || defined (HAVE_TCATTR)
+             /* The following code looks like the right thing in general,
+		but it is said to cause a crash on USG V.4.
+		Let's play safe by turning it on only for the MIPS.  */
+#ifdef VSUSP
+      tty.c_cc[VSUSP] = CDEL;	/* Turn off mips handling of C-z.  */
+#endif /* VSUSP */
+#ifdef V_DSUSP
+      tty.c_cc[V_DSUSP] = CDEL;	/* Turn off mips handling of C-y.  */
+#endif /* V_DSUSP */
+#endif /* mips or HAVE_TCATTR */
+#ifdef AIX
+#ifndef IBMR2AIX
+      /* AIX enhanced edit loses NULs, so disable it */
+      tty.c_line = 0;
+      tty.c_iflag &= ~ASCEDIT;
+#else
+      tty.c_cc[VSTRT] = 255;
+      tty.c_cc[VSTOP] = 255;
+      tty.c_cc[VSUSP] = 255;
+      tty.c_cc[VDSUSP] = 255;
+#endif /* IBMR2AIX */
+      /* Also, PTY overloads NUL and BREAK.
+	 don't ignore break, but don't signal either, so it looks like NUL.
+	 This really serves a purpose only if running in an XTERM window
+	 or via TELNET or the like, but does no harm elsewhere.  */
+      tty.c_iflag &= ~IGNBRK;
+      tty.c_iflag &= ~BRKINT;
+#endif
+#else /* if not HAVE_TERMIO */
+#ifdef VMS
+      tty.tt_char |= TT$M_NOECHO;
+      if (meta_key)
+	tty.tt_char |= TT$M_EIGHTBIT
+      if (flow_control)
+	tty.tt_char |= TT$M_TTSYNC;
+      else
+	tty.tt_char &= ~TT$M_TTSYNC;
+      tty.tt2_char |= TT2$M_PASTHRU | TT2$M_XON;
+#else /* not VMS (BSD, that is) */
+      tty.sg_flags &= ~(ECHO | CRMOD | XTABS);
+      if (meta_key)
+	tty.sg_flags |= ANYP;
+      tty.sg_flags |= interrupt_input ? RAW : CBREAK;
+#endif /* not VMS (BSD, that is) */
+#endif /* not HAVE_TERMIO */
+
+#ifdef VMS
+      SYS$QIOW (0, input_chan, IO$_SETMODE, &input_iosb, 0, 0,
+		&tty.class, 12, 0, 0, 0, 0);
+#else
+#ifndef HAVE_TCATTR
+      ioctl (0, TIOCSETN, &tty);
+#else
+      tcsetattr (0, TCSADRAIN, &tty);
+#endif
+#endif /* not VMS */
+
+      /* This code added to insure that, if flow-control is not to be used,
+	 we have an unlocked screen at the start. */
+#ifdef TCXONC
+      if (!flow_control) ioctl (0, TCXONC, 1);
+#endif
+#ifndef APOLLO
+#ifdef TIOCSTART
+      if (!flow_control) ioctl (0, TIOCSTART, 0);
+#endif
+#endif
+
+#ifdef AIX
+      hft_init ();
+#ifdef IBMR2AIX
+      {
+	/* IBM's HFT device usually thinks a ^J should be LF/CR.  We need it
+	   to be only LF.  This is the way that is done. */
+	struct termio tty;
+
+	if (ioctl (1, HFTGETID, &tty) != -1)
+	  write (1, "\033[20l", 5);
+      }
+#endif
+#endif
+
+      /* If going to use CBREAK mode, we must request C-g to interrupt
+	 and turn off start and stop chars, etc.  If not going to use
+	 CBREAK mode, do this anyway so as to turn off local flow
+	 control for user coming over network on 4.2; in this case,
+	 only t_stopc and t_startc really matter.  */
+#ifdef TIOCGLTC
+      ioctl (0, TIOCGLTC, &old_ltchars);
+#endif /* TIOCGLTC */
+#ifndef HAVE_TERMIO
+#ifdef TIOCGETC
+      ioctl (0, TIOCGETC, &old_tchars);
+      ioctl (0, TIOCLGET, &old_lmode);
+
+      /* Note: if not using CBREAK mode, it makes no difference how we set this */
+      tchars = new_tchars;
+      tchars.t_intrc = quit_char;
+      if (flow_control)
+	{
+	  tchars.t_startc = '\021';
+	  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
+
+      lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_lmode;
+
+      ioctl (0, TIOCSETC, &tchars);
+      ioctl (0, TIOCLSET, &lmode);
+#endif /* TIOCGETC */
+#endif /* not HAVE_TERMIO */
+#ifdef TIOCGLTC
+      ioctl (0, TIOCSLTC, &new_ltchars);
+#endif /* TIOCGLTC */
+
+#ifdef VMS
+/*  Appears to do nothing when in PASTHRU mode.
+      SYS$QIOW (0, input_chan, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
+		interrupt_signal, oob_chars, 0, 0, 0, 0);
+*/
+      queue_kbd_input (0);
+#endif /* VMS */
+    }
+
+#ifdef F_SETFL
+#ifdef F_GETOWN		/* F_SETFL does not imply existance of F_GETOWN */
+  if (interrupt_input)
+    {
+      old_fcntl_owner = fcntl (0, F_GETOWN, 0);
+      fcntl (0, F_SETOWN, getpid ());
+      init_sigio ();
+    }
+#endif /* F_GETOWN */
+#endif /* F_SETFL */
+
+#ifdef BSD4_1
+  if (interrupt_input)
+    init_sigio ();
+#endif
+
+#ifdef VMS  /* VMS sometimes has this symbol but lacks setvbuf.  */
+#undef _IOFBF
+#endif
+#ifdef _IOFBF
+  /* This symbol is defined on recent USG systems.
+     Someone says without this call USG won't really buffer the file
+     even with a call to setbuf. */
+  setvbuf (stdout, _sobuf, _IOFBF, sizeof _sobuf);
+#else
+  setbuf (stdout, _sobuf);
+#endif
+  set_terminal_modes ();
+  if (term_initted && no_redraw_on_reenter)
+    {
+      if (display_completed)
+	direct_output_forward_char (0);
+    }
+  else
+    {
+      screen_garbaged = 1;
+#ifdef MULTI_SCREEN
+      if (SCREENP (Vterminal_screen))
+	SCREEN_GARBAGED_P (XSCREEN (Vterminal_screen)) = 1;
+#endif
+    }
+  term_initted = 1;
+}
+
+/* Return nonzero if safe to use tabs in output.
+   At the time this is called, init_sys_modes has not been done yet.  */
+   
+tabs_safe_p ()
+{
+  TERMINAL tty;
+  if (noninteractive)
+    return 1;
+#ifdef VMS
+  SYS$QIOW (0, input_chan, IO$_SENSEMODE, &tty, 0, 0,
+	    &tty.class, 12, 0, 0, 0, 0);
+#else
+  tcgetattr (0, &tty);
+#endif /* not VMS */
+  return (TABS_OK (tty));
+}
+
+/* Get terminal size from system.
+   Store number of lines into *heightp and width into *widthp.
+   If zero or a negative number is stored, the value is not valid.  */
+
+get_screen_size (widthp, heightp)
+     int *widthp, *heightp;
+{
+/* Define the 4.3 names in terms of the Sun names
+   if the latter exist and the former do not.  */
+#ifdef TIOCGSIZE
+#ifndef TIOCGWINSZ
+#define TIOCGWINSZ TIOCGSIZE
+#define winsize ttysize
+#define ws_row ts_lines
+#define ws_col ts_cols
+#endif
+#endif /* Sun */
+
+/* Do it using the 4.3 names if possible.  */
+#ifdef TIOCGWINSZ
+  struct winsize size;
+  *widthp = 0;
+  *heightp = 0;
+  if (ioctl (0, TIOCGWINSZ, &size) < 0)
+    return;
+  *widthp = size.ws_col;
+  *heightp = size.ws_row;
+#else /* not TIOCGWNSIZ */
+#ifdef VMS
+  TERMINAL tty;
+  SYS$QIOW (0, input_chan, IO$_SENSEMODE, &tty, 0, 0,
+	    &tty.class, 12, 0, 0, 0, 0);
+  *widthp = tty.scr_wid;
+  *heightp = tty.scr_len;
+#else /* system doesn't know size */
+  *widthp = 0;
+  *heightp = 0;
+#endif /* system does not know size */
+#endif /* not TIOCGWINSZ */
+}
+
+reset_sys_modes ()
+{
+  if (noninteractive)
+    {
+      fflush (stdout);
+      return;
+    }
+  if (!term_initted)
+    return;
+  if (read_socket_hook || !EQ (Vwindow_system, Qnil))
+    return;
+  cursor_to (SCREEN_HEIGHT (selected_screen) - 1, 0);
+  clear_end_of_line (SCREEN_WIDTH (selected_screen));
+  /* clear_end_of_line may move the cursor */
+  cursor_to (SCREEN_HEIGHT (selected_screen) - 1, 0);
+#ifdef IBMR2AIX
+  {
+    /* HFT devices normally use ^J as a LF/CR.  We forced it to 
+       do the LF only.  Now, we need to reset it. */
+    struct termio tty;
+
+    if (ioctl (1, HFTGETID, &tty) != -1)
+      write (1, "\033[20h", 5);
+  }
+#endif
+
+  reset_terminal_modes ();
+  fflush (stdout);
+#ifdef BSD
+#ifndef BSD4_1
+  /* Avoid possible loss of output when changing terminal modes.  */
+  fsync (fileno (stdout));
+#endif
+#endif
+#ifdef TIOCGLTC
+  ioctl (0, TIOCSLTC, &old_ltchars);
+#endif /* TIOCGLTC */
+#ifndef HAVE_TERMIO
+#ifdef TIOCGETC
+  ioctl (0, TIOCSETC, &old_tchars);
+  ioctl (0, TIOCLSET, &old_lmode);
+#endif /* TIOCGETC */
+#endif /* not HAVE_TERMIO */
+#ifdef F_SETFL
+#ifdef F_SETOWN		/* F_SETFL does not imply existance of F_SETOWN */
+  if (interrupt_input)
+    {
+      reset_sigio ();
+      fcntl (0, F_SETOWN, old_fcntl_owner);
+    }
+#endif /* F_SETOWN */
+#endif /* F_SETFL */
+#ifdef BSD4_1
+  if (interrupt_input)
+    reset_sigio ();
+#endif /* BSD4_1 */
+#ifdef VMS
+  end_kbd_input ();
+  SYS$QIOW (0, input_chan, IO$_SETMODE, &input_iosb, 0, 0,
+	    &old_gtty.class, 12, 0, 0, 0, 0);
+#else /* not VMS */
+#ifndef HAVE_TCATTR
+  while (ioctl (0, TCSETAW, &old_gtty) < 0 && errno == EINTR);
+#else
+  while (tcsetattr (0, TCSADRAIN, &old_gtty) < 0 && errno == EINTR);
+#endif
+#endif /* not VMS */
+
+#ifdef AIX
+  hft_reset ();
+#endif
+}
+
+#ifdef HAVE_PTYS
+
+/* Set up the proper status flags for use of a pty.  */
+
+setup_pty (fd)
+     int fd;
+{
+  /* I'm told that TOICREMOTE does not mean control chars
+     "can't be sent" but rather that they don't have
+     input-editing or signaling effects.
+     That should be good, because we have other ways
+     to do those things in Emacs.
+     However, telnet mode seems not to work on 4.2.
+     So TIOCREMOTE is turned off now. */
+
+  /* Under hp-ux, if TIOCREMOTE is turned on, some calls
+     will hang.  In particular, the "timeout" feature (which
+     causes a read to return if there is no data available)
+     does this.  Also it is known that telnet mode will hang
+     in such a way that Emacs must be stopped (perhaps this
+     is the same problem).
+     
+     If TIOCREMOTE is turned off, then there is a bug in
+     hp-ux which sometimes loses data.  Apparently the
+     code which blocks the master process when the internal
+     buffer fills up does not work.  Other than this,
+     though, everything else seems to work fine.
+     
+     Since the latter lossage is more benign, we may as well
+     lose that way.  -- cph */
+#ifdef FIONBIO
+#ifdef SYSV_PTYS
+  {
+    int on = 1;
+    ioctl (fd, FIONBIO, &on);
+  }
+#endif
+#endif
+#ifdef IBMRTAIX
+  /* On AIX, the parent gets SIGHUP when a pty attached child dies.  So, we */
+  /* ignore SIGHUP once we've started a child on a pty.  Note that this may */
+  /* cause EMACS not to die when it should, i.e., when its own controlling  */
+  /* tty goes away.  I've complained to the AIX developers, and they may    */
+  /* change this behavior, but I'm not going to hold my breath.             */
+  signal (SIGHUP, SIG_IGN);
+#endif
+}
+#endif /* HAVE_PTYS */
+
+#ifdef VMS
+
+/* Assigning an input channel is done at the start of Emacs execution.
+   This is called each time Emacs is resumed, also, but does nothing
+   because input_chain is no longer zero.  */
+
+init_vms_input ()
+{
+  int status;
+  
+  if (input_chan == 0)
+    {
+      status = SYS$ASSIGN (&input_dsc, &input_chan, 0, 0);
+      if (! (status & 1))
+	LIB$STOP (status);
+    }
+}
+
+/* Deassigning the input channel is done before exiting.  */
+
+stop_vms_input ()
+{
+  return SYS$DASSGN (input_chan);
+}
+
+short input_buffer;
+
+/* Request reading one character into the keyboard buffer.
+   This is done as soon as the buffer becomes empty.  */
+
+queue_kbd_input ()
+{
+  int status;
+  waiting_for_ast = 0;
+  stop_input = 0;
+  status = SYS$QIO (0, input_chan, IO$_READVBLK,
+		    &input_iosb, kbd_input_ast, 1,
+		    &input_buffer, 1, 0, terminator_mask, 0, 0);
+}
+
+int input_count;
+
+/* Ast routine that is called when keyboard input comes in
+   in accord with the SYS$QIO above.  */
+
+kbd_input_ast ()
+{
+  register int c = -1;
+  int old_errno = errno;
+  extern int *input_available_clear_word;
+
+  if (waiting_for_ast)
+    SYS$SETEF (input_ef);
+  waiting_for_ast = 0;
+  input_count++;
+#ifdef ASTDEBUG
+  if (input_count == 25)
+    exit (1);
+  printf ("Ast # %d,", input_count);
+  printf (" iosb = %x, %x, %x, %x",
+	  input_iosb.offset, input_iosb.status, input_iosb.termlen,
+	  input_iosb.term);
+#endif
+  if (input_iosb.offset)
+    {
+      c = input_buffer;
+#ifdef ASTDEBUG
+      printf (", char = 0%o", c);
+#endif
+    }
+#ifdef ASTDEBUG
+  printf ("\n");
+  fflush (stdout);
+  sleep (1);
+#endif
+  if (! stop_input)
+    queue_kbd_input ();
+  if (c >= 0)
+    {
+      struct input_event e;
+      e.kind = ascii_keystroke;
+      XSET (buf[i].code, Lisp_Int, cbuf[i]);
+      e.screen = selected_screen;
+      kbd_buffer_store_event (&e);
+    }
+
+  if (input_available_clear_word)
+    *input_available_clear_word = 0;
+  errno = old_errno;
+}
+
+/* Wait until there is something in kbd_buffer.  */
+
+wait_for_kbd_input ()
+{
+  extern int have_process_input, process_exited;
+
+  /* If already something, avoid doing system calls.  */
+  if (detect_input_pending ())
+    {
+      return;
+    }
+  /* Clear a flag, and tell ast routine above to set it.  */
+  SYS$CLREF (input_ef);
+  waiting_for_ast = 1;
+  /* Check for timing error: ast happened while we were doing that.  */
+  if (!detect_input_pending ())
+    {
+      /* No timing error: wait for flag to be set.  */
+      set_waiting_for_input (0);
+      SYS$WFLOR (input_ef, input_eflist);
+      clear_waiting_for_input (0);
+      if (!detect_input_pending ())
+	/* Check for subprocess input availability */
+	{
+	  int dsp = have_process_input || process_exited;
+
+	  SYS$CLREF (process_ef);
+	  if (have_process_input)
+	    process_command_input ();
+	  if (process_exited)
+	    process_exit ();
+	  if (dsp)
+	    {
+	      update_mode_lines++;
+	      redisplay_preserve_echo_area ();
+	    }
+	}
+    }
+  waiting_for_ast = 0;
+}
+
+/* Get rid of any pending QIO, when we are about to suspend
+   or when we want to throw away pending input.
+   We wait for a positive sign that the AST routine has run
+   and therefore there is no I/O request queued when we return.
+   SYS$SETAST is used to avoid a timing error.  */
+
+end_kbd_input ()
+{
+#ifdef ASTDEBUG
+  printf ("At end_kbd_input.\n");
+  fflush (stdout);
+  sleep (1);
+#endif
+  if (LIB$AST_IN_PROG ())  /* Don't wait if suspending from kbd_buffer_store_event! */
+    {
+      SYS$CANCEL (input_chan);
+      return;
+    }
+
+  SYS$SETAST (0);
+  /* Clear a flag, and tell ast routine above to set it.  */
+  SYS$CLREF (input_ef);
+  waiting_for_ast = 1;
+  stop_input = 1;
+  SYS$CANCEL (input_chan);
+  SYS$SETAST (1);
+  SYS$WAITFR (input_ef);
+  waiting_for_ast = 0;
+}
+
+/* Wait for either input available or time interval expiry.  */
+
+input_wait_timeout (timeval)
+     int timeval;		/* Time to wait, in seconds */
+{
+  int time [2];
+  static int zero = 0;
+  static int large = -10000000;
+
+  LIB$EMUL (&timeval, &large, &zero, time); 	  /* Convert to VMS format */
+
+  /* If already something, avoid doing system calls.  */
+  if (detect_input_pending ())
+    {
+      return;
+    }
+  /* Clear a flag, and tell ast routine above to set it.  */
+  SYS$CLREF (input_ef);
+  waiting_for_ast = 1;
+  /* Check for timing error: ast happened while we were doing that.  */
+  if (!detect_input_pending ())
+    {
+      /* No timing error: wait for flag to be set.  */
+      SYS$CANTIM (1, 0);
+      if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
+	SYS$WFLOR (timer_ef, timer_eflist);	  /* Wait for timer expiry or input */
+    }
+  waiting_for_ast = 0;
+}
+
+/* The standard `sleep' routine works some other way
+   and it stops working if you have ever quit out of it.
+   This one continues to work.  */
+
+sys_sleep (timeval)
+     int timeval;
+{
+  int time [2];
+  static int zero = 0;
+  static int large = -10000000;
+  
+  LIB$EMUL (&timeval, &large, &zero, time); 	  /* Convert to VMS format */
+
+  SYS$CANTIM (1, 0);
+  if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
+    SYS$WAITFR (timer_ef);	  /* Wait for timer expiry only */
+}
+
+init_sigio ()
+{
+  request_sigio ();
+}
+
+reset_sigio ()
+{
+  unrequest_sigio ();
+}
+
+request_sigio ()
+{
+  croak ("request sigio");
+}
+
+unrequest_sigio ()
+{
+  croak ("unrequest sigio");
+}
+
+#endif /* VMS */
+
+/* Note that VMS compiler won't accept defined (CANNOT_DUMP).  */
+#ifndef CANNOT_DUMP
+#define NEED_STARTS
+#endif
+
+#ifndef SYSTEM_MALLOC
+#ifndef NEED_STARTS
+#define NEED_STARTS
+#endif
+#endif
+
+#ifdef NEED_STARTS
+/* Some systems that cannot dump also cannot implement these.  */
+
+/*
+ *	Return the address of the start of the text segment prior to
+ *	doing an unexec.  After unexec the return value is undefined.
+ *	See crt0.c for further explanation and _start.
+ *
+ */
+
+#ifndef CANNOT_UNEXEC
+char *
+start_of_text ()
+{
+#ifdef TEXT_START
+  return ((char *) TEXT_START);
+#else
+#ifdef GOULD
+  extern csrt ();
+  return ((char *) csrt);
+#else /* not GOULD */
+  extern int _start ();
+  return ((char *) _start);
+#endif /* GOULD */
+#endif /* TEXT_START */
+}
+#endif /* not CANNOT_UNEXEC */
+
+/*
+ *	Return the address of the start of the data segment prior to
+ *	doing an unexec.  After unexec the return value is undefined.
+ *	See crt0.c for further information and definition of data_start.
+ *
+ *	Apparently, on BSD systems this is etext at startup.  On
+ *	USG systems (swapping) this is highly mmu dependent and
+ *	is also dependent on whether or not the program is running
+ *	with shared text.  Generally there is a (possibly large)
+ *	gap between end of text and start of data with shared text.
+ *
+ *	On Uniplus+ systems with shared text, data starts at a
+ *	fixed address.  Each port (from a given oem) is generally
+ *	different, and the specific value of the start of data can
+ *	be obtained via the UniPlus+ specific "uvar" system call,
+ *	however the method outlined in crt0.c seems to be more portable.
+ *
+ *	Probably what will have to happen when a USG unexec is available,
+ *	at least on UniPlus, is temacs will have to be made unshared so
+ *	that text and data are contiguous.  Then once loadup is complete,
+ *	unexec will produce a shared executable where the data can be
+ *	at the normal shared text boundry and the startofdata variable
+ *	will be patched by unexec to the correct value.
+ *
+ */
+ 
+char *
+start_of_data ()
+{
+#ifdef DATA_START
+  return ((char *) DATA_START);
+#else
+  extern int data_start;
+  return ((char *) &data_start);
+#endif
+}
+#endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
+
+#ifndef CANNOT_DUMP
+/* Some systems that cannot dump also cannot implement these.  */
+
+/*
+ *	Return the address of the end of the text segment prior to
+ *	doing an unexec.  After unexec the return value is undefined.
+ */
+ 
+char *
+end_of_text ()
+{
+#ifdef TEXT_END
+  return ((char *) TEXT_END);
+#else
+  extern int etext;
+  return ((char *) &etext);
+#endif
+}
+ 
+/*
+ *	Return the address of the end of the data segment prior to
+ *	doing an unexec.  After unexec the return value is undefined.
+ */
+
+char *
+end_of_data ()
+{
+#ifdef DATA_END
+  return ((char *) DATA_END);
+#else
+  extern int edata;
+  return ((char *) &edata);
+#endif
+}
+
+#endif /* not CANNOT_DUMP */
+
+/* Get_system_name returns as its value
+ a string for the Lisp function system-name to return. */
+
+#ifdef BSD4_1
+#include <whoami.h>
+#endif
+
+#ifdef USG
+/* Can't have this within the function since `static' is #defined to nothing */
+static struct utsname get_system_name_name;
+#endif
+
+char *
+get_system_name ()
+{
+#ifdef USG
+  uname (&get_system_name_name);
+  return (get_system_name_name.nodename);
+#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
+    {
+      char *end;
+
+      if ((end = index (sp, ':')) != 0)
+	*end = '\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 */
+}
+
+#ifndef VMS
+#ifndef HAVE_SELECT
+
+#ifdef HAVE_X_WINDOWS
+/* Cause explanatory error message at compile time,
+   since the select emulation is not good enough for X.  */
+int *x = &x_windows_lose_if_no_select_system_call;
+#endif
+
+/* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
+ * Only checks read descriptors.
+ */
+/* How long to wait between checking fds in select */
+#define SELECT_PAUSE 1
+int select_alarmed;
+
+/* For longjmp'ing back to read_input_waiting.  */
+
+jmp_buf read_alarm_throw;
+
+/* Nonzero if the alarm signal should throw back to read_input_waiting.
+   The read_socket_hook function sets this to 1 while it is waiting.  */
+
+int read_alarm_should_throw;
+
+SIGTYPE
+select_alarm ()
+{
+  select_alarmed = 1;
+#ifdef BSD4_1
+  sigrelse (SIGALRM);
+#else /* not BSD4_1 */
+  signal (SIGALRM, SIG_IGN);
+#endif /* not BSD4_1 */
+  if (read_alarm_should_throw)
+    longjmp (read_alarm_throw, 1);
+}
+
+/* Only rfds are checked.  */
+int
+select (nfds, rfds, wfds, efds, timeout)
+     int nfds;
+     int *rfds, *wfds, *efds, *timeout;
+{
+  int ravail = 0, orfds = 0, old_alarm;
+  int timeoutval = timeout ? *timeout : 100000;
+  int *local_timeout = &timeoutval;
+  extern int proc_buffered_char[];
+#ifndef subprocesses
+  int process_tick = 0, update_tick = 0;
+#else
+  extern int process_tick, update_tick;
+#endif
+  SIGTYPE (*old_trap) ();
+  unsigned char buf;
+
+  if (rfds)
+    {
+      orfds = *rfds;
+      *rfds = 0;
+    }
+  if (wfds)
+    *wfds = 0;
+  if (efds)
+    *efds = 0;
+
+  /* If we are looking only for the terminal, with no timeout,
+     just read it and wait -- that's more efficient.  */
+  if (orfds == 1 && *local_timeout == 100000 && process_tick == update_tick)
+    {
+      if (! detect_input_pending ())
+	read_input_waiting ();
+      *rfds = 1;
+      return 1;
+    }
+
+  /* Once a second, till the timer expires, check all the flagged read
+   * descriptors to see if any input is available.  If there is some then
+   * set the corresponding bit in the return copy of rfds.
+   */ 
+  while (1)
+    {
+      register int to_check, bit, fd;
+
+      if (rfds)
+	{
+	  for (to_check = nfds, bit = 1, fd = 0; --to_check >= 0; bit <<= 1, fd++)
+	    {
+	      if (orfds & bit)
+		{
+		  int avail = 0, status = 0;
+
+		  if (bit == 1)
+		    avail = detect_input_pending (); /* Special keyboard handler */
+		  else
+		    {
+#ifdef FIONREAD
+		      status = ioctl (fd, FIONREAD, &avail);
+#else /* no FIONREAD */
+		      /* Hoping it will return -1 if nothing available
+			 or 0 if all 0 chars requested are read.  */
+		      if (proc_buffered_char[fd] >= 0)
+			avail = 1;
+		      else
+			{
+			  avail = read (fd, &buf, 1);
+			  if (avail > 0)
+			    proc_buffered_char[fd] = buf;
+			}
+#endif /* no FIONREAD */
+		    }
+		  if (status >= 0 && avail > 0)
+		    {
+		      (*rfds) |= bit;
+		      ravail++;
+		    }
+		}
+	    }
+	}
+      if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
+	break;
+      old_alarm = alarm (0);
+      old_trap = (int (*)()) signal (SIGALRM, select_alarm);
+      select_alarmed = 0;
+      alarm (SELECT_PAUSE);
+      /* Wait for a SIGALRM (or maybe a SIGTINT) */
+      while (select_alarmed == 0 && *local_timeout != 0
+	     && process_tick == update_tick)
+	{
+	  /* If we are interested in terminal input,
+	     wait by reading the terminal.
+	     That makes instant wakeup for terminal input at least.  */
+	  if (orfds & 1)
+	    {
+	      read_input_waiting ();
+	      if (detect_input_pending ())
+		select_alarmed = 1;
+	    }
+	  else
+	    pause ();
+	}
+      (*local_timeout) -= SELECT_PAUSE;
+      /* Reset the old alarm if there was one */
+      alarm (0);
+      signal (SIGALRM, old_trap);
+      if (old_alarm != 0)
+	{
+	  /* Reset or forge an interrupt for the original handler. */
+	  old_alarm -= SELECT_PAUSE;
+	  if (old_alarm <= 0)
+	    kill (getpid (), SIGALRM); /* Fake an alarm with the orig' handler */
+	  else
+	    alarm (old_alarm);
+	}
+      if (*local_timeout == 0)  /* Stop on timer being cleared */
+	break;
+    }
+  return ravail;
+}
+
+/* Read keyboard input into the standard buffer,
+   waiting for at least one character.  */
+
+/* Make all keyboard buffers much bigger when using X windows.  */
+#ifdef HAVE_X_WINDOWS
+#define BUFFER_SIZE_FACTOR 16
+#else
+#define BUFFER_SIZE_FACTOR 1
+#endif
+
+read_input_waiting ()
+{
+  char buf[256 * BUFFER_SIZE_FACTOR];
+  struct input_event e;
+  int nread;
+
+  if (read_socket_hook)
+    {
+      read_alarm_should_throw = 0;
+      if (! setjmp (read_alarm_throw))
+	nread = (*read_socket_hook) (0, buf, 256 * BUFFER_SIZE_FACTOR, 1, 0);
+      else
+	nread = -1;
+    }
+  else
+    nread = read (fileno (stdin), buf, 1);
+
+  /* Scan the chars for C-g and store them in kbd_buffer.  */
+  e.kind = ascii_keystroke;
+  e.screen = selected_screen;
+  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] == Ctl ('G'))
+	break;
+    }
+}
+
+#endif /* not HAVE_SELECT */
+#endif /* not VMS */
+
+#ifdef BSD4_1
+/* VARARGS */
+setpriority ()
+{
+  return 0;
+}
+
+/*
+ * Partially emulate 4.2 open call.
+ * open is defined as this in 4.1.
+ *
+ * - added by Michael Bloom @ Citicorp/TTI
+ *
+ */
+
+int
+sys_open (path, oflag, mode)
+     char *path;
+     int oflag, mode;
+{
+  if (oflag & O_CREAT) 
+    return creat (path, mode);
+  else
+    return open (path, oflag);
+}
+
+init_sigio ()
+{
+  if (noninteractive)
+    return;
+  lmode = LINTRUP | lmode;
+  ioctl (0, TIOCLSET, &lmode);
+}
+
+reset_sigio ()
+{
+  if (noninteractive)
+    return;
+  lmode = ~LINTRUP & lmode;
+  ioctl (0, TIOCLSET, &lmode);
+}
+
+request_sigio ()
+{
+  sigrelse (SIGTINT);
+
+  interrupts_deferred = 0;
+}
+
+unrequest_sigio ()
+{
+  sighold (SIGTINT);
+
+  interrupts_deferred = 1;
+}
+
+/* still inside #ifdef BSD4_1 */
+#ifdef subprocesses
+
+int sigheld; /* Mask of held signals */
+
+sigholdx (signum)
+     int signum;
+{
+  sigheld |= sigbit (signum);
+  sighold (signum);
+}
+
+sigisheld (signum)
+     int signum;
+{
+  sigheld |= sigbit (signum);
+}
+
+sigunhold (signum)
+     int signum;
+{
+  sigheld &= ~sigbit (signum);
+  sigrelse (signum);
+}
+
+sigfree ()    /* Free all held signals */
+{
+  int i;
+  for (i = 0; i < NSIG; i++)
+    if (sigheld & sigbit (i))
+      sigrelse (i);
+  sigheld = 0;
+}
+
+sigbit (i)
+{
+  return 1 << (i - 1);
+}
+#endif /* subprocesses */
+#endif /* BSD4_1 */
+
+/* POSIX signals support - DJB */
+/* Anyone with POSIX signals should have ANSI C declarations */
+
+#ifdef POSIX_SIGNALS
+
+sigset_t old_mask, empty_mask, full_mask, temp_mask;
+static struct sigaction new_action, old_action;
+
+init_signals ()
+{
+#ifdef POSIX_SIGNALS
+  sigemptyset (&signal_empty_mask);
+  sigfillset (&signal_full_mask);
+#endif
+}
+
+int (*signal_handler_t) ();
+
+signal_handler_t
+sys_signal (int signal_number, signal_handler_t action)
+{
+#ifdef DGUX
+  /* This gets us restartable system calls for efficiency.
+     The "else" code will works as well. */
+  return (berk_signal (signal_number, action));
+#else
+  sigemptyset (&new_action.sa_mask);
+  new_action.sa_handler = action;
+  new_action.sa_flags = NULL;
+  new_action (signal_number, &new_action, &old_action);
+  return (old_action.sa_handler);
+#endif /* DGUX */
+}
+
+int
+sys_sigpause (sigset_t new_mask)
+{
+  /* pause emulating berk sigpause... */
+  sigsuspend (&new_mask);
+  return (EINTR);
+}
+
+/* I'd like to have these guys return pointers to the mask storage in here,
+   but there'd be trouble if the code was saving multiple masks.  I'll be
+   safe and pass the structure.  It normally won't be more than 2 bytes
+   anyhow. - DJB */
+
+sigset_t
+sys_sigblock (sigset_t new_mask)
+{
+  sigset_t old_mask;
+  sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
+  return (old_mask);
+}
+
+sigset_t
+sys_sigunblock (sigset_t new_mask)
+{
+  sigset_t old_mask;
+  sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask);
+  return (old_mask);
+}
+
+sigset_t
+sys_sigsetmask (sigset_t new_mask)
+{
+  sigset_t old_mask;
+  sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
+  return (old_mask);
+}
+
+#endif /* POSIX_SIGNALS */
+
+#ifndef BSTRING
+
+void
+bzero (b, length)
+     register char *b;
+     register int length;
+{
+#ifdef VMS
+  short zero = 0;
+  long max_str = 65535;
+
+  while (length > max_str) {
+    (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
+    length -= max_str;
+    b += max_str;
+  }
+  max_str = length;
+  (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
+#else
+  while (length-- > 0)
+    *b++ = 0;
+#endif /* not VMS */
+}
+
+/* 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)
+     register char *b1;
+     register char *b2;
+     register int length;
+{
+#ifdef VMS
+  long max_str = 65535;
+
+  while (length > max_str) {
+    (void) LIB$MOVC3 (&max_str, b1, b2);
+    length -= max_str;
+    b1 += max_str;
+    b2 += max_str;
+  }
+  max_str = length;
+  (void) LIB$MOVC3 (&length, b1, b2);
+#else
+  while (length-- > 0)
+    *b2++ = *b1++;
+#endif /* not VMS */
+}
+
+int
+bcmp (b1, b2, length)	/* This could be a macro! */
+     register char *b1;
+     register char *b2;
+     register int length;
+{
+#ifdef VMS
+  struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
+  struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
+
+  return STR$COMPARE (&src1, &src2);
+#else
+  while (length-- > 0)
+    if (*b1++ != *b2++)
+      return 1;
+
+  return 0;
+#endif /* not VMS */
+}
+#endif /* not BSTRING */
+
+#ifdef USG
+/*
+ *	The BSD random returns numbers in the range of
+ *	0 to 2e31 - 1.  The USG rand returns numbers in the
+ *	range of 0 to 2e15 - 1.  This is probably not significant
+ *	in this usage.
+ */
+  
+long
+random ()
+{
+  /* Arrange to return a range centered on zero.  */
+  return (rand () << 15) + rand () - (1 << 29);
+}
+
+srandom (arg)
+     int arg;
+{
+  srand (arg);
+}
+
+#endif /* USG */
+
+#ifdef BSD4_1
+long random ()
+{
+  /* Arrange to return a range centered on zero.  */
+  return (rand () << 15) + rand () - (1 << 29);
+}
+
+srandom (arg)
+     int arg;
+{
+  srand (arg);
+}
+#endif /* BSD4_1 */
+
+#ifdef WRONG_NAME_INSQUE
+
+insque (q,p)
+     caddr_t q,p;
+{
+  _insque (q,p);
+}
+
+#endif
+
+#ifdef VMS
+
+#ifdef getenv
+/* If any place else asks for the TERM variable,
+   allow it to be overridden with the EMACS_TERM variable
+   before attempting to translate the logical name TERM.  As a last
+   resort, ask for VAX C's special idea of the TERM variable.  */
+#undef getenv
+char *
+sys_getenv (name)
+     char *name;
+{
+  register char *val;
+  static char buf[256];
+  static struct dsc$descriptor_s equiv
+    = {sizeof (buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf};
+  static struct dsc$descriptor_s d_name
+    = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
+  short eqlen;
+
+  if (!strcmp (name, "TERM"))
+    {
+      val = (char *) getenv ("EMACS_TERM");
+      if (val)
+	return val;
+    }
+
+  d_name.dsc$w_length = strlen (name);
+  d_name.dsc$a_pointer = name;
+  if (lib$sys_trnlog (&d_name, &eqlen, &equiv) == 1)
+    {
+      char *str = (char *) xmalloc (eqlen + 1);
+      bcopy (buf, str, eqlen);
+      str[eqlen] = '\0';
+      /* This is a storage leak, but a pain to fix.  With luck,
+	 no one will ever notice.  */
+      return str;
+    }
+  return (char *) getenv (name);
+}
+#endif /* getenv */
+
+#ifdef abort
+/* Since VMS doesn't believe in core dumps, the only way to debug this beast is
+   to force a call on the debugger from within the image. */
+#undef abort
+sys_abort ()
+{
+  reset_sys_modes ();
+  LIB$SIGNAL (SS$_DEBUG);
+}
+#endif /* abort */
+#endif /* VMS */
+
+#ifdef VMS
+#ifdef LINK_CRTL_SHARE
+#ifdef SHAREABLE_LIB_BUG
+/* Variables declared noshare and initialized in shareable 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. */
+int sys_nerr = 35;
+char *sys_errlist[] =
+  {
+    "error 0",
+    "not owner",
+    "no such file or directory",
+    "no such process",
+    "interrupted system call",
+    "i/o error",
+    "no such device or address",
+    "argument list too long",
+    "exec format error",
+    "bad file number",
+    "no child process",
+    "no more processes",
+    "not enough memory",
+    "permission denied",
+    "bad address",
+    "block device required",
+    "mount devices busy",
+    "file exists",
+    "cross-device link",
+    "no such device",
+    "not a directory",
+    "is a directory",
+    "invalid argument",
+    "file table overflow",
+    "too many open files",
+    "not a typewriter",
+    "text file busy",
+    "file too big",
+    "no space left on device",
+    "illegal seek",
+    "read-only file system",
+    "too many links",
+    "broken pipe",
+    "math argument",
+    "result too large",
+    "I/O stream empty",
+    "vax/vms specific error code nontranslatable error"
+  };
+#endif /* SHAREABLE_LIB_BUG */
+#endif /* LINK_CRTL_SHARE */
+#endif /* VMS */
+
+#ifdef INTERRUPTIBLE_OPEN
+
+int
+/* VARARGS 2 */
+sys_open (path, oflag, mode)
+     char *path;
+     int oflag, mode;
+{
+  register int rtnval;
+  
+  while ((rtnval = open (path, oflag, mode)) == -1
+	 && (errno == EINTR));
+  return (rtnval);
+}
+
+#endif /* INTERRUPTIBLE_OPEN */
+
+#ifdef INTERRUPTIBLE_CLOSE
+
+sys_close (fd)
+     int fd;
+{
+  register int rtnval;
+
+  while ((rtnval = close (fd)) == -1
+	 && (errno == EINTR));
+  return rtnval;
+}
+
+#endif /* INTERRUPTIBLE_CLOSE */
+
+#ifdef INTERRUPTIBLE_IO
+
+int
+sys_read (fildes, buf, nbyte)
+     int fildes;
+     char *buf;
+     unsigned int nbyte;
+{
+  register int rtnval;
+  
+  while ((rtnval = read (fildes, buf, nbyte)) == -1
+	 && (errno == EINTR));
+  return (rtnval);
+}
+
+int
+sys_write (fildes, buf, nbyte)
+     int fildes;
+     char *buf;
+     unsigned int nbyte;
+{
+  register int rtnval;
+
+  while ((rtnval = write (fildes, buf, nbyte)) == -1
+	 && (errno == EINTR));
+  return (rtnval);
+}
+
+#endif /* INTERRUPTIBLE_IO */
+
+#ifdef USG
+/*
+ *	All of the following are for USG.
+ *
+ *	On USG systems the system calls are INTERRUPTIBLE by signals
+ *	that the user program has elected to catch.  Thus the system call
+ *	must be retried in these cases.  To handle this without massive
+ *	changes in the source code, we remap the standard system call names
+ *	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
+ *	adds an extra level of function call overhead but it is almost
+ *	always negligible.   Fred Fish, Unisoft Systems Inc.
+ */
+
+char *sys_siglist[NSIG + 1] =
+{
+#ifdef AIX
+/* AIX has changed the signals a bit */
+  "bogus signal",			/* 0 */
+  "hangup",				/* 1  SIGHUP */
+  "interrupt",				/* 2  SIGINT */
+  "quit",				/* 3  SIGQUIT */
+  "illegal instruction",		/* 4  SIGILL */
+  "trace trap",				/* 5  SIGTRAP */
+  "IOT instruction",			/* 6  SIGIOT */
+  "crash likely",			/* 7  SIGDANGER */
+  "floating point exception",		/* 8  SIGFPE */
+  "kill",				/* 9  SIGKILL */
+  "bus error",				/* 10 SIGBUS */
+  "segmentation violation",		/* 11 SIGSEGV */
+  "bad argument to system call",	/* 12 SIGSYS */
+  "write on a pipe with no one to read it", /* 13 SIGPIPE */
+  "alarm clock",			/* 14 SIGALRM */
+  "software termination signum",	/* 15 SIGTERM */
+  "user defined signal 1",		/* 16 SIGUSR1 */
+  "user defined signal 2",		/* 17 SIGUSR2 */
+  "death of a child",			/* 18 SIGCLD */
+  "power-fail restart",			/* 19 SIGPWR */
+  "bogus signal",			/* 20 */
+  "bogus signal",			/* 21 */
+  "bogus signal",			/* 22 */
+  "bogus signal",			/* 23 */
+  "bogus signal",			/* 24 */
+  "LAN I/O interrupt",			/* 25 SIGAIO */
+  "PTY I/O interrupt",			/* 26 SIGPTY */
+  "I/O intervention required",		/* 27 SIGIOINT */
+  "HFT grant",				/* 28 SIGGRANT */
+  "HFT retract",			/* 29 SIGRETRACT */
+  "HFT sound done",			/* 30 SIGSOUND */
+  "HFT input ready",			/* 31 SIGMSG */
+#else /* not AIX */
+  "bogus signal",			/* 0 */
+  "hangup",				/* 1  SIGHUP */
+  "interrupt",				/* 2  SIGINT */
+  "quit",				/* 3  SIGQUIT */
+  "illegal instruction",		/* 4  SIGILL */
+  "trace trap",				/* 5  SIGTRAP */
+  "IOT instruction",			/* 6  SIGIOT */
+  "EMT instruction",			/* 7  SIGEMT */
+  "floating point exception",		/* 8  SIGFPE */
+  "kill",				/* 9  SIGKILL */
+  "bus error",				/* 10 SIGBUS */
+  "segmentation violation",		/* 11 SIGSEGV */
+  "bad argument to system call",	/* 12 SIGSYS */
+  "write on a pipe with no one to read it", /* 13 SIGPIPE */
+  "alarm clock",			/* 14 SIGALRM */
+  "software termination signum",	/* 15 SIGTERM */
+  "user defined signal 1",		/* 16 SIGUSR1 */
+  "user defined signal 2",		/* 17 SIGUSR2 */
+  "death of a child",			/* 18 SIGCLD */
+  "power-fail restart",			/* 19 SIGPWR */
+#endif /* not AIX */
+  0
+  };
+
+/*
+ *	Warning, this function may not duplicate 4.2 action properly
+ *	under error conditions.
+ */
+
+#ifndef MAXPATHLEN
+/* In 4.1, param.h fails to define this.  */
+#define MAXPATHLEN 1024
+#endif
+
+#ifndef HAVE_GETWD
+
+char *
+getwd (pathname)
+     char *pathname;
+{
+  char *npath, *spath;
+  extern char *getcwd ();
+
+  spath = npath = getcwd ((char *) 0, MAXPATHLEN);
+  /* On Altos 3068, getcwd can return @hostname/dir, so discard
+     up to first slash.  Should be harmless on other systems.  */
+  while (*npath && *npath != '/')
+    npath++;
+  strcpy (pathname, npath);
+  free (spath);			/* getcwd uses malloc */
+  return pathname;
+}
+
+#endif /* HAVE_GETWD */
+
+/*
+ *	Emulate rename using unlink/link.  Note that this is
+ *	only partially correct.  Also, doesn't enforce restriction
+ *	that files be of same type (regular->regular, dir->dir, etc).
+ */
+
+rename (from, to)
+     char *from;
+     char *to;
+{
+  if (access (from, 0) == 0)
+    {
+      unlink (to);
+      if (link (from, to) == 0)
+	if (unlink (from) == 0)
+	  return (0);
+    }
+  return (-1);
+}
+
+/* Set priority value to PRIO.  */
+
+void
+setpriority (which, who, prio)
+     int which, who, prio;
+{
+  int nice ();
+
+  nice (prio - nice (0));
+  return (0);
+}
+
+#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.  */
+
+utimes ()
+{
+}
+#endif
+
+#ifdef IRIS_UTIME
+
+/* The IRIS (3.5) has timevals, but uses sys V utime, and doesn't have the
+   utimbuf structure defined anywhere but in the man page. */
+
+struct utimbuf
+ {
+   long actime;
+   long modtime;
+ };
+
+utimes (name, tvp)
+     char *name;
+     struct timeval tvp[];
+{
+  struct utimbuf utb;
+  utb.actime  = tvp[0].tv_sec;
+  utb.modtime = tvp[1].tv_sec;
+  utime (name, &utb);
+}
+#endif /* IRIS_UTIME */
+
+
+#ifdef HPUX
+#ifndef HAVE_PERROR
+
+/* HPUX curses library references perror, but as far as we know
+   it won't be called.  Anyway this definition will do for now.  */
+
+perror ()
+{
+}
+
+#endif /* not HAVE_PERROR */
+#endif /* HPUX */
+
+#ifndef HAVE_DUP2
+
+/*
+ *	Emulate BSD dup2.  First close newd if it already exists.
+ *	Then, attempt to dup oldd.  If not successful, call dup2 recursively
+ *	until we are, then close the unsuccessful ones.
+ */
+
+dup2 (oldd, newd)
+     int oldd;
+     int newd;
+{
+  register int fd, ret;
+  
+  sys_close (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]);
+#else
+  fd = dup (old);
+  if (fd == -1)
+    return -1;
+  if (fd == new)
+    return new;
+  ret = dup2 (old,new);
+  sys_close (fd);
+  return ret;
+#endif
+}
+
+#endif /* not HAVE_DUP2 */
+
+/*
+ *	Gettimeofday.  Simulate as much as possible.  Only accurate
+ *	to nearest second.  Emacs doesn't use tzp so ignore it for now.
+ *	Only needed when subprocesses are defined.
+ */
+
+#ifdef subprocesses
+#ifndef VMS
+#ifndef HAVE_GETTIMEOFDAY
+#ifdef HAVE_TIMEVAL
+ 
+/* ARGSUSED */
+gettimeofday (tp, tzp)
+     struct timeval *tp;
+     struct timezone *tzp;
+{
+  extern long time ();
+
+  tp->tv_sec = time ((long *)0);    
+  tp->tv_usec = 0;
+  tzp->tz_minuteswest = -1;
+}
+ 
+#endif
+#endif
+#endif
+#endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
+  
+/*
+ *	This function will go away as soon as all the stubs fixed. (fnf)
+ */
+
+croak (badfunc)
+     char *badfunc;
+{
+  printf ("%s not yet implemented\r\n", badfunc);
+  reset_sys_modes ();
+  exit (1);
+}
+
+#endif /* USG */
+
+#ifdef DGUX
+
+char *sys_siglist[NSIG + 1] =
+{
+  "null signal",			 /*  0 SIGNULL   */
+  "hangup",				 /*  1 SIGHUP    */
+  "interrupt",		       		 /*  2 SIGINT    */
+  "quit",				 /*  3 SIGQUIT   */
+  "illegal instruction",		 /*  4 SIGILL    */
+  "trace trap",				 /*  5 SIGTRAP   */
+  "abort termination",			 /*  6 SIGABRT   */
+  "SIGEMT",				 /*  7 SIGEMT    */
+  "floating point exception",		 /*  8 SIGFPE    */
+  "kill",				 /*  9 SIGKILL   */
+  "bus error",				 /* 10 SIGBUS    */
+  "segmentation violation",		 /* 11 SIGSEGV   */
+  "bad argument to system call",	 /* 12 SIGSYS    */
+  "write on a pipe with no reader",	 /* 13 SIGPIPE   */
+  "alarm clock",			 /* 14 SIGALRM   */
+  "software termination signal",	 /* 15 SIGTERM   */
+  "user defined signal 1",		 /* 16 SIGUSR1   */
+  "user defined signal 2",		 /* 17 SIGUSR2   */
+  "child stopped or terminated",	 /* 18 SIGCLD    */
+  "power-fail restart",			 /* 19 SIGPWR    */
+  "window size changed",		 /* 20 SIGWINCH  */
+  "undefined",				 /* 21           */
+  "pollable event occured",		 /* 22 SIGPOLL   */
+  "sendable stop signal not from tty",	 /* 23 SIGSTOP   */
+  "stop signal from tty",		 /* 24 SIGSTP    */
+  "continue a stopped process",		 /* 25 SIGCONT   */
+  "attempted background tty read",	 /* 26 SIGTTIN   */
+  "attempted background tty write",	 /* 27 SIGTTOU   */
+  "undefined",				 /* 28           */
+  "undefined",				 /* 29           */
+  "undefined",				 /* 30           */
+  "undefined",				 /* 31           */
+  "undefined",				 /* 32           */
+  "socket (TCP/IP) urgent data arrival", /* 33 SIGURG    */
+  "I/O is possible",			 /* 34 SIGIO     */
+  "exceeded cpu time limit",		 /* 35 SIGXCPU   */
+  "exceeded file size limit",		 /* 36 SIGXFSZ   */
+  "virtual time alarm",			 /* 37 SIGVTALRM */
+  "profiling time alarm",		 /* 38 SIGPROF   */
+  "undefined",				 /* 39           */
+  "file record locks revoked",		 /* 40 SIGLOST   */
+  "undefined",				 /* 41           */
+  "undefined",				 /* 42           */
+  "undefined",				 /* 43           */
+  "undefined",				 /* 44           */
+  "undefined",				 /* 45           */
+  "undefined",				 /* 46           */
+  "undefined",				 /* 47           */
+  "undefined",				 /* 48           */
+  "undefined",				 /* 49           */
+  "undefined",				 /* 50           */
+  "undefined",				 /* 51           */
+  "undefined",				 /* 52           */
+  "undefined",				 /* 53           */
+  "undefined",				 /* 54           */
+  "undefined",				 /* 55           */
+  "undefined",				 /* 56           */
+  "undefined",				 /* 57           */
+  "undefined",				 /* 58           */
+  "undefined",				 /* 59           */
+  "undefined",				 /* 60           */
+  "undefined",				 /* 61           */
+  "undefined",				 /* 62           */
+  "undefined",				 /* 63           */
+  "notification message in mess. queue", /* 64 SIGDGNOTIFY */
+  0
+};
+
+#endif /* DGUX */
+
+/* Directory routines for systems that don't have them. */
+
+#ifdef SYSV_SYSTEM_DIR
+
+#include <dirent.h>
+
+#ifndef AIX
+int
+closedir (dirp)
+     register DIR *dirp;              /* stream from opendir */
+{
+  sys_close (dirp->dd_fd);
+  free ((char *) dirp->dd_buf);       /* directory block defined in <dirent.h> */
+  free ((char *) dirp);
+}
+#endif /* not AIX */
+#endif /* SYSV_SYSTEM_DIR */
+
+#ifdef NONSYSTEM_DIR_LIBRARY
+
+DIR *
+opendir (filename)
+     char *filename;	/* name of directory */
+{
+  register DIR *dirp;		/* -> malloc'ed storage */
+  register int fd;		/* file descriptor for read */
+  struct stat sbuf;		/* result of fstat */
+
+  fd = sys_open (filename, 0);
+  if (fd < 0)
+    return 0;
+
+  if (fstat (fd, &sbuf) < 0
+      || (sbuf.st_mode & S_IFMT) != S_IFDIR
+      || (dirp = (DIR *) malloc (sizeof (DIR))) == 0)
+    {
+      sys_close (fd);
+      return 0;		/* bad luck today */
+    }
+
+  dirp->dd_fd = fd;
+  dirp->dd_loc = dirp->dd_size = 0;	/* refill needed */
+
+  return dirp;
+}
+
+void
+closedir (dirp)
+     register DIR *dirp;		/* stream from opendir */
+{
+  sys_close (dirp->dd_fd);
+  free ((char *) dirp);
+}
+
+
+#ifndef VMS
+#define DIRSIZ	14
+struct olddir
+  {
+    ino_t od_ino; 		/* inode */
+    char od_name[DIRSIZ];	/* filename */
+  };
+#endif /* not VMS */
+
+struct direct dir_static;	/* simulated directory contents */
+
+/* ARGUSED */
+struct direct *
+readdir (dirp)
+     register DIR *dirp;	/* stream from opendir */
+{
+#ifndef VMS
+  register struct olddir *dp;	/* -> directory data */
+#else /* VMS */
+  register struct dir$_name *dp; /* -> directory data */
+  register struct dir$_version *dv; /* -> version data */
+#endif /* VMS */
+
+  for (; ;)
+    {
+      if (dirp->dd_loc >= dirp->dd_size)
+	dirp->dd_loc = dirp->dd_size = 0;
+
+      if (dirp->dd_size == 0 	/* refill buffer */
+	  && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
+	return 0;
+
+#ifndef VMS
+      dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc];
+      dirp->dd_loc += sizeof (struct olddir);
+
+      if (dp->od_ino != 0)	/* not deleted entry */
+	{
+	  dir_static.d_ino = dp->od_ino;
+	  strncpy (dir_static.d_name, dp->od_name, DIRSIZ);
+	  dir_static.d_name[DIRSIZ] = '\0';
+	  dir_static.d_namlen = strlen (dir_static.d_name);
+	  dir_static.d_reclen = sizeof (struct direct)
+	    - MAXNAMLEN + 3
+	      + dir_static.d_namlen - dir_static.d_namlen % 4;
+	  return &dir_static;	/* -> simulated structure */
+	}
+#else /* VMS */
+      dp = (struct dir$_name *) dirp->dd_buf;
+      if (dirp->dd_loc == 0)
+	dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1
+	  : dp->dir$b_namecount;
+      dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc];
+      dir_static.d_ino = dv->dir$w_fid_num;
+      dir_static.d_namlen = dp->dir$b_namecount;
+      dir_static.d_reclen = sizeof (struct direct)
+	- MAXNAMLEN + 3
+	  + dir_static.d_namlen - dir_static.d_namlen % 4;
+      strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
+      dir_static.d_name[dir_static.d_namlen] = '\0';
+      dirp->dd_loc = dirp->dd_size; /* only one record at a time */
+      return &dir_static;
+#endif /* VMS */
+    }
+}
+
+#ifdef VMS
+/* readdirver is just like readdir except it returns all versions of a file
+   as separate entries.  */
+
+/* ARGUSED */
+struct direct *
+readdirver (dirp)
+     register DIR *dirp;	/* stream from opendir */
+{
+  register struct dir$_name *dp; /* -> directory data */
+  register struct dir$_version *dv; /* -> version data */
+
+  if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name))
+    dirp->dd_loc = dirp->dd_size = 0;
+
+  if (dirp->dd_size == 0 	/* refill buffer */
+      && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
+    return 0;
+
+  dp = (struct dir$_name *) dirp->dd_buf;
+  if (dirp->dd_loc == 0)
+    dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1
+		   : dp->dir$b_namecount;
+  dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc];
+  strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
+  sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version);
+  dir_static.d_namlen = strlen (dir_static.d_name);
+  dir_static.d_ino = dv->dir$w_fid_num;
+  dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3
+			+ dir_static.d_namlen - dir_static.d_namlen % 4;
+  dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name);
+  return &dir_static;
+}
+
+#endif /* VMS */
+
+#endif /* NONSYSTEM_DIR_LIBRARY */
+
+/* Functions for VMS */
+#ifdef VMS
+#include "pwd.h"
+#include <acldef.h>
+#include <chpdef.h>
+#include <jpidef.h>
+
+/* Return as a string the VMS error string pertaining to STATUS.
+   Reuses the same static buffer each time it is called.  */
+
+char *
+vmserrstr (status)
+     int status;		/* VMS status code */
+{
+  int bufadr[2];
+  short len;
+  static char buf[257];
+
+  bufadr[0] = sizeof buf - 1;
+  bufadr[1] = (int) buf;
+  if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1))
+    return "untranslatable VMS error status";
+  buf[len] = '\0';
+  return buf;
+}
+
+#ifdef access
+#undef access
+  
+/* The following is necessary because 'access' emulation by VMS C (2.0) does
+ * not work correctly.  (It also doesn't work well in version 2.3.)
+ */
+
+#ifdef VMS4_4
+
+#define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
+	{ strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
+
+typedef union {
+    struct {
+	unsigned short s_buflen;
+	unsigned short s_code;
+	char *s_bufadr;
+	unsigned short *s_retlenadr;
+    } s;
+    int end;
+} item;
+#define buflen s.s_buflen
+#define code s.s_code
+#define bufadr s.s_bufadr
+#define retlenadr s.s_retlenadr
+
+#define R_OK 4	/* test for read permission */
+#define W_OK 2	/* test for write permission */
+#define X_OK 1	/* test for execute (search) permission */
+#define F_OK 0	/* test for presence of file */
+
+int
+sys_access (path, mode)
+     char *path;
+     int mode;
+{
+  static char *user = NULL;
+  char dir_fn[512];
+
+  /* translate possible directory spec into .DIR file name, so brain-dead
+   * access can treat the directory like a file.  */
+  if (directory_file_name (path, dir_fn))
+    path = dir_fn;
+  
+  if (mode == F_OK)
+    return access (path, mode);
+  if (user == NULL && (user = (char *) getenv ("USER")) == NULL)
+    return -1;
+  {
+    int stat;
+    int flags;
+    int acces;
+    unsigned short int dummy;
+    item itemlst[3];
+    static int constant = ACL$C_FILE;
+    DESCRIPTOR (path_desc, path);
+    DESCRIPTOR (user_desc, user);
+ 
+    flags = 0;
+    acces = 0;
+    if ((mode & X_OK) && ((stat = access (path, mode)) < 0 || mode == X_OK))
+      return stat;
+    if (mode & R_OK)
+      acces |= CHP$M_READ;
+    if (mode & W_OK)
+      acces |= CHP$M_WRITE;
+    itemlst[0].buflen = sizeof (int);
+    itemlst[0].code = CHP$_FLAGS;
+    itemlst[0].bufadr = (char *) &flags;
+    itemlst[0].retlenadr = &dummy;
+    itemlst[1].buflen = sizeof (int);
+    itemlst[1].code = CHP$_ACCESS;
+    itemlst[1].bufadr = (char *) &acces;
+    itemlst[1].retlenadr = &dummy;
+    itemlst[2].end = CHP$_END;
+    stat = SYS$CHECK_ACCESS (&constant, &path_desc, &user_desc, itemlst);
+    return stat == SS$_NORMAL ? 0 : -1;
+  }
+}
+
+#else /* not VMS4_4 */
+
+#include <prvdef.h>
+#define	ACE$M_WRITE	2
+#define	ACE$C_KEYID	1
+
+static unsigned short memid, grpid;
+static unsigned int uic;
+
+/* Called from init_sys_modes, so it happens not very often
+   but at least each time Emacs is loaded.  */
+sys_access_reinit ()
+{
+  uic = 0;
+}
+
+int
+sys_access (filename, type)
+     char * filename;
+     int type;
+{
+  struct FAB fab;
+  struct XABPRO xab;
+  int status, size, i, typecode, acl_controlled;
+  unsigned int *aclptr, *aclend, aclbuf[60];
+  union prvdef prvmask;
+
+  /* Get UIC and GRP values for protection checking.  */
+  if (uic == 0)
+    {
+      status = LIB$GETJPI (&JPI$_UIC, 0, 0, &uic, 0, 0);
+      if (! (status & 1))
+	return -1;
+      memid = uic & 0xFFFF;
+      grpid = uic >> 16;
+    }
+
+  if (type != 2)		/* not checking write access */
+    return access (filename, type);
+
+  /* Check write protection. */
+    
+#define	CHECKPRIV(bit)    (prvmask.bit)
+#define	WRITEABLE(field)  (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
+
+  /* Find privilege bits */
+  status = sys$setprv (0, 0, 0, prvmask);
+  if (! (status & 1))
+    error ("Unable to find privileges: %s", vmserrstr (status));
+  if (CHECKPRIV (PRV$V_BYPASS))
+    return 0;			/* BYPASS enabled */
+  fab = cc$rms_fab;
+  fab.fab$b_fac = FAB$M_GET;
+  fab.fab$l_fna = filename;
+  fab.fab$b_fns = strlen (filename);
+  fab.fab$l_xab = &xab;
+  xab = cc$rms_xabpro;
+  xab.xab$l_aclbuf = aclbuf;
+  xab.xab$w_aclsiz = sizeof (aclbuf);
+  status = sys$open (&fab, 0, 0);
+  if (! (status & 1))
+    return -1;
+  sys$close (&fab, 0, 0);
+  /* Check system access */
+  if (CHECKPRIV (PRV$V_SYSPRV) && WRITEABLE (XAB$V_SYS))
+    return 0;
+  /* Check ACL entries, if any */
+  acl_controlled = 0;
+  if (xab.xab$w_acllen > 0)
+    {
+      aclptr = aclbuf;
+      aclend = &aclbuf[xab.xab$w_acllen / 4];
+      while (*aclptr && aclptr < aclend)
+	{
+	  size = (*aclptr & 0xff) / 4;
+	  typecode = (*aclptr >> 8) & 0xff;
+	  if (typecode == ACE$C_KEYID)
+	    for (i = size - 1; i > 1; i--)
+	      if (aclptr[i] == uic)
+		{
+		  acl_controlled = 1;
+		  if (aclptr[1] & ACE$M_WRITE)
+		    return 0;	/* Write access through ACL */
+		}
+	  aclptr = &aclptr[size];
+	}
+      if (acl_controlled)	/* ACL specified, prohibits write access */
+	return -1;
+    }
+  /* No ACL entries specified, check normal protection */
+  if (WRITEABLE (XAB$V_WLD))	/* World writeable */
+    return 0;
+  if (WRITEABLE (XAB$V_GRP) &&
+      (unsigned short) (xab.xab$l_uic >> 16) == grpid)
+    return 0;			/* Group writeable */
+  if (WRITEABLE (XAB$V_OWN) &&
+      (xab.xab$l_uic & 0xFFFF) == memid)
+    return 0;			/* Owner writeable */
+
+  return -1;	/* Not writeable */
+}
+#endif /* not VMS4_4 */
+#endif /* access */
+  
+static char vtbuf[NAM$C_MAXRSS+1];
+
+/* translate a vms file spec to a unix path */
+char *
+sys_translate_vms (vfile)
+     char * vfile;
+{
+  char * p;
+  char * targ;
+
+  if (!vfile)
+    return 0;
+
+  targ = vtbuf;
+
+  /* leading device or logical name is a root directory */
+  if (p = strchr (vfile, ':'))
+    {
+      *targ++ = '/';
+      while (vfile < p)
+	*targ++ = *vfile++;
+      vfile++;
+      *targ++ = '/';
+    }
+  p = vfile;
+  if (*p == '[' || *p == '<')
+    {
+      while (*++vfile != *p + 2)
+	switch (*vfile)
+	  {
+	  case '.':
+	    if (vfile[-1] == *p)
+	      *targ++ = '.';
+	    *targ++ = '/';
+	    break;
+
+	  case '-':
+	    *targ++ = '.';
+	    *targ++ = '.';
+	    break;
+	    
+	  default:
+	    *targ++ = *vfile;
+	    break;
+	  }
+      vfile++;
+      *targ++ = '/';
+    }
+  while (*vfile)
+    *targ++ = *vfile++;
+
+  return vtbuf;
+}
+
+static char utbuf[NAM$C_MAXRSS+1];
+
+/* translate a unix path to a VMS file spec */
+char *
+sys_translate_unix (ufile)
+     char * ufile;
+{
+  int slash_seen = 0;
+  char *p;
+  char * targ;
+
+  if (!ufile)
+    return 0;
+
+  targ = utbuf;
+
+  if (*ufile == '/')
+    {
+      ufile++;
+    }
+
+  while (*ufile)
+    {
+      switch (*ufile)
+	{
+	case '/':
+	  if (slash_seen)
+	    if (index (&ufile[1], '/'))
+	      *targ++ = '.';
+	    else
+	      *targ++ = ']';
+	  else
+	    {
+	      *targ++ = ':';
+	      if (index (&ufile[1], '/'))
+		*targ++ = '[';
+	      slash_seen = 1;
+	    }
+	  break;
+
+	case '.':
+	  if (strncmp (ufile, "./", 2) == 0)
+	    {
+	      if (!slash_seen)
+		{
+		  *targ++ = '[';
+		  slash_seen = 1;
+		}
+	      ufile++;		/* skip the dot */
+	      if (index (&ufile[1], '/'))
+		*targ++ = '.';
+	      else
+		*targ++ = ']';
+	    }
+	  else if (strncmp (ufile, "../", 3) == 0)
+	    {
+	      if (!slash_seen)
+		{
+		  *targ++ = '[';
+		  slash_seen = 1;
+		}
+	      *targ++ = '-';
+	      ufile += 2;	/* skip the dots */
+	      if (index (&ufile[1], '/'))
+		*targ++ = '.';
+	      else
+		*targ++ = ']';
+	    }
+	  else
+	    *targ++ = *ufile;
+	  break;
+
+	default:
+	  *targ++ = *ufile;
+	  break;
+	}
+      ufile++;
+    }
+  *targ = '\0';
+  
+  return utbuf;
+}
+
+char *
+getwd (pathname)
+     char *pathname;
+{
+  char *ptr;
+  strcpy (pathname, egetenv ("PATH"));
+
+  ptr = pathname;
+  while (*ptr)
+    {
+      if ('a' <= *ptr && *ptr <= 'z')
+	*ptr -= 040;
+      ptr++;
+    }
+  return pathname;
+}
+
+getppid ()
+{
+  long item_code = JPI$_OWNER;
+  unsigned long parent_id;
+  int status;
+
+  if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0)
+    {
+      errno = EVMSERR;
+      vaxc$errno = status;
+      return -1;
+    }
+  return parent_id;
+}
+
+#undef getuid
+unsigned
+sys_getuid ()
+{
+  return (getgid () << 16) | getuid ();
+}
+
+int
+sys_read (fildes, buf, nbyte)
+     int fildes;
+     char *buf;
+     unsigned int nbyte;
+{
+  return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE));
+}
+
+#if 0
+int
+sys_write (fildes, buf, nbyte)
+     int fildes;
+     char *buf;
+     unsigned int nbyte;
+{
+  register int nwrote, rtnval = 0;
+
+  while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0) {
+    nbyte -= nwrote;
+    buf += nwrote;
+    rtnval += nwrote;
+  }
+  if (nwrote < 0)
+    return rtnval ? rtnval : -1;
+  if ((nwrote = write (fildes, buf, nbyte)) < 0)
+    return rtnval ? rtnval : -1;
+  return (rtnval + nwrote);
+}
+#endif /* 0 */
+
+/*
+ *	VAX/VMS VAX C RTL really loses. It insists that records
+ *      end with a newline (carriage return) character, and if they
+ *	don't it adds one (nice of it isn't it!)
+ *
+ *	Thus we do this stupidity below.
+ */
+
+int
+sys_write (fildes, buf, nbytes)
+     int fildes;
+     char *buf;
+     unsigned int nbytes;
+{
+  register char *p;
+  register char *e;
+  int retval, sum;
+  p = buf;
+  sum = 0;
+  while (nbytes > 0)
+    {
+      e =  p + min (MAXIOSIZE, nbytes) - 1;
+      while (*e != '\n' && e > p) e--;
+      if (p == e)		/* Ok.. so here we add a newline... sigh. */
+	e = p + min (MAXIOSIZE, nbytes) - 1;
+      retval = write (fildes, p, e - p + 1);
+      if (retval != e - p + 1) return -1;
+      p = e + 1;
+      sum = sum + retval;
+      nbytes -= retval;
+    }
+  return sum;
+}
+
+/* Create file NEW copying its attributes from file OLD.  If
+   OLD is 0 or does not exist, create based on the value of
+   vms_stmlf_recfm. */
+
+/* Protection value the file should ultimately have.
+   Set by create_copy_attrs, and use by rename_sansversions.  */
+static unsigned short int fab_final_pro;
+
+int
+creat_copy_attrs (old, new)
+     char *old, *new;
+{
+  struct FAB fab = cc$rms_fab;
+  struct XABPRO xabpro;
+  char aclbuf[256];	/* Choice of size is arbitrary.  See below. */
+  extern int vms_stmlf_recfm;
+
+  if (old)
+    {
+      fab.fab$b_fac = FAB$M_GET;
+      fab.fab$l_fna = old;
+      fab.fab$b_fns = strlen (old);
+      fab.fab$l_xab = (char *) &xabpro;
+      xabpro = cc$rms_xabpro;
+      xabpro.xab$l_aclbuf = aclbuf;
+      xabpro.xab$w_aclsiz = sizeof aclbuf;
+      /* Call $OPEN to fill in the fab & xabpro fields. */
+      if (sys$open (&fab, 0, 0) & 1)
+	{
+	  sys$close (&fab, 0, 0);
+	  fab.fab$l_alq = 0;	/* zero the allocation quantity */
+	  if (xabpro.xab$w_acllen > 0)
+	    {
+	      if (xabpro.xab$w_acllen > sizeof aclbuf)
+		/* If the acl buffer was too short, redo open with longer one.
+		   Wouldn't need to do this if there were some system imposed
+		   limit on the size of an ACL, but I can't find any such. */
+		{
+		  xabpro.xab$l_aclbuf = (char *) alloca (xabpro.xab$w_acllen);
+		  xabpro.xab$w_aclsiz = xabpro.xab$w_acllen;
+		  if (sys$open (&fab, 0, 0) & 1)
+		    sys$close (&fab, 0, 0);
+		  else
+		    old = 0;
+		}
+	    }
+	  else
+	    xabpro.xab$l_aclbuf = 0;
+	}
+      else
+	old = 0;
+    }
+  fab.fab$l_fna = new;
+  fab.fab$b_fns = strlen (new);
+  if (!old)
+    {
+      fab.fab$l_xab = 0;
+      fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR;
+      fab.fab$b_rat = FAB$M_CR;
+    }
+
+  /* Set the file protections such that we will be able to manipulate
+     this file.  Once we are done writing and renaming it, we will set
+     the protections back.  */
+  if (old)
+    fab_final_pro = xabpro.xab$w_pro;
+  else
+    sys$setdfprot (0, &fab_final_pro);
+  xabpro.xab$w_pro &= 0xff0f; /* set O:rewd for now. This is set back later. */
+
+  /* Create the new file with either default attrs or attrs copied
+     from old file. */
+  if (!(SYS$CREATE (&fab, 0, 0) & 1))
+    return -1;
+  sys$close (&fab, 0, 0);
+  /* As this is a "replacement" for creat, return a file descriptor
+     opened for writing. */
+  return open (new, O_WRONLY);
+}
+
+#ifdef creat
+#undef creat
+#include <varargs.h>
+#ifdef __GNUC__
+#ifndef va_count
+#define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
+#endif
+#endif
+
+sys_creat (va_alist)
+     va_dcl
+{
+  va_list list_incrementor;
+  char *name;
+  int mode;
+  int rfd;			/* related file descriptor */
+  int fd;			/* Our new file descriptor */
+  int count;
+  struct stat st_buf;
+  char rfm[12];
+  char rat[15];
+  char mrs[13];
+  char fsz[13];
+  extern int vms_stmlf_recfm;
+
+  va_count (count);
+  va_start (list_incrementor);
+  name = va_arg (list_incrementor, char *);
+  mode = va_arg (list_incrementor, int);
+  if (count > 2)
+    rfd = va_arg (list_incrementor, int);
+  va_end (list_incrementor);
+  if (count > 2)
+    {
+      /* Use information from the related file descriptor to set record
+	 format of the newly created file. */
+      fstat (rfd, &st_buf);
+      switch (st_buf.st_fab_rfm)
+	{
+	case FAB$C_FIX:
+	  strcpy (rfm, "rfm = fix");
+	  sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs);
+	  strcpy (rat, "rat = ");
+	  if (st_buf.st_fab_rat & FAB$M_CR)
+	    strcat (rat, "cr");
+	  else if (st_buf.st_fab_rat & FAB$M_FTN)
+	    strcat (rat, "ftn");
+	  else if (st_buf.st_fab_rat & FAB$M_PRN)
+	    strcat (rat, "prn");
+	  if (st_buf.st_fab_rat & FAB$M_BLK)
+	    if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
+	      strcat (rat, ", blk");
+	    else
+	      strcat (rat, "blk");
+	  return creat (name, 0, rfm, rat, mrs);
+
+	case FAB$C_VFC:
+	  strcpy (rfm, "rfm = vfc");
+	  sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz);
+	  strcpy (rat, "rat = ");
+	  if (st_buf.st_fab_rat & FAB$M_CR)
+	    strcat (rat, "cr");
+	  else if (st_buf.st_fab_rat & FAB$M_FTN)
+	    strcat (rat, "ftn");
+	  else if (st_buf.st_fab_rat & FAB$M_PRN)
+	    strcat (rat, "prn");
+	  if (st_buf.st_fab_rat & FAB$M_BLK)
+	    if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
+	      strcat (rat, ", blk");
+	    else
+	      strcat (rat, "blk");
+	  return creat (name, 0, rfm, rat, fsz);
+
+	case FAB$C_STM:
+	  strcpy (rfm, "rfm = stm");
+	  break;
+
+	case FAB$C_STMCR:
+	  strcpy (rfm, "rfm = stmcr");
+	  break;
+
+	case FAB$C_STMLF:
+	  strcpy (rfm, "rfm = stmlf");
+	  break;
+
+	case FAB$C_UDF:
+	  strcpy (rfm, "rfm = udf");
+	  break;
+
+	case FAB$C_VAR:
+	  strcpy (rfm, "rfm = var");
+	  break;
+	}
+      strcpy (rat, "rat = ");
+      if (st_buf.st_fab_rat & FAB$M_CR)
+	strcat (rat, "cr");
+      else if (st_buf.st_fab_rat & FAB$M_FTN)
+	strcat (rat, "ftn");
+      else if (st_buf.st_fab_rat & FAB$M_PRN)
+	strcat (rat, "prn");
+      if (st_buf.st_fab_rat & FAB$M_BLK)
+	if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
+	  strcat (rat, ", blk");
+	else
+	  strcat (rat, "blk");
+    }
+  else
+    {
+      strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var");
+      strcpy (rat, "rat=cr");
+    }
+  /* Until the VAX C RTL fixes the many bugs with modes, always use
+     mode 0 to get the user's default protection. */
+  fd = creat (name, 0, rfm, rat);
+  if (fd < 0 && errno == EEXIST)
+    {
+      if (unlink (name) < 0)
+	report_file_error ("delete", build_string (name));
+      fd = creat (name, 0, rfm, rat);
+    }
+  return fd;
+}
+#endif /* creat */
+
+/* fwrite to stdout is S L O W.  Speed it up by using fputc...*/
+sys_fwrite (ptr, size, num, fp)
+     register char * ptr;
+     FILE * fp;
+{
+  register int tot = num * size;
+
+  while (tot--)
+    fputc (*ptr++, fp);
+}
+
+/*
+ * The VMS C library routine creat actually creates a new version of an
+ * existing file rather than truncating the old version.  There are times
+ * when this is not the desired behavior, for instance, when writing an
+ * auto save file (you only want one version), or when you don't have
+ * write permission in the directory containing the file (but the file
+ * itself is writable).  Hence this routine, which is equivalent to 
+ * "close (creat (fn, 0));" on Unix if fn already exists.
+ */
+int
+vms_truncate (fn)
+     char *fn;
+{
+  struct FAB xfab = cc$rms_fab;
+  struct RAB xrab = cc$rms_rab;
+  int status;
+
+  xfab.fab$l_fop = FAB$M_TEF;	/* free allocated but unused blocks on close */
+  xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */
+  xfab.fab$b_shr = FAB$M_NIL;	/* allow no sharing - file must be locked */
+  xfab.fab$l_fna = fn;
+  xfab.fab$b_fns = strlen (fn);
+  xfab.fab$l_dna = ";0";	/* default to latest version of the file */
+  xfab.fab$b_dns = 2;
+  xrab.rab$l_fab = &xfab;
+
+  /* This gibberish opens the file, positions to the first record, and
+     deletes all records from there until the end of file. */
+  if ((sys$open (&xfab) & 01) == 01)
+    {
+      if ((sys$connect (&xrab) & 01) == 01 &&
+	  (sys$find (&xrab) & 01) == 01 &&
+	  (sys$truncate (&xrab) & 01) == 01)
+	status = 0;
+      else
+	status = -1;
+    }
+  else
+    status = -1;
+  sys$close (&xfab);
+  return status;
+}
+
+/* Define this symbol to actually read SYSUAF.DAT.  This requires either
+   SYSPRV or a readable SYSUAF.DAT. */
+
+#ifdef READ_SYSUAF
+/*
+ * getuaf.c
+ *
+ * Routine to read the VMS User Authorization File and return
+ * a specific user's record.
+ */
+
+static struct UAF retuaf;
+
+struct UAF *
+get_uaf_name (uname)
+     char * uname;
+{
+  register status;
+  struct FAB uaf_fab;
+  struct RAB uaf_rab;
+  
+  uaf_fab = cc$rms_fab;
+  uaf_rab = cc$rms_rab;
+  /* initialize fab fields */
+  uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
+  uaf_fab.fab$b_fns = 21;
+  uaf_fab.fab$b_fac = FAB$M_GET;
+  uaf_fab.fab$b_org = FAB$C_IDX;
+  uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
+  /* initialize rab fields */
+  uaf_rab.rab$l_fab = &uaf_fab;
+  /* open the User Authorization File */
+  status = sys$open (&uaf_fab);
+  if (!(status&1))
+    {
+      errno = EVMSERR;
+      vaxc$errno = status;
+      return 0;
+    }
+  status = sys$connect (&uaf_rab);
+  if (!(status&1))
+    {
+      errno = EVMSERR;
+      vaxc$errno = status;
+      return 0;
+    }
+  /* read the requested record - index is in uname */
+  uaf_rab.rab$l_kbf = uname;
+  uaf_rab.rab$b_ksz = strlen (uname);
+  uaf_rab.rab$b_rac = RAB$C_KEY;
+  uaf_rab.rab$l_ubf = (char *)&retuaf;
+  uaf_rab.rab$w_usz = sizeof retuaf;
+  status = sys$get (&uaf_rab);
+  if (!(status&1))
+    {
+      errno = EVMSERR;
+      vaxc$errno = status;
+      return 0;
+    }
+  /* close the User Authorization File */
+  status = sys$disconnect (&uaf_rab);
+  if (!(status&1))
+    {
+      errno = EVMSERR;
+      vaxc$errno = status;
+      return 0;
+    }
+  status = sys$close (&uaf_fab);
+  if (!(status&1))
+    {
+      errno = EVMSERR;
+      vaxc$errno = status;
+      return 0;
+    }
+  return &retuaf;
+}
+
+struct UAF *
+get_uaf_uic (uic)
+     unsigned long uic;
+{
+  register status;
+  struct FAB uaf_fab;
+  struct RAB uaf_rab;
+  
+  uaf_fab = cc$rms_fab;
+  uaf_rab = cc$rms_rab;
+  /* initialize fab fields */
+  uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
+  uaf_fab.fab$b_fns = 21;
+  uaf_fab.fab$b_fac = FAB$M_GET;
+  uaf_fab.fab$b_org = FAB$C_IDX;
+  uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
+  /* initialize rab fields */
+  uaf_rab.rab$l_fab = &uaf_fab;
+  /* open the User Authorization File */
+  status = sys$open (&uaf_fab);
+  if (!(status&1))
+    {
+      errno = EVMSERR;
+      vaxc$errno = status;
+      return 0;
+    }
+  status = sys$connect (&uaf_rab);
+  if (!(status&1))
+    {
+      errno = EVMSERR;
+      vaxc$errno = status;
+      return 0;
+    }
+  /* read the requested record - index is in uic */
+  uaf_rab.rab$b_krf = 1;	/* 1st alternate key */
+  uaf_rab.rab$l_kbf = (char *) &uic;
+  uaf_rab.rab$b_ksz = sizeof uic;
+  uaf_rab.rab$b_rac = RAB$C_KEY;
+  uaf_rab.rab$l_ubf = (char *)&retuaf;
+  uaf_rab.rab$w_usz = sizeof retuaf;
+  status = sys$get (&uaf_rab);
+  if (!(status&1))
+    {
+      errno = EVMSERR;
+      vaxc$errno = status;
+      return 0;
+    }
+  /* close the User Authorization File */
+  status = sys$disconnect (&uaf_rab);
+  if (!(status&1))
+    {
+      errno = EVMSERR;
+      vaxc$errno = status;
+      return 0;
+    }
+  status = sys$close (&uaf_fab);
+  if (!(status&1))
+    {
+      errno = EVMSERR;
+      vaxc$errno = status;
+      return 0;
+    }
+  return &retuaf;
+}
+
+static struct passwd retpw;
+
+struct passwd *
+cnv_uaf_pw (up)
+     struct UAF * up;
+{
+  char * ptr;
+
+  /* copy these out first because if the username is 32 chars, the next
+     section will overwrite the first byte of the UIC */
+  retpw.pw_uid = up->uaf$w_mem;
+  retpw.pw_gid = up->uaf$w_grp;
+
+  /* I suppose this is not the best sytle, to possibly overwrite one
+     byte beyond the end of the field, but what the heck... */
+  ptr = &up->uaf$t_username[UAF$S_USERNAME];
+  while (ptr[-1] == ' ')
+    ptr--;
+  *ptr = '\0';
+  strcpy (retpw.pw_name, up->uaf$t_username);
+
+  /* the rest of these are counted ascii strings */
+  strncpy (retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]);
+  retpw.pw_gecos[up->uaf$t_owner[0]] = '\0';
+  strncpy (retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]);
+  retpw.pw_dir[up->uaf$t_defdev[0]] = '\0';
+  strncat (retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]);
+  retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0';
+  strncpy (retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]);
+  retpw.pw_shell[up->uaf$t_defcli[0]] = '\0';
+
+  return &retpw;
+}
+#else /* not READ_SYSUAF */
+static struct passwd retpw;
+#endif /* not READ_SYSUAF */
+
+struct passwd *
+getpwnam (name)
+     char * name;
+{
+#ifdef READ_SYSUAF
+  struct UAF *up;
+#else
+  char * user;
+  char * dir;
+  unsigned char * full;
+#endif /* READ_SYSUAF */
+  char *ptr = name;
+
+  while (*ptr)
+    {
+      if ('a' <= *ptr && *ptr <= 'z')
+	*ptr -= 040;
+      ptr++;
+    }
+#ifdef READ_SYSUAF
+  if (!(up = get_uaf_name (name)))
+    return 0;
+  return cnv_uaf_pw (up);
+#else
+  if (strcmp (name, getenv ("USER")) == 0)
+    {
+      retpw.pw_uid = getuid ();
+      retpw.pw_gid = getgid ();
+      strcpy (retpw.pw_name, name);
+      if (full = egetenv ("FULLNAME"))
+	strcpy (retpw.pw_gecos, full);
+      else
+	*retpw.pw_gecos = '\0';
+      strcpy (retpw.pw_dir, egetenv ("HOME"));
+      *retpw.pw_shell = '\0';
+      return &retpw;
+    }
+  else
+    return 0;
+#endif /* not READ_SYSUAF */
+}
+
+struct passwd *
+getpwuid (uid)
+     unsigned long uid;
+{
+#ifdef READ_SYSUAF
+  struct UAF * up;
+
+  if (!(up = get_uaf_uic (uid)))
+    return 0;
+  return cnv_uaf_pw (up);
+#else
+  if (uid == sys_getuid ())
+    return getpwnam (egetenv ("USER"));
+  else
+    return 0;
+#endif /* not READ_SYSUAF */
+}
+
+/* return total address space available to the current process.  This is
+   the sum of the current p0 size, p1 size and free page table entries
+   available. */
+vlimit ()
+{
+  int item_code;
+  unsigned long free_pages;
+  unsigned long frep0va;
+  unsigned long frep1va;
+  register status;
+
+  item_code = JPI$_FREPTECNT;
+  if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0)
+    {
+      errno = EVMSERR;
+      vaxc$errno = status;
+      return -1;
+    }
+  free_pages *= 512;
+
+  item_code = JPI$_FREP0VA;
+  if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0)
+    {
+      errno = EVMSERR;
+      vaxc$errno = status;
+      return -1;
+    }
+  item_code = JPI$_FREP1VA;
+  if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0)
+    {
+      errno = EVMSERR;
+      vaxc$errno = status;
+      return -1;
+    }
+
+  return free_pages + frep0va + (0x7fffffff - frep1va);
+}
+
+define_logical_name (varname, string)
+     char *varname;
+     char *string;
+{
+  struct dsc$descriptor_s strdsc =
+    {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string};
+  struct dsc$descriptor_s envdsc =
+    {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
+  struct dsc$descriptor_s lnmdsc =
+    {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
+
+  return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0);
+}
+
+delete_logical_name (varname)
+     char *varname;
+{
+  struct dsc$descriptor_s envdsc =
+    {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
+  struct dsc$descriptor_s lnmdsc =
+    {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
+
+  return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc);
+}
+
+ulimit ()
+{}
+
+setpriority ()
+{}
+
+setpgrp ()
+{}
+
+execvp ()
+{
+  error ("execvp system call not implemented");
+}
+
+int
+rename (from, to)
+     char *from, *to;
+{
+  int status;
+  struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab;
+  struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam;
+  char from_esn[NAM$C_MAXRSS];
+  char to_esn[NAM$C_MAXRSS];
+
+  from_fab.fab$l_fna = from;
+  from_fab.fab$b_fns = strlen (from);
+  from_fab.fab$l_nam = &from_nam;
+  from_fab.fab$l_fop = FAB$M_NAM;
+
+  from_nam.nam$l_esa = from_esn;
+  from_nam.nam$b_ess = sizeof from_esn;
+
+  to_fab.fab$l_fna = to;
+  to_fab.fab$b_fns = strlen (to);
+  to_fab.fab$l_nam = &to_nam;
+  to_fab.fab$l_fop = FAB$M_NAM;
+
+  to_nam.nam$l_esa = to_esn;
+  to_nam.nam$b_ess = sizeof to_esn;
+
+  status = SYS$RENAME (&from_fab, 0, 0, &to_fab);
+
+  if (status & 1)
+    return 0;
+  else
+    {
+      if (status == RMS$_DEV)
+	errno = EXDEV;
+      else
+	errno = EVMSERR;
+      vaxc$errno = status;
+      return -1;
+    }
+}
+
+/* This function renames a file like `rename', but it strips
+   the version number from the "to" filename, such that the "to" file is
+   will always be a new version.  It also sets the file protection once it is
+   finished.  The protection that we will use is stored in fab_final_pro,
+   and was set when we did a creat_copy_attrs to create the file that we
+   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
+   bits).  To maintain portability, the VMS implementation of `chmod' wires
+   the W and D bits together.  */
+
+ 
+static struct fibdef fib;	/* We need this initialized to zero */
+char vms_file_written[NAM$C_MAXRSS];
+
+int
+rename_sans_version (from,to)
+     char *from, *to;
+{
+  short int chan;
+  int stat;
+  short int iosb[4];
+  int status;
+  struct FAB to_fab = cc$rms_fab;
+  struct NAM to_nam = cc$rms_nam;
+  struct dsc$descriptor fib_d ={sizeof (fib),0,0,(char*) &fib};
+  struct dsc$descriptor fib_attr[2]
+    = {{sizeof (fab_final_pro),ATR$C_FPRO,0,(char*) &fab_final_pro},{0,0,0,0}};
+  char to_esn[NAM$C_MAXRSS];
+
+  $DESCRIPTOR (disk,to_esn);
+
+  to_fab.fab$l_fna = to;
+  to_fab.fab$b_fns = strlen (to);
+  to_fab.fab$l_nam = &to_nam;
+  to_fab.fab$l_fop = FAB$M_NAM;
+
+  to_nam.nam$l_esa = to_esn;
+  to_nam.nam$b_ess = sizeof to_esn;
+
+  status = SYS$PARSE (&to_fab, 0, 0); /* figure out the full file name */
+
+  if (to_nam.nam$l_fnb && NAM$M_EXP_VER)
+    *(to_nam.nam$l_ver) = '\0';
+
+  stat = rename (from, to_esn);
+  if (stat < 0)
+    return stat;
+
+  strcpy (vms_file_written, to_esn);
+
+  to_fab.fab$l_fna = vms_file_written; /* this points to the versionless name */
+  to_fab.fab$b_fns = strlen (vms_file_written);
+
+  /* Now set the file protection to the correct value */
+  sys$open (&to_fab, 0, 0);	/* This fills in the nam$w_fid fields */
+
+  /* Copy these fields into the fib */
+  fib.fib$r_fid_overlay.fib$w_fid[0] = to_nam.nam$w_fid[0];
+  fib.fib$r_fid_overlay.fib$w_fid[1] = to_nam.nam$w_fid[1];
+  fib.fib$r_fid_overlay.fib$w_fid[2] = to_nam.nam$w_fid[2];
+
+  sys$close (&to_fab, 0, 0);
+
+  stat = sys$assign (&disk, &chan, 0, 0); /* open a channel to the disk */
+  if (!stat)
+    lib$signal (stat);
+  stat = sys$qiow (0, chan, IO$_MODIFY, iosb, 0, 0, &fib_d,
+		   0, 0, 0, &fib_attr, 0);
+  if (!stat)
+    lib$signal (stat);
+  stat = sys$dassgn (chan);
+  if (!stat)
+    lib$signal (stat);
+  strcpy (vms_file_written, to_esn); /* We will write this to the screen*/
+  return 0;
+}
+
+link (file, new)
+     char * file, * new;
+{
+  register status;
+  struct FAB fab;
+  struct NAM nam;
+  unsigned short fid[3];
+  char esa[NAM$C_MAXRSS];
+
+  fab = cc$rms_fab;
+  fab.fab$l_fop = FAB$M_OFP;
+  fab.fab$l_fna = file;
+  fab.fab$b_fns = strlen (file);
+  fab.fab$l_nam = &nam;
+
+  nam = cc$rms_nam;
+  nam.nam$l_esa = esa;
+  nam.nam$b_ess = NAM$C_MAXRSS;
+
+  status = SYS$PARSE (&fab);
+  if ((status & 1) == 0)
+    {
+      errno = EVMSERR;
+      vaxc$errno = status;
+      return -1;
+    }
+  status = SYS$SEARCH (&fab);
+  if ((status & 1) == 0)
+    {
+      errno = EVMSERR;
+      vaxc$errno = status;
+      return -1;
+    }
+
+  fid[0] = nam.nam$w_fid[0];
+  fid[1] = nam.nam$w_fid[1];
+  fid[2] = nam.nam$w_fid[2];
+
+  fab.fab$l_fna = new;
+  fab.fab$b_fns = strlen (new);
+
+  status = SYS$PARSE (&fab);
+  if ((status & 1) == 0)
+    {
+      errno = EVMSERR;
+      vaxc$errno = status;
+      return -1;
+    }
+
+  nam.nam$w_fid[0] = fid[0];
+  nam.nam$w_fid[1] = fid[1];
+  nam.nam$w_fid[2] = fid[2];
+
+  nam.nam$l_esa = nam.nam$l_name;
+  nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
+
+  status = SYS$ENTER (&fab);
+  if ((status & 1) == 0)
+    {
+      errno = EVMSERR;
+      vaxc$errno = status;
+      return -1;
+    }
+
+  return 0;
+}
+
+croak (badfunc)
+     char *badfunc;
+{
+  printf ("%s not yet implemented\r\n", badfunc);
+  reset_sys_modes ();
+  exit (1);
+}
+
+long
+random ()
+{
+  /* Arrange to return a range centered on zero.  */
+  return rand () - (1 << 30);
+}
+
+srandom (seed)
+{
+  srand (seed);
+}
+#endif /* VMS */
+
+#ifdef AIX
+
+/* Called from init_sys_modes.  */
+hft_init ()
+{
+  int junk;
+
+  /* If we're not on an HFT we shouldn't do any of this.  We determine
+     if we are on an HFT by trying to get an HFT error code.  If this
+     call fails, we're not on an HFT. */ 
+#ifdef IBMR2AIX
+  if (ioctl (0, HFQERROR, &junk) < 0)
+    return;
+#else /* not IBMR2AIX */
+  if (ioctl (0, HFQEIO, 0) < 0)
+    return;
+#endif /* not IBMR2AIX */
+
+  /* On AIX the default hft keyboard mapping uses backspace rather than delete
+     as the rubout key's ASCII code.  Here this is changed.  The bug is that
+     there's no way to determine the old mapping, so in reset_sys_modes
+     we need to assume that the normal map had been present.  Of course, this
+     code also doesn't help if on a terminal emulator which doesn't understand
+     HFT VTD's. */
+  {
+    struct hfbuf buf;
+    struct hfkeymap keymap;
+
+    buf.hf_bufp = (char *)&keymap;
+    buf.hf_buflen = sizeof (keymap);
+    keymap.hf_nkeys = 2;
+    keymap.hfkey[0].hf_kpos = 15;
+    keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
+#ifdef IBMR2AIX
+    keymap.hfkey[0].hf_keyidh = '<';
+#else /* not IBMR2AIX */
+    keymap.hfkey[0].hf_page = '<';
+#endif /* not IBMR2AIX */
+    keymap.hfkey[0].hf_char = 127;
+    keymap.hfkey[1].hf_kpos = 15;
+    keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
+#ifdef IBMR2AIX
+    keymap.hfkey[1].hf_keyidh = '<';
+#else /* not IBMR2AIX */
+    keymap.hfkey[1].hf_page = '<';
+#endif /* not IBMR2AIX */
+    keymap.hfkey[1].hf_char = 127;
+    hftctl (0, HFSKBD, &buf);
+  }
+  /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
+     at times.  */
+  line_ins_del_ok = char_ins_del_ok = 0;
+}
+
+/* Reset the rubout key to backspace. */
+
+hft_reset ()
+{
+  struct hfbuf buf;
+  struct hfkeymap keymap;
+  int junk;
+
+#ifdef IBMR2AIX
+  if (ioctl (0, HFQERROR, &junk) < 0)
+    return;
+#else /* not IBMR2AIX */
+  if (ioctl (0, HFQEIO, 0) < 0)
+    return;
+#endif /* not IBMR2AIX */
+
+  buf.hf_bufp = (char *)&keymap;
+  buf.hf_buflen = sizeof (keymap);
+  keymap.hf_nkeys = 2;
+  keymap.hfkey[0].hf_kpos = 15;
+  keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
+#ifdef IBMR2AIX
+  keymap.hfkey[0].hf_keyidh = '<';
+#else /* not IBMR2AIX */
+  keymap.hfkey[0].hf_page = '<';
+#endif /* not IBMR2AIX */
+  keymap.hfkey[0].hf_char = 8;
+  keymap.hfkey[1].hf_kpos = 15;
+  keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
+#ifdef IBMR2AIX
+  keymap.hfkey[1].hf_keyidh = '<';
+#else /* not IBMR2AIX */
+  keymap.hfkey[1].hf_page = '<';
+#endif /* not IBMR2AIX */
+  keymap.hfkey[1].hf_char = 8;
+  hftctl (0, HFSKBD, &buf);
+}
+
+#endif /* AIX */