97978a036bb6e97726d0056f226b49e0e8f2a1ff
[project/ubox.git] / validate / cli.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdbool.h>
5 #include <ctype.h>
6
7 #include <arpa/inet.h>
8 #include <netinet/ether.h>
9 #include <sys/stat.h>
10
11 #include <uci.h>
12
13 #include "libvalidate.h"
14
15 static void
16 print_usage(char *argv)
17 {
18         fprintf(stderr, "%s <datatype> <value>\t- validate a value against a type\n", argv);
19         fprintf(stderr, "%s <package> <section_type> <section_name> 'option:datatype:default' 'option:datatype:default' ...\n", argv);
20 }
21
22 static const char *
23 bool_to_num(const char *val)
24 {
25         if (!strcmp(val, "0") || !strcmp(val, "off") || !strcmp(val, "false") || !strcmp(val, "disabled"))
26                 return "0";
27         if (!strcmp(val, "1") || !strcmp(val, "on") || !strcmp(val, "true") || !strcmp(val, "enabled"))
28                 return "1";
29
30         return "";
31 }
32
33 static void
34 escape_value(enum dt_type type, const char *val)
35 {
36         const char *p;
37
38         switch(type)
39         {
40         case DT_BOOL:
41                 printf("%s", bool_to_num(val));
42                 break;
43
44         case DT_STRING:
45                 printf("'");
46
47                 for (p = val; *p; p++)
48                         if (*p == '\'')
49                                 printf("'\"'\"'");
50                         else
51                                 printf("%c", *p);
52
53                 printf("'");
54                 break;
55
56         default:
57                 printf("%s", val);
58                 break;
59         }
60 }
61
62 static void
63 export_value(enum dt_type type, const char *name, const char *val)
64 {
65         if ((type == DT_INVALID) || !val || !*val)
66         {
67                 printf("unset -v %s; ", name);
68                 return;
69         }
70
71         printf("%s=", name);
72         escape_value(type, val);
73         printf("; ");
74 }
75
76 static void
77 validate_value(struct uci_ptr *ptr, const char *expr, const char *def)
78 {
79         int i = 0;
80         bool empty = true, first = true;
81         enum dt_type type;
82         struct uci_element *e;
83         struct uci_option *opt = ptr->o;
84
85         if (opt->type == UCI_TYPE_LIST)
86         {
87                 uci_foreach_element(&opt->v.list, e)
88                 {
89                         if (!e->name || !*e->name)
90                                 continue;
91
92                         empty = false;
93                         break;
94                 }
95
96                 if (empty)
97                 {
98                         export_value(DT_STRING, ptr->option, def);
99                         return;
100                 }
101
102                 uci_foreach_element(&opt->v.list, e)
103                 {
104                         if (!e->name || !*e->name)
105                                 continue;
106
107                         if (first)
108                                 printf("%s=", ptr->option);
109                         else
110                                 printf("\\ ");
111
112                         first = false;
113                         type = dt_parse(expr, e->name);
114
115                         if (type != DT_INVALID)
116                                 escape_value(type, e->name);
117
118                         fprintf(stderr, "%s.%s.%s[%u]=%s validates as %s with %s\n",
119                                 ptr->package, ptr->section, ptr->option, i++, e->name,
120                                 expr, type ? "true" : "false");
121                 }
122
123                 printf("; ");
124         }
125         else
126         {
127                 if (!opt->v.string || !*opt->v.string)
128                 {
129                         export_value(DT_STRING, ptr->option, def);
130                         return;
131                 }
132
133                 type = dt_parse(expr, opt->v.string);
134                 export_value(type, ptr->option, opt->v.string);
135
136                 fprintf(stderr, "%s.%s.%s=%s validates as %s with %s\n",
137                                 ptr->package, ptr->section, ptr->option, opt->v.string,
138                         expr, type ? "true" : "false");
139         }
140 }
141
142 static void
143 validate_option(struct uci_context *ctx, char *package, char *section, char *option)
144 {
145         char *def, *expr;
146         struct uci_ptr ptr = { 0 };
147
148         if ((expr = strchr(option, ':')) == NULL)
149         {
150                 fprintf(stderr, "%s is not a valid option\n", option);
151                 return;
152         }
153
154         *expr++ = 0;
155
156         if ((def = strrchr(expr, ':')) != NULL)
157                 *def++ = 0;
158
159         ptr.package = package;
160         ptr.section = section;
161         ptr.option = option;
162
163         if (uci_lookup_ptr(ctx, &ptr, NULL, false) ||
164             !(ptr.flags & UCI_LOOKUP_COMPLETE) ||
165             (ptr.last->type != UCI_TYPE_OPTION))
166         {
167                 export_value(DT_STRING, option, def);
168                 return;
169         }
170
171         validate_value(&ptr, expr, def);
172 }
173
174 int
175 main(int argc, char **argv)
176 {
177         struct uci_context *ctx;
178         struct uci_package *package;
179         int len = argc - 4;
180         enum dt_type rv;
181         int i;
182
183         if (argc == 3) {
184                 rv = dt_parse(argv[1], argv[2]);
185                 fprintf(stderr, "%s - %s = %s\n", argv[1], argv[2], rv ? "true" : "false");
186                 return rv ? 0 : 1;
187         } else if (argc < 5) {
188                 print_usage(*argv);
189                 return -1;
190         }
191
192         if (*argv[3] == '\0') {
193                 printf("json_add_object; ");
194                 printf("json_add_string \"package\" \"%s\"; ", argv[1]);
195                 printf("json_add_string \"type\" \"%s\"; ", argv[2]);
196                 printf("json_add_object \"data\"; ");
197
198                 for (i = 0; i < len; i++) {
199                         char *datatype = strstr(argv[4 + i], ":");
200                         char *def;
201
202                         if (!datatype)
203                                 continue;
204                         *datatype = '\0';
205                         datatype++;
206                         def = strstr(datatype, ":");
207                         if (def)
208                                 *def = '\0';
209                         printf("json_add_string \"%s\" \"%s\"; ", argv[4 + i], datatype);
210                 }
211                 printf("json_close_object; ");
212                 printf("json_close_object; ");
213
214                 return 0;
215         }
216
217         ctx = uci_alloc_context();
218         if (!ctx)
219                 return -1;
220
221         if (uci_load(ctx, argv[1], &package))
222                 return -1;
223
224         for (i = 0; i < len; i++)
225                 validate_option(ctx, argv[1], argv[3], argv[4 + i]);
226
227         return 0;
228 }