syms.c 26 KB

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