1 /* 2 * Copyright (C) 1984-2002 Mark Nudelman 3 * 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. 6 * 7 * For more information about less, or for information on how to 8 * contact the author, see the README file. 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 #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 35 36 #if HAVE_TIME_T 37 #define time_type time_t 38 #else 39 #define time_type long 40 #endif 41 42 extern int sigs; 43 44 /* 45 * Like read() system call, but is deliberately interruptible. 46 */ 47 public int 48 iread(fd, buf, len) 49 int fd; 50 char *buf; 51 unsigned int len; 52 { 53 register int n; 54 55 #if MSDOS_COMPILER==WIN32C 56 if (ABORT_SIGS()) 57 return (READ_INTR); 58 #else 59 #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC 60 if (kbhit()) 61 { 62 int c; 63 64 c = getch(); 65 if (c == '\003') 66 return (READ_INTR); 67 ungetch(c); 68 } 69 #endif 70 #endif 71 72 flush(); 73 #if MSDOS_COMPILER==DJGPPC 74 if (isatty(fd)) 75 { 76 /* 77 * Don't try reading from a TTY until a character is 78 * available, because that makes some background programs 79 * believe DOS is busy in a way that prevents those 80 * programs from working while "less" waits. 81 */ 82 fd_set readfds; 83 84 FD_ZERO(&readfds); 85 FD_SET(fd, &readfds); 86 if (select(fd+1, &readfds, 0, 0, 0) == -1) 87 return (-1); 88 } 89 #endif 90 n = read(fd, buf, len); 91 #if 1 92 /* 93 * This is a kludge to workaround a problem on some systems 94 * where terminating a remote tty connection causes read() to 95 * start returning 0 forever, instead of -1. 96 */ 97 { 98 extern int ignore_eoi; 99 if (!ignore_eoi) 100 { 101 static int consecutive_nulls = 0; 102 if (n == 0) 103 consecutive_nulls++; 104 else 105 consecutive_nulls = 0; 106 if (consecutive_nulls > 20) 107 quit(QUIT_ERROR); 108 } 109 } 110 #endif 111 if (n < 0) 112 return (errno == EINTR ? READ_INTR : -1); 113 return (n); 114 } 115 116 /* 117 * Return the current time. 118 */ 119 #if HAVE_TIME 120 public long 121 get_time() 122 { 123 time_type t; 124 125 time(&t); 126 return (t); 127 } 128 #endif 129 130 131 #if !HAVE_STRERROR 132 /* 133 * Local version of strerror, if not available from the system. 134 */ 135 static char * 136 strerror(err) 137 int err; 138 { 139 #if HAVE_SYS_ERRLIST 140 static char buf[16]; 141 extern char *sys_errlist[]; 142 extern int sys_nerr; 143 144 if (err < sys_nerr) 145 return sys_errlist[err]; 146 snprintf(buf, sizeof(buf), "Error %d", err); 147 return buf; 148 #else 149 return ("cannot open"); 150 #endif 151 } 152 #endif 153 154 /* 155 * errno_message: Return an error message based on the value of "errno". 156 */ 157 public char * 158 errno_message(filename) 159 char *filename; 160 { 161 register char *p; 162 register char *m; 163 size_t len; 164 #if HAVE_ERRNO 165 #if MUST_DEFINE_ERRNO 166 extern int errno; 167 #endif 168 p = strerror(errno); 169 #else 170 p = "cannot open"; 171 #endif 172 len = strlen(filename) + strlen(p) + 3; 173 m = (char *) ecalloc(len, sizeof(char)); 174 snprintf(m, len, "%s: %s", filename, p); 175 return (m); 176 } 177 178 /* 179 * Return the ratio of two POSITIONS, as a percentage. 180 * {{ Assumes a POSITION is a long int. }} 181 */ 182 public int 183 percentage(num, den) 184 POSITION num, den; 185 { 186 POSITION num100 = num * 100; 187 188 if (num100 / 100 == num) 189 return (num100 / den); 190 else 191 return (num / (den / 100)); 192 } 193 194 /* 195 * Return the specified percentage of a POSITION. 196 */ 197 public POSITION 198 percent_pos(pos, percent) 199 POSITION pos; 200 int percent; 201 { 202 POSITION result100; 203 204 if (percent == 0) 205 return (0); 206 else if ((result100 = pos * percent) / percent == pos) 207 return (result100 / 100); 208 else 209 return (percent * (pos / 100)); 210 } 211 212 #if !HAVE_STRCHR 213 /* 214 * strchr is used by regexp.c. 215 */ 216 char * 217 strchr(s, c) 218 char *s; 219 int c; 220 { 221 for ( ; *s != '\0'; s++) 222 if (*s == c) 223 return (s); 224 if (c == '\0') 225 return (s); 226 return (NULL); 227 } 228 #endif 229 230 #if !HAVE_MEMCPY 231 VOID_POINTER 232 memcpy(dst, src, len) 233 VOID_POINTER dst; 234 VOID_POINTER src; 235 int len; 236 { 237 char *dstp = (char *) dst; 238 char *srcp = (char *) src; 239 int i; 240 241 for (i = 0; i < len; i++) 242 dstp[i] = srcp[i]; 243 return (dst); 244 } 245 #endif 246 247 #ifdef _OSK_MWC32 248 249 /* 250 * This implements an ANSI-style intercept setup for Microware C 3.2 251 */ 252 public int 253 os9_signal(type, handler) 254 int type; 255 RETSIGTYPE (*handler)(); 256 { 257 intercept(handler); 258 } 259 260 #include <sgstat.h> 261 262 int 263 isatty(f) 264 int f; 265 { 266 struct sgbuf sgbuf; 267 268 if (_gs_opt(f, &sgbuf) < 0) 269 return -1; 270 return (sgbuf.sg_class == 0); 271 } 272 273 #endif 274