libubox
C utility functions for OpenWrt.
json_script.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 #include <sys/stat.h>
17 #include <regex.h>
18 
19 #include "avl-cmp.h"
20 #include "json_script.h"
21 
22 struct json_call {
24  struct blob_attr *vars;
25  unsigned int seq;
26 };
27 
28 struct json_handler {
29  const char *name;
30  int (*cb)(struct json_call *call, struct blob_attr *cur);
31 };
32 
33 static int json_process_expr(struct json_call *call, struct blob_attr *cur);
34 static int json_process_cmd(struct json_call *call, struct blob_attr *cur);
35 static int eval_string(struct json_call *call, struct blob_buf *buf, const char *name, const char *pattern);
36 
37 struct json_script_file *
38 json_script_file_from_blobmsg(const char *name, void *data, int len)
39 {
40  struct json_script_file *f;
41  char *new_name;
42  int name_len = 0;
43 
44  if (name)
45  name_len = strlen(name) + 1;
46 
47  f = calloc_a(sizeof(*f) + len, &new_name, name_len);
48  if (!f)
49  return NULL;
50 
51  memcpy(f->data, data, len);
52  if (name)
53  f->avl.key = strcpy(new_name, name);
54 
55  return f;
56 }
57 
58 static struct json_script_file *
59 json_script_get_file(struct json_script_ctx *ctx, const char *filename)
60 {
61  struct json_script_file *f;
62 
63  f = avl_find_element(&ctx->files, filename, f, avl);
64  if (f)
65  return f;
66 
67  f = ctx->handle_file(ctx, filename);
68  if (!f)
69  return NULL;
70 
71  avl_insert(&ctx->files, &f->avl);
72  return f;
73 }
74 
75 static void __json_script_run(struct json_call *call, struct json_script_file *file,
76  struct blob_attr *context)
77 {
78  struct json_script_ctx *ctx = call->ctx;
79 
80  if (file->seq == call->seq) {
81  if (context)
82  ctx->handle_error(ctx, "Recursive include", context);
83 
84  return;
85  }
86 
87  file->seq = call->seq;
88  while (file) {
89  json_process_cmd(call, file->data);
90  file = file->next;
91  }
92 }
93 
94 const char *json_script_find_var(struct json_script_ctx *ctx, struct blob_attr *vars,
95  const char *name)
96 {
97  struct blob_attr *cur;
98  size_t rem;
99 
100  blobmsg_for_each_attr(cur, vars, rem) {
101  if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING)
102  continue;
103 
104  if (strcmp(blobmsg_name(cur), name) != 0)
105  continue;
106 
107  return blobmsg_data(cur);
108  }
109 
110  return ctx->handle_var(ctx, name, vars);
111 }
112 
113 static const char *
114 msg_find_var(struct json_call *call, const char *name)
115 {
116  return json_script_find_var(call->ctx, call->vars, name);
117 }
118 
119 static void
120 json_get_tuple(struct blob_attr *cur, struct blob_attr **tb, int t1, int t2)
121 {
122  static struct blobmsg_policy expr_tuple[3] = {
123  { .type = BLOBMSG_TYPE_STRING },
124  {},
125  {},
126  };
127 
128  expr_tuple[1].type = t1;
129  expr_tuple[2].type = t2;
130  blobmsg_parse_array(expr_tuple, 3, tb, blobmsg_data(cur), blobmsg_data_len(cur));
131 }
132 
133 static int handle_if(struct json_call *call, struct blob_attr *expr)
134 {
135  struct blob_attr *tb[4];
136  int ret;
137 
138  static const struct blobmsg_policy if_tuple[4] = {
139  { .type = BLOBMSG_TYPE_STRING },
140  { .type = BLOBMSG_TYPE_ARRAY },
141  { .type = BLOBMSG_TYPE_ARRAY },
142  { .type = BLOBMSG_TYPE_ARRAY },
143  };
144 
146 
147  if (!tb[1] || !tb[2])
148  return 0;
149 
150  ret = json_process_expr(call, tb[1]);
151  if (ret < 0)
152  return 0;
153 
154  if (ret)
155  return json_process_cmd(call, tb[2]);
156 
157  if (!tb[3])
158  return 0;
159 
160  return json_process_cmd(call, tb[3]);
161 }
162 
163 static int handle_case(struct json_call *call, struct blob_attr *expr)
164 {
165  struct blob_attr *tb[3], *cur;
166  const char *var;
167  size_t rem;
168 
170  if (!tb[1] || !tb[2])
171  return 0;
172 
173  var = msg_find_var(call, blobmsg_data(tb[1]));
174  if (!var)
175  return 0;
176 
177  blobmsg_for_each_attr(cur, tb[2], rem) {
178  if (!strcmp(var, blobmsg_name(cur)))
179  return json_process_cmd(call, cur);
180  }
181 
182  return 0;
183 }
184 
185 static int handle_return(struct json_call *call, struct blob_attr *expr)
186 {
187  return -2;
188 }
189 
190 static int handle_include(struct json_call *call, struct blob_attr *expr)
191 {
192  struct blob_attr *tb[3];
193  struct json_script_file *f;
194 
196  if (!tb[1])
197  return 0;
198 
199  f = json_script_get_file(call->ctx, blobmsg_data(tb[1]));
200  if (!f)
201  return 0;
202 
203  __json_script_run(call, f, expr);
204  return 0;
205 }
206 
207 static const struct json_handler cmd[] = {
208  { "if", handle_if },
209  { "case", handle_case },
210  { "return", handle_return },
211  { "include", handle_include },
212 };
213 
214 static int eq_regex_cmp(const char *str, const char *pattern, bool regex)
215 {
216  regex_t reg;
217  int ret;
218 
219  if (!regex)
220  return !strcmp(str, pattern);
221 
222  if (regcomp(&reg, pattern, REG_EXTENDED | REG_NOSUB))
223  return 0;
224 
225  ret = !regexec(&reg, str, 0, NULL, 0);
226  regfree(&reg);
227 
228  return ret;
229 }
230 
231 static int expr_eq_regex(struct json_call *call, struct blob_attr *expr, bool regex)
232 {
233  struct json_script_ctx *ctx = call->ctx;
234  struct blob_attr *tb[3], *cur;
235  const char *var;
236  size_t rem;
237 
239  if (!tb[1] || !tb[2])
240  return -1;
241 
242  var = msg_find_var(call, blobmsg_data(tb[1]));
243  if (!var)
244  return 0;
245 
246  switch(blobmsg_type(tb[2])) {
247  case BLOBMSG_TYPE_STRING:
248  return eq_regex_cmp(var, blobmsg_data(tb[2]), regex);
249  case BLOBMSG_TYPE_ARRAY:
250  blobmsg_for_each_attr(cur, tb[2], rem) {
251  if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) {
252  ctx->handle_error(ctx, "Unexpected element type", cur);
253  return -1;
254  }
255 
256  if (eq_regex_cmp(var, blobmsg_data(cur), regex))
257  return 1;
258  }
259  return 0;
260  default:
261  ctx->handle_error(ctx, "Unexpected element type", tb[2]);
262  return -1;
263  }
264 }
265 
266 static int handle_expr_eq(struct json_call *call, struct blob_attr *expr)
267 {
268  return expr_eq_regex(call, expr, false);
269 }
270 
271 static int handle_expr_regex(struct json_call *call, struct blob_attr *expr)
272 {
273  return expr_eq_regex(call, expr, true);
274 }
275 
276 static int handle_expr_has(struct json_call *call, struct blob_attr *expr)
277 {
278  struct json_script_ctx *ctx = call->ctx;
279  struct blob_attr *tb[3], *cur;
280  size_t rem;
281 
282  json_get_tuple(expr, tb, 0, 0);
283  if (!tb[1])
284  return -1;
285 
286  switch(blobmsg_type(tb[1])) {
287  case BLOBMSG_TYPE_STRING:
288  return !!msg_find_var(call, blobmsg_data(tb[1]));
289  case BLOBMSG_TYPE_ARRAY:
290  blobmsg_for_each_attr(cur, tb[1], rem) {
291  if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) {
292  ctx->handle_error(ctx, "Unexpected element type", cur);
293  return -1;
294  }
295 
296  if (msg_find_var(call, blobmsg_data(cur)))
297  return 1;
298  }
299  return 0;
300  default:
301  ctx->handle_error(ctx, "Unexpected element type", tb[1]);
302  return -1;
303  }
304 }
305 
306 static int expr_and_or(struct json_call *call, struct blob_attr *expr, bool and)
307 {
308  struct blob_attr *cur;
309  int ret;
310  size_t rem;
311  int i = 0;
312 
313  blobmsg_for_each_attr(cur, expr, rem) {
314  if (i++ < 1)
315  continue;
316 
317  ret = json_process_expr(call, cur);
318  if (ret < 0)
319  return ret;
320 
321  if (ret != and)
322  return ret;
323  }
324 
325  return and;
326 }
327 
328 static int handle_expr_and(struct json_call *call, struct blob_attr *expr)
329 {
330  return expr_and_or(call, expr, 1);
331 }
332 
333 static int handle_expr_or(struct json_call *call, struct blob_attr *expr)
334 {
335  return expr_and_or(call, expr, 0);
336 }
337 
338 static int handle_expr_not(struct json_call *call, struct blob_attr *expr)
339 {
340  struct blob_attr *tb[3];
341  int ret;
342 
344  if (!tb[1])
345  return -1;
346 
347  ret = json_process_expr(call, tb[1]);
348  if (ret < 0)
349  return ret;
350  return !ret;
351 }
352 
353 static int handle_expr_isdir(struct json_call *call, struct blob_attr *expr)
354 {
355  static struct blob_buf b;
356  struct blob_attr *tb[3];
357  const char *pattern, *path;
358  struct stat s;
359  int ret;
360 
362  if (!tb[1] || blobmsg_type(tb[1]) != BLOBMSG_TYPE_STRING)
363  return -1;
364  pattern = blobmsg_data(tb[1]);
365 
366  blob_buf_init(&b, 0);
367  ret = eval_string(call, &b, NULL, pattern);
368  if (ret < 0)
369  return ret;
370  path = blobmsg_data(blob_data(b.head));
371  ret = stat(path, &s);
372  if (ret < 0)
373  return 0;
374  return S_ISDIR(s.st_mode);
375 }
376 
377 static const struct json_handler expr[] = {
378  { "eq", handle_expr_eq },
379  { "regex", handle_expr_regex },
380  { "has", handle_expr_has },
381  { "and", handle_expr_and },
382  { "or", handle_expr_or },
383  { "not", handle_expr_not },
384  { "isdir", handle_expr_isdir },
385 };
386 
387 static int
388 __json_process_type(struct json_call *call, struct blob_attr *cur,
389  const struct json_handler *h, int n, bool *found)
390 {
391  const char *name = blobmsg_data(blobmsg_data(cur));
392  int i;
393 
394  for (i = 0; i < n; i++) {
395  if (strcmp(name, h[i].name) != 0)
396  continue;
397 
398  *found = true;
399  return h[i].cb(call, cur);
400  }
401 
402  *found = false;
403  return -1;
404 }
405 
406 static int json_process_expr(struct json_call *call, struct blob_attr *cur)
407 {
408  struct json_script_ctx *ctx = call->ctx;
409  bool found;
410  int ret;
411 
412  if (blobmsg_type(cur) != BLOBMSG_TYPE_ARRAY ||
414  ctx->handle_error(ctx, "Unexpected element type", cur);
415  return -1;
416  }
417 
418  ret = __json_process_type(call, cur, expr, ARRAY_SIZE(expr), &found);
419  if (!found) {
420  const char *name = blobmsg_data(blobmsg_data(cur));
421  ctx->handle_expr(ctx, name, cur, call->vars);
422  }
423 
424  return ret;
425 }
426 
427 static int eval_string(struct json_call *call, struct blob_buf *buf, const char *name, const char *pattern)
428 {
429  char *dest, *next, *str;
430  int len = 0;
431  bool var = false;
432  char c = '%';
433 
435  if (!dest)
436  return -1;
437 
438  next = alloca(strlen(pattern) + 1);
439  strcpy(next, pattern);
440 
441  for (str = next; str; str = next) {
442  const char *cur;
443  char *end, *new_buf;
444  int cur_len = 0;
445  bool cur_var = var;
446 
447  end = strchr(str, '%');
448  if (end) {
449  *end = 0;
450  next = end + 1;
451  var = !var;
452  } else {
453  end = str + strlen(str);
454  next = NULL;
455  }
456 
457  if (cur_var) {
458  if (end > str) {
459  cur = msg_find_var(call, str);
460  if (!cur)
461  continue;
462 
463  cur_len = strlen(cur);
464  } else {
465  cur = &c;
466  cur_len = 1;
467  }
468  } else {
469  if (str == end)
470  continue;
471 
472  cur = str;
473  cur_len = end - str;
474  }
475 
476  new_buf = blobmsg_realloc_string_buffer(buf, len + cur_len);
477  if (!new_buf) {
478  /* Make eval_string return -1 */
479  var = true;
480  break;
481  }
482 
483  dest = new_buf;
484  memcpy(dest + len, cur, cur_len);
485  len += cur_len;
486  }
487 
488  dest[len] = 0;
490 
491  if (var)
492  return -1;
493 
494  return 0;
495 }
496 
497 static int cmd_add_string(struct json_call *call, const char *pattern)
498 {
499  return eval_string(call, &call->ctx->buf, NULL, pattern);
500 }
501 
502 int json_script_eval_string(struct json_script_ctx *ctx, struct blob_attr *vars,
503  struct blob_buf *buf, const char *name,
504  const char *pattern)
505 {
506  struct json_call call = {
507  .ctx = ctx,
508  .vars = vars,
509  };
510 
511  return eval_string(&call, buf, name, pattern);
512 }
513 
514 static int cmd_process_strings(struct json_call *call, struct blob_attr *attr)
515 {
516  struct json_script_ctx *ctx = call->ctx;
517  struct blob_attr *cur;
518  int args = -1;
519  int ret;
520  size_t rem;
521  void *c;
522 
523  blob_buf_init(&ctx->buf, 0);
524  c = blobmsg_open_array(&ctx->buf, NULL);
525  blobmsg_for_each_attr(cur, attr, rem) {
526  if (args++ < 0)
527  continue;
528 
529  if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) {
530  blobmsg_add_blob(&ctx->buf, cur);
531  continue;
532  }
533 
534  ret = cmd_add_string(call, blobmsg_data(cur));
535  if (ret) {
536  ctx->handle_error(ctx, "Unterminated variable reference in string", attr);
537  return ret;
538  }
539  }
540 
541  blobmsg_close_array(&ctx->buf, c);
542 
543  return 0;
544 }
545 
546 static int __json_process_cmd(struct json_call *call, struct blob_attr *cur)
547 {
548  struct json_script_ctx *ctx = call->ctx;
549  const char *name;
550  bool found;
551  int ret;
552 
553  if (blobmsg_type(cur) != BLOBMSG_TYPE_ARRAY ||
555  ctx->handle_error(ctx, "Unexpected element type", cur);
556  return -1;
557  }
558 
559  ret = __json_process_type(call, cur, cmd, ARRAY_SIZE(cmd), &found);
560  if (found)
561  return ret;
562 
564  ret = cmd_process_strings(call, cur);
565  if (ret)
566  return ret;
567 
568  ctx->handle_command(ctx, name, blob_data(ctx->buf.head), call->vars);
569 
570  return 0;
571 }
572 
573 static int json_process_cmd(struct json_call *call, struct blob_attr *block)
574 {
575  struct json_script_ctx *ctx = call->ctx;
576  struct blob_attr *cur;
577  size_t rem;
578  int ret;
579  int i = 0;
580 
581  if (blobmsg_type(block) != BLOBMSG_TYPE_ARRAY) {
582  ctx->handle_error(ctx, "Unexpected element type", block);
583  return -1;
584  }
585 
586  blobmsg_for_each_attr(cur, block, rem) {
587  if (ctx->abort)
588  break;
589 
590  switch(blobmsg_type(cur)) {
591  case BLOBMSG_TYPE_STRING:
592  if (!i)
593  return __json_process_cmd(call, block);
594  fallthrough;
595  default:
596  ret = json_process_cmd(call, cur);
597  if (ret < -1)
598  return ret;
599  break;
600  }
601  i++;
602  }
603 
604  return 0;
605 }
606 
608  struct blob_attr *vars)
609 {
610  static unsigned int _seq = 0;
611  struct json_call call = {
612  .ctx = ctx,
613  .vars = vars,
614  .seq = ++_seq,
615  };
616 
617  /* overflow */
618  if (!call.seq)
619  call.seq = ++_seq;
620 
621  ctx->abort = false;
622 
623  __json_script_run(&call, file, NULL);
624 }
625 
626 void json_script_run(struct json_script_ctx *ctx, const char *name,
627  struct blob_attr *vars)
628 {
629  struct json_script_file *file;
630 
631  file = json_script_get_file(ctx, name);
632  if (!file)
633  return;
634 
635  json_script_run_file(ctx, file, vars);
636 }
637 
639 {
640  struct json_script_file *next;
641 
642  if (!f)
643  return;
644 
645  next = f->next;
646  free(f);
647 
649 }
650 
651 void
653 {
654  struct json_script_file *f, *next;
655 
658 
659  blob_buf_free(&ctx->buf);
660 }
661 
662 static void
663 __default_handle_error(struct json_script_ctx *ctx, const char *msg,
664  struct blob_attr *context)
665 {
666 }
667 
668 static const char *
669 __default_handle_var(struct json_script_ctx *ctx, const char *name,
670  struct blob_attr *vars)
671 {
672  return NULL;
673 }
674 
675 static int
676 __default_handle_expr(struct json_script_ctx *ctx, const char *name,
677  struct blob_attr *expr, struct blob_attr *vars)
678 {
679  ctx->handle_error(ctx, "Unknown expression type", expr);
680  return -1;
681 }
682 
683 static struct json_script_file *
684 __default_handle_file(struct json_script_ctx *ctx, const char *name)
685 {
686  return NULL;
687 }
688 
690 {
691  avl_init(&ctx->files, avl_strcmp, false, NULL);
692 
693  if (!ctx->handle_error)
695 
696  if (!ctx->handle_var)
698 
699  if (!ctx->handle_expr)
701 
702  if (!ctx->handle_file)
704 }
int avl_strcmp(const void *k1, const void *k2, void *ptr)
Definition: avl-cmp.c:26
int avl_insert(struct avl_tree *tree, struct avl_node *new)
Definition: avl.c:220
void avl_init(struct avl_tree *tree, avl_tree_comp comp, bool allow_dups, void *ptr)
Definition: avl.c:92
#define avl_find_element(tree, key, element, node_element)
Definition: avl.h:240
#define avl_remove_all_elements(tree, element, node_member, ptr)
Definition: avl.h:545
void blob_buf_free(struct blob_buf *buf)
Definition: blob.c:104
int blob_buf_init(struct blob_buf *buf, int id)
Definition: blob.c:91
char data[]
Definition: blob.h:1
static void * blob_data(const struct blob_attr *attr)
Definition: blob.h:75
void * blobmsg_alloc_string_buffer(struct blob_buf *buf, const char *name, unsigned int maxlen)
Definition: blobmsg.c:326
void blobmsg_add_string_buffer(struct blob_buf *buf)
Definition: blobmsg.c:361
int blobmsg_parse_array(const struct blobmsg_policy *policy, int policy_len, struct blob_attr **tb, void *data, unsigned int len)
Definition: blobmsg.c:140
void * blobmsg_realloc_string_buffer(struct blob_buf *buf, unsigned int maxlen)
Definition: blobmsg.c:343
static size_t blobmsg_data_len(const struct blob_attr *attr)
Definition: blobmsg.h:95
static int blobmsg_add_blob(struct blob_buf *buf, struct blob_attr *attr)
Definition: blobmsg.h:241
static const char * blobmsg_name(const struct blob_attr *attr)
Definition: blobmsg.h:62
static void blobmsg_close_array(struct blob_buf *buf, void *cookie)
Definition: blobmsg.h:262
#define blobmsg_for_each_attr(pos, attr, rem)
Definition: blobmsg.h:364
uint8_t name[]
Definition: blobmsg.h:1
blobmsg_type
Definition: blobmsg.h:25
@ BLOBMSG_TYPE_TABLE
Definition: blobmsg.h:28
@ BLOBMSG_TYPE_STRING
Definition: blobmsg.h:29
@ BLOBMSG_TYPE_ARRAY
Definition: blobmsg.h:27
static void * blobmsg_open_array(struct blob_buf *buf, const char *name)
Definition: blobmsg.h:250
static void * blobmsg_data(const struct blob_attr *attr)
Definition: blobmsg.h:78
static struct blob_buf b
Definition: jshn.c:40
static int handle_return(struct json_call *call, struct blob_attr *expr)
Definition: json_script.c:185
static int cmd_add_string(struct json_call *call, const char *pattern)
Definition: json_script.c:497
static int __json_process_cmd(struct json_call *call, struct blob_attr *cur)
Definition: json_script.c:546
static const struct json_handler cmd[]
Definition: json_script.c:207
void json_script_init(struct json_script_ctx *ctx)
Definition: json_script.c:689
static int __default_handle_expr(struct json_script_ctx *ctx, const char *name, struct blob_attr *expr, struct blob_attr *vars)
Definition: json_script.c:676
static struct json_script_file * json_script_get_file(struct json_script_ctx *ctx, const char *filename)
Definition: json_script.c:59
static int expr_eq_regex(struct json_call *call, struct blob_attr *expr, bool regex)
Definition: json_script.c:231
void json_script_free(struct json_script_ctx *ctx)
Definition: json_script.c:652
static int handle_if(struct json_call *call, struct blob_attr *expr)
Definition: json_script.c:133
static void __json_script_run(struct json_call *call, struct json_script_file *file, struct blob_attr *context)
Definition: json_script.c:75
static int handle_expr_regex(struct json_call *call, struct blob_attr *expr)
Definition: json_script.c:271
struct json_script_file * json_script_file_from_blobmsg(const char *name, void *data, int len)
Definition: json_script.c:38
static int handle_expr_and(struct json_call *call, struct blob_attr *expr)
Definition: json_script.c:328
static const struct json_handler expr[]
Definition: json_script.c:377
static const char * __default_handle_var(struct json_script_ctx *ctx, const char *name, struct blob_attr *vars)
Definition: json_script.c:669
static int json_process_expr(struct json_call *call, struct blob_attr *cur)
Definition: json_script.c:406
static int handle_expr_or(struct json_call *call, struct blob_attr *expr)
Definition: json_script.c:333
static int expr_and_or(struct json_call *call, struct blob_attr *expr, bool and)
Definition: json_script.c:306
static void __default_handle_error(struct json_script_ctx *ctx, const char *msg, struct blob_attr *context)
Definition: json_script.c:663
static int json_process_cmd(struct json_call *call, struct blob_attr *cur)
Definition: json_script.c:573
static int __json_process_type(struct json_call *call, struct blob_attr *cur, const struct json_handler *h, int n, bool *found)
Definition: json_script.c:388
static const char * msg_find_var(struct json_call *call, const char *name)
Definition: json_script.c:114
static struct json_script_file * __default_handle_file(struct json_script_ctx *ctx, const char *name)
Definition: json_script.c:684
static int handle_expr_has(struct json_call *call, struct blob_attr *expr)
Definition: json_script.c:276
static int handle_expr_isdir(struct json_call *call, struct blob_attr *expr)
Definition: json_script.c:353
int json_script_eval_string(struct json_script_ctx *ctx, struct blob_attr *vars, struct blob_buf *buf, const char *name, const char *pattern)
Definition: json_script.c:502
static void json_get_tuple(struct blob_attr *cur, struct blob_attr **tb, int t1, int t2)
Definition: json_script.c:120
void json_script_run(struct json_script_ctx *ctx, const char *name, struct blob_attr *vars)
Definition: json_script.c:626
static int handle_case(struct json_call *call, struct blob_attr *expr)
Definition: json_script.c:163
void json_script_run_file(struct json_script_ctx *ctx, struct json_script_file *file, struct blob_attr *vars)
Definition: json_script.c:607
static int cmd_process_strings(struct json_call *call, struct blob_attr *attr)
Definition: json_script.c:514
const char * json_script_find_var(struct json_script_ctx *ctx, struct blob_attr *vars, const char *name)
Definition: json_script.c:94
static int handle_expr_eq(struct json_call *call, struct blob_attr *expr)
Definition: json_script.c:266
static int eval_string(struct json_call *call, struct blob_buf *buf, const char *name, const char *pattern)
Definition: json_script.c:427
static int handle_include(struct json_call *call, struct blob_attr *expr)
Definition: json_script.c:190
static void __json_script_file_free(struct json_script_file *f)
Definition: json_script.c:638
static int handle_expr_not(struct json_call *call, struct blob_attr *expr)
Definition: json_script.c:338
static int eq_regex_cmp(const char *str, const char *pattern, bool regex)
Definition: json_script.c:214
const void * key
Definition: avl.h:84
Definition: blob.h:52
Definition: blob.h:64
struct blob_attr * head
Definition: blob.h:65
enum blobmsg_type type
Definition: blobmsg.h:48
unsigned int seq
Definition: json_script.c:25
struct json_script_ctx * ctx
Definition: json_script.c:23
struct blob_attr * vars
Definition: json_script.c:24
int(* cb)(struct json_call *call, struct blob_attr *cur)
Definition: json_script.c:30
const char * name
Definition: json_script.c:29
const char *(* handle_var)(struct json_script_ctx *ctx, const char *name, struct blob_attr *vars)
Definition: json_script.h:57
int(* handle_expr)(struct json_script_ctx *ctx, const char *name, struct blob_attr *expr, struct blob_attr *vars)
Definition: json_script.h:50
void(* handle_error)(struct json_script_ctx *ctx, const char *msg, struct blob_attr *context)
Definition: json_script.h:77
struct blob_buf buf
Definition: json_script.h:28
void(* handle_command)(struct json_script_ctx *ctx, const char *name, struct blob_attr *cmd, struct blob_attr *vars)
Definition: json_script.h:40
struct json_script_file *(* handle_file)(struct json_script_ctx *ctx, const char *name)
Definition: json_script.h:67
struct avl_tree files
Definition: json_script.h:27
unsigned int seq
Definition: json_script.h:85
struct avl_node avl
Definition: json_script.h:82
struct json_script_file * next
Definition: json_script.h:83
struct blob_attr data[]
Definition: json_script.h:86
#define ARRAY_SIZE(x)
struct udebug_client_msg * msg
Definition: udebug-priv.h:29
#define fallthrough
Definition: utils.h:238
#define calloc_a(len,...)
Definition: utils.h:39