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, "") || !strcmp(val, "off") || !strcmp(val, "false") || !strcmp(val, "no") || !strcmp(val, "disabled")) 26 return ""; 27 if (!strcmp(val, "1") || !strcmp(val, "on") || !strcmp(val, "true") || !strcmp(val, "yes") || !strcmp(val, "enabled")) 28 return "1"; 29 30 return ""; 31 } 32 33 static bool 34 parse_tuple(char *tuple, char **option, char **expr, char **def) 35 { 36 char *p; 37 bool esc; 38 39 for (esc = false, p = *option = tuple, *expr = NULL, *def = NULL; *p; p++) 40 { 41 if (!esc && *p == '\\') 42 { 43 esc = true; 44 continue; 45 } 46 47 if (!esc && *p == ':') 48 { 49 *p++ = 0; 50 51 if (!*expr) 52 *expr = p; 53 else if (!*def) 54 *def = p; 55 else 56 break; 57 } 58 59 esc = false; 60 } 61 62 return (*expr != NULL); 63 } 64 65 static void 66 escape_value(enum dt_type type, const char *val) 67 { 68 const char *p; 69 70 switch(type) 71 { 72 case DT_BOOL: 73 printf("%s", bool_to_num(val)); 74 break; 75 76 case DT_STRING: 77 printf("'"); 78 79 for (p = val; *p; p++) 80 if (*p == '\'') 81 printf("'\"'\"'"); 82 else 83 printf("%c", *p); 84 85 printf("'"); 86 break; 87 88 default: 89 printf("%s", val); 90 break; 91 } 92 } 93 94 static void 95 export_value(enum dt_type type, const char *name, const char *val) 96 { 97 if ((type == DT_INVALID) || !val || !*val) 98 { 99 printf("unset -v %s; ", name); 100 return; 101 } 102 103 printf("%s=", name); 104 escape_value(type, val); 105 printf("; "); 106 } 107 108 static int 109 validate_value(struct uci_ptr *ptr, const char *expr, const char *def) 110 { 111 int i = 0; 112 bool empty = true; 113 enum dt_type type = DT_INVALID; 114 struct uci_element *e; 115 struct uci_option *opt = NULL; 116 117 if ((ptr->flags & UCI_LOOKUP_COMPLETE) && 118 (ptr->last->type == UCI_TYPE_OPTION)) 119 opt = ptr->o; 120 121 if (opt && opt->type == UCI_TYPE_LIST) 122 { 123 uci_foreach_element(&opt->v.list, e) 124 { 125 if (!e->name || !*e->name) 126 continue; 127 128 if (empty) 129 printf("%s=", ptr->option); 130 else 131 printf("\\ "); 132 133 empty = false; 134 type = dt_parse(expr, e->name); 135 136 if (type != DT_INVALID) 137 escape_value(type, e->name); 138 139 fprintf(stderr, "%s.%s.%s[%u]=%s validates as %s with %s\n", 140 ptr->package, ptr->section, ptr->option, i++, e->name, 141 expr, type ? "true" : "false"); 142 } 143 144 if (!empty) 145 printf("; "); 146 } 147 else if (opt && opt->v.string && *opt->v.string) 148 { 149 empty = false; 150 type = dt_parse(expr, opt->v.string); 151 export_value(type, ptr->option, opt->v.string); 152 153 fprintf(stderr, "%s.%s.%s=%s validates as %s with %s\n", 154 ptr->package, ptr->section, ptr->option, opt->v.string, 155 expr, type ? "true" : "false"); 156 } 157 158 if (empty) 159 { 160 type = dt_parse(expr, def); 161 162 if (type == DT_INVALID) 163 type = DT_STRING; 164 165 export_value(type, ptr->option, def); 166 167 fprintf(stderr, "%s.%s.%s is unset and defaults to %s %s\n", 168 ptr->package, ptr->section, ptr->option, expr, def); 169 } 170 171 return type ? 0 : -1; 172 } 173 174 static int 175 validate_option(struct uci_context *ctx, char *package, char *section, char *option) 176 { 177 char *opt, *expr, *def; 178 struct uci_ptr ptr = {}; 179 180 if (!parse_tuple(option, &opt, &expr, &def)) 181 { 182 fprintf(stderr, "%s is not a valid option\n", option); 183 return -1; 184 } 185 186 ptr.package = package; 187 ptr.section = section; 188 ptr.option = opt; 189 190 uci_lookup_ptr(ctx, &ptr, NULL, false); 191 192 return validate_value(&ptr, expr, def); 193 } 194 195 int 196 main(int argc, char **argv) 197 { 198 struct uci_context *ctx; 199 struct uci_package *package; 200 char *opt, *expr, *def; 201 int len = argc - 4; 202 enum dt_type rv; 203 int i, rc; 204 205 if (argc == 3) { 206 rv = dt_parse(argv[1], argv[2]); 207 fprintf(stderr, "%s - %s = %s\n", argv[1], argv[2], rv ? "true" : "false"); 208 return rv ? 0 : 1; 209 } else if (argc < 5) { 210 print_usage(*argv); 211 return -1; 212 } 213 214 if (*argv[3] == '\0') { 215 printf("json_add_object; "); 216 printf("json_add_string \"package\" \"%s\"; ", argv[1]); 217 printf("json_add_string \"type\" \"%s\"; ", argv[2]); 218 printf("json_add_object \"data\"; "); 219 220 for (i = 0; i < len; i++) { 221 if (!parse_tuple(argv[4 + i], &opt, &expr, &def)) 222 continue; 223 224 printf("json_add_string \"%s\" \"%s\"; ", opt, expr); 225 } 226 227 printf("json_close_object; "); 228 printf("json_close_object; "); 229 230 return 0; 231 } 232 233 ctx = uci_alloc_context(); 234 if (!ctx) 235 return -1; 236 237 if (uci_load(ctx, argv[1], &package)) 238 return -1; 239 240 rc = 0; 241 for (i = 0; i < len; i++) { 242 if (validate_option(ctx, argv[1], argv[3], argv[4 + i])) { 243 rc = -1; 244 } 245 } 246 247 return rc; 248 } 249
This page was automatically generated by LXR 0.3.1. • OpenWrt