nixio linux IO/socket api (incomplete / WIP)
[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 }