syms.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  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. static faux_argv_t *param2argv(const kpargv_t *pargv, const char *entry_name)
  21. {
  22. faux_list_node_t *iter = NULL;
  23. faux_list_t *pargs = NULL;
  24. faux_argv_t *args = NULL;
  25. kparg_t *parg = NULL;
  26. assert(pargv);
  27. if (!pargv)
  28. return NULL;
  29. pargs = kpargv_find_multi(pargv, entry_name);
  30. args = faux_argv_new();
  31. iter = faux_list_head(pargs);
  32. while ((parg = (kparg_t *)faux_list_each(&iter))) {
  33. faux_argv_add(args, kparg_value(parg));
  34. }
  35. faux_list_free(pargs);
  36. return args;
  37. }
  38. // Candidate from pargv contains possible begin of current word (that must be
  39. // completed). kpargv's list don't contain candidate but only already parsed
  40. // words.
  41. static int srp_compl_or_help(kcontext_t *context, bool_t help)
  42. {
  43. faux_argv_t *args = NULL;
  44. pline_t *pline = NULL;
  45. sr_conn_ctx_t *conn = NULL;
  46. sr_session_ctx_t *sess = NULL;
  47. const char *entry_name = NULL;
  48. assert(context);
  49. if (sr_connect(SR_CONN_DEFAULT, &conn))
  50. return -1;
  51. if (sr_session_start(conn, SR_DS_RUNNING, &sess)) {
  52. sr_disconnect(conn);
  53. return -1;
  54. }
  55. entry_name = kentry_name(kcontext_candidate_entry(context));
  56. args = param2argv(kcontext_parent_pargv(context), entry_name);
  57. pline = pline_parse(sess, args, 0);
  58. faux_argv_free(args);
  59. pline_print_completions(pline, help);
  60. pline_free(pline);
  61. sr_disconnect(conn);
  62. return 0;
  63. }
  64. int srp_compl(kcontext_t *context)
  65. {
  66. return srp_compl_or_help(context, BOOL_FALSE);
  67. }
  68. int srp_help(kcontext_t *context)
  69. {
  70. return srp_compl_or_help(context, BOOL_TRUE);
  71. }
  72. static int srp_check_type(kcontext_t *context,
  73. pt_e not_accepted_nodes,
  74. size_t max_expr_num)
  75. {
  76. faux_argv_t *args = NULL;
  77. pline_t *pline = NULL;
  78. sr_conn_ctx_t *conn = NULL;
  79. sr_session_ctx_t *sess = NULL;
  80. const char *entry_name = NULL;
  81. const char *value = NULL;
  82. pexpr_t *expr = NULL;
  83. size_t expr_num = 0;
  84. assert(context);
  85. if (sr_connect(SR_CONN_DEFAULT, &conn))
  86. return -1;
  87. if (sr_session_start(conn, SR_DS_RUNNING, &sess)) {
  88. sr_disconnect(conn);
  89. return -1;
  90. }
  91. entry_name = kentry_name(kcontext_candidate_entry(context));
  92. value = kcontext_candidate_value(context);
  93. args = param2argv(kcontext_parent_pargv(context), entry_name);
  94. if (value)
  95. faux_argv_add(args, value);
  96. pline = pline_parse(sess, args, 0);
  97. faux_argv_free(args);
  98. if (pline->invalid)
  99. return -1;
  100. expr_num = faux_list_len(pline->exprs);
  101. if (expr_num < 1)
  102. return -1;
  103. if ((max_expr_num > 0) && // '0' means unlimited
  104. (expr_num > max_expr_num))
  105. return -1;
  106. expr = pline_current_expr(pline);
  107. if (expr->pat & not_accepted_nodes)
  108. return -1;
  109. pline_free(pline);
  110. sr_disconnect(conn);
  111. return 0;
  112. }
  113. int srp_PLINE_SET(kcontext_t *context)
  114. {
  115. return srp_check_type(context, PT_NOT_SET, 0);
  116. }
  117. int srp_PLINE_DEL(kcontext_t *context)
  118. {
  119. return srp_check_type(context, PT_NOT_DEL, 1);
  120. }
  121. int srp_PLINE_EDIT(kcontext_t *context)
  122. {
  123. return srp_check_type(context, PT_NOT_EDIT, 1);
  124. }
  125. int srp_set(kcontext_t *context)
  126. {
  127. int ret = 0;
  128. faux_argv_t *args = NULL;
  129. pline_t *pline = NULL;
  130. sr_conn_ctx_t *conn = NULL;
  131. sr_session_ctx_t *sess = NULL;
  132. faux_list_node_t *iter = NULL;
  133. pexpr_t *expr = NULL;
  134. size_t err_num = 0;
  135. assert(context);
  136. if (sr_connect(SR_CONN_DEFAULT, &conn))
  137. return -1;
  138. if (sr_session_start(conn, SR_DS_RUNNING, &sess)) {
  139. sr_disconnect(conn);
  140. return -1;
  141. }
  142. args = param2argv(kcontext_pargv(context), "path");
  143. pline = pline_parse(sess, args, 0);
  144. faux_argv_free(args);
  145. if (pline->invalid) {
  146. fprintf(stderr, "Invalid set request\n");
  147. ret = -1;
  148. goto cleanup;
  149. }
  150. iter = faux_list_head(pline->exprs);
  151. while ((expr = (pexpr_t *)faux_list_each(&iter))) {
  152. if (!(expr->pat & PT_SET)) {
  153. err_num++;
  154. fprintf(stderr, "Illegal expression for set operation\n");
  155. break;
  156. }
  157. if (sr_set_item_str(sess, expr->xpath, expr->value, NULL, 0) !=
  158. SR_ERR_OK) {
  159. err_num++;
  160. fprintf(stderr, "Can't set data\n");
  161. break;
  162. }
  163. }
  164. if (sr_has_changes(sess)) {
  165. if (err_num > 0)
  166. sr_discard_changes(sess);
  167. else
  168. sr_apply_changes(sess, 0);
  169. }
  170. if (err_num > 0)
  171. ret = -1;
  172. cleanup:
  173. pline_free(pline);
  174. sr_disconnect(conn);
  175. return ret;
  176. }
  177. int srp_del(kcontext_t *context)
  178. {
  179. int ret = 0;
  180. faux_argv_t *args = NULL;
  181. pline_t *pline = NULL;
  182. sr_conn_ctx_t *conn = NULL;
  183. sr_session_ctx_t *sess = NULL;
  184. pexpr_t *expr = NULL;
  185. size_t err_num = 0;
  186. assert(context);
  187. if (sr_connect(SR_CONN_DEFAULT, &conn))
  188. return -1;
  189. if (sr_session_start(conn, SR_DS_RUNNING, &sess)) {
  190. sr_disconnect(conn);
  191. return -1;
  192. }
  193. args = param2argv(kcontext_pargv(context), "path");
  194. pline = pline_parse(sess, args, 0);
  195. faux_argv_free(args);
  196. if (pline->invalid) {
  197. fprintf(stderr, "Invalid 'del' request\n");
  198. ret = -1;
  199. goto cleanup;
  200. }
  201. if (faux_list_len(pline->exprs) > 1) {
  202. fprintf(stderr, "Can't delete more than one object\n");
  203. ret = -1;
  204. goto cleanup;
  205. }
  206. expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs));
  207. if (!(expr->pat & PT_DEL)) {
  208. fprintf(stderr, "Illegal expression for 'del' operation\n");
  209. ret = -1;
  210. goto cleanup;
  211. }
  212. if (sr_delete_item(sess, expr->xpath, 0) != SR_ERR_OK) {
  213. fprintf(stderr, "Can't delete data\n");
  214. ret = -1;
  215. goto cleanup;
  216. }
  217. sr_apply_changes(sess, 0);
  218. cleanup:
  219. pline_free(pline);
  220. sr_disconnect(conn);
  221. return ret;
  222. }
  223. int srp_edit(kcontext_t *context)
  224. {
  225. int ret = 0;
  226. faux_argv_t *args = NULL;
  227. pline_t *pline = NULL;
  228. sr_conn_ctx_t *conn = NULL;
  229. sr_session_ctx_t *sess = NULL;
  230. pexpr_t *expr = NULL;
  231. size_t err_num = 0;
  232. faux_argv_t *cur_path = NULL;
  233. assert(context);
  234. if (sr_connect(SR_CONN_DEFAULT, &conn))
  235. return -1;
  236. if (sr_session_start(conn, SR_DS_RUNNING, &sess)) {
  237. sr_disconnect(conn);
  238. return -1;
  239. }
  240. cur_path = (faux_argv_t *)kplugin_udata(kcontext_plugin(context));
  241. args = param2argv(kcontext_pargv(context), "path");
  242. pline = pline_parse(sess, args, 0);
  243. if (pline->invalid) {
  244. fprintf(stderr, "Invalid 'edit' request\n");
  245. ret = -1;
  246. goto cleanup;
  247. }
  248. if (faux_list_len(pline->exprs) > 1) {
  249. fprintf(stderr, "Can't process more than one object\n");
  250. ret = -1;
  251. goto cleanup;
  252. }
  253. expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs));
  254. if (!(expr->pat & PT_EDIT)) {
  255. fprintf(stderr, "Illegal expression for 'edit' operation\n");
  256. ret = -1;
  257. goto cleanup;
  258. }
  259. if (sr_set_item_str(sess, expr->xpath, NULL, NULL, 0) != SR_ERR_OK) {
  260. fprintf(stderr, "Can't set editing data\n");
  261. ret = -1;
  262. goto cleanup;
  263. }
  264. sr_apply_changes(sess, 0);
  265. if (sr_delete_item(sess, expr->xpath, 0) != SR_ERR_OK) {
  266. fprintf(stderr, "Can't delete data\n");
  267. ret = -1;
  268. goto cleanup;
  269. }
  270. cleanup:
  271. if (ret < 0)
  272. faux_argv_free(args);
  273. pline_free(pline);
  274. sr_disconnect(conn);
  275. return ret;
  276. }