ksession_parse.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893
  1. /** @file ksession_parse.c
  2. */
  3. #include <assert.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <signal.h>
  8. #include <sys/types.h>
  9. #include <sys/wait.h>
  10. #include <unistd.h>
  11. #include <syslog.h>
  12. #include <faux/eloop.h>
  13. #include <faux/buf.h>
  14. #include <faux/list.h>
  15. #include <faux/argv.h>
  16. #include <faux/error.h>
  17. #include <klish/khelper.h>
  18. #include <klish/kscheme.h>
  19. #include <klish/kpath.h>
  20. #include <klish/kpargv.h>
  21. #include <klish/kexec.h>
  22. #include <klish/ksession.h>
  23. #include <klish/ksession_parse.h>
  24. #define ARGV_ALT_QUOTES "'"
  25. static bool_t ksession_validate_arg(ksession_t *session, kpargv_t *pargv)
  26. {
  27. char *out = NULL;
  28. int retcode = -1;
  29. kentry_t *ptype_entry = NULL;
  30. kparg_t *candidate = NULL;
  31. assert(session);
  32. if (!session)
  33. return BOOL_FALSE;
  34. assert(pargv);
  35. if (!pargv)
  36. return BOOL_FALSE;
  37. candidate = kpargv_candidate_parg(pargv);
  38. if (!candidate)
  39. return BOOL_FALSE;
  40. ptype_entry = kentry_nested_by_purpose(kparg_entry(candidate),
  41. KENTRY_PURPOSE_PTYPE);
  42. if (!ptype_entry)
  43. return BOOL_FALSE;
  44. if (!ksession_exec_locally(session, ptype_entry, pargv, NULL, NULL,
  45. &retcode, &out)) {
  46. return BOOL_FALSE;
  47. }
  48. if (retcode != 0)
  49. return BOOL_FALSE;
  50. if (!faux_str_is_empty(out))
  51. kparg_set_value(candidate, out);
  52. return BOOL_TRUE;
  53. }
  54. static kpargv_status_e ksession_parse_arg(ksession_t *session,
  55. kentry_t *current_entry, faux_argv_node_t **argv_iter,
  56. kpargv_t *pargv, bool_t entry_is_command, bool_t is_filter)
  57. {
  58. kentry_t *entry = current_entry;
  59. kentry_mode_e mode = KENTRY_MODE_NONE;
  60. kpargv_status_e retcode = KPARSE_NONE; // For ENTRY itself
  61. kpargv_status_e rc = KPARSE_NONE; // For nested ENTRYs
  62. kpargv_purpose_e purpose = KPURPOSE_NONE;
  63. //if (kentry_purpose(entry) == KENTRY_PURPOSE_COMMON)
  64. //fprintf(stderr, "PARSE: name=%s, arg=%s, pargs=%d\n",
  65. //kentry_name(entry), faux_argv_current(*argv_iter),
  66. //kpargv_pargs_len(pargv));
  67. assert(current_entry);
  68. if (!current_entry)
  69. return KPARSE_ERROR;
  70. assert(argv_iter);
  71. if (!argv_iter)
  72. return KPARSE_ERROR;
  73. assert(pargv);
  74. if (!pargv)
  75. return KPARSE_ERROR;
  76. purpose = kpargv_purpose(pargv); // Purpose of parsing
  77. // If we know the entry is a command then don't validate it. This
  78. // behaviour is usefull for special purpose entries like PTYPEs, CONDs,
  79. // etc. These entries are the starting point for parsing their args.
  80. // We don't need to parse command itself. Command is predefined.
  81. if (entry_is_command) {
  82. kparg_t *parg = NULL;
  83. // Command is an ENTRY with ACTIONs
  84. if (kentry_actions_len(entry) <= 0)
  85. return KPARSE_ERROR;
  86. parg = kparg_new(entry, NULL);
  87. kpargv_add_pargs(pargv, parg);
  88. kpargv_set_command(pargv, entry);
  89. retcode = KPARSE_OK;
  90. // Is entry candidate to resolve current arg?
  91. // Container can't be a candidate.
  92. } else if (!kentry_container(entry)) {
  93. const char *current_arg = NULL;
  94. kparg_t *parg = NULL;
  95. kentry_filter_e filter_flag = kentry_filter(entry);
  96. // When purpose is COMPLETION or HELP then fill completion list.
  97. // Additionally if it's last continuable argument then lie to
  98. // engine: make all last arguments NOTFOUND. It's necessary to walk
  99. // through all variants to gather all completions.
  100. // is_filter: When it's a filter then all non-first entries can be
  101. // filters or non-filters
  102. if (((KPURPOSE_COMPLETION == purpose) ||
  103. (KPURPOSE_HELP == purpose)) &&
  104. ((filter_flag == KENTRY_FILTER_DUAL) ||
  105. (is_filter && (filter_flag == KENTRY_FILTER_TRUE)) ||
  106. (!is_filter && (filter_flag == KENTRY_FILTER_FALSE)) ||
  107. (is_filter && kpargv_pargs_len(pargv)))) {
  108. if (!*argv_iter) {
  109. // That's time to add entry to completions list.
  110. if (!kpargv_continuable(pargv))
  111. kpargv_add_completions(pargv, entry);
  112. return KPARSE_NOTFOUND;
  113. // Add entry to completions if it's last incompleted arg.
  114. } else if (faux_argv_is_last(*argv_iter) &&
  115. kpargv_continuable(pargv)) {
  116. kpargv_add_completions(pargv, entry);
  117. return KPARSE_NOTFOUND;
  118. }
  119. }
  120. // If all arguments are resolved already then return INCOMPLETED
  121. if (!*argv_iter)
  122. return KPARSE_NOTFOUND;
  123. // Validate argument
  124. current_arg = faux_argv_current(*argv_iter);
  125. parg = kparg_new(entry, current_arg);
  126. kpargv_set_candidate_parg(pargv, parg);
  127. if (ksession_validate_arg(session, pargv)) {
  128. kpargv_accept_candidate_parg(pargv);
  129. // Command is an ENTRY with ACTIONs or NAVigation
  130. if (kentry_actions_len(entry) > 0)
  131. kpargv_set_command(pargv, entry);
  132. faux_argv_each(argv_iter); // Next argument
  133. retcode = KPARSE_OK;
  134. } else {
  135. // It's not a container and is not validated so
  136. // no chance to find anything here.
  137. kpargv_decline_candidate_parg(pargv);
  138. kparg_free(parg);
  139. return KPARSE_NOTFOUND;
  140. }
  141. }
  142. //if (kentry_purpose(entry) == KENTRY_PURPOSE_COMMON)
  143. //fprintf(stderr, "ITSELF: name=%s, retcode=%s\n",
  144. //kentry_name(entry), kpargv_status_decode(retcode));
  145. // It's not container and suitable entry is not found
  146. if (retcode == KPARSE_NOTFOUND)
  147. return retcode;
  148. // ENTRY has no nested ENTRYs so return
  149. if (kentry_entrys_is_empty(entry))
  150. return retcode;
  151. // EMPTY mode
  152. mode = kentry_mode(entry);
  153. if (KENTRY_MODE_EMPTY == mode)
  154. return retcode;
  155. // SWITCH mode
  156. // Entries within SWITCH can't has 'min'/'max' else than 1.
  157. // So these attributes will be ignored. Note SWITCH itself can have
  158. // 'min'/'max'.
  159. if (KENTRY_MODE_SWITCH == mode) {
  160. kentry_entrys_node_t *iter = kentry_entrys_iter(entry);
  161. kentry_t *nested = NULL;
  162. //if (kentry_purpose(entry) == KENTRY_PURPOSE_COMMON)
  163. //fprintf(stderr, "SWITCH: name=%s, arg %s\n", kentry_name(entry),
  164. //*argv_iter ? faux_argv_current(*argv_iter) : "<empty>");
  165. while ((nested = kentry_entrys_each(&iter))) {
  166. kpargv_status_e res = KPARSE_NONE;
  167. // Ignore entries with non-COMMON purpose.
  168. if (kentry_purpose(nested) != KENTRY_PURPOSE_COMMON)
  169. continue;
  170. //if (kentry_purpose(entry) == KENTRY_PURPOSE_COMMON)
  171. //fprintf(stderr, "SWITCH-nested name=%s, nested=%s\n",
  172. //kentry_name(entry), kentry_name(nested));
  173. res = ksession_parse_arg(session, nested, argv_iter,
  174. pargv, BOOL_FALSE, is_filter);
  175. if (res == KPARSE_NONE)
  176. rc = KPARSE_NOTFOUND;
  177. else
  178. rc = res;
  179. //if (kentry_purpose(entry) == KENTRY_PURPOSE_COMMON)
  180. //fprintf(stderr, "SWITCH-nested-answer: name=%s, nested=%s, res=%s\n",
  181. //kentry_name(entry), kentry_name(nested), kpargv_status_decode(res));
  182. // Save choosen entry name to container's value
  183. if ((res == KPARSE_OK) && kentry_container(entry)) {
  184. kparg_t *parg = kparg_new(entry, kentry_name(nested));
  185. kpargv_add_pargs(pargv, parg);
  186. }
  187. // Try next entries if current status is NOTFOUND or NONE
  188. if ((res == KPARSE_OK) || (res == KPARSE_ERROR))
  189. break;
  190. }
  191. // SEQUENCE mode
  192. } else if (KENTRY_MODE_SEQUENCE == mode) {
  193. kentry_entrys_node_t *iter = kentry_entrys_iter(entry);
  194. kentry_entrys_node_t *saved_iter = iter;
  195. kentry_t *nested = NULL;
  196. kpargv_t *cur_level_pargv = kpargv_new();
  197. while ((nested = kentry_entrys_each(&iter))) {
  198. kpargv_status_e res = KPARSE_NONE;
  199. size_t num = 0;
  200. size_t min = kentry_min(nested);
  201. bool_t break_loop = BOOL_FALSE;
  202. bool_t consumed = BOOL_FALSE;
  203. // Ignore entries with non-COMMON purpose.
  204. if (kentry_purpose(nested) != KENTRY_PURPOSE_COMMON)
  205. continue;
  206. // Filter out double parsing for optional entries.
  207. if (kpargv_entry_exists(cur_level_pargv, nested))
  208. continue;
  209. //if (kentry_purpose(entry) == KENTRY_PURPOSE_COMMON)
  210. //fprintf(stderr, "SEQ name=%s, arg=%s\n",
  211. //kentry_name(entry), *argv_iter ? faux_argv_current(*argv_iter) : "<empty>");
  212. // Try to match argument and current entry
  213. // (from 'min' to 'max' times)
  214. for (num = 0; num < kentry_max(nested); num++) {
  215. //if (kentry_purpose(entry) == KENTRY_PURPOSE_COMMON)
  216. //fprintf(stderr, "SEQ-nested: name=%s, nested=%s\n",
  217. //kentry_name(entry), kentry_name(nested));
  218. res = ksession_parse_arg(session, nested,
  219. argv_iter, pargv, BOOL_FALSE, is_filter);
  220. //if (kentry_purpose(entry) == KENTRY_PURPOSE_COMMON)
  221. //fprintf(stderr, "SEQ-nested-answer: name=%s, nested=%s, res=%s, num=%d, min=%d\n",
  222. //kentry_name(entry), kentry_name(nested), kpargv_status_decode(res), num, min);
  223. // It's not an error but there will be not
  224. // additional arguments of the same entry
  225. if ((res == KPARSE_NONE) ||
  226. ((res == KPARSE_NOTFOUND) && (num >= min)))
  227. break;
  228. // Only ERROR, OK or NOTFOUND (with not
  229. // enough arguments) will set rc
  230. rc = res;
  231. // Only OK will continue the loop. Any
  232. // another case will break the loop and ext loop
  233. if (res != KPARSE_OK) {
  234. break_loop = BOOL_TRUE;
  235. break;
  236. }
  237. consumed = BOOL_TRUE;
  238. }
  239. if (break_loop)
  240. break;
  241. if (consumed) {
  242. // Remember if optional parameter was already
  243. // entered
  244. kparg_t *tmp_parg = kparg_new(nested, NULL);
  245. kpargv_add_pargs(cur_level_pargv, tmp_parg);
  246. // SEQ container will get all entered nested
  247. // entry names as value within resulting pargv
  248. if (kentry_container(entry)) {
  249. kparg_t *parg = kparg_new(entry,
  250. kentry_name(nested));
  251. kpargv_add_pargs(pargv, parg);
  252. }
  253. // Mandatory or ordered parameter
  254. if ((min > 0) || kentry_order(nested))
  255. saved_iter = iter;
  256. // If optional entry is found then go back to nearest
  257. // non-optional (or ordered) entry to try to find
  258. // another optional entries.
  259. if ((0 == min) && (num > 0))
  260. iter = saved_iter;
  261. }
  262. }
  263. kpargv_free(cur_level_pargv);
  264. }
  265. if (rc == KPARSE_NONE)
  266. return retcode;
  267. if (retcode == KPARSE_NONE)
  268. return rc;
  269. // If nested result is NOTFOUND but argument was consumed
  270. // by entry itself then whole sequence is ERROR
  271. if ((retcode == KPARSE_OK) && (rc == KPARSE_NOTFOUND))
  272. rc = KPARSE_ERROR;
  273. //if (kentry_purpose(entry) == KENTRY_PURPOSE_COMMON)
  274. //fprintf(stderr, "RET: name=%s, rc=%s\n", kentry_name(entry), kpargv_status_decode(rc));
  275. return rc;
  276. }
  277. kpargv_t *ksession_parse_line(ksession_t *session, const faux_argv_t *argv,
  278. kpargv_purpose_e purpose, bool_t is_filter)
  279. {
  280. faux_argv_node_t *argv_iter = NULL;
  281. kpargv_t *pargv = NULL;
  282. kpargv_status_e pstatus = KPARSE_NONE;
  283. kpath_levels_node_t *levels_iterr = NULL;
  284. klevel_t *level = NULL;
  285. size_t level_found = 0; // Level where command was found
  286. kpath_t *path = NULL;
  287. bool_t dont_parse_upper;
  288. assert(session);
  289. if (!session)
  290. return NULL;
  291. assert(argv);
  292. if (!argv)
  293. return NULL;
  294. argv_iter = faux_argv_iter(argv);
  295. // When the purpose is completion or help and user didn't type
  296. // any text yet then don't show completion/help for the upper
  297. // kpath levels but only for the current one.
  298. // When user enters only single unfinished word then don't show help
  299. // for the upper kpath levels too.
  300. dont_parse_upper = (faux_argv_len(argv) == 0 &&
  301. (purpose == KPURPOSE_COMPLETION || purpose == KPURPOSE_HELP)) ||
  302. (faux_argv_len(argv) == 1 && faux_argv_is_continuable(argv) &&
  303. purpose == KPURPOSE_HELP);
  304. // Initialize kpargv_t
  305. pargv = kpargv_new();
  306. assert(pargv);
  307. kpargv_set_continuable(pargv, faux_argv_is_continuable(argv));
  308. kpargv_set_purpose(pargv, purpose);
  309. // Iterate levels of path from higher to lower. Note the reversed
  310. // iterator will be used.
  311. path = ksession_path(session);
  312. levels_iterr = kpath_iterr(path);
  313. level_found = kpath_len(path) - 1; // Levels begin with '0'
  314. while ((level = kpath_eachr(&levels_iterr))) {
  315. kentry_t *current_entry = klevel_entry(level);
  316. // Ignore entries with non-COMMON purpose. These entries are for
  317. // special processing and will be ignored here.
  318. if (kentry_purpose(current_entry) != KENTRY_PURPOSE_COMMON)
  319. continue;
  320. // Parsing
  321. pstatus = ksession_parse_arg(session, current_entry, &argv_iter,
  322. pargv, BOOL_FALSE, is_filter);
  323. if ((pstatus != KPARSE_NOTFOUND) && (pstatus != KPARSE_NONE))
  324. break;
  325. // NOTFOUND but some args were parsed.
  326. // When it's completion for first argument (that can be continued)
  327. // len == 0 and engine will search for completions on higher
  328. // levels of path.
  329. if (kpargv_pargs_len(pargv) > 0)
  330. break;
  331. if (dont_parse_upper)
  332. break;
  333. level_found--;
  334. }
  335. // Save last argument
  336. if (argv_iter)
  337. kpargv_set_last_arg(pargv, faux_argv_current(argv_iter));
  338. // It's a higher level of parsing, so some statuses can have different
  339. // meanings
  340. if (KPARSE_NONE == pstatus) {
  341. pstatus = KPARSE_ERROR;
  342. } else if (KPARSE_OK == pstatus) {
  343. // Not all args are parsed
  344. if (argv_iter != NULL)
  345. pstatus = KPARSE_ERROR; // Additional not parsable args
  346. // If no ACTIONs were found i.e. command was not found
  347. else if (!kpargv_command(pargv))
  348. pstatus = KPARSE_NOACTION;
  349. } else if (KPARSE_NOTFOUND == pstatus) {
  350. pstatus = KPARSE_ERROR; // Unknown command
  351. }
  352. kpargv_set_status(pargv, pstatus);
  353. kpargv_set_level(pargv, level_found);
  354. return pargv;
  355. }
  356. // Delimeter of commands is '|' (pipe)
  357. faux_list_t *ksession_split_pipes(const char *raw_line, faux_error_t *error)
  358. {
  359. faux_list_t *list = NULL;
  360. faux_argv_t *argv = NULL;
  361. faux_argv_node_t *argv_iter = NULL;
  362. faux_argv_t *cur_argv = NULL; // Current argv
  363. const char *delimeter = "|";
  364. const char *arg = NULL;
  365. assert(raw_line);
  366. if (!raw_line)
  367. return NULL;
  368. // Split raw line to arguments
  369. argv = faux_argv_new();
  370. assert(argv);
  371. if (!argv)
  372. return NULL;
  373. faux_argv_set_quotes(argv, ARGV_ALT_QUOTES);
  374. if (faux_argv_parse(argv, raw_line) < 0) {
  375. faux_argv_free(argv);
  376. return NULL;
  377. }
  378. list = faux_list_new(FAUX_LIST_UNSORTED, FAUX_LIST_NONUNIQUE,
  379. NULL, NULL, (void (*)(void *))faux_argv_free);
  380. assert(list);
  381. if (!list) {
  382. faux_argv_free(argv);
  383. return NULL;
  384. }
  385. argv_iter = faux_argv_iter(argv);
  386. cur_argv = faux_argv_new();
  387. assert(cur_argv);
  388. while ((arg = faux_argv_each(&argv_iter))) {
  389. if (strcmp(arg, delimeter) == 0) {
  390. // End of current line (from "|" to "|")
  391. // '|' in a first position is an error
  392. if (faux_argv_len(cur_argv) == 0) {
  393. faux_argv_free(argv);
  394. faux_list_free(list);
  395. faux_error_sprintf(error, "The pipe '|' can't "
  396. "be at the first position");
  397. return NULL;
  398. }
  399. // Add argv to argv's list
  400. faux_list_add(list, cur_argv);
  401. cur_argv = faux_argv_new();
  402. assert(cur_argv);
  403. } else {
  404. faux_argv_add(cur_argv, arg);
  405. }
  406. }
  407. // Continuable flag is usefull for last argv
  408. faux_argv_set_continuable(cur_argv, faux_argv_is_continuable(argv));
  409. // Empty cur_argv is not an error. It's usefull for completion and help.
  410. // But empty cur_argv and continuable is abnormal.
  411. if ((faux_argv_len(cur_argv) == 0) &&
  412. faux_argv_is_continuable(cur_argv)) {
  413. faux_argv_free(argv);
  414. faux_list_free(list);
  415. faux_error_sprintf(error, "The pipe '|' can't "
  416. "be the last argument");
  417. return NULL;
  418. }
  419. faux_list_add(list, cur_argv);
  420. faux_argv_free(argv);
  421. return list;
  422. }
  423. // is_piped means full command contains more than one piped components
  424. static bool_t ksession_check_line(const kpargv_t *pargv, faux_error_t *error,
  425. bool_t is_first, bool_t is_piped)
  426. {
  427. kpargv_purpose_e purpose = KPURPOSE_EXEC;
  428. const kentry_t *cmd = NULL;
  429. if (!pargv)
  430. return BOOL_FALSE;
  431. purpose = kpargv_purpose(pargv);
  432. cmd = kpargv_command(pargv);
  433. // For execution pargv must be fully correct but for completion
  434. // it's not a case
  435. if ((KPURPOSE_EXEC == purpose) && (kpargv_status(pargv) != KPARSE_OK)) {
  436. faux_error_sprintf(error, "%s", kpargv_status_str(pargv));
  437. return BOOL_FALSE;
  438. }
  439. // Can't check following conditions without cmd
  440. if (!cmd)
  441. return BOOL_TRUE;
  442. // First component
  443. if (is_first) {
  444. // First component can't be a filter
  445. if (kentry_filter(cmd) == KENTRY_FILTER_TRUE) {
  446. faux_error_sprintf(error, "The filter \"%s\" "
  447. "can't be used without previous pipeline",
  448. kentry_name(cmd));
  449. return BOOL_FALSE;
  450. }
  451. // Components after pipe "|"
  452. } else {
  453. // Only the first component can be non-filter
  454. if (kentry_filter(cmd) == KENTRY_FILTER_FALSE) {
  455. faux_error_sprintf(error, "The non-filter command \"%s\" "
  456. "can't be destination of pipe",
  457. kentry_name(cmd));
  458. return BOOL_FALSE;
  459. }
  460. // Only the first component can have 'restore=true' attribute
  461. if (kentry_restore(cmd)) {
  462. faux_error_sprintf(error, "The command \"%s\" "
  463. "can't be destination of pipe",
  464. kentry_name(cmd));
  465. return BOOL_FALSE;
  466. }
  467. }
  468. is_piped = is_piped; // Happy compiler
  469. return BOOL_TRUE;
  470. }
  471. // All components except last one must be legal for execution but last
  472. // component must be parsed for completion.
  473. // Completion is a "back-end" operation so it doesn't need detailed error
  474. // reporting.
  475. kpargv_t *ksession_parse_for_hint(ksession_t *session,
  476. const char *raw_line, kpargv_purpose_e purpose)
  477. {
  478. faux_list_t *split = NULL;
  479. faux_list_node_t *iter = NULL;
  480. kpargv_t *pargv = NULL;
  481. bool_t is_piped = BOOL_FALSE;
  482. assert(session);
  483. if (!session)
  484. return NULL;
  485. assert(raw_line);
  486. if (!raw_line)
  487. return NULL;
  488. // Split raw line (with '|') to components
  489. split = ksession_split_pipes(raw_line, NULL);
  490. if (!split || (faux_list_len(split) < 1)) {
  491. faux_list_free(split);
  492. return NULL;
  493. }
  494. is_piped = (faux_list_len(split) > 1);
  495. iter = faux_list_head(split);
  496. while (iter) {
  497. faux_argv_t *argv = (faux_argv_t *)faux_list_data(iter);
  498. bool_t is_last = (iter == faux_list_tail(split));
  499. bool_t is_first = (iter == faux_list_head(split));
  500. kpargv_purpose_e purp = is_last ? purpose : KPURPOSE_EXEC;
  501. pargv = ksession_parse_line(session, argv, purp, !is_first);
  502. if (!ksession_check_line(pargv, NULL, is_first, is_piped)) {
  503. kpargv_free(pargv);
  504. pargv = NULL;
  505. break;
  506. }
  507. if (!is_last)
  508. kpargv_free(pargv);
  509. iter = faux_list_next_node(iter);
  510. }
  511. faux_list_free(split);
  512. return pargv;
  513. }
  514. kexec_t *ksession_parse_for_exec(ksession_t *session, const char *raw_line,
  515. faux_error_t *error)
  516. {
  517. faux_list_t *split = NULL;
  518. faux_list_node_t *iter = NULL;
  519. kpargv_t *pargv = NULL;
  520. kexec_t *exec = NULL;
  521. bool_t is_piped = BOOL_FALSE;
  522. size_t index = 0;
  523. assert(session);
  524. if (!session)
  525. return NULL;
  526. assert(raw_line);
  527. if (!raw_line)
  528. return NULL;
  529. // Split raw line (with '|') to components
  530. split = ksession_split_pipes(raw_line, error);
  531. if (!split || (faux_list_len(split) < 1)) {
  532. faux_list_free(split);
  533. return NULL;
  534. }
  535. is_piped = (faux_list_len(split) > 1);
  536. // Create exec list
  537. exec = kexec_new(session, KCONTEXT_TYPE_ACTION);
  538. assert(exec);
  539. if (!exec) {
  540. faux_list_free(split);
  541. return NULL;
  542. }
  543. kexec_set_line(exec, raw_line);
  544. iter = faux_list_head(split);
  545. while (iter) {
  546. faux_argv_t *argv = (faux_argv_t *)faux_list_data(iter);
  547. kcontext_t *context = NULL;
  548. bool_t is_first = (iter == faux_list_head(split));
  549. bool_t is_last = (iter == faux_list_tail(split));
  550. char *context_line = NULL;
  551. pargv = ksession_parse_line(session, argv, KPURPOSE_EXEC, !is_first);
  552. // All components must be ready for execution
  553. if (!ksession_check_line(pargv, error, is_first, is_piped)) {
  554. kpargv_free(pargv);
  555. kexec_free(exec);
  556. faux_list_free(split);
  557. return NULL;
  558. }
  559. // Fill the kexec_t
  560. context = kcontext_new(KCONTEXT_TYPE_ACTION);
  561. assert(context);
  562. kcontext_set_scheme(context, ksession_scheme(session));
  563. kcontext_set_pargv(context, pargv);
  564. // Context for ACTION execution contains session
  565. kcontext_set_session(context, session);
  566. context_line = faux_argv_line(argv);
  567. kcontext_set_line(context, context_line);
  568. faux_str_free(context_line);
  569. kcontext_set_pipeline_stage(context, index);
  570. kcontext_set_is_last_pipeline_stage(context, is_last);
  571. if (is_last) {
  572. kcontext_set_bufout(context, kexec_bufout(exec));
  573. kcontext_set_buferr(context, kexec_buferr(exec));
  574. }
  575. kexec_add_contexts(exec, context);
  576. // Next component
  577. iter = faux_list_next_node(iter);
  578. index++;
  579. }
  580. faux_list_free(split);
  581. return exec;
  582. }
  583. kexec_t *ksession_parse_for_local_exec(ksession_t *session, kentry_t *entry,
  584. const kpargv_t *parent_pargv, const kcontext_t *parent_context,
  585. const kexec_t *parent_exec)
  586. {
  587. faux_argv_node_t *argv_iter = NULL;
  588. kpargv_t *pargv = NULL;
  589. kexec_t *exec = NULL;
  590. faux_argv_t *argv = NULL;
  591. kcontext_t *context = NULL;
  592. kpargv_status_e pstatus = KPARSE_NONE;
  593. const char *line = NULL; // TODO: Must be 'line' field of ENTRY
  594. assert(session);
  595. if (!session)
  596. return NULL;
  597. assert(entry);
  598. if (!entry)
  599. return NULL;
  600. exec = kexec_new(session, KCONTEXT_TYPE_SERVICE_ACTION);
  601. assert(exec);
  602. argv = faux_argv_new();
  603. assert(argv);
  604. faux_argv_set_quotes(argv, ARGV_ALT_QUOTES);
  605. faux_argv_parse(argv, line);
  606. argv_iter = faux_argv_iter(argv);
  607. pargv = kpargv_new();
  608. assert(pargv);
  609. kpargv_set_continuable(pargv, faux_argv_is_continuable(argv));
  610. kpargv_set_purpose(pargv, KPURPOSE_EXEC);
  611. pstatus = ksession_parse_arg(session, entry, &argv_iter, pargv,
  612. BOOL_TRUE, BOOL_FALSE);
  613. // Parsing problems
  614. if ((pstatus != KPARSE_OK) || (argv_iter != NULL)) {
  615. kexec_free(exec);
  616. faux_argv_free(argv);
  617. kpargv_free(pargv);
  618. return NULL;
  619. }
  620. context = kcontext_new(KCONTEXT_TYPE_SERVICE_ACTION);
  621. assert(context);
  622. kcontext_set_scheme(context, ksession_scheme(session));
  623. kcontext_set_pargv(context, pargv);
  624. kcontext_set_parent_pargv(context, parent_pargv);
  625. kcontext_set_parent_context(context, parent_context);
  626. kcontext_set_parent_exec(context, parent_exec);
  627. kcontext_set_bufout(context, kexec_bufout(exec));
  628. kcontext_set_session(context, session);
  629. kexec_add_contexts(exec, context);
  630. faux_argv_free(argv);
  631. return exec;
  632. }
  633. static bool_t stop_loop_ev(faux_eloop_t *eloop, faux_eloop_type_e type,
  634. void *associated_data, void *user_data)
  635. {
  636. ksession_t *session = (ksession_t *)user_data;
  637. if (!session)
  638. return BOOL_FALSE;
  639. ksession_set_done(session, BOOL_TRUE); // Stop the whole session
  640. // Happy compiler
  641. eloop = eloop;
  642. type = type;
  643. associated_data = associated_data;
  644. return BOOL_FALSE; // Stop Event Loop
  645. }
  646. static bool_t get_stdout(kexec_t *exec)
  647. {
  648. ssize_t r = -1;
  649. faux_buf_t *faux_buf = NULL;
  650. void *linear_buf = NULL;
  651. int fd = -1;
  652. if (!exec)
  653. return BOOL_FALSE;
  654. fd = kexec_stdout(exec);
  655. assert(fd != -1);
  656. faux_buf = kexec_bufout(exec);
  657. assert(faux_buf);
  658. do {
  659. ssize_t really_readed = 0;
  660. ssize_t linear_len =
  661. faux_buf_dwrite_lock_easy(faux_buf, &linear_buf);
  662. // Non-blocked read. The fd became non-blocked while
  663. // kexec_prepare().
  664. r = read(fd, linear_buf, linear_len);
  665. if (r > 0)
  666. really_readed = r;
  667. faux_buf_dwrite_unlock_easy(faux_buf, really_readed);
  668. } while (r > 0);
  669. return BOOL_TRUE;
  670. }
  671. static bool_t action_terminated_ev(faux_eloop_t *eloop, faux_eloop_type_e type,
  672. void *associated_data, void *user_data)
  673. {
  674. int wstatus = 0;
  675. pid_t child_pid = -1;
  676. kexec_t *exec = (kexec_t *)user_data;
  677. if (!exec)
  678. return BOOL_FALSE;
  679. // Wait for any child process. Doesn't block.
  680. while ((child_pid = waitpid(-1, &wstatus, WNOHANG)) > 0)
  681. kexec_continue_command_execution(exec, child_pid, wstatus);
  682. // Check if kexec is done now
  683. if (kexec_done(exec)) {
  684. // May be buffer still contains data
  685. get_stdout(exec);
  686. return BOOL_FALSE; // To break a loop
  687. }
  688. // Happy compiler
  689. eloop = eloop;
  690. type = type;
  691. associated_data = associated_data;
  692. return BOOL_TRUE;
  693. }
  694. static bool_t action_stdout_ev(faux_eloop_t *eloop, faux_eloop_type_e type,
  695. void *associated_data, void *user_data)
  696. {
  697. kexec_t *exec = (kexec_t *)user_data;
  698. // Happy compiler
  699. eloop = eloop;
  700. type = type;
  701. associated_data = associated_data;
  702. return get_stdout(exec);
  703. }
  704. bool_t ksession_exec_locally(ksession_t *session, kentry_t *entry,
  705. kpargv_t *parent_pargv, const kcontext_t *parent_context,
  706. const kexec_t *parent_exec, int *retcode, char **out)
  707. {
  708. kexec_t *exec = NULL;
  709. faux_eloop_t *eloop = NULL;
  710. faux_buf_t *buf = NULL;
  711. char *cstr = NULL;
  712. ssize_t len = 0;
  713. assert(entry);
  714. if (!entry)
  715. return BOOL_FALSE;
  716. // Parsing
  717. exec = ksession_parse_for_local_exec(session, entry,
  718. parent_pargv, parent_context, parent_exec);
  719. if (!exec)
  720. return BOOL_FALSE;
  721. // Session status can be changed while parsing because it can execute
  722. // nested ksession_exec_locally() to check for PTYPEs, CONDitions etc.
  723. // So check for 'done' flag to propagate it.
  724. // NOTE: Don't interrupt single kexec_t. Let's it to complete.
  725. // if (ksession_done(session)) {
  726. // kexec_free(exec);
  727. // return BOOL_FALSE; // Because action is not completed
  728. // }
  729. // Execute kexec and then wait for completion using local Eloop
  730. if (!kexec_exec(exec)) {
  731. kexec_free(exec);
  732. return BOOL_FALSE; // Something went wrong
  733. }
  734. // If kexec contains only non-exec (for example dry-run) ACTIONs then
  735. // we don't need event loop
  736. if (!kexec_retcode(exec, retcode)) {
  737. // Local service loop
  738. eloop = faux_eloop_new(NULL);
  739. faux_eloop_add_signal(eloop, SIGINT, stop_loop_ev, session);
  740. faux_eloop_add_signal(eloop, SIGTERM, stop_loop_ev, session);
  741. faux_eloop_add_signal(eloop, SIGQUIT, stop_loop_ev, session);
  742. faux_eloop_add_signal(eloop, SIGCHLD, action_terminated_ev, exec);
  743. faux_eloop_add_fd(eloop, kexec_stdout(exec), POLLIN,
  744. action_stdout_ev, exec);
  745. faux_eloop_loop(eloop);
  746. faux_eloop_free(eloop);
  747. kexec_retcode(exec, retcode);
  748. }
  749. if (!out) {
  750. kexec_free(exec);
  751. return BOOL_TRUE;
  752. }
  753. buf = kexec_bufout(exec);
  754. if ((len = faux_buf_len(buf)) <= 0) {
  755. kexec_free(exec);
  756. return BOOL_TRUE;
  757. }
  758. cstr = faux_malloc(len + 1);
  759. faux_buf_read(buf, cstr, len);
  760. cstr[len] = '\0';
  761. *out = cstr;
  762. kexec_free(exec);
  763. return BOOL_TRUE;
  764. }