Annotation of src/usr.bin/less/os.c, Revision 1.8
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.6 millert 42: extern int sigs;
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)
! 123: goto start;
! 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