You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

commands.c 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /*-
  2. * Copyright 2016 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "rspamadm.h"
  17. #include "libutil/util.h"
  18. #include "libutil/logger.h"
  19. #include "lua/lua_common.h"
  20. #include "lua/lua_thread_pool.h"
  21. extern struct rspamadm_command pw_command;
  22. extern struct rspamadm_command configtest_command;
  23. extern struct rspamadm_command fuzzy_merge_command;
  24. extern struct rspamadm_command configdump_command;
  25. extern struct rspamadm_command control_command;
  26. extern struct rspamadm_command confighelp_command;
  27. extern struct rspamadm_command statconvert_command;
  28. extern struct rspamadm_command fuzzyconvert_command;
  29. extern struct rspamadm_command signtool_command;
  30. extern struct rspamadm_command lua_command;
  31. extern struct rspamadm_command dkim_keygen_command;
  32. const struct rspamadm_command *commands[] = {
  33. &help_command,
  34. &pw_command,
  35. &configtest_command,
  36. &fuzzy_merge_command,
  37. &configdump_command,
  38. &control_command,
  39. &confighelp_command,
  40. &statconvert_command,
  41. &fuzzyconvert_command,
  42. &signtool_command,
  43. &lua_command,
  44. &dkim_keygen_command,
  45. NULL
  46. };
  47. const struct rspamadm_command *
  48. rspamadm_search_command (const gchar *name, GPtrArray *all_commands)
  49. {
  50. const struct rspamadm_command *ret = NULL, *cmd;
  51. const gchar *alias;
  52. guint i, j;
  53. if (name == NULL) {
  54. name = "help";
  55. }
  56. PTR_ARRAY_FOREACH (all_commands, i, cmd) {
  57. if (strcmp (name, cmd->name) == 0) {
  58. ret = cmd;
  59. break;
  60. }
  61. PTR_ARRAY_FOREACH (cmd->aliases, j, alias) {
  62. if (strcmp (name, alias) == 0) {
  63. ret = cmd;
  64. break;
  65. }
  66. }
  67. }
  68. return ret;
  69. }
  70. void
  71. rspamadm_fill_internal_commands (GPtrArray *dest)
  72. {
  73. guint i;
  74. for (i = 0; i < G_N_ELEMENTS (commands); i ++) {
  75. if (commands[i]) {
  76. g_ptr_array_add (dest, (gpointer)commands[i]);
  77. }
  78. }
  79. }
  80. static void
  81. lua_thread_str_error_cb (struct thread_entry *thread, int ret, const char *msg)
  82. {
  83. msg_err ("call to rspamadm lua script failed (%d): %s",
  84. ret, msg);
  85. }
  86. static void
  87. rspamadm_lua_command_run (gint argc, gchar **argv,
  88. const struct rspamadm_command *cmd)
  89. {
  90. struct thread_entry *thread = lua_thread_pool_get_for_config (rspamd_main->cfg);
  91. lua_State *L = thread->lua_state;
  92. gint table_idx = GPOINTER_TO_INT (cmd->command_data);
  93. gint i;
  94. /* Function */
  95. lua_rawgeti (L, LUA_REGISTRYINDEX, table_idx);
  96. lua_pushstring (L, "handler");
  97. lua_gettable (L, -2);
  98. /* Args */
  99. lua_createtable (L, argc + 1, 0);
  100. for (i = 0; i < argc; i ++) {
  101. lua_pushstring (L, argv[i]);
  102. lua_rawseti (L, -2, i); /* Starting from zero ! */
  103. }
  104. if (lua_repl_thread_call (thread, 1, (void *)cmd, lua_thread_str_error_cb) != 0) {
  105. exit (EXIT_FAILURE);
  106. }
  107. lua_settop (L, 0);
  108. }
  109. static const gchar *
  110. rspamadm_lua_command_help (gboolean full_help,
  111. const struct rspamadm_command *cmd)
  112. {
  113. struct thread_entry *thread = lua_thread_pool_get_for_config (rspamd_main->cfg);
  114. lua_State *L = thread->lua_state;
  115. gint table_idx = GPOINTER_TO_INT (cmd->command_data);
  116. if (full_help) {
  117. lua_rawgeti (L, LUA_REGISTRYINDEX, table_idx);
  118. /* Function */
  119. lua_pushstring (L, "handler");
  120. lua_gettable (L, -2);
  121. /* Args */
  122. lua_createtable (L, 2, 0);
  123. lua_pushstring (L, cmd->name);
  124. lua_rawseti (L, -2, 0); /* Starting from zero ! */
  125. lua_pushstring (L, "--help");
  126. lua_rawseti (L, -2, 1);
  127. if (lua_repl_thread_call (thread, 1, (void *)cmd, lua_thread_str_error_cb) != 0) {
  128. exit (EXIT_FAILURE);
  129. }
  130. }
  131. else {
  132. lua_rawgeti (L, LUA_REGISTRYINDEX, table_idx);
  133. lua_pushstring (L, "description");
  134. lua_gettable (L, -2);
  135. if (lua_isstring (L, -1)) {
  136. printf (" %-18s %-60s\n", cmd->name, lua_tostring (L, -1));
  137. }
  138. else {
  139. printf (" %-18s %-60s\n", cmd->name, "no description available");
  140. }
  141. }
  142. lua_settop (L, 0);
  143. return NULL; /* Must be handled in rspamadm itself */
  144. }
  145. void
  146. rspamadm_fill_lua_commands (lua_State *L, GPtrArray *dest)
  147. {
  148. gint i;
  149. GPtrArray *lua_paths;
  150. GError *err = NULL;
  151. const gchar *lualibdir = RSPAMD_LUALIBDIR, *path;
  152. struct rspamadm_command *lua_cmd;
  153. gchar search_dir[PATH_MAX];
  154. if (g_hash_table_lookup (ucl_vars, "LUALIBDIR")) {
  155. lualibdir = g_hash_table_lookup (ucl_vars, "LUALIBDIR");
  156. }
  157. rspamd_snprintf (search_dir, sizeof (search_dir), "%s%crspamadm%c",
  158. lualibdir, G_DIR_SEPARATOR, G_DIR_SEPARATOR);
  159. if ((lua_paths = rspamd_glob_path (search_dir, "*.lua", FALSE, &err)) == NULL) {
  160. msg_err ("cannot glob files in %s/*.lua: %e", search_dir, err);
  161. g_error_free (err);
  162. return;
  163. }
  164. PTR_ARRAY_FOREACH (lua_paths, i, path) {
  165. if (luaL_dofile (L, path) != 0) {
  166. msg_err ("cannot execute lua script %s: %s",
  167. path, lua_tostring (L, -1));
  168. lua_settop (L, 0);
  169. continue;
  170. } else {
  171. if (lua_type (L, -1) == LUA_TTABLE) {
  172. lua_pushstring (L, "handler");
  173. lua_gettable (L, -2);
  174. }
  175. else {
  176. continue; /* Something goes wrong, huh */
  177. }
  178. if (lua_type (L, -1) != LUA_TFUNCTION) {
  179. msg_err ("rspamadm script %s does not have 'handler' field with type "
  180. "function",
  181. path);
  182. continue;
  183. }
  184. /* Pop handler */
  185. lua_pop (L, 1);
  186. lua_cmd = g_malloc0 (sizeof (*lua_cmd));
  187. lua_pushstring (L, "name");
  188. lua_gettable (L, -2);
  189. if (lua_type (L, -1) == LUA_TSTRING) {
  190. lua_cmd->name = g_strdup (lua_tostring (L, -1));
  191. }
  192. else {
  193. goffset ext_pos;
  194. gchar *name;
  195. name = g_path_get_basename (path);
  196. /* Remove .lua */
  197. ext_pos = rspamd_substring_search (path, strlen (path), ".lua", 4);
  198. if (ext_pos != -1) {
  199. name[ext_pos] = '\0';
  200. }
  201. lua_cmd->name = name;
  202. }
  203. lua_pop (L, 1);
  204. lua_pushstring (L, "aliases");
  205. lua_gettable (L, -2);
  206. if (lua_type (L, -1) == LUA_TTABLE) {
  207. lua_cmd->aliases = g_ptr_array_new_full (
  208. rspamd_lua_table_size (L, -1),
  209. g_free);
  210. for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) {
  211. if (lua_isstring (L, -1)) {
  212. g_ptr_array_add (lua_cmd->aliases,
  213. g_strdup (lua_tostring (L, -1)));
  214. }
  215. }
  216. }
  217. lua_pop (L, 1);
  218. lua_pushvalue (L, -1);
  219. /* Reference table itself */
  220. lua_cmd->command_data = GINT_TO_POINTER (luaL_ref (L, LUA_REGISTRYINDEX));
  221. lua_cmd->flags |= RSPAMADM_FLAG_LUA;
  222. lua_cmd->run = rspamadm_lua_command_run;
  223. lua_cmd->help = rspamadm_lua_command_help;
  224. g_ptr_array_add (dest, lua_cmd);
  225. }
  226. lua_settop (L, 0);
  227. }
  228. }