syms.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  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_set(kcontext_t *context)
  153. {
  154. int ret = 0;
  155. faux_argv_t *args = NULL;
  156. pline_t *pline = NULL;
  157. sr_conn_ctx_t *conn = NULL;
  158. sr_session_ctx_t *sess = NULL;
  159. faux_list_node_t *iter = NULL;
  160. pexpr_t *expr = NULL;
  161. size_t err_num = 0;
  162. faux_argv_t *cur_path = NULL;
  163. kplugin_t *plugin = NULL;
  164. assert(context);
  165. if (sr_connect(SR_CONN_DEFAULT, &conn))
  166. return -1;
  167. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  168. sr_disconnect(conn);
  169. return -1;
  170. }
  171. plugin = kcontext_plugin(context);
  172. cur_path = (faux_argv_t *)kplugin_udata(plugin);
  173. args = param2argv(cur_path, kcontext_pargv(context), "path");
  174. pline = pline_parse(sess, args, 0);
  175. faux_argv_free(args);
  176. if (pline->invalid) {
  177. fprintf(stderr, "Invalid set request\n");
  178. ret = -1;
  179. goto cleanup;
  180. }
  181. iter = faux_list_head(pline->exprs);
  182. while ((expr = (pexpr_t *)faux_list_each(&iter))) {
  183. if (!(expr->pat & PT_SET)) {
  184. err_num++;
  185. fprintf(stderr, "Illegal expression for set operation\n");
  186. break;
  187. }
  188. if (sr_set_item_str(sess, expr->xpath, expr->value, NULL, 0) !=
  189. SR_ERR_OK) {
  190. err_num++;
  191. fprintf(stderr, "Can't set data\n");
  192. break;
  193. }
  194. }
  195. if (sr_has_changes(sess)) {
  196. if (err_num > 0)
  197. sr_discard_changes(sess);
  198. else
  199. sr_apply_changes(sess, 0);
  200. }
  201. if (err_num > 0)
  202. ret = -1;
  203. cleanup:
  204. pline_free(pline);
  205. sr_disconnect(conn);
  206. return ret;
  207. }
  208. int srp_del(kcontext_t *context)
  209. {
  210. int ret = 0;
  211. faux_argv_t *args = NULL;
  212. pline_t *pline = NULL;
  213. sr_conn_ctx_t *conn = NULL;
  214. sr_session_ctx_t *sess = NULL;
  215. pexpr_t *expr = NULL;
  216. size_t err_num = 0;
  217. faux_argv_t *cur_path = NULL;
  218. kplugin_t *plugin = NULL;
  219. assert(context);
  220. if (sr_connect(SR_CONN_DEFAULT, &conn))
  221. return -1;
  222. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  223. sr_disconnect(conn);
  224. return -1;
  225. }
  226. plugin = kcontext_plugin(context);
  227. cur_path = (faux_argv_t *)kplugin_udata(plugin);
  228. args = param2argv(cur_path, kcontext_pargv(context), "path");
  229. pline = pline_parse(sess, args, 0);
  230. faux_argv_free(args);
  231. if (pline->invalid) {
  232. fprintf(stderr, "Invalid 'del' request\n");
  233. ret = -1;
  234. goto cleanup;
  235. }
  236. if (faux_list_len(pline->exprs) > 1) {
  237. fprintf(stderr, "Can't delete more than one object\n");
  238. ret = -1;
  239. goto cleanup;
  240. }
  241. expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs));
  242. if (!(expr->pat & PT_DEL)) {
  243. fprintf(stderr, "Illegal expression for 'del' operation\n");
  244. ret = -1;
  245. goto cleanup;
  246. }
  247. if (sr_delete_item(sess, expr->xpath, 0) != SR_ERR_OK) {
  248. fprintf(stderr, "Can't delete data\n");
  249. ret = -1;
  250. goto cleanup;
  251. }
  252. sr_apply_changes(sess, 0);
  253. cleanup:
  254. pline_free(pline);
  255. sr_disconnect(conn);
  256. return ret;
  257. }
  258. int srp_edit(kcontext_t *context)
  259. {
  260. int ret = 0;
  261. faux_argv_t *args = NULL;
  262. pline_t *pline = NULL;
  263. sr_conn_ctx_t *conn = NULL;
  264. sr_session_ctx_t *sess = NULL;
  265. pexpr_t *expr = NULL;
  266. size_t err_num = 0;
  267. faux_argv_t *cur_path = NULL;
  268. kplugin_t *plugin = NULL;
  269. assert(context);
  270. if (sr_connect(SR_CONN_DEFAULT, &conn))
  271. return -1;
  272. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  273. sr_disconnect(conn);
  274. return -1;
  275. }
  276. plugin = kcontext_plugin(context);
  277. cur_path = (faux_argv_t *)kplugin_udata(plugin);
  278. args = param2argv(cur_path, kcontext_pargv(context), "path");
  279. pline = pline_parse(sess, args, 0);
  280. if (pline->invalid) {
  281. fprintf(stderr, "Invalid 'edit' request\n");
  282. ret = -1;
  283. goto cleanup;
  284. }
  285. if (faux_list_len(pline->exprs) > 1) {
  286. fprintf(stderr, "Can't process more than one object\n");
  287. ret = -1;
  288. goto cleanup;
  289. }
  290. expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs));
  291. if (!(expr->pat & PT_EDIT)) {
  292. fprintf(stderr, "Illegal expression for 'edit' operation\n");
  293. ret = -1;
  294. goto cleanup;
  295. }
  296. if (sr_set_item_str(sess, expr->xpath, NULL, NULL, 0) != SR_ERR_OK) {
  297. fprintf(stderr, "Can't set editing data\n");
  298. ret = -1;
  299. goto cleanup;
  300. }
  301. sr_apply_changes(sess, 0);
  302. // Set new current path
  303. faux_argv_free(cur_path);
  304. kplugin_set_udata(plugin, args);
  305. cleanup:
  306. if (ret < 0)
  307. faux_argv_free(args);
  308. pline_free(pline);
  309. sr_disconnect(conn);
  310. return ret;
  311. }
  312. int srp_top(kcontext_t *context)
  313. {
  314. faux_argv_t *cur_path = NULL;
  315. kplugin_t *plugin = NULL;
  316. assert(context);
  317. plugin = kcontext_plugin(context);
  318. cur_path = (faux_argv_t *)kplugin_udata(plugin);
  319. faux_argv_free(cur_path);
  320. kplugin_set_udata(plugin, NULL);
  321. return 0;
  322. }
  323. int srp_up(kcontext_t *context)
  324. {
  325. sr_conn_ctx_t *conn = NULL;
  326. sr_session_ctx_t *sess = NULL;
  327. faux_argv_t *cur_path = NULL;
  328. kplugin_t *plugin = NULL;
  329. faux_argv_node_t *iter = NULL;
  330. assert(context);
  331. plugin = kcontext_plugin(context);
  332. cur_path = (faux_argv_t *)kplugin_udata(plugin);
  333. if (!cur_path)
  334. return -1; // It's top level and can't level up
  335. if (sr_connect(SR_CONN_DEFAULT, &conn))
  336. return -1;
  337. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  338. sr_disconnect(conn);
  339. return -1;
  340. }
  341. // Remove last arguments one by one and wait for legal edit-like pline
  342. while (faux_argv_len(cur_path) > 0) {
  343. pline_t *pline = NULL;
  344. pexpr_t *expr = NULL;
  345. size_t len = 0;
  346. iter = faux_argv_iterr(cur_path);
  347. faux_argv_del(cur_path, iter);
  348. pline = pline_parse(sess, cur_path, 0);
  349. if (pline->invalid) {
  350. pline_free(pline);
  351. continue;
  352. }
  353. len = faux_list_len(pline->exprs);
  354. if (len != 1) {
  355. pline_free(pline);
  356. continue;
  357. }
  358. expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs));
  359. if (!(expr->pat & PT_EDIT)) {
  360. pline_free(pline);
  361. continue;
  362. }
  363. // Here new path is ok
  364. pline_free(pline);
  365. break;
  366. }
  367. // Don't store empty path
  368. while (faux_argv_len(cur_path) == 0) {
  369. faux_argv_free(cur_path);
  370. kplugin_set_udata(plugin, NULL);
  371. }
  372. sr_disconnect(conn);
  373. return 0;
  374. }