inpcb: Use netisr_ncpus for listing inpcbs.
[dragonfly.git] / contrib / less / os.c
blob530abe19d4cc50d47caa06886c296b8817f2d266
1 /*
2 * Copyright (C) 1984-2015 Mark Nudelman
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.
7 * For more information, see the README file.
8 */
12 * Operating system dependent routines.
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.
19 * The makefile provides defines to decide whether various
20 * Unix features are present.
23 #include "less.h"
24 #include <signal.h>
25 #include <setjmp.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
37 * BSD setjmp() saves (and longjmp() restores) the signal mask.
38 * This costs a system call or two per setjmp(), so if possible we clear the
39 * signal mask with sigsetmask(), and use _setjmp()/_longjmp() instead.
40 * On other systems, setjmp() doesn't affect the signal mask and so
41 * _setjmp() does not exist; we just use setjmp().
43 #if HAVE__SETJMP && HAVE_SIGSETMASK
44 #define SET_JUMP _setjmp
45 #define LONG_JUMP _longjmp
46 #else
47 #define SET_JUMP setjmp
48 #define LONG_JUMP longjmp
49 #endif
51 public int reading;
53 static jmp_buf read_label;
55 extern int sigs;
58 * Like read() system call, but is deliberately interruptible.
59 * A call to intread() from a signal handler will interrupt
60 * any pending iread().
62 public int
63 iread(fd, buf, len)
64 int fd;
65 char *buf;
66 unsigned int len;
68 register int n;
70 start:
71 #if MSDOS_COMPILER==WIN32C
72 if (ABORT_SIGS())
73 return (READ_INTR);
74 #else
75 #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
76 if (kbhit())
78 int c;
80 c = getch();
81 if (c == '\003')
82 return (READ_INTR);
83 ungetch(c);
85 #endif
86 #endif
87 if (SET_JUMP(read_label))
90 * We jumped here from intread.
92 reading = 0;
93 #if HAVE_SIGPROCMASK
95 sigset_t mask;
96 sigemptyset(&mask);
97 sigprocmask(SIG_SETMASK, &mask, NULL);
99 #else
100 #if HAVE_SIGSETMASK
101 sigsetmask(0);
102 #else
103 #ifdef _OSK
104 sigmask(~0);
105 #endif
106 #endif
107 #endif
108 return (READ_INTR);
111 flush();
112 reading = 1;
113 #if MSDOS_COMPILER==DJGPPC
114 if (isatty(fd))
117 * Don't try reading from a TTY until a character is
118 * available, because that makes some background programs
119 * believe DOS is busy in a way that prevents those
120 * programs from working while "less" waits.
122 fd_set readfds;
124 FD_ZERO(&readfds);
125 FD_SET(fd, &readfds);
126 if (select(fd+1, &readfds, 0, 0, 0) == -1)
127 return (-1);
129 #endif
130 n = read(fd, buf, len);
131 #if 1
133 * This is a kludge to workaround a problem on some systems
134 * where terminating a remote tty connection causes read() to
135 * start returning 0 forever, instead of -1.
138 extern int ignore_eoi;
139 if (!ignore_eoi)
141 static int consecutive_nulls = 0;
142 if (n == 0)
143 consecutive_nulls++;
144 else
145 consecutive_nulls = 0;
146 if (consecutive_nulls > 20)
147 quit(QUIT_ERROR);
150 #endif
151 reading = 0;
152 if (n < 0)
154 #if HAVE_ERRNO
156 * Certain values of errno indicate we should just retry the read.
158 #if MUST_DEFINE_ERRNO
159 extern int errno;
160 #endif
161 #ifdef EINTR
162 if (errno == EINTR)
163 goto start;
164 #endif
165 #ifdef EAGAIN
166 if (errno == EAGAIN)
167 goto start;
168 #endif
169 #endif
170 return (-1);
172 return (n);
176 * Interrupt a pending iread().
178 public void
179 intread()
181 LONG_JUMP(read_label, 1);
185 * Return the current time.
187 #if HAVE_TIME
188 public time_type
189 get_time()
191 time_type t;
193 time(&t);
194 return (t);
196 #endif
199 #if !HAVE_STRERROR
201 * Local version of strerror, if not available from the system.
203 static char *
204 strerror(err)
205 int err;
207 #if HAVE_SYS_ERRLIST
208 static char buf[16];
209 extern char *sys_errlist[];
210 extern int sys_nerr;
212 if (err < sys_nerr)
213 return sys_errlist[err];
214 sprintf(buf, "Error %d", err);
215 return buf;
216 #else
217 return ("cannot open");
218 #endif
220 #endif
223 * errno_message: Return an error message based on the value of "errno".
225 public char *
226 errno_message(filename)
227 char *filename;
229 register char *p;
230 register char *m;
231 int len;
232 #if HAVE_ERRNO
233 #if MUST_DEFINE_ERRNO
234 extern int errno;
235 #endif
236 p = strerror(errno);
237 #else
238 p = "cannot open";
239 #endif
240 len = (int) (strlen(filename) + strlen(p) + 3);
241 m = (char *) ecalloc(len, sizeof(char));
242 SNPRINTF2(m, len, "%s: %s", filename, p);
243 return (m);
246 /* #define HAVE_FLOAT 0 */
248 static POSITION
249 muldiv(val, num, den)
250 POSITION val, num, den;
252 #if HAVE_FLOAT
253 double v = (((double) val) * num) / den;
254 return ((POSITION) (v + 0.5));
255 #else
256 POSITION v = ((POSITION) val) * num;
258 if (v / num == val)
259 /* No overflow */
260 return (POSITION) (v / den);
261 else
262 /* Above calculation overflows;
263 * use a method that is less precise but won't overflow. */
264 return (POSITION) (val / (den / num));
265 #endif
269 * Return the ratio of two POSITIONS, as a percentage.
270 * {{ Assumes a POSITION is a long int. }}
272 public int
273 percentage(num, den)
274 POSITION num, den;
276 return (int) muldiv(num, (POSITION) 100, den);
280 * Return the specified percentage of a POSITION.
282 public POSITION
283 percent_pos(pos, percent, fraction)
284 POSITION pos;
285 int percent;
286 long fraction;
288 /* Change percent (parts per 100) to perden (parts per NUM_FRAC_DENOM). */
289 POSITION perden = (percent * (NUM_FRAC_DENOM / 100)) + (fraction / 100);
291 if (perden == 0)
292 return (0);
293 return (POSITION) muldiv(pos, perden, (POSITION) NUM_FRAC_DENOM);
296 #if !HAVE_STRCHR
298 * strchr is used by regexp.c.
300 char *
301 strchr(s, c)
302 char *s;
303 int c;
305 for ( ; *s != '\0'; s++)
306 if (*s == c)
307 return (s);
308 if (c == '\0')
309 return (s);
310 return (NULL);
312 #endif
314 #if !HAVE_MEMCPY
315 VOID_POINTER
316 memcpy(dst, src, len)
317 VOID_POINTER dst;
318 VOID_POINTER src;
319 int len;
321 char *dstp = (char *) dst;
322 char *srcp = (char *) src;
323 int i;
325 for (i = 0; i < len; i++)
326 dstp[i] = srcp[i];
327 return (dst);
329 #endif
331 #ifdef _OSK_MWC32
334 * This implements an ANSI-style intercept setup for Microware C 3.2
336 public int
337 os9_signal(type, handler)
338 int type;
339 RETSIGTYPE (*handler)();
341 intercept(handler);
344 #include <sgstat.h>
346 int
347 isatty(f)
348 int f;
350 struct sgbuf sgbuf;
352 if (_gs_opt(f, &sgbuf) < 0)
353 return -1;
354 return (sgbuf.sg_class == 0);
357 #endif