Annotation of src/usr.bin/less/os.c, Revision 1.6
1.1 etheisen 1: /*
1.6 ! millert 2: * Copyright (C) 1984-2002 Mark Nudelman
1.1 etheisen 3: *
1.6 ! 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.6 ! 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.6 ! 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: {
1.6 ! millert 75: register int n;
1.1 etheisen 76:
1.6 ! 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.6 ! 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.6 ! 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.6 ! 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.6 ! 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.6 ! 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];
1.6 ! millert 202: snprintf(buf, sizeof(buf), "Error %d", err);
1.1 etheisen 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: {
1.6 ! millert 217: register char *p;
! 218: register char *m;
! 219: size_t len;
1.1 etheisen 220: #if HAVE_ERRNO
1.6 ! millert 221: #if MUST_DEFINE_ERRNO
1.1 etheisen 222: extern int errno;
1.6 ! millert 223: #endif
1.1 etheisen 224: p = strerror(errno);
225: #else
226: p = "cannot open";
227: #endif
1.5 deraadt 228: len = strlen(filename) + strlen(p) + 3;
229: m = (char *) ecalloc(len, sizeof(char));
230: snprintf(m, len, "%s: %s", filename, p);
1.1 etheisen 231: return (m);
232: }
233:
234: /*
1.6 ! millert 235: * Return the ratio of two POSITIONS, as a percentage.
! 236: * {{ Assumes a POSITION is a long int. }}
! 237: */
! 238: public int
! 239: percentage(num, den)
! 240: POSITION num, den;
! 241: {
! 242: POSITION num100 = num * 100;
! 243:
! 244: if (num100 / 100 == num)
! 245: return (num100 / den);
! 246: else
! 247: return (num / (den / 100));
! 248: }
! 249:
! 250: /*
! 251: * Return the specified percentage of a POSITION.
1.1 etheisen 252: */
1.6 ! millert 253: public POSITION
! 254: percent_pos(pos, percent)
! 255: POSITION pos;
! 256: int percent;
1.1 etheisen 257: {
1.6 ! millert 258: POSITION result100;
! 259:
! 260: if (percent == 0)
! 261: return (0);
! 262: else if ((result100 = pos * percent) / percent == pos)
! 263: return (result100 / 100);
! 264: else
! 265: return (percent * (pos / 100));
1.1 etheisen 266: }
1.6 ! millert 267:
! 268: #if !HAVE_STRCHR
! 269: /*
! 270: * strchr is used by regexp.c.
! 271: */
! 272: char *
! 273: strchr(s, c)
! 274: char *s;
! 275: int c;
1.1 etheisen 276: {
1.6 ! millert 277: for ( ; *s != '\0'; s++)
! 278: if (*s == c)
! 279: return (s);
! 280: if (c == '\0')
! 281: return (s);
! 282: return (NULL);
! 283: }
! 284: #endif
1.1 etheisen 285:
1.6 ! millert 286: #if !HAVE_MEMCPY
! 287: VOID_POINTER
! 288: memcpy(dst, src, len)
! 289: VOID_POINTER dst;
! 290: VOID_POINTER src;
! 291: int len;
! 292: {
! 293: char *dstp = (char *) dst;
! 294: char *srcp = (char *) src;
! 295: int i;
! 296:
! 297: for (i = 0; i < len; i++)
! 298: dstp[i] = srcp[i];
! 299: return (dst);
1.1 etheisen 300: }
301: #endif
302:
1.6 ! millert 303: #ifdef _OSK_MWC32
! 304:
1.1 etheisen 305: /*
1.6 ! millert 306: * This implements an ANSI-style intercept setup for Microware C 3.2
1.1 etheisen 307: */
1.6 ! millert 308: public int
! 309: os9_signal(type, handler)
! 310: int type;
! 311: RETSIGTYPE (*handler)();
! 312: {
! 313: intercept(handler);
! 314: }
! 315:
! 316: #include <sgstat.h>
! 317:
! 318: int
! 319: isatty(f)
! 320: int f;
1.1 etheisen 321: {
1.6 ! millert 322: struct sgbuf sgbuf;
! 323:
! 324: if (_gs_opt(f, &sgbuf) < 0)
! 325: return -1;
! 326: return (sgbuf.sg_class == 0);
! 327: }
1.1 etheisen 328:
1.6 ! millert 329: #endif