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

1.1       etheisen    1: /*
1.1.1.3 ! shadchin    2:  * Copyright (C) 1984-2011  Mark Nudelman
1.1       etheisen    3:  *
1.1.1.2   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.1.1.2   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: #include <setjmp.h>
                     27: #if HAVE_TIME_H
                     28: #include <time.h>
                     29: #endif
                     30: #if HAVE_ERRNO_H
                     31: #include <errno.h>
                     32: #endif
                     33: #if HAVE_VALUES_H
                     34: #include <values.h>
                     35: #endif
                     36:
                     37: #if HAVE_TIME_T
                     38: #define time_type      time_t
                     39: #else
                     40: #define        time_type       long
                     41: #endif
                     42:
                     43: /*
                     44:  * BSD setjmp() saves (and longjmp() restores) the signal mask.
                     45:  * This costs a system call or two per setjmp(), so if possible we clear the
                     46:  * signal mask with sigsetmask(), and use _setjmp()/_longjmp() instead.
                     47:  * On other systems, setjmp() doesn't affect the signal mask and so
                     48:  * _setjmp() does not exist; we just use setjmp().
                     49:  */
                     50: #if HAVE__SETJMP && HAVE_SIGSETMASK
                     51: #define SET_JUMP       _setjmp
                     52: #define LONG_JUMP      _longjmp
                     53: #else
                     54: #define SET_JUMP       setjmp
                     55: #define LONG_JUMP      longjmp
                     56: #endif
                     57:
                     58: public int reading;
                     59:
                     60: static jmp_buf read_label;
                     61:
1.1.1.2   millert    62: extern int sigs;
                     63:
