fix accidental lowercasing of license headers
[project/uci.git] / cli.c
1 /*
2  * cli - Command Line Interface for the Unified Configuration Interface
3  * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2
7  * as published by the Free Software Foundation
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  */
14 #include <strings.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include "uci.h"
18
19 static const char *appname = "uci";
20 static enum {
21         CLI_FLAG_MERGE =    (1 << 0),
22         CLI_FLAG_QUIET =    (1 << 1),
23         CLI_FLAG_NOCOMMIT = (1 << 2),
24 } flags;
25 static FILE *input;
26
27 static struct uci_context *ctx;
28 enum {
29         /* section cmds */
30         CMD_GET,
31         CMD_SET,
32         CMD_DEL,
33         CMD_RENAME,
34         /* package cmds */
35         CMD_SHOW,
36         CMD_IMPORT,
37         CMD_EXPORT,
38         CMD_COMMIT,
39 };
40
41 static void uci_usage(int argc, char **argv)
42 {
43         fprintf(stderr,
44                 "Usage: %s [<options>] <command> [<arguments>]\n\n"
45                 "Commands:\n"
46                 "\texport     [<config>]\n"
47                 "\timport     [<config>]\n"
48                 "\tshow       [<config>[.<section>[.<option>]]]\n"
49                 "\tget        <config>.<section>[.<option>]\n"
50                 "\tset        <config>.<section>[.<option>]=<value>\n"
51                 "\trename     <config>.<section>[.<option>]=<name>\n"
52                 "\n"
53                 "Options:\n"
54                 "\t-f <file>  use <file> as input instead of stdin\n"
55                 "\t-m         when importing, merge data into an existing package\n"
56                 "\t-n         name unnamed sections on export (default)\n"
57                 "\t-N         don't name unnamed sections\n"
58                 "\t-p <path>  add a search path for config change files\n"
59                 "\t-P <path>  add a search path for config change files and use as default\n"
60                 "\t-q         quiet mode (don't print error messages)\n"
61                 "\t-s         force strict mode (stop on parser errors, default)\n"
62                 "\t-S         disable strict mode\n"
63                 "\n",
64                 argv[0]
65         );
66         exit(255);
67 }
68
69 static void cli_perror(void)
70 {
71         if (flags & CLI_FLAG_QUIET)
72                 return;
73
74         uci_perror(ctx, appname);
75 }
76
77 static void uci_show_section(struct uci_section *p)
78 {
79         struct uci_element *e;
80         const char *cname, *sname;
81
82         cname = p->package->e.name;
83         sname = p->e.name;
84         printf("%s.%s=%s\n", cname, sname, p->type);
85         uci_foreach_element(&p->options, e) {
86                 printf("%s.%s.%s=%s\n", cname, sname, e->name, uci_to_option(e)->value);
87         }
88 }
89
90 static void uci_show_package(struct uci_package *p)
91 {
92         struct uci_element *e;
93
94         uci_foreach_element( &p->sections, e) {
95                 uci_show_section(uci_to_section(e));
96         }
97 }
98
99
100 static int package_cmd(int cmd, char *package)
101 {
102         struct uci_package *p = NULL;
103
104         if (uci_load(ctx, package, &p) != UCI_OK) {
105                 cli_perror();
106                 return 1;
107         }
108         if (!p)
109                 return 0;
110         switch(cmd) {
111         case CMD_COMMIT:
112                 if (flags & CLI_FLAG_NOCOMMIT)
113                         return 0;
114                 if (uci_commit(ctx, &p, false) != UCI_OK)
115                         cli_perror();
116                 break;
117         case CMD_EXPORT:
118                 uci_export(ctx, stdout, p, true);
119                 break;
120         case CMD_SHOW:
121                 uci_show_package(p);
122                 break;
123         }
124
125         uci_unload(ctx, p);
126         return 0;
127 }
128
129 static int uci_do_import(int argc, char **argv)
130 {
131         struct uci_package *package = NULL;
132         char *name = NULL;
133         int ret = UCI_OK;
134
135         if (argc > 2)
136                 return 255;
137
138         if (argc == 2)
139                 name = argv[1];
140         else if (flags & CLI_FLAG_MERGE)
141                 /* need a package to merge */
142                 return 255;
143
144         if (flags & CLI_FLAG_MERGE) {
145                 if (uci_load(ctx, name, &package) != UCI_OK)
146                         package = NULL;
147         }
148         ret = uci_import(ctx, input, name, &package, (name != NULL));
149         if (ret == UCI_OK) {
150                 if (flags & CLI_FLAG_MERGE) {
151                         ret = uci_save(ctx, package);
152                 } else {
153                         struct uci_element *e;
154                         /* loop through all config sections and overwrite existing data */
155                         uci_foreach_element(&ctx->root, e) {
156                                 struct uci_package *p = uci_to_package(e);
157                                 ret = uci_commit(ctx, &p, true);
158                         }
159                 }
160         }
161
162         if (ret != UCI_OK) {
163                 cli_perror();
164                 return 1;
165         }
166
167         return 0;
168 }
169
170 static int uci_do_package_cmd(int cmd, int argc, char **argv)
171 {
172         char **configs = NULL;
173         char **p;
174
175         if (argc > 2)
176                 return 255;
177
178         if (argc == 2)
179                 return package_cmd(cmd, argv[1]);
180
181         if ((uci_list_configs(ctx, &configs) != UCI_OK) || !configs) {
182                 cli_perror();
183                 return 1;
184         }
185
186         for (p = configs; *p; p++) {
187                 package_cmd(cmd, *p);
188         }
189
190         return 0;
191 }
192
193
194 static int uci_do_section_cmd(int cmd, int argc, char **argv)
195 {
196         struct uci_package *p = NULL;
197         struct uci_element *e = NULL;
198         char *package = NULL;
199         char *section = NULL;
200         char *option = NULL;
201         char *value = NULL;
202         char **ptr = NULL;
203         int ret = UCI_OK;
204
205         if (argc != 2)
206                 return 255;
207
208         switch(cmd) {
209         case CMD_SET:
210         case CMD_RENAME:
211                 ptr = &value;
212                 break;
213         default:
214                 break;
215         }
216         if (uci_parse_tuple(ctx, argv[1], &package, &section, &option, ptr) != UCI_OK)
217                 return 1;
218
219         if (uci_load(ctx, package, &p) != UCI_OK) {
220                 cli_perror();
221                 return 1;
222         }
223         if (!p)
224                 return 0;
225
226         switch(cmd) {
227         case CMD_GET:
228                 if (uci_lookup(ctx, &e, p, section, option) != UCI_OK)
229                         return 1;
230
231                 switch(e->type) {
232                 case UCI_TYPE_SECTION:
233                         value = uci_to_section(e)->type;
234                         break;
235                 case UCI_TYPE_OPTION:
236                         value = uci_to_option(e)->value;
237                         break;
238                 default:
239                         /* should not happen */
240                         return 1;
241                 }
242                 /* throw the value to stdout */
243                 printf("%s\n", value);
244                 break;
245         case CMD_RENAME:
246                 ret = uci_rename(ctx, p, section, option, value);
247                 break;
248         case CMD_SET:
249                 ret = uci_set(ctx, p, section, option, value);
250                 break;
251         case CMD_DEL:
252                 ret = uci_delete(ctx, p, section, option);
253                 break;
254         }
255
256         /* no save necessary for get */
257         if (cmd == CMD_GET)
258                 return 0;
259
260         /* save changes, but don't commit them yet */
261         if (ret == UCI_OK)
262                 ret = uci_save(ctx, p);
263
264         if (ret != UCI_OK) {
265                 cli_perror();
266                 return 1;
267         }
268
269         return 0;
270 }
271
272 static int uci_cmd(int argc, char **argv)
273 {
274         int cmd = 0;
275
276         if (!strcasecmp(argv[0], "show"))
277                 cmd = CMD_SHOW;
278         else if (!strcasecmp(argv[0], "export"))
279                 cmd = CMD_EXPORT;
280         else if (!strcasecmp(argv[0], "commit"))
281                 cmd = CMD_COMMIT;
282         else if (!strcasecmp(argv[0], "get"))
283                 cmd = CMD_GET;
284         else if (!strcasecmp(argv[0], "set"))
285                 cmd = CMD_SET;
286         else if (!strcasecmp(argv[0], "ren") ||
287                  !strcasecmp(argv[0], "rename"))
288                 cmd = CMD_RENAME;
289         else if (!strcasecmp(argv[0], "del"))
290                 cmd = CMD_DEL;
291         else if (!strcasecmp(argv[0], "import"))
292                 cmd = CMD_IMPORT;
293         else
294                 cmd = -1;
295
296         switch(cmd) {
297                 case CMD_GET:
298                 case CMD_SET:
299                 case CMD_DEL:
300                 case CMD_RENAME:
301                         return uci_do_section_cmd(cmd, argc, argv);
302                 case CMD_SHOW:
303                 case CMD_EXPORT:
304                 case CMD_COMMIT:
305                         return uci_do_package_cmd(cmd, argc, argv);
306                 case CMD_IMPORT:
307                         return uci_do_import(argc, argv);
308                 default:
309                         return 255;
310         }
311 }
312
313 int main(int argc, char **argv)
314 {
315         int ret;
316         int c;
317
318         input = stdin;
319         ctx = uci_alloc_context();
320         if (!ctx) {
321                 fprintf(stderr, "Out of memory\n");
322                 return 1;
323         }
324
325         while((c = getopt(argc, argv, "f:mnNp:P:sSq")) != -1) {
326                 switch(c) {
327                         case 'f':
328                                 input = fopen(optarg, "r");
329                                 if (!input) {
330                                         perror("uci");
331                                         return 1;
332                                 }
333                                 break;
334                         case 'm':
335                                 flags |= CLI_FLAG_MERGE;
336                                 break;
337                         case 's':
338                                 ctx->flags |= UCI_FLAG_STRICT;
339                                 break;
340                         case 'S':
341                                 ctx->flags &= ~UCI_FLAG_STRICT;
342                                 ctx->flags |= UCI_FLAG_PERROR;
343                                 break;
344                         case 'n':
345                                 ctx->flags |= UCI_FLAG_EXPORT_NAME;
346                                 break;
347                         case 'N':
348                                 ctx->flags &= ~UCI_FLAG_EXPORT_NAME;
349                                 break;
350                         case 'p':
351                                 uci_add_history_path(ctx, optarg);
352                                 break;
353                         case 'P':
354                                 uci_add_history_path(ctx, ctx->savedir);
355                                 uci_set_savedir(ctx, optarg);
356                                 flags |= CLI_FLAG_NOCOMMIT;
357                                 break;
358                         case 'q':
359                                 flags |= CLI_FLAG_QUIET;
360                                 break;
361                         default:
362                                 uci_usage(argc, argv);
363                                 break;
364                 }
365         }
366         if (optind > 1)
367                 argv[optind - 1] = argv[0];
368         argv += optind - 1;
369         argc -= optind - 1;
370
371         if (argc < 2)
372                 uci_usage(argc, argv);
373         ret = uci_cmd(argc - 1, argv + 1);
374         if (input != stdin)
375                 fclose(input);
376         if (ret == 255)
377                 uci_usage(argc, argv);
378
379         uci_free_context(ctx);
380
381         return ret;
382 }