gateway: simplify stopping the cleanup timer
[olsrd.git] / lib / tas / src / glua.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon (olsrd)
4  *
5  * Copyright (c) 2004, Thomas Lopatic (thomas@olsr.org)
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  *   notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above copyright
15  *   notice, this list of conditions and the following disclaimer in
16  *   the documentation and/or other materials provided with the
17  *   distribution.
18  * * Neither the name of olsr.org, olsrd nor the names of its
19  *   contributors may be used to endorse or promote products derived
20  *   from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * Visit http://www.olsr.org for more information.
36  *
37  * If you find this software useful feel free to make a donation
38  * to the project. For more information see the website or contact
39  * the copyright holders.
40  *
41  */
42
43 #include "lua/lua.h"
44 #include "lua/lauxlib.h"
45 #include "lua/lualib.h"
46
47 #include "link.h"
48 #include "plugin.h"
49 #include "lib.h"
50 #include "os_unix.h"
51 #include "http.h"
52 #include "glua.h"
53 #include "glua_ext.h"
54
55 #include <stdio.h>
56 #include <string.h>
57
58 static const char infoKey;
59 static const char keepFlagKey;
60 static const char argListKey;
61
62 int
63 lspToLua(const char *rootDir, const char *lspFileName, const char *workDir, const char *luaFileName)
64 {
65   FILE *file;
66   int lspLen;
67   unsigned char *buff;
68   int start, code, i, k;
69   char *lspPath = fullPath(rootDir, lspFileName);
70   char *luaPath = fullPath(workDir, luaFileName);
71
72   if (fileIsNewer(lspPath, luaPath) == 0) {
73     freeMem(lspPath);
74     freeMem(luaPath);
75     return 0;
76   }
77
78   file = fopen(lspPath, "r");
79
80   if (file == NULL) {
81     error("cannot open %s\n", lspPath);
82     freeMem(lspPath);
83     freeMem(luaPath);
84     return -1;
85   }
86
87   if (fseek(file, 0, SEEK_END) < 0) {
88     error("cannot seek to end of %s\n", lspPath);
89     fclose(file);
90     freeMem(lspPath);
91     freeMem(luaPath);
92     return -1;
93   }
94
95   lspLen = ftell(file);
96
97   if (lspLen < 0) {
98     error("cannot determine length of %s\n", lspPath);
99     fclose(file);
100     freeMem(lspPath);
101     freeMem(luaPath);
102     return -1;
103   }
104
105   if (fseek(file, 0, SEEK_SET) < 0) {
106     error("cannot seek to beginning of %s\n", lspPath);
107     fclose(file);
108     freeMem(lspPath);
109     freeMem(luaPath);
110     return -1;
111   }
112
113   buff = allocMem(lspLen);
114
115   if (fread(buff, lspLen, 1, file) != 1) {
116     error("cannot read %s\n", lspPath);
117     fclose(file);
118     freeMem(lspPath);
119     freeMem(luaPath);
120     freeMem(buff);
121     return -1;
122   }
123
124   fclose(file);
125
126   if (createAllDirs(luaPath) < 0) {
127     error("cannot create required directories for %s\n", luaPath);
128     freeMem(lspPath);
129     freeMem(luaPath);
130     freeMem(buff);
131     return -1;
132   }
133
134   file = fopen(luaPath, "w");
135
136   if (file == NULL) {
137     error("cannot open %s\n", luaPath);
138     freeMem(lspPath);
139     freeMem(luaPath);
140     freeMem(buff);
141     return -1;
142   }
143
144   start = 0;
145   code = 0;
146
147   i = 0;
148
149   for (;;) {
150     if (code == 0 && (i == lspLen || strncmp((char *)(buff + i), "<?lua", 5) == 0)) {
151       fprintf(file, "tas.write(\"");
152
153       for (k = start; k < i; k++) {
154         if (buff[k] == 13)
155           continue;
156
157         if (buff[k] == '\\' || buff[k] == '"' || buff[k] == 10)
158           fputc('\\', file);
159
160         fputc(buff[k], file);
161       }
162
163       fprintf(file, "\")\n");
164
165       if (i == lspLen)
166         break;
167
168       if (buff[i + 5] == '=') {
169         i += 6;
170         code = 2;
171       }
172
173       else {
174         i += 5;
175         code = 1;
176       }
177
178       start = i;
179
180       continue;
181     }
182
183     if (code > 0 && (i == lspLen || strncmp((char *)(buff + i), "?>", 2) == 0)) {
184       if (code > 1)
185         fprintf(file, "tas.write(");
186
187       for (k = start; k < i; k++)
188         if (buff[k] != 13)
189           fputc(buff[k], file);
190
191       if (code > 1)
192         fputc(')', file);
193
194       fputc('\n', file);
195
196       if (i == lspLen)
197         break;
198
199       i += 2;
200       start = i;
201
202       code = 0;
203
204       continue;
205     }
206
207     i++;
208   }
209
210   fclose(file);
211   freeMem(lspPath);
212   freeMem(luaPath);
213   freeMem(buff);
214   return 0;
215 }
216
217 static int
218 luaWriter(lua_State * lua __attribute__ ((unused)), const void *buff, int len, FILE * file)
219 {
220   return fwrite(buff, len, 1, file) == 1;
221 }
222
223 int
224 luaToLex(char **errMsg, const char *workDir, const char *luaFileName, const char *lexFileName)
225 {
226   lua_State *lua;
227   int res;
228   FILE *file;
229   char *luaPath = fullPath(workDir, luaFileName);
230   char *lexPath = fullPath(workDir, lexFileName);
231
232   *errMsg = NULL;
233
234   if (fileIsNewer(luaPath, lexPath) == 0) {
235     freeMem(luaPath);
236     freeMem(lexPath);
237     return 0;
238   }
239
240   lua = lua_open();
241
242   res = luaL_loadfile(lua, luaPath);
243
244   if (res != 0) {
245     *errMsg = myStrdup(lua_tostring(lua, -1));
246     error("cannot load %s: %s\n", luaPath, *errMsg);
247     lua_close(lua);
248     freeMem(luaPath);
249     freeMem(lexPath);
250     return -1;
251   }
252
253   file = fopen(lexPath, "wb");
254
255   if (file == NULL) {
256     error("cannot open %s\n", lexPath);
257     lua_close(lua);
258     freeMem(luaPath);
259     freeMem(lexPath);
260     return -1;
261   }
262
263   lua_dump(lua, (lua_Chunkwriter) luaWriter, file);
264
265   fclose(file);
266
267   lua_close(lua);
268   freeMem(luaPath);
269   freeMem(lexPath);
270   return 0;
271 }
272
273 static int
274 tasWrite(lua_State * lua)
275 {
276   int numArg = lua_gettop(lua);
277   const char *strConv;
278   int i;
279   struct connInfo *info;
280
281   lua_pushlightuserdata(lua, &infoKey);
282   lua_gettable(lua, LUA_REGISTRYINDEX);
283
284   info = lua_touserdata(lua, -1);
285
286   lua_getglobal(lua, "tostring");
287
288   for (i = 1; i <= numArg; i++) {
289     lua_pushvalue(lua, -1);
290     lua_pushvalue(lua, i);
291
292     lua_call(lua, 1, 1);
293
294     strConv = lua_tostring(lua, -1);
295
296     if (strConv == NULL)
297       return luaL_error(lua, "cannot convert value to string");
298
299     writeBuff(&info->write[2], (const unsigned char *)strConv, strlen(strConv));
300
301     lua_pop(lua, 1);
302   }
303
304   return 0;
305 }
306
307 static int
308 tasAddHeaderLine(lua_State * lua)
309 {
310   struct connInfo *info;
311   char *line;
312
313   lua_pushlightuserdata(lua, &infoKey);
314   lua_gettable(lua, LUA_REGISTRYINDEX);
315
316   info = lua_touserdata(lua, -1);
317
318   line = myStrdup(luaL_checkstring(lua, 1));
319
320   chomp(line, strlen(line));
321
322   writeBuff(&info->write[1], (const unsigned char *)line, strlen(line));
323   writeBuff(&info->write[1], (const unsigned char *)"\r\n", 2);
324
325   freeMem(line);
326
327   return 0;
328 }
329
330 static int
331 tasSetContentType(lua_State * lua)
332 {
333   struct connInfo *info;
334   const char *contType;
335   char *s;
336
337   lua_pushlightuserdata(lua, &infoKey);
338   lua_gettable(lua, LUA_REGISTRYINDEX);
339
340   info = lua_touserdata(lua, -1);
341
342   contType = luaL_checkstring(lua, 1);
343
344   s = allocBuff(info, strlen(contType) + 1);
345   strcpy(s, contType);
346
347   return 0;
348 }
349
350 static int
351 tasKeepState(lua_State * lua)
352 {
353   int *keepFlag;
354
355   lua_pushlightuserdata(lua, &keepFlagKey);
356   lua_gettable(lua, LUA_REGISTRYINDEX);
357
358   keepFlag = lua_touserdata(lua, -1);
359
360   *keepFlag = 1;
361
362   return 0;
363 }
364
365 static int
366 tasGetParameters(lua_State * lua)
367 {
368   int i;
369   char **argList;
370
371   lua_pushlightuserdata(lua, &argListKey);
372   lua_gettable(lua, LUA_REGISTRYINDEX);
373
374   argList = lua_touserdata(lua, -1);
375
376   lua_newtable(lua);
377
378   if (argList == NULL)
379     return 1;
380
381   for (i = 0; argList[i] != NULL; i += 2) {
382     lua_pushstring(lua, argList[i]);
383     lua_pushstring(lua, argList[i + 1]);
384     lua_settable(lua, -3);
385   }
386
387   return 1;
388 }
389
390 static const struct luaL_reg tasLib[] = {
391   {"write", tasWrite},
392   {"set_content_type", tasSetContentType},
393   {"add_header_line", tasAddHeaderLine},
394   {"keep_state", tasKeepState},
395   {"get_parameters", tasGetParameters},
396 #ifdef TAS_EXTRA_FUNCTIONS
397   TAS_EXTRA_FUNCTIONS
398 #endif /* TAS_EXTRA_FUNCTIONS */
399   {NULL, NULL}
400 };
401
402 static int
403 luaopen_tas(lua_State * lua)
404 {
405   luaL_openlib(lua, "tas", tasLib, 0);
406   return 1;
407 }
408
409 int
410 runLua(char **errMsg, struct connInfo *info, const char *workDir, const char *lexFileName, char **argList, void **session)
411 {
412   lua_State *lua;
413   int res;
414   char *lexPath = fullPath(workDir, lexFileName);
415   int keepFlag = 0;
416
417   *errMsg = NULL;
418
419   if (*session == NULL) {
420     lua = lua_open();
421
422     luaopen_base(lua);
423     luaopen_table(lua);
424     luaopen_io(lua);
425     luaopen_string(lua);
426     luaopen_math(lua);
427     luaopen_debug(lua);
428     luaopen_loadlib(lua);
429
430     luaopen_tas(lua);
431   }
432
433   else
434     lua = *session;
435
436   lua_pushlightuserdata(lua, &infoKey);
437   lua_pushlightuserdata(lua, info);
438   lua_settable(lua, LUA_REGISTRYINDEX);
439
440   lua_pushlightuserdata(lua, &argListKey);
441   lua_pushlightuserdata(lua, argList);
442   lua_settable(lua, LUA_REGISTRYINDEX);
443
444   lua_pushlightuserdata(lua, &keepFlagKey);
445   lua_pushlightuserdata(lua, &keepFlag);
446   lua_settable(lua, LUA_REGISTRYINDEX);
447
448   res = luaL_loadfile(lua, lexPath);
449
450   if (res != 0) {
451     *errMsg = myStrdup(lua_tostring(lua, -1));
452     error("cannot load %s: %s\n", lexPath, *errMsg);
453     lua_close(lua);
454     freeMem(lexPath);
455     return -1;
456   }
457
458   res = lua_pcall(lua, 0, 0, 0);
459
460   if (res != 0) {
461     *errMsg = myStrdup(lua_tostring(lua, -1));
462     error("cannot run %s: %s\n", lexPath, *errMsg);
463     lua_close(lua);
464     freeMem(lexPath);
465     return -1;
466   }
467
468   if (keepFlag == 0) {
469     lua_close(lua);
470     *session = NULL;
471   }
472
473   else
474     *session = lua;
475
476   freeMem(lexPath);
477   return 0;
478 }
479
480 void
481 freeLuaSession(void *session)
482 {
483   lua_close(session);
484 }
485
486 /*
487  * Local Variables:
488  * c-basic-offset: 2
489  * indent-tabs-mode: nil
490  * End:
491  */