cli.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*
  2. * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2
  6. * as published by the Free Software Foundation
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <strings.h>
  14. #include <stdlib.h>
  15. #include <unistd.h>
  16. #include "uci.h"
  17. static const char *appname = "uci";
  18. static enum {
  19. CLI_FLAG_MERGE = (1 << 0),
  20. } flags;
  21. static FILE *input = stdin;
  22. static struct uci_context *ctx;
  23. enum {
  24. /* section cmds */
  25. CMD_GET,
  26. CMD_SET,
  27. CMD_DEL,
  28. CMD_RENAME,
  29. /* package cmds */
  30. CMD_SHOW,
  31. CMD_IMPORT,
  32. CMD_EXPORT,
  33. CMD_COMMIT,
  34. };
  35. static void uci_usage(int argc, char **argv)
  36. {
  37. fprintf(stderr,
  38. "Usage: %s [<options>] <command> [<arguments>]\n\n"
  39. "Commands:\n"
  40. "\texport [<config>]\n"
  41. "\timport [<config>]\n"
  42. "\tshow [<config>[.<section>[.<option>]]]\n"
  43. "\tget <config>.<section>[.<option>]\n"
  44. "\tset <config>.<section>[.<option>]=<value>\n"
  45. "\trename <config>.<section>[.<option>]=<name>\n"
  46. "\n"
  47. "Options:\n"
  48. "\t-f <file> use <file> as input instead of stdin\n"
  49. "\t-m when importing, merge data into an existing package\n"
  50. "\t-s force strict mode (stop on parser errors)\n"
  51. "\t-S disable strict mode\n"
  52. "\n",
  53. argv[0]
  54. );
  55. exit(255);
  56. }
  57. static void uci_show_section(struct uci_section *p)
  58. {
  59. struct uci_element *e;
  60. const char *cname, *sname;
  61. cname = p->package->e.name;
  62. sname = p->e.name;
  63. printf("%s.%s=%s\n", cname, sname, p->type);
  64. uci_foreach_element(&p->options, e) {
  65. printf("%s.%s.%s=%s\n", cname, sname, e->name, uci_to_option(e)->value);
  66. }
  67. }
  68. static void uci_show_package(struct uci_package *p)
  69. {
  70. struct uci_element *e;
  71. uci_foreach_element( &p->sections, e) {
  72. uci_show_section(uci_to_section(e));
  73. }
  74. }
  75. static int package_cmd(int cmd, char *package)
  76. {
  77. struct uci_package *p = NULL;
  78. if (uci_load(ctx, package, &p) != UCI_OK) {
  79. uci_perror(ctx, appname);
  80. return 1;
  81. }
  82. switch(cmd) {
  83. case CMD_COMMIT:
  84. if (uci_commit(ctx, &p) != UCI_OK)
  85. uci_perror(ctx, appname);
  86. break;
  87. case CMD_EXPORT:
  88. uci_export(ctx, stdout, p, true);
  89. break;
  90. case CMD_SHOW:
  91. uci_show_package(p);
  92. break;
  93. }
  94. uci_unload(ctx, p);
  95. return 0;
  96. }
  97. static int uci_do_import(int argc, char **argv)
  98. {
  99. return 0;
  100. }
  101. static int uci_do_package_cmd(int cmd, int argc, char **argv)
  102. {
  103. char **configs = NULL;
  104. char **p;
  105. if (argc > 2)
  106. return 255;
  107. if (argc == 2)
  108. return package_cmd(cmd, argv[1]);
  109. if ((uci_list_configs(ctx, &configs) != UCI_OK) || !configs) {
  110. uci_perror(ctx, appname);
  111. return 1;
  112. }
  113. for (p = configs; *p; p++) {
  114. package_cmd(cmd, *p);
  115. }
  116. return 0;
  117. }
  118. static int uci_do_section_cmd(int cmd, int argc, char **argv)
  119. {
  120. char *package = NULL;
  121. char *section = NULL;
  122. char *option = NULL;
  123. char *value = NULL;
  124. char **ptr = NULL;
  125. struct uci_package *p = NULL;
  126. struct uci_element *e = NULL;
  127. if (argc != 2)
  128. return 255;
  129. switch(cmd) {
  130. case CMD_SET:
  131. case CMD_RENAME:
  132. ptr = &value;
  133. break;
  134. default:
  135. break;
  136. }
  137. if (uci_parse_tuple(ctx, argv[1], &package, &section, &option, ptr) != UCI_OK)
  138. return 1;
  139. if (uci_load(ctx, package, &p) != UCI_OK) {
  140. uci_perror(ctx, appname);
  141. return 1;
  142. }
  143. switch(cmd) {
  144. case CMD_GET:
  145. if (uci_lookup(ctx, &e, p, section, option) != UCI_OK)
  146. return 1;
  147. switch(e->type) {
  148. case UCI_TYPE_SECTION:
  149. value = uci_to_section(e)->type;
  150. break;
  151. case UCI_TYPE_OPTION:
  152. value = uci_to_option(e)->value;
  153. break;
  154. default:
  155. /* should not happen */
  156. return 1;
  157. }
  158. /* throw the value to stdout */
  159. printf("%s\n", value);
  160. break;
  161. case CMD_RENAME:
  162. if (uci_rename(ctx, p, section, option, value) != UCI_OK) {
  163. uci_perror(ctx, appname);
  164. return 1;
  165. }
  166. break;
  167. case CMD_SET:
  168. if (uci_set(ctx, p, section, option, value) != UCI_OK) {
  169. uci_perror(ctx, appname);
  170. return 1;
  171. }
  172. break;
  173. case CMD_DEL:
  174. if (uci_delete(ctx, p, section, option) != UCI_OK) {
  175. uci_perror(ctx, appname);
  176. return 1;
  177. }
  178. break;
  179. }
  180. /* no save necessary for get */
  181. if (cmd == CMD_GET)
  182. return 0;
  183. /* save changes, but don't commit them yet */
  184. if (uci_save(ctx, p) != UCI_OK) {
  185. uci_perror(ctx, appname);
  186. return 1;
  187. }
  188. return 0;
  189. }
  190. static int uci_cmd(int argc, char **argv)
  191. {
  192. int cmd = 0;
  193. if (!strcasecmp(argv[0], "show"))
  194. cmd = CMD_SHOW;
  195. else if (!strcasecmp(argv[0], "export"))
  196. cmd = CMD_EXPORT;
  197. else if (!strcasecmp(argv[0], "commit"))
  198. cmd = CMD_COMMIT;
  199. else if (!strcasecmp(argv[0], "get"))
  200. cmd = CMD_GET;
  201. else if (!strcasecmp(argv[0], "set"))
  202. cmd = CMD_SET;
  203. else if (!strcasecmp(argv[0], "ren") ||
  204. !strcasecmp(argv[0], "rename"))
  205. cmd = CMD_RENAME;
  206. else if (!strcasecmp(argv[0], "del"))
  207. cmd = CMD_DEL;
  208. else if (!strcasecmp(argv[0], "import"))
  209. cmd = CMD_IMPORT;
  210. else
  211. cmd = -1;
  212. switch(cmd) {
  213. case CMD_GET:
  214. case CMD_SET:
  215. case CMD_DEL:
  216. case CMD_RENAME:
  217. return uci_do_section_cmd(cmd, argc, argv);
  218. case CMD_SHOW:
  219. case CMD_EXPORT:
  220. case CMD_COMMIT:
  221. return uci_do_package_cmd(cmd, argc, argv);
  222. case CMD_IMPORT:
  223. return uci_do_import(argc, argv);
  224. default:
  225. return 255;
  226. }
  227. }
  228. int main(int argc, char **argv)
  229. {
  230. int ret;
  231. int c;
  232. ctx = uci_alloc_context();
  233. if (!ctx) {
  234. fprintf(stderr, "Out of memory\n");
  235. return 1;
  236. }
  237. while((c = getopt(argc, argv, "sS")) != -1) {
  238. switch(c) {
  239. case 'f':
  240. input = fopen(optarg, "r");
  241. if (!input) {
  242. perror("uci");
  243. return 1;
  244. }
  245. break;
  246. case 'm':
  247. flags |= CLI_FLAG_MERGE;
  248. break;
  249. case 's':
  250. ctx->flags |= UCI_FLAG_STRICT;
  251. break;
  252. case 'S':
  253. ctx->flags &= ~UCI_FLAG_STRICT;
  254. ctx->flags |= UCI_FLAG_PERROR;
  255. break;
  256. default:
  257. uci_usage(argc, argv);
  258. break;
  259. }
  260. }
  261. if (optind > 1)
  262. argv[optind - 1] = argv[0];
  263. argv += optind - 1;
  264. argc -= optind - 1;
  265. if (argc < 2)
  266. uci_usage(argc, argv);
  267. ret = uci_cmd(argc - 1, argv + 1);
  268. if (input != stdin)
  269. fclose(input);
  270. if (ret == 255)
  271. uci_usage(argc, argv);
  272. uci_free_context(ctx);
  273. return ret;
  274. }