134f9b3eeSRoland Mainz /***********************************************************************
234f9b3eeSRoland Mainz *                                                                      *
334f9b3eeSRoland Mainz *               This software is part of the ast package               *
434f9b3eeSRoland Mainz *          Copyright (c) 1982-2009 AT&T Intellectual Property          *
534f9b3eeSRoland Mainz *                      and is licensed under the                       *
634f9b3eeSRoland Mainz *                  Common Public License, Version 1.0                  *
734f9b3eeSRoland Mainz *                    by AT&T Intellectual Property                     *
834f9b3eeSRoland Mainz *                                                                      *
934f9b3eeSRoland Mainz *                A copy of the License is available at                 *
1034f9b3eeSRoland Mainz *            http://www.opensource.org/licenses/cpl1.0.txt             *
1134f9b3eeSRoland Mainz *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
1234f9b3eeSRoland Mainz *                                                                      *
1334f9b3eeSRoland Mainz *              Information and Software Systems Research               *
1434f9b3eeSRoland Mainz *                            AT&T Research                             *
1534f9b3eeSRoland Mainz *                           Florham Park NJ                            *
1634f9b3eeSRoland Mainz *                                                                      *
1734f9b3eeSRoland Mainz *               Roland Mainz <roland.mainz@nrubsig.org>                *
1834f9b3eeSRoland Mainz *                                                                      *
1934f9b3eeSRoland Mainz ***********************************************************************/
2034f9b3eeSRoland Mainz #pragma prototyped
2134f9b3eeSRoland Mainz 
2234f9b3eeSRoland Mainz #include	<shell.h>
2334f9b3eeSRoland Mainz #include	<stdio.h>
2434f9b3eeSRoland Mainz #include	<stdbool.h>
2534f9b3eeSRoland Mainz #include	<option.h>
2634f9b3eeSRoland Mainz #include	<stk.h>
2734f9b3eeSRoland Mainz #include	<tm.h>
2834f9b3eeSRoland Mainz #include	"name.h"
2934f9b3eeSRoland Mainz #undef nv_isnull
3034f9b3eeSRoland Mainz #ifndef SH_DICT
3134f9b3eeSRoland Mainz #   define SH_DICT     "libshell"
3234f9b3eeSRoland Mainz #endif
3334f9b3eeSRoland Mainz #include	<poll.h>
3434f9b3eeSRoland Mainz #ifdef __GNUC__
3534f9b3eeSRoland Mainz #include <alloca.h>
3634f9b3eeSRoland Mainz #endif /* __GNUC__ */
3734f9b3eeSRoland Mainz 
3834f9b3eeSRoland Mainz #define sh_contexttoshb(context)	((Shbltin_t*)(context))
3934f9b3eeSRoland Mainz #define sh_contexttoshell(context)	((context)?(sh_contexttoshb(context)->shp):(NULL))
4034f9b3eeSRoland Mainz 
4134f9b3eeSRoland Mainz static const char sh_optpoll[] =
4234f9b3eeSRoland Mainz "[-?\n@(#)$Id: poll (AT&T Labs Research) 2009-05-14 $\n]"
4334f9b3eeSRoland Mainz "[-author?Roland Mainz <roland.mainz@nrubsig.org]"
4434f9b3eeSRoland Mainz "[-license?http://www.opensource.org/licenses/cpl1.0.txt]"
4534f9b3eeSRoland Mainz "[+NAME? poll - input/output multiplexing]"
4634f9b3eeSRoland Mainz "[+DESCRIPTION?The poll command provides applications with a mechanism "
4734f9b3eeSRoland Mainz 	"for multiplexing input/output over a set of file descriptors. "
4834f9b3eeSRoland Mainz 	"For each member of the array variable \bvar\b, "
4934f9b3eeSRoland Mainz 	"poll examines the given file descriptor in the subscript \b.fd\b "
5034f9b3eeSRoland Mainz 	"for the event(s) specified in the subscript \b.events\b."
5134f9b3eeSRoland Mainz 	"The poll command identifies those file descriptors on which an "
5234f9b3eeSRoland Mainz 	"application can read or write data, or on which certain events have "
5334f9b3eeSRoland Mainz 	"occurred.]"
5434f9b3eeSRoland Mainz "[+?The \bvar\b argument specifies the file descriptors to be examined "
5534f9b3eeSRoland Mainz 	"and the events of interest for each file descriptor. "
5634f9b3eeSRoland Mainz 	"It is a array of structured variables with one member for each open "
5734f9b3eeSRoland Mainz 	"file descriptor of interest. The array's members contain the following "
5834f9b3eeSRoland Mainz 	"subscripts:]{"
5934f9b3eeSRoland Mainz 		"[+?\b.fd\b       # file descriptor]"
6034f9b3eeSRoland Mainz 		"[+?\b.events\b   # requested events]"
6134f9b3eeSRoland Mainz 		"[+?\b.revents\b  # returned event]"
6234f9b3eeSRoland Mainz 	"}"
6334f9b3eeSRoland Mainz "[+?The \bfd\b variable specifies an open file descriptor and the "
6434f9b3eeSRoland Mainz 	"\bevents\b and \brevents\b members are strings constructed from "
6534f9b3eeSRoland Mainz 	"a concaternation of the following event flags, seperated by '|':]"
6634f9b3eeSRoland Mainz 	"{ "
6734f9b3eeSRoland Mainz 	"[+POLLIN?Data other than high priority data may be "
6834f9b3eeSRoland Mainz 		"read without blocking. For STREAMS, this "
6934f9b3eeSRoland Mainz 		"flag is set in revents even if the message "
7034f9b3eeSRoland Mainz 		"is of zero length.]"
7134f9b3eeSRoland Mainz 	"[+POLLRDNORM?Normal data (priority band equals 0) may be "
7234f9b3eeSRoland Mainz 		"read without blocking. For STREAMS, this "
7334f9b3eeSRoland Mainz 		"flag is set in revents even if the message "
7434f9b3eeSRoland Mainz 		"is of zero length.]"
7534f9b3eeSRoland Mainz 	"[+POLLRDBAND?Data from a non-zero priority band may be "
7634f9b3eeSRoland Mainz 		"read without blocking. For STREAMS, this "
7734f9b3eeSRoland Mainz 		"flag is set in revents even if the message "
7834f9b3eeSRoland Mainz 		"is of zero length.]"
7934f9b3eeSRoland Mainz 	"[+POLLPRI?High priority data may be received without "
8034f9b3eeSRoland Mainz 		"blocking. For STREAMS, this flag is set in "
8134f9b3eeSRoland Mainz 		"revents even if the message is of zero "
8234f9b3eeSRoland Mainz 		"length.]"
8334f9b3eeSRoland Mainz 	"[+POLLOUT?Normal data (priority band equals 0) may be "
8434f9b3eeSRoland Mainz 		"written without blocking.]"
8534f9b3eeSRoland Mainz 	"[+POLLWRNORM?The same as POLLOUT.]"
8634f9b3eeSRoland Mainz 	"[+POLLWRBAND?Priority data (priority band > 0) may be "
8734f9b3eeSRoland Mainz 		"written.  This event only examines bands "
8834f9b3eeSRoland Mainz 		"that have been written to at least once.]"
8934f9b3eeSRoland Mainz 	"[+POLLERR?An error has occurred on the device or "
9034f9b3eeSRoland Mainz 		"stream.  This flag is only valid in the "
9134f9b3eeSRoland Mainz 		"revents bitmask; it is not used in the "
9234f9b3eeSRoland Mainz 		"events member.]"
9334f9b3eeSRoland Mainz 	"[+POLLHUP?A hangup has occurred on the stream. This "
9434f9b3eeSRoland Mainz 		"event and POLLOUT are mutually exclusive; a "
9534f9b3eeSRoland Mainz 		"stream can never be writable if a hangup has "
9634f9b3eeSRoland Mainz 		"occurred. However, this event and POLLIN, "
9734f9b3eeSRoland Mainz 		", POLLRDBAND, or POLLPRI are not "
9834f9b3eeSRoland Mainz 		"mutually exclusive. This flag is only valid "
9934f9b3eeSRoland Mainz 		"in the revents bitmask; it is not used in "
10034f9b3eeSRoland Mainz 		"the events member.]"
10134f9b3eeSRoland Mainz 	"[+POLLNVAL?The specified fd value does not belong to an "
10234f9b3eeSRoland Mainz 		"open file. This flag is only valid in the "
10334f9b3eeSRoland Mainz 		"revents member; it is not used in the events "
10434f9b3eeSRoland Mainz 		"member.]"
10534f9b3eeSRoland Mainz    "}"
10634f9b3eeSRoland Mainz "]"
10734f9b3eeSRoland Mainz 
10834f9b3eeSRoland Mainz "[+?If the value fd is less than 0, events is ignored and "
10934f9b3eeSRoland Mainz 	"revents is set to 0 in that entry on return from poll.]"
11034f9b3eeSRoland Mainz 
11134f9b3eeSRoland Mainz "[+?The results of the poll query are stored in the revents "
11234f9b3eeSRoland Mainz 	"member in the \bvar\b structure. POLL*-strings are set in the \brevents\b "
11334f9b3eeSRoland Mainz 	"variable to indicate which of the requested events are true. "
11434f9b3eeSRoland Mainz 	"If none are true, the \brevents\b will be an empty string when "
11534f9b3eeSRoland Mainz 	"the poll command returns. The event flags "
11634f9b3eeSRoland Mainz 	"POLLHUP, POLLERR, and POLLNVAL are always set in \brevents\b "
11734f9b3eeSRoland Mainz 	"if the conditions they indicate are true; this occurs even "
11834f9b3eeSRoland Mainz 	"though these flags were not present in events.]"
11934f9b3eeSRoland Mainz 
12034f9b3eeSRoland Mainz "[+?If none of the defined events have occurred on any selected "
12134f9b3eeSRoland Mainz 	"file descriptor, poll waits at least timeout milliseconds "
12234f9b3eeSRoland Mainz 	"for an event to occur on any of the selected file descriptors. "
12334f9b3eeSRoland Mainz 	"On a computer where millisecond timing accuracy is not "
12434f9b3eeSRoland Mainz 	"available, timeout is rounded up to the nearest legal value "
12534f9b3eeSRoland Mainz 	"available on that system. If the value timeout is 0, poll "
12634f9b3eeSRoland Mainz 	"returns immediately. If the value of timeout is -1, poll "
12734f9b3eeSRoland Mainz 	"blocks until a requested event occurs or until the call is "
12834f9b3eeSRoland Mainz 	"interrupted.]"
12934f9b3eeSRoland Mainz 
13034f9b3eeSRoland Mainz "[+?The poll function supports regular files, terminal and "
13134f9b3eeSRoland Mainz 	"pseudo-terminal devices, STREAMS-based files, FIFOs and "
13234f9b3eeSRoland Mainz 	"pipes. The behavior of poll on elements of fds that refer "
13334f9b3eeSRoland Mainz 	"to other types of file is unspecified.]"
13434f9b3eeSRoland Mainz 
13534f9b3eeSRoland Mainz "[+?The poll function supports sockets.]"
13634f9b3eeSRoland Mainz 
13734f9b3eeSRoland Mainz "[+?A file descriptor for a socket that is listening for connections "
13834f9b3eeSRoland Mainz 	"will indicate that it is ready for reading, once connections "
13934f9b3eeSRoland Mainz 	"are available. A file descriptor for a socket that "
14034f9b3eeSRoland Mainz 	"is connecting asynchronously will indicate that it is ready "
14134f9b3eeSRoland Mainz 	"for writing, once a connection has been established.]"
142*b30d1939SAndy Fiddaman 
14334f9b3eeSRoland Mainz "[+?Regular files always poll TRUE for reading and writing.]"
14434f9b3eeSRoland Mainz 
14534f9b3eeSRoland Mainz "[e:eventarray]:[fdcount?Upon successful completion, an indexed array "
14634f9b3eeSRoland Mainz 	"of strings is returned which contains a list of array subscripts "
14734f9b3eeSRoland Mainz 	"in the poll array which received events.]"
14834f9b3eeSRoland Mainz "[t:timeout]:[seconds?Timeout in seconds. If the value timeout is 0, "
14934f9b3eeSRoland Mainz 	"poll returns immediately. If the value of timeout is -1, poll "
15034f9b3eeSRoland Mainz 	"blocks until a requested event occurs or until the call is "
15134f9b3eeSRoland Mainz 	"interrupted.]"
15234f9b3eeSRoland Mainz "[T:mtimeout]:[milliseconds?Timeout in milliseconds. If the value timeout is 0, "
15334f9b3eeSRoland Mainz 	"poll returns immediately. If the value of timeout is -1, poll "
15434f9b3eeSRoland Mainz 	"blocks until a requested event occurs or until the call is "
15534f9b3eeSRoland Mainz 	"interrupted.]"
15634f9b3eeSRoland Mainz "\n"
15734f9b3eeSRoland Mainz "\nvar\n"
15834f9b3eeSRoland Mainz "\n"
15934f9b3eeSRoland Mainz "[+EXIT STATUS?]{"
16034f9b3eeSRoland Mainz         "[+0?Success.]"
16134f9b3eeSRoland Mainz         "[+>0?An error occurred.]"
16234f9b3eeSRoland Mainz "}"
16334f9b3eeSRoland Mainz "[+SEE ALSO?\bopen\b(1),\btmpfile\b(1),\bdup\b(1),\bclose\b(1),\bpoll\b(2)]"
16434f9b3eeSRoland Mainz ;
16534f9b3eeSRoland Mainz 
16634f9b3eeSRoland Mainz /*
16734f9b3eeSRoland Mainz  * |mystpcpy| - like |strcpy()| but returns the end of the buffer
16834f9b3eeSRoland Mainz  *
16934f9b3eeSRoland Mainz  * Copy string s2 to s1.  s1 must be large enough.
17034f9b3eeSRoland Mainz  * return s1-1 (position of string terminator ('\0') in destnation buffer).
17134f9b3eeSRoland Mainz  */
17234f9b3eeSRoland Mainz static
mystpcpy(char * s1,const char * s2)17334f9b3eeSRoland Mainz char *mystpcpy(char *s1, const char *s2)
17434f9b3eeSRoland Mainz {
17534f9b3eeSRoland Mainz         while (*s1++ = *s2++)
17634f9b3eeSRoland Mainz                 ;
17734f9b3eeSRoland Mainz         return (s1-1);
17834f9b3eeSRoland Mainz }
17934f9b3eeSRoland Mainz 
18034f9b3eeSRoland Mainz static
nv_open_fmt(Dt_t * dict,int flags,const char * namefmt,...)18134f9b3eeSRoland Mainz Namval_t *nv_open_fmt(Dt_t *dict, int flags, const char *namefmt, ...)
18234f9b3eeSRoland Mainz {
18334f9b3eeSRoland Mainz 	char 	varnamebuff[PATH_MAX];
18434f9b3eeSRoland Mainz 	va_list	ap;
18534f9b3eeSRoland Mainz 
18634f9b3eeSRoland Mainz 	va_start(ap, namefmt);
18734f9b3eeSRoland Mainz 	vsnprintf(varnamebuff, sizeof(varnamebuff), namefmt, ap);
18834f9b3eeSRoland Mainz 	va_end(ap);
189*b30d1939SAndy Fiddaman 
19034f9b3eeSRoland Mainz 	return nv_open(varnamebuff, dict, flags);
19134f9b3eeSRoland Mainz }
19234f9b3eeSRoland Mainz 
19334f9b3eeSRoland Mainz static
poll_strtoevents(const char * str)19434f9b3eeSRoland Mainz int poll_strtoevents(const char *str)
19534f9b3eeSRoland Mainz {
19634f9b3eeSRoland Mainz 	int events = 0;
197*b30d1939SAndy Fiddaman 
19834f9b3eeSRoland Mainz 	if (strstr(str, "POLLIN"))     events |= POLLIN;
19934f9b3eeSRoland Mainz 	if (strstr(str, "POLLRDNORM")) events |= POLLRDNORM;
20034f9b3eeSRoland Mainz 	if (strstr(str, "POLLRDBAND")) events |= POLLRDBAND;
20134f9b3eeSRoland Mainz 	if (strstr(str, "POLLPRI"))    events |= POLLPRI;
20234f9b3eeSRoland Mainz 	if (strstr(str, "POLLOUT"))    events |= POLLOUT;
20334f9b3eeSRoland Mainz 	if (strstr(str, "POLLWRNORM")) events |= POLLWRNORM;
20434f9b3eeSRoland Mainz 	if (strstr(str, "POLLWRBAND")) events |= POLLWRBAND;
20534f9b3eeSRoland Mainz 	if (strstr(str, "POLLERR"))    events |= POLLERR;
20634f9b3eeSRoland Mainz 	if (strstr(str, "POLLHUP"))    events |= POLLHUP;
20734f9b3eeSRoland Mainz 	if (strstr(str, "POLLNVAL"))   events |= POLLNVAL;
20834f9b3eeSRoland Mainz 
20934f9b3eeSRoland Mainz 	return events;
21034f9b3eeSRoland Mainz }
21134f9b3eeSRoland Mainz 
21234f9b3eeSRoland Mainz 
21334f9b3eeSRoland Mainz static
poll_eventstostr(char * s,int events)21434f9b3eeSRoland Mainz void poll_eventstostr(char *s, int events)
21534f9b3eeSRoland Mainz {
21634f9b3eeSRoland Mainz 	*s='\0';
21734f9b3eeSRoland Mainz 	if (!events)
21834f9b3eeSRoland Mainz 		return;
219*b30d1939SAndy Fiddaman 
22034f9b3eeSRoland Mainz 	if (events & POLLIN)		s=mystpcpy(s, "POLLIN|");
22134f9b3eeSRoland Mainz 	if (events & POLLRDNORM)	s=mystpcpy(s, "POLLRDNORM|");
22234f9b3eeSRoland Mainz 	if (events & POLLRDBAND)	s=mystpcpy(s, "POLLRDBAND|");
22334f9b3eeSRoland Mainz 	if (events & POLLPRI)		s=mystpcpy(s, "POLLPRI|");
22434f9b3eeSRoland Mainz 	if (events & POLLOUT)		s=mystpcpy(s, "POLLOUT|");
22534f9b3eeSRoland Mainz 	if (events & POLLWRNORM)	s=mystpcpy(s, "POLLWRNORM|");
22634f9b3eeSRoland Mainz 	if (events & POLLWRBAND)	s=mystpcpy(s, "POLLWRBAND|");
22734f9b3eeSRoland Mainz 	if (events & POLLERR)		s=mystpcpy(s, "POLLERR|");
22834f9b3eeSRoland Mainz 	if (events & POLLHUP)		s=mystpcpy(s, "POLLHUP|");
22934f9b3eeSRoland Mainz 	if (events & POLLNVAL)		s=mystpcpy(s, "POLLNVAL|");
23034f9b3eeSRoland Mainz 
23134f9b3eeSRoland Mainz 	/* Remove trailling '|' */
23234f9b3eeSRoland Mainz 	s--;
23334f9b3eeSRoland Mainz 	if(*s=='|')
23434f9b3eeSRoland Mainz 		*s='\0';
23534f9b3eeSRoland Mainz }
23634f9b3eeSRoland Mainz 
23734f9b3eeSRoland Mainz #undef  getconf
23834f9b3eeSRoland Mainz #define getconf(x)      strtol(astconf(x,NiL,NiL),NiL,0)
239*b30d1939SAndy Fiddaman 
b_poll(int argc,char * argv[],Shbltin_t * context)240*b30d1939SAndy Fiddaman extern int b_poll(int argc, char *argv[], Shbltin_t *context)
24134f9b3eeSRoland Mainz {
24234f9b3eeSRoland Mainz 	Namval_t *np;
243*b30d1939SAndy Fiddaman 	Shell_t *shp = context->shp;
24434f9b3eeSRoland Mainz 	char *varname;
24534f9b3eeSRoland Mainz 	int n;
24634f9b3eeSRoland Mainz 	int fd;
24734f9b3eeSRoland Mainz 	nfds_t numpollfd = 0;
24834f9b3eeSRoland Mainz 	int i;
24934f9b3eeSRoland Mainz 	char *s;
25034f9b3eeSRoland Mainz 	double timeout = -1.;
25134f9b3eeSRoland Mainz 	char buff[PATH_MAX*2+1]; /* enogth to hold two variable names */
25234f9b3eeSRoland Mainz 	char *eventarrayname = NULL;
25334f9b3eeSRoland Mainz 
25434f9b3eeSRoland Mainz 	while (n = optget(argv, sh_optpoll)) switch (n)
25534f9b3eeSRoland Mainz 	{
25634f9b3eeSRoland Mainz 	    case 't':
25734f9b3eeSRoland Mainz 	    case 'T':
25834f9b3eeSRoland Mainz 		errno = 0;
259*b30d1939SAndy Fiddaman 		timeout = strtod(opt_info.arg, (char **)NULL);
26034f9b3eeSRoland Mainz 		if (errno != 0)
26134f9b3eeSRoland Mainz 			errormsg(SH_DICT, ERROR_system(1), "%s: invalid timeout", opt_info.arg);
26234f9b3eeSRoland Mainz 
26334f9b3eeSRoland Mainz 		/* -t uses seconds, -T milliseconds */
26434f9b3eeSRoland Mainz 		if (n == 't')
26534f9b3eeSRoland Mainz 			timeout *= 1000.;
26634f9b3eeSRoland Mainz 		break;
26734f9b3eeSRoland Mainz 	    case 'e':
26834f9b3eeSRoland Mainz 	    	eventarrayname = opt_info.arg;
26934f9b3eeSRoland Mainz 		break;
27034f9b3eeSRoland Mainz 	    case ':':
27134f9b3eeSRoland Mainz 		errormsg(SH_DICT, 2, "%s", opt_info.arg);
27234f9b3eeSRoland Mainz 		break;
27334f9b3eeSRoland Mainz 	    case '?':
27434f9b3eeSRoland Mainz 		errormsg(SH_DICT, ERROR_usage(2), "%s", opt_info.arg);
27534f9b3eeSRoland Mainz 		break;
27634f9b3eeSRoland Mainz 	}
27734f9b3eeSRoland Mainz 	argc -= opt_info.index;
27834f9b3eeSRoland Mainz 	argv += opt_info.index;
27934f9b3eeSRoland Mainz 	if(argc!=1)
28034f9b3eeSRoland Mainz 		errormsg(SH_DICT, ERROR_usage(2), optusage((char*)0));
28134f9b3eeSRoland Mainz 
28234f9b3eeSRoland Mainz         varname = argv[0];
28334f9b3eeSRoland Mainz 
28434f9b3eeSRoland Mainz 	Namval_t *array_np, *array_np_sub;
28534f9b3eeSRoland Mainz 	const char *subname;
28634f9b3eeSRoland Mainz 
28734f9b3eeSRoland Mainz 	array_np = nv_open(varname, shp->var_tree, NV_NOFAIL|NV_NOADD);
28834f9b3eeSRoland Mainz 	if (!array_np)
28934f9b3eeSRoland Mainz 		errormsg(SH_DICT, ERROR_system(1), "cannot find array variable %s", varname);
29034f9b3eeSRoland Mainz 	if(!nv_isattr(array_np, NV_ARRAY))
29134f9b3eeSRoland Mainz 		errormsg(SH_DICT, ERROR_system(1), "variable %s is not an array", varname);
29234f9b3eeSRoland Mainz 
29334f9b3eeSRoland Mainz 	/* Count number of array elememts. We need to do it "manually" to
29434f9b3eeSRoland Mainz 	 * handle sparse indexed and associative arrays */
29534f9b3eeSRoland Mainz 	nv_putsub(array_np, NULL, ARRAY_SCAN);
29634f9b3eeSRoland Mainz 	array_np_sub = array_np;
29734f9b3eeSRoland Mainz 	do
29834f9b3eeSRoland Mainz 	{
29934f9b3eeSRoland Mainz 		if (!(subname=nv_getsub(array_np_sub)))
30034f9b3eeSRoland Mainz 			break;
30134f9b3eeSRoland Mainz 		numpollfd++;
30234f9b3eeSRoland Mainz 	} while( array_np_sub && nv_nextsub(array_np_sub) );
30334f9b3eeSRoland Mainz 
30434f9b3eeSRoland Mainz #ifdef __GNUC__
30534f9b3eeSRoland Mainz         /*
30634f9b3eeSRoland Mainz          * Allocate stack space via |alloca()| for gcc builds since ctfconvert
30734f9b3eeSRoland Mainz          * is unable to handle VLAs from gcc. We need this until CR #6379193
30834f9b3eeSRoland Mainz 	 * is fixed.
30934f9b3eeSRoland Mainz          */
31034f9b3eeSRoland Mainz 	struct pollfd *pollfd = alloca(sizeof(struct pollfd)*(numpollfd+1));
31134f9b3eeSRoland Mainz #else
31234f9b3eeSRoland Mainz 	/* We must allocate one more entry with VLA with zero elements do not work with all compilers */
31334f9b3eeSRoland Mainz 	struct pollfd pollfd[numpollfd+1];
31434f9b3eeSRoland Mainz #endif /* __GNUC__ */
31534f9b3eeSRoland Mainz 
31634f9b3eeSRoland Mainz 	nv_putsub(array_np, NULL, ARRAY_SCAN);
31734f9b3eeSRoland Mainz 	array_np_sub = array_np;
31834f9b3eeSRoland Mainz 	i = 0;
31934f9b3eeSRoland Mainz 	do
32034f9b3eeSRoland Mainz 	{
32134f9b3eeSRoland Mainz 		if (!(subname=nv_getsub(array_np_sub)))
32234f9b3eeSRoland Mainz 			break;
32334f9b3eeSRoland Mainz 
32434f9b3eeSRoland Mainz 		np = nv_open_fmt(shp->var_tree, NV_NOFAIL|NV_NOADD, "%s[%s].fd", varname, subname);
32534f9b3eeSRoland Mainz 		if (!np)
32634f9b3eeSRoland Mainz 			errormsg(SH_DICT, ERROR_system(1), "missing pollfd %s[%s].fd", varname, subname);
32734f9b3eeSRoland Mainz 		fd = (int)nv_getnum(np);
32834f9b3eeSRoland Mainz 		if (fd < 0 || fd > OPEN_MAX)
32934f9b3eeSRoland Mainz 			errormsg(SH_DICT, ERROR_system(1), "invalid pollfd fd %d", fd);
33034f9b3eeSRoland Mainz 		nv_close(np);
33134f9b3eeSRoland Mainz 		pollfd[i].fd = fd;
33234f9b3eeSRoland Mainz 
33334f9b3eeSRoland Mainz 		np = nv_open_fmt(shp->var_tree, NV_NOFAIL|NV_NOADD, "%s[%s].events", varname, subname);
33434f9b3eeSRoland Mainz 		if (!np)
33534f9b3eeSRoland Mainz 			errormsg(SH_DICT, ERROR_system(1), "missing pollfd %s[%s].events", varname, subname);
33634f9b3eeSRoland Mainz 
33734f9b3eeSRoland Mainz 		s = nv_getval(np);
33834f9b3eeSRoland Mainz 		if (!s)
33934f9b3eeSRoland Mainz 			errormsg(SH_DICT, ERROR_system(1), "missing pollfd events value");
34034f9b3eeSRoland Mainz 		pollfd[i].events  = poll_strtoevents(s);
34134f9b3eeSRoland Mainz 		nv_close(np);
34234f9b3eeSRoland Mainz 
34334f9b3eeSRoland Mainz 		pollfd[i].revents = 0;
344*b30d1939SAndy Fiddaman 
34534f9b3eeSRoland Mainz 		i++;
34634f9b3eeSRoland Mainz 	} while( array_np_sub && nv_nextsub(array_np_sub) );
347*b30d1939SAndy Fiddaman 
34834f9b3eeSRoland Mainz 	n = poll(pollfd, numpollfd, timeout);
34934f9b3eeSRoland Mainz 	/* FixMe: EGAIN and EINTR may require extra handling */
35034f9b3eeSRoland Mainz 	if (n < 0)
35134f9b3eeSRoland Mainz 		errormsg(SH_DICT, ERROR_system(1), "failure");
35234f9b3eeSRoland Mainz 
35334f9b3eeSRoland Mainz 	if (eventarrayname)
35434f9b3eeSRoland Mainz 	{
35534f9b3eeSRoland Mainz 		np = nv_open_fmt(shp->var_tree, NV_VARNAME|NV_ARRAY|NV_NOFAIL, "%s", eventarrayname);
35634f9b3eeSRoland Mainz 		if (!np)
35734f9b3eeSRoland Mainz 			errormsg(SH_DICT, ERROR_system(1), "couldn't create poll count variable %s", eventarrayname);
35834f9b3eeSRoland Mainz 		nv_close(np);
35934f9b3eeSRoland Mainz 	}
36034f9b3eeSRoland Mainz 
36134f9b3eeSRoland Mainz 	nv_putsub(array_np, NULL, ARRAY_SCAN);
36234f9b3eeSRoland Mainz 	array_np_sub = array_np;
36334f9b3eeSRoland Mainz 	i = 0;
36434f9b3eeSRoland Mainz 	do
36534f9b3eeSRoland Mainz 	{
36634f9b3eeSRoland Mainz 		if (!(subname=nv_getsub(array_np_sub)))
36734f9b3eeSRoland Mainz 			break;
368*b30d1939SAndy Fiddaman 
36934f9b3eeSRoland Mainz 		np = nv_open_fmt(shp->var_tree, NV_NOFAIL, "%s[%s].revents", varname, subname);
37034f9b3eeSRoland Mainz 		if (!np)
37134f9b3eeSRoland Mainz 			errormsg(SH_DICT, ERROR_system(1), "couldn't create pollfd %s[%s].revents", varname, subname);
37234f9b3eeSRoland Mainz 
37334f9b3eeSRoland Mainz 		poll_eventstostr(buff, pollfd[i].revents);
374*b30d1939SAndy Fiddaman 
37534f9b3eeSRoland Mainz 		nv_putval(np, buff, 0);
37634f9b3eeSRoland Mainz 		nv_close(np);
377*b30d1939SAndy Fiddaman 
37834f9b3eeSRoland Mainz 		if (eventarrayname && pollfd[i].revents)
37934f9b3eeSRoland Mainz 		{
38034f9b3eeSRoland Mainz 			sprintf(buff, "%s+=( '%s' )", eventarrayname, subname);
38134f9b3eeSRoland Mainz 			sh_trap(buff, 0);
38234f9b3eeSRoland Mainz 		}
383*b30d1939SAndy Fiddaman 
38434f9b3eeSRoland Mainz 		i++;
38534f9b3eeSRoland Mainz 	} while( array_np_sub && nv_nextsub(array_np_sub) );
386*b30d1939SAndy Fiddaman 
38734f9b3eeSRoland Mainz 	nv_close(array_np);
388*b30d1939SAndy Fiddaman 
38934f9b3eeSRoland Mainz 	return(0);
39034f9b3eeSRoland Mainz }
391