syms.c 25 KB

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