1// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5#include "config.h"
6#include <string.h>
7
8/*third party lib*/
9#include <json-c/json.h>
10
11
12static char *alloc_json_string(struct json_object *o)
13{
14 const char *v;
15
16 if (!json_object_is_type(o, json_type_string))
17 return NULL;
18
19 v = json_object_get_string(o);
20 if (!v)
21 return NULL;
22
23 return strdup(v);
24}
25
26static int get_json_int(struct json_object *o, int *i, bool nonneg)
27{
28 if (!json_object_is_type(o, json_type_int))
29 return -1;
30
31 *i = json_object_get_int(o);
32
33 if (*i == INT32_MIN)
34 return -1;
35
36 if (*i == INT32_MAX)
37 return -1;
38
39 if (nonneg && *i < 0)
40 return -1;
41
42 return 0;
43}
44
45static int get_json_boolean(struct json_object *o, bool *b)
46{
47 if (!json_object_is_type(o, json_type_boolean))
48 return -1;
49
50 *b = json_object_get_boolean(o);
51
52 return 0;
53}
54
55static int read_map_config(struct json_object *root, DumpConfig& cfg)
56{
57 if (!json_object_is_type(root, json_type_array))
58 return -1;
59
60 int len = json_object_array_length(root);
61 if (len < 1)
62 return -1;
63
64 for (int i = 0; i < len; i++) {
65 struct json_object *v = json_object_array_get_idx(root, i);
66 if (!v)
67 return -1;
68
69 cfg.modules.push_back(alloc_json_string(v));
70 }
71
72 return 0;
73}
74
75static int read_variable_item(struct json_object *root, DumpConfig& cfg)
76{
77 struct json_object_iterator it;
78 struct json_object_iterator it_end;
79 Variable tmp;
80
81 tmp.max_size = 1024;
82 tmp.is_pointer = false;
83
84 for (it = json_object_iter_begin(root),
85 it_end = json_object_iter_end(root);
86 !json_object_iter_equal(&it, &it_end);
87 json_object_iter_next(&it)) {
88
89 struct json_object *v;
90 const char* n = json_object_iter_peek_name(&it);
91 if (!n)
92 goto out_err;
93
94 v = json_object_iter_peek_value(&it);
95 if (!v)
96 goto out_err;
97
98 if (strcmp(n, "name") == 0) {
99 tmp.sym_name = alloc_json_string(v);
100 if (tmp.sym_name.empty())
101 goto out_err;
102 }
103 else if (strcmp(n, "is_pointer") == 0) {
104 get_json_boolean(v, &tmp.is_pointer);
105 }
106 else if (strcmp(n, "max_size") == 0) {
107 int number = 0;
108 get_json_int(v, &number, true);
109 if (number > 0) {
110 tmp.max_size = (number + 3) & (~3);
111 }
112 } else {
113 printf("WARNING: ignoring unknown config item: %s\n", n);
114 }
115 }
116
117 cfg.vars.push_back(tmp);
118
119 return 0;
120
121out_err:
122 return -1;
123}
124
125
126static int read_global_var_config(struct json_object *root, DumpConfig& cfg)
127{
128 if (!json_object_is_type(root, json_type_array))
129 return -1;
130
131 int len = json_object_array_length(root);
132 if (len < 1)
133 return -1;
134
135 for (int i = 0; i < len; i++) {
136 struct json_object *v;
137
138 v = json_object_array_get_idx(root, i);
139 if (!v)
140 return -1;
141
142 if (read_variable_item(v, cfg) != 0)
143 return -1;
144 }
145
146 return 0;
147}
148
149int load_config(DumpConfig& cfg)
150{
151 const char* user_file = nullptr;
152 char cfg_file[256];
153 struct json_object_iterator it;
154 struct json_object_iterator it_end;
155
156 cfg.max_heap_size = 0;
157 cfg.dump_pthread_list = false;
158 cfg.dump_robust_mutex_list = false;
159 cfg.current_thread_only = false;
160 cfg.max_stack_size = 32*1024; /*set zero to disable dump stack*/
161 cfg.max_param_size = 256;
162 cfg.compress_level = 3;
163 cfg.shared_buffer_size = 4*1024*1024;
164 cfg.max_dump_bytes = 4*1024*1024*1024LL;
165
166 cfg.log_to_stdout = false;
167 cfg.log_to_file = true;
168 cfg.log_file_max_size = 20*1024*1024;
169 cfg.log_flush_threshold = 0;
170 cfg.log_debug = false;
171
172 user_file = getenv("ST2_CONFIG_FILE");
173 if (nullptr == user_file) {
174 snprintf(cfg_file, sizeof(cfg_file), "%s/.config/emd.json", getenv("HOME"));
175 }
176 else {
177 snprintf(cfg_file, sizeof(cfg_file), "%s", user_file);
178 }
179 struct json_object* root = json_object_from_file(cfg_file);
180 if (!root) {
181 fprintf(stderr, "failed to open or parse :%s, error:%s\n",
182 cfg_file, strerror(errno));
183 goto end;
184 }
185
186 for (it = json_object_iter_begin(root),
187 it_end = json_object_iter_end(root);
188 !json_object_iter_equal(&it, &it_end);
189 json_object_iter_next(&it)) {
190
191 struct json_object *v = nullptr;
192 const char* n = json_object_iter_peek_name(&it);
193 if (!n)
194 break;
195
196 v = json_object_iter_peek_value(&it);
197 if (!v)
198 break;
199
200 if (strcmp(n, "dump_dir") == 0) {
201 cfg.dump_dir = alloc_json_string(v);
202 }
203 else if (strcmp(n, "modules") == 0) {
204 read_map_config(v, cfg);
205 }
206 else if (strcmp(n, "variables") == 0) {
207 read_global_var_config(v, cfg);
208 }
209 else if (strcmp(n, "compress_level") == 0) {
210 get_json_int(v, &cfg.compress_level, true);
211 }
212 else if (strcmp(n, "dump_pthread_list") == 0) {
213 get_json_boolean(v, &cfg.dump_pthread_list);
214 }
215 else if (strcmp(n, "dump_robust_mutex_list") == 0) {
216 get_json_boolean(v, &cfg.dump_robust_mutex_list);
217 }
218 else if (strcmp(n, "log_debug") == 0) {
219 get_json_boolean(v, &cfg.log_debug);
220 }
221 else if (strcmp(n, "log_to_stdout") == 0) {
222 get_json_boolean(v, &cfg.log_to_stdout);
223 }
224 else if (strcmp(n, "log_to_file") == 0) {
225 get_json_boolean(v, &cfg.log_to_file);
226 }
227 else if (strcmp(n, "shared_buffer_size") == 0) {
228 int number = 0;
229 get_json_int(v, &number, true);
230 if (number > 0) {
231 cfg.shared_buffer_size = number*1024;
232 }
233 }
234 else if (strcmp(n, "max_dump_bytes") == 0) {
235 int number = 0;
236 get_json_int(v, &number, true);
237 if (number > 0) {
238 cfg.max_dump_bytes = number*1024LL;
239 }
240 }
241 else if (strcmp(n, "log_file_max_size") == 0) {
242 int number = 0;
243 get_json_int(v, &number, true);
244 if (number > 0) {
245 cfg.log_file_max_size = number*1024;
246 }
247 }
248 else if (strcmp(n, "log_flush_threshold") == 0) {
249 int number = 0;
250 get_json_int(v, &number, true);
251 if (number >= 0) {
252 cfg.log_flush_threshold = number*1024;
253 }
254 }
255 else if (strcmp(n, "mode") == 0) {
256 get_json_int(v, (int*)&cfg.mode, true);
257 }
258 else {
259 printf("WARNING: ignoring unknown config item: %s\n", n);
260 }
261 }
262
263 json_object_put(root);
264
265end:
266 if (cfg.dump_dir.empty()) {
267 cfg.dump_dir = getenv("HOME");
268 cfg.dump_dir += "/.local/share/emd/";
269 }
270 else if (cfg.dump_dir[0] == '~') {
271 cfg.dump_dir.replace(0, 1, getenv("HOME"));
272 }
273
274 return 0;
275}
276
277
278