syms.c 28 KB

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