1.1       etheisen   64: /*
                     65:  * Like read() system call, but is deliberately interruptible.
                     66:  * A call to intread() from a signal handler will interrupt
                     67:  * any pending iread().
                     68:  */
                     69:        public int
                     70: iread(fd, buf, len)
                     71:        int fd;
                     72:        char *buf;
                     73:        unsigned int len;
                     74: {
                     75:        register int n;
                     76:
1.1.1.3 ! shadchin   77: start:
1.1.1.2   millert    78: #if MSDOS_COMPILER==WIN32C
                     79:        if (ABORT_SIGS())
                     80:                return (READ_INTR);
                     81: #else
                     82: #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
1.1       etheisen   83:        if (kbhit())
                     84:        {
                     85:                int c;
                     86:
                     87:                c = getch();
                     88:                if (c == '\003')
                     89:                        return (READ_INTR);
                     90:                ungetch(c);
                     91:        }
                     92: #endif
1.1.1.2   millert    93: #endif
1.1       etheisen   94:        if (SET_JUMP(read_label))
                     95:        {
                     96:                /*
                     97:                 * We jumped here from intread.
                     98:                 */
                     99:                reading = 0;
1.1.1.2   millert   100: #if HAVE_SIGPROCMASK
                    101:                {
                    102:                  sigset_t mask;
                    103:                  sigemptyset(&mask);
                    104:                  sigprocmask(SIG_SETMASK, &mask, NULL);
                    105:                }
                    106: #else
1.1       etheisen  107: #if HAVE_SIGSETMASK
                    108:                sigsetmask(0);
1.1.1.2   millert   109: #else
                    110: #ifdef _OSK
                    111:                sigmask(~0);
                    112: #endif
                    113: #endif
1.1       etheisen  114: #endif
                    115:                return (READ_INTR);
                    116:        }
                    117:
                    118:        flush();
                    119:        reading = 1;
1.1.1.2   millert   120: #if MSDOS_COMPILER==DJGPPC
                    121:        if (isatty(fd))
                    122:        {
                    123:                /*
                    124:                 * Don't try reading from a TTY until a character is
                    125:                 * available, because that makes some background programs
                    126:                 * believe DOS is busy in a way that prevents those
                    127:                 * programs from working while "less" waits.
                    128:                 */
                    129:                fd_set readfds;
                    130:
                    131:                FD_ZERO(&readfds);
                    132:                FD_SET(fd, &readfds);
                    133:                if (select(fd+1, &readfds, 0, 0, 0) == -1)
                    134:                        return (-1);
                    135:        }
                    136: #endif
1.1       etheisen  137:        n = read(fd, buf, len);
1.1.1.2   millert   138: #if 1
                    139:        /*
                    140:         * This is a kludge to workaround a problem on some systems
                    141:         * where terminating a remote tty connection causes read() to
                    142:         * start returning 0 forever, instead of -1.
                    143:         */
                    144:        {
                    145:                extern int ignore_eoi;
                    146:                if (!ignore_eoi)
                    147:                {
                    148:                        static int consecutive_nulls = 0;
                    149:                        if (n == 0)
                    150:                                consecutive_nulls++;
                    151:                        else
                    152:                                consecutive_nulls = 0;
                    153:                        if (consecutive_nulls > 20)
                    154:                                quit(QUIT_ERROR);
                    155:                }
                    156:        }
                    157: #endif
1.1       etheisen  158:        reading = 0;
                    159:        if (n < 0)
1.1.1.3 ! shadchin  160:        {
        !           161: #if HAVE_ERRNO
        !           162:                /*
        !           163:                 * Certain values of errno indicate we should just retry the read.
        !           164:                 */
        !           165: #if MUST_DEFINE_ERRNO
        !           166:                extern int errno;
        !           167: #endif
        !           168: #ifdef EINTR
        !           169:                if (errno == EINTR)
        !           170:                        goto start;
        !           171: #endif
        !           172: #ifdef EAGAIN
        !           173:                if (errno == EAGAIN)
        !           174:                        goto start;
        !           175: #endif
        !           176: #endif
1.1       etheisen  177:                return (-1);
1.1.1.3 ! shadchin  178:        }
1.1       etheisen  179:        return (n);
                    180: }
                    181:
                    182: /*
                    183:  * Interrupt a pending iread().
                    184:  */
                    185:        public void
                    186: intread()
                    187: {
                    188:        LONG_JUMP(read_label, 1);
                    189: }
                    190:
                    191: /*
                    192:  * Return the current time.
                    193:  */
                    194: #if HAVE_TIME
                    195:        public long
                    196: get_time()
                    197: {
                    198:        time_type t;
                    199:
                    200:        time(&t);
                    201:        return (t);
                    202: }
                    203: #endif
                    204:
                    205:
                    206: #if !HAVE_STRERROR
                    207: /*
                    208:  * Local version of strerror, if not available from the system.
                    209:  */
                    210:        static char *
                    211: strerror(err)
                    212:        int err;
                    213: {
                    214: #if HAVE_SYS_ERRLIST
                    215:        static char buf[16];
                    216:        extern char *sys_errlist[];
                    217:        extern int sys_nerr;
                    218:
                    219:        if (err < sys_nerr)
                    220:                return sys_errlist[err];
                    221:        sprintf(buf, "Error %d", err);
                    222:        return buf;
                    223: #else
                    224:        return ("cannot open");
                    225: #endif
                    226: }
                    227: #endif
                    228:
                    229: /*
                    230:  * errno_message: Return an error message based on the value of "errno".
                    231:  */
                    232:        public char *
                    233: errno_message(filename)
                    234:        char *filename;
                    235: {
                    236:        register char *p;
                    237:        register char *m;
1.1.1.3 ! shadchin  238:        int len;
1.1       etheisen  239: #if HAVE_ERRNO
1.1.1.2   millert   240: #if MUST_DEFINE_ERRNO
1.1       etheisen  241:        extern int errno;
1.1.1.2   millert   242: #endif
1.1       etheisen  243:        p = strerror(errno);
                    244: #else
                    245:        p = "cannot open";
                    246: #endif
1.1.1.3 ! shadchin  247:        len = strlen(filename) + strlen(p) + 3;
        !           248:        m = (char *) ecalloc(len, sizeof(char));
        !           249:        SNPRINTF2(m, len, "%s: %s", filename, p);
1.1       etheisen  250:        return (m);
                    251: }
                    252:
