syms.c 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195
  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 <sysrepo/values.h>
  20. #include "pline.h"
  21. #include "private.h"
  22. #define ERRORMSG "Error: "
  23. static void _log(LY_LOG_LEVEL level, const char *msg, const char *path)
  24. {
  25. fprintf(stderr, ERRORMSG "%s %s\n", msg, path ? path : "");
  26. }
  27. int srp_set_log_func(void)
  28. {
  29. ly_set_log_clb(_log, 1);
  30. return 0;
  31. }
  32. static faux_argv_t *param2argv(const faux_argv_t *cur_path,
  33. const kpargv_t *pargv, const char *entry_name)
  34. {
  35. faux_list_node_t *iter = NULL;
  36. faux_list_t *pargs = NULL;
  37. faux_argv_t *args = NULL;
  38. kparg_t *parg = NULL;
  39. assert(pargv);
  40. if (!pargv)
  41. return NULL;
  42. pargs = kpargv_find_multi(pargv, entry_name);
  43. if (cur_path)
  44. args = faux_argv_dup(cur_path);
  45. else
  46. args = faux_argv_new();
  47. iter = faux_list_head(pargs);
  48. while ((parg = (kparg_t *)faux_list_each(&iter))) {
  49. faux_argv_add(args, kparg_value(parg));
  50. }
  51. faux_list_free(pargs);
  52. return args;
  53. }
  54. // Candidate from pargv contains possible begin of current word (that must be
  55. // completed). kpargv's list don't contain candidate but only already parsed
  56. // words.
  57. static int srp_compl_or_help(kcontext_t *context, bool_t help)
  58. {
  59. faux_argv_t *args = NULL;
  60. pline_t *pline = NULL;
  61. sr_conn_ctx_t *conn = NULL;
  62. sr_session_ctx_t *sess = NULL;
  63. const char *entry_name = NULL;
  64. faux_argv_t *cur_path = NULL;
  65. assert(context);
  66. if (sr_connect(SR_CONN_DEFAULT, &conn))
  67. return -1;
  68. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  69. sr_disconnect(conn);
  70. return -1;
  71. }
  72. cur_path = (faux_argv_t *)srp_udata_path(context);
  73. entry_name = kentry_name(kcontext_candidate_entry(context));
  74. args = param2argv(cur_path, kcontext_parent_pargv(context), entry_name);
  75. pline = pline_parse(sess, args, srp_udata_opts(context));
  76. faux_argv_free(args);
  77. pline_print_completions(pline, help);
  78. pline_free(pline);
  79. sr_disconnect(conn);
  80. return 0;
  81. }
  82. int srp_compl(kcontext_t *context)
  83. {
  84. return srp_compl_or_help(context, BOOL_FALSE);
  85. }
  86. int srp_help(kcontext_t *context)
  87. {
  88. return srp_compl_or_help(context, BOOL_TRUE);
  89. }
  90. int srp_prompt_edit_path(kcontext_t *context)
  91. {
  92. faux_argv_t *cur_path = NULL;
  93. char *path = NULL;
  94. assert(context);
  95. cur_path = (faux_argv_t *)srp_udata_path(context);
  96. if (cur_path)
  97. path = faux_argv_line(cur_path);
  98. printf("[edit%s%s]\n", path ? " " : "", path ? path : "");
  99. faux_str_free(path);
  100. return 0;
  101. }
  102. static int srp_check_type(kcontext_t *context,
  103. pt_e not_accepted_nodes,
  104. size_t max_expr_num)
  105. {
  106. int ret = -1;
  107. faux_argv_t *args = NULL;
  108. pline_t *pline = NULL;
  109. sr_conn_ctx_t *conn = NULL;
  110. sr_session_ctx_t *sess = NULL;
  111. const char *entry_name = NULL;
  112. const char *value = NULL;
  113. pexpr_t *expr = NULL;
  114. size_t expr_num = 0;
  115. faux_argv_t *cur_path = NULL;
  116. assert(context);
  117. if (sr_connect(SR_CONN_DEFAULT, &conn))
  118. return -1;
  119. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  120. sr_disconnect(conn);
  121. return -1;
  122. }
  123. cur_path = (faux_argv_t *)srp_udata_path(context);
  124. entry_name = kentry_name(kcontext_candidate_entry(context));
  125. value = kcontext_candidate_value(context);
  126. args = param2argv(cur_path, kcontext_parent_pargv(context), entry_name);
  127. if (value)
  128. faux_argv_add(args, value);
  129. pline = pline_parse(sess, args, srp_udata_opts(context));
  130. faux_argv_free(args);
  131. if (pline->invalid)
  132. goto err;
  133. expr_num = faux_list_len(pline->exprs);
  134. if (expr_num < 1)
  135. goto err;
  136. if ((max_expr_num > 0) && // '0' means unlimited
  137. (expr_num > max_expr_num))
  138. goto err;
  139. expr = pline_current_expr(pline);
  140. if (expr->pat & not_accepted_nodes)
  141. goto err;
  142. ret = 0;
  143. err:
  144. pline_free(pline);
  145. sr_disconnect(conn);
  146. return ret;
  147. }
  148. int srp_PLINE_SET(kcontext_t *context)
  149. {
  150. return srp_check_type(context, PT_NOT_SET, 0);
  151. }
  152. int srp_PLINE_DEL(kcontext_t *context)
  153. {
  154. return srp_check_type(context, PT_NOT_DEL, 1);
  155. }
  156. int srp_PLINE_EDIT(kcontext_t *context)
  157. {
  158. return srp_check_type(context, PT_NOT_EDIT, 1);
  159. }
  160. int srp_PLINE_INSERT_FROM(kcontext_t *context)
  161. {
  162. return srp_check_type(context, PT_NOT_INSERT, 1);
  163. }
  164. static faux_argv_t *assemble_insert_to(sr_session_ctx_t *sess, const kpargv_t *pargv,
  165. faux_argv_t *cur_path, const char *candidate_value, pline_opts_t *opts)
  166. {
  167. faux_argv_t *args = NULL;
  168. faux_argv_t *insert_to = NULL;
  169. pline_t *pline = NULL;
  170. pexpr_t *expr = NULL;
  171. size_t i = 0;
  172. assert(sess);
  173. args = param2argv(cur_path, pargv, "from_path");
  174. pline = pline_parse(sess, args, opts);
  175. expr = pline_current_expr(pline);
  176. for (i = 0; i < (expr->args_num - expr->list_pos); i++) {
  177. faux_argv_node_t *iter = faux_argv_iterr(args);
  178. faux_argv_del(args, iter);
  179. }
  180. insert_to = param2argv(args, pargv, "to_path");
  181. faux_argv_free(args);
  182. if (candidate_value)
  183. faux_argv_add(insert_to, candidate_value);
  184. pline_free(pline);
  185. return insert_to;
  186. }
  187. int srp_PLINE_INSERT_TO(kcontext_t *context)
  188. {
  189. int ret = -1;
  190. faux_argv_t *args = NULL;
  191. pline_t *pline = NULL;
  192. sr_conn_ctx_t *conn = NULL;
  193. sr_session_ctx_t *sess = NULL;
  194. const char *value = NULL;
  195. pexpr_t *expr = NULL;
  196. size_t expr_num = 0;
  197. faux_argv_t *cur_path = NULL;
  198. assert(context);
  199. if (sr_connect(SR_CONN_DEFAULT, &conn))
  200. return -1;
  201. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  202. sr_disconnect(conn);
  203. return -1;
  204. }
  205. cur_path = (faux_argv_t *)srp_udata_path(context);
  206. value = kcontext_candidate_value(context);
  207. args = assemble_insert_to(sess, kcontext_parent_pargv(context),
  208. cur_path, value, srp_udata_opts(context));
  209. pline = pline_parse(sess, args, srp_udata_opts(context));
  210. faux_argv_free(args);
  211. if (pline->invalid)
  212. goto err;
  213. expr_num = faux_list_len(pline->exprs);
  214. if (expr_num != 1)
  215. goto err;
  216. expr = pline_current_expr(pline);
  217. if (expr->pat & PT_NOT_INSERT)
  218. goto err;
  219. ret = 0;
  220. err:
  221. pline_free(pline);
  222. sr_disconnect(conn);
  223. return ret;
  224. }
  225. static int srp_compl_or_help_insert_to(kcontext_t *context, bool_t help)
  226. {
  227. faux_argv_t *args = NULL;
  228. pline_t *pline = NULL;
  229. sr_conn_ctx_t *conn = NULL;
  230. sr_session_ctx_t *sess = NULL;
  231. faux_argv_t *cur_path = NULL;
  232. assert(context);
  233. if (sr_connect(SR_CONN_DEFAULT, &conn))
  234. return -1;
  235. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  236. sr_disconnect(conn);
  237. return -1;
  238. }
  239. cur_path = (faux_argv_t *)srp_udata_path(context);
  240. args = assemble_insert_to(sess, kcontext_parent_pargv(context),
  241. cur_path, NULL, srp_udata_opts(context));
  242. pline = pline_parse(sess, args, srp_udata_opts(context));
  243. faux_argv_free(args);
  244. pline_print_completions(pline, help);
  245. pline_free(pline);
  246. sr_disconnect(conn);
  247. return 0;
  248. }
  249. int srp_compl_insert_to(kcontext_t *context)
  250. {
  251. return srp_compl_or_help_insert_to(context, BOOL_FALSE);
  252. }
  253. int srp_help_insert_to(kcontext_t *context)
  254. {
  255. return srp_compl_or_help_insert_to(context, BOOL_TRUE);
  256. }
  257. int srp_set(kcontext_t *context)
  258. {
  259. int ret = 0;
  260. faux_argv_t *args = NULL;
  261. pline_t *pline = NULL;
  262. sr_conn_ctx_t *conn = NULL;
  263. sr_session_ctx_t *sess = NULL;
  264. faux_list_node_t *iter = NULL;
  265. pexpr_t *expr = NULL;
  266. size_t err_num = 0;
  267. faux_argv_t *cur_path = NULL;
  268. assert(context);
  269. if (sr_connect(SR_CONN_DEFAULT, &conn))
  270. return -1;
  271. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  272. sr_disconnect(conn);
  273. return -1;
  274. }
  275. cur_path = (faux_argv_t *)srp_udata_path(context);
  276. args = param2argv(cur_path, kcontext_pargv(context), "path");
  277. pline = pline_parse(sess, args, srp_udata_opts(context));
  278. faux_argv_free(args);
  279. if (pline->invalid) {
  280. fprintf(stderr, ERRORMSG "Invalid set request.\n");
  281. ret = -1;
  282. goto cleanup;
  283. }
  284. iter = faux_list_head(pline->exprs);
  285. while ((expr = (pexpr_t *)faux_list_each(&iter))) {
  286. if (!(expr->pat & PT_SET)) {
  287. err_num++;
  288. fprintf(stderr, ERRORMSG "Illegal expression for set operation.\n");
  289. break;
  290. }
  291. if (sr_set_item_str(sess, expr->xpath, expr->value, NULL, 0) !=
  292. SR_ERR_OK) {
  293. err_num++;
  294. fprintf(stderr, ERRORMSG "Can't set data.\n");
  295. break;
  296. }
  297. }
  298. if (err_num > 0)
  299. ret = -1;
  300. if (!sr_has_changes(sess))
  301. goto cleanup;
  302. if (err_num > 0) {
  303. sr_discard_changes(sess);
  304. goto cleanup;
  305. }
  306. sr_apply_changes(sess, 0);
  307. cleanup:
  308. pline_free(pline);
  309. sr_disconnect(conn);
  310. return ret;
  311. }
  312. int srp_del(kcontext_t *context)
  313. {
  314. int ret = -1;
  315. faux_argv_t *args = NULL;
  316. pline_t *pline = NULL;
  317. sr_conn_ctx_t *conn = NULL;
  318. sr_session_ctx_t *sess = NULL;
  319. pexpr_t *expr = NULL;
  320. size_t err_num = 0;
  321. faux_argv_t *cur_path = NULL;
  322. assert(context);
  323. if (sr_connect(SR_CONN_DEFAULT, &conn))
  324. return -1;
  325. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  326. sr_disconnect(conn);
  327. return -1;
  328. }
  329. cur_path = (faux_argv_t *)srp_udata_path(context);
  330. args = param2argv(cur_path, kcontext_pargv(context), "path");
  331. pline = pline_parse(sess, args, srp_udata_opts(context));
  332. faux_argv_free(args);
  333. if (pline->invalid) {
  334. fprintf(stderr, ERRORMSG "Invalid 'del' request.\n");
  335. goto err;
  336. }
  337. if (faux_list_len(pline->exprs) > 1) {
  338. fprintf(stderr, ERRORMSG "Can't delete more than one object.\n");
  339. goto err;
  340. }
  341. expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs));
  342. if (!(expr->pat & PT_DEL)) {
  343. fprintf(stderr, ERRORMSG "Illegal expression for 'del' operation.\n");
  344. goto err;
  345. }
  346. if (sr_delete_item(sess, expr->xpath, 0) != SR_ERR_OK) {
  347. fprintf(stderr, ERRORMSG "Can't delete data.\n");
  348. goto err;
  349. }
  350. sr_apply_changes(sess, 0);
  351. ret = 0;
  352. err:
  353. pline_free(pline);
  354. sr_disconnect(conn);
  355. return ret;
  356. }
  357. int srp_edit(kcontext_t *context)
  358. {
  359. int ret = -1;
  360. faux_argv_t *args = NULL;
  361. pline_t *pline = NULL;
  362. sr_conn_ctx_t *conn = NULL;
  363. sr_session_ctx_t *sess = NULL;
  364. pexpr_t *expr = NULL;
  365. size_t err_num = 0;
  366. faux_argv_t *cur_path = NULL;
  367. assert(context);
  368. if (sr_connect(SR_CONN_DEFAULT, &conn))
  369. return -1;
  370. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  371. sr_disconnect(conn);
  372. return -1;
  373. }
  374. cur_path = (faux_argv_t *)srp_udata_path(context);
  375. args = param2argv(cur_path, kcontext_pargv(context), "path");
  376. pline = pline_parse(sess, args, srp_udata_opts(context));
  377. if (pline->invalid) {
  378. fprintf(stderr, ERRORMSG "Invalid 'edit' request.\n");
  379. goto err;
  380. }
  381. if (faux_list_len(pline->exprs) > 1) {
  382. fprintf(stderr, ERRORMSG "Can't process more than one object.\n");
  383. goto err;
  384. }
  385. expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs));
  386. if (!(expr->pat & PT_EDIT)) {
  387. fprintf(stderr, ERRORMSG "Illegal expression for 'edit' operation.\n");
  388. goto err;
  389. }
  390. if (sr_set_item_str(sess, expr->xpath, NULL, NULL, 0) != SR_ERR_OK) {
  391. fprintf(stderr, ERRORMSG "Can't set editing data.\n");
  392. goto err;
  393. }
  394. sr_apply_changes(sess, 0);
  395. // Set new current path
  396. srp_udata_set_path(context, args);
  397. ret = 0;
  398. err:
  399. if (ret < 0)
  400. faux_argv_free(args);
  401. pline_free(pline);
  402. sr_disconnect(conn);
  403. return ret;
  404. }
  405. int srp_top(kcontext_t *context)
  406. {
  407. assert(context);
  408. srp_udata_set_path(context, NULL);
  409. return 0;
  410. }
  411. int srp_up(kcontext_t *context)
  412. {
  413. sr_conn_ctx_t *conn = NULL;
  414. sr_session_ctx_t *sess = NULL;
  415. faux_argv_t *cur_path = NULL;
  416. faux_argv_node_t *iter = NULL;
  417. assert(context);
  418. cur_path = (faux_argv_t *)srp_udata_path(context);
  419. if (!cur_path)
  420. return -1; // It's top level and can't level up
  421. if (sr_connect(SR_CONN_DEFAULT, &conn))
  422. return -1;
  423. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  424. sr_disconnect(conn);
  425. return -1;
  426. }
  427. // Remove last arguments one by one and wait for legal edit-like pline
  428. while (faux_argv_len(cur_path) > 0) {
  429. pline_t *pline = NULL;
  430. pexpr_t *expr = NULL;
  431. size_t len = 0;
  432. iter = faux_argv_iterr(cur_path);
  433. faux_argv_del(cur_path, iter);
  434. pline = pline_parse(sess, cur_path, srp_udata_opts(context));
  435. if (pline->invalid) {
  436. pline_free(pline);
  437. continue;
  438. }
  439. len = faux_list_len(pline->exprs);
  440. if (len != 1) {
  441. pline_free(pline);
  442. continue;
  443. }
  444. expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs));
  445. if (!(expr->pat & PT_EDIT)) {
  446. pline_free(pline);
  447. continue;
  448. }
  449. // Here new path is ok
  450. pline_free(pline);
  451. break;
  452. }
  453. // Don't store empty path
  454. if (faux_argv_len(cur_path) == 0)
  455. srp_udata_set_path(context, NULL);
  456. sr_disconnect(conn);
  457. return 0;
  458. }
  459. int srp_insert(kcontext_t *context)
  460. {
  461. int ret = -1;
  462. pline_t *pline = NULL;
  463. pline_t *pline_to = NULL;
  464. sr_conn_ctx_t *conn = NULL;
  465. sr_session_ctx_t *sess = NULL;
  466. faux_list_node_t *iter = NULL;
  467. pexpr_t *expr = NULL;
  468. pexpr_t *expr_to = NULL;
  469. faux_argv_t *cur_path = NULL;
  470. faux_argv_t *insert_from = NULL;
  471. faux_argv_t *insert_to = NULL;
  472. sr_move_position_t position = SR_MOVE_LAST;
  473. kpargv_t *pargv = NULL;
  474. const char *list_keys = NULL;
  475. const char *leaflist_value = NULL;
  476. assert(context);
  477. if (sr_connect(SR_CONN_DEFAULT, &conn))
  478. return -1;
  479. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  480. sr_disconnect(conn);
  481. return -1;
  482. }
  483. cur_path = (faux_argv_t *)srp_udata_path(context);
  484. pargv = kcontext_pargv(context);
  485. // 'from' argument
  486. insert_from = param2argv(cur_path, pargv, "from_path");
  487. pline = pline_parse(sess, insert_from, srp_udata_opts(context));
  488. faux_argv_free(insert_from);
  489. if (pline->invalid) {
  490. fprintf(stderr, ERRORMSG "Invalid 'from' expression.\n");
  491. goto err;
  492. }
  493. if (faux_list_len(pline->exprs) > 1) {
  494. fprintf(stderr, ERRORMSG "Can't process more than one object.\n");
  495. goto err;
  496. }
  497. expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs));
  498. if (!(expr->pat & PT_INSERT)) {
  499. fprintf(stderr, ERRORMSG "Illegal 'from' expression for 'insert' operation.\n");
  500. goto err;
  501. }
  502. // Position
  503. if (kpargv_find(pargv, "first"))
  504. position = SR_MOVE_FIRST;
  505. else if (kpargv_find(pargv, "last"))
  506. position = SR_MOVE_LAST;
  507. else if (kpargv_find(pargv, "before"))
  508. position = SR_MOVE_BEFORE;
  509. else if (kpargv_find(pargv, "after"))
  510. position = SR_MOVE_AFTER;
  511. else {
  512. fprintf(stderr, ERRORMSG "Illegal 'position' argument.\n");
  513. goto err;
  514. }
  515. // 'to' argument
  516. if ((SR_MOVE_BEFORE == position) || (SR_MOVE_AFTER == position)) {
  517. insert_to = assemble_insert_to(sess, pargv, cur_path,
  518. NULL, srp_udata_opts(context));
  519. pline_to = pline_parse(sess, insert_to, srp_udata_opts(context));
  520. faux_argv_free(insert_to);
  521. if (pline_to->invalid) {
  522. fprintf(stderr, ERRORMSG "Invalid 'to' expression.\n");
  523. goto err;
  524. }
  525. if (faux_list_len(pline_to->exprs) > 1) {
  526. fprintf(stderr, ERRORMSG "Can't process more than one object.\n");
  527. goto err;
  528. }
  529. expr_to = (pexpr_t *)faux_list_data(faux_list_head(pline_to->exprs));
  530. if (!(expr_to->pat & PT_INSERT)) {
  531. fprintf(stderr, ERRORMSG "Illegal 'to' expression for 'insert' operation.\n");
  532. goto err;
  533. }
  534. if (PAT_LIST_KEY == expr_to->pat)
  535. list_keys = expr_to->last_keys;
  536. else // PATH_LEAFLIST_VALUE
  537. leaflist_value = expr_to->last_keys;
  538. }
  539. if (sr_move_item(sess, expr->xpath, position,
  540. list_keys, leaflist_value, NULL, 0) != SR_ERR_OK) {
  541. fprintf(stderr, ERRORMSG "Can't move element.\n");
  542. goto err;
  543. }
  544. sr_apply_changes(sess, 0);
  545. ret = 0;
  546. err:
  547. pline_free(pline);
  548. pline_free(pline_to);
  549. sr_disconnect(conn);
  550. return ret;
  551. }
  552. int srp_verify(kcontext_t *context)
  553. {
  554. int ret = -1;
  555. sr_conn_ctx_t *conn = NULL;
  556. sr_session_ctx_t *sess = NULL;
  557. assert(context);
  558. if (sr_connect(SR_CONN_DEFAULT, &conn)) {
  559. fprintf(stderr, ERRORMSG "Can't connect to data repository.\n");
  560. return -1;
  561. }
  562. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  563. fprintf(stderr, ERRORMSG "Can't connect to candidate data store.\n");
  564. goto err;
  565. }
  566. // Validate candidate config
  567. if (sr_validate(sess, NULL, 0) != SR_ERR_OK) {
  568. fprintf(stderr, ERRORMSG "Invalid candidate configuration.\n");
  569. goto err;
  570. }
  571. ret = 0;
  572. err:
  573. sr_disconnect(conn);
  574. return ret;
  575. }
  576. int srp_commit(kcontext_t *context)
  577. {
  578. int ret = -1;
  579. sr_conn_ctx_t *conn = NULL;
  580. sr_session_ctx_t *sess = NULL;
  581. assert(context);
  582. if (sr_connect(SR_CONN_DEFAULT, &conn)) {
  583. fprintf(stderr, ERRORMSG "Can't connect to data repository.\n");
  584. return -1;
  585. }
  586. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  587. fprintf(stderr, ERRORMSG "Can't connect to candidate data store.\n");
  588. goto err;
  589. }
  590. // Copy candidate to running-config
  591. if (sr_session_switch_ds(sess, SR_DS_RUNNING)) {
  592. fprintf(stderr, ERRORMSG "Can't connect to running-config data store.\n");
  593. goto err;
  594. }
  595. if (sr_copy_config(sess, NULL, SRP_REPO_EDIT, 0) != SR_ERR_OK) {
  596. fprintf(stderr, ERRORMSG "Can't commit to running-config.\n");
  597. goto err;
  598. }
  599. // Copy running-config to startup-config
  600. if (sr_session_switch_ds(sess, SR_DS_STARTUP)) {
  601. fprintf(stderr, ERRORMSG "Can't connect to startup-config data store.\n");
  602. goto err;
  603. }
  604. if (sr_copy_config(sess, NULL, SR_DS_RUNNING, 0) != SR_ERR_OK) {
  605. fprintf(stderr, ERRORMSG "Can't store data to startup-config.\n");
  606. goto err;
  607. }
  608. ret = 0;
  609. err:
  610. sr_disconnect(conn);
  611. return ret;
  612. }
  613. int srp_rollback(kcontext_t *context)
  614. {
  615. int ret = -1;
  616. sr_conn_ctx_t *conn = NULL;
  617. sr_session_ctx_t *sess = NULL;
  618. assert(context);
  619. if (sr_connect(SR_CONN_DEFAULT, &conn)) {
  620. fprintf(stderr, ERRORMSG "Can't connect to data repository.\n");
  621. return -1;
  622. }
  623. // Copy running-config to candidate config
  624. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  625. fprintf(stderr, ERRORMSG "Can't connect to candidate data store.\n");
  626. goto err;
  627. }
  628. if (sr_copy_config(sess, NULL, SR_DS_RUNNING, 0) != SR_ERR_OK) {
  629. fprintf(stderr, ERRORMSG "Can't rollback to running-config.\n");
  630. goto err;
  631. }
  632. ret = 0;
  633. err:
  634. sr_disconnect(conn);
  635. return ret;
  636. }
  637. int srp_show_xml(kcontext_t *context)
  638. {
  639. int ret = -1;
  640. faux_argv_t *args = NULL;
  641. pline_t *pline = NULL;
  642. sr_conn_ctx_t *conn = NULL;
  643. sr_session_ctx_t *sess = NULL;
  644. pexpr_t *expr = NULL;
  645. faux_argv_t *cur_path = NULL;
  646. sr_data_t *data = NULL;
  647. struct ly_out *out = NULL;
  648. struct lyd_node *child = NULL;
  649. assert(context);
  650. if (sr_connect(SR_CONN_DEFAULT, &conn))
  651. return -1;
  652. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  653. sr_disconnect(conn);
  654. return -1;
  655. }
  656. cur_path = (faux_argv_t *)srp_udata_path(context);
  657. args = param2argv(cur_path, kcontext_pargv(context), "path");
  658. pline = pline_parse(sess, args, srp_udata_opts(context));
  659. faux_argv_free(args);
  660. if (pline->invalid) {
  661. fprintf(stderr, ERRORMSG "Invalid 'show' request.\n");
  662. goto err;
  663. }
  664. if (faux_list_len(pline->exprs) > 1) {
  665. fprintf(stderr, ERRORMSG "Can't process more than one object.\n");
  666. goto err;
  667. }
  668. expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs));
  669. if (!(expr->pat & PT_EDIT)) {
  670. fprintf(stderr, ERRORMSG "Illegal expression for 'show' operation.\n");
  671. goto err;
  672. }
  673. if (sr_get_subtree(sess, expr->xpath, 0, &data) != SR_ERR_OK) {
  674. fprintf(stderr, ERRORMSG "Can't get specified subtree.\n");
  675. goto err;
  676. }
  677. ly_out_new_file(stdout, &out);
  678. lyd_print_tree(out, data->tree, LYD_XML, 0);
  679. ly_out_free(out, NULL, 0);
  680. // child = lyd_child(data->tree);
  681. // if (child) {
  682. // ly_out_new_file(stdout, &out);
  683. // lyd_print_all(out, child, LYD_XML, 0);
  684. // }
  685. struct lyd_meta *meta = lyd_find_meta(data->tree->meta, NULL, "junos-configuration-metadata:active");
  686. if (meta)
  687. printf("META\n");
  688. sr_release_data(data);
  689. ret = 0;
  690. err:
  691. pline_free(pline);
  692. sr_disconnect(conn);
  693. return ret;
  694. }
  695. static int show(kcontext_t *context, sr_datastore_t ds)
  696. {
  697. int ret = -1;
  698. faux_argv_t *args = NULL;
  699. pline_t *pline = NULL;
  700. sr_conn_ctx_t *conn = NULL;
  701. sr_session_ctx_t *sess = NULL;
  702. pexpr_t *expr = NULL;
  703. faux_argv_t *cur_path = NULL;
  704. char *xpath = NULL;
  705. assert(context);
  706. if (sr_connect(SR_CONN_DEFAULT, &conn))
  707. return -1;
  708. if (sr_session_start(conn, ds, &sess)) {
  709. sr_disconnect(conn);
  710. return -1;
  711. }
  712. cur_path = (faux_argv_t *)srp_udata_path(context);
  713. if (kpargv_find(kcontext_pargv(context), "path") || cur_path) {
  714. args = param2argv(cur_path, kcontext_pargv(context), "path");
  715. pline = pline_parse(sess, args, srp_udata_opts(context));
  716. faux_argv_free(args);
  717. if (pline->invalid) {
  718. fprintf(stderr, ERRORMSG "Invalid 'show' request.\n");
  719. goto err;
  720. }
  721. if (faux_list_len(pline->exprs) > 1) {
  722. fprintf(stderr, ERRORMSG "Can't process more than one object.\n");
  723. goto err;
  724. }
  725. if (!(expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs)))) {
  726. fprintf(stderr, ERRORMSG "Can't get expression.\n");
  727. goto err;
  728. }
  729. if (!(expr->pat & PT_EDIT)) {
  730. fprintf(stderr, ERRORMSG "Illegal expression for 'show' operation.\n");
  731. goto err;
  732. }
  733. if (!expr->xpath) {
  734. fprintf(stderr, ERRORMSG "Empty expression for 'show' operation.\n");
  735. goto err;
  736. }
  737. xpath = expr->xpath;
  738. }
  739. show_xpath(sess, xpath, srp_udata_opts(context));
  740. ret = 0;
  741. err:
  742. pline_free(pline);
  743. sr_disconnect(conn);
  744. return ret;
  745. }
  746. int srp_show(kcontext_t *context)
  747. {
  748. return show(context, SRP_REPO_EDIT);
  749. }
  750. int srp_show_running(kcontext_t *context)
  751. {
  752. sr_conn_ctx_t *conn = NULL;
  753. sr_session_ctx_t *sess = NULL;
  754. if (sr_connect(SR_CONN_DEFAULT, &conn))
  755. return -1;
  756. if (sr_session_start(conn, SR_DS_RUNNING, &sess)) {
  757. sr_disconnect(conn);
  758. return -1;
  759. }
  760. show_xpath(sess, NULL, srp_udata_opts(context));
  761. sr_disconnect(conn);
  762. return 0;
  763. }
  764. int srp_deactivate(kcontext_t *context)
  765. {
  766. int ret = -1;
  767. faux_argv_t *args = NULL;
  768. pline_t *pline = NULL;
  769. sr_conn_ctx_t *conn = NULL;
  770. sr_session_ctx_t *sess = NULL;
  771. pexpr_t *expr = NULL;
  772. faux_argv_t *cur_path = NULL;
  773. sr_data_t *data = NULL;
  774. const struct ly_ctx *ctx = NULL;
  775. assert(context);
  776. if (sr_connect(SR_CONN_DEFAULT, &conn))
  777. return -1;
  778. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  779. sr_disconnect(conn);
  780. return -1;
  781. }
  782. cur_path = (faux_argv_t *)srp_udata_path(context);
  783. args = param2argv(cur_path, kcontext_pargv(context), "path");
  784. pline = pline_parse(sess, args, srp_udata_opts(context));
  785. faux_argv_free(args);
  786. if (pline->invalid) {
  787. fprintf(stderr, ERRORMSG "Invalid 'show' request.\n");
  788. goto err;
  789. }
  790. if (faux_list_len(pline->exprs) > 1) {
  791. fprintf(stderr, ERRORMSG "Can't process more than one object.\n");
  792. goto err;
  793. }
  794. expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs));
  795. if (!(expr->pat & PT_DEL)) {
  796. fprintf(stderr, ERRORMSG "Illegal expression for 'show' operation.\n");
  797. goto err;
  798. }
  799. if (sr_get_subtree(sess, expr->xpath, 0, &data) != SR_ERR_OK) {
  800. fprintf(stderr, ERRORMSG "Can't get specified subtree.\n");
  801. goto err;
  802. }
  803. if (lyd_new_meta(LYD_CTX(data->tree), data->tree, NULL,
  804. "junos-configuration-metadata:active", "false", 0, NULL)) {
  805. fprintf(stderr, ERRORMSG "Can't deactivate.\n");
  806. goto err;
  807. }
  808. struct lyd_meta *meta = lyd_find_meta(data->tree->meta, NULL, "junos-configuration-metadata:active");
  809. if (meta)
  810. printf("META\n");
  811. if (sr_has_changes(sess))
  812. fprintf(stderr, ERRORMSG "Has changes.\n");
  813. if (sr_apply_changes(sess, 0)) {
  814. fprintf(stderr, ERRORMSG "Can't apply changes.\n");
  815. }
  816. sr_release_data(data);
  817. if (sr_get_subtree(sess, expr->xpath, 0, &data) != SR_ERR_OK) {
  818. fprintf(stderr, ERRORMSG "Can't get specified subtree.\n");
  819. goto err;
  820. }
  821. struct ly_out *out = NULL;
  822. ly_out_new_file(stdout, &out);
  823. lyd_print_tree(out, data->tree, LYD_XML, 0);
  824. ly_out_free(out, NULL, 0);
  825. sr_release_data(data);
  826. ret = 0;
  827. err:
  828. pline_free(pline);
  829. sr_disconnect(conn);
  830. return ret;
  831. }
  832. int srp_diff(kcontext_t *context)
  833. {
  834. int ret = -1;
  835. pline_t *pline = NULL;
  836. sr_conn_ctx_t *conn = NULL;
  837. sr_session_ctx_t *sess1 = NULL;
  838. sr_session_ctx_t *sess2 = NULL;
  839. sr_data_t *data1 = NULL;
  840. sr_data_t *data2 = NULL;
  841. faux_argv_t *cur_path = NULL;
  842. const char *xpath = NULL;
  843. struct lyd_node *diff = NULL;
  844. assert(context);
  845. if (sr_connect(SR_CONN_DEFAULT, &conn))
  846. return -1;
  847. if (sr_session_start(conn, SR_DS_RUNNING, &sess1)) {
  848. sr_disconnect(conn);
  849. return -1;
  850. }
  851. if (sr_session_start(conn, SRP_REPO_EDIT, &sess2)) {
  852. sr_disconnect(conn);
  853. return -1;
  854. }
  855. cur_path = (faux_argv_t *)srp_udata_path(context);
  856. if (kpargv_find(kcontext_pargv(context), "path") || cur_path) {
  857. faux_argv_t *args = NULL;
  858. pexpr_t *expr = NULL;
  859. args = param2argv(cur_path, kcontext_pargv(context), "path");
  860. pline = pline_parse(sess2, args, srp_udata_opts(context));
  861. faux_argv_free(args);
  862. if (pline->invalid) {
  863. fprintf(stderr, ERRORMSG "Invalid 'show' request.\n");
  864. goto err;
  865. }
  866. if (faux_list_len(pline->exprs) > 1) {
  867. fprintf(stderr, ERRORMSG "Can't process more than one object.\n");
  868. goto err;
  869. }
  870. if (!(expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs)))) {
  871. fprintf(stderr, ERRORMSG "Can't get expression.\n");
  872. goto err;
  873. }
  874. if (!(expr->pat & PT_EDIT)) {
  875. fprintf(stderr, ERRORMSG "Illegal expression for 'show' operation.\n");
  876. goto err;
  877. }
  878. if (!expr->xpath) {
  879. fprintf(stderr, ERRORMSG "Empty expression for 'show' operation.\n");
  880. goto err;
  881. }
  882. xpath = expr->xpath;
  883. }
  884. if (!xpath)
  885. xpath = "/*";
  886. if (sr_get_data(sess1, xpath, 0, 0, 0, &data1) != SR_ERR_OK) {
  887. fprintf(stderr, ERRORMSG "Can't get specified subtree.\n");
  888. goto err;
  889. }
  890. if (sr_get_data(sess2, xpath, 0, 0, 0, &data2) != SR_ERR_OK) {
  891. fprintf(stderr, ERRORMSG "Can't get specified subtree.\n");
  892. goto err;
  893. }
  894. if (lyd_diff_siblings(data1->tree, data2->tree, 0, &diff) != LY_SUCCESS) {
  895. fprintf(stderr, ERRORMSG "Can't generate diff.\n");
  896. goto err;
  897. }
  898. show_subtree(diff, 0, DIFF_OP_NONE, srp_udata_opts(context));
  899. lyd_free_siblings(diff);
  900. ret = 0;
  901. err:
  902. if (data1)
  903. sr_release_data(data1);
  904. if (data2)
  905. sr_release_data(data2);
  906. pline_free(pline);
  907. sr_disconnect(conn);
  908. return ret;
  909. }
  910. static int srp_compl_xpath(kcontext_t *context, const sr_datastore_t datastore)
  911. {
  912. sr_conn_ctx_t *conn = NULL;
  913. sr_session_ctx_t *sess = NULL;
  914. sr_val_t *vals = NULL;
  915. size_t val_num = 0;
  916. size_t i = 0;
  917. const char *script = NULL;
  918. assert(context);
  919. script = kcontext_script(context);
  920. if (faux_str_is_empty(script))
  921. return -1;
  922. if (sr_connect(SR_CONN_DEFAULT, &conn))
  923. return -1;
  924. if (sr_session_start(conn, datastore, &sess)) {
  925. sr_disconnect(conn);
  926. return -1;
  927. }
  928. sr_get_items(sess, script, 0, 0, &vals, &val_num);
  929. for (i = 0; i < val_num; i++) {
  930. char *tmp = sr_val_to_str(&vals[i]);
  931. if (!tmp)
  932. continue;
  933. printf("%s\n", tmp);
  934. free(tmp);
  935. }
  936. sr_free_values(vals, val_num);
  937. sr_disconnect(conn);
  938. return 0;
  939. }
  940. int srp_compl_xpath_running(kcontext_t *context)
  941. {
  942. return srp_compl_xpath(context, SR_DS_RUNNING);
  943. }
  944. int srp_compl_xpath_candidate(kcontext_t *context)
  945. {
  946. return srp_compl_xpath(context, SR_DS_CANDIDATE);
  947. }