Annotation of src/usr.bin/less/os.c, Revision 1.1.1.1
1.1 etheisen 1: /*
2: * Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice in the documentation and/or other materials provided with
12: * the distribution.
13: *
14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
15: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
18: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
20: * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
23: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: */
26:
27:
28: /*
29: * Operating system dependent routines.
30: *
31: * Most of the stuff in here is based on Unix, but an attempt
32: * has been made to make things work on other operating systems.
33: * This will sometimes result in a loss of functionality, unless
34: * someone rewrites code specifically for the new operating system.
35: *
36: * The makefile provides defines to decide whether various
37: * Unix features are present.
38: */
39:
40: #include "less.h"
41: #include <signal.h>
42: #include <setjmp.h>
43: #if HAVE_TIME_H
44: #include <time.h>
45: #endif
46: #if HAVE_ERRNO_H
47: #include <errno.h>
48: #endif
49: #if HAVE_VALUES_H
50: #include <values.h>
51: #endif
52:
53: #if HAVE_TIME_T
54: #define time_type time_t
55: #else
56: #define time_type long
57: #endif
58:
59: /*
60: * BSD setjmp() saves (and longjmp() restores) the signal mask.
61: * This costs a system call or two per setjmp(), so if possible we clear the
62: * signal mask with sigsetmask(), and use _setjmp()/_longjmp() instead.
63: * On other systems, setjmp() doesn't affect the signal mask and so
64: * _setjmp() does not exist; we just use setjmp().
65: */
66: #if HAVE__SETJMP && HAVE_SIGSETMASK
67: #define SET_JUMP _setjmp
68: #define LONG_JUMP _longjmp
69: #else
70: #define SET_JUMP setjmp
71: #define LONG_JUMP longjmp
72: #endif
73:
74: public int reading;
75:
76: static jmp_buf read_label;
77:
78: /*
79: * Like read() system call, but is deliberately interruptible.
80: * A call to intread() from a signal handler will interrupt
81: * any pending iread().
82: */
83: public int
84: iread(fd, buf, len)
85: int fd;
86: char *buf;
87: unsigned int len;
88: {
89: register int n;
90:
91: #if MSOFTC
92: if (kbhit())
93: {
94: int c;
95:
96: c = getch();
97: if (c == '\003')
98: return (READ_INTR);
99: ungetch(c);
100: }
101: #endif
102: if (SET_JUMP(read_label))
103: {
104: /*
105: * We jumped here from intread.
106: */
107: reading = 0;
108: #if HAVE_SIGSETMASK
109: sigsetmask(0);
110: #endif
111: return (READ_INTR);
112: }
113:
114: flush();
115: reading = 1;
116: n = read(fd, buf, len);
117: reading = 0;
118: if (n < 0)
119: return (-1);
120: return (n);
121: }
122:
123: /*
124: * Interrupt a pending iread().
125: */
126: public void
127: intread()
128: {
129: LONG_JUMP(read_label, 1);
130: }
131:
132: /*
133: * Return the current time.
134: */
135: #if HAVE_TIME
136: public long
137: get_time()
138: {
139: time_type t;
140:
141: time(&t);
142: return (t);
143: }
144: #endif
145:
146:
147: #if !HAVE_STRERROR
148: /*
149: * Local version of strerror, if not available from the system.
150: */
151: static char *
152: strerror(err)
153: int err;
154: {
155: #if HAVE_SYS_ERRLIST
156: static char buf[16];
157: extern char *sys_errlist[];
158: extern int sys_nerr;
159:
160: if (err < sys_nerr)
161: return sys_errlist[err];
162: sprintf(buf, "Error %d", err);
163: return buf;
164: #else
165: return ("cannot open");
166: #endif
167: }
168: #endif
169:
170: /*
171: * errno_message: Return an error message based on the value of "errno".
172: */
173: public char *
174: errno_message(filename)
175: char *filename;
176: {
177: register char *p;
178: register char *m;
179: #if HAVE_ERRNO
180: extern int errno;
181: p = strerror(errno);
182: #else
183: p = "cannot open";
184: #endif
185: m = (char *) ecalloc(strlen(filename) + strlen(p) + 3, sizeof(char));
186: sprintf(m, "%s: %s", filename, p);
187: return (m);
188: }
189:
190: /*
191: * Return the largest possible number that can fit in a long.
192: */
193: #ifdef MAXLONG
194: static long
195: get_maxlong()
196: {
197: return (MAXLONG);
198: }
199: #else
200: static long
201: get_maxlong()
202: {
203: long n, n2;
204:
205: /*
206: * Keep doubling n until we overflow.
207: * {{ This actually only returns the largest power of two that
208: * can fit in a long, but percentage() doesn't really need
209: * it any more accurate than that. }}
210: */
211: n2 = 128; /* Hopefully no maxlong is less than 128! */
212: do {
213: n = n2;
214: n2 *= 2;
215: } while (n2 / 2 == n);
216: return (n);
217: }
218: #endif
219:
220: /*
221: * Return the ratio of two longs, as a percentage.
222: */
223: public int
224: percentage(num, den)
225: long num, den;
226: {
227: static long maxlong100 = 0;
228:
229: if (maxlong100 == 0)
230: maxlong100 = get_maxlong() / 100;
231: if (num > maxlong100)
232: return (num / (den/100));
233: else
234: return (100*num / den);
235: }