1.1.1.3 ! shadchin  253: /* #define HAVE_FLOAT 0 */
        !           254:
        !           255:        static POSITION
        !           256: muldiv(val, num, den)
        !           257:        POSITION val, num, den;
        !           258: {
        !           259: #if HAVE_FLOAT
        !           260:        double v = (((double) val) * num) / den;
        !           261:        return ((POSITION) (v + 0.5));
        !           262: #else
        !           263:        POSITION v = ((POSITION) val) * num;
        !           264:
        !           265:        if (v / num == val)
        !           266:                /* No overflow */
        !           267:                return (POSITION) (v / den);
        !           268:        else
        !           269:                /* Above calculation overflows;
        !           270:                 * use a method that is less precise but won't overflow. */
        !           271:                return (POSITION) (val / (den / num));
        !           272: #endif
        !           273: }
        !           274:
1.1       etheisen  275: /*
1.1.1.2   millert   276:  * Return the ratio of two POSITIONS, as a percentage.
                    277:  * {{ Assumes a POSITION is a long int. }}
1.1       etheisen  278:  */
1.1.1.2   millert   279:        public int
                    280: percentage(num, den)
                    281:        POSITION num, den;
1.1       etheisen  282: {
1.1.1.3 ! shadchin  283:        return (int) muldiv(num,  (POSITION) 100, den);
1.1       etheisen  284: }
1.1.1.2   millert   285:
                    286: /*
                    287:  * Return the specified percentage of a POSITION.
                    288:  */
                    289:        public POSITION
1.1.1.3 ! shadchin  290: percent_pos(pos, percent, fraction)
1.1.1.2   millert   291:        POSITION pos;
                    292:        int percent;
1.1.1.3 ! shadchin  293:        long fraction;
1.1       etheisen  294: {
1.1.1.3 ! shadchin  295:        /* Change percent (parts per 100) to perden (parts per NUM_FRAC_DENOM). */
        !           296:        POSITION perden = (percent * (NUM_FRAC_DENOM / 100)) + (fraction / 100);
1.1       etheisen  297:
1.1.1.3 ! shadchin  298:        if (perden == 0)
1.1.1.2   millert   299:                return (0);
1.1.1.3 ! shadchin  300:        return (POSITION) muldiv(pos, perden, (POSITION) NUM_FRAC_DENOM);
1.1.1.2   millert   301: }
                    302:
                    303: #if !HAVE_STRCHR
                    304: /*
                    305:  * strchr is used by regexp.c.
                    306:  */
                    307:        char *
                    308: strchr(s, c)
                    309:        char *s;
                    310:        int c;
                    311: {
                    312:        for ( ;  *s != '\0';  s++)
                    313:                if (*s == c)
                    314:                        return (s);
                    315:        if (c == '\0')
                    316:                return (s);
                    317:        return (NULL);
                    318: }
                    319: #endif
                    320:
                    321: #if !HAVE_MEMCPY
                    322:        VOID_POINTER
                    323: memcpy(dst, src, len)
                    324:        VOID_POINTER dst;
                    325:        VOID_POINTER src;
                    326:        int len;
                    327: {
                    328:        char *dstp = (char *) dst;
                    329:        char *srcp = (char *) src;
                    330:        int i;
                    331:
                    332:        for (i = 0;  i < len;  i++)
                    333:                dstp[i] = srcp[i];
                    334:        return (dst);
1.1       etheisen  335: }
                    336: #endif
                    337:
1.1.1.2   millert   338: #ifdef _OSK_MWC32
                    339:
1.1       etheisen  340: /*
1.1.1.2   millert   341:  * This implements an ANSI-style intercept setup for Microware C 3.2
1.1       etheisen  342:  */
1.1.1.2   millert   343:        public int
                    344: os9_signal(type, handler)
                    345:        int type;
                    346:        RETSIGTYPE (*handler)();
1.1       etheisen  347: {
1.1.1.2   millert   348:        intercept(handler);
1.1       etheisen  349: }
1.1.1.2   millert   350:
                    351: #include <sgstat.h>
                    352:
                    353:        int
                    354: isatty(f)
                    355:        int f;
                    356: {
                    357:        struct sgbuf sgbuf;
                    358:
                    359:        if (_gs_opt(f, &sgbuf) < 0)
                    360:                return -1;
                    361:        return (sgbuf.sg_class == 0);
                    362: }
                    363:
                    364: #endif