start all programs with wmiir setsid
[wmiirc-lua.git] / luaixp / lixp_instance.c
blobc54a76ad5f19267774790e67725044b19597fca7
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 [,short_read] = read(file, [max_buffer_size])
71 * -- returns contents of file
73 * max_buffer_size limits the read to IXP_READ_MAX_BUFFER_SIZE by default, but
74 * can be configured to a different value. Setting max_buffer_size to zero
75 * means no limit will be applied.
77 * On return data holds the data read, and short_read indicates if there was
78 * more data that was not read.
80 * If the file contents are expected to be large use l_ixp_iread(), which
81 * iterates over the file.
83 int l_ixp_read (lua_State *L)
85 struct ixp *ixp;
86 IxpCFid *fid;
87 const char *file;
88 char *buf, *_buf;
89 size_t buf_ofs, buf_size;
90 lua_Number max_buffer_size;
91 size_t realloc_size;
92 int short_read = 1;
94 ixp = lixp_checkixp (L, 1);
95 file = luaL_checkstring (L, 2);
96 max_buffer_size = luaL_optnumber (L, 3, IXP_READ_MAX_BUFFER_SIZE);
98 fid = ixp_open(ixp->client, file, P9_OREAD);
99 if(fid == NULL)
100 return lixp_pusherror (L, "count not open p9 file");
102 buf_size = fid->iounit;
103 if (max_buffer_size && buf_size > max_buffer_size)
104 buf_size = max_buffer_size;
105 buf = malloc (buf_size);
106 if (!buf) {
107 ixp_close(fid);
108 return lixp_pusherror (L, "count not allocate memory");
110 buf_ofs = 0;
112 DBGF("** ixp.read (%s) **\n", file);
114 for (;;) {
115 int rc = ixp_read (fid, buf+buf_ofs, buf_size-buf_ofs);
116 if (rc==0) {
117 short_read = 0;
118 break;
120 } else if (rc<0) {
121 ixp_close(fid);
122 return lixp_pusherror (L, "failed to read from p9 file");
125 buf_ofs += rc;
127 if (buf_ofs > buf_size)
128 return lixp_pusherror (L, "internal error while reading");
130 if (buf_ofs == buf_size)
131 break;
133 if (max_buffer_size && buf_size >= max_buffer_size)
134 break;
136 realloc_size = max_buffer_size;
137 if (!max_buffer_size)
138 realloc_size = buf_size * 2;
140 _buf = NULL;
141 if (realloc_size > buf_size)
142 _buf = realloc (buf, realloc_size);
144 if (!_buf) {
145 ixp_close(fid);
146 free(buf);
147 return lixp_pusherrorf(L, "failed to allocate %u bytes",
148 realloc_size);
150 buf = _buf;
151 buf_size = realloc_size;
154 ixp_close(fid);
156 if (memchr(buf, '\0', buf_ofs))
157 fprintf(stderr, "** WARNING: ixp.read (%s): result contains null characters **\n", file);
159 lua_pushlstring(L, buf, buf_ofs);
160 lua_pushboolean(L, short_read);
161 return 2;
164 /* ------------------------------------------------------------------------
165 * lua: create(file, [data]) -- create a file, optionally write data to it
167 int l_ixp_create (lua_State *L)
169 struct ixp *ixp;
170 IxpCFid *fid;
171 const char *file;
172 const char *data;
173 size_t data_len = 0;
175 ixp = lixp_checkixp (L, 1);
176 file = luaL_checkstring (L, 2);
177 data = luaL_optlstring (L, 3, NULL, &data_len);
179 DBGF("** ixp.create (%s) **\n", file);
181 fid = ixp_create (ixp->client, file, 0777, P9_OWRITE);
182 if (!fid)
183 return lixp_pusherror (L, "count not create file");
185 if (data && data_len
186 && !(fid->qid.type & P9_DMDIR)) {
187 int rc = lixp_write_data (fid, data, data_len);
188 if (rc < 0) {
189 ixp_close(fid);
190 return lixp_pusherror (L, "failed to write to p9 file");
194 ixp_close(fid);
195 return 0;
198 /* ------------------------------------------------------------------------
199 * lua: remove(file) -- remove a file
201 int l_ixp_remove (lua_State *L)
203 struct ixp *ixp;
204 int rc;
205 const char *file;
207 ixp = lixp_checkixp (L, 1);
208 file = luaL_checkstring (L, 2);
210 DBGF("** ixp.remove (%s) **\n", file);
212 rc = ixp_remove (ixp->client, file);
213 if (!rc)
214 return lixp_pusherror (L, "failed to remove p9 file");
216 return 0;
219 /* ------------------------------------------------------------------------
220 * lua: itr = iread(file) -- returns a line iterator
223 struct l_ixp_iread_s {
224 IxpCFid *fid;
225 char *buf;
226 size_t buf_pos;
227 size_t buf_len;
228 size_t buf_size;
231 static int iread_iter (lua_State *L);
233 int l_ixp_iread (lua_State *L)
235 struct ixp *ixp;
236 const char *file;
237 struct l_ixp_iread_s *ctx;
239 ixp = lixp_checkixp (L, 1);
240 file = luaL_checkstring (L, 2);
242 ctx = (struct l_ixp_iread_s*)lua_newuserdata (L, sizeof(*ctx));
243 if (!ctx)
244 return lixp_pusherror (L, "count not allocate context");
245 memset (ctx, 0, sizeof (*ctx));
247 // set the metatable for the new userdata
248 luaL_getmetatable (L, L_IXP_IREAD_MT);
249 lua_setmetatable (L, -2);
251 ctx->fid = ixp_open(ixp->client, file, P9_OREAD);
252 if(ctx->fid == NULL) {
253 return lixp_pusherror (L, "count not open p9 file");
256 DBGF("** ixp.iread (%s) **\n", file);
258 // create and return the iterator function
259 // the only argument is the userdata
260 lua_pushcclosure (L, iread_iter, 1);
261 return 1;
264 static int iread_iter (lua_State *L)
266 struct l_ixp_iread_s *ctx;
267 char *s, *cr;
269 ctx = (struct l_ixp_iread_s*)lua_touserdata (L, lua_upvalueindex(1));
271 DBGF("** ixp.iread - iter **\n");
273 if (!ctx->buf) {
274 ctx->buf = malloc (ctx->fid->iounit);
275 if (!ctx->buf)
276 return lixp_pusherror (L, "count not allocate memory");
277 ctx->buf_size = ctx->fid->iounit;
278 ctx->buf_len = 0;
281 if (!ctx->buf_len) {
282 int rc;
283 ctx->buf_pos = 0;
284 rc = ixp_read (ctx->fid, ctx->buf, ctx->buf_size);
285 if (rc <= 0) {
286 return 0; // we are done
288 ctx->buf_len = rc;
291 s = ctx->buf + ctx->buf_pos;
293 cr = strchr (s, '\n');
294 if (!cr) {
295 // no match, just return the whole thing
296 // TODO: should read more upto a cr or some limit
297 if (memchr(s, '\0', ctx->buf_len))
298 fprintf(stderr, "** WARNING: ixp.iread - iter: result contains null characters **\n");
299 lua_pushlstring (L, s, ctx->buf_len);
300 ctx->buf_len = 0;
301 return 1;
303 } else {
304 // we have a match s..cr is our sub string
305 int len = cr-s;
306 if (memchr(s, '\0', len))
307 fprintf(stderr, "** WARNING: ixp.iread - iter: result contains null characters **\n");
308 lua_pushlstring (L, s, len);
309 len++;
310 ctx->buf_pos += len;
311 ctx->buf_len -= len;
312 return 1;
316 static int iread_gc (lua_State *L)
318 struct l_ixp_iread_s *ctx;
320 ctx = (struct l_ixp_iread_s*)lua_touserdata (L, 1);
322 DBGF("** ixp.iread - gc **\n");
324 ixp_close (ctx->fid);
326 if (ctx->buf)
327 free (ctx->buf);
329 return 0;
332 void lixp_init_iread_mt (lua_State *L)
334 luaL_newmetatable(L, L_IXP_IREAD_MT);
336 // setup the __gc field
337 lua_pushstring (L, "__gc");
338 lua_pushcfunction (L, iread_gc);
339 lua_settable (L, -3);
342 /* ------------------------------------------------------------------------
343 * lua: stat = stat(file) -- returns a status table
346 int l_ixp_stat (lua_State *L)
348 struct ixp *ixp;
349 struct IxpStat *stat;
350 const char *file;
351 int rc;
353 ixp = lixp_checkixp (L, 1);
354 file = luaL_checkstring (L, 2);
356 DBGF("** ixp.stat (%s) **\n", file);
358 stat = ixp_stat(ixp->client, file);
359 if(!stat)
360 return lixp_pusherror(L, "cannot stat file");
362 rc = lixp_pushstat (L, stat);
364 ixp_freestat (stat);
366 return rc;
369 /* ------------------------------------------------------------------------
370 * lua: itr = idir(dir) -- returns a file name iterator
373 struct l_ixp_idir_s {
374 IxpCFid *fid;
375 unsigned char *buf;
376 IxpMsg m;
379 static int idir_iter (lua_State *L);
381 int l_ixp_idir (lua_State *L)
383 struct ixp *ixp;
384 const char *file;
385 struct l_ixp_idir_s *ctx;
387 ixp = lixp_checkixp (L, 1);
388 file = luaL_checkstring (L, 2);
390 ctx = (struct l_ixp_idir_s*)lua_newuserdata (L, sizeof(*ctx));
391 if (!ctx)
392 return lixp_pusherror (L, "count not allocate context");
393 memset(ctx, 0, sizeof (*ctx));
395 // set the metatable for the new userdata
396 luaL_getmetatable (L, L_IXP_IDIR_MT);
397 lua_setmetatable (L, -2);
399 ctx->fid = ixp_open(ixp->client, file, P9_OREAD);
400 if(ctx->fid == NULL) {
401 return lixp_pusherror (L, "count not open p9 file");
404 ctx->buf = malloc (ctx->fid->iounit);
405 if (!ctx->buf) {
406 ixp_close (ctx->fid);
407 ctx->fid = NULL;
408 return lixp_pusherror (L, "count not allocate memory");
411 DBGF("** ixp.idir (%s) **\n", file);
413 // create and return the iterator function
414 // the only argument is the userdata
415 lua_pushcclosure (L, idir_iter, 1);
416 return 1;
419 static int idir_iter (lua_State *L)
421 struct l_ixp_idir_s *ctx;
422 IxpStat stat;
424 ctx = (struct l_ixp_idir_s*)lua_touserdata (L, lua_upvalueindex(1));
426 DBGF("** ixp.idir - iter **\n");
428 if (ctx->m.pos >= ctx->m.end) {
429 int rc = ixp_read (ctx->fid, ctx->buf, ctx->fid->iounit);
430 if (rc <= 0) {
431 return 0;
434 ctx->m = ixp_message(ctx->buf, rc, MsgUnpack);
435 if (ctx->m.pos >= ctx->m.end)
436 return 0;
439 ixp_pstat(&ctx->m, &stat);
441 return lixp_pushstat (L, &stat);
444 static int idir_gc (lua_State *L)
446 struct l_ixp_idir_s *ctx;
448 ctx = (struct l_ixp_idir_s*)lua_touserdata (L, 1);
450 DBGF("** ixp.idir - gc **\n");
452 free (ctx->buf);
454 ixp_close (ctx->fid);
456 return 0;
459 void lixp_init_idir_mt (lua_State *L)
461 luaL_newmetatable(L, L_IXP_IDIR_MT);
463 // setup the __gc field
464 lua_pushstring (L, "__gc");
465 lua_pushcfunction (L, idir_gc);
466 lua_settable (L, -3);