Annotation of src/usr.bin/less/os.c, Revision 1.1
1.1 ! etheisen 1: /*
! 2: * Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman
! 3: * All rights reserved.
! 4: *
! 5: * Redistribution and use in source and binary forms, with or without
! 6: * modification, are permitted provided that the following conditions
! 7: * are met:
! 8: * 1. Redistributions of source code must retain the above copyright
! 9: * notice, this list of conditions and the following disclaimer.
! 10: * 2. Redistributions in binary form must reproduce the above copyright
! 11: * notice in the documentation and/or other materials provided with
! 12: * the distribution.
! 13: *
! 14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
! 15: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 16: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 17: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
! 18: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 19: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
! 20: * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
! 21: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
! 22: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
! 23: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
! 24: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 25: */
! 26:
! 27:
! 28: /*
! 29: * Operating system dependent routines.
! 30: *
! 31: * Most of the stuff in here is based on Unix, but an attempt
! 32: * has been made to make things work on other operating systems.
! 33: * This will sometimes result in a loss of functionality, unless
! 34: * someone rewrites code specifically for the new operating system.
! 35: *
! 36: * The makefile provides defines to decide whether various
! 37: * Unix features are present.
! 38: */
! 39:
! 40: #include "less.h"
! 41: #include <signal.h>
! 42: #include <setjmp.h>
! 43: #if HAVE_TIME_H
! 44: #include <time.h>
! 45: #endif
! 46: #if HAVE_ERRNO_H
! 47: #include <errno.h>
! 48: #endif
! 49: #if HAVE_VALUES_H
! 50: #include <values.h>
! 51: #endif
! 52:
! 53: #if HAVE_TIME_T
! 54: #define time_type time_t
! 55: #else
! 56: #define time_type long
! 57: #endif
! 58:
! 59: /*
! 60: * BSD setjmp() saves (and longjmp() restores) the signal mask.
! 61: * This costs a system call or two per setjmp(), so if possible we clear the
! 62: * signal mask with sigsetmask(), and use _setjmp()/_longjmp() instead.
! 63: * On other systems, setjmp() doesn't affect the signal mask and so
! 64: * _setjmp() does not exist; we just use setjmp().
! 65: */
! 66: #if HAVE__SETJMP && HAVE_SIGSETMASK
! 67: #define SET_JUMP _setjmp
! 68: #define LONG_JUMP _longjmp
! 69: #else
! 70: #define SET_JUMP setjmp
! 71: #define LONG_JUMP longjmp
! 72: #endif
! 73:
! 74: public int reading;
! 75:
! 76: static jmp_buf read_label;
! 77:
! 78: /*
! 79: * Like read() system call, but is deliberately interruptible.
! 80: * A call to intread() from a signal handler will interrupt
! 81: * any pending iread().
! 82: */
! 83: public int
! 84: iread(fd, buf, len)
! 85: int fd;
! 86: char *buf;
! 87: unsigned int len;
! 88: {
! 89: register int n;
! 90:
! 91: #if MSOFTC
! 92: if (kbhit())
! 93: {
! 94: int c;
! 95:
! 96: c = getch();
! 97: if (c == '\003')
! 98: return (READ_INTR);
! 99: ungetch(c);
! 100: }
! 101: #endif
! 102: if (SET_JUMP(read_label))
! 103: {
! 104: /*
! 105: * We jumped here from intread.
! 106: */
! 107: reading = 0;
! 108: #if HAVE_SIGSETMASK
! 109: sigsetmask(0);
! 110: #endif
! 111: return (READ_INTR);
! 112: }
! 113:
! 114: flush();
! 115: reading = 1;
! 116: n = read(fd, buf, len);
! 117: reading = 0;
! 118: if (n < 0)
! 119: return (-1);
! 120: return (n);
! 121: }
! 122:
! 123: /*
! 124: * Interrupt a pending iread().
! 125: */
! 126: public void
! 127: intread()
! 128: {
! 129: LONG_JUMP(read_label, 1);
! 130: }
! 131:
! 132: /*
! 133: * Return the current time.
! 134: */
! 135: #if HAVE_TIME
! 136: public long
! 137: get_time()
! 138: {
! 139: time_type t;
! 140:
! 141: time(&t);
! 142: return (t);
! 143: }
! 144: #endif
! 145:
! 146:
! 147: #if !HAVE_STRERROR
! 148: /*
! 149: * Local version of strerror, if not available from the system.
! 150: */
! 151: static char *
! 152: strerror(err)
! 153: int err;
! 154: {
! 155: #if HAVE_SYS_ERRLIST
! 156: static char buf[16];
! 157: extern char *sys_errlist[];
! 158: extern int sys_nerr;
! 159:
! 160: if (err < sys_nerr)
! 161: return sys_errlist[err];
! 162: sprintf(buf, "Error %d", err);
! 163: return buf;
! 164: #else
! 165: return ("cannot open");
! 166: #endif
! 167: }
! 168: #endif
! 169:
! 170: /*
! 171: * errno_message: Return an error message based on the value of "errno".
! 172: */
! 173: public char *
! 174: errno_message(filename)
! 175: char *filename;
! 176: {
! 177: register char *p;
! 178: register char *m;
! 179: #if HAVE_ERRNO
! 180: extern int errno;
! 181: p = strerror(errno);
! 182: #else
! 183: p = "cannot open";
! 184: #endif
! 185: m = (char *) ecalloc(strlen(filename) + strlen(p) + 3, sizeof(char));
! 186: sprintf(m, "%s: %s", filename, p);
! 187: return (m);
! 188: }
! 189:
! 190: /*
! 191: * Return the largest possible number that can fit in a long.
! 192: */
! 193: #ifdef MAXLONG
! 194: static long
! 195: get_maxlong()
! 196: {
! 197: return (MAXLONG);
! 198: }
! 199: #else
! 200: static long
! 201: get_maxlong()
! 202: {
! 203: long n, n2;
! 204:
! 205: /*
! 206: * Keep doubling n until we overflow.
! 207: * {{ This actually only returns the largest power of two that
! 208: * can fit in a long, but percentage() doesn't really need
! 209: * it any more accurate than that. }}
! 210: */
! 211: n2 = 128; /* Hopefully no maxlong is less than 128! */
! 212: do {
! 213: n = n2;
! 214: n2 *= 2;
! 215: } while (n2 / 2 == n);
! 216: return (n);
! 217: }
! 218: #endif
! 219:
! 220: /*
! 221: * Return the ratio of two longs, as a percentage.
! 222: */
! 223: public int
! 224: percentage(num, den)
! 225: long num, den;
! 226: {
! 227: static long maxlong100 = 0;
! 228:
! 229: if (maxlong100 == 0)
! 230: maxlong100 = get_maxlong() / 100;
! 231: if (num > maxlong100)
! 232: return (num / (den/100));
! 233: else
! 234: return (100*num / den);
! 235: }