shell_plugin.c 4.6 KB

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