#include <pwd.h>
#include <grp.h>
#endif /* HAVE_PWD_H */
-#ifdef HAVE_LIMITS_H
#include <limits.h>
-#endif /* HAVE_LIMITS_H */
#include <unistd.h>
#include <allocator.h>
#endif
#endif
+static int emacs_get_tty (int, struct emacs_tty *);
+static int emacs_set_tty (int, struct emacs_tty *, int);
+#if defined TIOCNOTTY || defined USG5 || defined CYGWIN
+static void croak (char *) NO_RETURN;
+#endif
+
/* Declare here, including term.h is problematic on some systems. */
extern void tputs (const char *, int, int (*)(int));
1800, 2400, 4800, 9600, 19200, 38400
};
-void croak (char *) NO_RETURN;
-
-/* Temporary used by `sigblock' when defined in terms of signprocmask. */
-
-SIGMASKTYPE sigprocmask_set;
-
#if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME)
\f
-int wait_debugging; /* Set nonzero to make following function work under dbx
- (at least for bsd). */
+/* Set nonzero to make following function work under dbx
+ (at least for bsd). */
+int wait_debugging EXTERNALLY_VISIBLE;
#ifndef MSDOS
-/* Wait for subprocess with process id `pid' to terminate and
- make sure it will get eliminated (not remain forever as a zombie) */
-void
-wait_for_termination (int pid)
+static void
+wait_for_termination_1 (int pid, int interruptible)
{
while (1)
{
-#if defined (BSD_SYSTEM) || defined (HPUX)
+#if (defined (BSD_SYSTEM) || defined (HPUX)) && !defined(__GNU__)
/* Note that kill returns -1 even if the process is just a zombie now.
But inevitably a SIGCHLD interrupt should be generated
and child_sig will do wait3 and make the process go away. */
sigsuspend (&empty_mask);
#endif /* not WINDOWSNT */
#endif /* not BSD_SYSTEM, and not HPUX version >= 6 */
+ if (interruptible)
+ QUIT;
}
}
+/* Wait for subprocess with process id `pid' to terminate and
+ make sure it will get eliminated (not remain forever as a zombie) */
+
+void
+wait_for_termination (int pid)
+{
+ wait_for_termination_1 (pid, 0);
+}
+
+/* Like the above, but allow keyboard interruption. */
+void
+interruptible_wait_for_termination (int pid)
+{
+ wait_for_termination_1 (pid, 1);
+}
+
/*
* flush any pending output
* (may flush input as well; it does not matter the way we use it)
#else
#ifdef F_SETFL
-int old_fcntl_flags[MAXDESC];
+static int old_fcntl_flags[MAXDESC];
void
init_sigio (int fd)
\f
#ifdef F_SETOWN
-int old_fcntl_owner[MAXDESC];
+static int old_fcntl_owner[MAXDESC];
#endif /* F_SETOWN */
/* This may also be defined in stdio,
void
get_tty_size (int fd, int *widthp, int *heightp)
{
-
-#ifdef TIOCGWINSZ
+#if defined TIOCGWINSZ
/* BSD-style. */
struct winsize size;
*heightp = size.ws_row;
}
-#else
-#ifdef TIOCGSIZE
+#elif defined TIOCGSIZE
/* SunOS - style. */
struct ttysize size;
*heightp = size.ts_lines;
}
-#else
-#ifdef MSDOS
+#elif defined WINDOWSNT
+
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ if (GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info))
+ {
+ *widthp = info.srWindow.Right - info.srWindow.Left + 1;
+ *heightp = info.srWindow.Bottom - info.srWindow.Top + 1;
+ }
+ else
+ *widthp = *heightp = 0;
+
+#elif defined MSDOS
+
*widthp = ScreenCols ();
*heightp = ScreenRows ();
+
#else /* system doesn't know size */
+
*widthp = 0;
*heightp = 0;
+
#endif
-#endif /* not SunOS-style */
-#endif /* not BSD-style */
}
/* Set the logical window size associated with descriptor FD
/* POSIX signals support - DJB */
/* Anyone with POSIX signals should have ANSI C declarations */
-sigset_t empty_mask, full_mask;
+sigset_t empty_mask;
#ifndef WINDOWSNT
sys_sigblock (sigset_t new_mask)
{
sigset_t old_mask;
- sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
+ pthread_sigmask (SIG_BLOCK, &new_mask, &old_mask);
return (old_mask);
}
sys_sigunblock (sigset_t new_mask)
{
sigset_t old_mask;
- sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask);
+ pthread_sigmask (SIG_UNBLOCK, &new_mask, &old_mask);
return (old_mask);
}
sys_sigsetmask (sigset_t new_mask)
{
sigset_t old_mask;
- sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
+ pthread_sigmask (SIG_SETMASK, &new_mask, &old_mask);
return (old_mask);
}
init_signals (void)
{
sigemptyset (&empty_mask);
- sigfillset (&full_mask);
#if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
if (! initialized)
}
/*
- * Build a full Emacs-sized word out of whatever we've got.
+ * Return a nonnegative random integer out of whatever we've got.
+ * It contains enough bits to make a random (signed) Emacs fixnum.
* This suffices even for a 64-bit architecture with a 15-bit rand.
*/
-long
+EMACS_INT
get_random (void)
{
- long val = random ();
-#if VALBITS > RAND_BITS
- val = (val << RAND_BITS) ^ random ();
-#if VALBITS > 2*RAND_BITS
- val = (val << RAND_BITS) ^ random ();
-#if VALBITS > 3*RAND_BITS
- val = (val << RAND_BITS) ^ random ();
-#if VALBITS > 4*RAND_BITS
- val = (val << RAND_BITS) ^ random ();
-#endif /* need at least 5 */
-#endif /* need at least 4 */
-#endif /* need at least 3 */
-#endif /* need at least 2 */
- return val & ((1L << VALBITS) - 1);
+ EMACS_UINT val = 0;
+ int i;
+ for (i = 0; i < (FIXNUM_BITS + RAND_BITS - 1) / RAND_BITS; i++)
+ val = (random () ^ (val << RAND_BITS)
+ ^ (val >> (BITS_PER_EMACS_INT - RAND_BITS)));
+ val ^= val >> (BITS_PER_EMACS_INT - FIXNUM_BITS);
+ return val & INTMASK;
}
#ifndef HAVE_STRERROR
#ifndef WINDOWSNT
char *
-strerror (errnum)
- int errnum;
+strerror (int errnum)
{
extern char *sys_errlist[];
extern int sys_nerr;
return rtnval;
}
-int
-emacs_read (int fildes, char *buf, unsigned int nbyte)
+/* Maximum number of bytes to read or write in a single system call.
+ This works around a serious bug in Linux kernels before 2.6.16; see
+ <https://bugzilla.redhat.com/show_bug.cgi?format=multiple&id=612839>.
+ It's likely to work around similar bugs in other operating systems, so do it
+ on all platforms. Round INT_MAX down to a page size, with the conservative
+ assumption that page sizes are at most 2**18 bytes (any kernel with a
+ page size larger than that shouldn't have the bug). */
+#ifndef MAX_RW_COUNT
+#define MAX_RW_COUNT (INT_MAX >> 18 << 18)
+#endif
+
+/* Read from FILEDESC to a buffer BUF with size NBYTE, retrying if interrupted.
+ Return the number of bytes read, which might be less than NBYTE.
+ On error, set errno and return -1. */
+EMACS_INT
+emacs_read (int fildes, char *buf, EMACS_INT nbyte)
{
- register int rtnval;
+ register ssize_t rtnval;
+
+ /* There is no need to check against MAX_RW_COUNT, since no caller ever
+ passes a size that large to emacs_read. */
while ((rtnval = read (fildes, buf, nbyte)) == -1
&& (errno == EINTR))
return (rtnval);
}
-int
-emacs_write (int fildes, const char *buf, unsigned int nbyte)
+/* Write to FILEDES from a buffer BUF with size NBYTE, retrying if interrupted
+ or if a partial write occurs. Return the number of bytes written, setting
+ errno if this is less than NBYTE. */
+EMACS_INT
+emacs_write (int fildes, const char *buf, EMACS_INT nbyte)
{
- register int rtnval, bytes_written;
+ ssize_t rtnval;
+ EMACS_INT bytes_written;
bytes_written = 0;
while (nbyte > 0)
{
- rtnval = write (fildes, buf, nbyte);
+ rtnval = write (fildes, buf, min (nbyte, MAX_RW_COUNT));
- if (rtnval == -1)
+ if (rtnval < 0)
{
if (errno == EINTR)
{
continue;
}
else
- return (bytes_written ? bytes_written : -1);
+ break;
}
buf += rtnval;
nbyte -= rtnval;
bytes_written += rtnval;
}
+
return (bytes_written);
}
}
#endif /* HPUX and not HAVE_PERROR */
-#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.
- */
-
-int
-dup2 (int oldd, int newd)
-{
- register int fd, ret;
-
- emacs_close (newd);
-
-#ifdef F_DUPFD
- return fcntl (oldd, F_DUPFD, newd);
-#else
- fd = dup (old);
- if (fd == -1)
- return -1;
- if (fd == new)
- return new;
- ret = dup2 (old,new);
- emacs_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.
#endif /* !HAVE_RMDIR */
\f
-#ifndef HAVE_MEMSET
-void *
-memset (void *b, int n, size_t length)
-{
- unsigned char *p = b;
- while (length-- > 0)
- *p++ = n;
- return b;
-}
-#endif /* !HAVE_MEMSET */
-
-#ifndef HAVE_MEMCPY
-void *
-memcpy (void *b1, void *b2, size_t length)
-{
- unsigned char *p1 = b1, *p2 = b2;
- while (length-- > 0)
- *p1++ = *p2++;
- return b1;
-}
-#endif /* !HAVE_MEMCPY */
-
-#ifndef HAVE_MEMMOVE
-void *
-memmove (void *b1, void *b2, size_t length)
-{
- unsigned char *p1 = b1, *p2 = b2;
- if (p1 < p2 || p1 >= p2 + length)
- while (length-- > 0)
- *p1++ = *p2++;
- else
- {
- p1 += length;
- p2 += length;
- while (length-- > 0)
- *--p1 = *--p2;
- }
- return b1;
-}
-#endif /* !HAVE_MEMCPY */
-
-#ifndef HAVE_MEMCMP
-int
-memcmp (void *b1, void *b2, size_t length)
-{
- unsigned char *p1 = b1, *p2 = b2;
- while (length-- > 0)
- if (*p1++ != *p2++)
- return p1[-1] < p2[-1] ? -1 : 1;
- return 0;
-}
-#endif /* !HAVE_MEMCMP */
-\f
#ifndef HAVE_STRSIGNAL
char *
strsignal (int code)
CHECK_NUMBER (tem);
err = cfsetspeed (&attr, XINT (tem));
if (err != 0)
- error ("cfsetspeed(%d) failed: %s", XINT (tem), emacs_strerror (errno));
+ error ("cfsetspeed(%"pI"d) failed: %s", XINT (tem),
+ emacs_strerror (errno));
childp2 = Fplist_put (childp2, QCspeed, tem);
/* Configure bytesize. */
#if PROCFS_FILE_OFFSET_BITS_HACK == 1
#define _FILE_OFFSET_BITS 64
+#ifdef _FILE_OFFSET_BITS /* Avoid unused-macro warnings. */
+#endif
#endif /* PROCFS_FILE_OFFSET_BITS_HACK == 1 */
Lisp_Object