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

1.1       etheisen    1: /*
1.1.1.2 ! millert     2:  * Copyright (C) 1984-2002  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.2 ! millert    77: #if MSDOS_COMPILER==WIN32C
        !            78:        if (ABORT_SIGS())
        !            79:                return (READ_INTR);
        !            80: #else
        !            81: #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
1.1       etheisen   82:        if (kbhit())
                     83:        {
                     84:                int c;
                     85:
                     86:                c = getch();
                     87:                if (c == '\003')
                     88:                        return (READ_INTR);
                     89:                ungetch(c);
                     90:        }
                     91: #endif
1.1.1.2 ! millert    92: #endif
1.1       etheisen   93:        if (SET_JUMP(read_label))
                     94:        {
                     95:                /*
                     96:                 * We jumped here from intread.
                     97:                 */
                     98:                reading = 0;
1.1.1.2 ! millert    99: #if HAVE_SIGPROCMASK
        !           100:                {
        !           101:                  sigset_t mask;
        !           102:                  sigemptyset(&mask);
        !           103:                  sigprocmask(SIG_SETMASK, &mask, NULL);
        !           104:                }
        !           105: #else
1.1       etheisen  106: #if HAVE_SIGSETMASK
                    107:                sigsetmask(0);
1.1.1.2 ! millert   108: #else
        !           109: #ifdef _OSK
        !           110:                sigmask(~0);
        !           111: #endif
        !           112: #endif
1.1       etheisen  113: #endif
                    114:                return (READ_INTR);
                    115:        }
                    116:
                    117:        flush();
                    118:        reading = 1;
1.1.1.2 ! millert   119: #if MSDOS_COMPILER==DJGPPC
        !           120:        if (isatty(fd))
        !           121:        {
        !           122:                /*
        !           123:                 * Don't try reading from a TTY until a character is
        !           124:                 * available, because that makes some background programs
        !           125:                 * believe DOS is busy in a way that prevents those
        !           126:                 * programs from working while "less" waits.
        !           127:                 */
        !           128:                fd_set readfds;
        !           129:
        !           130:                FD_ZERO(&readfds);
        !           131:                FD_SET(fd, &readfds);
        !           132:                if (select(fd+1, &readfds, 0, 0, 0) == -1)
        !           133:                        return (-1);
        !           134:        }
        !           135: #endif
1.1       etheisen  136:        n = read(fd, buf, len);
1.1.1.2 ! millert   137: #if 1
        !           138:        /*
        !           139:         * This is a kludge to workaround a problem on some systems
        !           140:         * where terminating a remote tty connection causes read() to
        !           141:         * start returning 0 forever, instead of -1.
        !           142:         */
        !           143:        {
        !           144:                extern int ignore_eoi;
        !           145:                if (!ignore_eoi)
        !           146:                {
        !           147:                        static int consecutive_nulls = 0;
        !           148:                        if (n == 0)
        !           149:                                consecutive_nulls++;
        !           150:                        else
        !           151:                                consecutive_nulls = 0;
        !           152:                        if (consecutive_nulls > 20)
        !           153:                                quit(QUIT_ERROR);
        !           154:                }
        !           155:        }
        !           156: #endif
1.1       etheisen  157:        reading = 0;
                    158:        if (n < 0)
                    159:                return (-1);
                    160:        return (n);
                    161: }
                    162:
                    163: /*
                    164:  * Interrupt a pending iread().
                    165:  */
                    166:        public void
                    167: intread()
                    168: {
                    169:        LONG_JUMP(read_label, 1);
                    170: }
                    171:
                    172: /*
                    173:  * Return the current time.
                    174:  */
                    175: #if HAVE_TIME
                    176:        public long
                    177: get_time()
                    178: {
                    179:        time_type t;
                    180:
                    181:        time(&t);
                    182:        return (t);
                    183: }
                    184: #endif
                    185:
                    186:
                    187: #if !HAVE_STRERROR
                    188: /*
                    189:  * Local version of strerror, if not available from the system.
                    190:  */
                    191:        static char *
                    192: strerror(err)
                    193:        int err;
                    194: {
                    195: #if HAVE_SYS_ERRLIST
                    196:        static char buf[16];
                    197:        extern char *sys_errlist[];
                    198:        extern int sys_nerr;
                    199:
                    200:        if (err < sys_nerr)
                    201:                return sys_errlist[err];
                    202:        sprintf(buf, "Error %d", err);
                    203:        return buf;
                    204: #else
                    205:        return ("cannot open");
                    206: #endif
                    207: }
                    208: #endif
                    209:
                    210: /*
                    211:  * errno_message: Return an error message based on the value of "errno".
                    212:  */
                    213:        public char *
                    214: errno_message(filename)
                    215:        char *filename;
                    216: {
                    217:        register char *p;
                    218:        register char *m;
                    219: #if HAVE_ERRNO
1.1.1.2 ! millert   220: #if MUST_DEFINE_ERRNO
1.1       etheisen  221:        extern int errno;
1.1.1.2 ! millert   222: #endif
1.1       etheisen  223:        p = strerror(errno);
                    224: #else
                    225:        p = "cannot open";
                    226: #endif
                    227:        m = (char *) ecalloc(strlen(filename) + strlen(p) + 3, sizeof(char));
                    228:        sprintf(m, "%s: %s", filename, p);
                    229:        return (m);
                    230: }
                    231:
                    232: /*
1.1.1.2 ! millert   233:  * Return the ratio of two POSITIONS, as a percentage.
        !           234:  * {{ Assumes a POSITION is a long int. }}
1.1       etheisen  235:  */
1.1.1.2 ! millert   236:        public int
        !           237: percentage(num, den)
        !           238:        POSITION num, den;
