home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / less2912.zip / os.c < prev    next >
C/C++ Source or Header  |  1995-11-09  |  5KB  |  240 lines

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