syms.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <assert.h>
  5. #include <syslog.h>
  6. #include <faux/faux.h>
  7. #include <faux/str.h>
  8. #include <faux/argv.h>
  9. #include <faux/list.h>
  10. #include <faux/error.h>
  11. #include <klish/khelper.h>
  12. #include <klish/kplugin.h>
  13. #include <klish/kentry.h>
  14. #include <klish/kscheme.h>
  15. #include <klish/kcontext.h>
  16. #include <klish/kpargv.h>
  17. #include <sysrepo.h>
  18. #include <sysrepo/xpath.h>
  19. #include "pline.h"
  20. #include "syms.h"
  21. static faux_argv_t *param2argv(const faux_argv_t *cur_path,
  22. const kpargv_t *pargv, const char *entry_name)
  23. {
  24. faux_list_node_t *iter = NULL;
  25. faux_list_t *pargs = NULL;
  26. faux_argv_t *args = NULL;
  27. kparg_t *parg = NULL;
  28. assert(pargv);
  29. if (!pargv)
  30. return NULL;
  31. pargs = kpargv_find_multi(pargv, entry_name);
  32. if (cur_path)
  33. args = faux_argv_dup(cur_path);
  34. else
  35. args = faux_argv_new();
  36. iter = faux_list_head(pargs);
  37. while ((parg = (kparg_t *)faux_list_each(&iter))) {
  38. faux_argv_add(args, kparg_value(parg));
  39. }
  40. faux_list_free(pargs);
  41. return args;
  42. }
  43. // Candidate from pargv contains possible begin of current word (that must be
  44. // completed). kpargv's list don't contain candidate but only already parsed
  45. // words.
  46. static int srp_compl_or_help(kcontext_t *context, bool_t help)
  47. {
  48. faux_argv_t *args = NULL;
  49. pline_t *pline = NULL;
  50. sr_conn_ctx_t *conn = NULL;
  51. sr_session_ctx_t *sess = NULL;
  52. const char *entry_name = NULL;
  53. faux_argv_t *cur_path = NULL;
  54. kplugin_t *plugin = NULL;
  55. assert(context);
  56. if (sr_connect(SR_CONN_DEFAULT, &conn))
  57. return -1;
  58. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  59. sr_disconnect(conn);
  60. return -1;
  61. }
  62. plugin = kcontext_plugin(context);
  63. cur_path = (faux_argv_t *)kplugin_udata(plugin);
  64. entry_name = kentry_name(kcontext_candidate_entry(context));
  65. args = param2argv(cur_path, kcontext_parent_pargv(context), entry_name);
  66. pline = pline_parse(sess, args, 0);
  67. faux_argv_free(args);
  68. pline_print_completions(pline, help);
  69. pline_free(pline);
  70. sr_disconnect(conn);
  71. return 0;
  72. }
  73. int srp_compl(kcontext_t *context)
  74. {
  75. return srp_compl_or_help(context, BOOL_FALSE);
  76. }
  77. int srp_help(kcontext_t *context)
  78. {
  79. return srp_compl_or_help(context, BOOL_TRUE);
  80. }
  81. int srp_prompt_edit_path(kcontext_t *context)
  82. {
  83. faux_argv_t *cur_path = NULL;
  84. kplugin_t *plugin = NULL;
  85. char *path = NULL;
  86. assert(context);
  87. plugin = kcontext_plugin(context);
  88. cur_path = (faux_argv_t *)kplugin_udata(plugin);
  89. if (cur_path)
  90. path = faux_argv_line(cur_path);
  91. printf("[edit%s%s]\n", path ? " " : "", path ? path : "");
  92. faux_str_free(path);
  93. return 0;
  94. }
  95. static int srp_check_type(kcontext_t *context,
  96. pt_e not_accepted_nodes,
  97. size_t max_expr_num)
  98. {
  99. faux_argv_t *args = NULL;
  100. pline_t *pline = NULL;
  101. sr_conn_ctx_t *conn = NULL;
  102. sr_session_ctx_t *sess = NULL;
  103. const char *entry_name = NULL;
  104. const char *value = NULL;
  105. pexpr_t *expr = NULL;
  106. size_t expr_num = 0;
  107. faux_argv_t *cur_path = NULL;
  108. kplugin_t *plugin = NULL;
  109. assert(context);
  110. if (sr_connect(SR_CONN_DEFAULT, &conn))
  111. return -1;
  112. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  113. sr_disconnect(conn);
  114. return -1;
  115. }
  116. plugin = kcontext_plugin(context);
  117. cur_path = (faux_argv_t *)kplugin_udata(plugin);
  118. entry_name = kentry_name(kcontext_candidate_entry(context));
  119. value = kcontext_candidate_value(context);
  120. args = param2argv(cur_path, kcontext_parent_pargv(context), entry_name);
  121. if (value)
  122. faux_argv_add(args, value);
  123. pline = pline_parse(sess, args, 0);
  124. faux_argv_free(args);
  125. if (pline->invalid)
  126. return -1;
  127. expr_num = faux_list_len(pline->exprs);
  128. if (expr_num < 1)
  129. return -1;
  130. if ((max_expr_num > 0) && // '0' means unlimited
  131. (expr_num > max_expr_num))
  132. return -1;
  133. expr = pline_current_expr(pline);
  134. if (expr->pat & not_accepted_nodes)
  135. return -1;
  136. pline_free(pline);
  137. sr_disconnect(conn);
  138. return 0;
  139. }
  140. int srp_PLINE_SET(kcontext_t *context)
  141. {
  142. return srp_check_type(context, PT_NOT_SET, 0);
  143. }
  144. int srp_PLINE_DEL(kcontext_t *context)
  145. {
  146. return srp_check_type(context, PT_NOT_DEL, 1);
  147. }
  148. int srp_PLINE_EDIT(kcontext_t *context)
  149. {
  150. return srp_check_type(context, PT_NOT_EDIT, 1);
  151. }
  152. int srp_PLINE_INSERT_FROM(kcontext_t *context)
  153. {
  154. return srp_check_type(context, PT_NOT_INSERT, 1);
  155. }
  156. static faux_argv_t *assemble_insert_to(sr_session_ctx_t *sess, const kpargv_t *pargv,
  157. faux_argv_t *cur_path, const char *candidate_value)
  158. {
  159. faux_argv_t *args = NULL;
  160. faux_argv_t *insert_to = NULL;
  161. pline_t *pline = NULL;
  162. pexpr_t *expr = NULL;
  163. size_t i = 0;
  164. assert(sess);
  165. args = param2argv(cur_path, pargv, "from_path");
  166. pline = pline_parse(sess, args, 0);
  167. expr = pline_current_expr(pline);
  168. for (i = 0; i < (expr->args_num - expr->list_pos); i++) {
  169. faux_argv_node_t *iter = faux_argv_iterr(args);
  170. faux_argv_del(args, iter);
  171. }
  172. insert_to = param2argv(args, pargv, "to_path");
  173. faux_argv_free(args);
  174. if (candidate_value)
  175. faux_argv_add(insert_to, candidate_value);
  176. pline_free(pline);
  177. return insert_to;
  178. }
  179. int srp_PLINE_INSERT_TO(kcontext_t *context)
  180. {
  181. return srp_check_type(context, PT_NOT_INSERT, 1);
  182. }
  183. int srp_set(kcontext_t *context)
  184. {
  185. int ret = 0;
  186. faux_argv_t *args = NULL;
  187. pline_t *pline = NULL;
  188. sr_conn_ctx_t *conn = NULL;
  189. sr_session_ctx_t *sess = NULL;
  190. faux_list_node_t *iter = NULL;
  191. pexpr_t *expr = NULL;
  192. size_t err_num = 0;
  193. faux_argv_t *cur_path = NULL;
  194. kplugin_t *plugin = NULL;
  195. assert(context);
  196. if (sr_connect(SR_CONN_DEFAULT, &conn))
  197. return -1;
  198. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  199. sr_disconnect(conn);
  200. return -1;
  201. }
  202. plugin = kcontext_plugin(context);
  203. cur_path = (faux_argv_t *)kplugin_udata(plugin);
  204. args = param2argv(cur_path, kcontext_pargv(context), "path");
  205. pline = pline_parse(sess, args, 0);
  206. faux_argv_free(args);
  207. if (pline->invalid) {
  208. fprintf(stderr, "Invalid set request\n");
  209. ret = -1;
  210. goto cleanup;
  211. }
  212. iter = faux_list_head(pline->exprs);
  213. while ((expr = (pexpr_t *)faux_list_each(&iter))) {
  214. if (!(expr->pat & PT_SET)) {
  215. err_num++;
  216. fprintf(stderr, "Illegal expression for set operation\n");
  217. break;
  218. }
  219. if (sr_set_item_str(sess, expr->xpath, expr->value, NULL, 0) !=
  220. SR_ERR_OK) {
  221. err_num++;
  222. fprintf(stderr, "Can't set data\n");
  223. break;
  224. }
  225. }
  226. if (sr_has_changes(sess)) {
  227. if (err_num > 0)
  228. sr_discard_changes(sess);
  229. else
  230. sr_apply_changes(sess, 0);
  231. }
  232. if (err_num > 0)
  233. ret = -1;
  234. cleanup:
  235. pline_free(pline);
  236. sr_disconnect(conn);
  237. return ret;
  238. }
  239. int srp_del(kcontext_t *context)
  240. {
  241. int ret = 0;
  242. faux_argv_t *args = NULL;
  243. pline_t *pline = NULL;
  244. sr_conn_ctx_t *conn = NULL;
  245. sr_session_ctx_t *sess = NULL;
  246. pexpr_t *expr = NULL;
  247. size_t err_num = 0;
  248. faux_argv_t *cur_path = NULL;
  249. kplugin_t *plugin = NULL;
  250. assert(context);
  251. if (sr_connect(SR_CONN_DEFAULT, &conn))
  252. return -1;
  253. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  254. sr_disconnect(conn);
  255. return -1;
  256. }
  257. plugin = kcontext_plugin(context);
  258. cur_path = (faux_argv_t *)kplugin_udata(plugin);
  259. args = param2argv(cur_path, kcontext_pargv(context), "path");
  260. pline = pline_parse(sess, args, 0);
  261. faux_argv_free(args);
  262. if (pline->invalid) {
  263. fprintf(stderr, "Invalid 'del' request\n");
  264. ret = -1;
  265. goto cleanup;
  266. }
  267. if (faux_list_len(pline->exprs) > 1) {
  268. fprintf(stderr, "Can't delete more than one object\n");
  269. ret = -1;
  270. goto cleanup;
  271. }
  272. expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs));
  273. if (!(expr->pat & PT_DEL)) {
  274. fprintf(stderr, "Illegal expression for 'del' operation\n");
  275. ret = -1;
  276. goto cleanup;
  277. }
  278. if (sr_delete_item(sess, expr->xpath, 0) != SR_ERR_OK) {
  279. fprintf(stderr, "Can't delete data\n");
  280. ret = -1;
  281. goto cleanup;
  282. }
  283. sr_apply_changes(sess, 0);
  284. cleanup:
  285. pline_free(pline);
  286. sr_disconnect(conn);
  287. return ret;
  288. }
  289. int srp_edit(kcontext_t *context)
  290. {
  291. int ret = 0;
  292. faux_argv_t *args = NULL;
  293. pline_t *pline = NULL;
  294. sr_conn_ctx_t *conn = NULL;
  295. sr_session_ctx_t *sess = NULL;
  296. pexpr_t *expr = NULL;
  297. size_t err_num = 0;
  298. faux_argv_t *cur_path = NULL;
  299. kplugin_t *plugin = NULL;
  300. assert(context);
  301. if (sr_connect(SR_CONN_DEFAULT, &conn))
  302. return -1;
  303. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  304. sr_disconnect(conn);
  305. return -1;
  306. }
  307. plugin = kcontext_plugin(context);
  308. cur_path = (faux_argv_t *)kplugin_udata(plugin);
  309. args = param2argv(cur_path, kcontext_pargv(context), "path");
  310. pline = pline_parse(sess, args, 0);
  311. if (pline->invalid) {
  312. fprintf(stderr, "Invalid 'edit' request\n");
  313. ret = -1;
  314. goto cleanup;
  315. }
  316. if (faux_list_len(pline->exprs) > 1) {
  317. fprintf(stderr, "Can't process more than one object\n");
  318. ret = -1;
  319. goto cleanup;
  320. }
  321. expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs));
  322. if (!(expr->pat & PT_EDIT)) {
  323. fprintf(stderr, "Illegal expression for 'edit' operation\n");
  324. ret = -1;
  325. goto cleanup;
  326. }
  327. if (sr_set_item_str(sess, expr->xpath, NULL, NULL, 0) != SR_ERR_OK) {
  328. fprintf(stderr, "Can't set editing data\n");
  329. ret = -1;
  330. goto cleanup;
  331. }
  332. sr_apply_changes(sess, 0);
  333. // Set new current path
  334. faux_argv_free(cur_path);
  335. kplugin_set_udata(plugin, args);
  336. cleanup:
  337. if (ret < 0)
  338. faux_argv_free(args);
  339. pline_free(pline);
  340. sr_disconnect(conn);
  341. return ret;
  342. }
  343. int srp_top(kcontext_t *context)
  344. {
  345. faux_argv_t *cur_path = NULL;
  346. kplugin_t *plugin = NULL;
  347. assert(context);
  348. plugin = kcontext_plugin(context);
  349. cur_path = (faux_argv_t *)kplugin_udata(plugin);
  350. faux_argv_free(cur_path);
  351. kplugin_set_udata(plugin, NULL);
  352. return 0;
  353. }
  354. int srp_up(kcontext_t *context)
  355. {
  356. sr_conn_ctx_t *conn = NULL;
  357. sr_session_ctx_t *sess = NULL;
  358. faux_argv_t *cur_path = NULL;
  359. kplugin_t *plugin = NULL;
  360. faux_argv_node_t *iter = NULL;
  361. assert(context);
  362. plugin = kcontext_plugin(context);
  363. cur_path = (faux_argv_t *)kplugin_udata(plugin);
  364. if (!cur_path)
  365. return -1; // It's top level and can't level up
  366. if (sr_connect(SR_CONN_DEFAULT, &conn))
  367. return -1;
  368. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  369. sr_disconnect(conn);
  370. return -1;
  371. }
  372. // Remove last arguments one by one and wait for legal edit-like pline
  373. while (faux_argv_len(cur_path) > 0) {
  374. pline_t *pline = NULL;
  375. pexpr_t *expr = NULL;
  376. size_t len = 0;
  377. iter = faux_argv_iterr(cur_path);
  378. faux_argv_del(cur_path, iter);
  379. pline = pline_parse(sess, cur_path, 0);
  380. if (pline->invalid) {
  381. pline_free(pline);
  382. continue;
  383. }
  384. len = faux_list_len(pline->exprs);
  385. if (len != 1) {
  386. pline_free(pline);
  387. continue;
  388. }
  389. expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs));
  390. if (!(expr->pat & PT_EDIT)) {
  391. pline_free(pline);
  392. continue;
  393. }
  394. // Here new path is ok
  395. pline_free(pline);
  396. break;
  397. }
  398. // Don't store empty path
  399. while (faux_argv_len(cur_path) == 0) {
  400. faux_argv_free(cur_path);
  401. kplugin_set_udata(plugin, NULL);
  402. }
  403. sr_disconnect(conn);
  404. return 0;
  405. }
  406. int srp_insert(kcontext_t *context)
  407. {
  408. int ret = 0;
  409. faux_argv_t *args = NULL;
  410. pline_t *pline = NULL;
  411. sr_conn_ctx_t *conn = NULL;
  412. sr_session_ctx_t *sess = NULL;
  413. faux_list_node_t *iter = NULL;
  414. pexpr_t *expr = NULL;
  415. size_t err_num = 0;
  416. faux_argv_t *cur_path = NULL;
  417. kplugin_t *plugin = NULL;
  418. faux_argv_t *insert_to = NULL;
  419. assert(context);
  420. if (sr_connect(SR_CONN_DEFAULT, &conn))
  421. return -1;
  422. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  423. sr_disconnect(conn);
  424. return -1;
  425. }
  426. plugin = kcontext_plugin(context);
  427. cur_path = (faux_argv_t *)kplugin_udata(plugin);
  428. insert_to = assemble_insert_to(sess, kcontext_pargv(context),
  429. cur_path, NULL);
  430. printf("insert_to: %s\n", faux_argv_line(insert_to));
  431. faux_argv_free(insert_to);
  432. /*
  433. args = param2argv(cur_path, kcontext_pargv(context), "path");
  434. pline = pline_parse(sess, args, 0);
  435. faux_argv_free(args);
  436. if (pline->invalid) {
  437. fprintf(stderr, "Invalid set request\n");
  438. ret = -1;
  439. goto cleanup;
  440. }
  441. iter = faux_list_head(pline->exprs);
  442. while ((expr = (pexpr_t *)faux_list_each(&iter))) {
  443. if (!(expr->pat & PT_SET)) {
  444. err_num++;
  445. fprintf(stderr, "Illegal expression for set operation\n");
  446. break;
  447. }
  448. if (sr_set_item_str(sess, expr->xpath, expr->value, NULL, 0) !=
  449. SR_ERR_OK) {
  450. err_num++;
  451. fprintf(stderr, "Can't set data\n");
  452. break;
  453. }
  454. }
  455. if (sr_has_changes(sess)) {
  456. if (err_num > 0)
  457. sr_discard_changes(sess);
  458. else
  459. sr_apply_changes(sess, 0);
  460. }
  461. if (err_num > 0)
  462. ret = -1;
  463. cleanup:
  464. pline_free(pline);
  465. */ sr_disconnect(conn);
  466. return ret;
  467. }