proto-shell: move script handler config parse code to handler.c
[project/netifd.git] / handler.c
1 /*
2 * netifd - network interface daemon
3 * Copyright (C) 2012-2013 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
15 #define _GNU_SOURCE
16 #include <glob.h>
17 #include <fcntl.h>
18 #include <stdio.h>
19 #include <unistd.h>
20
21 #include "netifd.h"
22 #include "system.h"
23 #include "handler.h"
24
25 static int
26 netifd_dir_push(int fd)
27 {
28 int prev_fd = open(".", O_RDONLY | O_DIRECTORY);
29 system_fd_set_cloexec(prev_fd);
30 if (fd >= 0)
31 fchdir(fd);
32 return prev_fd;
33 }
34
35 static void
36 netifd_dir_pop(int prev_fd)
37 {
38 fchdir(prev_fd);
39 close(prev_fd);
40 }
41
42 int netifd_open_subdir(const char *name)
43 {
44 int prev_dir;
45 int ret = -1;
46
47 prev_dir = netifd_dir_push(-1);
48 if (chdir(main_path)) {
49 perror("chdir(main path)");
50 goto out;
51 }
52
53 ret = open(name, O_RDONLY | O_DIRECTORY);
54 if (ret >= 0)
55 system_fd_set_cloexec(ret);
56
57 out:
58 netifd_dir_pop(prev_dir);
59 return ret;
60 }
61
62 static void
63 netifd_init_script_handler(const char *name, script_dump_cb cb)
64 {
65 struct json_tokener *tok = NULL;
66 json_object *obj;
67 static char buf[512];
68 char *start, *cmd;
69 FILE *f;
70 int len;
71
72 #define DUMP_SUFFIX " '' dump"
73
74 cmd = alloca(strlen(name) + 1 + sizeof(DUMP_SUFFIX));
75 sprintf(cmd, "%s" DUMP_SUFFIX, name);
76
77 f = popen(cmd, "r");
78 if (!f)
79 return;
80
81 do {
82 start = fgets(buf, sizeof(buf), f);
83 if (!start)
84 continue;
85
86 len = strlen(start);
87
88 if (!tok)
89 tok = json_tokener_new();
90
91 obj = json_tokener_parse_ex(tok, start, len);
92 if (!is_error(obj)) {
93 cb(name, obj);
94 json_object_put(obj);
95 json_tokener_free(tok);
96 tok = NULL;
97 } else if (start[len - 1] == '\n') {
98 json_tokener_free(tok);
99 tok = NULL;
100 }
101 } while (!feof(f) && !ferror(f));
102
103 if (tok)
104 json_tokener_free(tok);
105
106 pclose(f);
107 }
108
109 void netifd_init_script_handlers(int dir_fd, script_dump_cb cb)
110 {
111 glob_t g;
112 int i, prev_fd;
113
114 prev_fd = netifd_dir_push(dir_fd);
115 glob("./*.sh", 0, NULL, &g);
116 for (i = 0; i < g.gl_pathc; i++)
117 netifd_init_script_handler(g.gl_pathv[i], cb);
118 netifd_dir_pop(prev_fd);
119 }
120
121 char *
122 netifd_handler_parse_config(struct uci_blob_param_list *config, json_object *obj)
123 {
124 struct blobmsg_policy *attrs;
125 char *str_buf, *str_cur;
126 int str_len = 0;
127 int i;
128
129 config->n_params = json_object_array_length(obj);
130 attrs = calloc(1, sizeof(*attrs) * config->n_params);
131 if (!attrs)
132 return NULL;
133
134 config->params = attrs;
135 for (i = 0; i < config->n_params; i++) {
136 json_object *cur, *name, *type;
137
138 cur = json_check_type(json_object_array_get_idx(obj, i), json_type_array);
139 if (!cur)
140 goto error;
141
142 name = json_check_type(json_object_array_get_idx(cur, 0), json_type_string);
143 if (!name)
144 goto error;
145
146 type = json_check_type(json_object_array_get_idx(cur, 1), json_type_int);
147 if (!type)
148 goto error;
149
150 attrs[i].name = json_object_get_string(name);
151 attrs[i].type = json_object_get_int(type);
152 if (attrs[i].type > BLOBMSG_TYPE_LAST)
153 goto error;
154
155 str_len += strlen(attrs[i].name) + 1;
156 }
157
158 str_buf = malloc(str_len);
159 if (!str_buf)
160 goto error;
161
162 str_cur = str_buf;
163 for (i = 0; i < config->n_params; i++) {
164 const char *name = attrs[i].name;
165
166 attrs[i].name = str_cur;
167 str_cur += sprintf(str_cur, "%s", name) + 1;
168 }
169
170 return str_buf;
171
172 error:
173 free(attrs);
174 config->n_params = 0;
175 return NULL;
176 }