shell_new.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. * shell_new.c
  3. */
  4. #include "private.h"
  5. #include <assert.h>
  6. #include <stdlib.h>
  7. #include <sys/types.h>
  8. #include <unistd.h>
  9. #include "lub/string.h"
  10. #include "lub/db.h"
  11. #include "lub/list.h"
  12. #include "clish/plugin.h"
  13. /*-------------------------------------------------------- */
  14. static void clish_shell_init(clish_shell_t * this,
  15. void *cookie, FILE * istream,
  16. FILE * ostream,
  17. bool_t stop_on_error)
  18. {
  19. clish_ptype_t *tmp_ptype = NULL;
  20. clish_plugin_t *plugin = NULL;
  21. /* initialise the tree of views */
  22. lub_bintree_init(&this->view_tree,
  23. clish_view_bt_offset(),
  24. clish_view_bt_compare, clish_view_bt_getkey);
  25. /* initialise the tree of ptypes */
  26. lub_bintree_init(&this->ptype_tree,
  27. clish_ptype_bt_offset(),
  28. clish_ptype_bt_compare, clish_ptype_bt_getkey);
  29. /* initialise the tree of vars */
  30. lub_bintree_init(&this->var_tree,
  31. clish_var_bt_offset(),
  32. clish_var_bt_compare, clish_var_bt_getkey);
  33. /* Initialize plugin list */
  34. this->plugins = lub_list_new(NULL);
  35. /* Create internal plugin "clish" */
  36. plugin = clish_plugin_new(NULL, "clish");
  37. lub_list_add(this->plugins, plugin);
  38. /* Initialise the list of unresolved (yet) symbols */
  39. this->syms = lub_list_new(clish_sym_compare);
  40. /* Create userdata storage */
  41. this->udata = lub_list_new(clish_udata_compare);
  42. assert(this->udata);
  43. /* Default syms and hooks */
  44. this->hooks[CLISH_SYM_TYPE_NONE] = NULL;
  45. this->hooks[CLISH_SYM_TYPE_ACTION] = clish_sym_new(
  46. CLISH_DEFAULT_SYM, NULL, CLISH_SYM_TYPE_ACTION);
  47. this->hooks[CLISH_SYM_TYPE_INIT] = NULL;
  48. this->hooks[CLISH_SYM_TYPE_FINI] = NULL;
  49. this->hooks[CLISH_SYM_TYPE_ACCESS] = clish_sym_new(
  50. CLISH_DEFAULT_ACCESS, NULL, CLISH_SYM_TYPE_ACCESS);
  51. this->hooks[CLISH_SYM_TYPE_CONFIG] = clish_sym_new(
  52. CLISH_DEFAULT_CONFIG, NULL, CLISH_SYM_TYPE_CONFIG);
  53. this->hooks[CLISH_SYM_TYPE_LOG] = clish_sym_new(
  54. CLISH_DEFAULT_LOG, NULL, CLISH_SYM_TYPE_LOG);
  55. /* set up defaults */
  56. this->client_cookie = cookie;
  57. this->global = NULL;
  58. this->startup = NULL;
  59. this->idle_timeout = 0; /* No idle timeout by default */
  60. this->wdog = NULL;
  61. this->wdog_timeout = 0; /* No watchdog timeout by default */
  62. this->wdog_active = BOOL_FALSE;
  63. this->state = SHELL_STATE_INITIALISING;
  64. this->overview = NULL;
  65. this->tinyrl = clish_shell_tinyrl_new(istream, ostream, 0);
  66. this->current_file = NULL;
  67. this->pwdv = NULL;
  68. this->pwdc = 0;
  69. this->depth = -1; /* Current depth is undefined */
  70. this->client = NULL;
  71. this->lockfile = lub_string_dup(CLISH_LOCK_PATH);
  72. this->default_shebang = lub_string_dup("/bin/sh");
  73. this->fifo_name = NULL;
  74. this->interactive = BOOL_TRUE; /* The interactive shell by default. */
  75. this->log = BOOL_FALSE; /* Disable logging by default */
  76. this->dryrun = BOOL_FALSE; /* Disable dry-run by default */
  77. this->user = lub_db_getpwuid(getuid()); /* Get user information */
  78. /* Create internal ptypes and params */
  79. /* Current depth */
  80. tmp_ptype = clish_shell_find_create_ptype(this,
  81. "__DEPTH", "Depth", "[0-9]+",
  82. CLISH_PTYPE_REGEXP, CLISH_PTYPE_NONE);
  83. assert(tmp_ptype);
  84. this->param_depth = clish_param_new("_cur_depth",
  85. "Current depth", tmp_ptype);
  86. clish_param__set_hidden(this->param_depth, BOOL_TRUE);
  87. /* Current pwd */
  88. tmp_ptype = clish_shell_find_create_ptype(this,
  89. "__PWD", "Path", ".+",
  90. CLISH_PTYPE_REGEXP, CLISH_PTYPE_NONE);
  91. assert(tmp_ptype);
  92. this->param_pwd = clish_param_new("_cur_pwd",
  93. "Current path", tmp_ptype);
  94. clish_param__set_hidden(this->param_pwd, BOOL_TRUE);
  95. /* Args */
  96. tmp_ptype = clish_shell_find_create_ptype(this,
  97. "internal_ARGS",
  98. "Arguments", "[^\\\\]+",
  99. CLISH_PTYPE_REGEXP,
  100. CLISH_PTYPE_NONE);
  101. assert(tmp_ptype);
  102. /* Push non-NULL istream */
  103. if (istream)
  104. clish_shell_push_fd(this, istream, stop_on_error);
  105. }
  106. /*--------------------------------------------------------- */
  107. static void clish_shell_fini(clish_shell_t *this)
  108. {
  109. clish_view_t *view;
  110. clish_ptype_t *ptype;
  111. clish_var_t *var;
  112. unsigned i;
  113. lub_list_node_t *iter;
  114. /* Free all loaded plugins */
  115. while ((iter = lub_list__get_head(this->plugins))) {
  116. /* Remove the symbol from the list */
  117. lub_list_del(this->plugins, iter);
  118. /* Free the instance */
  119. clish_plugin_free((clish_plugin_t *)lub_list_node__get_data(iter),
  120. (void *)this);
  121. lub_list_node_free(iter);
  122. }
  123. lub_list_free(this->plugins);
  124. /* delete each VIEW held */
  125. while ((view = lub_bintree_findfirst(&this->view_tree))) {
  126. lub_bintree_remove(&this->view_tree, view);
  127. clish_view_delete(view);
  128. }
  129. /* delete each PTYPE held */
  130. while ((ptype = lub_bintree_findfirst(&this->ptype_tree))) {
  131. lub_bintree_remove(&this->ptype_tree, ptype);
  132. clish_ptype_delete(ptype);
  133. }
  134. /* delete each VAR held */
  135. while ((var = lub_bintree_findfirst(&this->var_tree))) {
  136. lub_bintree_remove(&this->var_tree, var);
  137. clish_var_delete(var);
  138. }
  139. /* Free symbol list */
  140. while ((iter = lub_list__get_head(this->syms))) {
  141. /* Remove the symbol from the list */
  142. lub_list_del(this->syms, iter);
  143. /* Free the instance */
  144. clish_sym_free((clish_sym_t *)lub_list_node__get_data(iter));
  145. lub_list_node_free(iter);
  146. }
  147. lub_list_free(this->syms);
  148. /* Free user data storage */
  149. while ((iter = lub_list__get_head(this->udata))) {
  150. /* Remove the symbol from the list */
  151. lub_list_del(this->udata, iter);
  152. /* Free the instance */
  153. clish_udata_free((clish_udata_t *)lub_list_node__get_data(iter));
  154. lub_list_node_free(iter);
  155. }
  156. lub_list_free(this->udata);
  157. /* free the textual details */
  158. lub_string_free(this->overview);
  159. /* Remove the startup command */
  160. if (this->startup)
  161. clish_command_delete(this->startup);
  162. /* Remove the watchdog command */
  163. if (this->wdog)
  164. clish_command_delete(this->wdog);
  165. /* clean up the file stack */
  166. while (!clish_shell_pop_file(this));
  167. /* delete the tinyrl object */
  168. clish_shell_tinyrl_delete(this->tinyrl);
  169. /* finalize each of the pwd strings */
  170. for (i = 0; i < this->pwdc; i++) {
  171. clish_shell__fini_pwd(this->pwdv[i]);
  172. free(this->pwdv[i]);
  173. }
  174. /* free the pwd vector */
  175. free(this->pwdv);
  176. konf_client_free(this->client);
  177. /* Free internal params */
  178. clish_param_delete(this->param_depth);
  179. clish_param_delete(this->param_pwd);
  180. lub_string_free(this->lockfile);
  181. lub_string_free(this->default_shebang);
  182. free(this->user);
  183. if (this->fifo_name) {
  184. unlink(this->fifo_name);
  185. lub_string_free(this->fifo_name);
  186. }
  187. }
  188. /*-------------------------------------------------------- */
  189. clish_shell_t *clish_shell_new(
  190. void *cookie,
  191. FILE * istream,
  192. FILE * ostream,
  193. bool_t stop_on_error)
  194. {
  195. clish_shell_t *this = malloc(sizeof(clish_shell_t));
  196. if (this)
  197. clish_shell_init(this, cookie,
  198. istream, ostream, stop_on_error);
  199. return this;
  200. }
  201. /*--------------------------------------------------------- */
  202. void clish_shell_delete(clish_shell_t *this)
  203. {
  204. clish_context_t context;
  205. context.shell = this;
  206. /* Now call the client finalization */
  207. clish_shell_exec_fini(&context);
  208. clish_shell_fini(this);
  209. free(this);
  210. }
  211. /*--------------------------------------------------------- */
  212. struct passwd *clish_shell__get_user(clish_shell_t * this)
  213. {
  214. return this->user;
  215. }
  216. /*-------------------------------------------------------- */