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 */
}
|