diff options
Diffstat (limited to 'contrib/less/os.c')
| -rw-r--r-- | contrib/less/os.c | 312 | 
1 files changed, 312 insertions, 0 deletions
| diff --git a/contrib/less/os.c b/contrib/less/os.c new file mode 100644 index 0000000000000..4c532e9350e71 --- /dev/null +++ b/contrib/less/os.c @@ -0,0 +1,312 @@ +/* + * Copyright (C) 1984-2000  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 about less, or for information on how to  + * contact the author, 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_LIMITS_H +#include <limits.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; + +#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_SIGSETMASK +		sigsetmask(0); +#else +#ifdef _OSK +		sigmask(~0); +#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) +		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; +#if HAVE_ERRNO +#if MUST_DEFINE_ERRNO +	extern int errno; +#endif +	p = strerror(errno); +#else +	p = "cannot open"; +#endif +	m = (char *) ecalloc(strlen(filename) + strlen(p) + 3, sizeof(char)); +	sprintf(m, "%s: %s", filename, p); +	return (m); +} + +/* + * Return the largest possible number that can fit in a long. + */ +	static long +get_maxlong() +{ +#ifdef LONG_MAX +	return (LONG_MAX); +#else +#ifdef MAXLONG +	return (MAXLONG); +#else +	long n, n2; + +	/* +	 * Keep doubling n until we overflow. +	 * {{ This actually only returns the largest power of two that +	 *    can fit in a long, but percentage() doesn't really need +	 *    it any more accurate than that. }} +	 */ +	n2 = 128;  /* Hopefully no maxlong is less than 128! */ +	do { +		n = n2; +		n2 *= 2; +	} while (n2 / 2 == n); +	return (n); +#endif +#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; +{ +	if (num <= get_maxlong() / 100) +		return ((100 * num) / den); +	else +		return (num / (den / 100)); +} + +/* + * Return the specified percentage of a POSITION. + * {{ Assumes a POSITION is a long int. }} + */ +	public POSITION +percent_pos(pos, percent) +	POSITION pos; +	int percent; +{ +	if (pos <= get_maxlong() / 100) +		return ((percent * pos) / 100); +	else +		return (percent * (pos / 100)); +} + +#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> + +	public int  +isatty(f) +	int f; +{ +	struct sgbuf sgbuf; + +	if (_gs_opt(f, &sgbuf) < 0) +		return -1; +	return (sgbuf.sg_class == 0); +} +	 +#endif | 
