shell_plugin.c 6.1 KB

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