The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
util.c
Go to the documentation of this file.
1/*
2 * This program is is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2 if the
4 * License as published by the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
14 */
15
16/**
17 * $Id: 3ed156b6f79b98de009580e053786a0dc09488d9 $
18 * @file rlm_lua/util.c
19 * @brief Helper Lua land functions.
20 *
21 * @author Arran Cudbard-Bell (a.cudbardb@freeradius.org)
22 *
23 * @copyright 2013 The FreeRADIUS Server Project.
24 */
25RCSID("$Id: 3ed156b6f79b98de009580e053786a0dc09488d9 $")
26
27#define LOG_PREFIX fr_lua_mctx->mi->name
28
29#include <freeradius-devel/server/base.h>
30
31#include "config.h"
32#include "lua.h"
33
34#include <lauxlib.h>
35#include <lualib.h>
36
37static _Thread_local request_t *fr_lua_request;
38static _Thread_local module_ctx_t const *fr_lua_mctx;
39
40void fr_lua_util_fr_register(lua_State *L)
41{
42 /* fr.{} */
43 lua_newtable(L);
44 lua_setglobal(L, "fr");
45 lua_settop(L, 0);
46}
47
48/** Lua function to output debug messages
49 *
50 * Lua arguments are one or more strings. Each successive argument will be printed on a new line.
51 *
52 * @param L Lua interpreter.
53 * @return 0 (no arguments)
54 */
55static int _util_log_debug(lua_State *L)
56{
57 request_t *request = fr_lua_request;
58 int idx;
59
60 while ((idx = lua_gettop(L))) {
61 char const *msg = lua_tostring(L, idx);
62 lua_pop(L, 1);
63 if (!msg) continue;
64
65 ROPTIONAL(RDEBUG2, DEBUG2, "%s", msg);
66 }
67
68 return 0;
69}
70
71/** Lua function to output informational messages
72 *
73 * Lua arguments are one or more strings. Each successive argument will be printed on a new line.
74 *
75 * @param L Lua interpreter.
76 * @return 0 (no arguments)
77 */
78static int _util_log_info(lua_State *L)
79{
80 request_t *request = fr_lua_request;
81 int idx;
82
83 while ((idx = lua_gettop(L))) {
84 char const *msg = lua_tostring(L, idx);
85 lua_pop(L, 1);
86 if (!msg) continue;
87
88 ROPTIONAL(RINFO, INFO, "%s", msg);
89 }
90
91 return 0;
92}
93
94
95/** Lua function to output warning messages
96 *
97 * Lua arguments are one or more strings. Each successive argument will be printed on a new line.
98 *
99 * @param L Lua interpreter.
100 * @return 0 (no arguments)
101 */
102static int _util_log_warn(lua_State *L)
103{
104 request_t *request = fr_lua_request;
105 int idx;
106
107 while ((idx = lua_gettop(L))) {
108 char const *msg = lua_tostring(L, idx);
109 lua_pop(L, 1);
110 if (!msg) continue;
111
112 ROPTIONAL(RWARN, WARN, "%s", msg);
113 }
114
115 return 0;
116}
117
118/** Lua function to output error messages.
119 *
120 * Lua arguments are one or more strings. Each successive argument will be printed on a new line.
121 *
122 * @param L Lua interpreter.
123 * @return 0 (no arguments)
124 */
125static int _util_log_error(lua_State *L)
126{
127 request_t *request = fr_lua_request;
128 int idx;
129
130 while ((idx = lua_gettop(L))) {
131 char const *msg = lua_tostring(L, idx);
132 lua_pop(L, 1);
133 if (!msg) continue;
134
135 ROPTIONAL(RERROR, ERROR, "%s", msg);
136 }
137
138 return 0;
139}
140
141static int _util_log_newindex(UNUSED lua_State *L)
142{
144
145 RWDEBUG("fr.log.$func() is read-only");
146
147 return 1;
148}
149
150/** Emit a debug log message
151 *
152 * @param msg to be printed.
153 */
155{
156 request_t *request = fr_lua_request;
157
158 ROPTIONAL(RDEBUG2, DEBUG2, "%s", msg);
159}
160
161/** Emit an info log message
162 *
163 * @param msg to be printed.
164 */
166{
167 request_t *request = fr_lua_request;
168
169 ROPTIONAL(RINFO, INFO, "%s", msg);
170}
171
172/** Emit a warning log message
173 *
174 * @param msg to be printed.
175 */
177{
178 request_t *request = fr_lua_request;
179
180 ROPTIONAL(RWARN, WARN, "%s", msg);
181}
182
183/** Emit a error log message
184 *
185 * @param msg to be printed.
186 */
188{
189 request_t *request = fr_lua_request;
190
191 ROPTIONAL(RERROR, ERROR, "%s", msg);
192}
193
194/** Insert cdefs into the lua environment
195 *
196 * For LuaJIT using the FFI is significantly faster than the Lua interface.
197 * Help people wishing to use the FFI by inserting cdefs for standard functions.
198 *
199 * @param L Lua interpreter.
200 * @return 0 (no arguments).
201 */
203{
204 char const *search_path;
205 char *lua_str, *ctx = NULL;
206 int ret;
207
209
210 search_path = dl_module_search_path();
211
212 /*
213 * If the search path contains multiple directories find where the library is.
214 */
215 if (strchr(search_path, ':')) {
216 char *paths, *path, *file, *p;
217 ctx = paths = talloc_typed_strdup(NULL, search_path);
218 while ((path = strsep(&paths, ":")) != NULL) {
219 p = strrchr(path, '/');
220 if (p && ((p[1] == '\0') || (p[1] == ':'))) *p = '\0';
221 file = talloc_typed_asprintf(ctx, "%s%clibfreeradius-lua%s", path, FR_DIR_SEP, DL_EXTENSION);
222 if (access(file, F_OK) == 0) {
223 search_path = path;
224 break;
225 }
226 }
227 }
228
229 lua_str = talloc_asprintf(NULL, "\
230 ffi = require(\"ffi\")\
231 ffi.cdef [[\
232 void fr_lua_util_jit_log_debug(char const *msg);\
233 void fr_lua_util_jit_log_info(char const *msg);\
234 void fr_lua_util_jit_log_warn(char const *msg);\
235 void fr_lua_util_jit_log_error(char const *msg);\
236 ]]\
237 fr_lua = ffi.load(\"%s%clibfreeradius-lua%s\")\
238 _fr_log = {}\
239 _fr_log.debug = function(msg)\
240 fr_lua.fr_lua_util_jit_log_debug(msg)\
241 end\
242 _fr_log.info = function(msg)\
243 fr_lua.fr_lua_util_jit_log_info(msg)\
244 end\
245 _fr_log.warn = function(msg)\
246 fr_lua.fr_lua_util_jit_log_warn(msg)\
247 end\
248 _fr_log.error = function(msg)\
249 fr_lua.fr_lua_util_jit_log_error(msg)\
250 end\
251 function _ro_log(table) \
252 return setmetatable({}, { \
253 __index = table,\
254 __newindex = function(table, key, value)\
255 _fr_log.warn(\"fr.log.$func() is read-only\")\
256 end, \
257 __metatable = false \
258 }); \
259 end\
260 fr.log = _ro_log(_fr_log)\
261 ", search_path, FR_DIR_SEP, DL_EXTENSION);
262 ret = luaL_dostring(L, lua_str);
263 talloc_free(lua_str);
264 TALLOC_FREE(ctx);
265 if (ret != 0) {
266 ERROR("Failed setting up FFI: %s",
267 lua_gettop(L) ? lua_tostring(L, -1) : "Unknown error");
268
269 return -1;
270 }
271
272 return 0;
273}
274
275/** Register utililiary functions in the lua environment
276 *
277 * @param L Lua interpreter.
278 * @return 0 (no arguments).
279 */
281{
282 /* fr.{} */
283 lua_getglobal(L, "fr");
284 luaL_checktype(L, -1, LUA_TTABLE);
285
286 /* fr.log.{} */
287 lua_newtable(L);
288 {
289 lua_newtable(L); //__metatable
290 {
291 lua_pushvalue(L, -1);
292 lua_setfield(L, -2, "__index");
293
294 lua_pushcfunction(L, _util_log_newindex);
295 lua_setfield(L, -2, "__newindex");
296 }
297
298 lua_pushcfunction(L, _util_log_debug);
299 lua_setfield(L, -2, "debug");
300
301 lua_pushcfunction(L, _util_log_info);
302 lua_setfield(L, -2, "info");
303
304 lua_pushcfunction(L, _util_log_warn);
305 lua_setfield(L, -2, "warn");
306
307 lua_pushcfunction(L, _util_log_error);
308 lua_setfield(L, -2, "error");
309 }
310
311 lua_setmetatable(L, -2);
312 lua_setfield(L, -2, "log");
313
314 return 0;
315}
316
317/** Set the thread local instance
318 *
319 * @param[in] mctx all helper and C functions callable from Lua should use.
320 */
322{
323 fr_lua_mctx = mctx;
324}
325
326/** Get the thread local instance
327 *
328 * @return mctx all helper and C functions callable from Lua should use.
329 */
331{
332 return fr_lua_mctx;
333}
334
335/** Set the thread local request
336 *
337 * @param[in] request all helper and C functions callable from Lua should use.
338 */
340{
341 fr_lua_request = request;
342}
343
344/** Get the thread local request
345 *
346 * @return request all helper and C functions callable from Lua should use.
347 */
int const char * file
Definition acutest.h:702
log_entry msg
Definition acutest.h:794
#define RCSID(id)
Definition build.h:483
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:209
#define UNUSED
Definition build.h:315
#define ERROR(fmt,...)
Definition dhcpclient.c:41
char const * dl_module_search_path(void)
Definition dl_module.c:483
#define DL_EXTENSION
Definition dl_module.h:57
#define ROPTIONAL(_l_request, _l_global, _fmt,...)
Use different logging functions depending on whether request is NULL or not.
Definition log.h:528
#define RWDEBUG(fmt,...)
Definition log.h:361
#define RWARN(fmt,...)
Definition log.h:297
#define RERROR(fmt,...)
Definition log.h:298
#define RINFO(fmt,...)
Definition log.h:296
talloc_free(reap)
Library function signatures for lua module.
char * strsep(char **stringp, char const *delim)
Definition missing.c:123
Temporary structure to hold arguments for module calls.
Definition module_ctx.h:41
static int _util_log_newindex(UNUSED lua_State *L)
Definition util.c:141
void fr_lua_util_jit_log_warn(char const *msg)
Emit a warning log message.
Definition util.c:176
int fr_lua_util_jit_log_register(lua_State *L)
Insert cdefs into the lua environment.
Definition util.c:202
void fr_lua_util_set_mctx(module_ctx_t const *mctx)
Set the thread local instance.
Definition util.c:321
request_t * fr_lua_util_get_request(void)
Get the thread local request.
Definition util.c:348
void fr_lua_util_set_request(request_t *request)
Set the thread local request.
Definition util.c:339
static int _util_log_debug(lua_State *L)
Lua function to output debug messages.
Definition util.c:55
static _Thread_local module_ctx_t const * fr_lua_mctx
Definition util.c:38
void fr_lua_util_fr_register(lua_State *L)
Definition util.c:40
static int _util_log_info(lua_State *L)
Lua function to output informational messages.
Definition util.c:78
static int _util_log_error(lua_State *L)
Lua function to output error messages.
Definition util.c:125
void fr_lua_util_jit_log_error(char const *msg)
Emit a error log message.
Definition util.c:187
void fr_lua_util_jit_log_debug(char const *msg)
Emit a debug log message.
Definition util.c:154
static int _util_log_warn(lua_State *L)
Lua function to output warning messages.
Definition util.c:102
static _Thread_local request_t * fr_lua_request
Definition util.c:37
int fr_lua_util_log_register(lua_State *L)
Register utililiary functions in the lua environment.
Definition util.c:280
void fr_lua_util_jit_log_info(char const *msg)
Emit an info log message.
Definition util.c:165
module_ctx_t const * fr_lua_util_get_mctx(void)
Get the thread local instance.
Definition util.c:330
#define fr_assert(_expr)
Definition rad_assert.h:38
#define RDEBUG2(fmt,...)
Definition radclient.h:54
#define DEBUG2(fmt,...)
Definition radclient.h:43
#define WARN(fmt,...)
Definition radclient.h:47
#define INFO(fmt,...)
Definition radict.c:54
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
Definition talloc.c:492
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition talloc.c:445