shell_plugin.c 4.8 KB

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