Freeciv-3.1
Loading...
Searching...
No Matches
script_fcdb.c
Go to the documentation of this file.
1/*****************************************************************************
2 Freeciv - Copyright (C) 2005 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12*****************************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdarg.h>
19#include <stdlib.h>
20#include <time.h>
21
22/* dependencies/lua */
23#include "lua.h"
24#include "lualib.h"
25
26/* dependencies/tolua */
27#include "tolua.h"
28
29/* dependencies/luasql */
30#ifdef HAVE_FCDB_MYSQL
31#include "ls_mysql.h"
32#endif
33#ifdef HAVE_FCDB_ODBC
34#include "ls_odbc.h"
35#endif
36#ifdef HAVE_FCDB_POSTGRES
37#include "ls_postgres.h"
38#endif
39#ifdef HAVE_FCDB_SQLITE3
40#include "ls_sqlite3.h"
41#endif
42
43/* utility */
44#include "log.h"
45#include "md5.h"
46#include "registry.h"
47#include "string_vector.h"
48
49/* common/scriptcore */
50#include "luascript.h"
51#include "luascript_types.h"
52#include "tolua_common_a_gen.h"
53#include "tolua_common_z_gen.h"
54#include "tolua_game_gen.h"
55
56/* server */
57#include "console.h"
58#include "stdinhand.h"
59
60/* server/scripting */
61#ifdef HAVE_FCDB
62#include <tolua_fcdb_gen.h> /* <> so looked from the build directory first. */
63#endif /* HAVE_FCDB */
64
65#include "script_fcdb.h"
66
67#ifdef HAVE_FCDB
68
69#define SCRIPT_FCDB_LUA_FILE "database.lua"
70
71static void script_fcdb_functions_define(void);
72static bool script_fcdb_functions_check(const char *fcdb_luafile);
73
74static void script_fcdb_cmd_reply(struct fc_lua *lfcl, enum log_level level,
75 const char *format, ...)
76 fc__attribute((__format__ (__printf__, 3, 4)));
77
78/**********************************************************************/
81static struct fc_lua *fcl = NULL;
82
83/**********************************************************************/
109static void script_fcdb_functions_define(void)
110{
111 luascript_func_add(fcl, "database_init", TRUE, 0, 0);
112 luascript_func_add(fcl, "database_free", TRUE, 0, 0);
113
114 luascript_func_add(fcl, "user_exists", TRUE, 1, 1, API_TYPE_CONNECTION,
115 API_TYPE_BOOL);
116 luascript_func_add(fcl, "user_verify", TRUE, 2, 1, API_TYPE_CONNECTION,
117 API_TYPE_STRING, API_TYPE_BOOL);
118 luascript_func_add(fcl, "user_save", FALSE, 2, 0, API_TYPE_CONNECTION,
119 API_TYPE_STRING);
120 luascript_func_add(fcl, "user_log", TRUE, 2, 0, API_TYPE_CONNECTION,
121 API_TYPE_BOOL);
122 luascript_func_add(fcl, "user_delegate_to", FALSE, 3, 1,
123 API_TYPE_CONNECTION, API_TYPE_PLAYER, API_TYPE_STRING,
124 API_TYPE_BOOL);
125 luascript_func_add(fcl, "user_take", FALSE, 4, 1, API_TYPE_CONNECTION,
126 API_TYPE_CONNECTION, API_TYPE_PLAYER, API_TYPE_BOOL,
127 API_TYPE_BOOL);
128}
129
130/**********************************************************************/
133static bool script_fcdb_functions_check(const char *fcdb_luafile)
134{
135 bool ret = TRUE;
136 struct strvec *missing_func_required = strvec_new();
137 struct strvec *missing_func_optional = strvec_new();
138
139 if (!luascript_func_check(fcl, missing_func_required,
140 missing_func_optional)) {
141 strvec_iterate(missing_func_required, func_name) {
142 log_error("Database script '%s' does not define the required function "
143 "'%s'.", fcdb_luafile, func_name);
144 ret = FALSE;
146 strvec_iterate(missing_func_optional, func_name) {
147 log_verbose("Database script '%s' does not define the optional "
148 "function '%s'.", fcdb_luafile, func_name);
150 }
151
152 strvec_destroy(missing_func_required);
153 strvec_destroy(missing_func_optional);
154
155 return ret;
156}
157
158/**********************************************************************/
161static void script_fcdb_cmd_reply(struct fc_lua *lfcl, enum log_level level,
162 const char *format, ...)
163{
164 va_list args;
166 char buf[1024];
167
168 va_start(args, format);
169 fc_vsnprintf(buf, sizeof(buf), format, args);
170 va_end(args);
171
172 switch (level) {
173 case LOG_FATAL:
174 /* Special case - will quit the server. */
175 log_fatal("%s", buf);
176 break;
177 case LOG_ERROR:
178 case LOG_WARN:
180 break;
181 case LOG_NORMAL:
183 break;
184 case LOG_VERBOSE:
186 break;
187 case LOG_DEBUG:
189 break;
190 }
191
192 cmd_reply(CMD_FCDB, lfcl->caller, rfc_status, "%s", buf);
193}
194
195/**********************************************************************/
198static int md5sum(lua_State *L)
199{
200 int n = lua_gettop(L);
201 char sum[MD5_HEX_BYTES + 1];
202 const char *plaintext;
203 size_t len;
204
205 if (n != 1 || lua_type(L, -1) != LUA_TSTRING) {
206 lua_pushliteral(L, "invalid argument");
207 lua_error(L);
208 }
209
210 plaintext = lua_tolstring(L, -1, &len);
211 create_md5sum((unsigned char*)plaintext, len, sum);
212
213 lua_pushstring(L, sum);
214 return 1;
215}
216#endif /* HAVE_FCDB */
217
218/**********************************************************************/
222bool script_fcdb_init(const char *fcdb_luafile)
223{
224#ifdef HAVE_FCDB
225 if (fcl != NULL) {
226 fc_assert_ret_val(fcl->state != NULL, FALSE);
227
228 return TRUE;
229 }
230
231 if (!fcdb_luafile) {
232 /* Use default freeciv database lua file. */
233 fcdb_luafile = FC_CONF_PATH "/" SCRIPT_FCDB_LUA_FILE;
234 }
235
236 fcl = luascript_new(NULL, FALSE);
237 if (fcl == NULL) {
238 log_error("Error loading the Freeciv database lua definition.");
239 return FALSE;
240 }
241
242 tolua_common_a_open(fcl->state);
243 tolua_game_open(fcl->state);
244
245#ifdef MESON_BUILD
246 /* Tolua adds 'tolua_' prefix to _open() function names,
247 * and we can't pass it a basename where the original
248 * 'tolua_' has been stripped when generating from meson. */
249 tolua_tolua_fcdb_open(fcl->state);
250#else /* MESON_BUILD */
251 tolua_fcdb_open(fcl->state);
252#endif /* MESON_BUILD */
253 lua_register(fcl->state, "md5sum", md5sum);
254#ifdef HAVE_FCDB_MYSQL
255 luaL_requiref(fcl->state, "ls_mysql", luaopen_luasql_mysql, 1);
256 lua_pop(fcl->state, 1);
257#endif
258#ifdef HAVE_FCDB_ODBC
259 luaL_requiref(fcl->state, "ls_odbc", luaopen_luasql_odbc, 1);
260 lua_pop(fcl->state, 1);
261#endif
262#ifdef HAVE_FCDB_POSTGRES
263 luaL_requiref(fcl->state, "ls_postgres", luaopen_luasql_postgres, 1);
264 lua_pop(fcl->state, 1);
265#endif
266#ifdef HAVE_FCDB_SQLITE3
267 luaL_requiref(fcl->state, "ls_sqlite3", luaopen_luasql_sqlite3, 1);
268 lua_pop(fcl->state, 1);
269#endif
270 tolua_common_z_open(fcl->state);
271
273
274 /* Define the prototypes for the needed lua functions. */
275 script_fcdb_functions_define();
276
277 if (luascript_do_file(fcl, fcdb_luafile)
278 || !script_fcdb_functions_check(fcdb_luafile)) {
279 log_error("Error loading the Freeciv database lua script '%s'.",
280 fcdb_luafile);
282 return FALSE;
283 }
284
285 if (!script_fcdb_call("database_init")) {
286 log_error("Error connecting to the database");
288 return FALSE;
289 }
290#endif /* HAVE_FCDB */
291
292 return TRUE;
293}
294
295/**********************************************************************/
301bool script_fcdb_call(const char *func_name, ...)
302{
303 bool success = TRUE;
304#ifdef HAVE_FCDB
305
306 va_list args;
307 va_start(args, func_name);
308
309 success = luascript_func_call_valist(fcl, func_name, args);
310 va_end(args);
311#endif /* HAVE_FCDB */
312
313 return success;
314}
315
316/**********************************************************************/
320{
321#ifdef HAVE_FCDB
322 if (!script_fcdb_call("database_free", 0)) {
323 log_error("Error closing the database connection. Continuing anyway...");
324 }
325
326 if (fcl) {
327 /* luascript_func_free() is called by luascript_destroy(). */
329 fcl = NULL;
330 }
331#endif /* HAVE_FCDB */
332}
333
334/**********************************************************************/
338bool script_fcdb_do_string(struct connection *caller, const char *str)
339{
340#ifdef HAVE_FCDB
341 int status;
342 struct connection *save_caller;
343 luascript_log_func_t save_output_fct;
344
345 /* Set a log callback function which allows to send the results of the
346 * command to the clients. */
347 save_caller = fcl->caller;
348 save_output_fct = fcl->output_fct;
349 fcl->output_fct = script_fcdb_cmd_reply;
350 fcl->caller = caller;
351
352 status = luascript_do_string(fcl, str, "cmd");
353
354 /* Reset the changes. */
355 fcl->caller = save_caller;
356 fcl->output_fct = save_output_fct;
357
358 return (status == 0);
359#else
360 return TRUE;
361#endif /* HAVE_FCDB */
362}
#define str
Definition astring.c:76
#define n
Definition astring.c:77
@ CMD_FCDB
Definition commands.h:97
rfc_status
Definition console.h:35
@ C_DEBUG
Definition console.h:39
@ C_OK
Definition console.h:41
@ C_LOG_BASE
Definition console.h:40
@ C_COMMENT
Definition console.h:37
@ C_WARNING
Definition console.h:50
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define log_fatal(message,...)
Definition log.h:100
log_level
Definition log.h:28
@ LOG_ERROR
Definition log.h:30
@ LOG_DEBUG
Definition log.h:34
@ LOG_NORMAL
Definition log.h:32
@ LOG_FATAL
Definition log.h:29
@ LOG_VERBOSE
Definition log.h:33
@ LOG_WARN
Definition log.h:31
#define log_error(message,...)
Definition log.h:103
int luascript_do_string(struct fc_lua *fcl, const char *str, const char *name)
Definition luascript.c:617
int luascript_do_file(struct fc_lua *fcl, const char *filename)
Definition luascript.c:637
struct fc_lua * luascript_new(luascript_log_func_t output_fct, bool secured_environment)
Definition luascript.c:332
void luascript_destroy(struct fc_lua *fcl)
Definition luascript.c:386
void(* luascript_log_func_t)(struct fc_lua *fcl, enum log_level level, const char *format,...) fc__attribute((__format__(__printf__
Definition luascript.h:39
bool luascript_func_call_valist(struct fc_lua *fcl, const char *func_name, va_list args)
bool luascript_func_check(struct fc_lua *fcl, struct strvec *missing_func_required, struct strvec *missing_func_optional)
void luascript_func_init(struct fc_lua *fcl)
void luascript_func_add(struct fc_lua *fcl, const char *func_name, bool required, int nargs, int nreturns,...)
void create_md5sum(const unsigned char *input, int len, char output[MD5_HEX_BYTES+1])
Definition md5.c:335
#define MD5_HEX_BYTES
Definition md5.h:21
int len
Definition packhand.c:125
void script_fcdb_free(void)
bool script_fcdb_do_string(struct connection *caller, const char *str)
bool script_fcdb_call(const char *func_name,...)
bool script_fcdb_init(const char *fcdb_luafile)
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:183
void cmd_reply(enum command_id cmd, struct connection *caller, enum rfc_status rfc_status, const char *format,...)
Definition stdinhand.c:418
void strvec_destroy(struct strvec *psv)
struct strvec * strvec_new(void)
#define strvec_iterate(psv, str)
#define strvec_iterate_end
enum auth_status status
Definition connection.h:222
struct connection * caller
Definition luascript.h:49
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:896
#define fc__attribute(x)
Definition support.h:89
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
TOLUA_API int tolua_common_a_open(lua_State *tolua_S)
TOLUA_API int tolua_common_z_open(lua_State *tolua_S)
TOLUA_API int tolua_fcdb_open(lua_State *tolua_S)
TOLUA_API int tolua_game_open(lua_State *tolua_S)