Reimplement the load average plugin in pure Lua.
[wmiirc-lua.git] / luaixp / lixp_instance.c
blob23e2e7e563082f22b752a8e0404e8b41b8de8811
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <errno.h>
6 #include <time.h>
7 #include <signal.h>
9 #include <ixp.h>
10 #include <lua.h>
11 #include <lauxlib.h>
13 #include "lixp_debug.h"
14 #include "lixp_util.h"
15 #include "lixp_instance.h"
18 /* ------------------------------------------------------------------------
19 * utility functions
22 struct ixp *lixp_checkixp (lua_State *L, int narg)
24 void *ud = luaL_checkudata (L, narg, L_IXP_MT);
25 luaL_argcheck (L, ud != NULL, 1, "`ixp' expected");
26 return (struct ixp*)ud;
29 int l_ixp_tostring (lua_State *L)
31 struct ixp *ixp = lixp_checkixp (L, 1);
32 lua_pushfstring (L, "ixp instance %p", ixp);
33 return 1;
36 /* ------------------------------------------------------------------------
37 * lua: write(file, data) -- writes data to a file
40 int l_ixp_write (lua_State *L)
42 struct ixp *ixp;
43 IxpCFid *fid;
44 const char *file;
45 const char *data;
46 size_t data_len;
47 int rc;
49 ixp = lixp_checkixp (L, 1);
50 file = luaL_checkstring (L, 2);
51 data = luaL_checklstring (L, 3, &data_len);
53 fid = ixp_open(ixp->client, file, P9_OWRITE);
54 if(fid == NULL)
55 return lixp_pusherror (L, "count not open p9 file");
57 DBGF("** ixp.write (%s,%s) **\n", file, data);
59 rc = lixp_write_data (fid, data, data_len);
60 if (rc < 0) {
61 ixp_close(fid);
62 return lixp_pusherror (L, "failed to write to p9 file");
65 ixp_close(fid);
66 return 0;
69 /* ------------------------------------------------------------------------
70 * lua: data = read(file) -- returns all contents (upto 4k)
72 int l_ixp_read (lua_State *L)
74 struct ixp *ixp;
75 IxpCFid *fid;
76 const char *file;
77 char *buf;
78 size_t buf_ofs, buf_size, buf_left;
80 ixp = lixp_checkixp (L, 1);
81 file = luaL_checkstring (L, 2);
83 fid = ixp_open(ixp->client, file, P9_OREAD);
84 if(fid == NULL)
85 return lixp_pusherror (L, "count not open p9 file");
87 buf = malloc (fid->iounit);
88 if (!buf) {
89 ixp_close(fid);
90 return lixp_pusherror (L, "count not allocate memory");
92 buf_ofs = 0;
93 buf_size = buf_left = fid->iounit;
95 DBGF("** ixp.read (%s) **\n", file);
97 for (;;) {
98 int rc = ixp_read (fid, buf+buf_ofs, buf_left);
99 if (rc==0)
100 break;
101 else if (rc<0) {
102 ixp_close(fid);
103 return lixp_pusherror (L, "failed to read from p9 file");
106 buf_ofs += rc;
107 buf_left -= rc;
109 if (buf_ofs >= buf_size)
110 return lixp_pusherror (L, "internal error while reading");
112 if (buf_size >= 4096)
113 break;
115 buf = realloc (buf, 4096);
116 if (!buf) {
117 ixp_close(fid);
118 return lixp_pusherror (L, "count not allocate memory");
120 buf_size = 4096;
123 ixp_close(fid);
125 lua_pushstring (L, buf);
126 return 1;
129 /* ------------------------------------------------------------------------
130 * lua: create(file, [data]) -- create a file, optionally write data to it
132 int l_ixp_create (lua_State *L)
134 struct ixp *ixp;
135 IxpCFid *fid;
136 const char *file;
137 const char *data;
138 size_t data_len = 0;
140 ixp = lixp_checkixp (L, 1);
141 file = luaL_checkstring (L, 2);
142 data = luaL_optlstring (L, 3, NULL, &data_len);
144 DBGF("** ixp.create (%s) **\n", file);
146 fid = ixp_create (ixp->client, file, 0777, P9_OWRITE);
147 if (!fid)
148 return lixp_pusherror (L, "count not create file");
150 if (data && data_len
151 && !(fid->qid.type & P9_DMDIR)) {
152 int rc = lixp_write_data (fid, data, data_len);
153 if (rc < 0) {
154 ixp_close(fid);
155 return lixp_pusherror (L, "failed to write to p9 file");
159 ixp_close(fid);
160 return 0;
163 /* ------------------------------------------------------------------------
164 * lua: remove(file) -- remove a file
166 int l_ixp_remove (lua_State *L)
168 struct ixp *ixp;
169 int rc;
170 const char *file;
172 ixp = lixp_checkixp (L, 1);
173 file = luaL_checkstring (L, 2);
175 DBGF("** ixp.remove (%s) **\n", file);
177 rc = ixp_remove (ixp->client, file);
178 if (!rc)
179 return lixp_pusherror (L, "failed to remove p9 file");
181 return 0;
184 /* ------------------------------------------------------------------------
185 * lua: itr = iread(file) -- returns a line iterator
188 struct l_ixp_iread_s {
189 IxpCFid *fid;
190 char *buf;
191 size_t buf_pos;
192 size_t buf_len;
193 size_t buf_size;
196 static int iread_iter (lua_State *L);
198 int l_ixp_iread (lua_State *L)
200 struct ixp *ixp;
201 const char *file;
202 struct l_ixp_iread_s *ctx;
204 ixp = lixp_checkixp (L, 1);
205 file = luaL_checkstring (L, 2);
207 ctx = (struct l_ixp_iread_s*)lua_newuserdata (L, sizeof(*ctx));
208 if (!ctx)
209 return lixp_pusherror (L, "count not allocate context");
210 memset (ctx, 0, sizeof (*ctx));
212 // set the metatable for the new userdata
213 luaL_getmetatable (L, L_IXP_IREAD_MT);
214 lua_setmetatable (L, -2);
216 ctx->fid = ixp_open(ixp->client, file, P9_OREAD);
217 if(ctx->fid == NULL) {
218 return lixp_pusherror (L, "count not open p9 file");
221 DBGF("** ixp.iread (%s) **\n", file);
223 // create and return the iterator function
224 // the only argument is the userdata
225 lua_pushcclosure (L, iread_iter, 1);
226 return 1;
229 static int iread_iter (lua_State *L)
231 struct l_ixp_iread_s *ctx;
232 char *s, *e, *cr;
234 ctx = (struct l_ixp_iread_s*)lua_touserdata (L, lua_upvalueindex(1));
236 DBGF("** ixp.iread - iter **\n");
238 if (!ctx->buf) {
239 ctx->buf = malloc (ctx->fid->iounit);
240 if (!ctx->buf)
241 return lixp_pusherror (L, "count not allocate memory");
242 ctx->buf_size = ctx->fid->iounit;
243 ctx->buf_len = 0;
246 if (!ctx->buf_len) {
247 int rc;
248 ctx->buf_pos = 0;
249 rc = ixp_read (ctx->fid, ctx->buf, ctx->buf_size);
250 if (rc <= 0) {
251 return 0; // we are done
253 ctx->buf_len = rc;
256 s = ctx->buf + ctx->buf_pos;
257 e = s + ctx->buf_len;
259 cr = strchr (s, '\n');
260 if (!cr) {
261 // no match, just return the whole thing
262 // TODO: should read more upto a cr or some limit
263 lua_pushstring (L, s);
264 ctx->buf_len = 0;
265 return 1;
267 } else {
268 // we have a match s..cr is our sub string
269 int len = (cr-s) + 1;
270 *cr = 0;
271 lua_pushstring (L, s);
272 ctx->buf_pos += len;
273 ctx->buf_len -= len;
274 return 1;
278 static int iread_gc (lua_State *L)
280 struct l_ixp_iread_s *ctx;
282 ctx = (struct l_ixp_iread_s*)lua_touserdata (L, 1);
284 DBGF("** ixp.iread - gc **\n");
286 ixp_close (ctx->fid);
288 if (ctx->buf)
289 free (ctx->buf);
291 return 0;
294 void lixp_init_iread_mt (lua_State *L)
296 luaL_newmetatable(L, L_IXP_IREAD_MT);
298 // setup the __gc field
299 lua_pushstring (L, "__gc");
300 lua_pushcfunction (L, iread_gc);
301 lua_settable (L, -3);
304 /* ------------------------------------------------------------------------
305 * lua: stat = stat(file) -- returns a status table
308 int l_ixp_stat (lua_State *L)
310 struct ixp *ixp;
311 struct IxpStat *stat;
312 const char *file;
313 int rc;
315 ixp = lixp_checkixp (L, 1);
316 file = luaL_checkstring (L, 2);
318 DBGF("** ixp.stat (%s) **\n", file);
320 stat = ixp_stat(ixp->client, file);
321 if(!stat)
322 return lixp_pusherror(L, "cannot stat file");
324 rc = lixp_pushstat (L, stat);
326 ixp_freestat (stat);
328 return rc;
331 /* ------------------------------------------------------------------------
332 * lua: itr = idir(dir) -- returns a file name iterator
335 struct l_ixp_idir_s {
336 IxpCFid *fid;
337 unsigned char *buf;
338 IxpMsg m;
341 static int idir_iter (lua_State *L);
343 int l_ixp_idir (lua_State *L)
345 struct ixp *ixp;
346 const char *file;
347 struct l_ixp_idir_s *ctx;
349 ixp = lixp_checkixp (L, 1);
350 file = luaL_checkstring (L, 2);
352 ctx = (struct l_ixp_idir_s*)lua_newuserdata (L, sizeof(*ctx));
353 if (!ctx)
354 return lixp_pusherror (L, "count not allocate context");
355 memset(ctx, 0, sizeof (*ctx));
357 // set the metatable for the new userdata
358 luaL_getmetatable (L, L_IXP_IDIR_MT);
359 lua_setmetatable (L, -2);
361 ctx->fid = ixp_open(ixp->client, file, P9_OREAD);
362 if(ctx->fid == NULL) {
363 return lixp_pusherror (L, "count not open p9 file");
366 ctx->buf = malloc (ctx->fid->iounit);
367 if (!ctx->buf) {
368 ixp_close (ctx->fid);
369 ctx->fid = NULL;
370 return lixp_pusherror (L, "count not allocate memory");
373 DBGF("** ixp.idir (%s) **\n", file);
375 // create and return the iterator function
376 // the only argument is the userdata
377 lua_pushcclosure (L, idir_iter, 1);
378 return 1;
381 static int idir_iter (lua_State *L)
383 struct l_ixp_idir_s *ctx;
384 IxpStat stat;
386 ctx = (struct l_ixp_idir_s*)lua_touserdata (L, lua_upvalueindex(1));
388 DBGF("** ixp.idir - iter **\n");
390 if (ctx->m.pos >= ctx->m.end) {
391 int rc = ixp_read (ctx->fid, ctx->buf, ctx->fid->iounit);
392 if (rc <= 0) {
393 return 0;
396 ctx->m = ixp_message(ctx->buf, rc, MsgUnpack);
397 if (ctx->m.pos >= ctx->m.end)
398 return 0;
401 ixp_pstat(&ctx->m, &stat);
403 return lixp_pushstat (L, &stat);
406 static int idir_gc (lua_State *L)
408 struct l_ixp_idir_s *ctx;
410 ctx = (struct l_ixp_idir_s*)lua_touserdata (L, 1);
412 DBGF("** ixp.idir - gc **\n");
414 free (ctx->buf);
416 ixp_close (ctx->fid);
418 return 0;
421 void lixp_init_idir_mt (lua_State *L)
423 luaL_newmetatable(L, L_IXP_IDIR_MT);
425 // setup the __gc field
426 lua_pushstring (L, "__gc");
427 lua_pushcfunction (L, idir_gc);
428 lua_settable (L, -3);