syms.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254
  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_conn_ctx_t *conn = NULL;
  749. sr_session_ctx_t *sess = NULL;
  750. pexpr_t *expr = NULL;
  751. faux_argv_t *cur_path = NULL;
  752. char *xpath = NULL;
  753. assert(context);
  754. if (sr_connect(SR_CONN_DEFAULT, &conn)) {
  755. fprintf(stderr, ERRORMSG "Can't connect to data store\n");
  756. return -1;
  757. }
  758. if (sr_session_start(conn, ds, &sess)) {
  759. fprintf(stderr, ERRORMSG "Can't start data store session\n");
  760. sr_disconnect(conn);
  761. return -1;
  762. }
  763. cur_path = (faux_argv_t *)srp_udata_path(context);
  764. if (kpargv_find(kcontext_pargv(context), "path") || cur_path) {
  765. args = param2argv(cur_path, kcontext_pargv(context), "path");
  766. pline = pline_parse(sess, args, srp_udata_opts(context));
  767. faux_argv_free(args);
  768. if (pline->invalid) {
  769. fprintf(stderr, ERRORMSG "Invalid 'show' request\n");
  770. goto err;
  771. }
  772. if (faux_list_len(pline->exprs) > 1) {
  773. fprintf(stderr, ERRORMSG "Can't process more than one object\n");
  774. goto err;
  775. }
  776. if (!(expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs)))) {
  777. fprintf(stderr, ERRORMSG "Can't get expression\n");
  778. goto err;
  779. }
  780. if (!(expr->pat & PT_EDIT)) {
  781. fprintf(stderr, ERRORMSG "Illegal expression for 'show' operation\n");
  782. goto err;
  783. }
  784. if (!expr->xpath) {
  785. fprintf(stderr, ERRORMSG "Empty expression for 'show' operation\n");
  786. goto err;
  787. }
  788. xpath = expr->xpath;
  789. }
  790. show_xpath(sess, xpath, srp_udata_opts(context));
  791. ret = 0;
  792. err:
  793. pline_free(pline);
  794. sr_disconnect(conn);
  795. return ret;
  796. }
  797. int srp_show(kcontext_t *context)
  798. {
  799. return show(context, SRP_REPO_EDIT);
  800. }
  801. int srp_show_running(kcontext_t *context)
  802. {
  803. sr_conn_ctx_t *conn = NULL;
  804. sr_session_ctx_t *sess = NULL;
  805. if (sr_connect(SR_CONN_DEFAULT, &conn)) {
  806. fprintf(stderr, ERRORMSG "Can't connect to data store\n");
  807. return -1;
  808. }
  809. if (sr_session_start(conn, SR_DS_RUNNING, &sess)) {
  810. fprintf(stderr, ERRORMSG "Can't start data store session\n");
  811. sr_disconnect(conn);
  812. return -1;
  813. }
  814. show_xpath(sess, NULL, srp_udata_opts(context));
  815. sr_disconnect(conn);
  816. return 0;
  817. }
  818. int srp_deactivate(kcontext_t *context)
  819. {
  820. int ret = -1;
  821. faux_argv_t *args = NULL;
  822. pline_t *pline = NULL;
  823. sr_conn_ctx_t *conn = NULL;
  824. sr_session_ctx_t *sess = NULL;
  825. pexpr_t *expr = NULL;
  826. faux_argv_t *cur_path = NULL;
  827. sr_data_t *data = NULL;
  828. assert(context);
  829. if (sr_connect(SR_CONN_DEFAULT, &conn)) {
  830. fprintf(stderr, ERRORMSG "Can't connect to data store\n");
  831. return -1;
  832. }
  833. if (sr_session_start(conn, SRP_REPO_EDIT, &sess)) {
  834. fprintf(stderr, ERRORMSG "Can't start data store session\n");
  835. sr_disconnect(conn);
  836. return -1;
  837. }
  838. cur_path = (faux_argv_t *)srp_udata_path(context);
  839. args = param2argv(cur_path, kcontext_pargv(context), "path");
  840. pline = pline_parse(sess, args, srp_udata_opts(context));
  841. faux_argv_free(args);
  842. if (pline->invalid) {
  843. fprintf(stderr, ERRORMSG "Invalid 'show' request\n");
  844. goto err;
  845. }
  846. if (faux_list_len(pline->exprs) > 1) {
  847. fprintf(stderr, ERRORMSG "Can't process more than one object\n");
  848. goto err;
  849. }
  850. expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs));
  851. if (!(expr->pat & PT_DEL)) {
  852. fprintf(stderr, ERRORMSG "Illegal expression for 'show' operation\n");
  853. goto err;
  854. }
  855. if (sr_get_subtree(sess, expr->xpath, 0, &data) != SR_ERR_OK) {
  856. srp_error(sess, ERRORMSG "Can't get specified subtree\n");
  857. goto err;
  858. }
  859. if (lyd_new_meta(LYD_CTX(data->tree), data->tree, NULL,
  860. "junos-configuration-metadata:active", "false", 0, NULL)) {
  861. fprintf(stderr, ERRORMSG "Can't deactivate\n");
  862. goto err;
  863. }
  864. struct lyd_meta *meta = lyd_find_meta(data->tree->meta, NULL, "junos-configuration-metadata:active");
  865. if (meta)
  866. printf("META\n");
  867. if (sr_has_changes(sess))
  868. fprintf(stderr, ERRORMSG "Has changes\n");
  869. if (sr_apply_changes(sess, 0) != SR_ERR_OK)
  870. srp_error(sess, ERRORMSG "Can't apply changes\n");
  871. sr_release_data(data);
  872. if (sr_get_subtree(sess, expr->xpath, 0, &data) != SR_ERR_OK) {
  873. srp_error(sess, ERRORMSG "Can't get specified subtree\n");
  874. goto err;
  875. }
  876. struct ly_out *out = NULL;
  877. ly_out_new_file(stdout, &out);
  878. lyd_print_tree(out, data->tree, LYD_XML, 0);
  879. ly_out_free(out, NULL, 0);
  880. sr_release_data(data);
  881. ret = 0;
  882. err:
  883. pline_free(pline);
  884. sr_disconnect(conn);
  885. return ret;
  886. }
  887. int srp_diff(kcontext_t *context)
  888. {
  889. int ret = -1;
  890. pline_t *pline = NULL;
  891. sr_conn_ctx_t *conn = NULL;
  892. sr_session_ctx_t *sess1 = NULL;
  893. sr_session_ctx_t *sess2 = NULL;
  894. sr_data_t *data1 = NULL;
  895. sr_data_t *data2 = NULL;
  896. faux_argv_t *cur_path = NULL;
  897. const char *xpath = NULL;
  898. struct lyd_node *diff = NULL;
  899. assert(context);
  900. if (sr_connect(SR_CONN_DEFAULT, &conn)) {
  901. fprintf(stderr, ERRORMSG "Can't connect to data store\n");
  902. return -1;
  903. }
  904. if (sr_session_start(conn, SR_DS_RUNNING, &sess1)) {
  905. fprintf(stderr, ERRORMSG "Can't start data store session\n");
  906. sr_disconnect(conn);
  907. return -1;
  908. }
  909. if (sr_session_start(conn, SRP_REPO_EDIT, &sess2)) {
  910. fprintf(stderr, ERRORMSG "Can't start data store session\n");
  911. sr_disconnect(conn);
  912. return -1;
  913. }
  914. cur_path = (faux_argv_t *)srp_udata_path(context);
  915. if (kpargv_find(kcontext_pargv(context), "path") || cur_path) {
  916. faux_argv_t *args = NULL;
  917. pexpr_t *expr = NULL;
  918. args = param2argv(cur_path, kcontext_pargv(context), "path");
  919. pline = pline_parse(sess2, args, srp_udata_opts(context));
  920. faux_argv_free(args);
  921. if (pline->invalid) {
  922. fprintf(stderr, ERRORMSG "Invalid 'show' request\n");
  923. goto err;
  924. }
  925. if (faux_list_len(pline->exprs) > 1) {
  926. fprintf(stderr, ERRORMSG "Can't process more than one object\n");
  927. goto err;
  928. }
  929. if (!(expr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs)))) {
  930. fprintf(stderr, ERRORMSG "Can't get expression\n");
  931. goto err;
  932. }
  933. if (!(expr->pat & PT_EDIT)) {
  934. fprintf(stderr, ERRORMSG "Illegal expression for 'show' operation\n");
  935. goto err;
  936. }
  937. if (!expr->xpath) {
  938. fprintf(stderr, ERRORMSG "Empty expression for 'show' operation\n");
  939. goto err;
  940. }
  941. xpath = expr->xpath;
  942. }
  943. if (!xpath)
  944. xpath = "/*";
  945. if (sr_get_data(sess1, xpath, 0, 0, 0, &data1) != SR_ERR_OK) {
  946. srp_error(sess1, ERRORMSG "Can't get specified subtree\n");
  947. goto err;
  948. }
  949. if (sr_get_data(sess2, xpath, 0, 0, 0, &data2) != SR_ERR_OK) {
  950. srp_error(sess2, ERRORMSG "Can't get specified subtree\n");
  951. goto err;
  952. }
  953. if (lyd_diff_siblings(data1->tree, data2->tree, 0, &diff) != LY_SUCCESS) {
  954. srp_error(sess2, ERRORMSG "Can't generate diff\n");
  955. goto err;
  956. }
  957. show_subtree(diff, 0, DIFF_OP_NONE, srp_udata_opts(context));
  958. lyd_free_siblings(diff);
  959. ret = 0;
  960. err:
  961. if (data1)
  962. sr_release_data(data1);
  963. if (data2)
  964. sr_release_data(data2);
  965. pline_free(pline);
  966. sr_disconnect(conn);
  967. return ret;
  968. }
  969. static int srp_compl_xpath(kcontext_t *context, const sr_datastore_t datastore)
  970. {
  971. sr_conn_ctx_t *conn = NULL;
  972. sr_session_ctx_t *sess = NULL;
  973. sr_val_t *vals = NULL;
  974. size_t val_num = 0;
  975. size_t i = 0;
  976. const char *script = NULL;
  977. assert(context);
  978. script = kcontext_script(context);
  979. if (faux_str_is_empty(script))
  980. return -1;
  981. if (sr_connect(SR_CONN_DEFAULT, &conn))
  982. return -1;
  983. if (sr_session_start(conn, datastore, &sess)) {
  984. sr_disconnect(conn);
  985. return -1;
  986. }
  987. sr_get_items(sess, script, 0, 0, &vals, &val_num);
  988. for (i = 0; i < val_num; i++) {
  989. char *tmp = sr_val_to_str(&vals[i]);
  990. if (!tmp)
  991. continue;
  992. printf("%s\n", tmp);
  993. free(tmp);
  994. }
  995. sr_free_values(vals, val_num);
  996. sr_disconnect(conn);
  997. return 0;
  998. }
  999. int srp_compl_xpath_running(kcontext_t *context)
  1000. {
  1001. return srp_compl_xpath(context, SR_DS_RUNNING);
  1002. }
  1003. int srp_compl_xpath_candidate(kcontext_t *context)
  1004. {
  1005. return srp_compl_xpath(context, SR_DS_CANDIDATE);
  1006. }