summaryrefslogtreecommitdiff
path: root/ipl/cfuncs/fpoll.c
blob: 9230e18bd2e190ce53d2dcacb8a5b2f1a3db7e32 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/*
############################################################################
#
#	File:     fpoll.c
#
#	Subject:  Function to poll file for input
#
#	Author:   Gregg M. Townsend
#
#	Date:     October 27, 2009
#
############################################################################
#
#   This file is in the public domain.
#
############################################################################
#
#  fpoll(f, msec) waits until data is available for input from file f,
#  and then returns.  It also returns when end-of-file is reached.
#  If msec is specified, and no data is available after waiting that
#  many milliseconds, then fpoll fails.  If msec is omitted, fpoll
#  waits indefinitely.
#
############################################################################
#
#  Requires:  UNIX, dynamic loading
#
############################################################################
*/

#include <stdio.h>
#include <string.h>	/* for memset call from FD_ZERO (solaris gcc) */
#include <sys/types.h>
#include <sys/time.h>

#include "icall.h"

int fpoll(int argc, descriptor *argv)	/*: await data from file */
   {
   FILE *f;
   int msec, r;
   fd_set fds;
   struct timeval tv, *tvp;

   /* check arguments */
   if (argc < 1)
      Error(105);
   if ((IconType(argv[1]) != 'f') || (FileStat(argv[1]) & Fs_Window))
      ArgError(1, 105);
   if (!(FileStat(argv[1]) & Fs_Read))
      ArgError(1, 212);
   f = FileVal(argv[1]);

   if (argc < 2)
      msec = -1;
   else {
      ArgInteger(2);
      msec = IntegerVal(argv[2]);
      }

   /* check for data already in buffer */
   /* there's no legal way to do this in C; we cheat */
#if defined(__GLIBC__) && defined(_STDIO_USES_IOSTREAM)	/* new GCC library */
   if (f->_IO_read_ptr < f->_IO_read_end)
      RetArg(1);
#elif defined(__GLIBC__)				/* old GCC library */
   if (f->__bufp < f->__get_limit)
      RetArg(1);
#elif defined(_FSTDIO)					/* new BSD library */
   if (f->_r > 0)
      RetArg(1);
#else							/* old AT&T library */
   if (f->_cnt > 0)
      RetArg(1);
#endif

   /* set up select(2) structure */
   FD_ZERO(&fds);			/* clear file bits */
   FD_SET(fileno(f), &fds);		/* set bit of interest */

   /* set up timeout and pointer */
   if (msec < 0)
      tvp = NULL;
   else {
      tv.tv_sec = msec / 1000;
      tv.tv_usec = (msec % 1000) * 1000;
      tvp = &tv;
      }

   /* poll the file using select(2) */
   r = select(fileno(f) + 1, &fds, (fd_set*)NULL, (fd_set*)NULL, tvp);

   if (r > 0)
      RetArg(1);			/* success */
   else if (r == 0)			
      Fail;				/* timeout */
   else
      ArgError(1, 214);			/* I/O error */

}