shell_plugin.c 5.0 KB

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