[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.10

1.1       etheisen    1: /*
1.8       shadchin    2:  * Copyright (C) 1984-2011  Mark Nudelman
1.1       etheisen    3:  *
1.6       millert     4:  * You may distribute under the terms of either the GNU General Public
                      5:  * License or the Less License, as specified in the README file.
1.1       etheisen    6:  *
1.6       millert     7:  * For more information about less, or for information on how to
                      8:  * contact the author, see the README file.
1.1       etheisen    9:  */
                     10:
                     11:
                     12: /*
                     13:  * Operating system dependent routines.
                     14:  *
                     15:  * Most of the stuff in here is based on Unix, but an attempt
                     16:  * has been made to make things work on other operating systems.
                     17:  * This will sometimes result in a loss of functionality, unless
                     18:  * someone rewrites code specifically for the new operating system.
                     19:  *
                     20:  * The makefile provides defines to decide whether various
                     21:  * Unix features are present.
                     22:  */
                     23:
                     24: #include "less.h"
                     25: #include <signal.h>
                     26: #if HAVE_TIME_H
                     27: #include <time.h>
                     28: #endif
                     29: #if HAVE_ERRNO_H
                     30: #include <errno.h>
                     31: #endif
                     32: #if HAVE_VALUES_H
                     33: #include <values.h>
                     34: #endif
                     35:
                     36: #if HAVE_TIME_T
                     37: #define time_type      time_t
                     38: #else
                     39: #define        time_type       long
                     40: #endif
                     41:
1.10    ! millert    42: extern volatile sig_atomic_t sigs;
1.6       millert    43:
1.1       etheisen   44: /*
                     45:  * Like read() system call, but is deliberately interruptible.
                     46:  */
                     47:        public int
                     48: iread(fd, buf, len)
                     49:        int fd;
                     50:        char *buf;
                     51:        unsigned int len;
                     52: {
1.6       millert    53:        register int n;
1.1       etheisen   54:
1.8       shadchin   55: start:
1.6       millert    56: #if MSDOS_COMPILER==WIN32C
                     57:        if (ABORT_SIGS())
                     58:                return (READ_INTR);
                     59: #else
                     60: #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
1.1       etheisen   61:        if (kbhit())
                     62:        {
                     63:                int c;
                     64:
                     65:                c = getch();
                     66:                if (c == '\003')
                     67:                        return (READ_INTR);
                     68:                ungetch(c);
                     69:        }
                     70: #endif
1.6       millert    71: #endif
1.1       etheisen   72:
                     73:        flush();
1.6       millert    74: #if MSDOS_COMPILER==DJGPPC
                     75:        if (isatty(fd))
                     76:        {
                     77:                /*
                     78:                 * Don't try reading from a TTY until a character is
                     79:                 * available, because that makes some background programs
                     80:                 * believe DOS is busy in a way that prevents those
                     81:                 * programs from working while "less" waits.
                     82:                 */
                     83:                fd_set readfds;
                     84:
                     85:                FD_ZERO(&readfds);
                     86:                FD_SET(fd, &readfds);
                     87:                if (select(fd+1, &readfds, 0, 0, 0) == -1)
                     88:                        return (-1);
                     89:        }
                     90: #endif
1.1       etheisen   91:        n = read(fd, buf, len);
1.6       millert    92: #if 1
                     93:        /*
                     94:         * This is a kludge to workaround a problem on some systems
                     95:         * where terminating a remote tty connection causes read() to
                     96:         * start returning 0 forever, instead of -1.
                     97:         */
                     98:        {
                     99:                extern int ignore_eoi;
                    100:                if (!ignore_eoi)
                    101:                {
                    102:                        static int consecutive_nulls = 0;
                    103:                        if (n == 0)
                    104:                                consecutive_nulls++;
                    105:                        else
                    106:                                consecutive_nulls = 0;
                    107:                        if (consecutive_nulls > 20)
                    108:                                quit(QUIT_ERROR);
                    109:                }
                    110:        }
                    111: #endif
1.1       etheisen  112:        if (n < 0)
1.8       shadchin  113:        {
                    114: #if HAVE_ERRNO
                    115:                /*
                    116:                 * Certain values of errno indicate we should just retry the read.
                    117:                 */
                    118: #if MUST_DEFINE_ERRNO
                    119:                extern int errno;
                    120: #endif
                    121: #ifdef EINTR
                    122:                if (errno == EINTR)
1.9       millert   123:                        return (READ_INTR);
1.8       shadchin  124: #endif
                    125: #ifdef EAGAIN
                    126:                if (errno == EAGAIN)
                    127:                        goto start;
                    128: #endif
                    129: #endif
                    130:                return (-1);
                    131:        }
1.1       etheisen  132:        return (n);
                    133: }
                    134:
                    135: /*
                    136:  * Return the current time.
                    137:  */
                    138: #if HAVE_TIME
                    139:        public long
                    140: get_time()
                    141: {
                    142:        time_type t;
                    143:
                    144:        time(&t);
                    145:        return (t);
                    146: }
                    147: #endif
                    148:
                    149:
                    150: #if !HAVE_STRERROR
                    151: /*
                    152:  * Local version of strerror, if not available from the system.
                    153:  */
                    154:        static char *
                    155: strerror(err)
                    156:        int err;
                    157: {
                    158: #if HAVE_SYS_ERRLIST
                    159:        static char buf[16];
                    160:        extern char *sys_errlist[];
                    161:        extern int sys_nerr;
                    162:
                    163:        if (err < sys_nerr)
                    164:                return sys_errlist[err];
1.6       millert   165:        snprintf(buf, sizeof(buf), "Error %d", err);
1.1       etheisen  166:        return buf;
                    167: #else
                    168:        return ("cannot open");
                    169: #endif
                    170: }
                    171: #endif
                    172:
                    173: /*
                    174:  * errno_message: Return an error message based on the value of "errno".
                    175:  */
                    176:        public char *
                    177: errno_message(filename)
                    178:        char *filename;
                    179: {
1.6       millert   180:        register char *p;
                    181:        register char *m;
                    182:        size_t len;
1.1       etheisen  183: #if HAVE_ERRNO
1.6       millert   184: #if MUST_DEFINE_ERRNO
1.1       etheisen  185:        extern int errno;
1.6       millert   186: #endif
1.1       etheisen  187:        p = strerror(errno);
                    188: #else
                    189:        p = "cannot open";
                    190: #endif
1.5       deraadt   191:        len = strlen(filename) + strlen(p) + 3;
                    192:        m = (char *) ecalloc(len, sizeof(char));
1.8       shadchin  193:        SNPRINTF2(m, len, "%s: %s", filename, p);
1.1       etheisen  194:        return (m);
                    195: }
                    196:
1.8       shadchin  197: /* #define HAVE_FLOAT 0 */
                    198:
                    199:        static POSITION
                    200: muldiv(val, num, den)
                    201:        POSITION val, num, den;
                    202: {
                    203: #if HAVE_FLOAT
                    204:        double v = (((double) val) * num) / den;
                    205:        return ((POSITION) (v + 0.5));
                    206: #else
                    207:        POSITION v = ((POSITION) val) * num;
                    208:
                    209:        if (v / num == val)
                    210:                /* No overflow */
                    211:                return (POSITION) (v / den);
                    212:        else
                    213:                /* Above calculation overflows;
                    214:                 * use a method that is less precise but won't overflow. */
                    215:                return (POSITION) (val / (den / num));
                    216: #endif
                    217: }
                    218:
1.1       etheisen  219: /*
1.6       millert   220:  * Return the ratio of two POSITIONS, as a percentage.
                    221:  * {{ Assumes a POSITION is a long int. }}
                    222:  */
                    223:        public int
                    224: percentage(num, den)
                    225:        POSITION num, den;
                    226: {
1.8       shadchin  227:        return (int) muldiv(num,  (POSITION) 100, den);
1.6       millert   228: }
                    229:
                    230: /*
                    231:  * Return the specified percentage of a POSITION.
1.1       etheisen  232:  */
1.6       millert   233:        public POSITION
1.8       shadchin  234: percent_pos(pos, percent, fraction)
1.6       millert   235:        POSITION pos;
                    236:        int percent;
1.8       shadchin  237:        long fraction;
1.1       etheisen  238: {
1.8       shadchin  239:        /* Change percent (parts per 100) to perden (parts per NUM_FRAC_DENOM). */
                    240:        POSITION perden = (percent * (NUM_FRAC_DENOM / 100)) + (fraction / 100);
1.6       millert   241:
1.8       shadchin  242:        if (perden == 0)
1.6       millert   243:                return (0);
1.8       shadchin  244:        return (POSITION) muldiv(pos, perden, (POSITION) NUM_FRAC_DENOM);
1.1       etheisen  245: }
1.6       millert   246:
                    247: #if !HAVE_STRCHR
                    248: /*
                    249:  * strchr is used by regexp.c.
                    250:  */
                    251:        char *
                    252: strchr(s, c)
                    253:        char *s;
                    254:        int c;
1.1       etheisen  255: {
1.6       millert   256:        for ( ;  *s != '\0';  s++)
                    257:                if (*s == c)
                    258:                        return (s);
                    259:        if (c == '\0')
                    260:                return (s);
                    261:        return (NULL);
                    262: }
                    263: #endif
1.1       etheisen  264:
1.6       millert   265: #if !HAVE_MEMCPY
                    266:        VOID_POINTER
                    267: memcpy(dst, src, len)
                    268:        VOID_POINTER dst;
                    269:        VOID_POINTER src;
                    270:        int len;
                    271: {
                    272:        char *dstp = (char *) dst;
                    273:        char *srcp = (char *) src;
                    274:        int i;
                    275:
                    276:        for (i = 0;  i < len;  i++)
                    277:                dstp[i] = srcp[i];
                    278:        return (dst);
1.1       etheisen  279: }
                    280: #endif
                    281:
1.6       millert   282: #ifdef _OSK_MWC32
                    283:
1.1       etheisen  284: /*
1.6       millert   285:  * This implements an ANSI-style intercept setup for Microware C 3.2
1.1       etheisen  286:  */
1.6       millert   287:        public int
                    288: os9_signal(type, handler)
                    289:        int type;
                    290:        RETSIGTYPE (*handler)();
                    291: {
                    292:        intercept(handler);
                    293: }
                    294:
                    295: #include <sgstat.h>
                    296:
                    297:        int
                    298: isatty(f)
                    299:        int f;
1.1       etheisen  300: {
1.6       millert   301:        struct sgbuf sgbuf;
                    302:
                    303:        if (_gs_opt(f, &sgbuf) < 0)
                    304:                return -1;
                    305:        return (sgbuf.sg_class == 0);
                    306: }
1.1       etheisen  307:
1.6       millert   308: #endif