294aa89376a0ac8abba4e752d55dba05ca717bab
[collectd.git] / src / lua.c
1 /**
2  * collectd - src/lua.c
3  * Copyright (C) 2010       Julien Ammous
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation; only version 2.1 of the License is
8  * applicable.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  *
19  * Authors:
20  *   Julien Ammous
21  **/
22
23 #include <unistd.h> // access
24
25 /* Include the Lua API header files. */
26 #define lua_c
27 #include <lua.h>
28 #include <lauxlib.h>
29 #include <lualib.h>
30
31 #include "collectd.h"
32 #include "plugin.h"
33 #include "common.h"
34 #include "configfile.h"
35 #include "utils_cache.h"
36
37 #include "lua_exports.c"
38
39 typedef struct lua_script_s {
40   char          *script_path;
41   lua_State     *lua_state;
42   
43   struct lua_script_s  *next;
44 } lua_script_t;
45
46
47 static char           base_path[MAXPATHLEN];
48 static lua_script_t   scripts;
49
50
51
52 /* Declare the Lua libraries we wish to use. */
53 /* Note: If you are opening and running a file containing Lua code */
54 /* using 'lua_dofile(l, "myfile.lua") - you must delcare all the libraries */
55 /* used in that file here also. */
56 static const luaL_reg lualibs[] =
57 {
58         // { "base",       luaopen_base },
59         { NULL,         NULL }
60 };
61
62 /* A function to open up all the Lua libraries you declared above. */
63 static void openlualibs(lua_State *l)
64 {
65   const luaL_reg *lib;
66   for( lib = lualibs; lib->func != NULL; lib++) {
67     lib->func(l);
68     lua_settop(l, 0);
69   }
70 }
71
72
73
74
75
76 static int lua_config_base_path (const oconfig_item_t *ci)
77 {
78   if( (ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING) ){
79     ERROR("lua plugin: The '%s' config option requires a single string argument", ci->key);
80     return -1;
81   }
82   
83   strncpy(base_path, ci->values[0].value.string, sizeof(base_path));
84   
85   /* add ending slash if not provided */
86   if( base_path[strlen(base_path) - 1] != '/' ){
87     base_path[strlen(base_path)] = '/';
88   }
89   
90   INFO("lua plugin: BasePath = '%s'", base_path);
91   return 0;
92 }
93
94 static int lua_config_script (const oconfig_item_t *ci)
95 {
96   lua_script_t *script = &scripts;
97   
98   if( (ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING) ){
99     ERROR("lua plugin: The '%s' config option requires a single string argument", ci->key);
100     return -1;
101   }
102   
103   /* find a free slot for the structure */
104   while( script->next != NULL ){
105     script = script->next;
106   }
107   
108   /* build full path : base_path + given path + \0 */
109   script->script_path = malloc(
110       strlen(base_path) +
111       strlen(ci->values[0].value.string) + 1
112     );
113   
114   strncpy(script->script_path, base_path, sizeof(script->script_path));
115   strncpy(script->script_path + strlen(base_path), ci->values[0].value.string, sizeof(script->script_path));
116   
117   /* check if the file exists and we can read it */
118   if( access(script->script_path, R_OK) == -1 ) {
119     ERROR("lua plugin: Cannot read file '%s' : %s", script->script_path, strerror(errno));
120     free(script->script_path);
121     return -1;
122   }
123   
124   /* initialize the lua context */
125   script->lua_state = lua_open();
126   
127   openlualibs(script->lua_state);
128   
129   if( register_exported_functions(script->lua_state) != 0 ) {
130     ERROR("lua plugin: Cannot register exported functions, aborting");
131     free(script->script_path);
132     return -1;
133   }
134   
135   /* and try to load the file */
136   if( luaL_dofile(script->lua_state, "script.lua") != 0 ) {
137     ERROR("lua plugin: error while loading '%s' => %s\n", script->script_path, lua_tostring(script->lua_state, -1));
138     free(script->script_path);
139     return -1;
140   }
141   
142   INFO("lua plugin: file '%s' loaded succesfully", script->script_path);
143   
144   return 0;
145 }
146
147 // <Plugin lua>
148 //   BasePath /
149 //   Script script1.lua
150 //   Script script2.lua
151 // </Plugin>
152 static int lua_config(oconfig_item_t *ci)
153 {
154   int i;
155
156   for (i = 0; i < ci->children_num; i++)
157   {
158     oconfig_item_t *child = ci->children + i;
159
160     if (strcasecmp ("BasePath", child->key) == 0) {
161       lua_config_base_path(child);
162     }
163     else if (strcasecmp ("Script", child->key) == 0){
164       lua_config_script(child);
165     }
166     else
167     {
168       WARNING ("network plugin: Option `%s' is not allowed here.",
169           child->key);
170     }
171   }
172   
173   return 0;
174 }
175
176 static int lua_init()
177 {
178   INFO("Lua plugin loaded.");
179   
180   return 0;
181 }
182
183 void module_register()
184 {
185   plugin_register_complex_config("lua", lua_config);
186   plugin_register_init("lua", lua_init);
187 }
188
189
190