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