#include <signal.h>
#include <setjmp.h>
-#include "config.h"
+#include <config.h>
#include "lisp.h"
#include "blockinput.h"
#undef NULL
#endif
#endif /* not 4.1 bsd */
-/* Get DGUX definition for FASYNC - DJB */
-#ifdef DGUX
-#include <sys/file.h>
-#endif /* DGUX */
+#ifdef BROKEN_FASYNC
+/* On some systems (DGUX comes to mind real fast) FASYNC causes
+ background writes to the terminal to stop all processes in the
+ process group when invoked under the csh (and probably any shell
+ with job control). This stops Emacs dead in its tracks when coming
+ up under X11. */
+#undef FASYNC
+#endif
#include <sys/ioctl.h>
#include "systty.h"
-
-#ifdef BSD
-#ifdef BSD4_1
-#include <wait.h>
-#else /* not 4.1 */
-#include <sys/wait.h>
-#endif /* not 4.1 */
-#endif /* BSD */
+#include "syswait.h"
#ifdef BROKEN_TIOCGWINSZ
#undef TIOCGWINSZ
#include "syssignal.h"
#include "systime.h"
+/* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */
+#ifndef LPASS8
+#define LPASS8 0
+#endif
+
+#ifdef BSD4_1
+#define LNOFLSH 0100000
+#endif
+
static int baud_convert[] =
#ifdef BAUD_CONVERT
BAUD_CONVERT;
extern short ospeed;
/* The file descriptor for Emacs's input terminal.
- Under Unix, this is always left zero;
+ Under Unix, this is normaly zero except when using X;
under VMS, we place the input channel number here.
This allows us to write more code that works for both VMS and Unix. */
static int input_fd;
+\f
+/* Specify a different file descriptor for further input operations. */
+
+void
+change_input_fd (fd)
+ int fd;
+{
+ input_fd = fd;
+}
+
+/* Discard pending input on descriptor input_fd. */
discard_tty_input ()
{
#ifdef APOLLO
{
int zero = 0;
- ioctl (0, TIOCFLUSH, &zero);
+ ioctl (input_fd, TIOCFLUSH, &zero);
}
#else /* not Apollo */
EMACS_GET_TTY (input_fd, &buf);
#ifdef SIGTSTP
+/* Arrange for character C to be read as the next input from
+ the terminal. */
+
stuff_char (c)
char c;
{
/* Should perhaps error if in batch mode */
#ifdef TIOCSTI
- ioctl (0, TIOCSTI, &c);
+ ioctl (input_fd, TIOCSTI, &c);
#else /* no TIOCSTI */
- error ("Cannot stuff terminal input characters in this version of Unix.");
+ error ("Cannot stuff terminal input characters in this version of Unix");
#endif /* no TIOCSTI */
}
#endif /* SIGTSTP */
-
+\f
init_baud_rate ()
{
if (noninteractive)
#ifdef HAVE_TERMIOS
struct termios sg;
- sg.c_cflag = (sg.c_cflag & ~CBAUD) | B9600;
- tcgetattr (0, &sg);
+ sg.c_cflag = B9600;
+ tcgetattr (input_fd, &sg);
ospeed = cfgetospeed (&sg);
#else /* neither VMS nor TERMIOS */
#ifdef HAVE_TERMIO
struct termio sg;
- sg.c_cflag = (sg.c_cflag & ~CBAUD) | B9600;
+ sg.c_cflag = B9600;
#ifdef HAVE_TCATTR
- tcgetattr (0, &sg);
+ tcgetattr (input_fd, &sg);
#else
ioctl (input_fd, TCGETA, &sg);
#endif
struct sgttyb sg;
sg.sg_ospeed = B9600;
- if (ioctl (0, TIOCGETP, &sg) < 0)
+ if (ioctl (input_fd, TIOCGETP, &sg) < 0)
abort ();
ospeed = sg.sg_ospeed;
#endif /* not HAVE_TERMIO */
#endif
/* Ok to do nothing if this feature does not exist */
}
-
+\f
#ifndef subprocesses
wait_without_blocking ()
#endif
#endif
}
-
+\f
#ifndef VMS
/* Set up the terminal at the other end of a pseudo-terminal that
we will be controlling an inferior through.
input */
s.main.c_oflag &= ~OLCUC; /* Disable map of lower case to upper on
output */
+ s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
#if 0
/* Said to be unnecessary: */
s.main.c_cc[VMIN] = 1; /* minimum number of characters to accept */
s.main.c_iflag &= ~IGNBRK;
s.main.c_iflag &= ~BRKINT;
/* QUIT and INTR work better as signals, so disable character forms */
- s.main.c_cc[VQUIT] = 0377;
s.main.c_cc[VINTR] = 0377;
#ifdef SIGNALS_VIA_CHARACTERS
/* the QUIT and INTR character are used in process_send_signal
s.main.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE
| CBREAK | TANDEM);
+ s.main.sg_flags |= LPASS8;
s.main.sg_erase = 0377;
s.main.sg_kill = 0377;
+ s.lmode = LLITOUT | s.lmode; /* Don't strip 8th bit */
#endif /* not HAVE_TERMIO */
{
EMACS_SET_TTY_PGRP (input_fd, &pid);
}
-
+\f
/* Record a signal code and the handler for it. */
struct save_signal
{
#else
#ifdef SIGTSTP
-#ifdef GETPGRP_NO_ARG
- EMACS_KILLPG (getpgrp (), SIGTSTP);
-#else
- EMACS_KILLPG (getpgrp (0), SIGTSTP);
-#endif
+ {
+ int pgrp = EMACS_GETPGRP (0);
+ EMACS_KILLPG (pgrp, SIGTSTP);
+ }
#else /* No SIGTSTP */
#ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
init_sigio ()
{
#ifdef FASYNC
- old_fcntl_flags = fcntl (0, F_GETFL, 0) & ~FASYNC;
+ old_fcntl_flags = fcntl (input_fd, F_GETFL, 0) & ~FASYNC;
#endif
request_sigio ();
}
#ifdef SIGWINCH
sigunblock (sigmask (SIGWINCH));
#endif
- fcntl (0, F_SETFL, old_fcntl_flags | FASYNC);
+ fcntl (input_fd, F_SETFL, old_fcntl_flags | FASYNC);
interrupts_deferred = 0;
}
#ifdef SIGWINCH
sigblock (sigmask (SIGWINCH));
#endif
- fcntl (0, F_SETFL, old_fcntl_flags);
+ fcntl (input_fd, F_SETFL, old_fcntl_flags);
interrupts_deferred = 1;
}
request_sigio ()
{
int on = 1;
- ioctl (0, FIOASYNC, &on);
+ ioctl (input_fd, FIOASYNC, &on);
interrupts_deferred = 0;
}
{
int off = 0;
- ioctl (0, FIOASYNC, &off);
+ ioctl (input_fd, FIOASYNC, &off);
interrupts_deferred = 1;
}
#endif /* FASYNC */
#endif /* F_SETFL */
\f
+/* Saving and restoring the process group of Emacs's terminal. */
+
+#ifdef BSD
+
+/* The process group of which Emacs was a member when it initially
+ started.
+
+ If Emacs was in its own process group (i.e. inherited_pgroup ==
+ getpid ()), then we know we're running under a shell with job
+ control (Emacs would never be run as part of a pipeline).
+ Everything is fine.
+
+ If Emacs was not in its own process group, then we know we're
+ running under a shell (or a caller) that doesn't know how to
+ separate itself from Emacs (like sh). Emacs must be in its own
+ process group in order to receive SIGIO correctly. In this
+ situation, we put ourselves in our own pgroup, forcibly set the
+ tty's pgroup to our pgroup, and make sure to restore and reinstate
+ the tty's pgroup just like any other terminal setting. If
+ inherited_group was not the tty's pgroup, then we'll get a
+ SIGTTmumble when we try to change the tty's pgroup, and a CONT if
+ it goes foreground in the future, which is what should happen. */
+int inherited_pgroup;
+
+/* Split off the foreground process group to Emacs alone.
+ When we are in the foreground, but not started in our own process
+ group, redirect the TTY to point to our own process group. We need
+ to be in our own process group to receive SIGIO properly. */
+narrow_foreground_group ()
+{
+ int me = getpid ();
+
+ setpgrp (0, inherited_pgroup);
+ if (inherited_pgroup != me)
+ EMACS_SET_TTY_PGRP (input_fd, &me);
+ setpgrp (0, me);
+}
+
+/* Set the tty to our original foreground group. */
+widen_foreground_group ()
+{
+ if (inherited_pgroup != getpid ())
+ EMACS_SET_TTY_PGRP (input_fd, &inherited_pgroup);
+ setpgrp (0, inherited_pgroup);
+}
+
+#endif
+\f
/* Getting and setting emacs_tty structures. */
/* Set *TC to the parameters associated with the terminal FD.
int lmode;
#endif
+#ifndef F_SETOWN_BUG
#ifdef F_SETOWN
int old_fcntl_owner;
#endif /* F_SETOWN */
+#endif /* F_SETOWN_BUG */
/* This may also be defined in stdio,
but if so, this does no harm,
#endif
#endif /* not VMS */
+#ifdef BSD
+ if (! read_socket_hook && EQ (Vwindow_system, Qnil))
+ narrow_foreground_group ();
+#endif
+
EMACS_GET_TTY (input_fd, &old_tty);
if (!read_socket_hook && EQ (Vwindow_system, Qnil))
tty.tchars.t_stopc = '\023';
}
-/* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */
-#ifndef LPASS8
-#define LPASS8 0
-#endif
-
-#ifdef BSD4_1
-#define LNOFLSH 0100000
-#endif
-
tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_tty.lmode;
+#ifdef ultrix
+ /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt
+ anything, and leaving it in breaks the meta key. Go figure. */
+ tty.lmode &= ~LLITOUT;
+#endif
#ifdef BSD4_1
lmode = tty.lmode;
we have an unlocked terminal at the start. */
#ifdef TCXONC
- if (!flow_control) ioctl (0, TCXONC, 1);
+ if (!flow_control) ioctl (input_fd, TCXONC, 1);
#endif
#ifndef APOLLO
#ifdef TIOCSTART
- if (!flow_control) ioctl (0, TIOCSTART, 0);
+ if (!flow_control) ioctl (input_fd, TIOCSTART, 0);
#endif
#endif
}
#ifdef F_SETFL
+#ifndef F_SETOWN_BUG
#ifdef F_GETOWN /* F_SETFL does not imply existence of F_GETOWN */
if (interrupt_input)
{
- old_fcntl_owner = fcntl (0, F_GETOWN, 0);
- fcntl (0, F_SETOWN, getpid ());
+ old_fcntl_owner = fcntl (input_fd, F_GETOWN, 0);
+ fcntl (input_fd, F_SETOWN, getpid ());
init_sigio ();
}
#endif /* F_GETOWN */
+#endif /* F_SETOWN_BUG */
#endif /* F_SETFL */
#ifdef BSD4_1
#endif
#ifdef F_SETFL
+#ifndef F_SETOWN_BUG
#ifdef F_SETOWN /* F_SETFL does not imply existence of F_SETOWN */
if (interrupt_input)
{
reset_sigio ();
- fcntl (0, F_SETOWN, old_fcntl_owner);
+ fcntl (input_fd, F_SETOWN, old_fcntl_owner);
}
#endif /* F_SETOWN */
+#endif /* F_SETOWN_BUG */
#endif /* F_SETFL */
#ifdef BSD4_1
if (interrupt_input)
#ifdef AIX
hft_reset ();
#endif
+
+#ifdef BSD
+ widen_foreground_group ();
+#endif
}
\f
#ifdef HAVE_PTYS
read_input_waiting ()
{
- char buf[256 * BUFFER_SIZE_FACTOR];
struct input_event e;
int nread, i;
extern int quit_char;
if (read_socket_hook)
{
+ struct input_event buf[256];
+
read_alarm_should_throw = 0;
if (! setjmp (read_alarm_throw))
- nread = (*read_socket_hook) (0, buf, 256 * BUFFER_SIZE_FACTOR, 1, 0);
+ nread = (*read_socket_hook) (0, buf, 256, 1, 0);
else
nread = -1;
+
+ /* Scan the chars for C-g and store them in kbd_buffer. */
+ for (i = 0; i < nread; i++)
+ {
+ kbd_buffer_store_event (&buf[i]);
+ /* Don't look at input that follows a C-g too closely.
+ This reduces lossage due to autorepeat on C-g. */
+ if (buf[i].kind == ascii_keystroke
+ && XINT(buf[i].code) == quit_char)
+ break;
+ }
}
else
- nread = read (fileno (stdin), buf, 1);
-
- /* Scan the chars for C-g and store them in kbd_buffer. */
- e.kind = ascii_keystroke;
- e.frame_or_window = selected_frame;
- e.modifiers = 0;
- for (i = 0; i < nread; i++)
{
- XSET (e.code, Lisp_Int, buf[i]);
- kbd_buffer_store_event (&e);
- /* Don't look at input that follows a C-g too closely.
- This reduces lossage due to autorepeat on C-g. */
- if (buf[i] == quit_char)
- break;
+ char buf[3];
+ nread = read (fileno (stdin), buf, 1);
+
+ /* Scan the chars for C-g and store them in kbd_buffer. */
+ e.kind = ascii_keystroke;
+ e.frame_or_window = selected_frame;
+ e.modifiers = 0;
+ for (i = 0; i < nread; i++)
+ {
+ /* Convert chars > 0177 to meta events if desired.
+ We do this under the same conditions that read_avail_input does. */
+ if (read_socket_hook == 0)
+ {
+ /* If the user says she has a meta key, then believe her. */
+ if (meta_key == 1 && (buf[i] & 0x80))
+ e.modifiers = meta_modifier;
+ if (meta_key != 2)
+ buf[i] &= ~0x80;
+ }
+
+ XSET (e.code, Lisp_Int, buf[i]);
+ kbd_buffer_store_event (&e);
+ /* Don't look at input that follows a C-g too closely.
+ This reduces lossage due to autorepeat on C-g. */
+ if (buf[i] == quit_char)
+ break;
+ }
}
}
\f
#ifndef BSTRING
+#ifndef bzero
+
void
bzero (b, length)
register char *b;
#endif /* not VMS */
}
+#endif /* no bzero */
+
+#ifndef bcopy
/* Saying `void' requires a declaration, above, where bcopy is used
and that declaration causes pain for systems where bcopy is a macro. */
bcopy (b1, b2, length)
*b2++ = *b1++;
#endif /* not VMS */
}
+#endif /* no bcopy */
+#ifndef bcmp
int
bcmp (b1, b2, length) /* This could be a macro! */
register char *b1;
return 0;
#endif /* not VMS */
}
+#endif /* no bcmp */
+
#endif /* not BSTRING */
\f
#ifndef HAVE_RANDOM
char *buf;
unsigned int nbyte;
{
- register int rtnval;
+ register int rtnval, bytes_written;
- while ((rtnval = write (fildes, buf, nbyte)) == -1
- && (errno == EINTR));
- return (rtnval);
+ bytes_written = 0;
+
+ while (nbyte > 0)
+ {
+ rtnval = write (fildes, buf, nbyte);
+
+ if (rtnval == -1)
+ {
+ if (errno == EINTR)
+ continue;
+ else
+ return (-1);
+ }
+
+ buf += rtnval;
+ nbyte -= rtnval;
+ bytes_written += rtnval;
+ }
+ return (bytes_written);
}
#endif /* INTERRUPTIBLE_IO */
\f
+#ifndef HAVE_VFORK
+
+/*
+ * Substitute fork for vfork on USG flavors.
+ */
+
+vfork ()
+{
+ return (fork ());
+}
+
+#endif /* not HAVE_VFORK */
+\f
#ifdef USG
/*
* All of the following are for USG.
BLOCK_INPUT; /* getcwd uses malloc */
spath = npath = getcwd ((char *) 0, MAXPATHLEN);
+ if (spath == 0)
+ return spath;
/* On Altos 3068, getcwd can return @hostname/dir, so discard
up to first slash. Should be harmless on other systems. */
while (*npath && *npath != '/')
#ifndef HAVE_RENAME
rename (from, to)
- char *from;
- char *to;
+ const char *from;
+ const char *to;
{
if (access (from, 0) == 0)
{
#endif
-#ifndef HAVE_VFORK
-
-/*
- * Substitute fork for vfork on USG flavors.
- */
-
-vfork ()
-{
- return (fork ());
-}
-
-#endif /* not HAVE_VFORK */
-
#ifdef MISSING_UTIMES
/* HPUX (among others) sets HAVE_TIMEVAL but does not implement utimes. */
#include <dirent.h>
-#ifndef AIX
+#if defined(BROKEN_CLOSEDIR) || !defined(HAVE_CLOSEDIR)
+
int
closedir (dirp)
register DIR *dirp; /* stream from opendir */
{
- sys_close (dirp->dd_fd);
- xfree ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
+ int rtnval;
+
+ rtnval = sys_close (dirp->dd_fd);
+
+ /* Some systems (like Solaris) allocate the buffer and the DIR all
+ in one block. Why in the world are we freeing this ourselves
+ anyway? */
+#if ! (defined (sun) && defined (USG5_4))
+ xfree ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
+#endif
xfree ((char *) dirp);
+
+ return rtnval;
}
-#endif /* not AIX */
+#endif /* BROKEN_CLOSEDIR or not HAVE_CLOSEDIR */
#endif /* SYSV_SYSTEM_DIR */
#ifdef NONSYSTEM_DIR_LIBRARY
#endif /* VMS */
#endif /* NONSYSTEM_DIR_LIBRARY */
+
+\f
+/* mkdir and rmdir functions, for systems which don't have them. */
+
+#ifndef HAVE_MKDIR
+/*
+ * Written by Robert Rother, Mariah Corporation, August 1985.
+ *
+ * If you want it, it's yours. All I ask in return is that if you
+ * figure out how to do this in a Bourne Shell script you send me
+ * a copy.
+ * sdcsvax!rmr or rmr@uscd
+ *
+ * Severely hacked over by John Gilmore to make a 4.2BSD compatible
+ * subroutine. 11Mar86; hoptoad!gnu
+ *
+ * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
+ * subroutine didn't return EEXIST. It does now.
+ */
+
+/*
+ * Make a directory.
+ */
+int
+mkdir (dpath, dmode)
+ char *dpath;
+ int dmode;
+{
+ int cpid, status, fd;
+ struct stat statbuf;
+
+ if (stat (dpath, &statbuf) == 0)
+ {
+ errno = EEXIST; /* Stat worked, so it already exists */
+ return -1;
+ }
+
+ /* If stat fails for a reason other than non-existence, return error */
+ if (errno != ENOENT)
+ return -1;
+
+ synch_process_alive = 1;
+ switch (cpid = fork ())
+ {
+
+ case -1: /* Error in fork */
+ return (-1); /* Errno is set already */
+
+ case 0: /* Child process */
+ /*
+ * Cheap hack to set mode of new directory. Since this
+ * child process is going away anyway, we zap its umask.
+ * FIXME, this won't suffice to set SUID, SGID, etc. on this
+ * directory. Does anybody care?
+ */
+ status = umask (0); /* Get current umask */
+ status = umask (status | (0777 & ~dmode)); /* Set for mkdir */
+ fd = sys_open("/dev/null", 2);
+ if (fd >= 0)
+ {
+ dup2 (fd, 0);
+ dup2 (fd, 1);
+ dup2 (fd, 2);
+ }
+ execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
+ _exit (-1); /* Can't exec /bin/mkdir */
+
+ default: /* Parent process */
+ wait_for_termination (cpid);
+ }
+
+ if (synch_process_death != 0 || synch_process_retcode != 0)
+ {
+ errno = EIO; /* We don't know why, but */
+ return -1; /* /bin/mkdir failed */
+ }
+
+ return 0;
+}
+#endif /* not HAVE_MKDIR */
+
+#ifndef HAVE_RMDIR
+int
+rmdir (dpath)
+ char *dpath;
+{
+ int cpid, status, fd;
+ struct stat statbuf;
+
+ if (stat (dpath, &statbuf) != 0)
+ {
+ /* Stat just set errno. We don't have to */
+ return -1;
+ }
+
+ synch_process_alive = 1;
+ switch (cpid = fork ())
+ {
+
+ case -1: /* Error in fork */
+ return (-1); /* Errno is set already */
+
+ case 0: /* Child process */
+ fd = sys_open("/dev/null", 2);
+ if (fd >= 0)
+ {
+ dup2 (fd, 0);
+ dup2 (fd, 1);
+ dup2 (fd, 2);
+ }
+ execl ("/bin/rmdir", "rmdir", dpath, (char *) 0);
+ _exit (-1); /* Can't exec /bin/mkdir */
+
+ default: /* Parent process */
+ wait_for_termination (cpid);
+ }
+
+ if (synch_process_death != 0 || synch_process_retcode != 0)
+ {
+ errno = EIO; /* We don't know why, but */
+ return -1; /* /bin/rmdir failed */
+ }
+
+ return 0;
+}
+#endif /* !HAVE_RMDIR */
+
+
\f
/* Functions for VMS */
#ifdef VMS
getwd (pathname)
char *pathname;
{
- char *ptr;
+ char *ptr, *val;
extern char *getcwd ();
#define MAXPATHLEN 1024
ptr = xmalloc (MAXPATHLEN);
- getcwd (ptr, MAXPATHLEN);
+ val = getcwd (ptr, MAXPATHLEN);
+ if (val == 0)
+ {
+ xfree (ptr);
+ return val;
+ }
strcpy (pathname, ptr);
xfree (ptr);