shell_plugin.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * shell_plugin.c
  3. */
  4. #include "private.h"
  5. #include <assert.h>
  6. #include <string.h>
  7. #include <dlfcn.h>
  8. #include "lub/string.h"
  9. #include "lub/list.h"
  10. #include "clish/plugin.h"
  11. #include "clish/view.h"
  12. /*----------------------------------------------------------------------- */
  13. clish_plugin_t * clish_shell_find_plugin(clish_shell_t *this, const char *name)
  14. {
  15. lub_list_node_t *iter;
  16. clish_plugin_t *plugin;
  17. assert(this);
  18. if (!name || !name[0])
  19. return NULL;
  20. /* Iterate elements */
  21. for(iter = lub_list__get_head(this->plugins);
  22. iter; iter = lub_list_node__get_next(iter)) {
  23. plugin = (clish_plugin_t *)lub_list_node__get_data(iter);
  24. if (!strcmp(name, clish_plugin__get_name(plugin)))
  25. return plugin;
  26. }
  27. return NULL;
  28. }
  29. /*----------------------------------------------------------------------- */
  30. clish_plugin_t * clish_shell_create_plugin(clish_shell_t *this,
  31. const char *name)
  32. {
  33. clish_plugin_t *plugin;
  34. assert(this);
  35. if (!name || !name[0])
  36. return NULL;
  37. plugin = clish_plugin_new(name, this);
  38. lub_list_add(this->plugins, plugin);
  39. return plugin;
  40. }
  41. /*----------------------------------------------------------------------- */
  42. clish_plugin_t * clish_shell_find_create_plugin(clish_shell_t *this,
  43. const char *name)
  44. {
  45. clish_plugin_t *plugin = clish_shell_find_plugin(this, name);
  46. return (plugin ? plugin : clish_shell_create_plugin(this, name));
  47. }
  48. /*----------------------------------------------------------------------- */
  49. /* For all plugins:
  50. * * dlopen(plugin)
  51. * * dlsym(initialize function)
  52. * * exec init functions to get all plugin syms
  53. */
  54. int clish_shell_load_plugins(clish_shell_t *this)
  55. {
  56. lub_list_node_t *iter;
  57. clish_plugin_t *plugin;
  58. assert(this);
  59. /* Iterate elements */
  60. for(iter = lub_list__get_head(this->plugins);
  61. iter; iter = lub_list_node__get_next(iter)) {
  62. plugin = (clish_plugin_t *)lub_list_node__get_data(iter);
  63. if (clish_plugin_load(plugin))
  64. return -1;
  65. #ifdef DEBUG
  66. clish_plugin_dump(plugin);
  67. #endif
  68. }
  69. return 0;
  70. }
  71. /*----------------------------------------------------------------------- */
  72. /* Iterate plugins to find symbol by name.
  73. * The symbol name can be simple or with namespace:
  74. * mysym@plugin1
  75. * The symbols with suffix will be resolved using specified plugin only.
  76. */
  77. static clish_sym_t *plugins_find_sym(clish_shell_t *this, const char *name, int type)
  78. {
  79. lub_list_node_t *iter;
  80. clish_plugin_t *plugin;
  81. clish_sym_t *sym = NULL;
  82. /* To parse command name */
  83. char *saveptr = NULL;
  84. const char *delim = "@";
  85. char *plugin_name = NULL;
  86. char *cmdn = NULL;
  87. char *str = lub_string_dup(name);
  88. assert(this);
  89. /* Parse name to get sym name and optional plugin name */
  90. cmdn = strtok_r(str, delim, &saveptr);
  91. if (!cmdn) {
  92. lub_string_free(str);
  93. return NULL;
  94. }
  95. plugin_name = strtok_r(NULL, delim, &saveptr);
  96. if (plugin_name) {
  97. /* Search for symbol in specified namespace */
  98. /* Iterate elements */
  99. for(iter = lub_list__get_head(this->plugins);
  100. iter; iter = lub_list_node__get_next(iter)) {
  101. plugin = (clish_plugin_t *)lub_list_node__get_data(iter);
  102. if (strcmp(clish_plugin__get_pubname(plugin), plugin_name))
  103. continue;
  104. if ((sym = clish_plugin_get_sym(plugin, cmdn, type)))
  105. break;
  106. }
  107. } else {
  108. /* Iterate all plugins */
  109. for(iter = lub_list__get_head(this->plugins);
  110. iter; iter = lub_list_node__get_next(iter)) {
  111. plugin = (clish_plugin_t *)lub_list_node__get_data(iter);
  112. if ((sym = clish_plugin_get_sym(plugin, cmdn, type)))
  113. break;
  114. }
  115. }
  116. lub_string_free(str);
  117. return sym;
  118. }
  119. /*--------------------------------------------------------- */
  120. /* Find symbol by name in the list of unresolved symbols */
  121. clish_sym_t *clish_shell_find_sym(clish_shell_t *this, const char *name, int type)
  122. {
  123. lub_list_node_t *iter;
  124. clish_sym_t *sym;
  125. /* Iterate elements */
  126. for(iter = lub_list__get_head(this->syms);
  127. iter; iter = lub_list_node__get_next(iter)) {
  128. int res;
  129. sym = (clish_sym_t *)lub_list_node__get_data(iter);
  130. res = strcmp(clish_sym__get_name(sym), name);
  131. if (!res && ((CLISH_SYM_TYPE_NONE == type) || (clish_sym__get_type(sym) == type)))
  132. return sym;
  133. if (res > 0) /* No chance to find name */
  134. break;
  135. }
  136. return NULL;
  137. }
  138. /*----------------------------------------------------------------------- */
  139. /* Add symbol to the table of unresolved symbols */
  140. clish_sym_t *clish_shell_add_sym(clish_shell_t *this,
  141. void *func, const char *name, int type)
  142. {
  143. clish_sym_t *sym = NULL;
  144. if (!name)
  145. return NULL;
  146. if ((sym = clish_shell_find_sym(this, name, type)))
  147. return sym;
  148. if (!(sym = clish_sym_new(name, func, type)))
  149. return NULL;
  150. lub_list_add(this->syms, sym);
  151. return sym;
  152. }
  153. /*----------------------------------------------------------------------- */
  154. clish_sym_t *clish_shell_add_unresolved_sym(clish_shell_t *this,
  155. const char *name, int type)
  156. {
  157. return clish_shell_add_sym(this, NULL, name, type);
  158. }
  159. /*----------------------------------------------------------------------- */
  160. /* Link one unresolved symbol.
  161. * sym - unresolved symbol
  162. * Returns 0 if the symbol was succesfully resolved
  163. */
  164. static int link_unresolved_sym(clish_shell_t *this, clish_sym_t *sym)
  165. {
  166. clish_sym_t *plugin_sym;
  167. const char *sym_name = NULL;
  168. int sym_type;
  169. if (clish_sym__get_func(sym)) /* Don't relink non-null fn */
  170. return 0;
  171. sym_name = clish_sym__get_name(sym);
  172. sym_type = clish_sym__get_type(sym);
  173. plugin_sym = plugins_find_sym(this, sym_name, sym_type);
  174. if (!plugin_sym) {
  175. fprintf(stderr, "Error: Can't resolve symbol %s.\n",
  176. sym_name);
  177. return -1;
  178. }
  179. /* Copy symbol attributes */
  180. clish_sym_clone(sym, plugin_sym);
  181. return 0;
  182. }
  183. /*----------------------------------------------------------------------- */
  184. /* Link unresolved symbols */
  185. int clish_shell_link_plugins(clish_shell_t *this)
  186. {
  187. clish_sym_t *sym;
  188. lub_list_node_t *iter;
  189. /* Iterate elements */
  190. for(iter = lub_list__get_head(this->syms);
  191. iter; iter = lub_list_node__get_next(iter)) {
  192. sym = (clish_sym_t *)lub_list_node__get_data(iter);
  193. if (link_unresolved_sym(this, sym) < 0)
  194. return -1;
  195. }
  196. return 0;
  197. }
  198. /*----------------------------------------------------------------------- */
  199. /* Get hook sym */
  200. clish_sym_t *clish_shell_get_hook(const clish_shell_t *this, int type)
  201. {
  202. return this->hooks[type];
  203. }