e88075ce412660bb49f408324741ce6104bbd48f
[project/luci.git] / libs / nixio / src / select.c
1 /*
2  * nixio - Linux I/O library for lua
3  *
4  *   Copyright (C) 2009 Steven Barth <steven@midlink.org>
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  */
18
19 #include <lua.h>
20 #include <lualib.h>
21 #include <lauxlib.h>
22 #include <sys/select.h>
23 #include "nixio.h"
24
25 static int nixio_select(lua_State *L) {
26         int nfds = 0, tmpfd = -1, i = 0, j = 0, o = 0, k, tlen;
27         fd_set rfds, wfds, xfds;
28         fd_set *fdsets[3] = {&rfds, &wfds, &xfds};
29         FD_ZERO(fdsets[0]);
30         FD_ZERO(fdsets[1]);
31         FD_ZERO(fdsets[2]);
32
33         struct timeval timeout;
34         timeout.tv_sec = luaL_optinteger(L, 4, 0);
35         timeout.tv_usec = luaL_optinteger(L, 5, 0);
36
37         /* create fdsets */
38         for (i=0; i<3; i++) {
39                 o = i + 1;
40                 if (lua_isnoneornil(L, o)) {
41                         fdsets[i] = NULL;
42                         continue;
43                 }
44
45                 luaL_checktype(L, o, LUA_TTABLE);
46                 tlen = lua_objlen(L, o);
47                 luaL_argcheck(L, tlen <= FD_SETSIZE, o, "too many fds");
48
49                 for (j=1; j<=tlen; j++) {
50                         lua_rawgeti(L, o, j);
51                         tmpfd = nixio__checkfd(L, -1);
52                         FD_SET(tmpfd, fdsets[i]);
53                         if (tmpfd >= nfds) {
54                                 nfds = tmpfd + 1;
55                         }
56                         lua_pop(L, 1);
57                 }
58         }
59
60         int stat = select(nfds, fdsets[0], fdsets[1], fdsets[2], &timeout);
61
62         if (stat < 0) {
63                 return nixio__perror(L);
64         } else if (stat == 0) {
65                 lua_pushinteger(L, stat);
66                 for (i=1; i<=3; i++) {
67                         if (lua_isnoneornil(L, i)) {
68                                 lua_pushnil(L);
69                         } else {
70                                 lua_newtable(L);
71                         }
72                 }
73         } else {
74                 lua_pushinteger(L, stat);
75
76                 /* create return tables */
77                 for (i=0; i<3; i++) {
78                         o = i + 1;
79                         if (lua_isnoneornil(L, o)) {
80                                 lua_pushnil(L);
81                                 continue;
82                         }
83
84                         lua_newtable(L);
85                         tlen = lua_objlen(L, o);
86                         k = 1;
87
88                         for (j=1; j<=tlen; j++) {
89                                 lua_rawgeti(L, o, j);
90                                 tmpfd = nixio__tofd(L, -1);
91                                 if (FD_ISSET(tmpfd, fdsets[i])) {
92                                         lua_rawseti(L, -2, k++);
93                                 } else {
94                                         lua_pop(L, 1);
95                                 }
96                         }
97                 }
98         }
99         return 4;
100 }
101
102 /* module table */
103 static const luaL_reg R[] = {
104         {"select",      nixio_select},
105         {NULL,                  NULL}
106 };
107
108 void nixio_open_select(lua_State *L) {
109         luaL_register(L, NULL, R);
110 }