1 /*=========================================================================*\
2 * Serial stream
3 * LuaSocket toolkit
4 \*=========================================================================*/
5 #include <string.h>
6 
7 #include "lua.h"
8 #include "lauxlib.h"
9 
10 #include "auxiliar.h"
11 #include "socket.h"
12 #include "options.h"
13 #include "unix.h"
14 #ifndef _WIN32
15 #include <sys/un.h>
16 #endif
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <fcntl.h>
20 /*
21 Reuses userdata definition from unix.h, since it is useful for all
22 stream-like objects.
23 
24 If we stored the serial path for use in error messages or userdata
25 printing, we might need our own userdata definition.
26 
27 Group usage is semi-inherited from unix.c, but unnecessary since we
28 have only one object type.
29 */
30 
31 /*=========================================================================*\
32 * Internal function prototypes
33 \*=========================================================================*/
34 static int global_create(lua_State *L);
35 static int meth_send(lua_State *L);
36 static int meth_receive(lua_State *L);
37 static int meth_close(lua_State *L);
38 static int meth_settimeout(lua_State *L);
39 static int meth_getfd(lua_State *L);
40 static int meth_setfd(lua_State *L);
41 static int meth_dirty(lua_State *L);
42 static int meth_getstats(lua_State *L);
43 static int meth_setstats(lua_State *L);
44 
45 /* serial object methods */
46 static luaL_Reg serial_methods[] = {
47     {"__gc",        meth_close},
48     {"__tostring",  auxiliar_tostring},
49     {"close",       meth_close},
50     {"dirty",       meth_dirty},
51     {"getfd",       meth_getfd},
52     {"getstats",    meth_getstats},
53     {"setstats",    meth_setstats},
54     {"receive",     meth_receive},
55     {"send",        meth_send},
56     {"setfd",       meth_setfd},
57     {"settimeout",  meth_settimeout},
58     {NULL,          NULL}
59 };
60 
61 /* our socket creation function */
62 static luaL_Reg func[] = {
63     {"serial", global_create},
64     {NULL,          NULL}
65 };
66 
67 
68 /*-------------------------------------------------------------------------*\
69 * Initializes module
70 \*-------------------------------------------------------------------------*/
luaopen_socket_serial(lua_State * L)71 LUASOCKET_API int luaopen_socket_serial(lua_State *L) {
72     /* create classes */
73     auxiliar_newclass(L, "serial{client}", serial_methods);
74     /* create class groups */
75     auxiliar_add2group(L, "serial{client}", "serial{any}");
76     /* make sure the function ends up in the package table */
77     luaL_openlib(L, "socket", func, 0);
78     /* return the function instead of the 'socket' table */
79     lua_pushstring(L, "serial");
80     lua_gettable(L, -2);
81     return 1;
82 }
83 
84 /*=========================================================================*\
85 * Lua methods
86 \*=========================================================================*/
87 /*-------------------------------------------------------------------------*\
88 * Just call buffered IO methods
89 \*-------------------------------------------------------------------------*/
meth_send(lua_State * L)90 static int meth_send(lua_State *L) {
91     p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
92     return buffer_meth_send(L, &un->buf);
93 }
94 
meth_receive(lua_State * L)95 static int meth_receive(lua_State *L) {
96     p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
97     return buffer_meth_receive(L, &un->buf);
98 }
99 
meth_getstats(lua_State * L)100 static int meth_getstats(lua_State *L) {
101     p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
102     return buffer_meth_getstats(L, &un->buf);
103 }
104 
meth_setstats(lua_State * L)105 static int meth_setstats(lua_State *L) {
106     p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
107     return buffer_meth_setstats(L, &un->buf);
108 }
109 
110 /*-------------------------------------------------------------------------*\
111 * Select support methods
112 \*-------------------------------------------------------------------------*/
meth_getfd(lua_State * L)113 static int meth_getfd(lua_State *L) {
114     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
115     lua_pushnumber(L, (int) un->sock);
116     return 1;
117 }
118 
119 /* this is very dangerous, but can be handy for those that are brave enough */
meth_setfd(lua_State * L)120 static int meth_setfd(lua_State *L) {
121     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
122     un->sock = (t_socket) luaL_checknumber(L, 2);
123     return 0;
124 }
125 
meth_dirty(lua_State * L)126 static int meth_dirty(lua_State *L) {
127     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
128     lua_pushboolean(L, !buffer_isempty(&un->buf));
129     return 1;
130 }
131 
132 /*-------------------------------------------------------------------------*\
133 * Closes socket used by object
134 \*-------------------------------------------------------------------------*/
meth_close(lua_State * L)135 static int meth_close(lua_State *L)
136 {
137     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
138     socket_destroy(&un->sock);
139     lua_pushnumber(L, 1);
140     return 1;
141 }
142 
143 
144 /*-------------------------------------------------------------------------*\
145 * Just call tm methods
146 \*-------------------------------------------------------------------------*/
meth_settimeout(lua_State * L)147 static int meth_settimeout(lua_State *L) {
148     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
149     return timeout_meth_settimeout(L, &un->tm);
150 }
151 
152 /*=========================================================================*\
153 * Library functions
154 \*=========================================================================*/
155 
156 
157 /*-------------------------------------------------------------------------*\
158 * Creates a serial object
159 \*-------------------------------------------------------------------------*/
global_create(lua_State * L)160 static int global_create(lua_State *L) {
161     const char* path = luaL_checkstring(L, 1);
162 
163     /* allocate unix object */
164     p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
165 
166     /* open serial device */
167 #ifdef __MINGW32__
168     t_socket sock = open(path, O_RDWR);
169 #else
170     t_socket sock = open(path, O_NOCTTY|O_RDWR);
171 #endif
172 
173     /*printf("open %s on %d\n", path, sock);*/
174 
175     if (sock < 0)  {
176         lua_pushnil(L);
177         lua_pushstring(L, socket_strerror(errno));
178         lua_pushnumber(L, errno);
179         return 3;
180     }
181     /* set its type as client object */
182     auxiliar_setclass(L, "serial{client}", -1);
183     /* initialize remaining structure fields */
184     socket_setnonblocking(&sock);
185     un->sock = sock;
186     io_init(&un->io, (p_send) socket_write, (p_recv) socket_read,
187             (p_error) socket_ioerror, &un->sock);
188     timeout_init(&un->tm, -1, -1);
189     buffer_init(&un->buf, &un->io, &un->tm);
190     return 1;
191 }
192