home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 6 File / 06-File.zip / less373.zip / os.c < prev    next >
C/C++ Source or Header  |  2002-01-14  |  6KB  |  328 lines

  1. /*
  2.  * Copyright (C) 1984-2000  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. #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.  
  62. extern int sigs;
  63.  
  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.  
  77. #if MSDOS_COMPILER==WIN32C
  78.     if (ABORT_SIGS())
  79.         return (READ_INTR);
  80. #else
  81. #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
  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
  92. #endif
  93.     if (SET_JUMP(read_label))
  94.     {
  95.         /*
  96.          * We jumped here from intread.
  97.          */
  98.         reading = 0;
  99. #if HAVE_SIGPROCMASK
  100.         {
  101.           sigset_t mask;
  102.           sigemptyset(&mask);
  103.           sigprocmask(SIG_SETMASK, &mask, NULL);
  104.         }
  105. #else
  106. #if HAVE_SIGSETMASK
  107.         sigsetmask(0);
  108. #else
  109. #ifdef _OSK
  110.         sigmask(~0);
  111. #endif
  112. #endif
  113. #endif
  114.         return (READ_INTR);
  115.     }
  116.  
  117.     flush();
  118.     reading = 1;
  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
  136.     n = read(fd, buf, len);
  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
  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
  220. #if MUST_DEFINE_ERRNO
  221.     extern int errno;
  222. #endif
  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. /*
  233.  * Return the ratio of two POSITIONS, as a percentage.
  234.  * {{ Assumes a POSITION is a long int. }}
  235.  */
  236.     public int
  237. percentage(num, den)
  238.     POSITION num, den;
  239. {
  240.     POSITION num100 = num * 100;
  241.  
  242.     if (num100 / 100 == num)
  243.         return (num100 / den);
  244.     else
  245.         return (num / (den / 100));
  246. }
  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;
  255. {
  256.     POSITION result100;
  257.  
  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);
  298. }
  299. #endif
  300.  
  301. #ifdef _OSK_MWC32
  302.  
  303. /*
  304.  * This implements an ANSI-style intercept setup for Microware C 3.2
  305.  */
  306.     public int 
  307. os9_signal(type, handler)
  308.     int type;
  309.     RETSIGTYPE (*handler)();
  310. {
  311.     intercept(handler);
  312. }
  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
  328.