Annotation of src/usr.bin/less/os.c, Revision 1.1.1.2
1.1 etheisen 1: /*
1.1.1.2 ! millert 2: * Copyright (C) 1984-2002 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.2 ! 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: #include <setjmp.h>
27: #if HAVE_TIME_H
28: #include <time.h>
29: #endif
30: #if HAVE_ERRNO_H
31: #include <errno.h>
32: #endif
33: #if HAVE_VALUES_H
34: #include <values.h>
35: #endif
36:
37: #if HAVE_TIME_T
38: #define time_type time_t
39: #else
40: #define time_type long
41: #endif
42:
43: /*
44: * BSD setjmp() saves (and longjmp() restores) the signal mask.
45: * This costs a system call or two per setjmp(), so if possible we clear the
46: * signal mask with sigsetmask(), and use _setjmp()/_longjmp() instead.
47: * On other systems, setjmp() doesn't affect the signal mask and so
48: * _setjmp() does not exist; we just use setjmp().
49: */
50: #if HAVE__SETJMP && HAVE_SIGSETMASK
51: #define SET_JUMP _setjmp
52: #define LONG_JUMP _longjmp
53: #else
54: #define SET_JUMP setjmp
55: #define LONG_JUMP longjmp
56: #endif
57:
58: public int reading;
59:
60: static jmp_buf read_label;
61:
1.1.1.2 ! millert 62: extern int sigs;
! 63:
1.1 etheisen 64: /*
65: * Like read() system call, but is deliberately interruptible.
66: * A call to intread() from a signal handler will interrupt
67: * any pending iread().
68: */
69: public int
70: iread(fd, buf, len)
71: int fd;
72: char *buf;
73: unsigned int len;
74: {
75: register int n;
76:
1.1.1.2 ! millert 77: #if MSDOS_COMPILER==WIN32C
! 78: if (ABORT_SIGS())
! 79: return (READ_INTR);
! 80: #else
! 81: #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
1.1 etheisen 82: if (kbhit())
83: {
84: int c;
85:
86: c = getch();
87: if (c == '\003')
88: return (READ_INTR);
89: ungetch(c);
90: }
91: #endif
1.1.1.2 ! millert 92: #endif
1.1 etheisen 93: if (SET_JUMP(read_label))
94: {
95: /*
96: * We jumped here from intread.
97: */
98: reading = 0;
1.1.1.2 ! millert 99: #if HAVE_SIGPROCMASK
! 100: {
! 101: sigset_t mask;
! 102: sigemptyset(&mask);
! 103: sigprocmask(SIG_SETMASK, &mask, NULL);
! 104: }
! 105: #else
1.1 etheisen 106: #if HAVE_SIGSETMASK
107: sigsetmask(0);
1.1.1.2 ! millert 108: #else
! 109: #ifdef _OSK
! 110: sigmask(~0);
! 111: #endif
! 112: #endif
1.1 etheisen 113: #endif
114: return (READ_INTR);
115: }
116:
117: flush();
118: reading = 1;
1.1.1.2 ! millert 119: #if MSDOS_COMPILER==DJGPPC
! 120: if (isatty(fd))
! 121: {
! 122: /*
! 123: * Don't try reading from a TTY until a character is
! 124: * available, because that makes some background programs
! 125: * believe DOS is busy in a way that prevents those
! 126: * programs from working while "less" waits.
! 127: */
! 128: fd_set readfds;
! 129:
! 130: FD_ZERO(&readfds);
! 131: FD_SET(fd, &readfds);
! 132: if (select(fd+1, &readfds, 0, 0, 0) == -1)
! 133: return (-1);
! 134: }
! 135: #endif
1.1 etheisen 136: n = read(fd, buf, len);
1.1.1.2 ! millert 137: #if 1
! 138: /*
! 139: * This is a kludge to workaround a problem on some systems
! 140: * where terminating a remote tty connection causes read() to
! 141: * start returning 0 forever, instead of -1.
! 142: */
! 143: {
! 144: extern int ignore_eoi;
! 145: if (!ignore_eoi)
! 146: {
! 147: static int consecutive_nulls = 0;
! 148: if (n == 0)
! 149: consecutive_nulls++;
! 150: else
! 151: consecutive_nulls = 0;
! 152: if (consecutive_nulls > 20)
! 153: quit(QUIT_ERROR);
! 154: }
! 155: }
! 156: #endif
1.1 etheisen 157: reading = 0;
158: if (n < 0)
159: return (-1);
160: return (n);
161: }
162:
163: /*
164: * Interrupt a pending iread().
165: */
166: public void
167: intread()
168: {
169: LONG_JUMP(read_label, 1);
170: }
171:
172: /*
173: * Return the current time.
174: */
175: #if HAVE_TIME
176: public long
177: get_time()
178: {
179: time_type t;
180:
181: time(&t);
182: return (t);
183: }
184: #endif
185:
186:
187: #if !HAVE_STRERROR
188: /*
189: * Local version of strerror, if not available from the system.
190: */
191: static char *
192: strerror(err)
193: int err;
194: {
195: #if HAVE_SYS_ERRLIST
196: static char buf[16];
197: extern char *sys_errlist[];
198: extern int sys_nerr;
199:
200: if (err < sys_nerr)
201: return sys_errlist[err];
202: sprintf(buf, "Error %d", err);
203: return buf;
204: #else
205: return ("cannot open");
206: #endif
207: }
208: #endif
209:
210: /*
211: * errno_message: Return an error message based on the value of "errno".
212: */
213: public char *
214: errno_message(filename)
215: char *filename;
216: {
217: register char *p;
218: register char *m;
219: #if HAVE_ERRNO
1.1.1.2 ! millert 220: #if MUST_DEFINE_ERRNO
1.1 etheisen 221: extern int errno;
1.1.1.2 ! millert 222: #endif
1.1 etheisen 223: p = strerror(errno);
224: #else
225: p = "cannot open";
226: #endif
227: m = (char *) ecalloc(strlen(filename) + strlen(p) + 3, sizeof(char));
228: sprintf(m, "%s: %s", filename, p);
229: return (m);
230: }
231:
232: /*
1.1.1.2 ! millert 233: * Return the ratio of two POSITIONS, as a percentage.
! 234: * {{ Assumes a POSITION is a long int. }}
1.1 etheisen 235: */
1.1.1.2 ! millert 236: public int
! 237: percentage(num, den)
! 238: POSITION num, den;
1.1 etheisen 239: {
1.1.1.2 ! millert 240: POSITION num100 = num * 100;
! 241:
! 242: if (num100 / 100 == num)
! 243: return (num100 / den);
! 244: else
! 245: return (num / (den / 100));
1.1 etheisen 246: }
1.1.1.2 ! millert 247:
! 248: /*
! 249: * Return the specified percentage of a POSITION.
! 250: */
! 251: public POSITION
! 252: percent_pos(pos, percent)
! 253: POSITION pos;
! 254: int percent;
1.1 etheisen 255: {
1.1.1.2 ! millert 256: POSITION result100;
1.1 etheisen 257:
1.1.1.2 ! millert 258: if (percent == 0)
! 259: return (0);
! 260: else if ((result100 = pos * percent) / percent == pos)
! 261: return (result100 / 100);
! 262: else
! 263: return (percent * (pos / 100));
! 264: }
! 265:
! 266: #if !HAVE_STRCHR
! 267: /*
! 268: * strchr is used by regexp.c.
! 269: */
! 270: char *
! 271: strchr(s, c)
! 272: char *s;
! 273: int c;
! 274: {
! 275: for ( ; *s != '\0'; s++)
! 276: if (*s == c)
! 277: return (s);
! 278: if (c == '\0')
! 279: return (s);
! 280: return (NULL);
! 281: }
! 282: #endif
! 283:
! 284: #if !HAVE_MEMCPY
! 285: VOID_POINTER
! 286: memcpy(dst, src, len)
! 287: VOID_POINTER dst;
! 288: VOID_POINTER src;
! 289: int len;
! 290: {
! 291: char *dstp = (char *) dst;
! 292: char *srcp = (char *) src;
! 293: int i;
! 294:
! 295: for (i = 0; i < len; i++)
! 296: dstp[i] = srcp[i];
! 297: return (dst);
1.1 etheisen 298: }
299: #endif
300:
1.1.1.2 ! millert 301: #ifdef _OSK_MWC32
! 302:
1.1 etheisen 303: /*
1.1.1.2 ! millert 304: * This implements an ANSI-style intercept setup for Microware C 3.2
1.1 etheisen 305: */
1.1.1.2 ! millert 306: public int
! 307: os9_signal(type, handler)
! 308: int type;
! 309: RETSIGTYPE (*handler)();
1.1 etheisen 310: {
1.1.1.2 ! millert 311: intercept(handler);
1.1 etheisen 312: }
1.1.1.2 ! millert 313:
! 314: #include <sgstat.h>
! 315:
! 316: int
! 317: isatty(f)
! 318: int f;
! 319: {
! 320: struct sgbuf sgbuf;
! 321:
! 322: if (_gs_opt(f, &sgbuf) < 0)
! 323: return -1;
! 324: return (sgbuf.sg_class == 0);
! 325: }
! 326:
! 327: #endif