shell_plugin.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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_plugin_fn_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_plugin_fn_t *func = 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. func = 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 ((func = clish_plugin_get_sym(plugin, cmdn)))
  88. break;
  89. }
  90. }
  91. end:
  92. lub_string_free(str);
  93. return func;
  94. }
  95. /*--------------------------------------------------------- */
  96. clish_sym_t *clish_shell_find_sym(clish_shell_t *this, const char *name)
  97. {
  98. lub_list_node_t *iter;
  99. clish_sym_t *sym;
  100. /* Iterate elements */
  101. for(iter = lub_list__get_head(this->syms);
  102. iter; iter = lub_list_node__get_next(iter)) {
  103. int res;
  104. sym = (clish_sym_t *)lub_list_node__get_data(iter);
  105. res = strcmp(clish_sym__get_name(sym), name);
  106. if (!res)
  107. return sym;
  108. if (res > 0) /* No chances to find name */
  109. break;
  110. }
  111. return NULL;
  112. }
  113. /*----------------------------------------------------------------------- */
  114. clish_sym_t *clish_shell_add_sym(clish_shell_t *this,
  115. clish_plugin_fn_t *func, const char *name)
  116. {
  117. clish_sym_t *sym = NULL;
  118. if (!name)
  119. return NULL;
  120. if ((sym = clish_shell_find_sym(this, name)))
  121. return sym;
  122. if (!(sym = clish_sym_new(name, func)))
  123. return NULL;
  124. lub_list_add(this->syms, sym);
  125. return sym;
  126. }
  127. /*----------------------------------------------------------------------- */
  128. clish_sym_t *clish_shell_add_unresolved_sym(clish_shell_t *this,
  129. const char *name)
  130. {
  131. return clish_shell_add_sym(this, NULL, name);
  132. }
  133. /*----------------------------------------------------------------------- */
  134. int clish_shell_link_plugins(clish_shell_t *this)
  135. {
  136. clish_sym_t *sym;
  137. lub_list_node_t *iter;
  138. char *sym_name = NULL;
  139. clish_plugin_fn_t *fn = NULL;
  140. /* Iterate elements */
  141. for(iter = lub_list__get_head(this->syms);
  142. iter; iter = lub_list_node__get_next(iter)) {
  143. sym = (clish_sym_t *)lub_list_node__get_data(iter);
  144. sym_name = clish_sym__get_name(sym);
  145. fn = plugins_find_sym(this, sym_name);
  146. if (!fn) {
  147. fprintf(stderr, "Error: Can't resolve symbol %s.\n",
  148. sym_name);
  149. return -1;
  150. }
  151. clish_sym__set_func(sym, fn);
  152. }
  153. return 0;
  154. }