HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / wslua / wslua_util.c
blob50d3e04f584d13a39f2bb15a68452f3f8aa2384c
1 /*
2 * wslua_util.c
4 * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org>
6 * $Id$
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "config.h"
29 /* WSLUA_MODULE Utility Utility Functions */
31 #include "wslua.h"
32 #include <math.h>
33 #include <epan/stat_cmd_args.h>
35 WSLUA_API gboolean wslua_optbool(lua_State* L, int n, gboolean def) {
36 gboolean val = FALSE;
38 if ( lua_isboolean(L,n) ) {
39 val = lua_toboolean(L,n);
40 } else if ( lua_isnil(L,n) || lua_gettop(L) < n ){
41 val = def;
42 } else {
43 luaL_argerror(L,n,"must be a boolean");
46 return val;
50 WSLUA_API const gchar* lua_shiftstring(lua_State* L, int i) {
51 const gchar* p = luaL_checkstring(L, i);
53 if (p) {
54 lua_remove(L,i);
55 return p;
56 } else {
57 return NULL;
61 /* following is based on the luaL_setfuncs() from Lua 5.2, so we can use it in pre-5.2 */
62 WSLUA_API void wslua_setfuncs(lua_State *L, const luaL_Reg *l, int nup) {
63 luaL_checkstack(L, nup, "too many upvalues");
64 for (; l->name != NULL; l++) { /* fill the table with given functions */
65 int i;
66 for (i = 0; i < nup; i++) /* copy upvalues to the top */
67 lua_pushvalue(L, -nup);
68 lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
69 lua_setfield(L, -(nup + 2), l->name);
71 lua_pop(L, nup); /* remove upvalues */
74 WSLUA_FUNCTION wslua_get_version(lua_State* L) { /* Get Wireshark version */
75 const gchar* str = VERSION;
76 lua_pushstring(L,str);
77 WSLUA_RETURN(1); /* version string */
80 WSLUA_FUNCTION wslua_format_date(lua_State* LS) { /* Formats an absolute timestamp into a human readable date */
81 #define WSLUA_ARG_format_date_TIMESTAMP 1 /* A timestamp value to convert. */
82 lua_Number timestamp = luaL_checknumber(LS,WSLUA_ARG_format_date_TIMESTAMP);
83 nstime_t then;
84 gchar* str;
86 then.secs = (guint32)floor(timestamp);
87 then.nsecs = (guint32) ( (timestamp-(double)(then.secs))*1000000000);
88 str = abs_time_to_str(&then, ABSOLUTE_TIME_LOCAL, TRUE);
89 lua_pushstring(LS,str);
91 WSLUA_RETURN(1); /* A string with the formated date */
94 WSLUA_FUNCTION wslua_format_time(lua_State* LS) { /* Formats a relative timestamp in a human readable form */
95 #define WSLUA_ARG_format_time_TIMESTAMP 1 /* A timestamp value to convert */
96 lua_Number timestamp = luaL_checknumber(LS,WSLUA_ARG_format_time_TIMESTAMP);
97 nstime_t then;
98 gchar* str;
100 then.secs = (guint32)floor(timestamp);
101 then.nsecs = (guint32) ( (timestamp-(double)(then.secs))*1000000000);
102 str = rel_time_to_str(&then);
103 lua_pushstring(LS,str);
105 WSLUA_RETURN(1); /* A string with the formated time */
108 WSLUA_FUNCTION wslua_report_failure(lua_State* LS) { /* Reports a failure to the user */
109 #define WSLUA_ARG_report_failure_TEXT 1 /* Message */
110 const gchar* s = luaL_checkstring(LS,WSLUA_ARG_report_failure_TEXT);
111 report_failure("%s",s);
112 return 0;
115 static int wslua_log(lua_State* L, GLogLevelFlags log_level) {
116 GString* str = g_string_new("");
117 int n = lua_gettop(L); /* Number of arguments */
118 int i;
120 lua_getglobal(L, "tostring");
121 for (i=1; i<=n; i++) {
122 const char *s;
123 lua_pushvalue(L, -1); /* function to be called */
124 lua_pushvalue(L, i); /* value to print */
125 lua_call(L, 1, 1);
126 s = lua_tostring(L, -1); /* get result */
127 if (s == NULL)
128 return luaL_error(L, "`tostring' must return a string");
130 if (i>1) g_string_append(str,"\t");
131 g_string_append(str,s);
133 lua_pop(L, 1); /* pop result */
136 g_log(LOG_DOMAIN_LUA, log_level, "%s\n", str->str);
137 g_string_free(str,TRUE);
139 return 0;
142 WSLUA_FUNCTION wslua_critical( lua_State* L ) { /* Will add a log entry with critical severity*/
143 /* WSLUA_MOREARGS critical objects to be printed */
144 wslua_log(L,G_LOG_LEVEL_CRITICAL);
145 return 0;
147 WSLUA_FUNCTION wslua_warn( lua_State* L ) { /* Will add a log entry with warn severity */
148 /* WSLUA_MOREARGS warn objects to be printed */
149 wslua_log(L,G_LOG_LEVEL_WARNING);
150 return 0;
152 WSLUA_FUNCTION wslua_message( lua_State* L ) { /* Will add a log entry with message severity */
153 /* WSLUA_MOREARGS message objects to be printed */
154 wslua_log(L,G_LOG_LEVEL_MESSAGE);
155 return 0;
157 WSLUA_FUNCTION wslua_info( lua_State* L ) { /* Will add a log entry with info severity */
158 /* WSLUA_MOREARGS info objects to be printed */
159 wslua_log(L,G_LOG_LEVEL_INFO);
160 return 0;
162 WSLUA_FUNCTION wslua_debug( lua_State* L ) { /* Will add a log entry with debug severity */
163 /* WSLUA_MOREARGS debug objects to be printed */
164 wslua_log(L,G_LOG_LEVEL_DEBUG);
165 return 0;
168 /* The returned filename is g_malloc()'d so the caller must free it */
169 /* except when NULL is returned if file doesn't exist */
170 static char* wslua_get_actual_filename(const char* fname) {
171 char fname_clean[256];
172 char* f;
173 char* filename;
175 g_strlcpy(fname_clean,fname,255);
176 fname_clean[255] = '\0';
178 for(f = fname_clean; *f; f++) {
179 switch(*f) {
180 case '/': case '\\':
181 *f = *(G_DIR_SEPARATOR_S);
182 break;
183 default:
184 break;
188 if ( file_exists(fname_clean) ) {
189 return g_strdup(fname_clean);
192 filename = get_persconffile_path(fname_clean,FALSE);
194 if ( file_exists(filename) ) {
195 return filename;
197 g_free(filename);
199 filename = get_datafile_path(fname_clean);
200 if ( file_exists(filename) ) {
201 return filename;
203 g_free(filename);
205 return NULL;
208 WSLUA_FUNCTION wslua_loadfile(lua_State* L) {
209 /* Lua's loadfile() has been modified so that if a file does not exist
210 in the current directory it will look for it in wireshark's user and system directories */
211 #define WSLUA_ARG_loadfile_FILENAME 1 /* Name of the file to be loaded */
212 const char *given_fname = luaL_checkstring(L, WSLUA_ARG_loadfile_FILENAME);
213 char* filename;
215 filename = wslua_get_actual_filename(given_fname);
217 if (!filename) WSLUA_ARG_ERROR(loadfile,FILENAME,"file does not exist");
219 if (luaL_loadfile(L, filename) == 0) {
220 g_free(filename);
221 return 1;
222 } else {
223 g_free(filename);
224 lua_pushnil(L);
225 lua_insert(L, -2);
226 return 2;
230 WSLUA_FUNCTION wslua_dofile(lua_State* L) {
231 /* Lua's dofile() has been modified so that if a file does not exist
232 in the current directory it will look for it in wireshark's user and system directories */
233 #define WSLUA_ARG_dofile_FILENAME 1 /* Name of the file to be run */
234 const char *given_fname = luaL_checkstring(L, WSLUA_ARG_dofile_FILENAME);
235 char* filename;
236 int n;
238 if (!given_fname) WSLUA_ARG_ERROR(dofile,FILENAME,"must be a string");
240 filename = wslua_get_actual_filename(given_fname);
242 if (!filename) WSLUA_ARG_ERROR(dofile,FILENAME,"file does not exist");
244 n = lua_gettop(L);
245 if (luaL_loadfile(L, filename) != 0) lua_error(L);
246 g_free(filename);
247 lua_call(L, 0, LUA_MULTRET);
248 return lua_gettop(L) - n;
252 WSLUA_FUNCTION wslua_persconffile_path(lua_State* L) {
253 #define WSLUA_OPTARG_persconffile_path_FILENAME 1 /* A filename */
254 const char *fname = luaL_optstring(L, WSLUA_OPTARG_persconffile_path_FILENAME,"");
255 char* filename = get_persconffile_path(fname,FALSE);
257 lua_pushstring(L,filename);
258 g_free(filename);
259 WSLUA_RETURN(1); /* The full pathname for a file in the personal configuration directory */
262 WSLUA_FUNCTION wslua_datafile_path(lua_State* L) {
263 #define WSLUA_OPTARG_datafile_path_FILENAME 1 /* A filename */
264 const char *fname = luaL_optstring(L, WSLUA_OPTARG_datafile_path_FILENAME,"");
265 char* filename = get_datafile_path(fname);
267 lua_pushstring(L,filename);
268 g_free(filename);
269 WSLUA_RETURN(1); /* The full pathname for a file in wireshark's configuration directory */
273 WSLUA_CLASS_DEFINE(Dir,NOP,NOP); /* A Directory */
275 WSLUA_CONSTRUCTOR Dir_open(lua_State* L) {
276 /* Usage: for filename in Dir.open(path) do ... end */
277 #define WSLUA_ARG_Dir_open_PATHNAME 1 /* The pathname of the directory */
278 #define WSLUA_OPTARG_Dir_open_EXTENSION 2 /* If given, only file with this extension will be returned */
280 const char* dirname = luaL_checkstring(L,WSLUA_ARG_Dir_open_PATHNAME);
281 const char* extension = luaL_optstring(L,WSLUA_OPTARG_Dir_open_EXTENSION,NULL);
282 Dir dir;
283 char* dirname_clean;
285 if (!dirname) WSLUA_ARG_ERROR(Dir_open,PATHNAME,"must be a string");
287 dirname_clean = wslua_get_actual_filename(dirname);
288 if (!dirname_clean) WSLUA_ARG_ERROR(Dir_open,PATHNAME,"directory does not exist");
290 if (!test_for_directory(dirname_clean)) {
291 g_free(dirname_clean);
292 WSLUA_ARG_ERROR(Dir_open,PATHNAME, "must be a directory");
295 dir = (Dir)g_malloc(sizeof(struct _wslua_dir));
296 dir->dir = OPENDIR_OP(dirname_clean);
297 g_free(dirname_clean);
298 dir->ext = extension ? g_strdup(extension) : NULL;
299 dir->dummy = (GError **)g_malloc(sizeof(GError *));
300 *(dir->dummy) = NULL;
302 if (dir->dir == NULL) {
303 g_free(dir->dummy);
304 g_free(dir);
306 WSLUA_ARG_ERROR(Dir_open,PATHNAME,"could not open directory");
309 pushDir(L,dir);
310 WSLUA_RETURN(1); /* the Dir object */
313 WSLUA_METAMETHOD Dir__call(lua_State* L) {
314 /* At every invocation will return one file (nil when done) */
316 Dir dir = checkDir(L,1);
317 const FILE_T* file;
318 const gchar* filename;
319 const char* ext;
321 if (!dir) {
322 luaL_argerror(L,1,"must be a Dir");
323 return 0;
326 if (!dir->dir) {
327 return 0;
330 if ( ! ( file = DIRGETNEXT_OP(dir->dir ) )) {
331 CLOSEDIR_OP(dir->dir);
332 dir->dir = NULL;
333 return 0;
337 if ( ! dir->ext ) {
338 filename = GETFNAME_OP(file);
339 lua_pushstring(L,filename);
340 return 1;
343 do {
344 filename = GETFNAME_OP(file);
346 /* XXX strstr returns ptr to first match,
347 this fails ext=".xxx" filename="aaa.xxxz.xxx" */
348 if ( ( ext = strstr(filename,dir->ext)) && g_str_equal(ext,dir->ext) ) {
349 lua_pushstring(L,filename);
350 return 1;
352 } while(( file = DIRGETNEXT_OP(dir->dir) ));
354 CLOSEDIR_OP(dir->dir);
355 dir->dir = NULL;
356 return 0;
359 WSLUA_METHOD Dir_close(lua_State* L) {
360 /* Closes the directory */
361 Dir dir = checkDir(L,1);
363 if (dir->dir) {
364 CLOSEDIR_OP(dir->dir);
365 dir->dir = NULL;
368 return 0;
371 /* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
372 static int Dir__gc(lua_State* L) {
373 Dir dir = checkDir(L,1);
375 if (dir->dir) {
376 CLOSEDIR_OP(dir->dir);
379 g_free(dir->dummy);
381 if (dir->ext) g_free(dir->ext);
383 g_free(dir);
385 return 0;
388 static const luaL_Reg Dir_methods[] = {
389 {"open", Dir_open},
390 {"close", Dir_close},
391 { NULL, NULL }
394 static const luaL_Reg Dir_meta[] = {
395 {"__call", Dir__call},
396 { NULL, NULL }
399 int Dir_register(lua_State* L) {
401 WSLUA_REGISTER_CLASS(Dir);
403 return 1;
407 typedef struct _statcmd_t {
408 lua_State* L;
409 int func_ref;
410 } statcmd_t;
412 static int statcmd_init_cb_error_handler(lua_State* L _U_) {
413 return 0;
416 static void statcmd_init(const char *opt_arg, void* userdata) {
417 statcmd_t* sc = (statcmd_t *)userdata;
418 lua_State* L = sc->L;
420 lua_settop(L,0);
421 lua_pushcfunction(L,statcmd_init_cb_error_handler);
422 lua_rawgeti(L, LUA_REGISTRYINDEX, sc->func_ref);
424 lua_pushstring(L,opt_arg);
426 switch ( lua_pcall(L,1,0,1) ) {
427 case 0:
428 break;
429 case LUA_ERRRUN:
430 g_warning("Runtime error while calling statcmd callback");
431 break;
432 case LUA_ERRMEM:
433 g_warning("Memory alloc error while calling statcmd callback");
434 break;
435 default:
436 g_assert_not_reached();
437 break;
442 WSLUA_FUNCTION wslua_register_stat_cmd_arg(lua_State* L) {
443 /* Register a function to handle a -z option */
444 #define WSLUA_ARG_register_stat_cmd_arg_ARGUMENT 1 /* Argument */
445 #define WSLUA_OPTARG_register_stat_cmd_arg_ACTION 2 /* Action */
446 const char* arg = luaL_checkstring(L,WSLUA_ARG_register_stat_cmd_arg_ARGUMENT);
447 statcmd_t* sc = (statcmd_t *)g_malloc0(sizeof(statcmd_t)); /* XXX leaked */
449 sc->L = L;
450 lua_pushvalue(L, WSLUA_OPTARG_register_stat_cmd_arg_ACTION);
451 sc->func_ref = luaL_ref(L, LUA_REGISTRYINDEX);
452 lua_remove(L,1);
454 register_stat_cmd_arg(arg, statcmd_init, sc);
455 return 0;