shell_plugin.c 4.8 KB

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