[BACK]Return to os.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / less

Annotation of src/usr.bin/less/os.c, Revision 1.1.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: }