kcontext.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <assert.h>
  5. #include <sys/types.h>
  6. #include <unistd.h>
  7. #include <faux/str.h>
  8. #include <faux/conv.h>
  9. #include <faux/list.h>
  10. #include <klish/khelper.h>
  11. #include <klish/kpargv.h>
  12. #include <klish/kcontext.h>
  13. #include <klish/kscheme.h>
  14. #include <klish/ksession.h>
  15. #include <klish/kaction.h>
  16. #include <klish/kscheme.h>
  17. #include <klish/kexec.h>
  18. struct kcontext_s {
  19. kcontext_type_e type;
  20. kscheme_t *scheme;
  21. int retcode;
  22. ksession_t *session;
  23. kplugin_t *plugin;
  24. kpargv_t *pargv;
  25. const kpargv_t *parent_pargv; // Parent
  26. const kcontext_t *parent_context; // Parent context (if available)
  27. const kexec_t *parent_exec; // Parent exec (if available)
  28. faux_list_node_t *action_iter; // Current action
  29. ksym_t *sym;
  30. int stdin;
  31. int stdout;
  32. int stderr;
  33. pid_t pid;
  34. bool_t done; // If all actions are done
  35. char *line; // Text command context belong to
  36. size_t pipeline_stage; // Index of current command within full pipeline
  37. };
  38. // Simple methods
  39. // Type
  40. KGET(context, kcontext_type_e, type);
  41. FAUX_HIDDEN KSET(context, kcontext_type_e, type);
  42. // Scheme
  43. KGET(context, kscheme_t *, scheme);
  44. KSET(context, kscheme_t *, scheme);
  45. // RetCode
  46. KGET(context, int, retcode);
  47. FAUX_HIDDEN KSET(context, int, retcode);
  48. // Plugin
  49. FAUX_HIDDEN KSET(context, kplugin_t *, plugin);
  50. // Sym
  51. KGET(context, ksym_t *, sym);
  52. FAUX_HIDDEN KSET(context, ksym_t *, sym);
  53. // Pargv
  54. KGET(context, kpargv_t *, pargv);
  55. FAUX_HIDDEN KSET(context, kpargv_t *, pargv);
  56. // Parent pargv
  57. KGET(context, const kpargv_t *, parent_pargv);
  58. FAUX_HIDDEN KSET(context, const kpargv_t *, parent_pargv);
  59. // Parent context
  60. KGET(context, const kcontext_t *, parent_context);
  61. FAUX_HIDDEN KSET(context, const kcontext_t *, parent_context);
  62. // Parent exec
  63. KGET(context, const kexec_t *, parent_exec);
  64. FAUX_HIDDEN KSET(context, const kexec_t *, parent_exec);
  65. // Action iterator
  66. KGET(context, faux_list_node_t *, action_iter);
  67. FAUX_HIDDEN KSET(context, faux_list_node_t *, action_iter);
  68. // STDIN
  69. KGET(context, int, stdin);
  70. FAUX_HIDDEN KSET(context, int, stdin);
  71. // STDOUT
  72. KGET(context, int, stdout);
  73. FAUX_HIDDEN KSET(context, int, stdout);
  74. // STDERR
  75. KGET(context, int, stderr);
  76. FAUX_HIDDEN KSET(context, int, stderr);
  77. // PID
  78. KGET(context, pid_t, pid);
  79. FAUX_HIDDEN KSET(context, pid_t, pid);
  80. // Session
  81. KGET(context, ksession_t *, session);
  82. FAUX_HIDDEN KSET(context, ksession_t *, session);
  83. // Done
  84. KGET_BOOL(context, done);
  85. FAUX_HIDDEN KSET_BOOL(context, done);
  86. // Line
  87. KGET_STR(context, line);
  88. FAUX_HIDDEN KSET_STR(context, line);
  89. // Pipeline stage
  90. KGET(context, size_t, pipeline_stage);
  91. FAUX_HIDDEN KSET(context, size_t, pipeline_stage);
  92. kcontext_t *kcontext_new(kcontext_type_e type)
  93. {
  94. kcontext_t *context = NULL;
  95. context = faux_zmalloc(sizeof(*context));
  96. assert(context);
  97. if (!context)
  98. return NULL;
  99. // Initialize
  100. context->type = type;
  101. context->scheme = NULL;
  102. context->retcode = 0;
  103. context->plugin = NULL;
  104. context->pargv = NULL;
  105. context->parent_pargv = NULL; // Don't free
  106. context->parent_context = NULL; // Don't free
  107. context->parent_exec = NULL; // Don't free
  108. context->action_iter = NULL;
  109. context->sym = NULL;
  110. context->stdin = -1;
  111. context->stdout = -1;
  112. context->stderr = -1;
  113. context->pid = -1; // PID of currently executed ACTION
  114. context->session = NULL; // Don't free
  115. context->done = BOOL_FALSE;
  116. context->line = NULL;
  117. context->pipeline_stage = 0;
  118. return context;
  119. }
  120. void kcontext_free(kcontext_t *context)
  121. {
  122. if (!context)
  123. return;
  124. kpargv_free(context->pargv);
  125. if (context->stdin != -1)
  126. close(context->stdin);
  127. if (context->stdout != -1)
  128. close(context->stdout);
  129. if (context->stderr != -1)
  130. close(context->stderr);
  131. faux_str_free(context->line);
  132. faux_free(context);
  133. }
  134. kparg_t *kcontext_candidate_parg(const kcontext_t *context)
  135. {
  136. const kpargv_t *pargv = NULL;
  137. assert(context);
  138. if (!context)
  139. return NULL;
  140. pargv = kcontext_parent_pargv(context);
  141. if (!pargv)
  142. return NULL;
  143. return kpargv_candidate_parg(pargv);
  144. }
  145. const kentry_t *kcontext_candidate_entry(const kcontext_t *context)
  146. {
  147. kparg_t *parg = NULL;
  148. assert(context);
  149. if (!context)
  150. return NULL;
  151. parg = kcontext_candidate_parg(context);
  152. if (!parg)
  153. return NULL;
  154. return kparg_entry(parg);
  155. }
  156. const char *kcontext_candidate_value(const kcontext_t *context)
  157. {
  158. kparg_t *parg = NULL;
  159. assert(context);
  160. if (!context)
  161. return NULL;
  162. parg = kcontext_candidate_parg(context);
  163. if (!parg)
  164. return NULL;
  165. return kparg_value(parg);
  166. }
  167. const kaction_t *kcontext_action(const kcontext_t *context)
  168. {
  169. faux_list_node_t *node = NULL;
  170. assert(context);
  171. if (!context)
  172. return NULL;
  173. node = kcontext_action_iter(context);
  174. if (!node)
  175. return NULL;
  176. return (const kaction_t *)faux_list_data(node);
  177. }
  178. const char *kcontext_script(const kcontext_t *context)
  179. {
  180. const kaction_t *action = NULL;
  181. assert(context);
  182. if (!context)
  183. return NULL;
  184. action = kcontext_action(context);
  185. if (!action)
  186. return NULL;
  187. return kaction_script(action);
  188. }
  189. bool_t kcontext_named_udata_new(kcontext_t *context,
  190. const char *name, void *data, kudata_data_free_fn free_fn)
  191. {
  192. assert(context);
  193. if (!context)
  194. return BOOL_FALSE;
  195. return kscheme_named_udata_new(context->scheme, name, data, free_fn);
  196. }
  197. void *kcontext_named_udata(const kcontext_t *context, const char *name)
  198. {
  199. assert(context);
  200. if (!context)
  201. return NULL;
  202. return kscheme_named_udata(context->scheme, name);
  203. }
  204. void *kcontext_udata(const kcontext_t *context)
  205. {
  206. kplugin_t *plugin = NULL;
  207. assert(context);
  208. if (!context)
  209. return NULL;
  210. plugin = kcontext_plugin(context);
  211. if (!plugin)
  212. return NULL;
  213. return kplugin_udata(plugin);
  214. }
  215. const kentry_t *kcontext_command(const kcontext_t *context)
  216. {
  217. kpargv_t *pargv = NULL;
  218. assert(context);
  219. if (!context)
  220. return NULL;
  221. pargv = kcontext_pargv(context);
  222. if (!pargv)
  223. return NULL;
  224. return kpargv_command(pargv);
  225. }
  226. kplugin_t *kcontext_plugin(const kcontext_t *context)
  227. {
  228. const kaction_t *action = NULL;
  229. assert(context);
  230. if (!context)
  231. return NULL;
  232. // If plugin field is specified then return it. It is specified for
  233. // plugin's init() and fini() functions.
  234. if (context->plugin)
  235. return context->plugin;
  236. // If plugin is not explicitly specified then return parent plugin for
  237. // currently executed sym (ACTION structure contains it).
  238. action = kcontext_action(context);
  239. if (!action)
  240. return NULL;
  241. return kaction_plugin(action);
  242. }