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