summaryrefslogtreecommitdiff
path: root/os.c
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2012-07-21 20:40:00 +0000
committerLorry <lorry@roadtrain.codethink.co.uk>2012-09-24 16:52:48 +0000
commit09a405d8f652b56944c93ebf5c673cdfe5319b04 (patch)
tree9cc4518b0a21096735b20ac3204a6fa032f1c566 /os.c
downloadless-master.tar.gz
Imported from /srv/lorry/lorry-area/less/less-451.tar.gz.HEADless-451masterbaserock/morph
Diffstat (limited to 'os.c')
-rwxr-xr-xos.c363
1 files changed, 363 insertions, 0 deletions
diff --git a/os.c b/os.c
new file mode 100755
index 0000000..eb75bba
--- /dev/null
+++ b/os.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 1984-2012 Mark Nudelman
+ *
+ * You may distribute under the terms of either the GNU General Public
+ * License or the Less License, as specified in the README file.
+ *
+ * For more information, see the README file.
+ */
+
+
+/*
+ * Operating system dependent routines.
+ *
+ * Most of the stuff in here is based on Unix, but an attempt
+ * has been made to make things work on other operating systems.
+ * This will sometimes result in a loss of functionality, unless
+ * someone rewrites code specifically for the new operating system.
+ *
+ * The makefile provides defines to decide whether various
+ * Unix features are present.
+ */
+
+#include "less.h"
+#include <signal.h>
+#include <setjmp.h>
+#if HAVE_TIME_H
+#include <time.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if HAVE_VALUES_H
+#include <values.h>
+#endif
+
+#if HAVE_TIME_T
+#define time_type time_t
+#else
+#define time_type long
+#endif
+
+/*
+ * BSD setjmp() saves (and longjmp() restores) the signal mask.
+ * This costs a system call or two per setjmp(), so if possible we clear the
+ * signal mask with sigsetmask(), and use _setjmp()/_longjmp() instead.
+ * On other systems, setjmp() doesn't affect the signal mask and so
+ * _setjmp() does not exist; we just use setjmp().
+ */
+#if HAVE__SETJMP && HAVE_SIGSETMASK
+#define SET_JUMP _setjmp
+#define LONG_JUMP _longjmp
+#else
+#define SET_JUMP setjmp
+#define LONG_JUMP longjmp
+#endif
+
+public int reading;
+
+static jmp_buf read_label;
+
+extern int sigs;
+
+/*
+ * Like read() system call, but is deliberately interruptible.
+ * A call to intread() from a signal handler will interrupt
+ * any pending iread().
+ */
+ public int
+iread(fd, buf, len)
+ int fd;
+ char *buf;
+ unsigned int len;
+{
+ register int n;
+
+start:
+#if MSDOS_COMPILER==WIN32C
+ if (ABORT_SIGS())
+ return (READ_INTR);
+#else
+#if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
+ if (kbhit())
+ {
+ int c;
+
+ c = getch();
+ if (c == '\003')
+ return (READ_INTR);
+ ungetch(c);
+ }
+#endif
+#endif
+ if (SET_JUMP(read_label))
+ {
+ /*
+ * We jumped here from intread.
+ */
+ reading = 0;
+#if HAVE_SIGPROCMASK
+ {
+ sigset_t mask;
+ sigemptyset(&mask);
+ sigprocmask(SIG_SETMASK, &mask, NULL);
+ }
+#else
+#if HAVE_SIGSETMASK
+ sigsetmask(0);
+#else
+#ifdef _OSK
+ sigmask(~0);
+#endif
+#endif
+#endif
+ return (READ_INTR);
+ }
+
+ flush();
+ reading = 1;
+#if MSDOS_COMPILER==DJGPPC
+ if (isatty(fd))
+ {
+ /*
+ * Don't try reading from a TTY until a character is
+ * available, because that makes some background programs
+ * believe DOS is busy in a way that prevents those
+ * programs from working while "less" waits.
+ */
+ fd_set readfds;
+
+ FD_ZERO(&readfds);
+ FD_SET(fd, &readfds);
+ if (select(fd+1, &readfds, 0, 0, 0) == -1)
+ return (-1);
+ }
+#endif
+ n = read(fd, buf, len);
+#if 1
+ /*
+ * This is a kludge to workaround a problem on some systems
+ * where terminating a remote tty connection causes read() to
+ * start returning 0 forever, instead of -1.
+ */
+ {
+ extern int ignore_eoi;
+ if (!ignore_eoi)
+ {
+ static int consecutive_nulls = 0;
+ if (n == 0)
+ consecutive_nulls++;
+ else
+ consecutive_nulls = 0;
+ if (consecutive_nulls > 20)
+ quit(QUIT_ERROR);
+ }
+ }
+#endif
+ reading = 0;
+ if (n < 0)
+ {
+#if HAVE_ERRNO
+ /*
+ * Certain values of errno indicate we should just retry the read.
+ */
+#if MUST_DEFINE_ERRNO
+ extern int errno;
+#endif
+#ifdef EINTR
+ if (errno == EINTR)
+ goto start;
+#endif
+#ifdef EAGAIN
+ if (errno == EAGAIN)
+ goto start;
+#endif
+#endif
+ return (-1);
+ }
+ return (n);
+}
+
+/*
+ * Interrupt a pending iread().
+ */
+ public void
+intread()
+{
+ LONG_JUMP(read_label, 1);
+}
+
+/*
+ * Return the current time.
+ */
+#if HAVE_TIME
+ public long
+get_time()
+{
+ time_type t;
+
+ time(&t);
+ return (t);
+}
+#endif
+
+
+#if !HAVE_STRERROR
+/*
+ * Local version of strerror, if not available from the system.
+ */
+ static char *
+strerror(err)
+ int err;
+{
+#if HAVE_SYS_ERRLIST
+ static char buf[16];
+ extern char *sys_errlist[];
+ extern int sys_nerr;
+
+ if (err < sys_nerr)
+ return sys_errlist[err];
+ sprintf(buf, "Error %d", err);
+ return buf;
+#else
+ return ("cannot open");
+#endif
+}
+#endif
+
+/*
+ * errno_message: Return an error message based on the value of "errno".
+ */
+ public char *
+errno_message(filename)
+ char *filename;
+{
+ register char *p;
+ register char *m;
+ int len;
+#if HAVE_ERRNO
+#if MUST_DEFINE_ERRNO
+ extern int errno;
+#endif
+ p = strerror(errno);
+#else
+ p = "cannot open";
+#endif
+ len = strlen(filename) + strlen(p) + 3;
+ m = (char *) ecalloc(len, sizeof(char));
+ SNPRINTF2(m, len, "%s: %s", filename, p);
+ return (m);
+}
+
+/* #define HAVE_FLOAT 0 */
+
+ static POSITION
+muldiv(val, num, den)
+ POSITION val, num, den;
+{
+#if HAVE_FLOAT
+ double v = (((double) val) * num) / den;
+ return ((POSITION) (v + 0.5));
+#else
+ POSITION v = ((POSITION) val) * num;
+
+ if (v / num == val)
+ /* No overflow */
+ return (POSITION) (v / den);
+ else
+ /* Above calculation overflows;
+ * use a method that is less precise but won't overflow. */
+ return (POSITION) (val / (den / num));
+#endif
+}
+
+/*
+ * Return the ratio of two POSITIONS, as a percentage.
+ * {{ Assumes a POSITION is a long int. }}
+ */
+ public int
+percentage(num, den)
+ POSITION num, den;
+{
+ return (int) muldiv(num, (POSITION) 100, den);
+}
+
+/*
+ * Return the specified percentage of a POSITION.
+ */
+ public POSITION
+percent_pos(pos, percent, fraction)
+ POSITION pos;
+ int percent;
+ long fraction;
+{
+ /* Change percent (parts per 100) to perden (parts per NUM_FRAC_DENOM). */
+ POSITION perden = (percent * (NUM_FRAC_DENOM / 100)) + (fraction / 100);
+
+ if (perden == 0)
+ return (0);
+ return (POSITION) muldiv(pos, perden, (POSITION) NUM_FRAC_DENOM);
+}
+
+#if !HAVE_STRCHR
+/*
+ * strchr is used by regexp.c.
+ */
+ char *
+strchr(s, c)
+ char *s;
+ int c;
+{
+ for ( ; *s != '\0'; s++)
+ if (*s == c)
+ return (s);
+ if (c == '\0')
+ return (s);
+ return (NULL);
+}
+#endif
+
+#if !HAVE_MEMCPY
+ VOID_POINTER
+memcpy(dst, src, len)
+ VOID_POINTER dst;
+ VOID_POINTER src;
+ int len;
+{
+ char *dstp = (char *) dst;
+ char *srcp = (char *) src;
+ int i;
+
+ for (i = 0; i < len; i++)
+ dstp[i] = srcp[i];
+ return (dst);
+}
+#endif
+
+#ifdef _OSK_MWC32
+
+/*
+ * This implements an ANSI-style intercept setup for Microware C 3.2
+ */
+ public int
+os9_signal(type, handler)
+ int type;
+ RETSIGTYPE (*handler)();
+{
+ intercept(handler);
+}
+
+#include <sgstat.h>
+
+ int
+isatty(f)
+ int f;
+{
+ struct sgbuf sgbuf;
+
+ if (_gs_opt(f, &sgbuf) < 0)
+ return -1;
+ return (sgbuf.sg_class == 0);
+}
+
+#endif