1.1       etheisen  239: {
1.1.1.2 ! millert   240:        POSITION num100 = num * 100;
        !           241:
        !           242:        if (num100 / 100 == num)
        !           243:                return (num100 / den);
        !           244:        else
        !           245:                return (num / (den / 100));
1.1       etheisen  246: }
1.1.1.2 ! millert   247:
        !           248: /*
        !           249:  * Return the specified percentage of a POSITION.
        !           250:  */
        !           251:        public POSITION
        !           252: percent_pos(pos, percent)
        !           253:        POSITION pos;
        !           254:        int percent;
1.1       etheisen  255: {
1.1.1.2 ! millert   256:        POSITION result100;
1.1       etheisen  257:
1.1.1.2 ! millert   258:        if (percent == 0)
        !           259:                return (0);
        !           260:        else if ((result100 = pos * percent) / percent == pos)
        !           261:                return (result100 / 100);
        !           262:        else
        !           263:                return (percent * (pos / 100));
        !           264: }
        !           265:
        !           266: #if !HAVE_STRCHR
        !           267: /*
        !           268:  * strchr is used by regexp.c.
        !           269:  */
        !           270:        char *
        !           271: strchr(s, c)
        !           272:        char *s;
        !           273:        int c;
        !           274: {
        !           275:        for ( ;  *s != '\0';  s++)
        !           276:                if (*s == c)
        !           277:                        return (s);
        !           278:        if (c == '\0')
        !           279:                return (s);
        !           280:        return (NULL);
        !           281: }
        !           282: #endif
        !           283:
        !           284: #if !HAVE_MEMCPY
        !           285:        VOID_POINTER
        !           286: memcpy(dst, src, len)
        !           287:        VOID_POINTER dst;
        !           288:        VOID_POINTER src;
        !           289:        int len;
        !           290: {
        !           291:        char *dstp = (char *) dst;
        !           292:        char *srcp = (char *) src;
        !           293:        int i;
        !           294:
        !           295:        for (i = 0;  i < len;  i++)
        !           296:                dstp[i] = srcp[i];
        !           297:        return (dst);
1.1       etheisen  298: }
                    299: #endif
                    300:
1.1.1.2 ! millert   301: #ifdef _OSK_MWC32
        !           302:
1.1       etheisen  303: /*
1.1.1.2 ! millert   304:  * This implements an ANSI-style intercept setup for Microware C 3.2
1.1       etheisen  305:  */
1.1.1.2 ! millert   306:        public int
        !           307: os9_signal(type, handler)
        !           308:        int type;
        !           309:        RETSIGTYPE (*handler)();
1.1       etheisen  310: {
1.1.1.2 ! millert   311:        intercept(handler);
1.1       etheisen  312: }
1.1.1.2 ! millert   313:
        !           314: #include <sgstat.h>
        !           315:
        !           316:        int
        !           317: isatty(f)
        !           318:        int f;
        !           319: {
        !           320:        struct sgbuf sgbuf;
        !           321:
        !           322:        if (_gs_opt(f, &sgbuf) < 0)
        !           323:                return -1;
        !           324:        return (sgbuf.sg_class == 0);
        !           325: }
        !           326:
        !           327: #endif