1 /* radare - LGPL - Copyright 2009-2021 - pancake */
2 
3 #include <r_core.h>
4 #include <r_types_base.h>
5 
6 #define NODECB(w,x,y) r_config_set_cb (cfg,w,x,y)
7 #define NODEICB(w,x,y) r_config_set_i_cb (cfg,w,x,y)
8 #define SETDESC(x,y) r_config_node_desc (x,y)
9 #define SETOPTIONS(x, ...) set_options (x, __VA_ARGS__)
10 #define SETI(x,y,z) SETDESC (r_config_set_i (cfg,x,y), z)
11 #define SETICB(w,x,y,z) SETDESC (NODEICB (w,x,y), z)
12 #define SETPREF(x,y,z) SETDESC (r_config_set (cfg,x,y), z)
13 #define SETCB(w,x,y,z) SETDESC (NODECB (w,x,y), z)
14 #define SETBPREF(x,y,z) SETDESC (NODECB (x,y,boolify_var_cb), z)
15 
boolify_var_cb(void * user,void * data)16 static bool boolify_var_cb(void *user, void *data) {
17 	RConfigNode *node = (RConfigNode *) data;
18 	if (node->i_value || r_str_is_false (node->value)) {
19 		free (node->value);
20 		node->value = strdup (r_str_bool (node->i_value));
21 	}
22 	return true;
23 }
24 
set_options(RConfigNode * node,...)25 static void set_options(RConfigNode *node, ...) {
26 	va_list argp;
27 	char *option = NULL;
28 	va_start (argp, node);
29 	option = va_arg (argp, char *);
30 	while (option) {
31 		r_config_node_add_option (node, option);
32 		option = va_arg (argp, char *);
33 	}
34 	va_end (argp);
35 }
36 
isGdbPlugin(RCore * core)37 static bool isGdbPlugin(RCore *core) {
38 	if (core->io && core->io->desc && core->io->desc->plugin) {
39 		if (core->io->desc->plugin->name && !strcmp (core->io->desc->plugin->name, "gdb")) {
40 			return true;
41 		}
42 	}
43 	return false;
44 }
45 
print_node_options(RConfigNode * node)46 static void print_node_options(RConfigNode *node) {
47 	if (node->options) {
48 		RListIter *iter;
49 		char *option;
50 		r_list_foreach (node->options, iter, option) {
51 			r_cons_printf ("%s\n", option);
52 		}
53 	}
54 }
55 
compareName(const RAnalFunction * a,const RAnalFunction * b)56 static int compareName(const RAnalFunction *a, const RAnalFunction *b) {
57 	return (a && b && a->name && b->name ?  strcmp (a->name, b->name) : 0);
58 }
59 
compareNameLen(const RAnalFunction * a,const RAnalFunction * b)60 static int compareNameLen(const RAnalFunction *a, const RAnalFunction *b) {
61 	size_t la, lb;
62 	if (!a || !b || !a->name || !b->name) {
63 		return 0;
64 	}
65 	la = strlen (a->name);
66 	lb = strlen (a->name);
67 	return (la > lb) - (la < lb);
68 }
69 
compareAddress(const RAnalFunction * a,const RAnalFunction * b)70 static int compareAddress(const RAnalFunction *a, const RAnalFunction *b) {
71 	return (a && b && a->addr && b->addr ? (a->addr > b->addr) - (a->addr < b->addr) : 0);
72 }
73 
compareType(const RAnalFunction * a,const RAnalFunction * b)74 static int compareType(const RAnalFunction *a, const RAnalFunction *b) {
75 	return (a && b && a->diff->type && b->diff->type ?
76 			(a->diff->type > b->diff->type) - (a->diff->type < b->diff->type) : 0);
77 }
78 
compareSize(const RAnalFunction * a,const RAnalFunction * b)79 static int compareSize(const RAnalFunction *a, const RAnalFunction *b) {
80 	ut64 sa, sb;
81 	// return a && b && a->_size < b->_size;
82 	if (!a || !b) {
83 		return 0;
84 	}
85 	sa = r_anal_function_realsize (a);
86 	sb = r_anal_function_realsize (b);
87 	return (sa > sb) - (sa < sb);
88 }
89 
compareDist(const RAnalFunction * a,const RAnalFunction * b)90 static int compareDist(const RAnalFunction *a, const RAnalFunction *b) {
91 	return (a && b && a->diff->dist && b->diff->dist ?
92 			(a->diff->dist > b->diff->dist) - (a->diff->dist < b->diff->dist) : 0);
93 }
94 
cb_diff_sort(void * _core,void * _node)95 static bool cb_diff_sort(void *_core, void *_node) {
96 	RConfigNode *node = _node;
97 	const char *column = node->value;
98 	RCore *core = _core;
99 	if (column && *column != '?') {
100 		if (!strcmp (column, "name")) {
101 			core->anal->columnSort = (RListComparator)compareName;
102 		} else if (!strcmp (column, "namelen")) {
103 			core->anal->columnSort = (RListComparator)compareNameLen;
104 		} else if (!strcmp (column, "addr")) {
105 			core->anal->columnSort = (RListComparator)compareAddress;
106 		} else if (!strcmp (column, "type")) {
107 			core->anal->columnSort = (RListComparator)compareType;
108 		} else if (!strcmp (column, "size")) {
109 			core->anal->columnSort = (RListComparator)compareSize;
110 		} else if (!strcmp (column, "dist")) {
111 			core->anal->columnSort = (RListComparator)compareDist;
112 		} else {
113 			goto fail;
114 		}
115 		return true;
116 	}
117 fail:
118 	eprintf ("e diff.sort = [name, namelen, addr, type, size, dist]\n");
119 	return false;
120 }
121 
has_esil(RCore * core,const char * name)122 static const char *has_esil(RCore *core, const char *name) {
123 	RListIter *iter;
124 	RAnalPlugin *h;
125 	r_return_val_if_fail (core && core->anal && name, NULL);
126 	r_list_foreach (core->anal->plugins, iter, h) {
127 		if (h->name && !strcmp (name, h->name)) {
128 			return h->esil? "Ae": "A_";
129 		}
130 	}
131 	return "__";
132 }
133 
134 // copypasta from binr/rasm2/rasm2.c
rasm2_list(RCore * core,const char * arch,int fmt)135 static void rasm2_list(RCore *core, const char *arch, int fmt) {
136 	int i;
137 	const char *feat2, *feat;
138 	RAsm *a = core->rasm;
139 	char bits[32];
140 	RAsmPlugin *h;
141 	RListIter *iter;
142 	PJ *pj = NULL;
143 	if (fmt == 'j') {
144 		pj = pj_new ();
145 		if (!pj) {
146 			return;
147 		}
148 		pj_o (pj);
149 	}
150 	r_list_foreach (a->plugins, iter, h) {
151 		if (arch && *arch) {
152 			if (h->cpus && !strcmp (arch, h->name)) {
153 				char *c = strdup (h->cpus);
154 				int n = r_str_split (c, ',');
155 				for (i = 0; i < n; i++) {
156 					r_cons_println (r_str_word_get0 (c, i));
157 				}
158 				free (c);
159 				break;
160 			}
161 		} else {
162 			bits[0] = 0;
163 			/* The underscore makes it easier to distinguish the
164 			 * columns */
165 			if (h->bits & 8) {
166 				strcat (bits, "_8");
167 			}
168 			if (h->bits & 16) {
169 				strcat (bits, "_16");
170 			}
171 			if (h->bits & 32) {
172 				strcat (bits, "_32");
173 			}
174 			if (h->bits & 64) {
175 				strcat (bits, "_64");
176 			}
177 			if (!*bits) {
178 				strcat (bits, "_0");
179 			}
180 			feat = "__";
181 			if (h->assemble && h->disassemble) {
182 				feat = "ad";
183 			}
184 			if (h->assemble && !h->disassemble) {
185 				feat = "a_";
186 			}
187 			if (!h->assemble && h->disassemble) {
188 				feat = "_d";
189 			}
190 			feat2 = has_esil (core, h->name);
191 			if (fmt == 'q') {
192 				r_cons_println (h->name);
193 			} else if (fmt == 'j') {
194 				const char *license = "GPL";
195 				pj_k (pj, h->name);
196 				pj_o (pj);
197 				pj_k (pj, "bits");
198 				pj_a (pj);
199 				pj_i (pj, 32);
200 				pj_i (pj, 64);
201 				pj_end (pj);
202 				pj_ks (pj, "license", license);
203 				pj_ks (pj, "description", h->desc);
204 				pj_ks (pj, "features", feat);
205 				pj_end (pj);
206 			} else {
207 				r_cons_printf ("%s%s  %-9s  %-11s %-7s %s\n",
208 						feat, feat2, bits, h->name,
209 						r_str_get_fail (h->license, "unknown"), h->desc);
210 			}
211 		}
212 	}
213 	if (fmt == 'j') {
214 		pj_end (pj);
215 		r_cons_println (pj_string (pj));
216 		pj_free (pj);
217 	}
218 }
219 
__setsegoff(RConfig * cfg,const char * asmarch,int asmbits)220 static inline void __setsegoff(RConfig *cfg, const char *asmarch, int asmbits) {
221 	int autoseg = (!strncmp (asmarch, "x86", 3) && asmbits == 16);
222 	r_config_set (cfg, "asm.segoff", r_str_bool (autoseg));
223 }
224 
cb_debug_hitinfo(void * user,void * data)225 static bool cb_debug_hitinfo(void *user, void *data) {
226 	RCore *core = (RCore*) user;
227 	RConfigNode *node = (RConfigNode*) data;
228 	core->dbg->hitinfo = node->i_value;
229 	return true;
230 }
231 
cb_anal_jmpretpoline(void * user,void * data)232 static bool cb_anal_jmpretpoline(void *user, void *data) {
233 	RCore *core = (RCore*) user;
234 	RConfigNode *node = (RConfigNode*) data;
235 	core->anal->opt.retpoline = node->i_value;
236 	return true;
237 }
cb_anal_jmptailcall(void * user,void * data)238 static bool cb_anal_jmptailcall(void *user, void *data) {
239 	RCore *core = (RCore*) user;
240 	RConfigNode *node = (RConfigNode*) data;
241 	core->anal->opt.tailcall = node->i_value;
242 	return true;
243 }
244 
cb_analarmthumb(void * user,void * data)245 static bool cb_analarmthumb(void *user, void *data) {
246 	RCore *core = (RCore*) user;
247 	RConfigNode *node = (RConfigNode*) data;
248 	core->anal->opt.armthumb = node->i_value;
249 	return true;
250 }
251 
cb_analdepth(void * user,void * data)252 static bool cb_analdepth(void *user, void *data) {
253 	RCore *core = (RCore*) user;
254 	RConfigNode *node = (RConfigNode*) data;
255 	core->anal->opt.depth = node->i_value;
256 	return true;
257 }
258 
cb_analgraphdepth(void * user,void * data)259 static bool cb_analgraphdepth(void *user, void *data) {
260 	RCore *core = (RCore *)user;
261 	RConfigNode *node = (RConfigNode *)data;
262 	core->anal->opt.graph_depth = node->i_value;
263 	return true;
264 }
265 
cb_analafterjmp(void * user,void * data)266 static bool cb_analafterjmp(void *user, void *data) {
267 	RCore *core = (RCore*) user;
268 	RConfigNode *node = (RConfigNode*) data;
269 	core->anal->opt.afterjmp = node->i_value;
270 	return true;
271 }
272 
cb_anal_delay(void * user,void * data)273 static bool cb_anal_delay(void *user, void *data) {
274 	RCore *core = (RCore*) user;
275 	RConfigNode *node = (RConfigNode*) data;
276 	core->anal->opt.delay = node->i_value;
277 	return true;
278 }
279 
cb_anal_endsize(void * user,void * data)280 static bool cb_anal_endsize(void *user, void *data) {
281 	RCore *core = (RCore*) user;
282 	RConfigNode *node = (RConfigNode*) data;
283 	core->anal->opt.endsize = node->i_value;
284 	return true;
285 }
286 
cb_analvars(void * user,void * data)287 static bool cb_analvars(void *user, void *data) {
288         RCore *core = (RCore*) user;
289         RConfigNode *node = (RConfigNode*) data;
290         core->anal->opt.vars = node->i_value;
291         return true;
292 }
293 
cb_analvars_stackname(void * user,void * data)294 static bool cb_analvars_stackname(void *user, void *data) {
295 	RCore *core = (RCore *)user;
296 	RConfigNode *node = (RConfigNode *)data;
297 	core->anal->opt.varname_stack = node->i_value;
298 	return true;
299 }
300 
cb_anal_nonull(void * user,void * data)301 static bool cb_anal_nonull(void *user, void *data) {
302         RCore *core = (RCore*) user;
303         RConfigNode *node = (RConfigNode*) data;
304         core->anal->opt.nonull = node->i_value;
305         return true;
306 }
307 
cb_analstrings(void * user,void * data)308 static bool cb_analstrings(void *user, void *data) {
309 	RCore *core = (RCore*) user;
310 	RConfigNode *node = (RConfigNode*) data;
311 	if (node->i_value) {
312 		r_config_set (core->config, "bin.strings", "false");
313 	}
314 	return true;
315 }
316 
cb_anal_ignbithints(void * user,void * data)317 static bool cb_anal_ignbithints(void *user, void *data) {
318 	RCore *core = (RCore*) user;
319 	RConfigNode *node = (RConfigNode*) data;
320 	core->anal->opt.ignbithints = node->i_value;
321 	return true;
322 }
323 
cb_analsleep(void * user,void * data)324 static bool cb_analsleep(void *user, void *data) {
325 	RCore *core = (RCore*) user;
326 	RConfigNode *node = (RConfigNode*) data;
327 	core->anal->sleep = node->i_value;
328 	return true;
329 }
330 
cb_analmaxrefs(void * user,void * data)331 static bool cb_analmaxrefs(void *user, void *data) {
332 	RCore *core = (RCore*) user;
333 	RConfigNode *node = (RConfigNode*) data;
334 	core->anal->maxreflines = node->i_value;
335 	return true;
336 }
337 
cb_analnorevisit(void * user,void * data)338 static bool cb_analnorevisit(void *user, void *data) {
339 	RCore *core = (RCore*) user;
340 	RConfigNode *node = (RConfigNode*) data;
341 	core->anal->opt.norevisit = node->i_value;
342 	return true;
343 }
344 
cb_analnopskip(void * user,void * data)345 static bool cb_analnopskip(void *user, void *data) {
346 	RCore *core = (RCore*) user;
347 	RConfigNode *node = (RConfigNode*) data;
348 	core->anal->opt.nopskip = node->i_value;
349 	return true;
350 }
351 
cb_analhpskip(void * user,void * data)352 static bool cb_analhpskip(void *user, void *data) {
353 	RCore *core = (RCore*) user;
354 	RConfigNode *node = (RConfigNode*) data;
355 	core->anal->opt.hpskip = node->i_value;
356 	return true;
357 }
358 
update_analarch_options(RCore * core,RConfigNode * node)359 static void update_analarch_options(RCore *core, RConfigNode *node) {
360 	RAnalPlugin *h;
361 	RListIter *it;
362 	if (core && core->anal && node) {
363 		r_config_node_purge_options (node);
364 		r_list_foreach (core->anal->plugins, it, h) {
365 			if (h->name) {
366 				SETOPTIONS (node, h->name, NULL);
367 			}
368 		}
369 	}
370 }
371 
cb_analarch(void * user,void * data)372 static bool cb_analarch(void *user, void *data) {
373 	RCore *core = (RCore*) user;
374 	RConfigNode *node = (RConfigNode*) data;
375 	if (*node->value == '?') {
376 		update_analarch_options (core, node);
377 		print_node_options (node);
378 		return false;
379 	}
380 	if (*node->value) {
381 		if (r_anal_use (core->anal, node->value)) {
382 			return true;
383 		}
384 		char *p = strchr (node->value, '.');
385 		if (p) {
386 			char *arch = strdup (node->value);
387 			arch[p - node->value] = 0;
388 			free (node->value);
389 			node->value = arch;
390 			if (r_anal_use (core->anal, node->value)) {
391 				return true;
392 			}
393 		}
394 		const char *aa = r_config_get (core->config, "asm.arch");
395 		if (!aa || strcmp (aa, node->value)) {
396 			eprintf ("anal.arch: cannot find '%s'\n", node->value);
397 		} else {
398 			r_config_set (core->config, "anal.arch", "null");
399 			return true;
400 		}
401 	}
402 	return false;
403 }
404 
cb_analcpu(void * user,void * data)405 static bool cb_analcpu(void *user, void *data) {
406 	RCore *core = (RCore *) user;
407 	RConfigNode *node = (RConfigNode *) data;
408 	r_anal_set_cpu (core->anal, node->value);
409 	/* set pcalign */
410 	{
411 		int v = r_anal_archinfo (core->anal, R_ANAL_ARCHINFO_ALIGN);
412 		r_config_set_i (core->config, "asm.pcalign", (v != -1)? v: 0);
413 	}
414 	return true;
415 }
416 
cb_analrecont(void * user,void * data)417 static bool cb_analrecont(void *user, void *data) {
418 	RCore *core = (RCore*) user;
419 	RConfigNode *node = (RConfigNode*) data;
420 	core->anal->opt.recont = node->i_value;
421 	return true;
422 }
423 
cb_analijmp(void * user,void * data)424 static bool cb_analijmp(void *user, void *data) {
425 	RCore *core = (RCore*) user;
426 	RConfigNode *node = (RConfigNode*) data;
427 	core->anal->opt.ijmp = node->i_value;
428 	return true;
429 }
430 
cb_asmsubvarmin(void * user,void * data)431 static bool cb_asmsubvarmin(void *user, void *data) {
432 	RCore *core = (RCore *) user;
433 	RConfigNode *node = (RConfigNode *) data;
434 	core->parser->minval = node->i_value;
435 	return true;
436 }
437 
cb_asmsubtail(void * user,void * data)438 static bool cb_asmsubtail(void *user, void *data) {
439 	RCore *core = (RCore *) user;
440 	RConfigNode *node = (RConfigNode *) data;
441 	core->parser->subtail = node->i_value;
442 	return true;
443 }
444 
cb_scrlast(void * user,void * data)445 static bool cb_scrlast(void *user, void *data) {
446 	RConfigNode *node = (RConfigNode *) data;
447 	r_cons_singleton ()->context->lastEnabled = node->i_value;
448 	return true;
449 }
450 
cb_scr_vi(void * user,void * data)451 static bool cb_scr_vi(void *user, void *data) {
452 	RCore *core = (RCore *) user;
453 	RConfigNode *node = (RConfigNode *) data;
454 	core->cons->line->enable_vi_mode = node->i_value;
455 	return true;
456 }
457 
cb_scr_prompt_mode(void * user,void * data)458 static bool cb_scr_prompt_mode(void *user, void *data) {
459 	RCore *core = (RCore *) user;
460 	RConfigNode *node = (RConfigNode *) data;
461 	core->cons->line->prompt_mode = node->i_value;
462 	return true;
463 }
464 
cb_scr_wideoff(void * user,void * data)465 static bool cb_scr_wideoff(void *user, void *data) {
466 	RCore *core = (RCore *) user;
467 	RConfigNode *node = (RConfigNode *) data;
468 	core->print->wide_offsets = node->i_value;
469 	return true;
470 }
471 
cb_scrrainbow(void * user,void * data)472 static bool cb_scrrainbow(void *user, void *data) {
473 	RCore *core = (RCore *) user;
474 	RConfigNode *node = (RConfigNode *) data;
475 	if (node->i_value) {
476 		core->print->flags |= R_PRINT_FLAGS_RAINBOW;
477 		r_core_cmd0 (core, "ecr");
478 	} else {
479 		core->print->flags &= (~R_PRINT_FLAGS_RAINBOW);
480 		r_core_cmd0 (core, "ecoo");
481 	}
482 	r_print_set_flags (core->print, core->print->flags);
483 	return true;
484 }
485 
cb_asmpseudo(void * user,void * data)486 static bool cb_asmpseudo (void *user, void *data) {
487 	RCore *core = (RCore *) user;
488 	RConfigNode *node = (RConfigNode *) data;
489 	core->rasm->pseudo = node->i_value;
490 	return true;
491 }
492 
cb_asmsubsec(void * user,void * data)493 static bool cb_asmsubsec(void *user, void *data) {
494 	RCore *core = (RCore *) user;
495 	RConfigNode *node = (RConfigNode *) data;
496 	if (node->i_value) {
497 		core->print->flags |= R_PRINT_FLAGS_SECSUB;
498 	} else {
499 		core->print->flags &= (~R_PRINT_FLAGS_SECSUB);
500 	}
501 	r_print_set_flags (core->print, core->print->flags);
502 	return true;
503 }
504 
cb_asmassembler(void * user,void * data)505 static bool cb_asmassembler(void *user, void *data) {
506 	RCore *core = (RCore *) user;
507 	RConfigNode *node = (RConfigNode *) data;
508 	r_asm_use_assembler (core->rasm, node->value);
509 	return true;
510 }
511 
update_cmdpdc_options(RCore * core,RConfigNode * node)512 static void update_cmdpdc_options(RCore *core, RConfigNode *node) {
513 	r_return_if_fail (core && core->rasm && node);
514 	RListIter *iter;
515 	r_config_node_purge_options (node);
516 	char *opts = r_core_cmd_str (core, "e cmd.pdc=?");
517 	RList *optl = r_str_split_list (opts, "\n", 0);
518 	char *opt;
519 	r_list_foreach (optl, iter, opt) {
520 		SETOPTIONS (node, opt, NULL);
521 	}
522 	r_list_free (optl);
523 	free (opts);
524 }
525 
update_asmcpu_options(RCore * core,RConfigNode * node)526 static void update_asmcpu_options(RCore *core, RConfigNode *node) {
527 	RAsmPlugin *h;
528 	RListIter *iter;
529 	r_return_if_fail (core && core->rasm);
530 	const char *arch = r_config_get (core->config, "asm.arch");
531 	if (!arch || !*arch) {
532 		return;
533 	}
534 	r_config_node_purge_options (node);
535 	r_list_foreach (core->rasm->plugins, iter, h) {
536 		if (h->cpus && !strcmp (arch, h->name)) {
537 			char *c = strdup (h->cpus);
538 			int i, n = r_str_split (c, ',');
539 			for (i = 0; i < n; i++) {
540 				const char *word = r_str_word_get0 (c, i);
541 				if (word && *word) {
542 					node->options->free = free;
543 					SETOPTIONS (node, word, NULL);
544 				}
545 			}
546 			free (c);
547 		}
548 	}
549 }
550 
cb_asmcpu(void * user,void * data)551 static bool cb_asmcpu(void *user, void *data) {
552 	RCore *core = (RCore *) user;
553 	RConfigNode *node = (RConfigNode *) data;
554 	if (*node->value == '?') {
555 		update_asmcpu_options (core, node);
556 		/* print verbose help instead of plain option listing */
557 		rasm2_list (core, r_config_get (core->config, "asm.arch"), node->value[1]);
558 		return 0;
559 	}
560 	r_asm_set_cpu (core->rasm, node->value);
561 	r_config_set (core->config, "anal.cpu", node->value);
562 	return true;
563 }
564 
update_asmarch_options(RCore * core,RConfigNode * node)565 static void update_asmarch_options(RCore *core, RConfigNode *node) {
566 	RAsmPlugin *h;
567 	RListIter *iter;
568 	if (core && node && core->rasm) {
569 		r_config_node_purge_options (node);
570 		r_list_foreach (core->rasm->plugins, iter, h) {
571 			if (h->name) {
572 				SETOPTIONS (node, h->name, NULL);
573 			}
574 		}
575 	}
576 }
577 
update_asmbits_options(RCore * core,RConfigNode * node)578 static void update_asmbits_options(RCore *core, RConfigNode *node) {
579 	if (core && core->rasm && core->rasm->cur && node) {
580 		int bits = core->rasm->cur->bits;
581 		int i;
582 		r_config_node_purge_options (node);
583 		for (i = 1; i <= bits; i <<= 1) {
584 			if (i & bits) {
585 				char *a = r_str_newf ("%d", i);
586 				SETOPTIONS (node, a, NULL);
587 				free (a);
588 			}
589 		}
590 	}
591 }
592 
cb_asmarch(void * user,void * data)593 static bool cb_asmarch(void *user, void *data) {
594 	char asmparser[32];
595 	RCore *core = (RCore *) user;
596 	RConfigNode *node = (RConfigNode *) data;
597 	const char *asmos = NULL;
598 	int bits = R_SYS_BITS;
599 	if (!*node->value || !core || !core->rasm) {
600 		return false;
601 	}
602 	asmos = r_config_get (core->config, "asm.os");
603 	if (core && core->anal && core->anal->bits) {
604 		bits = core->anal->bits;
605 	}
606 	if (*node->value == '?') {
607 		update_asmarch_options (core, node);
608 		if (strlen (node->value) > 1 && node->value[1] == '?') {
609 			/* print more verbose help instead of plain option values */
610 			rasm2_list (core, NULL, node->value[1]);
611 			return false;
612 		} else {
613 			print_node_options (node);
614 			return false;
615 		}
616 	}
617 	r_egg_setup (core->egg, node->value, bits, 0, R_SYS_OS);
618 
619 	if (!r_asm_use (core->rasm, node->value)) {
620 		eprintf ("asm.arch: cannot find (%s)\n", node->value);
621 		return false;
622 	}
623 	//we should strdup here otherwise will crash if any r_config_set
624 	//free the old value
625 	char *asm_cpu = strdup (r_config_get (core->config, "asm.cpu"));
626 	if (core->rasm->cur) {
627 		const char *newAsmCPU = core->rasm->cur->cpus;
628 		if (newAsmCPU) {
629 			if (*newAsmCPU) {
630 				char *nac = strdup (newAsmCPU);
631 				char *comma = strchr (nac, ',');
632 				if (comma) {
633 					if (!*asm_cpu || (*asm_cpu && !strstr(nac, asm_cpu))) {
634 						*comma = 0;
635 						r_config_set (core->config, "asm.cpu", nac);
636 					}
637 				}
638 				free (nac);
639 			} else {
640 				r_config_set (core->config, "asm.cpu", "");
641 			}
642 		}
643 		bits = core->rasm->cur->bits;
644 		if (8 & bits) {
645 			bits = 8;
646 		} else if (16 & bits) {
647 			bits = 16;
648 		} else if (32 & bits) {
649 			bits = 32;
650 		} else {
651 			bits = 64;
652 		}
653 		update_asmbits_options (core, r_config_node_get (core->config, "asm.bits"));
654 	}
655 	snprintf (asmparser, sizeof (asmparser), "%s.pseudo", node->value);
656 	r_config_set (core->config, "asm.parser", asmparser);
657 	if (core->rasm->cur && core->anal &&
658 	    !(core->rasm->cur->bits & core->anal->bits)) {
659 		r_config_set_i (core->config, "asm.bits", bits);
660 	}
661 
662 	//r_debug_set_arch (core->dbg, r_sys_arch_id (node->value), bits);
663 	r_debug_set_arch (core->dbg, node->value, bits);
664 	if (!r_config_set (core->config, "anal.arch", node->value)) {
665 		char *p, *s = strdup (node->value);
666 		if (s) {
667 			p = strchr (s, '.');
668 			if (p) {
669 				*p = 0;
670 			}
671 			if (!r_config_set (core->config, "anal.arch", s)) {
672 				/* fall back to the anal.null plugin */
673 				r_config_set (core->config, "anal.arch", "null");
674 			}
675 			free (s);
676 		}
677 	}
678 	// set pcalign
679 	if (core->anal) {
680 		const char *asmcpu = r_config_get (core->config, "asm.cpu");
681 		if (!r_syscall_setup (core->anal->syscall, node->value, core->anal->bits, asmcpu, asmos)) {
682 			//eprintf ("asm.arch: Cannot setup syscall '%s/%s' from '%s'\n",
683 			//	node->value, asmos, R2_LIBDIR"/radare2/"R2_VERSION"/syscall");
684 		}
685 	}
686 	//if (!strcmp (node->value, "bf"))
687 	//	r_config_set (core->config, "dbg.backend", "bf");
688 	__setsegoff (core->config, node->value, core->rasm->bits);
689 
690 	// set a default endianness
691 	int bigbin = r_bin_is_big_endian (core->bin);
692 	if (bigbin == -1 /* error: no endianness detected in binary */) {
693 		bigbin = r_config_get_i (core->config, "cfg.bigendian");
694 	}
695 
696 	// try to set endian of RAsm to match binary
697 	r_asm_set_big_endian (core->rasm, bigbin);
698 	// set endian of display to match binary
699 	core->print->big_endian = bigbin;
700 
701 	r_asm_set_cpu (core->rasm, asm_cpu);
702 	free (asm_cpu);
703 	RConfigNode *asmcpu = r_config_node_get (core->config, "asm.cpu");
704 	if (asmcpu) {
705 		update_asmcpu_options (core, asmcpu);
706 	}
707 	{
708 		int v = r_anal_archinfo (core->anal, R_ANAL_ARCHINFO_ALIGN);
709 		if (v != -1) {
710 			r_config_set_i (core->config, "asm.pcalign", v);
711 		} else {
712 			r_config_set_i (core->config, "asm.pcalign", 0);
713 		}
714 	}
715 	/* reload types and cc info */
716 	// changing asm.arch changes anal.arch
717 	// changing anal.arch sets types db
718 	// so ressetting is redundant and may lead to bugs
719 	// 1 case this is usefull is when sdb_types is null
720 	if (!core->anal || !core->anal->sdb_types) {
721 		r_core_anal_type_init (core);
722 	}
723 	r_core_anal_cc_init (core);
724 
725 	return true;
726 }
727 
cb_dbgbpsize(void * user,void * data)728 static bool cb_dbgbpsize(void *user, void *data) {
729 	RCore *core = (RCore *) user;
730 	RConfigNode *node = (RConfigNode *) data;
731 	core->dbg->bpsize = node->i_value;
732 	return true;
733 }
734 
cb_dbgbtdepth(void * user,void * data)735 static bool cb_dbgbtdepth(void *user, void *data) {
736 	RCore *core = (RCore *) user;
737 	RConfigNode *node = (RConfigNode *) data;
738 	core->dbg->btdepth = node->i_value;
739 	return true;
740 }
741 
cb_asmbits(void * user,void * data)742 static bool cb_asmbits(void *user, void *data) {
743 	RCore *core = (RCore *) user;
744 	RConfigNode *node = (RConfigNode *) data;
745 
746 	if (*node->value == '?') {
747 		update_asmbits_options (core, node);
748 		print_node_options (node);
749 		return false;
750 	}
751 
752 	bool ret = false;
753 	if (!core) {
754 		eprintf ("user can't be NULL\n");
755 		return false;
756 	}
757 
758 	int bits = node->i_value;
759 #if 0
760 // TODO: pretty good optimization, but breaks many tests when arch is different i think
761 	if (bits == core->rasm->bits && bits == core->anal->bits && bits == core->dbg->bits) {
762 		// early optimization
763 		return true;
764 	}
765 #endif
766 	if (bits > 0) {
767 		ret = r_asm_set_bits (core->rasm, bits);
768 		if (!ret) {
769 			RAsmPlugin *h = core->rasm->cur;
770 			if (!h) {
771 				eprintf ("e asm.bits: Cannot set value, no plugins defined yet\n");
772 				ret = true;
773 			}
774 			// else { eprintf ("Cannot set bits %d to '%s'\n", bits, h->name); }
775 		}
776 		if (!r_anal_set_bits (core->anal, bits)) {
777 			eprintf ("asm.arch: Cannot setup '%d' bits analysis engine\n", bits);
778 			ret = false;
779 		}
780 		core->print->bits = bits;
781 	}
782 	if (core->dbg && core->anal && core->anal->cur) {
783 		r_debug_set_arch (core->dbg, core->anal->cur->arch, bits);
784 		bool load_from_debug = r_config_get_i (core->config, "cfg.debug");
785 		if (load_from_debug) {
786 			if (core->dbg->h && core->dbg->h->reg_profile) {
787 // XXX. that should depend on the plugin, not the host os
788 #if __WINDOWS__
789 #if !defined(_WIN64)
790 				core->dbg->bits = R_SYS_BITS_32;
791 #else
792 				core->dbg->bits = R_SYS_BITS_64;
793 #endif
794 #endif
795 				char *rp = core->dbg->h->reg_profile (core->dbg);
796 				r_reg_set_profile_string (core->dbg->reg, rp);
797 				r_reg_set_profile_string (core->anal->reg, rp);
798 				free (rp);
799 			}
800 		} else {
801 			(void)r_anal_set_reg_profile (core->anal);
802 		}
803 	}
804 	r_core_anal_cc_init (core);
805 	const char *asmos = r_config_get (core->config, "asm.os");
806 	const char *asmarch = r_config_get (core->config, "asm.arch");
807 	const char *asmcpu = r_config_get (core->config, "asm.cpu");
808 	if (core->anal) {
809 		if (!r_syscall_setup (core->anal->syscall, asmarch, bits, asmcpu, asmos)) {
810 			//eprintf ("asm.arch: Cannot setup syscall '%s/%s' from '%s'\n",
811 			//	node->value, asmos, R2_LIBDIR"/radare2/"R2_VERSION"/syscall");
812 		}
813 		__setsegoff (core->config, asmarch, core->anal->bits);
814 		if (core->dbg) {
815 			r_bp_use (core->dbg->bp, asmarch, core->anal->bits);
816 			r_config_set_i (core->config, "dbg.bpsize", r_bp_size (core->dbg->bp));
817 		}
818 		/* set pcalign */
819 		int v = r_anal_archinfo (core->anal, R_ANAL_ARCHINFO_ALIGN);
820 		r_config_set_i (core->config, "asm.pcalign", (v != -1)? v: 0);
821 	}
822 	return ret;
823 }
824 
update_asmfeatures_options(RCore * core,RConfigNode * node)825 static void update_asmfeatures_options(RCore *core, RConfigNode *node) {
826 	int i, argc;
827 
828 	if (core && core->rasm && core->rasm->cur) {
829 		if (core->rasm->cur->features) {
830 			char *features = strdup (core->rasm->cur->features);
831 			argc = r_str_split (features, ',');
832 			for (i = 0; i < argc; i++) {
833 				const char *feature = r_str_word_get0 (features, i);
834 				if (feature) {
835 					r_config_node_add_option (node, feature);
836 				}
837 			}
838 			free (features);
839 		}
840 	}
841 }
842 
cb_flag_realnames(void * user,void * data)843 static bool cb_flag_realnames(void *user, void *data) {
844 	RCore *core = (RCore *) user;
845 	RConfigNode *node = (RConfigNode *) data;
846 	core->flags->realnames = node->i_value;
847 	return true;
848 }
849 
cb_asmfeatures(void * user,void * data)850 static bool cb_asmfeatures(void *user, void *data) {
851 	RCore *core = (RCore *) user;
852 	RConfigNode *node = (RConfigNode *) data;
853 	if (*node->value == '?') {
854 		update_asmfeatures_options (core, node);
855 		print_node_options (node);
856 		return 0;
857 	}
858 	R_FREE (core->rasm->features);
859 	if (node->value[0]) {
860 		core->rasm->features = strdup (node->value);
861 	}
862 	return 1;
863 }
864 
cb_asmlineswidth(void * user,void * data)865 static bool cb_asmlineswidth(void *user, void *data) {
866 	RCore *core = (RCore *) user;
867 	RConfigNode *node = (RConfigNode *) data;
868 	core->anal->lineswidth = node->i_value;
869 	return true;
870 }
871 
cb_emustr(void * user,void * data)872 static bool cb_emustr(void *user, void *data) {
873 	RCore *core = (RCore *) user;
874 	RConfigNode *node = (RConfigNode *) data;
875 	if (node->i_value) {
876 		r_config_set (core->config, "asm.emu", "true");
877 	}
878 	return true;
879 }
880 
cb_emuskip(void * user,void * data)881 static bool cb_emuskip(void *user, void *data) {
882 	RConfigNode *node = (RConfigNode*) data;
883 	if (*node->value == '?') {
884 		if (strlen (node->value) > 1 && node->value[1] == '?') {
885 			r_cons_printf ("Concatenation of meta types encoded as characters:\n" \
886 				"'d': data\n'c': code\n's': string\n'f': format\n'm': magic\n" \
887 				"'h': hide\n'C': comment\n'r': run\n" \
888 				"(default is 'ds' to skip data and strings)\n");
889 		} else {
890 			print_node_options (node);
891 		}
892 		return false;
893 	}
894 	return true;
895 }
896 
cb_jsonencoding(void * user,void * data)897 static bool cb_jsonencoding(void *user, void *data) {
898 	RConfigNode *node = (RConfigNode*) data;
899 	if (*node->value == '?') {
900 		if (node->value[1] && node->value[1] == '?') {
901 			r_cons_printf ("choose either: \n"\
902 			"none (default)\n" \
903 			"base64 - encode the json string values as base64\n" \
904 			"hex - convert the string to a string of hexpairs\n" \
905 			"array - convert the string to an array of chars\n" \
906 			"strip - strip non-printable characters\n");
907 		} else {
908 			print_node_options (node);
909 		}
910 		return false;
911 	}
912 	return true;
913 }
914 
cb_jsonencoding_numbers(void * user,void * data)915 static bool cb_jsonencoding_numbers(void *user, void *data) {
916 	RConfigNode *node = (RConfigNode*) data;
917 	if (*node->value == '?') {
918 		if (node->value[1] && node->value[1] == '?') {
919 			r_cons_printf ("choose either: \n"\
920 			"none (default)\n" \
921 			"string - encode the json number values as strings\n" \
922 			"hex - encode the number values as hex, then as a string\n");
923 		} else {
924 			print_node_options (node);
925 		}
926 		return false;
927 	}
928 	return true;
929 }
930 
cb_asm_armimm(void * user,void * data)931 static bool cb_asm_armimm(void *user, void *data) {
932 	RCore *core = (RCore *) user;
933 	RConfigNode *node = (RConfigNode *) data;
934 	core->rasm->immdisp = node->i_value ? true : false;
935 	return true;
936 }
937 
cb_asm_invhex(void * user,void * data)938 static bool cb_asm_invhex(void *user, void *data) {
939 	RCore *core = (RCore *) user;
940 	RConfigNode *node = (RConfigNode *) data;
941 	core->rasm->invhex = node->i_value;
942 	return true;
943 }
944 
cb_asm_pcalign(void * user,void * data)945 static bool cb_asm_pcalign(void *user, void *data) {
946 	RCore *core = (RCore *) user;
947 	RConfigNode *node = (RConfigNode *) data;
948 	int align = node->i_value;
949 	if (align < 0) {
950 		align = 0;
951 	}
952 	core->rasm->pcalign = align;
953 	core->anal->pcalign = align;
954 	return true;
955 }
956 
cb_asmos(void * user,void * data)957 static bool cb_asmos(void *user, void *data) {
958 	RCore *core = (RCore*) user;
959 	int asmbits = r_config_get_i (core->config, "asm.bits");
960 	RConfigNode *asmarch, *node = (RConfigNode*) data;
961 
962 	if (*node->value == '?') {
963 		print_node_options (node);
964 		return 0;
965 	}
966 	if (!node->value[0]) {
967 		free (node->value);
968 		node->value = strdup (R_SYS_OS);
969 	}
970 	asmarch = r_config_node_get (core->config, "asm.arch");
971 	if (asmarch) {
972 		const char *asmcpu = r_config_get (core->config, "asm.cpu");
973 		r_syscall_setup (core->anal->syscall, asmarch->value, core->anal->bits, asmcpu, node->value);
974 		__setsegoff (core->config, asmarch->value, asmbits);
975 	}
976 	r_anal_set_os (core->anal, node->value);
977 	r_core_anal_cc_init (core);
978 	return true;
979 }
980 
update_asmparser_options(RCore * core,RConfigNode * node)981 static void update_asmparser_options(RCore *core, RConfigNode *node) {
982 	RListIter *iter;
983 	RParsePlugin *parser;
984 	if (core && node && core->parser && core->parser->parsers) {
985 		r_config_node_purge_options (node);
986 		r_list_foreach (core->parser->parsers, iter, parser) {
987 			SETOPTIONS (node, parser->name, NULL);
988 		}
989 	}
990 }
991 
cb_asmparser(void * user,void * data)992 static bool cb_asmparser(void *user, void *data) {
993 	RCore *core = (RCore*) user;
994 	RConfigNode *node = (RConfigNode*) data;
995 	if (*node->value == '?') {
996 		update_asmparser_options (core, node);
997 		print_node_options (node);
998 		return false;
999 	}
1000 
1001 	return r_parse_use (core->parser, node->value);
1002 }
1003 
1004 typedef struct {
1005 	const char *name;
1006 	const char *aliases;
1007 } namealiases_pair;
1008 
cb_binstrenc(void * user,void * data)1009 static bool cb_binstrenc (void *user, void *data) {
1010 	RCore *core = (RCore*) user;
1011 	RConfigNode *node = (RConfigNode *)data;
1012 	if (*node->value == '?') {
1013 		print_node_options (node);
1014 		r_cons_printf ("  -- if string's 2nd & 4th bytes are 0 then utf16le else "
1015 		               "if 2nd - 4th & 6th bytes are 0 & no char > 0x10ffff then utf32le else "
1016 		               "if utf8 char detected then utf8 else latin1\n");
1017 		return false;
1018 	}
1019 	const namealiases_pair names[] = {
1020 		{ "guess", NULL },
1021 		{ "latin1", "ascii" },
1022 		{ "utf8", "utf-8" },
1023 		{ "utf16le", "utf-16le,utf16-le" },
1024 		{ "utf32le", "utf-32le,utf32-le" },
1025 		{ "utf16be", "utf-16be,utf16-be" },
1026 		{ "utf32be", "utf-32be,utf32-be" } };
1027 	int i;
1028 	char *enc = strdup (node->value);
1029 	if (!enc) {
1030 		return false;
1031 	}
1032 	r_str_case (enc, false);
1033 	for (i = 0; i < R_ARRAY_SIZE (names); i++) {
1034 		const namealiases_pair *pair = &names[i];
1035 		if (!strcmp (pair->name, enc) || r_str_cmp_list (pair->aliases, enc, ',')) {
1036 			free (node->value);
1037 			node->value = strdup (pair->name);
1038 			free (enc);
1039 			if (core->bin) {
1040 				free (core->bin->strenc);
1041 				core->bin->strenc = !strcmp (node->value, "guess") ? NULL : strdup (node->value);
1042 				r_bin_reset_strings (core->bin);
1043 			}
1044 			return true;
1045 		}
1046 	}
1047 	eprintf ("Unknown encoding: %s\n", node->value);
1048 	free (enc);
1049 	return false;
1050 }
1051 
cb_binfilter(void * user,void * data)1052 static bool cb_binfilter(void *user, void *data) {
1053 	RCore *core = (RCore*) user;
1054 	RConfigNode *node = (RConfigNode*) data;
1055 	core->bin->filter = node->i_value;
1056 	return true;
1057 }
1058 
1059 /* BinDemangleCmd */
cb_bdc(void * user,void * data)1060 static bool cb_bdc(void *user, void *data) {
1061 	RCore *core = (RCore*) user;
1062 	RConfigNode *node = (RConfigNode*) data;
1063 	core->bin->demanglercmd = node->i_value;
1064 	return true;
1065 }
1066 
cb_useldr(void * user,void * data)1067 static bool cb_useldr(void *user, void *data) {
1068 	RCore *core = (RCore*) user;
1069 	RConfigNode *node = (RConfigNode*) data;
1070 	core->bin->use_ldr = node->i_value;
1071 	return true;
1072 }
1073 
cb_binat(void * user,void * data)1074 static bool cb_binat(void *user, void *data) {
1075 	RCore *core = (RCore*) user;
1076 	RConfigNode *node = (RConfigNode*) data;
1077 	core->binat = node->i_value;
1078 	return true;
1079 }
1080 
cb_usextr(void * user,void * data)1081 static bool cb_usextr(void *user, void *data) {
1082 	RCore *core = (RCore*) user;
1083 	RConfigNode *node = (RConfigNode*) data;
1084 	core->bin->use_xtr = node->i_value;
1085 	return true;
1086 }
1087 
cb_strpurge(void * user,void * data)1088 static bool cb_strpurge(void *user, void *data) {
1089 	RCore *core = (RCore*) user;
1090 	RConfigNode *node = (RConfigNode*) data;
1091 	if (*node->value == '?') {
1092 		r_cons_printf (
1093 		    "There can be multiple entries separated by commas. No whitespace before/after entries.\n"
1094 		    "Possible entries:\n"
1095 		    "  all          : purge all strings\n"
1096 		    "  true         : use the false_positive() classifier in cbin.c\n"
1097 		    "  addr         : purge string at addr\n"
1098 		    "  addr1-addr2  : purge all strings in the range addr1-addr2 inclusive\n"
1099 		    "  !addr        : prevent purge of string at addr by prev entries\n"
1100 		    "  !addr1-addr2 : prevent purge of strings in range addr1-addr2 inclusive by prev entries\n"
1101 		    "Neither !true nor !false is supported.\n"
1102 		    "\n"
1103 		    "Examples:\n"
1104 		    "  e bin.str.purge=true,0-0xff,!0x1a\n"
1105 		    "    -- purge strings using the false_positive() classifier in cbin.c and also strings \n"
1106 		    "       with addresses in the range 0-0xff, but not the string at 0x1a.\n"
1107 		    "  e bin.str.purge=all,!0x1000-0x1fff\n"
1108 		    "    -- purge all strings except the strings with addresses in the range 0x1000-0x1fff.\n");
1109 		return false;
1110 	}
1111 	free (core->bin->strpurge);
1112 	core->bin->strpurge = !*node->value || !strcmp (node->value, "false")
1113 	                ? NULL : strdup (node->value);
1114 	return true;
1115 }
1116 
cb_maxname(void * user,void * data)1117 static bool cb_maxname (void *user, void *data) {
1118 	RConfigNode *node = (RConfigNode *)data;
1119 	RCore *core = (RCore *) user;
1120 	core->parser->maxflagnamelen = node->i_value;
1121 	return true;
1122 }
1123 
cb_midflags(void * user,void * data)1124 static bool cb_midflags (void *user, void *data) {
1125 	RConfigNode *node = (RConfigNode *)data;
1126 	if (*node->value == '?') {
1127 		print_node_options (node);
1128 		return false;
1129 	}
1130 	return true;
1131 }
1132 
cb_strfilter(void * user,void * data)1133 static bool cb_strfilter(void *user, void *data) {
1134 	RCore *core = (RCore*) user;
1135 	RConfigNode *node = (RConfigNode*) data;
1136 	if (*node->value == '?') {
1137 		if (strlen (node->value) > 1 && node->value[1] == '?') {
1138 			r_cons_printf ("Valid values for bin.str.filter:\n"
1139 				"a  only alphanumeric printable\n"
1140 				"8  only strings with utf8 chars\n"
1141 				"p  file/directory paths\n"
1142 				"e  email-like addresses\n"
1143 				"u  urls\n"
1144 				"i  IPv4 address-like strings\n"
1145 				"U  only uppercase strings\n"
1146 				"f  format-strings\n");
1147 		} else {
1148 			print_node_options (node);
1149 		}
1150 		return false;
1151 	} else {
1152 		core->bin->strfilter = node->value[0];
1153 	}
1154 	return true;
1155 }
1156 
cb_binforce(void * user,void * data)1157 static bool cb_binforce(void *user, void *data) {
1158 	RCore *core = (RCore*) user;
1159 	RConfigNode *node = (RConfigNode*) data;
1160 	r_bin_force_plugin (core->bin, node->value);
1161 	return true;
1162 }
1163 
cb_asmsyntax(void * user,void * data)1164 static bool cb_asmsyntax(void *user, void *data) {
1165 	RCore *core = (RCore*) user;
1166 	RConfigNode *node = (RConfigNode*) data;
1167 	if (*node->value == '?') {
1168 		print_node_options (node);
1169 		return false;
1170 	} else {
1171 		int syntax = r_asm_syntax_from_string (node->value);
1172 		if (syntax == -1) {
1173 			return false;
1174 		}
1175 		r_asm_set_syntax (core->rasm, syntax);
1176 	}
1177 	return true;
1178 }
1179 
cb_dirzigns(void * user,void * data)1180 static bool cb_dirzigns(void *user, void *data) {
1181 	RCore *core = (RCore*) user;
1182 	RConfigNode *node = (RConfigNode*) data;
1183 	free (core->anal->zign_path);
1184 	core->anal->zign_path = strdup (node->value);
1185 	return true;
1186 }
1187 
cb_bigendian(void * user,void * data)1188 static bool cb_bigendian(void *user, void *data) {
1189 	RCore *core = (RCore *) user;
1190 	RConfigNode *node = (RConfigNode *) data;
1191 	// Try to set endian based on preference, restrict by RAsmPlugin
1192 	bool isbig = r_asm_set_big_endian (core->rasm, node->i_value);
1193 	// Set anal endianness the same as asm
1194 	r_anal_set_big_endian (core->anal, isbig);
1195 	// the big endian should also be assigned to dbg->bp->endian
1196 	if (core->dbg && core->dbg->bp) {
1197 		core->dbg->bp->endian = isbig;
1198 	}
1199 	// Set printing endian to user's choice
1200 	core->print->big_endian = node->i_value;
1201 	return true;
1202 }
1203 
list_available_plugins(const char * path)1204 static void list_available_plugins(const char *path) {
1205 	RListIter *iter;
1206 	const char *fn;
1207 	RList *files = r_sys_dir (path);
1208 	r_list_sort (files, (RListComparator)strcmp);
1209 	r_list_foreach (files, iter, fn) {
1210 		if (*fn && *fn != '.' && r_str_endswith (fn, ".sdb")) {
1211 			char *f = strdup (fn);
1212 			f[strlen (f) - 4] = 0;
1213 			r_cons_println (f);
1214 			free (f);
1215 		}
1216 	}
1217 	r_list_free (files);
1218 }
1219 
cb_cfgcharset(void * user,void * data)1220 static bool cb_cfgcharset(void *user, void *data) {
1221 	RCore *core = (RCore*) user;
1222 	RConfigNode *node = (RConfigNode*) data;
1223 	const char *cf = r_str_trim_head_ro (node->value);
1224 	if (!*cf) {
1225 		return true;
1226 	}
1227 
1228 	const char *cs = R2_PREFIX R_SYS_DIR R2_SDB R_SYS_DIR "charsets" R_SYS_DIR;
1229 	bool rc = false;
1230 	if (*cf == '?') {
1231 		list_available_plugins (cs);
1232 	} else {
1233 		char *syscs = r_str_newf ("%s%s.sdb", cs, cf);
1234 		if (r_file_exists (syscs)) {
1235 			rc = r_charset_open (core->print->charset, syscs);
1236 		}
1237 		if (!rc) {
1238 			eprintf ("Warning: Cannot load charset file '%s' '%s'.\n", syscs, cf);
1239 		}
1240 		free (syscs);
1241 	}
1242 	return rc;
1243 }
1244 
cb_cfgdatefmt(void * user,void * data)1245 static bool cb_cfgdatefmt(void *user, void *data) {
1246 	RCore *core = (RCore*) user;
1247 	RConfigNode *node = (RConfigNode*) data;
1248 	snprintf (core->print->datefmt, 32, "%s", node->value);
1249 	return true;
1250 }
1251 
cb_timezone(void * user,void * data)1252 static bool cb_timezone(void *user, void *data) {
1253 	RCore *core = (RCore*) user;
1254 	RConfigNode *node = (RConfigNode*) data;
1255 	core->print->datezone = node->i_value;
1256 	return true;
1257 }
1258 
cb_cfgcorelog(void * user,void * data)1259 static bool cb_cfgcorelog(void *user, void *data) {
1260 	RCore *core = (RCore *) user;
1261 	RConfigNode *node = (RConfigNode *) data;
1262 	core->cfglog = node->i_value;
1263 	return true;
1264 }
1265 
cb_cfgdebug(void * user,void * data)1266 static bool cb_cfgdebug(void *user, void *data) {
1267 	RCore *core = (RCore*) user;
1268 	RConfigNode *node = (RConfigNode*) data;
1269 	if (!core) {
1270 		return false;
1271 	}
1272 	if (core->io) {
1273 		core->io->va = !node->i_value;
1274 	}
1275 	if (core->dbg && node->i_value) {
1276 		const char *dbgbackend = r_config_get (core->config, "dbg.backend");
1277 		r_debug_use (core->dbg, dbgbackend);
1278 		if (!strcmp (r_config_get (core->config, "cmd.prompt"), "")) {
1279 			r_config_set (core->config, "cmd.prompt", ".dr*");
1280 		}
1281 		if (!strcmp (dbgbackend, "bf")) {
1282 			r_config_set (core->config, "asm.arch", "bf");
1283 		}
1284 		if (core->io->desc) {
1285 			r_debug_select (core->dbg, r_io_fd_get_pid (core->io, core->io->desc->fd),
1286 					r_io_fd_get_tid (core->io, core->io->desc->fd));
1287 		}
1288 	} else {
1289 		r_debug_use (core->dbg, NULL);
1290 	}
1291 	return true;
1292 }
1293 
cb_dirhome(void * user,void * data)1294 static bool cb_dirhome(void *user, void *data) {
1295 	RConfigNode *node = (RConfigNode*) data;
1296 	if (node->value) {
1297 		r_sys_setenv (R_SYS_HOME, node->value);
1298 	}
1299 	return true;
1300 }
1301 
cb_dir_projects(void * user,void * data)1302 static bool cb_dir_projects(void *user, void *data) {
1303 	RConfigNode *node = (RConfigNode *)data;
1304 	char *value = R_STR_ISNOTEMPTY (node->value)? node->value: NULL;
1305 	if (value) {
1306 		char *newva = r_file_abspath (value);
1307 		free (node->value);
1308 		node->value = newva;
1309 	}
1310 	return true;
1311 }
1312 
cb_dirtmp(void * user,void * data)1313 static bool cb_dirtmp(void *user, void *data) {
1314 	RConfigNode *node = (RConfigNode *)data;
1315 	char *value = R_STR_ISNOTEMPTY (node->value)? node->value: NULL;
1316 	if (value) {
1317 		char *newva = r_file_abspath (value);
1318 		free (node->value);
1319 		node->value = newva;
1320 	}
1321 	return true;
1322 }
1323 
cb_dirsrc(void * user,void * data)1324 static bool cb_dirsrc(void *user, void *data) {
1325 	RConfigNode *node = (RConfigNode*) data;
1326 	RCore *core = (RCore *)user;
1327 	free (core->bin->srcdir);
1328 	core->bin->srcdir = strdup (node->value);
1329 	return true;
1330 }
1331 
cb_cfgsanbox(void * user,void * data)1332 static bool cb_cfgsanbox(void *user, void *data) {
1333 	RConfigNode *node = (RConfigNode*) data;
1334 	int ret = r_sandbox_enable (node->i_value);
1335 	if (node->i_value != ret) {
1336 		eprintf ("Cannot disable sandbox\n");
1337 	}
1338 	return (!node->i_value && ret)? 0: 1;
1339 }
1340 
cb_str_escbslash(void * user,void * data)1341 static bool cb_str_escbslash(void *user, void *data) {
1342 	RCore *core = (RCore*) user;
1343 	RConfigNode *node = (RConfigNode*) data;
1344 	core->print->esc_bslash = node->i_value;
1345 	return true;
1346 }
1347 
cb_completion_maxtab(void * user,void * data)1348 static bool cb_completion_maxtab (void *user, void *data) {
1349         RCore *core = (RCore*) user;
1350         RConfigNode *node = (RConfigNode*) data;
1351         core->cons->line->completion.args_limit = node->i_value;
1352         return true;
1353 }
1354 
cb_cfg_fortunes(void * user,void * data)1355 static bool cb_cfg_fortunes(void *user, void *data) {
1356 	RCore *core = (RCore *)user;
1357 	RConfigNode *node = (RConfigNode *)data;
1358 	// TODO CN_BOOL option does not receive the right hand side of assignment as an argument
1359 	if (*node->value == '?') {
1360 		r_core_fortune_list (core);
1361 		return false;
1362 	}
1363 	return true;
1364 }
1365 
cb_cfg_fortunes_type(void * user,void * data)1366 static bool cb_cfg_fortunes_type(void *user, void *data) {
1367 	RConfigNode *node = (RConfigNode *)data;
1368 	if (*node->value == '?') {
1369 		r_core_fortune_list_types ();
1370 		return false;
1371 	}
1372 	return true;
1373 }
1374 
check_decompiler(const char * name)1375 static void check_decompiler(const char* name) {
1376 	char *path = r_file_path (name);
1377 	if (path && path[0] == '/') {
1378 		r_cons_printf ("!*%s\n", name);
1379 	}
1380 	free (path);
1381 }
1382 
cb_cmdpdc(void * user,void * data)1383 static bool cb_cmdpdc(void *user, void *data) {
1384 	RCore *core = (RCore *) user;
1385 	RConfigNode *node = (RConfigNode *)data;
1386 	if (*node->value == '?') {
1387 		r_cons_printf ("pdc\n");
1388 		// spaguetti
1389 		check_decompiler ("r2retdec");
1390 		RListIter *iter;
1391 		RCorePlugin *cp;
1392 		r_list_foreach (core->rcmd->plist, iter, cp) {
1393 			if (!strcmp (cp->name, "r2ghidra")) {
1394 				r_cons_printf ("pdg\n");
1395 			}
1396 		}
1397 		check_decompiler ("r2ghidra");
1398 		check_decompiler ("r2jadx");
1399 		check_decompiler ("r2snow");
1400 		RConfigNode *r2dec = r_config_node_get (core->config, "r2dec.asm");
1401 		if (r2dec) {
1402 			r_cons_printf ("pdd\n");
1403 		}
1404 		return false;
1405 	}
1406 	return true;
1407 }
1408 
cb_cmdlog(void * user,void * data)1409 static bool cb_cmdlog(void *user, void *data) {
1410 	RCore *core = (RCore *) user;
1411 	RConfigNode *node = (RConfigNode *) data;
1412 	R_FREE (core->cmdlog);
1413 	core->cmdlog = strdup (node->value);
1414 	return true;
1415 }
1416 
cb_cmdtimes(void * user,void * data)1417 static bool cb_cmdtimes(void *user, void *data) {
1418 	RCore *core = (RCore *) user;
1419 	RConfigNode *node = (RConfigNode *) data;
1420 	core->cmdtimes = node->value;
1421 	return true;
1422 }
1423 
cb_cmdrepeat(void * user,void * data)1424 static bool cb_cmdrepeat(void *user, void *data) {
1425 	RCore *core = (RCore *) user;
1426 	RConfigNode *node = (RConfigNode *) data;
1427 	core->cmdrepeat = node->i_value;
1428 	return true;
1429 }
1430 
cb_screrrmode(void * user,void * data)1431 static bool cb_screrrmode(void *user, void *data) {
1432 	RConfigNode *node = (RConfigNode *) data;
1433 	if (*node->value == '?') {
1434 		r_cons_printf ("Valid values: null, echo, buffer, quiet, flush\n");
1435 		return false;
1436 	}
1437 	r_cons_errmodes (node->value);
1438 	return true;
1439 }
1440 
cb_scrnull(void * user,void * data)1441 static bool cb_scrnull(void *user, void *data) {
1442 	RCore *core = (RCore *) user;
1443 	RConfigNode *node = (RConfigNode *) data;
1444 	core->cons->null = node->i_value;
1445 	return true;
1446 }
1447 
cb_color(void * user,void * data)1448 static bool cb_color(void *user, void *data) {
1449 	RCore *core = (RCore *) user;
1450 	RConfigNode *node = (RConfigNode *) data;
1451 	if (node->i_value) {
1452 		core->print->flags |= R_PRINT_FLAGS_COLOR;
1453 	} else {
1454 		core->print->flags &= (~R_PRINT_FLAGS_COLOR);
1455 	}
1456 	if (!strcmp (node->value, "true")) {
1457 		node->i_value = 1;
1458 	} else if (!strcmp (node->value, "false")) {
1459 		node->i_value = 0;
1460 	}
1461 	r_cons_singleton ()->context->color_mode = (node->i_value > COLOR_MODE_16M)
1462 		? COLOR_MODE_16M: node->i_value;
1463 	r_cons_pal_update_event ();
1464 	r_print_set_flags (core->print, core->print->flags);
1465 	return true;
1466 }
1467 
cb_color_getter(void * user,RConfigNode * node)1468 static bool cb_color_getter(void *user, RConfigNode *node) {
1469 	(void)user;
1470 	node->i_value = r_cons_singleton ()->context->color_mode;
1471 	char buf[128];
1472 	r_config_node_value_format_i (buf, sizeof (buf), r_cons_singleton ()->context->color_mode, node);
1473 	if (!node->value || strcmp (node->value, buf) != 0) {
1474 		free (node->value);
1475 		node->value = strdup (buf);
1476 	}
1477 	return true;
1478 }
1479 
cb_decoff(void * user,void * data)1480 static bool cb_decoff(void *user, void *data) {
1481 	RCore *core = (RCore *) user;
1482 	RConfigNode *node = (RConfigNode *) data;
1483 	if (node->i_value) {
1484 		core->print->flags |= R_PRINT_FLAGS_ADDRDEC;
1485 	} else {
1486 		core->print->flags &= (~R_PRINT_FLAGS_ADDRDEC);
1487 	}
1488 	r_print_set_flags (core->print, core->print->flags);
1489 	return true;
1490 }
1491 
cb_dbgbep(void * user,void * data)1492 static bool cb_dbgbep(void *user, void *data) {
1493 	RConfigNode *node = (RConfigNode*) data;
1494 	if (*node->value == '?') {
1495 		print_node_options (node);
1496 		return false;
1497 	}
1498 	return true;
1499 }
1500 
cb_dbg_btalgo(void * user,void * data)1501 static bool cb_dbg_btalgo(void *user, void *data) {
1502 	RCore *core = (RCore*) user;
1503 	RConfigNode *node = (RConfigNode*) data;
1504 	if (*node->value == '?') {
1505 		print_node_options (node);
1506 		return false;
1507 	}
1508 	free (core->dbg->btalgo);
1509 	core->dbg->btalgo = strdup (node->value);
1510 	return true;
1511 }
1512 
cb_dbg_libs(void * user,void * data)1513 static bool cb_dbg_libs(void *user, void *data) {
1514 	RCore *core = (RCore*) user;
1515 	RConfigNode *node = (RConfigNode*) data;
1516 	free (core->dbg->glob_libs);
1517 	core->dbg->glob_libs = strdup (node->value);
1518 	return true;
1519 }
1520 
cb_dbg_unlibs(void * user,void * data)1521 static bool cb_dbg_unlibs(void *user, void *data) {
1522 	RCore *core = (RCore*) user;
1523 	RConfigNode *node = (RConfigNode*) data;
1524 	free (core->dbg->glob_unlibs);
1525 	core->dbg->glob_unlibs = strdup (node->value);
1526 	return true;
1527 }
1528 
cb_dbg_bpinmaps(void * user,void * data)1529 static bool cb_dbg_bpinmaps(void *user, void *data) {
1530 	RCore *core = (RCore *) user;
1531 	RConfigNode *node = (RConfigNode *) data;
1532 	core->dbg->bp->bpinmaps = node->i_value;
1533 	return true;
1534 }
1535 
cb_dbg_forks(void * user,void * data)1536 static bool cb_dbg_forks(void *user, void *data) {
1537 	RCore *core = (RCore*) user;
1538 	RConfigNode *node = (RConfigNode*) data;
1539 	core->dbg->trace_forks = node->i_value;
1540 	if (r_config_get_i (core->config, "cfg.debug")) {
1541 		r_debug_attach (core->dbg, core->dbg->pid);
1542 	}
1543 	return true;
1544 }
1545 
cb_dbg_gdb_page_size(void * user,void * data)1546 static bool cb_dbg_gdb_page_size(void *user, void *data) {
1547 	RCore *core = (RCore*) user;
1548 	RConfigNode *node = (RConfigNode*) data;
1549 	if (node->i_value < 64) { // 64 is hardcoded min packet size
1550 		return false;
1551 	}
1552 	if (isGdbPlugin (core)) {
1553 		char cmd[64];
1554 		snprintf (cmd, sizeof (cmd), "page_size %"PFMT64d, node->i_value);
1555 		free (r_io_system (core->io, cmd));
1556 	}
1557 	return true;
1558 }
1559 
cb_dbg_gdb_retries(void * user,void * data)1560 static bool cb_dbg_gdb_retries(void *user, void *data) {
1561 	RCore *core = (RCore*) user;
1562 	RConfigNode *node = (RConfigNode*) data;
1563 	if (node->i_value <= 0) {
1564 		return false;
1565 	}
1566 	if (isGdbPlugin (core)) {
1567 		char cmd[64];
1568 		snprintf (cmd, sizeof (cmd), "retries %"PFMT64d, node->i_value);
1569 		free (r_io_system (core->io, cmd));
1570 	}
1571 	return true;
1572 }
1573 
cb_dbg_execs(void * user,void * data)1574 static bool cb_dbg_execs(void *user, void *data) {
1575 	RConfigNode *node = (RConfigNode*) data;
1576 #if __linux__
1577 	RCore *core = (RCore*) user;
1578 	core->dbg->trace_execs = node->i_value;
1579 	if (r_config_get_i (core->config, "cfg.debug")) {
1580 		r_debug_attach (core->dbg, core->dbg->pid);
1581 	}
1582 #else
1583 	if (node->i_value) {
1584 		eprintf ("Warning: dbg.execs is not supported in this platform.\n");
1585 	}
1586 #endif
1587 	return true;
1588 }
1589 
cb_dbg_clone(void * user,void * data)1590 static bool cb_dbg_clone(void *user, void *data) {
1591 	RCore *core = (RCore*) user;
1592 	RConfigNode *node = (RConfigNode*) data;
1593 	core->dbg->trace_clone = node->i_value;
1594 	if (r_config_get_i (core->config, "cfg.debug")) {
1595 		r_debug_attach (core->dbg, core->dbg->pid);
1596 	}
1597 	return true;
1598 }
1599 
cb_dbg_follow_child(void * user,void * data)1600 static bool cb_dbg_follow_child(void *user, void *data) {
1601 	RCore *core = (RCore*) user;
1602 	RConfigNode *node = (RConfigNode*) data;
1603 	core->dbg->follow_child = node->i_value;
1604 	return true;
1605 }
1606 
cb_dbg_trace_continue(void * user,void * data)1607 static bool cb_dbg_trace_continue(void *user, void *data) {
1608 	RCore *core = (RCore*)user;
1609 	RConfigNode *node = (RConfigNode*)data;
1610 	core->dbg->trace_continue = node->i_value;
1611 	return true;
1612 }
1613 
cb_dbg_aftersc(void * user,void * data)1614 static bool cb_dbg_aftersc(void *user, void *data) {
1615 	RCore *core = (RCore*) user;
1616 	RConfigNode *node = (RConfigNode*) data;
1617 	core->dbg->trace_aftersyscall = node->i_value;
1618 	if (r_config_get_i (core->config, "cfg.debug")) {
1619 		r_debug_attach (core->dbg, core->dbg->pid);
1620 	}
1621 	return true;
1622 }
1623 
cb_runprofile(void * user,void * data)1624 static bool cb_runprofile(void *user, void *data) {
1625 	RCore *r = (RCore*) user;
1626 	RConfigNode *node = (RConfigNode*) data;
1627 	free ((void*)r->io->runprofile);
1628 	if (!node || !*(node->value)) {
1629 		r->io->runprofile = NULL;
1630 	} else {
1631 		r->io->runprofile = strdup (node->value);
1632 	}
1633 	return true;
1634 }
1635 
cb_dbg_args(void * user,void * data)1636 static bool cb_dbg_args(void *user, void *data) {
1637 	RCore *core = (RCore *)user;
1638 	RConfigNode *node = (RConfigNode*) data;
1639 	if (!node || !*(node->value)) {
1640 		core->io->args = NULL;
1641 	} else {
1642 		core->io->args = strdup (node->value);
1643 	}
1644 	return true;
1645 }
1646 
cb_dbgstatus(void * user,void * data)1647 static bool cb_dbgstatus(void *user, void *data) {
1648 	RCore *r = (RCore*) user;
1649 	RConfigNode *node = (RConfigNode*) data;
1650 	if (r_config_get_i (r->config, "cfg.debug")) {
1651 		if (node->i_value) {
1652 			r_config_set (r->config, "cmd.prompt",
1653 				".dr*; drd; sr PC;pi 1;s-");
1654 		} else {
1655 			r_config_set (r->config, "cmd.prompt", ".dr*");
1656 		}
1657 	}
1658 	return true;
1659 }
1660 
cb_dbgbackend(void * user,void * data)1661 static bool cb_dbgbackend(void *user, void *data) {
1662 	RCore *core = (RCore*) user;
1663 	RConfigNode *node = (RConfigNode*) data;
1664 	if (*node->value == '?') {
1665 		r_debug_plugin_list (core->dbg, 'q');
1666 		return false;
1667 	}
1668 	if (!strcmp (node->value, "bf")) {
1669 		// hack
1670 		r_config_set (core->config, "asm.arch", "bf");
1671 	}
1672 	r_debug_use (core->dbg, node->value);
1673 	return true;
1674 }
1675 
cb_gotolimit(void * user,void * data)1676 static bool cb_gotolimit(void *user, void *data) {
1677 	RCore *core = (RCore *) user;
1678 	RConfigNode *node = (RConfigNode*) data;
1679 	if (r_sandbox_enable (0)) {
1680 		eprintf ("Cannot change gotolimit\n");
1681 		return false;
1682 	}
1683 	if (core->anal->esil) {
1684 		core->anal->esil_goto_limit = node->i_value;
1685 	}
1686 	return true;
1687 }
1688 
cb_esilverbose(void * user,void * data)1689 static bool cb_esilverbose (void *user, void *data) {
1690 	RCore *core = (RCore *) user;
1691 	RConfigNode *node = (RConfigNode*) data;
1692 	if (core->anal->esil) {
1693 		core->anal->esil->verbose = node->i_value;
1694 	}
1695 	return true;
1696 }
1697 
cb_esilstackdepth(void * user,void * data)1698 static bool cb_esilstackdepth (void *user, void *data) {
1699 	RConfigNode *node = (RConfigNode*) data;
1700 	if (node->i_value < 3) {
1701 		eprintf ("esil.stack.depth must be greater than 2\n");
1702 		node->i_value = 32;
1703 	}
1704 	return true;
1705 }
1706 
cb_fixrows(void * user,void * data)1707 static bool cb_fixrows(void *user, void *data) {
1708 	RConfigNode *node = (RConfigNode *) data;
1709 	r_cons_singleton ()->fix_rows = (int)node->i_value;
1710 	return true;
1711 }
1712 
cb_fixcolumns(void * user,void * data)1713 static bool cb_fixcolumns(void *user, void *data) {
1714 	RConfigNode *node = (RConfigNode *) data;
1715 	r_cons_singleton ()->fix_columns = atoi (node->value);
1716 	return true;
1717 }
1718 
cb_rows(void * user,void * data)1719 static bool cb_rows(void *user, void *data) {
1720 	RConfigNode *node = (RConfigNode *) data;
1721 	r_cons_singleton ()->force_rows = node->i_value;
1722 	return true;
1723 }
1724 
cb_cmd_hexcursor(void * user,void * data)1725 static bool cb_cmd_hexcursor(void *user, void *data) {
1726 	RCore *core = (RCore *) user;
1727 	RConfigNode *node = (RConfigNode *) data;
1728 	core->print->cfmt = node->value;
1729 	return true;
1730 }
1731 
cb_hexcompact(void * user,void * data)1732 static bool cb_hexcompact(void *user, void *data) {
1733 	RCore *core = (RCore *) user;
1734 	RConfigNode *node = (RConfigNode *) data;
1735 	if (node->i_value) {
1736 		core->print->flags |= R_PRINT_FLAGS_COMPACT;
1737 	} else {
1738 		core->print->flags &= (~R_PRINT_FLAGS_COMPACT);
1739 	}
1740 	return true;
1741 }
1742 
cb_hex_pairs(void * user,void * data)1743 static bool cb_hex_pairs(void *user, void *data) {
1744 	RCore *core = (RCore *) user;
1745 	RConfigNode *node = (RConfigNode *) data;
1746 	core->print->pairs = node->i_value;
1747 	return true;
1748 }
1749 
cb_hex_section(void * user,void * data)1750 static bool cb_hex_section(void *user, void *data) {
1751 	RCore *core = (RCore *) user;
1752 	RConfigNode *node = (RConfigNode *) data;
1753 	if (node->i_value) {
1754 		core->print->flags |= R_PRINT_FLAGS_SECTION;
1755 	} else {
1756 		core->print->flags &= ~R_PRINT_FLAGS_SECTION;
1757 	}
1758 	return true;
1759 }
1760 
cb_hex_align(void * user,void * data)1761 static bool cb_hex_align(void *user, void *data) {
1762 	RCore *core = (RCore *) user;
1763 	RConfigNode *node = (RConfigNode *) data;
1764 	if (node->i_value) {
1765 		core->print->flags |= R_PRINT_FLAGS_ALIGN;
1766 	} else {
1767 		core->print->flags &= ~R_PRINT_FLAGS_ALIGN;
1768 	}
1769 	return true;
1770 }
1771 
cb_io_unalloc(void * user,void * data)1772 static bool cb_io_unalloc(void *user, void *data) {
1773 	RCore *core = (RCore *) user;
1774 	RConfigNode *node = (RConfigNode *) data;
1775 	if (node->i_value) {
1776 		core->print->flags |= R_PRINT_FLAGS_UNALLOC;
1777 	} else {
1778 		core->print->flags &= ~R_PRINT_FLAGS_UNALLOC;
1779 	}
1780 	return true;
1781 }
1782 
cb_io_unalloc_ch(void * user,void * data)1783 static bool cb_io_unalloc_ch(void *user, void *data) {
1784 	RCore *core = (RCore *) user;
1785 	RConfigNode *node = (RConfigNode *) data;
1786 	core->print->io_unalloc_ch = *node->value ? node->value[0] : ' ';
1787 	return true;
1788 }
1789 
cb_hex_header(void * user,void * data)1790 static bool cb_hex_header(void *user, void *data) {
1791 	RCore *core = (RCore *) user;
1792 	RConfigNode *node = (RConfigNode *) data;
1793 	if (node->i_value) {
1794 		core->print->flags |= R_PRINT_FLAGS_HEADER;
1795 	} else {
1796 		core->print->flags &= ~R_PRINT_FLAGS_HEADER;
1797 	}
1798 	return true;
1799 }
1800 
cb_hex_bytes(void * user,void * data)1801 static bool cb_hex_bytes(void *user, void *data) {
1802 	RCore *core = (RCore *) user;
1803 	RConfigNode *node = (RConfigNode *) data;
1804 	if (node->i_value) {
1805 		core->print->flags &= ~R_PRINT_FLAGS_NONHEX;
1806 	} else {
1807 		core->print->flags |= R_PRINT_FLAGS_NONHEX;
1808 	}
1809 	return true;
1810 }
1811 
cb_hex_ascii(void * user,void * data)1812 static bool cb_hex_ascii(void *user, void *data) {
1813 	RCore *core = (RCore *) user;
1814 	RConfigNode *node = (RConfigNode *) data;
1815 	if (node->i_value) {
1816 		core->print->flags &= ~R_PRINT_FLAGS_NONASCII;
1817 	} else {
1818 		core->print->flags |= R_PRINT_FLAGS_NONASCII;
1819 	}
1820 	return true;
1821 }
1822 
cb_hex_style(void * user,void * data)1823 static bool cb_hex_style(void *user, void *data) {
1824 	RCore *core = (RCore *) user;
1825 	RConfigNode *node = (RConfigNode *) data;
1826 	if (node->i_value) {
1827 		core->print->flags |= R_PRINT_FLAGS_STYLE;
1828 	} else {
1829 		core->print->flags &= ~R_PRINT_FLAGS_STYLE;
1830 	}
1831 	return true;
1832 }
1833 
cb_hex_hdroff(void * user,void * data)1834 static bool cb_hex_hdroff(void *user, void *data) {
1835 	RCore *core = (RCore *) user;
1836 	RConfigNode *node = (RConfigNode *) data;
1837 	if (node->i_value) {
1838 		core->print->flags |= R_PRINT_FLAGS_HDROFF;
1839 	} else {
1840 		core->print->flags &= ~R_PRINT_FLAGS_HDROFF;
1841 	}
1842 	return true;
1843 }
1844 
cb_log_events(void * user,void * data)1845 static bool cb_log_events (void *user, void *data) {
1846 	RCore *core = (RCore *) user;
1847 	RConfigNode *node = (RConfigNode *) data;
1848 	core->log_events = node->i_value;
1849 	return true;
1850 }
1851 
cb_hexcomments(void * user,void * data)1852 static bool cb_hexcomments(void *user, void *data) {
1853 	RCore *core = (RCore *) user;
1854 	RConfigNode *node = (RConfigNode *) data;
1855 	if (node->i_value) {
1856 		core->print->flags |= R_PRINT_FLAGS_COMMENT;
1857 	} else {
1858 		core->print->flags &= ~R_PRINT_FLAGS_COMMENT;
1859 	}
1860 	return true;
1861 }
1862 
cb_iopcache(void * user,void * data)1863 static bool cb_iopcache(void *user, void *data) {
1864 	RCore *core = (RCore *) user;
1865 	RConfigNode *node = (RConfigNode *) data;
1866 	if ((bool)node->i_value) {
1867 		if (core) {
1868 			r_config_set_b (core->config, "io.pcache.read", true);
1869 			r_config_set_b (core->config, "io.pcache.write", true);
1870 		}
1871 	} else {
1872 		if (core && core->io) {
1873 			r_io_desc_cache_fini_all (core->io);
1874 			r_config_set_b (core->config, "io.pcache.read", false);
1875 			r_config_set_b (core->config, "io.pcache.write", false);
1876 		}
1877 	}
1878 	return true;
1879 }
1880 
cb_iopcacheread(void * user,void * data)1881 static bool cb_iopcacheread(void *user, void *data) {
1882 	RCore *core = (RCore *) user;
1883 	RConfigNode *node = (RConfigNode *) data;
1884 	if ((bool)node->i_value) {
1885 		if (core && core->io) {
1886 			core->io->p_cache |= 1;
1887 		}
1888 	} else {
1889 		if (core && core->io && core->io->p_cache) {
1890 			core->io->p_cache &= 2;
1891 			if (!(core->io->p_cache & 2)) {
1892 				r_io_desc_cache_fini_all (core->io);
1893 				r_config_set_b (core->config, "io.pcache", false);
1894 			}
1895 		}
1896 	}
1897 	return true;
1898 }
1899 
cb_iopcachewrite(void * user,void * data)1900 static bool cb_iopcachewrite(void *user, void *data) {
1901 	RCore *core = (RCore *) user;
1902 	RConfigNode *node = (RConfigNode *) data;
1903 	if ((bool)node->i_value) {
1904 		if (core && core->io) {
1905 			core->io->p_cache |= 2;
1906 		}
1907 	} else {
1908 		if (core && core->io && core->io->p_cache) {
1909 			core->io->p_cache &= 1;
1910 			if (!(core->io->p_cache & 1)) {
1911 				r_io_desc_cache_fini_all (core->io);
1912 				r_config_set_b (core->config, "io.pcache", false);
1913 			}
1914 		}
1915 	}
1916 	return true;
1917 }
1918 
r_core_esil_cmd(RAnalEsil * esil,const char * cmd,ut64 a1,ut64 a2)1919 R_API bool r_core_esil_cmd(RAnalEsil *esil, const char *cmd, ut64 a1, ut64 a2) {
1920 	if (cmd && *cmd) {
1921 		RCore *core = esil->anal->user;
1922 		r_core_cmdf (core, "%s %"PFMT64d" %" PFMT64d, cmd, a1, a2);
1923 		return core->num->value;
1924 	}
1925 	return false;
1926 }
1927 
cb_cmd_esil_ioer(void * user,void * data)1928 static bool cb_cmd_esil_ioer(void *user, void *data) {
1929 	RCore *core = (RCore *) user;
1930 	RConfigNode *node = (RConfigNode *) data;
1931 	if (core && core->anal && core->anal->esil) {
1932 		core->anal->esil->cmd = r_core_esil_cmd;
1933 		free (core->anal->esil->cmd_ioer);
1934 		core->anal->esil->cmd_ioer = strdup (node->value);
1935 	}
1936 	return true;
1937 }
1938 
cb_cmd_esil_todo(void * user,void * data)1939 static bool cb_cmd_esil_todo(void *user, void *data) {
1940 	RCore *core = (RCore *) user;
1941 	RConfigNode *node = (RConfigNode *) data;
1942 	if (core && core->anal && core->anal->esil) {
1943 		core->anal->esil->cmd = r_core_esil_cmd;
1944 		free (core->anal->esil->cmd_todo);
1945 		core->anal->esil->cmd_todo = strdup (node->value);
1946 	}
1947 	return true;
1948 }
1949 
cb_cmd_esil_intr(void * user,void * data)1950 static bool cb_cmd_esil_intr(void *user, void *data) {
1951 	RCore *core = (RCore *) user;
1952 	RConfigNode *node = (RConfigNode *) data;
1953 	if (core && core->anal && core->anal->esil) {
1954 		core->anal->esil->cmd = r_core_esil_cmd;
1955 		free (core->anal->esil->cmd_intr);
1956 		core->anal->esil->cmd_intr = strdup (node->value);
1957 	}
1958 	return true;
1959 }
1960 
cb_mdevrange(void * user,void * data)1961 static bool cb_mdevrange(void *user, void *data) {
1962 	RCore *core = (RCore *) user;
1963 	RConfigNode *node = (RConfigNode *) data;
1964 	if (core && core->anal && core->anal->esil) {
1965 		core->anal->esil->cmd = r_core_esil_cmd;
1966 		free (core->anal->esil->mdev_range);
1967 		core->anal->esil->mdev_range = strdup (node->value);
1968 	}
1969 	return true;
1970 }
1971 
cb_cmd_esil_step(void * user,void * data)1972 static bool cb_cmd_esil_step(void *user, void *data) {
1973 	RCore *core = (RCore *) user;
1974 	RConfigNode *node = (RConfigNode *) data;
1975 	if (core && core->anal && core->anal->esil) {
1976 		core->anal->esil->cmd = r_core_esil_cmd;
1977 		free (core->anal->esil->cmd_step);
1978 		core->anal->esil->cmd_step = strdup (node->value);
1979 	}
1980 	return true;
1981 }
1982 
cb_cmd_esil_step_out(void * user,void * data)1983 static bool cb_cmd_esil_step_out(void *user, void *data) {
1984 	RCore *core = (RCore *) user;
1985 	RConfigNode *node = (RConfigNode *) data;
1986 	if (core && core->anal && core->anal->esil) {
1987 		core->anal->esil->cmd = r_core_esil_cmd;
1988 		free (core->anal->esil->cmd_step_out);
1989 		core->anal->esil->cmd_step_out = strdup (node->value);
1990 	}
1991 	return true;
1992 }
1993 
cb_cmd_esil_mdev(void * user,void * data)1994 static bool cb_cmd_esil_mdev(void *user, void *data) {
1995 	RCore *core = (RCore *) user;
1996 	RConfigNode *node = (RConfigNode *) data;
1997 	if (core && core->anal && core->anal->esil) {
1998 		core->anal->esil->cmd = r_core_esil_cmd;
1999 		free (core->anal->esil->cmd_mdev);
2000 		core->anal->esil->cmd_mdev = strdup (node->value);
2001 	}
2002 	return true;
2003 }
2004 
cb_cmd_esil_trap(void * user,void * data)2005 static bool cb_cmd_esil_trap(void *user, void *data) {
2006 	RCore *core = (RCore *) user;
2007 	RConfigNode *node = (RConfigNode *) data;
2008 	if (core && core->anal && core->anal->esil) {
2009 		core->anal->esil->cmd = r_core_esil_cmd;
2010 		core->anal->esil->cmd_trap = strdup (node->value);
2011 	}
2012 	return true;
2013 }
2014 
cb_fsview(void * user,void * data)2015 static bool cb_fsview(void *user, void *data) {
2016 	int type = R_FS_VIEW_NORMAL;
2017 	RCore *core = (RCore *) user;
2018 	RConfigNode *node = (RConfigNode *) data;
2019 	if (*node->value == '?') {
2020 		print_node_options (node);
2021 		return false;
2022 	}
2023 	if (!strcmp (node->value, "all")) {
2024 		type = R_FS_VIEW_ALL;
2025 	}
2026 	if (!strstr (node->value, "del")) {
2027 		type |= R_FS_VIEW_DELETED;
2028 	}
2029 	if (!strstr (node->value, "spe")) {
2030 		type |= R_FS_VIEW_SPECIAL;
2031 	}
2032 	r_fs_view (core->fs, type);
2033 	return true;
2034 }
2035 
cb_cmddepth(void * user,void * data)2036 static bool cb_cmddepth(void *user, void *data) {
2037 	RCore *core = (RCore *)user;
2038 	int c = R_MAX (((RConfigNode*)data)->i_value, 0);
2039 	core->max_cmd_depth = c;
2040 	core->cons->context->cmd_depth = c;
2041 	return true;
2042 }
2043 
cb_hexcols(void * user,void * data)2044 static bool cb_hexcols(void *user, void *data) {
2045 	RCore *core = (RCore *)user;
2046 	int c = R_MIN (1024, R_MAX (((RConfigNode*)data)->i_value, 0));
2047 	core->print->cols = c; // & ~1;
2048 	core->dbg->regcols = c/4;
2049 	return true;
2050 }
2051 
cb_hexstride(void * user,void * data)2052 static bool cb_hexstride(void *user, void *data) {
2053 	RConfigNode *node = (RConfigNode*) data;
2054 	((RCore *)user)->print->stride = node->i_value;
2055 	return true;
2056 }
2057 
cb_search_kwidx(void * user,void * data)2058 static bool cb_search_kwidx(void *user, void *data) {
2059 	RCore *core = (RCore *) user;
2060 	RConfigNode *node = (RConfigNode *) data;
2061 	core->search->n_kws = node->i_value;
2062 	return true;
2063 }
2064 
cb_io_cache_mode(void * user,void * data)2065 static bool cb_io_cache_mode(void *user, void *data) {
2066 	RCore *core = (RCore *)user;
2067 	RConfigNode *node = (RConfigNode *)data;
2068 	if (node->i_value) {
2069 		core->io->cachemode = true;
2070 	} else {
2071 		core->io->cachemode = false;
2072 	}
2073 	return true;
2074 }
2075 
cb_io_cache_read(void * user,void * data)2076 static bool cb_io_cache_read(void *user, void *data) {
2077 	RCore *core = (RCore *)user;
2078 	RConfigNode *node = (RConfigNode *)data;
2079 	if (node->i_value) {
2080 		core->io->cached |= R_PERM_R;
2081 	} else {
2082 		core->io->cached &= ~R_PERM_R;
2083 	}
2084 	return true;
2085 }
2086 
cb_io_cache_write(void * user,void * data)2087 static bool cb_io_cache_write(void *user, void *data) {
2088 	RCore *core = (RCore *)user;
2089 	RConfigNode *node = (RConfigNode *)data;
2090 	if (node->i_value) {
2091 		core->io->cached |= R_PERM_W;
2092 	} else {
2093 		core->io->cached &= ~R_PERM_W;
2094 	}
2095 	return true;
2096 }
2097 
cb_io_cache(void * user,void * data)2098 static bool cb_io_cache(void *user, void *data) {
2099 	(void)cb_io_cache_read (user, data);
2100 	(void)cb_io_cache_write (user, data);
2101 	return true;
2102 }
2103 
cb_ioaslr(void * user,void * data)2104 static bool cb_ioaslr(void *user, void *data) {
2105 	RCore *core = (RCore *) user;
2106 	RConfigNode *node = (RConfigNode *) data;
2107 	if (node->i_value != core->io->aslr) {
2108 		core->io->aslr = node->i_value;
2109 	}
2110 	return true;
2111 }
2112 
cb_io_pava(void * user,void * data)2113 static bool cb_io_pava(void *user, void *data) {
2114 	RCore *core = (RCore *) user;
2115 	RConfigNode *node = (RConfigNode *) data;
2116 	core->print->pava = node->i_value;
2117 	if (node->i_value && core->io->va) {
2118 		eprintf ("WARNING: You may probably want to disable io.va too\n");
2119 	}
2120 	return true;
2121 }
2122 
cb_iova(void * user,void * data)2123 static bool cb_iova(void *user, void *data) {
2124 	RCore *core = (RCore *) user;
2125 	RConfigNode *node = (RConfigNode *) data;
2126 	if (node->i_value != core->io->va) {
2127 		core->io->va = node->i_value;
2128 		/* ugly fix for r2 -d ... "r2 is going to die soon ..." */
2129 		if (core->io->desc) {
2130 			r_core_block_read (core);
2131 		}
2132 #if 0
2133 		/* reload symbol information */
2134 		if (r_list_length (r_bin_get_sections (core->bin)) > 0) {
2135 			r_core_cmd0 (core, ".ia*");
2136 		}
2137 #endif
2138 	}
2139 	return true;
2140 }
2141 
cb_ioff(void * user,void * data)2142 static bool cb_ioff(void *user, void *data) {
2143 	RCore *core = (RCore *) user;
2144 	RConfigNode *node = (RConfigNode *) data;
2145 	core->io->ff = node->i_value;
2146 	return true;
2147 }
2148 
cb_io_oxff(void * user,void * data)2149 static bool cb_io_oxff(void *user, void *data) {
2150 	RCore *core = (RCore *) user;
2151 	RConfigNode *node = (RConfigNode *) data;
2152 	core->io->Oxff = node->i_value;
2153 	return true;
2154 }
2155 
cb_ioautofd(void * user,void * data)2156 static bool cb_ioautofd(void *user, void *data) {
2157 	RCore *core = (RCore *) user;
2158 	RConfigNode *node = (RConfigNode *) data;
2159 	core->io->autofd = node->i_value;
2160 	return true;
2161 }
2162 
cb_scr_color_grep(void * user,void * data)2163 static bool cb_scr_color_grep(void *user, void *data) {
2164 	RCore *core = (RCore *) user;
2165 	RConfigNode *node = (RConfigNode *) data;
2166 
2167 	/* Let cons know we have a new pager. */
2168 	core->cons->grep_color = node->i_value;
2169 	return true;
2170 }
2171 
cb_scr_color_grep_highlight(void * user,void * data)2172 static bool cb_scr_color_grep_highlight(void *user, void *data) {
2173 	RCore *core = (RCore *) user;
2174 	RConfigNode *node = (RConfigNode *) data;
2175 	core->cons->grep_highlight = node->i_value;
2176 	return true;
2177 }
2178 
cb_pager(void * user,void * data)2179 static bool cb_pager(void *user, void *data) {
2180 	RCore *core = (RCore *) user;
2181 	RConfigNode *node = (RConfigNode *) data;
2182 	if (*node->value == '?') {
2183 		eprintf ("Usage: scr.pager must be '..' for internal less, or the path to a program in $PATH");
2184 		return false;
2185 	}
2186 	/* Let cons know we have a new pager. */
2187 	free (core->cons->pager);
2188 	core->cons->pager = strdup (node->value);
2189 	return true;
2190 }
2191 
cb_breaklines(void * user,void * data)2192 static bool cb_breaklines(void *user, void *data) {
2193 	RConfigNode *node = (RConfigNode *) data;
2194 	r_cons_singleton ()->break_lines = node->i_value;
2195 	return true;
2196 }
2197 
cb_scr_gadgets(void * user,void * data)2198 static bool cb_scr_gadgets(void *user, void *data) {
2199 	RCore *core = (RCore*) user;
2200 	RConfigNode *node = (RConfigNode *) data;
2201 	core->scr_gadgets = node->i_value;
2202 	return true;
2203 }
2204 
cb_fps(void * user,void * data)2205 static bool cb_fps(void *user, void *data) {
2206 	RConfigNode *node = (RConfigNode *) data;
2207 	r_cons_singleton ()->fps = node->i_value;
2208 	return true;
2209 }
2210 
cb_scrbreakword(void * user,void * data)2211 static bool cb_scrbreakword(void* user, void* data) {
2212 	RConfigNode *node = (RConfigNode*) data;
2213 	if (*node->value) {
2214 		r_cons_breakword (node->value);
2215 	} else {
2216 		r_cons_breakword (NULL);
2217 	}
2218 	return true;
2219 }
2220 
cb_scrcolumns(void * user,void * data)2221 static bool cb_scrcolumns(void* user, void* data) {
2222 	RConfigNode *node = (RConfigNode*) data;
2223 	RCore *core = (RCore*) user;
2224 	int n = atoi (node->value);
2225 	core->cons->force_columns = n;
2226 	core->dbg->regcols = n / 20;
2227 	return true;
2228 }
2229 
cb_scrfgets(void * user,void * data)2230 static bool cb_scrfgets(void* user, void* data) {
2231 	RCore *core = (RCore *) user;
2232 	RConfigNode *node = (RConfigNode*) data;
2233 	core->cons->user_fgets = node->i_value
2234 		? NULL : (void *)r_core_fgets;
2235 	return true;
2236 }
2237 
cb_scrhtml(void * user,void * data)2238 static bool cb_scrhtml(void *user, void *data) {
2239 	RConfigNode *node = (RConfigNode *) data;
2240 	r_cons_singleton ()->is_html = node->i_value;
2241 	// TODO: control error and restore old value (return false?) show errormsg?
2242 	return true;
2243 }
2244 
cb_newshell(void * user,void * data)2245 static bool cb_newshell(void *user, void *data) {
2246 	RConfigNode *node = (RConfigNode *)data;
2247 	RCore *core = (RCore *)user;
2248 	core->use_tree_sitter_r2cmd = node->i_value;
2249 	return true;
2250 }
2251 
cb_scrhighlight(void * user,void * data)2252 static bool cb_scrhighlight(void *user, void *data) {
2253 	RConfigNode *node = (RConfigNode *) data;
2254 	r_cons_highlight (node->value);
2255 	return true;
2256 }
2257 
2258 #if __WINDOWS__
scr_vtmode(void * user,void * data)2259 static bool scr_vtmode(void *user, void *data) {
2260 	RConfigNode *node = (RConfigNode *) data;
2261 	if (r_str_is_true (node->value)) {
2262 		node->i_value = 1;
2263 	}
2264 	node->i_value = node->i_value > 2 ? 2 : node->i_value;
2265 	r_line_singleton ()->vtmode = r_cons_singleton ()->vtmode = node->i_value;
2266 
2267 	DWORD mode;
2268 	HANDLE input = GetStdHandle (STD_INPUT_HANDLE);
2269 	GetConsoleMode (input, &mode);
2270 	if (node->i_value == 2) {
2271 		SetConsoleMode (input, mode & ENABLE_VIRTUAL_TERMINAL_INPUT);
2272 		r_cons_singleton ()->term_raw = ENABLE_VIRTUAL_TERMINAL_INPUT;
2273 	} else {
2274 		SetConsoleMode (input, mode & ~ENABLE_VIRTUAL_TERMINAL_INPUT);
2275 		r_cons_singleton ()->term_raw = 0;
2276 	}
2277 	HANDLE streams[] = { GetStdHandle (STD_OUTPUT_HANDLE), GetStdHandle (STD_ERROR_HANDLE) };
2278 	int i;
2279 	if (node->i_value > 0) {
2280 		for (i = 0; i < R_ARRAY_SIZE (streams); i++) {
2281 			GetConsoleMode (streams[i], &mode);
2282 			SetConsoleMode (streams[i],
2283 				mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
2284 		}
2285 	} else {
2286 		for (i = 0; i < R_ARRAY_SIZE (streams); i++) {
2287 			GetConsoleMode (streams[i], &mode);
2288 			SetConsoleMode (streams[i],
2289 				mode & ~ENABLE_VIRTUAL_TERMINAL_PROCESSING & ~ENABLE_WRAP_AT_EOL_OUTPUT);
2290 		}
2291 	}
2292 	return true;
2293 }
2294 #endif
2295 
cb_screcho(void * user,void * data)2296 static bool cb_screcho(void *user, void *data) {
2297 	RConfigNode *node = (RConfigNode *) data;
2298 	r_cons_singleton ()->echo = node->i_value;
2299 	return true;
2300 }
2301 
cb_scrlinesleep(void * user,void * data)2302 static bool cb_scrlinesleep(void *user, void *data) {
2303 	RConfigNode *node = (RConfigNode *) data;
2304 	r_cons_singleton ()->linesleep = node->i_value;
2305 	return true;
2306 }
2307 
cb_scrpagesize(void * user,void * data)2308 static bool cb_scrpagesize(void *user, void *data) {
2309 	RConfigNode *node = (RConfigNode *) data;
2310 	r_cons_singleton ()->pagesize= node->i_value;
2311 	return true;
2312 }
2313 
cb_scrflush(void * user,void * data)2314 static bool cb_scrflush(void *user, void *data) {
2315 	RConfigNode *node = (RConfigNode *) data;
2316 	r_cons_singleton ()->flush = node->i_value;
2317 	return true;
2318 }
2319 
cb_scrstrconv(void * user,void * data)2320 static bool cb_scrstrconv(void *user, void *data) {
2321 	RCore *core = (RCore*) user;
2322 	RConfigNode *node = (RConfigNode*) data;
2323 	if (*node->value == '?') {
2324 		if (strlen (node->value) > 1 && node->value[1] == '?') {
2325 			r_cons_printf ("Valid values for scr.strconv:\n"
2326 				"  asciiesc  convert to ascii with non-ascii chars escaped\n"
2327 				"  asciidot  convert to ascii with non-ascii chars turned into a dot (except control chars stated below)\n"
2328 				"\n"
2329 				"Ascii chars are in the range 0x20-0x7e. Always escaped control chars are alert (\\a),\n"
2330 				"backspace (\\b), formfeed (\\f), newline (\\n), carriage return (\\r), horizontal tab (\\t)\n"
2331 				"and vertical tab (\\v). Also, double quotes (\\\") are always escaped, but backslashes (\\\\)\n"
2332 				"are only escaped if str.escbslash = true.\n");
2333 		} else {
2334 			print_node_options (node);
2335 		}
2336 		return false;
2337 	} else {
2338 		free ((char *)core->print->strconv_mode);
2339 		core->print->strconv_mode = strdup (node->value);
2340 	}
2341 	return true;
2342 }
2343 
cb_graphformat(void * user,void * data)2344 static bool cb_graphformat(void *user, void *data) {
2345 	RConfigNode *node = (RConfigNode *) data;
2346 	if (*node->value == '?') {
2347 		r_cons_printf ("png\njpg\npdf\nps\nsvg\njson\n");
2348 		return false;
2349 	}
2350 	return true;
2351 }
2352 
cb_exectrap(void * user,void * data)2353 static bool cb_exectrap(void *user, void *data) {
2354 	RConfigNode *node = (RConfigNode *) data;
2355 	RCore *core = (RCore*) user;
2356 	if (core->anal && core->anal->esil) {
2357 		core->anal->esil->exectrap = node->i_value;
2358 	}
2359 	return true;
2360 }
2361 
cb_iotrap(void * user,void * data)2362 static bool cb_iotrap(void *user, void *data) {
2363 	RConfigNode *node = (RConfigNode *) data;
2364 	RCore *core = (RCore*) user;
2365 	if (core->anal && core->anal->esil) {
2366 		core->anal->esil->iotrap = node->i_value;
2367 	}
2368 	return true;
2369 }
2370 
cb_scr_bgfill(void * user,void * data)2371 static bool cb_scr_bgfill(void *user, void *data) {
2372 	RCore *core = (RCore*) user;
2373 	RConfigNode *node = (RConfigNode *) data;
2374 	if (node->i_value) {
2375 		core->print->flags |= R_PRINT_FLAGS_BGFILL;
2376 	} else {
2377 		core->print->flags &= (~R_PRINT_FLAGS_BGFILL);
2378 	}
2379 	r_print_set_flags (core->print, core->print->flags);
2380 	return true;
2381 }
2382 
cb_scrint(void * user,void * data)2383 static bool cb_scrint(void *user, void *data) {
2384 	RConfigNode *node = (RConfigNode *) data;
2385 	if (node->i_value && r_sandbox_enable (0)) {
2386 		return false;
2387 	}
2388 	r_cons_singleton ()->context->is_interactive = node->i_value;
2389 	return true;
2390 }
2391 
cb_scrnkey(void * user,void * data)2392 static bool cb_scrnkey(void *user, void *data) {
2393 	RConfigNode *node = (RConfigNode*) data;
2394 	if (!strcmp (node->value, "help") || *node->value == '?') {
2395 		print_node_options (node);
2396 		return false;
2397 	}
2398 	return true;
2399 }
2400 
cb_scr_histblock(void * user,void * data)2401 static bool cb_scr_histblock(void *user, void *data) {
2402 	RCore *core = (RCore *) user;
2403 	RConfigNode *node = (RConfigNode *) data;
2404 	core->print->histblock = node->i_value;
2405 	return true;
2406 }
2407 
cb_scrprompt(void * user,void * data)2408 static bool cb_scrprompt(void *user, void *data) {
2409 	RCore *core = (RCore *)user;
2410 	RConfigNode *node = (RConfigNode *) data;
2411 	core->print->scr_prompt = node->i_value;
2412 	r_line_singleton ()->echo = node->i_value;
2413 	return true;
2414 }
2415 
cb_scrrows(void * user,void * data)2416 static bool cb_scrrows(void* user, void* data) {
2417 	RConfigNode *node = (RConfigNode*) data;
2418 	int n = atoi (node->value);
2419 	((RCore *)user)->cons->force_rows = n;
2420 	return true;
2421 }
2422 
cb_contiguous(void * user,void * data)2423 static bool cb_contiguous(void *user, void *data) {
2424 	RCore *core = (RCore *)user;
2425 	RConfigNode *node = (RConfigNode *) data;
2426 	core->search->contiguous = node->i_value;
2427 	return true;
2428 }
2429 
cb_searchalign(void * user,void * data)2430 static bool cb_searchalign(void *user, void *data) {
2431 	RCore *core = (RCore *)user;
2432 	RConfigNode *node = (RConfigNode *) data;
2433 	core->search->align = node->i_value;
2434 	core->print->addrmod = node->i_value;
2435 	return true;
2436 }
2437 
cb_segoff(void * user,void * data)2438 static bool cb_segoff(void *user, void *data) {
2439 	RCore *core = (RCore *) user;
2440 	RConfigNode *node = (RConfigNode *) data;
2441 	if (node->i_value) {
2442 		core->print->flags |= R_PRINT_FLAGS_SEGOFF;
2443 	} else {
2444 		core->print->flags &= (((ut32)-1) & (~R_PRINT_FLAGS_SEGOFF));
2445 	}
2446 	return true;
2447 }
2448 
cb_seggrn(void * user,void * data)2449 static bool cb_seggrn(void *user, void *data) {
2450 	RCore *core = (RCore *) user;
2451 	RConfigNode *node = (RConfigNode *) data;
2452 	core->rasm->seggrn = node->i_value;
2453 	core->anal->seggrn = node->i_value;
2454 	core->print->seggrn = node->i_value;
2455 	return true;
2456 }
2457 
cb_stopthreads(void * user,void * data)2458 static bool cb_stopthreads(void *user, void *data) {
2459 	RCore *core = (RCore *) user;
2460 	RConfigNode *node = (RConfigNode *) data;
2461 	core->dbg->stop_all_threads = node->i_value;
2462 	return true;
2463 }
2464 
cb_scr_prompt_popup(void * user,void * data)2465 static bool cb_scr_prompt_popup(void *user, void *data) {
2466 	RCore *core = (RCore *) user;
2467 	RConfigNode *node = (RConfigNode *) data;
2468 	core->cons->show_autocomplete_widget = node->i_value;
2469 	return true;
2470 }
2471 
cb_swstep(void * user,void * data)2472 static bool cb_swstep(void *user, void *data) {
2473 	RCore *core = (RCore *) user;
2474 	RConfigNode *node = (RConfigNode *) data;
2475 	core->dbg->swstep = node->i_value;
2476 	return true;
2477 }
2478 
cb_consbreak(void * user,void * data)2479 static bool cb_consbreak(void *user, void *data) {
2480 	RCore *core = (RCore *) user;
2481 	RConfigNode *node = (RConfigNode *) data;
2482 	core->dbg->consbreak = node->i_value;
2483 	return true;
2484 }
2485 
cb_teefile(void * user,void * data)2486 static bool cb_teefile(void *user, void *data) {
2487 	RConfigNode *node = (RConfigNode *) data;
2488 	r_cons_singleton ()->teefile = node->value;
2489 	return true;
2490 }
2491 
cb_trace(void * user,void * data)2492 static bool cb_trace(void *user, void *data) {
2493 	RCore *core = (RCore *) user;
2494 	RConfigNode *node = (RConfigNode *) data;
2495 	core->dbg->trace->enabled = node->i_value;
2496 	return true;
2497 }
2498 
cb_tracetag(void * user,void * data)2499 static bool cb_tracetag(void *user, void *data) {
2500 	RCore *core = (RCore *) user;
2501 	RConfigNode *node = (RConfigNode *) data;
2502 	core->dbg->trace->tag = node->i_value;
2503 	return true;
2504 }
2505 
cb_utf8(void * user,void * data)2506 static bool cb_utf8(void *user, void *data) {
2507 	RConfigNode *node = (RConfigNode *) data;
2508 	r_cons_set_utf8 ((bool)node->i_value);
2509 	return true;
2510 }
2511 
cb_utf8_curvy(void * user,void * data)2512 static bool cb_utf8_curvy(void *user, void *data) {
2513 	RCore *core = (RCore *) user;
2514 	RConfigNode *node = (RConfigNode *) data;
2515 	core->cons->use_utf8_curvy = node->i_value;
2516 	return true;
2517 }
2518 
cb_dotted(void * user,void * data)2519 static bool cb_dotted(void *user, void *data) {
2520 	RCore *core = (RCore *) user;
2521 	RConfigNode *node = (RConfigNode *) data;
2522 	core->cons->dotted_lines = node->i_value;
2523 	return true;
2524 }
2525 
cb_zoombyte(void * user,void * data)2526 static bool cb_zoombyte(void *user, void *data) {
2527 	RCore *core = (RCore *) user;
2528 	RConfigNode *node = (RConfigNode *) data;
2529 	switch (*node->value) {
2530 	case 'p': case 'f': case 's': case '0':
2531 	case 'F': case 'e': case 'h':
2532 		core->print->zoom->mode = *node->value;
2533 		break;
2534 	default:
2535 		eprintf ("Invalid zoom.byte value. See pz? for help\n");
2536 		r_cons_printf ("pzp\npzf\npzs\npz0\npzF\npze\npzh\n");
2537 		return false;
2538 	}
2539 	return true;
2540 }
2541 
cb_analverbose(void * user,void * data)2542 static bool cb_analverbose(void *user, void *data) {
2543 	RCore *core = (RCore *) user;
2544 	RConfigNode *node = (RConfigNode *) data;
2545 	core->anal->verbose = node->i_value;
2546 	return true;
2547 }
2548 
cb_binverbose(void * user,void * data)2549 static bool cb_binverbose(void *user, void *data) {
2550 	RCore *core = (RCore *) user;
2551 	RConfigNode *node = (RConfigNode *) data;
2552 	core->bin->verbose = node->i_value;
2553 	return true;
2554 }
2555 
cb_prjname(void * user,void * data)2556 static bool cb_prjname(void *user, void *data) {
2557 	RCore *core = (RCore *) user;
2558 	RConfigNode *node = (RConfigNode *) data;
2559 	const char *prjname = node->value;
2560 	if (*prjname == '?') {
2561 		r_core_project_list (core, 0);
2562 		return false;
2563 	}
2564 	if (r_project_is_loaded (core->prj)) {
2565 		if (*prjname) {
2566 			if (!strcmp (prjname, core->prj->name)) {
2567 				return true;
2568 			}
2569 			if (r_project_rename (core->prj, prjname)) {
2570 				return true;
2571 			}
2572 			eprintf ("Cannot rename project.\n");
2573 		} else {
2574 			r_project_close (core->prj);
2575 		}
2576 	} else {
2577 		if (*prjname) {
2578 			if (r_project_open (core->prj, prjname, NULL)) {
2579 				return true;
2580 			}
2581 			eprintf ("Cannot open project.\n");
2582 		}
2583 	}
2584 	return false;
2585 }
2586 
cb_rawstr(void * user,void * data)2587 static bool cb_rawstr(void *user, void *data) {
2588 	RCore *core = (RCore *) user;
2589 	RConfigNode *node = (RConfigNode *) data;
2590 	core->bin->rawstr = node->i_value;
2591 	return true;
2592 }
2593 
cb_debase64(void * user,void * data)2594 static bool cb_debase64(void *user, void *data) {
2595 	RCore *core = (RCore *) user;
2596 	RConfigNode *node = (RConfigNode *) data;
2597 	core->bin->debase64 = node->i_value;
2598 	return true;
2599 }
2600 
cb_binstrings(void * user,void * data)2601 static bool cb_binstrings(void *user, void *data) {
2602 	const ut32 req = R_BIN_REQ_STRINGS;
2603 	RCore *core = (RCore *) user;
2604 	RConfigNode *node = (RConfigNode *) data;
2605 	if (node->i_value) {
2606 		core->bin->filter_rules |= req;
2607 	} else {
2608 		core->bin->filter_rules &= ~req;
2609 	}
2610 	return true;
2611 }
2612 
cb_bindbginfo(void * user,void * data)2613 static bool cb_bindbginfo(void *user, void *data) {
2614 	RCore *core = (RCore *) user;
2615 	RConfigNode *node = (RConfigNode *) data;
2616 	if (!core || !core->bin) {
2617 		return false;
2618 	}
2619 	core->bin->want_dbginfo = node->i_value;
2620 	return true;
2621 }
2622 
cb_binprefix(void * user,void * data)2623 static bool cb_binprefix(void *user, void *data) {
2624 	RCore *core = (RCore *) user;
2625 	RConfigNode *node = (RConfigNode *) data;
2626 	if (!core || !core->bin) {
2627 		return false;
2628 	}
2629 	if (node->value && *node->value) {
2630 		if (!strcmp (node->value, "auto")) {
2631 			if (!core->bin->file) {
2632 				return false;
2633 			}
2634 			char *name = (char *)r_file_basename (core->bin->file);
2635 			if (name) {
2636 				r_name_filter (name, strlen (name));
2637 				r_str_filter (name, strlen (name));
2638 				core->bin->prefix = strdup (name);
2639 				free (name);
2640 			}
2641 		} else {
2642 			core->bin->prefix = node->value;
2643 		}
2644 	}
2645 	return true;
2646 }
2647 
cb_binmaxstrbuf(void * user,void * data)2648 static bool cb_binmaxstrbuf(void *user, void *data) {
2649 	RCore *core = (RCore *) user;
2650 	RConfigNode *node = (RConfigNode *) data;
2651 	if (core->bin) {
2652 		int v = node->i_value;
2653 		ut64 old_v = core->bin->maxstrbuf;
2654 		if (v < 1) {
2655 			v = 4; // HACK
2656 		}
2657 		core->bin->maxstrbuf = v;
2658 		if (v>old_v) {
2659 			r_bin_reset_strings (core->bin);
2660 		}
2661 		return true;
2662 	}
2663 	return true;
2664 }
2665 
cb_binmaxstr(void * user,void * data)2666 static bool cb_binmaxstr(void *user, void *data) {
2667 	RCore *core = (RCore *) user;
2668 	RConfigNode *node = (RConfigNode *) data;
2669 	if (core->bin) {
2670 		int v = node->i_value;
2671 		if (v < 1) {
2672 			v = 4; // HACK
2673 		}
2674 		core->bin->maxstrlen = v;
2675 		r_bin_reset_strings (core->bin);
2676 		return true;
2677 	}
2678 	return true;
2679 }
2680 
cb_binminstr(void * user,void * data)2681 static bool cb_binminstr(void *user, void *data) {
2682 	RCore *core = (RCore *) user;
2683 	RConfigNode *node = (RConfigNode *) data;
2684 	if (core->bin) {
2685 		int v = node->i_value;
2686 		if (v < 1) {
2687 			v = 4; // HACK
2688 		}
2689 		core->bin->minstrlen = v;
2690 		r_bin_reset_strings (core->bin);
2691 		return true;
2692 	}
2693 	return true;
2694 }
2695 
cb_searchin(void * user,void * data)2696 static bool cb_searchin(void *user, void *data) {
2697 	RCore *core = (RCore*)user;
2698 	RConfigNode *node = (RConfigNode*) data;
2699 	if (*node->value == '?') {
2700 		if (strlen (node->value) > 1 && node->value[1] == '?') {
2701 			r_cons_printf ("Valid values for search.in (depends on .from/.to and io.va):\n"
2702 			"raw                search in raw io (ignoring bounds)\n"
2703 			"block              search in the current block\n"
2704 			"io.map             search in current map\n"
2705 			"io.sky.[rwx]       search in all skyline segments\n"
2706 			"io.maps            search in all maps\n"
2707 			"io.maps.[rwx]      search in all r-w-x io maps\n"
2708 			"bin.segment        search in current mapped segment\n"
2709 			"bin.segments       search in all mapped segments\n"
2710 			"bin.segments.[rwx] search in all r-w-x segments\n"
2711 			"bin.section        search in current mapped section\n"
2712 			"bin.sections       search in all mapped sections\n"
2713 			"bin.sections.[rwx] search in all r-w-x sections\n"
2714 			"dbg.stack          search in the stack\n"
2715 			"dbg.heap           search in the heap\n"
2716 			"dbg.map            search in current memory map\n"
2717 			"dbg.maps           search in all memory maps\n"
2718 			"dbg.maps.[rwx]     search in all executable marked memory maps\n"
2719 			"anal.fcn           search in the current function\n"
2720 			"anal.bb            search in the current basic-block\n");
2721 		} else {
2722 			print_node_options (node);
2723 		}
2724 		return false;
2725 	}
2726 	// Set anal.noncode if exec bit set in anal.in
2727 	if (r_str_startswith (node->name, "anal")) {
2728 		core->anal->opt.noncode = (strchr (node->value, 'x') == NULL);
2729 	}
2730 	return true;
2731 }
2732 
__dbg_swstep_getter(void * user,RConfigNode * node)2733 static int __dbg_swstep_getter(void *user, RConfigNode *node) {
2734 	RCore *core = (RCore*)user;
2735 	node->i_value = core->dbg->swstep;
2736 	return true;
2737 }
2738 
cb_dirpfx(RCore * core,RConfigNode * node)2739 static bool cb_dirpfx(RCore *core, RConfigNode *node) {
2740 	r_sys_prefix (node->value);
2741 	return true;
2742 }
2743 
cb_analsyscc(RCore * core,RConfigNode * node)2744 static bool cb_analsyscc(RCore *core, RConfigNode *node) {
2745 	if (core && core->anal) {
2746 		if (*node->value == '?') {
2747 			r_core_cmd0 (core, "afcl");
2748 			return false;
2749 		}
2750 		r_anal_set_syscc_default (core->anal, node->value);
2751 	}
2752 	return true;
2753 }
2754 
cb_analcc_getter(RCore * core,RConfigNode * node)2755 static bool cb_analcc_getter(RCore *core, RConfigNode *node) {
2756 	const char *cc = r_anal_cc_default (core->anal);
2757 	if (cc) {
2758 		free (node->value);
2759 		node->value = strdup (cc);
2760 	}
2761 	return true;
2762 }
2763 
cb_analcc(RCore * core,RConfigNode * node)2764 static bool cb_analcc(RCore *core, RConfigNode *node) {
2765 	if (core && core->anal) {
2766 		node->getter = (RConfigCallback)cb_analcc_getter;
2767 		if (*node->value == '?') {
2768 			r_core_cmd0 (core, "afcl");
2769 			return false;
2770 		}
2771 		r_anal_set_cc_default (core->anal, node->value);
2772 	}
2773 	return true;
2774 }
2775 
cb_anal_roregs(RCore * core,RConfigNode * node)2776 static bool cb_anal_roregs(RCore *core, RConfigNode *node) {
2777 	if (core && core->anal && core->anal->reg) {
2778 		r_list_free (core->anal->reg->roregs);
2779 		core->anal->reg->roregs = r_str_split_duplist (node->value, ",", true);
2780 	}
2781 	return true;
2782 }
2783 
cb_anal_gp(RCore * core,RConfigNode * node)2784 static bool cb_anal_gp(RCore *core, RConfigNode *node) {
2785 	core->anal->gp = node->i_value;
2786 	return true;
2787 }
2788 
cb_anal_from(RCore * core,RConfigNode * node)2789 static bool cb_anal_from(RCore *core, RConfigNode *node) {
2790 	if (r_config_get_i (core->config, "anal.limits")) {
2791 		r_anal_set_limits (core->anal,
2792 				r_config_get_i (core->config, "anal.from"),
2793 				r_config_get_i (core->config, "anal.to"));
2794 	}
2795 	return true;
2796 }
2797 
cb_anal_limits(void * user,RConfigNode * node)2798 static bool cb_anal_limits(void *user, RConfigNode *node) {
2799 	RCore *core = (RCore*)user;
2800 	if (node->i_value) {
2801 		r_anal_set_limits (core->anal,
2802 				r_config_get_i (core->config, "anal.from"),
2803 				r_config_get_i (core->config, "anal.to"));
2804 	} else {
2805 		r_anal_unset_limits (core->anal);
2806 	}
2807 	return 1;
2808 }
2809 
cb_anal_rnr(void * user,RConfigNode * node)2810 static bool cb_anal_rnr(void *user, RConfigNode *node) {
2811 	RCore *core = (RCore*)user;
2812 	core->anal->recursive_noreturn = node->i_value;
2813 	return 1;
2814 }
2815 
cb_anal_jmptbl(void * user,void * data)2816 static bool cb_anal_jmptbl(void *user, void *data) {
2817 	RCore *core = (RCore*) user;
2818 	RConfigNode *node = (RConfigNode*) data;
2819 	core->anal->opt.jmptbl = node->i_value;
2820 	return true;
2821 }
2822 
cb_anal_cjmpref(void * user,void * data)2823 static bool cb_anal_cjmpref(void *user, void *data) {
2824 	RCore *core = (RCore*) user;
2825 	RConfigNode *node = (RConfigNode*) data;
2826 	core->anal->opt.cjmpref = node->i_value;
2827 	return true;
2828 }
2829 
cb_anal_jmpref(void * user,void * data)2830 static bool cb_anal_jmpref(void *user, void *data) {
2831 	RCore *core = (RCore*) user;
2832 	RConfigNode *node = (RConfigNode*) data;
2833 	core->anal->opt.jmpref = node->i_value;
2834 	return true;
2835 }
2836 
cb_anal_jmpabove(void * user,void * data)2837 static bool cb_anal_jmpabove(void *user, void *data) {
2838 	RCore *core = (RCore*) user;
2839 	RConfigNode *node = (RConfigNode*) data;
2840 	core->anal->opt.jmpabove = node->i_value;
2841 	return true;
2842 }
2843 
cb_anal_loads(void * user,void * data)2844 static bool cb_anal_loads(void *user, void *data) {
2845 	RCore *core = (RCore*) user;
2846 	RConfigNode *node = (RConfigNode*) data;
2847 	core->anal->opt.loads = node->i_value;
2848 	return true;
2849 }
2850 
cb_anal_followdatarefs(void * user,void * data)2851 static bool cb_anal_followdatarefs(void *user, void *data) {
2852 	RCore *core = (RCore*) user;
2853 	RConfigNode *node = (RConfigNode*) data;
2854 	core->anal->opt.followdatarefs = node->i_value;
2855 	return true;
2856 }
2857 
cb_anal_jmpmid(void * user,void * data)2858 static bool cb_anal_jmpmid(void *user, void *data) {
2859 	RCore *core = (RCore*) user;
2860 	RConfigNode *node = (RConfigNode*) data;
2861 	core->anal->opt.jmpmid = node->i_value;
2862 	return true;
2863 }
2864 
cb_anal_searchstringrefs(void * user,void * data)2865 static bool cb_anal_searchstringrefs(void *user, void *data) {
2866 	RCore *core = (RCore*) user;
2867 	RConfigNode *node = (RConfigNode*) data;
2868 	core->anal->opt.searchstringrefs = node->i_value;
2869 	return true;
2870 }
2871 
cb_anal_pushret(void * user,void * data)2872 static bool cb_anal_pushret(void *user, void *data) {
2873 	RCore *core = (RCore*) user;
2874 	RConfigNode *node = (RConfigNode*) data;
2875 	core->anal->opt.pushret = node->i_value;
2876 	return true;
2877 }
2878 
cb_anal_brokenrefs(void * user,void * data)2879 static bool cb_anal_brokenrefs(void *user, void *data) {
2880 	RCore *core = (RCore*) user;
2881 	RConfigNode *node = (RConfigNode*) data;
2882 	core->anal->opt.followbrokenfcnsrefs = node->i_value;
2883 	return true;
2884 }
2885 
cb_anal_trycatch(void * user,void * data)2886 static bool cb_anal_trycatch(void *user, void *data) {
2887 	RCore *core = (RCore*) user;
2888 	RConfigNode *node = (RConfigNode*) data;
2889 	core->anal->opt.trycatch = node->i_value;
2890 	return true;
2891 }
2892 
cb_anal_bb_max_size(void * user,void * data)2893 static bool cb_anal_bb_max_size(void *user, void *data) {
2894 	RCore *core = (RCore*) user;
2895 	RConfigNode *node = (RConfigNode*) data;
2896 	core->anal->opt.bb_max_size = node->i_value;
2897 	return true;
2898 }
2899 
cb_anal_cpp_abi(void * user,void * data)2900 static bool cb_anal_cpp_abi(void *user, void *data) {
2901 	RCore *core = (RCore*) user;
2902 	RConfigNode *node = (RConfigNode*) data;
2903 
2904 	if (*node->value == '?') {
2905 		print_node_options (node);
2906 		return false;
2907 	}
2908 
2909 	if (*node->value) {
2910 		if (strcmp (node->value, "itanium") == 0) {
2911 			core->anal->cpp_abi = R_ANAL_CPP_ABI_ITANIUM;
2912 			return true;
2913 		} else if (strcmp (node->value, "msvc") == 0) {
2914 			core->anal->cpp_abi = R_ANAL_CPP_ABI_MSVC;
2915 			return true;
2916 		}
2917 		eprintf ("anal.cpp.abi: cannot find '%s'\n", node->value);
2918 	}
2919 	return false;
2920 }
2921 
cb_linesto(void * user,void * data)2922 static bool cb_linesto(void *user, void *data) {
2923 	RCore *core = (RCore*) user;
2924 	RConfigNode *node = (RConfigNode*) data;
2925 	ut64 from = (ut64)r_config_get_i (core->config, "lines.from");
2926 	int io_sz = r_io_size (core->io);
2927 	ut64 to = r_num_math (core->num, node->value);
2928 	if (to == 0) {
2929 		core->print->lines_cache_sz = -1; //r_core_lines_initcache (core, from, to);
2930 		return true;
2931 	}
2932 	if (to > from + io_sz) {
2933 		eprintf ("ERROR: \"lines.to\" can't exceed addr 0x%08"PFMT64x
2934 			" 0x%08"PFMT64x" %d\n", from, to, io_sz);
2935 		return true;
2936 	}
2937 	if (to > from) {
2938 		core->print->lines_cache_sz = r_core_lines_initcache (core, from, to);
2939 		//if (core->print->lines_cache_sz == -1) { eprintf ("ERROR: Can't allocate memory\n"); }
2940 	} else {
2941 		eprintf ("Invalid range 0x%08"PFMT64x" .. 0x%08"PFMT64x"\n", from, to);
2942 	}
2943 	return true;
2944 }
2945 
cb_linesabs(void * user,void * data)2946 static bool cb_linesabs(void *user, void *data) {
2947 	RCore *core = (RCore*) user;
2948 	RConfigNode *node = (RConfigNode*) data;
2949 	core->print->lines_abs = node->i_value;
2950 	if (core->print->lines_abs && core->print->lines_cache_sz <= 0) {
2951 		ut64 from = (ut64)r_config_get_i (core->config, "lines.from");
2952 		const char *to_str = r_config_get (core->config, "lines.to");
2953 		ut64 to = r_num_math (core->num, (to_str && *to_str) ? to_str : "$s");
2954 		core->print->lines_cache_sz = r_core_lines_initcache (core, from, to);
2955 		if (core->print->lines_cache_sz == -1) {
2956 			eprintf ("ERROR: \"lines.from\" and \"lines.to\" must be set\n");
2957 		} else {
2958 			eprintf ("Found %d lines\n", core->print->lines_cache_sz-1);
2959 		}
2960 	}
2961 	return true;
2962 }
2963 
cb_malloc(void * user,void * data)2964 static bool cb_malloc(void *user, void *data) {
2965  	RCore *core = (RCore*) user;
2966  	RConfigNode *node = (RConfigNode*) data;
2967 
2968  	if (node->value) {
2969  		if (!strcmp ("jemalloc", node->value) || !strcmp ("glibc", node->value)) {
2970 			if (core->dbg) {
2971 				core->dbg->malloc = data;
2972 			}
2973  		}
2974 
2975  	}
2976 	return true;
2977 }
2978 
cb_log_config_level(void * coreptr,void * nodeptr)2979 static bool cb_log_config_level(void *coreptr, void *nodeptr) {
2980 	RConfigNode *node = (RConfigNode *)nodeptr;
2981 	r_log_set_level (node->i_value);
2982 	return true;
2983 }
2984 
cb_log_config_traplevel(void * coreptr,void * nodeptr)2985 static bool cb_log_config_traplevel(void *coreptr, void *nodeptr) {
2986 	RConfigNode *node = (RConfigNode *)nodeptr;
2987 	r_log_set_traplevel (node->i_value);
2988 	return true;
2989 }
2990 
cb_log_config_file(void * coreptr,void * nodeptr)2991 static bool cb_log_config_file(void *coreptr, void *nodeptr) {
2992 	RConfigNode *node = (RConfigNode *)nodeptr;
2993 	const char *value = node->value;
2994 	r_log_set_file (value);
2995 	return true;
2996 }
2997 
cb_log_config_srcinfo(void * coreptr,void * nodeptr)2998 static bool cb_log_config_srcinfo(void *coreptr, void *nodeptr) {
2999 	RConfigNode *node = (RConfigNode *)nodeptr;
3000 	const char *value = node->value;
3001 	switch (value[0]) {
3002 	case 't':
3003 	case 'T':
3004 		r_log_set_srcinfo (true);
3005 		break;
3006 	default:
3007 		r_log_set_srcinfo (false);
3008 	}
3009 	return true;
3010 }
3011 
cb_log_config_colors(void * coreptr,void * nodeptr)3012 static bool cb_log_config_colors(void *coreptr, void *nodeptr) {
3013 	RConfigNode *node = (RConfigNode *)nodeptr;
3014 	const char *value = node->value;
3015 	switch (value[0]) {
3016 	case 't':
3017 	case 'T':
3018 		r_log_set_colors (true);
3019 		break;
3020 	default:
3021 		r_log_set_colors (false);
3022 	}
3023 	return true;
3024 }
3025 
cb_dbg_verbose(void * user,void * data)3026 static bool cb_dbg_verbose(void *user, void *data) {
3027 	RCore *core = (RCore *)user;
3028 	RConfigNode *node = (RConfigNode *)data;
3029 	const char *value = node->value;
3030 	switch (value[0]) {
3031 	case 't':
3032 	case 'T':
3033 		core->dbg->verbose = true;
3034 		break;
3035 	default:
3036 		core->dbg->verbose = false;
3037 	}
3038 	return true;
3039 }
3040 
r_core_config_init(RCore * core)3041 R_API int r_core_config_init(RCore *core) {
3042 	int i;
3043 	char buf[128], *p, *tmpdir;
3044 	RConfigNode *n;
3045 	RConfig *cfg = core->config = r_config_new (core);
3046 	if (!cfg) {
3047 		return 0;
3048 	}
3049 	cfg->cb_printf = r_cons_printf;
3050 	cfg->num = core->num;
3051 	/* dir.prefix is used in other modules, set it first */
3052 	{
3053 		char *pfx = r_sys_getenv("R2_PREFIX");
3054 #if __WINDOWS__
3055 		const char *invoke_dir = r_sys_prefix (NULL);
3056 		if (!pfx && invoke_dir) {
3057 			pfx = strdup (invoke_dir);
3058 		}
3059 #endif
3060 		if (!pfx) {
3061 			pfx = strdup (R2_PREFIX);
3062 		}
3063 		SETCB ("dir.prefix", pfx, (RConfigCallback)&cb_dirpfx, "Default prefix r2 was compiled for");
3064 		free (pfx);
3065 	}
3066 #if __ANDROID__
3067 	{ // use dir.home and also adjust check for permissions in directory before choosing a home
3068 		char *h = r_sys_getenv (R_SYS_HOME);
3069 		if (h) {
3070 			if (!strcmp (h, "/")) {
3071 				r_sys_setenv (R_SYS_HOME, "/data/local/tmp");
3072 			}
3073 			free (h);
3074 		}
3075 	}
3076 #endif
3077         SETCB ("cmd.times", "", &cb_cmdtimes, "Run when a command is repeated (number prefix)");
3078 	/* pdb */
3079 	SETPREF ("pdb.useragent", "Microsoft-Symbol-Server/6.11.0001.402", "User agent for Microsoft symbol server");
3080 	SETPREF ("pdb.server", "https://msdl.microsoft.com/download/symbols", "Semi-colon separated list of base URLs for Microsoft symbol servers");
3081 	{
3082 		char *pdb_path = r_str_home (R2_HOME_PDB);
3083 		SETPREF ("pdb.symstore", pdb_path, "Path to downstream symbol store");
3084 		R_FREE(pdb_path);
3085 	}
3086 	SETI ("pdb.extract", 1, "Avoid extract of the pdb file, just download");
3087 	SETI ("pdb.autoload", false, "Automatically load the required pdb files for loaded DLLs");
3088 
3089 	/* anal */
3090 	SETBPREF ("anal.detectwrites", "false", "Automatically reanalyze function after a write");
3091 	SETPREF ("anal.fcnprefix", "fcn",  "Prefix new function names with this");
3092 	const char *analcc = r_anal_cc_default (core->anal);
3093 	SETCB ("anal.cc", analcc? analcc: "", (RConfigCallback)&cb_analcc, "Specify default calling convention");
3094 	const char *analsyscc = r_anal_syscc_default (core->anal);
3095 	SETCB ("anal.syscc", analsyscc? analsyscc: "", (RConfigCallback)&cb_analsyscc, "Specify default syscall calling convention");
3096 	SETCB ("anal.verbose", "false", &cb_analverbose, "Show RAnal warnings when analyzing code");
3097 	SETBPREF ("anal.a2f", "false",  "Use the new WIP analysis algorithm (core/p/a2f), anal.depth ignored atm");
3098 	SETCB ("anal.roregs", "gp,zero", (RConfigCallback)&cb_anal_roregs, "Comma separated list of register names to be readonly");
3099 	SETICB ("anal.gp", 0, (RConfigCallback)&cb_anal_gp, "Set the value of the GP register (MIPS)");
3100 	SETBPREF ("anal.gpfixed", "true", "Set gp register to anal.gp before emulating each instruction in aae");
3101 	SETCB ("anal.limits", "false", (RConfigCallback)&cb_anal_limits, "Restrict analysis to address range [anal.from:anal.to]");
3102 	SETCB ("anal.rnr", "false", (RConfigCallback)&cb_anal_rnr, "Recursive no return checks (EXPERIMENTAL)");
3103 	SETCB ("anal.limits", "false", (RConfigCallback)&cb_anal_limits, "Restrict analysis to address range [anal.from:anal.to]");
3104 	SETICB ("anal.from", -1, (RConfigCallback)&cb_anal_from, "Lower limit on the address range for analysis");
3105 	SETICB ("anal.to", -1, (RConfigCallback)&cb_anal_from, "Upper limit on the address range for analysis");
3106 	n = NODECB ("anal.in", "io.maps.x", &cb_searchin);
3107 	SETDESC (n, "Specify search boundaries for analysis");
3108 	SETOPTIONS (n, "range", "block",
3109 		"bin.segment", "bin.segments", "bin.segments.x", "bin.segments.r", "bin.section", "bin.sections", "bin.sections.rwx", "bin.sections.r", "bin.sections.rw", "bin.sections.rx", "bin.sections.wx", "bin.sections.x",
3110 		"io.map", "io.maps", "io.maps.rwx", "io.maps.r", "io.maps.rw", "io.maps.rx", "io.maps.wx", "io.maps.x",
3111 		"dbg.stack", "dbg.heap",
3112 		"dbg.map", "dbg.maps", "dbg.maps.rwx", "dbg.maps.r", "dbg.maps.rw", "dbg.maps.rx", "dbg.maps.wx", "dbg.maps.x",
3113 		"anal.fcn", "anal.bb",
3114 	NULL);
3115 	SETI ("anal.timeout", 0, "Stop analyzing after a couple of seconds");
3116 	SETCB ("anal.jmp.retpoline", "true", &cb_anal_jmpretpoline, "Analyze retpolines, may be slower if not needed");
3117 	SETICB ("anal.jmp.tailcall", 0, &cb_anal_jmptailcall, "Consume a branch as a call if delta is big");
3118 
3119 	SETCB ("anal.armthumb", "false", &cb_analarmthumb, "aae computes arm/thumb changes (lot of false positives ahead)");
3120 	SETCB ("anal.jmp.after", "true", &cb_analafterjmp, "Continue analysis after jmp/ujmp");
3121 	SETCB ("anal.endsize", "true", &cb_anal_endsize, "Adjust function size at the end of the analysis (known to be buggy)");
3122 	SETCB ("anal.delay", "true", &cb_anal_delay, "Enable delay slot analysis if supported by the architecture");
3123 	SETICB ("anal.depth", 64, &cb_analdepth, "Max depth at code analysis"); // XXX: warn if depth is > 50 .. can be problematic
3124 	SETICB ("anal.graph_depth", 256, &cb_analgraphdepth, "Max depth for path search");
3125 	SETICB ("anal.sleep", 0, &cb_analsleep, "Sleep N usecs every so often during analysis. Avoid 100% CPU usage");
3126 	SETCB ("anal.ignbithints", "false", &cb_anal_ignbithints, "Ignore the ahb hints (only obey asm.bits)");
3127 	SETBPREF ("anal.calls", "false", "Make basic af analysis walk into calls");
3128 	SETBPREF ("anal.autoname", "false", "Speculatively set a name for the functions, may result in some false positives");
3129 	SETBPREF ("anal.hasnext", "false", "Continue analysis after each function");
3130 	SETICB ("anal.nonull", 0, &cb_anal_nonull, "Do not analyze regions of N null bytes");
3131 	SETBPREF ("anal.esil", "false", "Use the new ESIL code analysis");
3132 	SETCB ("anal.strings", "false", &cb_analstrings, "Identify and register strings during analysis (aar only)");
3133 	SETPREF ("anal.types.spec", "gcc",  "Set profile for specifying format chars used in type analysis");
3134 	SETBPREF ("anal.types.verbose", "false", "Verbose output from type analysis");
3135 	SETBPREF ("anal.types.constraint", "false", "Enable constraint types analysis for variables");
3136 	SETCB ("anal.vars", "true", &cb_analvars, "Analyze local variables and arguments");
3137 	SETCB ("anal.vars.stackname", "false", &cb_analvars_stackname, "Name variables based on their offset on the stack");
3138 	SETBPREF ("anal.vinfun", "true",  "Search values in functions (aav) (false by default to only find on non-code)");
3139 	SETBPREF ("anal.vinfunrange", "false",  "Search values outside function ranges (requires anal.vinfun=false)\n");
3140 	SETCB ("anal.norevisit", "false", &cb_analnorevisit, "Do not visit function analysis twice (EXPERIMENTAL)");
3141 	SETCB ("anal.nopskip", "true", &cb_analnopskip, "Skip nops at the beginning of functions");
3142 	SETCB ("anal.hpskip", "false", &cb_analhpskip, "Skip `mov reg, reg` and `lea reg, [reg] at the beginning of functions");
3143 	n = NODECB ("anal.arch", R_SYS_ARCH, &cb_analarch);
3144 	SETDESC (n, "Select the architecture to use");
3145 	update_analarch_options (core, n);
3146 	SETCB ("anal.cpu", R_SYS_ARCH, &cb_analcpu, "Specify the anal.cpu to use");
3147 	SETPREF ("anal.prelude", "", "Specify an hexpair to find preludes in code");
3148 	SETCB ("anal.recont", "false", &cb_analrecont, "End block after splitting a basic block instead of error"); // testing
3149 	SETCB ("anal.jmp.indir", "false", &cb_analijmp, "Follow the indirect jumps in function analysis"); // testing
3150 	SETI ("anal.ptrdepth", 3, "Maximum number of nested pointers to follow in analysis");
3151 	SETICB ("asm.lines.maxref", 0, &cb_analmaxrefs, "Maximum number of reflines to be analyzed and displayed in asm.lines with pd");
3152 
3153 	SETCB ("anal.jmp.tbl", "true", &cb_anal_jmptbl, "Analyze jump tables in switch statements");
3154 
3155 	SETCB ("anal.jmp.cref", "false", &cb_anal_cjmpref, "Create references for conditional jumps");
3156 	SETCB ("anal.jmp.ref", "true", &cb_anal_jmpref, "Create references for unconditional jumps");
3157 
3158 	SETCB ("anal.jmp.above", "true", &cb_anal_jmpabove, "Jump above function pointer");
3159 	SETCB ("anal.loads", "false", &cb_anal_loads, "Define as dword/string/qword when analyzing load instructions");
3160 	SETCB ("anal.datarefs", "false", &cb_anal_followdatarefs, "Follow data references for code coverage");
3161 	SETCB ("anal.brokenrefs", "false", &cb_anal_brokenrefs, "Follow function references as well if function analysis was failed");
3162 	SETCB ("anal.jmp.mid", "true", &cb_anal_jmpmid, "Continue analysis after jump to middle of instruction (x86 only)");
3163 
3164 	SETCB ("anal.refstr", "false", &cb_anal_searchstringrefs, "Search string references in data references");
3165 	SETCB ("anal.trycatch", "false", &cb_anal_trycatch, "Honor try.X.Y.{from,to,catch} flags");
3166 	SETCB ("anal.bb.maxsize", "512K", &cb_anal_bb_max_size, "Maximum basic block size");
3167 	SETCB ("anal.pushret", "false", &cb_anal_pushret, "Analyze push+ret as jmp");
3168 
3169 	n = NODECB ("anal.cpp.abi", "itanium", &cb_anal_cpp_abi);
3170 	SETDESC (n, "Select C++ ABI (Compiler)");
3171 	SETOPTIONS (n, "itanium", "msvc", NULL);
3172 
3173 #if __linux__ && __GNU_LIBRARY__ && __GLIBC__ && __GLIBC_MINOR__
3174  	SETCB ("dbg.malloc", "glibc", &cb_malloc, "Choose malloc structure parser");
3175 #else
3176 	SETCB ("dbg.malloc", "jemalloc", &cb_malloc, "Choose malloc structure parser");
3177 #endif
3178 #if __GLIBC_MINOR__ > 25
3179 	SETBPREF ("dbg.glibc.tcache", "true", "Set glib tcache parsing");
3180 #else
3181 	SETBPREF ("dbg.glibc.tcache", "false", "Set glib tcache parsing");
3182 #endif
3183 #if __x86_64__
3184 	SETI ("dbg.glibc.ma_offset", 0x000000, "Main_arena offset from his symbol");
3185 	SETI ("dbg.glibc.fc_offset", 0x00280, "First chunk offset from brk_start");
3186 #else
3187 	SETI ("dbg.glibc.ma_offset", 0x1bb000, "Main_arena offset from his symbol");
3188 	SETI ("dbg.glibc.fc_offset", 0x148, "First chunk offset from brk_start");
3189 #endif
3190 	SETBPREF ("dbg.glibc.demangle", "false", "Demangle linked-lists pointers introduced in glibc 2.32");
3191 	SETBPREF ("esil.prestep", "true", "Step before esil evaluation in `de` commands");
3192 	SETPREF ("esil.fillstack", "", "Initialize ESIL stack with (random, debrujn, sequence, zeros, ...)");
3193 	SETICB ("esil.verbose", 0, &cb_esilverbose, "Show ESIL verbose level (0, 1, 2)");
3194 	SETICB ("esil.gotolimit", core->anal->esil_goto_limit, &cb_gotolimit, "Maximum number of gotos per ESIL expression");
3195 	SETICB ("esil.stack.depth", 256, &cb_esilstackdepth, "Number of elements that can be pushed on the esilstack");
3196 	SETI ("esil.stack.size", 0xf0000, "Set stack size in ESIL VM");
3197 	SETI ("esil.stack.addr", 0x100000, "Set stack address in ESIL VM");
3198 	SETPREF ("esil.stack.pattern", "0", "Specify fill pattern to initialize the stack (0, w, d, i)");
3199 	SETI ("esil.addr.size", 64, "Maximum address size in accessed by the ESIL VM");
3200 	SETBPREF ("esil.breakoninvalid", "false", "Break esil execution when instruction is invalid");
3201 	SETI ("esil.timeout", 0, "A timeout (in seconds) for when we should give up emulating");
3202 	/* asm */
3203 	//asm.os needs to be first, since other asm.* depend on it
3204 	n = NODECB ("asm.os", R_SYS_OS, &cb_asmos);
3205 	SETDESC (n, "Select operating system (kernel)");
3206 	SETOPTIONS (n, "ios", "dos", "darwin", "linux", "freebsd", "openbsd", "netbsd", "windows", "s110", NULL);
3207 	SETI ("asm.xrefs.fold", 5,  "Maximum number of xrefs to be displayed as list (use columns above)");
3208 	SETBPREF ("asm.xrefs.code", "true",  "Show the code xrefs (generated by jumps instead of calls)");
3209 	SETI ("asm.xrefs.max", 20,  "Maximum number of xrefs to be displayed without folding");
3210 	SETCB ("asm.invhex", "false", &cb_asm_invhex, "Show invalid instructions as hexadecimal numbers");
3211 	SETBPREF ("asm.instr", "true", "Display the disassembled instruction");
3212 	SETBPREF ("asm.meta", "true", "Display the code/data/format conversions in disasm");
3213 	SETBPREF ("asm.bytes", "true", "Display the bytes of each instruction");
3214 	SETBPREF ("asm.bytes.right", "false", "Display the bytes at the right of the disassembly");
3215 	SETI ("asm.types", 1, "Display the fcn types in calls (0=no,1=quiet,2=verbose)");
3216 	SETBPREF ("asm.midcursor", "false", "Cursor in visual disasm mode breaks the instruction");
3217 	SETBPREF ("asm.cmt.flgrefs", "true", "Show comment flags associated to branch reference");
3218 	SETBPREF ("asm.cmt.right", "true", "Show comments at right of disassembly if they fit in screen");
3219 	SETBPREF ("asm.cmt.esil", "false", "Show ESIL expressions as comments");
3220 	SETI ("asm.cmt.col", 71, "Column to align comments");
3221 	SETICB ("asm.pcalign", 0, &cb_asm_pcalign, "Only recognize as valid instructions aligned to this value");
3222 	// maybe rename to asm.cmt.calls
3223 	SETBPREF ("asm.calls", "true", "Show callee function related info as comments in disasm");
3224 	SETBPREF ("asm.comments", "true", "Show comments in disassembly view");
3225 	SETBPREF ("asm.usercomments", "false", "Show user comments even if asm.comments is false");
3226 	SETBPREF ("asm.sub.jmp", "true", "Always substitute jump, call and branch targets in disassembly");
3227 	SETBPREF ("asm.hints", "true", "Disable all asm.hint* if false");
3228 	SETBPREF ("asm.hint.jmp", "false", "Show jump hints [numbers] in disasm");
3229 	SETBPREF ("asm.hint.call", "true", "Show call hints [numbers] in disasm");
3230 	SETBPREF ("asm.hint.call.indirect", "true", "Hints for indirect call intructions go to the call destination");
3231 	SETBPREF ("asm.hint.lea", "false", "Show LEA hints [numbers] in disasm");
3232 	SETBPREF ("asm.hint.emu", "false", "Show asm.emu hints [numbers] in disasm");
3233 	SETBPREF ("asm.hint.cdiv", "false", "Show CDIV hints optimization hint");
3234 	SETI ("asm.hint.pos", 1, "Shortcut hint position (-1, 0, 1)");
3235 	SETBPREF ("asm.slow", "true", "Perform slow analysis operations in disasm");
3236 	SETBPREF ("asm.decode", "false", "Use code analysis as a disassembler");
3237 	SETICB ("asm.imm.arm", false,  &cb_asm_armimm, "Display # for immediates in ARM");
3238 	SETBPREF ("asm.imm.str", "true", "Show immediates values as strings");
3239 	SETBPREF ("asm.imm.trim", "false", "Remove all offsets and constants from disassembly");
3240 	SETBPREF ("asm.indent", "false", "Indent disassembly based on reflines depth");
3241 	SETI ("asm.indentspace", 2, "How many spaces to indent the code");
3242 	SETBPREF ("asm.dwarf", "false", "Show dwarf comment at disassembly");
3243 	SETBPREF ("asm.dwarf.abspath", "false", "Show absolute path in asm.dwarf");
3244 	SETBPREF ("asm.dwarf.file", "true", "Show filename of asm.dwarf in pd");
3245 	SETBPREF ("asm.esil", "false", "Show ESIL instead of mnemonic");
3246 	SETBPREF ("asm.nodup", "false", "Do not show dupped instructions (collapse disasm)");
3247 	SETBPREF ("asm.emu", "false", "Run ESIL emulation analysis on disasm");
3248 	SETBPREF ("emu.pre", "false", "Run ESIL emulation starting at the closest flag in pd");
3249 	SETBPREF ("asm.refptr", "true", "Show refpointer information in disasm");
3250 	SETBPREF ("emu.lazy", "false", "Do not emulate all instructions with aae (optimization)");
3251 	SETBPREF ("emu.stack", "false", "Create a temporary fake stack when emulating in disasm (asm.emu)");
3252 	SETCB ("emu.str", "false", &cb_emustr, "Show only strings if any in the asm.emu output");
3253 	SETBPREF ("emu.str.lea", "true", "Disable this in ARM64 code to remove some false positives");
3254 	SETBPREF ("emu.str.off", "false", "Always show offset when printing asm.emu strings");
3255 	SETBPREF ("emu.str.inv", "true", "Color-invert emu.str strings");
3256 	SETBPREF ("emu.str.flag", "true", "Also show flag (if any) for asm.emu string");
3257 	SETBPREF ("emu.write", "false", "Allow asm.emu to modify memory (WARNING)");
3258 	SETBPREF ("emu.ssa", "false", "Perform SSA checks and show the ssa reg names as comments");
3259 	n = NODECB ("emu.skip", "ds", &cb_emuskip);
3260 	SETDESC (n, "Skip metadata of given types in asm.emu");
3261 	SETOPTIONS (n, "d", "c", "s", "f", "m", "h", "C", "r", NULL);
3262 	SETBPREF ("asm.sub.names", "true", "Replace numeric values by flags (e.g. 0x4003e0 -> sym.imp.printf)");
3263 	SETPREF ("asm.strip", "", "strip all instructions given comma separated types");
3264 	SETBPREF ("asm.optype", "false", "show opcode type next to the instruction bytes");
3265 	SETBPREF ("asm.lines.fcn", "true", "Show function boundary lines");
3266 	SETBPREF ("asm.flags", "true", "Show flags");
3267 	SETICB ("asm.flags.maxname", 0, &cb_maxname, "Maximum length of flag name with smart chopping");
3268 	SETI ("asm.flags.limit", 0, "Maximum number of flags to show in a single offset");
3269 	SETBPREF ("asm.flags.offset", "false", "Show offset in flags");
3270 	SETBPREF ("asm.flags.inbytes", "false",  "Display flags inside the bytes space");
3271 	SETBPREF ("asm.flags.inline", "false",  "Display flags in line separated by commas instead of newlines");
3272 	n = NODEICB ("asm.flags.middle", 2, &cb_midflags);
3273 	SETOPTIONS (n, "0 = do not show flag", "1 = show without realign", "2 = realign at middle flag",
3274 		"3 = realign at middle flag if sym.*", NULL);
3275 	SETDESC (n, "Realign disassembly if there is a flag in the middle of an instruction");
3276 	SETCB ("asm.flags.real", "false", &cb_flag_realnames,
3277 	       "Show flags' unfiltered realnames instead of names, except realnames from demangling");
3278 	SETBPREF ("asm.bb.line", "false", "Show empty line after every basic block");
3279 	SETBPREF ("asm.bb.middle", "true", "Realign disassembly if a basic block starts in the middle of an instruction");
3280 	SETBPREF ("asm.lbytes", "true", "Align disasm bytes to left");
3281 	SETBPREF ("asm.lines", "true", "Show ASCII-art lines at disassembly");
3282 	SETBPREF ("asm.lines.bb", "true", "Show flow lines at jumps");
3283 	SETBPREF ("asm.lines.call", "false", "Enable call lines");
3284 	SETBPREF ("asm.lines.ret", "false", "Show separator lines after ret");
3285 	SETBPREF ("asm.lines.out", "true", "Show out of block lines");
3286 	SETBPREF ("asm.lines.right", "false", "Show lines before opcode instead of offset");
3287 	SETBPREF ("asm.lines.wide", "false", "Put a space between lines");
3288 	SETBPREF ("asm.fcnsig", "true", "Show function signature in disasm");
3289 	SETICB ("asm.lines.width", 7, &cb_asmlineswidth, "Number of columns for program flow arrows");
3290 	SETICB ("asm.sub.varmin", 0x100, &cb_asmsubvarmin, "Minimum value to substitute in instructions (asm.sub.var)");
3291 	SETCB ("asm.sub.tail", "false", &cb_asmsubtail, "Replace addresses with prefix .. syntax");
3292 	SETBPREF ("asm.middle", "false", "Allow disassembling jumps in the middle of an instruction");
3293 	SETBPREF ("asm.noisy", "true", "Show comments considered noisy but possibly useful");
3294 	SETBPREF ("asm.offset", "true", "Show offsets in disassembly");
3295 	SETBPREF ("hex.offset", "true", "Show offsets in hex-dump");
3296 	SETBPREF ("scr.square", "true", "Use square pixels or not");
3297 	SETCB ("scr.prompt.vi", "false", &cb_scr_vi, "Use vi mode for input prompt");
3298 	SETCB ("scr.prompt.mode", "false", &cb_scr_prompt_mode,  "Set prompt color based on vi mode");
3299 	SETCB ("scr.wideoff", "false", &cb_scr_wideoff, "Adjust offsets to match asm.bits");
3300 	SETCB ("scr.rainbow", "false", &cb_scrrainbow, "Shows rainbow colors depending of address");
3301 	SETCB ("scr.last", "true", &cb_scrlast, "Cache last output after flush to make _ command work (disable for performance)");
3302 	SETBPREF ("asm.reloff", "false", "Show relative offsets instead of absolute address in disasm");
3303 	SETBPREF ("asm.reloff.flags", "false", "Show relative offsets to flags (not only functions)");
3304 	SETBPREF ("asm.section", "false", "Show section name before offset");
3305 	SETBPREF ("asm.section.perm", "false", "Show section permissions in the disasm");
3306 	SETBPREF ("asm.section.name", "true", "Show section name in the disasm");
3307 	SETI ("asm.section.col", 20, "Columns width to show asm.section");
3308 	SETCB ("asm.sub.section", "false", &cb_asmsubsec, "Show offsets in disasm prefixed with section/map name");
3309 	SETCB ("asm.pseudo", "false", &cb_asmpseudo, "Enable pseudo syntax");
3310 	SETBPREF ("asm.size", "false", "Show size of opcodes in disassembly (pd)");
3311 	SETBPREF ("asm.stackptr", "false", "Show stack pointer at disassembly");
3312 	SETBPREF ("asm.cyclespace", "false", "Indent instructions depending on CPU-cycles");
3313 	SETBPREF ("asm.cycles", "false", "Show CPU-cycles taken by instruction at disassembly");
3314 	SETI ("asm.tabs", 0, "Use tabs in disassembly");
3315 	SETBPREF ("asm.tabs.once", "false", "Only tabulate the opcode, not the arguments");
3316 	SETI ("asm.tabs.off", 0, "tabulate spaces after the offset");
3317 	SETBPREF ("asm.trace", "false", "Show execution traces for each opcode");
3318 	SETBPREF ("asm.tracespace", "false", "Indent disassembly with trace.count information");
3319 	SETBPREF ("asm.ucase", "false", "Use uppercase syntax at disassembly");
3320 	SETBPREF ("asm.capitalize", "false", "Use camelcase at disassembly");
3321 	SETBPREF ("asm.var", "true", "Show local function variables in disassembly");
3322 	SETBPREF ("asm.var.access", "false", "Show accesses of local variables");
3323 	SETBPREF ("asm.sub.var", "true", "Substitute variables in disassembly");
3324 	SETI ("asm.var.summary", 0, "Show variables summary instead of full list in disasm (0, 1, 2)");
3325 	SETBPREF ("asm.sub.varonly", "true", "Substitute the entire variable expression with the local variable name (e.g. [local10h] instead of [ebp+local10h])");
3326 	SETBPREF ("asm.sub.reg", "false", "Substitute register names with their associated role name (drp~=)");
3327 	SETBPREF ("asm.sub.rel", "true", "Substitute pc relative expressions in disasm");
3328 	SETBPREF ("asm.cmt.fold", "false", "Fold comments, toggle with Vz");
3329 	SETBPREF ("asm.family", "false", "Show family name in disasm");
3330 	SETBPREF ("asm.symbol", "false", "Show symbol+delta instead of absolute offset");
3331 	SETBPREF ("asm.anal", "false", "Analyze code and refs while disassembling (see anal.strings)");
3332 	SETI ("asm.symbol.col", 40, "Columns width to show asm.section");
3333 	SETCB ("asm.assembler", "", &cb_asmassembler, "Set the plugin name to use when assembling");
3334 	SETBPREF ("asm.minicols", "false", "Only show the instruction in the column disasm");
3335 	RConfigNode *asmcpu = NODECB ("asm.cpu", R_SYS_ARCH, &cb_asmcpu);
3336 	SETDESC (asmcpu, "Set the kind of asm.arch cpu");
3337 	RConfigNode *asmarch = NODECB ("asm.arch", R_SYS_ARCH, &cb_asmarch);
3338 	SETDESC (asmarch, "Set the arch to be used by asm");
3339 	/* we need to have both asm.arch and asm.cpu defined before updating options */
3340 	update_asmarch_options (core, asmarch);
3341 	update_asmcpu_options (core, asmcpu);
3342 	n = NODECB ("asm.features", "", &cb_asmfeatures);
3343 	SETDESC (n, "Specify supported features by the target CPU");
3344 	update_asmfeatures_options (core, n);
3345 	n = NODECB ("asm.parser", "x86.pseudo", &cb_asmparser);
3346 	SETDESC (n, "Set the asm parser to use");
3347 	update_asmparser_options (core, n);
3348 	SETCB ("asm.segoff", "false", &cb_segoff, "Show segmented address in prompt (x86-16)");
3349 	SETCB ("asm.decoff", "false", &cb_decoff, "Show segmented address in prompt (x86-16)");
3350 	SETICB ("asm.seggrn", 4, &cb_seggrn, "Segment granularity in bits (x86-16)");
3351 	n = NODECB ("asm.syntax", "intel", &cb_asmsyntax);
3352 	SETDESC (n, "Select assembly syntax");
3353 	SETOPTIONS (n, "att", "intel", "masm", "jz", "regnum", NULL);
3354 	SETI ("asm.nbytes", 6, "Number of bytes for each opcode at disassembly");
3355 	SETBPREF ("asm.bytes.space", "false", "Separate hexadecimal bytes with a whitespace");
3356 #if R_SYS_BITS == R_SYS_BITS_64
3357 	SETICB ("asm.bits", 64, &cb_asmbits, "Word size in bits at assembler");
3358 #else
3359 	SETICB ("asm.bits", 32, &cb_asmbits, "Word size in bits at assembler");
3360 #endif
3361 	n = r_config_node_get(cfg, "asm.bits");
3362 	update_asmbits_options (core, n);
3363 	SETBPREF ("asm.functions", "true", "Show functions in disassembly");
3364 	SETBPREF ("asm.xrefs", "true", "Show xrefs in disassembly");
3365 	SETBPREF ("asm.demangle", "true", "Show demangled symbols in disasm");
3366 	SETBPREF ("asm.describe", "false", "Show opcode description");
3367 	SETPREF ("asm.highlight", "", "Highlight current line");
3368 	SETBPREF ("asm.marks", "true", "Show marks before the disassembly");
3369 	SETBPREF ("asm.cmt.refs", "false", "Show flag and comments from refs in disasm");
3370 	SETBPREF ("asm.cmt.patch", "false", "Show patch comments in disasm");
3371 	SETBPREF ("asm.cmt.off", "nodup", "Show offset comment in disasm (true, false, nodup)");
3372 	SETBPREF ("asm.payloads", "false", "Show payload bytes in disasm");
3373 
3374 	/* bin */
3375 	SETPREF ("bin.hashlimit", "10M", "Only compute hash when opening a file if smaller than this size");
3376 	SETCB ("bin.usextr", "true", &cb_usextr, "Use extract plugins when loading files");
3377 	SETCB ("bin.useldr", "true", &cb_useldr, "Use loader plugins when loading files");
3378 	SETCB ("bin.str.purge", "", &cb_strpurge, "Purge strings (e bin.str.purge=? provides more detail)");
3379 	SETPREF ("bin.str.real", "false", "Set the realname in rbin.strings for better disasm (EXPERIMENTAL)");
3380 	SETBPREF ("bin.b64str", "false", "Try to debase64 the strings");
3381 	SETCB ("bin.at", "false", &cb_binat, "RBin.cur depends on RCore.offset");
3382 	SETBPREF ("bin.libs", "false", "Try to load libraries after loading main binary");
3383 	n = NODECB ("bin.str.filter", "", &cb_strfilter);
3384 	SETDESC (n, "Filter strings");
3385 	SETOPTIONS (n, "a", "8", "p", "e", "u", "i", "U", "f", NULL);
3386 	SETCB ("bin.filter", "true", &cb_binfilter, "Filter symbol names to fix dupped names");
3387 	SETCB ("bin.force", "", &cb_binforce, "Force that rbin plugin");
3388 	SETPREF ("bin.cache", "false", "Enable io.cache and fall to io.cache.read if bin needs to patch relocs");
3389 	SETPREF ("bin.lang", "", "Language for bin.demangle");
3390 	SETBPREF ("bin.demangle", "true", "Import demangled symbols from RBin");
3391 	SETBPREF ("bin.demangle.libs", "false", "Show library name on demangled symbols names");
3392 	SETI ("bin.baddr", -1, "Base address of the binary");
3393 	SETI ("bin.laddr", 0, "Base address for loading library ('*.so')");
3394 	SETCB ("bin.dbginfo", "true", &cb_bindbginfo, "Load debug information at startup if available");
3395 	SETBPREF ("bin.relocs", "true", "Load relocs information at startup if available");
3396 	SETICB ("bin.minstr", 0, &cb_binminstr, "Minimum string length for r_bin");
3397 	SETICB ("bin.maxstr", 0, &cb_binmaxstr, "Maximum string length for r_bin");
3398 	SETICB ("bin.maxstrbuf", 1024*1024*10, & cb_binmaxstrbuf, "Maximum size of range to load strings from");
3399 	n = NODECB ("bin.str.enc", "guess", &cb_binstrenc);
3400 	SETDESC (n, "Default string encoding of binary");
3401 	SETOPTIONS (n, "ascii", "latin1", "utf8", "utf16le", "utf32le", "utf16be", "utf32be", "guess", NULL);
3402 	SETCB ("bin.prefix", "", &cb_binprefix, "Prefix all symbols/sections/relocs with a specific string");
3403 	SETCB ("bin.rawstr", "false", &cb_rawstr, "Load strings from raw binaries");
3404 	SETCB ("bin.strings", "true", &cb_binstrings, "Load strings from rbin on startup");
3405 	SETCB ("bin.debase64", "false", &cb_debase64, "Try to debase64 all strings");
3406 	SETBPREF ("bin.classes", "true", "Load classes from rbin on startup");
3407 	SETCB ("bin.verbose", "false", &cb_binverbose, "Show RBin warnings when loading binaries");
3408 
3409 	/* prj */
3410 	SETCB ("prj.name", "", &cb_prjname, "Name of current project");
3411 	SETBPREF ("prj.files", "false", "Save the target binary inside the project directory");
3412 	{
3413 		char *p = r_file_path ("git");
3414 		bool found = (p && *p == '/');
3415 		SETBPREF ("prj.git", r_str_bool (found), "Use git to share your project and version changes");
3416 		free (p);
3417 	}
3418 	SETBPREF ("prj.zip", "false", "Use ZIP format for project files");
3419 	SETBPREF ("prj.gpg", "false", "TODO: Encrypt project with GnuPGv2");
3420 
3421 	/* cfg */
3422 	SETCB ("cfg.charset", "", &cb_cfgcharset, "Specify encoding to use when printing strings");
3423 	SETBPREF ("cfg.r2wars", "false", "Enable some tweaks for the r2wars game");
3424 	SETBPREF ("cfg.plugins", "true", "Load plugins at startup");
3425 	SETCB ("time.fmt", "%Y-%m-%d %H:%M:%S %z", &cb_cfgdatefmt, "Date format (%Y-%m-%d %H:%M:%S %z)");
3426 	SETICB ("time.zone", 0, &cb_timezone, "Time zone, in hours relative to GMT: +2, -1,..");
3427 	SETCB ("cfg.corelog", "false", &cb_cfgcorelog, "Log changes using the T api needed for realtime syncing");
3428 	SETBPREF ("cfg.newtab", "false", "Show descriptions in command completion");
3429 	SETCB ("cfg.debug", "false", &cb_cfgdebug, "Debugger mode");
3430 	p = r_sys_getenv ("EDITOR");
3431 #if __WINDOWS__
3432 	r_config_set (cfg, "cfg.editor", r_str_get_fail (p, "notepad"));
3433 #else
3434 	r_config_set (cfg, "cfg.editor", r_str_get_fail (p, "vi"));
3435 #endif
3436 	free (p);
3437 	r_config_desc (cfg, "cfg.editor", "Select default editor program");
3438 	char *whoami = r_sys_whoami ();
3439 	SETPREF ("cfg.user", whoami, "Set current username/pid");
3440 	free (whoami);
3441 	SETCB ("cfg.fortunes", "true", &cb_cfg_fortunes, "If enabled show tips at start");
3442 	SETCB ("cfg.fortunes.type", "tips,fun", &cb_cfg_fortunes_type, "Type of fortunes to show (tips, fun)");
3443 	SETBPREF ("cfg.fortunes.clippy", "false", "Use ?E instead of ?e");
3444 	SETBPREF ("cfg.fortunes.tts", "false", "Speak out the fortune");
3445 	SETPREF ("cfg.prefixdump", "dump", "Filename prefix for automated dumps");
3446 	SETCB ("cfg.sandbox", "false", &cb_cfgsanbox, "Sandbox mode disables systems and open on upper directories");
3447 	SETBPREF ("cfg.wseek", "false", "Seek after write");
3448 	SETCB ("cfg.bigendian", "false", &cb_bigendian, "Use little (false) or big (true) endianness");
3449 	p = r_sys_getenv ("R2_CFG_NEWSHELL");
3450 	SETCB ("cfg.newshell", r_str_bool (p && atoi (p)), &cb_newshell, "Use new commands parser");
3451 	free (p);
3452 	SETI ("cfg.cpuaffinity", 0, "Run on cpuid");
3453 
3454 	/* log */
3455 	// R2_LOGLEVEL / log.level
3456 	p = r_sys_getenv ("R2_LOGLEVEL");
3457 	SETICB ("log.level", p? atoi(p): R_DEFAULT_LOGLVL, cb_log_config_level, "Target log level/severity"\
3458 	 " (0:SILLY, 1:DEBUG, 2:VERBOSE, 3:INFO, 4:WARN, 5:ERROR, 6:FATAL)"
3459 	);
3460 	free (p);
3461 	// R2_LOGTRAP_LEVEL / log.traplevel
3462 	p = r_sys_getenv ("R2_LOGTRAPLEVEL");
3463 	SETICB ("log.traplevel", p ? atoi(p) : R_LOGLVL_FATAL, cb_log_config_traplevel, "Log level for trapping R2 when hit"\
3464 	 " (0:SILLY, 1:VERBOSE, 2:DEBUG, 3:INFO, 4:WARN, 5:ERROR, 6:FATAL)"
3465 	);
3466 	free (p);
3467 	// R2_LOGFILE / log.file
3468 	p = r_sys_getenv ("R2_LOGFILE");
3469 	SETCB ("log.file", r_str_get (p), cb_log_config_file, "Logging output filename / path");
3470 	free (p);
3471 	// R2_LOGSRCINFO / log.srcinfo
3472 	p = r_sys_getenv ("R2_LOGSRCINFO");
3473 	SETCB ("log.srcinfo", r_str_get_fail (p, "false"), cb_log_config_srcinfo, "Should the log output contain src info (filename:lineno)");
3474 	free (p);
3475 	// R2_LOGCOLORS / log.colors
3476 	p = r_sys_getenv ("R2_LOGCOLORS");
3477 	SETCB ("log.colors", r_str_get_fail (p, "false"), cb_log_config_colors, "Should the log output use colors (TODO)");
3478 	free (p);
3479 
3480 	SETCB ("log.events", "false", &cb_log_events, "Remote HTTP server to sync events with");
3481 
3482 	// zign
3483 	SETPREF ("zign.prefix", "sign", "Default prefix for zignatures matches");
3484 	SETI ("zign.maxsz", 500, "Maximum zignature length");
3485 	SETI ("zign.minsz", 16, "Minimum zignature length for matching");
3486 	SETI ("zign.mincc", 10, "Minimum cyclomatic complexity for matching");
3487 	SETBPREF ("zign.graph", "true", "Use graph metrics for matching");
3488 	SETBPREF ("zign.bytes", "true", "Use bytes patterns for matching");
3489 	SETBPREF ("zign.offset", "false", "Use original offset for matching");
3490 	SETBPREF ("zign.refs", "true", "Use references for matching");
3491 	SETBPREF ("zign.hash", "true", "Use Hash for matching");
3492 	SETBPREF ("zign.types", "true", "Use types for matching");
3493 	SETBPREF ("zign.autoload", "false", "Autoload all zignatures located in " R_JOIN_2_PATHS ("~", R2_HOME_ZIGNS));
3494 	SETPREF ("zign.diff.bthresh", "1.0", "Threshold for diffing zign bytes [0, 1] (see zc?)");
3495 	SETPREF ("zign.diff.gthresh", "1.0", "Threshold for diffing zign graphs [0, 1] (see zc?)");
3496 	SETPREF ("zign.threshold", "0.0", "Minimum similarity required for inclusion in zb output");
3497 
3498 	/* diff */
3499 	SETCB ("diff.sort", "addr", &cb_diff_sort, "Specify function diff sorting column see (e diff.sort=?)");
3500 	SETI ("diff.from", 0, "Set source diffing address for px (uses cc command)");
3501 	SETI ("diff.to", 0, "Set destination diffing address for px (uses cc command)");
3502 	SETBPREF ("diff.bare", "false", "Never show function names in diff output");
3503 	SETBPREF ("diff.levenstein", "false", "Use faster (and buggy) levenstein algorithm for buffer distance diffing");
3504 
3505 	/* dir */
3506 	SETI ("dir.depth", 10,  "Maximum depth when searching recursively for files");
3507 	{
3508 		char *path = r_str_newf (R_JOIN_2_PATHS ("%s", R2_SDB_MAGIC), r_config_get (core->config, "dir.prefix"));
3509 		SETPREF ("dir.magic", path, "Path to r_magic files");
3510 		free (path);
3511 		path = r_str_newf (R_JOIN_2_PATHS ("%s", R2_PLUGINS), r_config_get (core->config, "dir.prefix"));
3512 		SETPREF ("dir.plugins", path, "Path to plugin files to be loaded at startup");
3513 		free (path);
3514 	}
3515 	SETCB ("dir.source", "", &cb_dirsrc, "Path to find source files");
3516 	SETPREF ("dir.types", "/usr/include", "Default path to look for cparse type files");
3517 	SETPREF ("dir.libs", "", "Specify path to find libraries to load when bin.libs=true");
3518 	p = r_sys_getenv (R_SYS_HOME);
3519 	SETCB ("dir.home", r_str_get_fail (p, "/"), &cb_dirhome, "Path for the home directory");
3520 	free (p);
3521 	p = r_sys_getenv (R_SYS_TMP);
3522 	SETCB ("dir.tmp", r_str_get (p), &cb_dirtmp, "Path of the tmp directory");
3523 	free (p);
3524 #if __ANDROID__
3525 	SETCB ("dir.projects", "/data/data/org.radare.radare2installer/radare2/projects", &cb_dir_projects, "Default path for projects");
3526 #else
3527 	SETCB ("dir.projects", R_JOIN_2_PATHS ("~", R2_HOME_PROJECTS), &cb_dir_projects, "Default path for projects");
3528 #endif
3529 	SETCB ("dir.zigns", R_JOIN_2_PATHS ("~", R2_HOME_ZIGNS), &cb_dirzigns, "Default path for zignatures (see zo command)");
3530 	SETPREF ("stack.reg", "SP", "Which register to use as stack pointer in the visual debug");
3531 	SETBPREF ("stack.bytes", "true", "Show bytes instead of words in stack");
3532 	SETBPREF ("stack.anotated", "false", "Show anotated hexdump in visual debug");
3533 	SETI ("stack.size", 64,  "Size in bytes of stack hexdump in visual debug");
3534 	SETI ("stack.delta", 0,  "Delta for the stack dump");
3535 
3536 	SETCB ("dbg.libs", "", &cb_dbg_libs, "If set stop when loading matching libname");
3537 	SETBPREF ("dbg.skipover", "false", "Make dso perform a dss (same goes for esil and visual/graph");
3538 	SETI ("dbg.hwbp", 0, "Set HW or SW breakpoints");
3539 	SETCB ("dbg.unlibs", "", &cb_dbg_unlibs, "If set stop when unloading matching libname");
3540 	SETCB ("dbg.verbose", "true", &cb_dbg_verbose, "Verbose debug output");
3541 	SETBPREF ("dbg.slow", "false", "Show stack and regs in visual mode in a slow but verbose mode");
3542 	SETBPREF ("dbg.funcarg", "false", "Display arguments to function call in visual mode");
3543 
3544 	SETCB ("dbg.bpinmaps", "true", &cb_dbg_bpinmaps, "Activate breakpoints only if they are inside a valid map");
3545 	SETCB ("dbg.forks", "false", &cb_dbg_forks, "Stop execution if fork() is done (see dbg.threads)");
3546 	n = NODECB ("dbg.btalgo", "fuzzy", &cb_dbg_btalgo);
3547 	SETDESC (n, "Select backtrace algorithm");
3548 	SETOPTIONS (n, "default", "fuzzy", "anal", "trace", NULL);
3549 	SETCB ("dbg.threads", "false", &cb_stopthreads, "Stop all threads when debugger breaks (see dbg.forks)");
3550 	SETCB ("dbg.clone", "false", &cb_dbg_clone, "Stop execution if new thread is created");
3551 	SETCB ("dbg.aftersyscall", "true", &cb_dbg_aftersc, "Stop execution before the syscall is executed (see dcs)");
3552 	SETCB ("dbg.profile", "", &cb_runprofile, "Path to RRunProfile file");
3553 	SETCB ("dbg.args", "", &cb_dbg_args, "Set the args of the program to debug");
3554 	SETCB ("dbg.follow.child", "false", &cb_dbg_follow_child, "Continue tracing the child process on fork. By default the parent process is traced");
3555 	SETCB ("dbg.trace_continue", "true", &cb_dbg_trace_continue, "Trace every instruction between the initial PC position and the PC position at the end of continue's execution");
3556 	/* debug */
3557 	SETCB ("dbg.status", "false", &cb_dbgstatus, "Set cmd.prompt to '.dr*' or '.dr*;drd;sr PC;pi 1;s-'");
3558 #if DEBUGGER
3559 	SETCB ("dbg.backend", "native", &cb_dbgbackend, "Select the debugger backend");
3560 #else
3561 	SETCB ("dbg.backend", "esil", &cb_dbgbackend, "Select the debugger backend");
3562 #endif
3563 	n = NODECB ("dbg.bep", "loader", &cb_dbgbep);
3564 	SETDESC (n, "Break on entrypoint");
3565 	SETOPTIONS (n, "loader", "entry", "constructor", "main", NULL);
3566 	if (core->cons->rows > 30) { // HACKY
3567 		r_config_set_i (cfg, "dbg.follow", 64);
3568 	} else {
3569 		r_config_set_i (cfg, "dbg.follow", 32);
3570 	}
3571 	r_config_desc (cfg, "dbg.follow", "Follow program counter when pc > core->offset + dbg.follow");
3572 	SETBPREF ("dbg.rebase", "true", "Rebase anal/meta/comments/flags when reopening file in debugger");
3573 	SETCB ("dbg.swstep", "false", &cb_swstep, "Force use of software steps (code analysis+breakpoint)");
3574 	SETBPREF ("dbg.trace.inrange", "false", "While tracing, avoid following calls outside specified range");
3575 	SETBPREF ("dbg.trace.libs", "true", "Trace library code too");
3576 	SETBPREF ("dbg.exitkills", "true", "Kill process on exit");
3577 	SETPREF ("dbg.exe.path", "", "Path to binary being debugged");
3578 	SETCB ("dbg.execs", "false", &cb_dbg_execs, "Stop execution if new thread is created");
3579 	SETICB ("dbg.gdb.page_size", 4096, &cb_dbg_gdb_page_size, "Page size on gdb target (useful for QEMU)");
3580 	SETICB ("dbg.gdb.retries", 10, &cb_dbg_gdb_retries, "Number of retries before gdb packet read times out");
3581 	SETCB ("dbg.consbreak", "false", &cb_consbreak, "SIGINT handle for attached processes");
3582 
3583 	r_config_set_getter (cfg, "dbg.swstep", (RConfigCallback)__dbg_swstep_getter);
3584 
3585 // TODO: This should be specified at first by the debug backend when attaching
3586 #if __arm__ || __mips__
3587 	SETICB ("dbg.bpsize", 4, &cb_dbgbpsize, "Size of software breakpoints");
3588 #else
3589 	SETICB ("dbg.bpsize", 1, &cb_dbgbpsize, "Size of software breakpoints");
3590 #endif
3591 	SETBPREF ("dbg.bpsysign", "false", "Ignore system breakpoints");
3592 	SETICB ("dbg.btdepth", 128, &cb_dbgbtdepth, "Depth of backtrace");
3593 	SETCB ("dbg.trace", "false", &cb_trace, "Trace program execution (see asm.trace)");
3594 	SETICB ("dbg.trace.tag", 0, &cb_tracetag, "Trace tag");
3595 
3596 
3597 	/* cmd */
3598 	SETCB ("cmd.demangle", "false", &cb_bdc, "run xcrun swift-demangle and similar if available (SLOW)");
3599 	SETICB ("cmd.depth", 10, &cb_cmddepth, "Maximum command depth");
3600 	SETPREF ("cmd.bp", "", "Run when a breakpoint is hit");
3601 	SETPREF ("cmd.onsyscall", "", "Run when a syscall is hit");
3602 	SETICB ("cmd.hitinfo", 1, &cb_debug_hitinfo, "Show info when a tracepoint/breakpoint is hit");
3603 	SETPREF ("cmd.stack", "", "Command to display the stack in visual debug mode");
3604 	SETPREF ("cmd.cprompt", "", "Column visual prompt commands");
3605 	SETPREF ("cmd.gprompt", "", "Graph visual prompt commands");
3606 	SETPREF ("cmd.hit", "", "Run when a search hit is found");
3607 	SETPREF ("cmd.open", "", "Run when file is opened");
3608 	SETPREF ("cmd.load", "", "Run when binary is loaded");
3609 	RConfigNode *cmdpdc = NODECB ("cmd.pdc", "", &cb_cmdpdc);
3610 	SETDESC (cmdpdc, "Select pseudo-decompiler command to run after pdc");
3611 	update_cmdpdc_options (core, cmdpdc);
3612 	SETCB ("cmd.log", "", &cb_cmdlog, "Every time a new T log is added run this command");
3613 	SETPREF ("cmd.prompt", "", "Prompt commands");
3614 	SETCB ("cmd.repeat", "false", &cb_cmdrepeat, "Empty command an alias for '..' (repeat last command)");
3615 	SETPREF ("cmd.fcn.new", "", "Run when new function is analyzed");
3616 	SETPREF ("cmd.fcn.delete", "", "Run when a function is deleted");
3617 	SETPREF ("cmd.fcn.rename", "", "Run when a function is renamed");
3618 	SETPREF ("cmd.visual", "", "Replace current print mode");
3619 	SETPREF ("cmd.vprompt", "", "Visual prompt commands");
3620 
3621 	SETCB ("cmd.esil.step", "", &cb_cmd_esil_step, "Command to run before performing a step in the emulator");
3622 	SETCB ("cmd.esil.stepout", "", &cb_cmd_esil_step_out, "Command to run after performing a step in the emulator");
3623 	SETCB ("cmd.esil.mdev", "", &cb_cmd_esil_mdev, "Command to run when memory device address is accessed");
3624 	SETCB ("cmd.esil.intr", "", &cb_cmd_esil_intr, "Command to run when an esil interrupt happens");
3625 	SETCB ("cmd.esil.trap", "", &cb_cmd_esil_trap, "Command to run when an esil trap happens");
3626 	SETCB ("cmd.esil.todo", "", &cb_cmd_esil_todo, "Command to run when the esil instruction contains TODO");
3627 	SETCB ("cmd.esil.ioer", "", &cb_cmd_esil_ioer, "Command to run when esil fails to IO (invalid read/write)");
3628 
3629 	/* filesystem */
3630 	n = NODECB ("fs.view", "normal", &cb_fsview);
3631 	SETDESC (n, "Set visibility options for filesystems");
3632 	SETOPTIONS (n, "all", "deleted", "special", NULL);
3633 
3634 	/* hexdump */
3635 	SETCB ("hex.header", "true", &cb_hex_header, "Show header in hexdump");
3636 	SETCB ("hex.bytes", "true", &cb_hex_bytes, "Show bytes column in hexdump");
3637 	SETCB ("hex.ascii", "true", &cb_hex_ascii, "Show ascii column in hexdump");
3638 	SETCB ("hex.hdroff", "false", &cb_hex_hdroff, "Show aligned 1 byte in header instead of delta nibble");
3639 	SETCB ("hex.style", "false", &cb_hex_style, "Improve the hexdump header style");
3640 	SETCB ("hex.pairs", "true", &cb_hex_pairs, "Show bytes paired in 'px' hexdump");
3641 	SETCB ("hex.align", "false", &cb_hex_align, "Align hexdump with flag + flagsize");
3642 	SETCB ("hex.section", "false", &cb_hex_section, "Show section name before the offset");
3643 	SETCB ("hex.compact", "false", &cb_hexcompact, "Show smallest 16 byte col hexdump (60 columns)");
3644 	SETCB ("cmd.hexcursor", "", &cb_cmd_hexcursor, "If set and cursor is enabled display given pf format string");
3645 	SETI ("hex.flagsz", 0, "If non zero, overrides the flag size in pxa");
3646 	SETICB ("hex.cols", 16, &cb_hexcols, "Number of columns in hexdump");
3647 	SETI ("hex.depth", 5, "Maximal level of recurrence while telescoping memory");
3648 	SETBPREF ("hex.onechar", "false", "Number of columns in hexdump");
3649 	SETICB ("hex.stride", 0, &cb_hexstride, "Line stride in hexdump (default is 0)");
3650 	SETCB ("hex.comments", "true", &cb_hexcomments, "Show comments in 'px' hexdump");
3651 
3652 	/* http */
3653 	SETBPREF ("http.log", "true", "Show HTTP requests processed");
3654 	SETPREF ("http.sync", "", "Remote HTTP server to sync events with");
3655 	SETBPREF ("http.colon", "false", "Only accept the : command");
3656 	SETPREF ("http.logfile", "", "Specify a log file instead of stderr for http requests");
3657 	SETBPREF ("http.cors", "false", "Enable CORS");
3658 	SETPREF ("http.referer", "", "CSFR protection if set");
3659 	SETBPREF ("http.dirlist", "false", "Enable directory listing");
3660 	SETPREF ("http.allow", "", "Only accept clients from the comma separated IP list");
3661 #if __WINDOWS__
3662 	r_config_set (cfg, "http.browser", "start");
3663 #else
3664 	if (r_file_exists ("/usr/bin/openURL")) { // iOS ericautils
3665 		r_config_set (cfg, "http.browser", "/usr/bin/openURL");
3666 	} else if (r_file_exists ("/system/bin/toolbox")) {
3667 		r_config_set (cfg, "http.browser",
3668 				"LD_LIBRARY_PATH=/system/lib am start -a android.intent.action.VIEW -d");
3669 	} else if (r_file_exists ("/usr/bin/xdg-open")) {
3670 		r_config_set (cfg, "http.browser", "xdg-open");
3671 	} else if (r_file_exists ("/usr/bin/open")) {
3672 		r_config_set (cfg, "http.browser", "open");
3673 	} else {
3674 		r_config_set (cfg, "http.browser", "firefox");
3675 	}
3676 	r_config_desc (cfg, "http.browser", "Command to open HTTP URLs");
3677 #endif
3678 	SETI ("http.maxsize", 0, "Maximum file size for upload");
3679 	SETPREF ("http.index", "index.html", "Main html file to check in directory");
3680 	SETPREF ("http.bind", "localhost", "Server address");
3681 	SETPREF ("http.homeroot", R_JOIN_2_PATHS ("~", R2_HOME_WWWROOT), "http home root directory");
3682 #if __WINDOWS__
3683 	{
3684 		char *wwwroot = r_str_newf ("%s\\share\\www", r_sys_prefix (NULL));
3685 		SETPREF ("http.root", wwwroot, "http root directory");
3686 		free (wwwroot);
3687 	}
3688 #elif __ANDROID__
3689 	SETPREF ("http.root", "/data/data/org.radare.radare2installer/www", "http root directory");
3690 #else
3691 	SETPREF ("http.root", R2_WWWROOT, "http root directory");
3692 #endif
3693 	SETPREF ("http.port", "9090", "HTTP server port");
3694 	SETPREF ("http.maxport", "9999", "Last HTTP server port");
3695 	SETPREF ("http.ui", "m", "Default webui (m, t, f)");
3696 	SETBPREF ("http.sandbox", "true", "Sandbox the HTTP server");
3697 	SETI ("http.timeout", 3, "Disconnect clients after N seconds of inactivity");
3698 	SETI ("http.dietime", 0, "Kill server after N seconds with no client");
3699 	SETBPREF ("http.verbose", "false", "Output server logs to stdout");
3700 	SETBPREF ("http.upget", "false", "/up/ answers GET requests, in addition to POST");
3701 	SETBPREF ("http.upload", "false", "Enable file uploads to /up/<filename>");
3702 	SETPREF ("http.uri", "", "Address of HTTP proxy");
3703 	SETBPREF ("http.auth", "false", "Enable/Disable HTTP Authentification");
3704 	SETPREF ("http.authtok", "r2admin:r2admin", "HTTP Authentification user:password token");
3705 	p = r_sys_getenv ("R2_HTTP_AUTHFILE");
3706 	SETPREF ("http.authfile", r_str_get (p), "HTTP Authentification user file");
3707 	tmpdir = r_file_tmpdir ();
3708 	r_config_set (cfg, "http.uproot", tmpdir);
3709 	free (tmpdir);
3710 	r_config_desc (cfg, "http.uproot", "Path where files are uploaded");
3711 
3712 	/* tcp */
3713 	SETBPREF ("tcp.islocal", "false", "Bind a loopback for tcp command server");
3714 
3715 	/* graph */
3716 	SETBPREF ("graph.aeab", "false", "Show aeab info on each basic block instead of disasm");
3717 	SETBPREF ("graph.trace", "false", "Fold all non-traced basic blocks");
3718 	SETBPREF ("graph.dummy", "true", "Create dummy nodes in the graph for better layout (20% slower)");
3719 	SETBPREF ("graph.few", "false", "Show few basic blocks in the graph");
3720 	SETBPREF ("graph.comments", "true", "Show disasm comments in graph");
3721 	SETBPREF ("graph.cmtright", "false", "Show comments at right");
3722 	SETCB ("graph.gv.format", "gif", &cb_graphformat, "Graph image extension when using 'w' format (png, jpg, pdf, ps, svg, json)");
3723 	SETBPREF ("graph.refs", "false", "Graph references in callgraphs (.agc*;aggi)");
3724 	SETBPREF ("graph.json.usenames", "true", "Use names instead of addresses in Global Call Graph (agCj)");
3725 	SETI ("graph.edges", 2, "0=no edges, 1=simple edges, 2=avoid collisions");
3726 	SETI ("graph.layout", 0, "Graph layout (0=vertical, 1=horizontal)");
3727 	SETI ("graph.linemode", 1, "Graph edges (0=diagonal, 1=square)");
3728 	SETPREF ("graph.font", "Courier", "Font for dot graphs");
3729 	SETBPREF ("graph.offset", "false", "Show offsets in graphs");
3730 	SETBPREF ("graph.bytes", "false", "Show opcode bytes in graphs");
3731 	SETBPREF ("graph.web", "false", "Display graph in web browser (VV)");
3732 	SETI ("graph.from", UT64_MAX, "Lower bound address when drawing global graphs");
3733 	SETI ("graph.to", UT64_MAX, "Upper bound address when drawing global graphs");
3734 	SETI ("graph.scroll", 5, "Scroll speed in ascii-art graph");
3735 	SETBPREF ("graph.invscroll", "false", "Invert scroll direction in ascii-art graph");
3736 	SETPREF ("graph.title", "", "Title of the graph");
3737 	SETBPREF ("graph.body", "true", "Show body of the nodes in the graph");
3738 	SETBPREF ("graph.bubble", "false", "Show nodes as bubbles");
3739 	SETBPREF ("graph.ntitles", "true", "Display title of node");
3740 	SETPREF ("graph.gv.node", "", "Graphviz node style. (color=gray, style=filled shape=box)");
3741 	SETPREF ("graph.gv.edge", "", "Graphviz edge style. (arrowhead=\"vee\")");
3742 	SETPREF ("graph.gv.spline", "", "Graphviz spline style. (splines=\"ortho\")");
3743 	SETPREF ("graph.gv.graph", "", "Graphviz global style attributes. (bgcolor=white)");
3744 	SETPREF ("graph.gv.current", "false", "Highlight the current node in graphviz graph.");
3745 	SETBPREF ("graph.nodejmps", "true", "Enables shortcuts for every node.");
3746 	SETBPREF ("graph.hints", "true", "Show true (t) and false (f) hints for conditional edges in graph");
3747 	SETCB ("graph.dotted", "false", &cb_dotted, "Dotted lines for conditional jumps in graph");
3748 
3749 	/* hud */
3750 	SETPREF ("hud.path", "", "Set a custom path for the HUD file");
3751 
3752 	SETCB ("esil.exectrap", "false", &cb_exectrap, "trap when executing code in non-executable memory");
3753 	SETCB ("esil.iotrap", "true", &cb_iotrap, "invalid read or writes produce a trap exception");
3754 	SETBPREF ("esil.romem", "false", "Set memory as read-only for ESIL");
3755 	SETBPREF ("esil.stats", "false", "Statistics from ESIL emulation stored in sdb");
3756 	SETBPREF ("esil.nonull", "false", "Prevent memory read, memory write at null pointer");
3757 	SETCB ("esil.mdev.range", "", &cb_mdevrange, "Specify a range of memory to be handled by cmd.esil.mdev");
3758 
3759 	/* json encodings */
3760 	n = NODECB ("cfg.json.str", "none", &cb_jsonencoding);
3761 	SETDESC (n, "Encode strings from json outputs using the specified option");
3762 	SETOPTIONS (n, "none", "base64", "strip", "hex", "array", NULL);
3763 
3764 	n = NODECB ("cfg.json.num", "none", &cb_jsonencoding_numbers);
3765 	SETDESC (n, "Encode numbers from json outputs using the specified option");
3766 	SETOPTIONS (n, "none", "string", "hex", NULL);
3767 
3768 
3769 	/* scr */
3770 #if __EMSCRIPTEN__
3771 	r_config_set_cb (cfg, "scr.fgets", "true", cb_scrfgets);
3772 #else
3773 	r_config_set_cb (cfg, "scr.fgets", "false", cb_scrfgets);
3774 #endif
3775 	r_config_desc (cfg, "scr.fgets", "Use fgets() instead of dietline for prompt input");
3776 	SETCB ("scr.echo", "false", &cb_screcho, "Show rcons output in realtime to stderr and buffer");
3777 	SETICB ("scr.linesleep", 0, &cb_scrlinesleep, "Flush sleeping some ms in every line");
3778 	SETICB ("scr.maxtab", 4096, &cb_completion_maxtab, "Change max number of auto completion suggestions");
3779 	SETICB ("scr.pagesize", 1, &cb_scrpagesize, "Flush in pages when scr.linesleep is != 0");
3780 	SETCB ("scr.flush", "false", &cb_scrflush, "Force flush to console in realtime (breaks scripting)");
3781 	SETBPREF ("scr.slow", "true", "Do slow stuff on visual mode like RFlag.get_at(true)");
3782 	SETCB ("scr.prompt.popup", "false", &cb_scr_prompt_popup, "Show widget dropdown for autocomplete");
3783 #if __WINDOWS__
3784 	SETICB ("scr.vtmode", r_cons_singleton ()->vtmode,
3785 		&scr_vtmode, "Use VT sequences on Windows (0: Disable, 1: Output, 2: Input & Output)");
3786 #endif
3787 #if __ANDROID__
3788 	SETBPREF ("scr.responsive", "true", "Auto-adjust Visual depending on screen (e.g. unset asm.bytes)");
3789 	SETI ("scr.wheel.speed", 1, "Mouse wheel speed");
3790 #else
3791 	SETBPREF ("scr.responsive", "false", "Auto-adjust Visual depending on screen (e.g. unset asm.bytes)");
3792 	SETI ("scr.wheel.speed", 4, "Mouse wheel speed");
3793 #endif
3794 	SETBPREF ("scr.wheel.nkey", "false", "Use sn/sp and scr.nkey on wheel instead of scroll");
3795 	// RENAME TO scr.mouse
3796 	SETBPREF ("scr.wheel", "true", "Mouse wheel in Visual; temporaryly disable/reenable by right click/Enter)");
3797 	SETBPREF ("scr.cursor", "false", "Keyboard controlled cursor in visual and panels");
3798 	SETPREF ("scr.layout", "", "Name of the selected layout");
3799 	// DEPRECATED: USES hex.cols now SETI ("scr.colpos", 80, "Column position of cmd.cprompt in visual");
3800 	SETCB ("scr.breakword", "", &cb_scrbreakword, "Emulate console break (^C) when a word is printed (useful for pD)");
3801 	SETCB ("scr.breaklines", "false", &cb_breaklines, "Break lines in Visual instead of truncating them");
3802 	SETCB ("scr.gadgets", "true", &cb_scr_gadgets, "Run pg in prompt, visual and panels");
3803 	SETBPREF ("scr.panelborder", "false", "Specify panels border active area (0 by default)");
3804 	SETICB ("scr.columns", 0, &cb_scrcolumns, "Force console column count (width)");
3805 	SETBPREF ("scr.dumpcols", "false", "Prefer pC commands before p ones");
3806 	SETCB ("scr.rows", "0", &cb_scrrows, "Force console row count (height) ");
3807 	SETICB ("scr.rows", 0, &cb_rows, "Force console row count (height) (duplicate?)");
3808 	SETCB ("scr.fps", "false", &cb_fps, "Show FPS in Visual");
3809 	SETICB ("scr.fix.rows", 0, &cb_fixrows, "Workaround for Linux TTY");
3810 	SETICB ("scr.fix.columns", 0, &cb_fixcolumns, "Workaround for Prompt iOS SSH client");
3811 	SETCB ("scr.highlight", "", &cb_scrhighlight, "Highlight that word at RCons level");
3812 	SETCB ("scr.interactive", "true", &cb_scrint, "Start in interactive mode");
3813 	SETCB ("scr.bgfill", "false", &cb_scr_bgfill, "Fill background for ascii art when possible");
3814 	SETI ("scr.feedback", 1, "Set visual feedback level (1=arrow on jump, 2=every key (useful for videos))");
3815 	SETCB ("scr.html", "false", &cb_scrhtml, "Disassembly uses HTML syntax");
3816 	n = NODECB ("scr.nkey", "flag", &cb_scrnkey);
3817 	SETDESC (n, "Select visual seek mode (affects n/N visual commands)");
3818 	SETOPTIONS (n, "fun", "hit", "flag", NULL);
3819 	SETCB ("scr.pager", "", &cb_pager, "System program (or '..') to use when output exceeds screen boundaries");
3820 	SETI ("scr.scrollbar", 0, "Show flagzone (fz) scrollbar in visual mode (0=no,1=right,2=top,3=bottom)");
3821 	SETBPREF ("scr.randpal", "false", "Random color palete or just get the next one from 'eco'");
3822 	SETCB ("scr.highlight.grep", "false", &cb_scr_color_grep_highlight, "Highlight (INVERT) the grepped words");
3823 	SETBPREF ("scr.prompt.file", "false", "Show user prompt file (used by r2 -q)");
3824 	SETBPREF ("scr.prompt.flag", "false", "Show flag name in the prompt");
3825 	SETBPREF ("scr.prompt.sect", "false", "Show section name in the prompt");
3826 	SETBPREF ("scr.tts", "false", "Use tts if available by a command (see ic)");
3827 	SETCB ("scr.hist.block", "true", &cb_scr_histblock, "Use blocks for histogram");
3828 	SETCB ("scr.prompt", "true", &cb_scrprompt, "Show user prompt (used by r2 -q)");
3829 	SETCB ("scr.tee", "", &cb_teefile, "Pipe output to file of this name");
3830 	SETPREF ("scr.seek", "", "Seek to the specified address on startup");
3831 	SETICB ("scr.color", (core->print->flags&R_PRINT_FLAGS_COLOR)?COLOR_MODE_16:COLOR_MODE_DISABLED, &cb_color, "Enable colors (0: none, 1: ansi, 2: 256 colors, 3: truecolor)");
3832 	r_config_set_getter (cfg, "scr.color", (RConfigCallback)cb_color_getter);
3833 	SETCB ("scr.color.grep", "false", &cb_scr_color_grep, "Enable colors when using ~grep");
3834 	SETBPREF ("scr.color.pipe", "false", "Enable colors when using pipes");
3835 	SETBPREF ("scr.color.ops", "true", "Colorize numbers and registers in opcodes");
3836 	SETBPREF ("scr.color.args", "true", "Colorize arguments and variables of functions");
3837 	SETBPREF ("scr.color.bytes", "true", "Colorize bytes that represent the opcodes of the instruction");
3838 	SETCB ("scr.null", "false", &cb_scrnull, "Show no output");
3839 	SETCB ("scr.errmode", "echo", &cb_screrrmode, "Error string handling");
3840 	SETCB ("scr.utf8", r_str_bool (r_cons_is_utf8()), &cb_utf8, "Show UTF-8 characters instead of ANSI");
3841 	SETCB ("scr.utf8.curvy", "false", &cb_utf8_curvy, "Show curved UTF-8 corners (requires scr.utf8)");
3842 	SETBPREF ("scr.demo", "false", "Use demoscene effects if available");
3843 	SETBPREF ("scr.histsave", "true", "Always save history on exit");
3844 	n = NODECB ("scr.strconv", "asciiesc", &cb_scrstrconv);
3845 	SETDESC (n, "Convert string before display");
3846 	SETOPTIONS (n, "asciiesc", "asciidot", NULL);
3847 	SETBPREF ("scr.confirmquit", "false", "Confirm on quit");
3848 	SETBPREF ("scr.progressbar", "false", "Display a progress bar when running scripts.");
3849 
3850 	/* str */
3851 	SETCB ("str.escbslash", "false", &cb_str_escbslash, "Escape the backslash");
3852 
3853 	/* search */
3854 	SETCB ("search.contiguous", "true", &cb_contiguous, "Accept contiguous/adjacent search hits");
3855 	SETBPREF ("search.verbose", "true", "Make the output of search commands verbose");
3856 	SETICB ("search.align", 0, &cb_searchalign, "Only catch aligned search hits");
3857 	SETI ("search.chunk", 0, "Chunk size for /+ (default size is asm.bits/8");
3858 	SETI ("search.esilcombo", 8, "Stop search after N consecutive hits");
3859 	SETI ("search.distance", 0, "Search string distance");
3860 	SETBPREF ("search.flags", "true", "All search results are flagged, otherwise only printed");
3861 	SETBPREF ("search.overlap", "false", "Look for overlapped search hits");
3862 	SETI ("search.maxhits", 0, "Maximum number of hits (0: no limit)");
3863 	SETI ("search.from", -1, "Search start address");
3864 	n = NODECB ("search.in", "io.maps", &cb_searchin);
3865 	SETDESC (n, "Specify search boundaries");
3866 	SETOPTIONS (n, "raw", "block",
3867 		"bin.section", "bin.sections", "bin.sections.rwx", "bin.sections.r", "bin.sections.rw", "bin.sections.rx", "bin.sections.wx", "bin.sections.x",
3868 		"io.map", "io.maps", "io.maps.rwx", "io.maps.r", "io.maps.rw", "io.maps.rx", "io.maps.wx", "io.maps.x",
3869 		"dbg.stack", "dbg.heap",
3870 		"dbg.map", "dbg.maps", "dbg.maps.rwx", "dbg.maps.r", "dbg.maps.rw", "dbg.maps.rx", "dbg.maps.wx", "dbg.maps.x",
3871 		"anal.fcn", "anal.bb",
3872 	NULL);
3873 	SETICB ("search.kwidx", 0, &cb_search_kwidx, "Store last search index count");
3874 	SETPREF ("search.prefix", "hit", "Prefix name in search hits label");
3875 	SETBPREF ("search.show", "true", "Show search results");
3876 	SETI ("search.to", -1, "Search end address");
3877 
3878 	/* rop */
3879 	SETI ("rop.len", 5, "Maximum ROP gadget length");
3880 	SETBPREF ("rop.sdb", "false", "Cache results in sdb (experimental)");
3881 	SETBPREF ("rop.db", "true", "Categorize rop gadgets in sdb");
3882 	SETBPREF ("rop.subchains", "false", "Display every length gadget from rop.len=X to 2 in /Rl");
3883 	SETBPREF ("rop.conditional", "false", "Include conditional jump, calls and returns in ropsearch");
3884 	SETBPREF ("rop.comments", "false", "Display comments in rop search output");
3885 
3886 	/* io */
3887 	SETCB ("io.cache", "false", &cb_io_cache, "Change both of io.cache.{read,write}");
3888 	SETCB ("io.cache.auto", "false", &cb_io_cache_mode, "Automatic cache all reads in the IO backend");
3889 	SETCB ("io.cache.read", "false", &cb_io_cache_read, "Enable read cache for vaddr (or paddr when io.va=0)");
3890 	SETCB ("io.cache.write", "false", &cb_io_cache_write, "Enable write cache for vaddr (or paddr when io.va=0)");
3891 	SETCB ("io.pcache", "false", &cb_iopcache, "io.cache for p-level");
3892 	SETCB ("io.pcache.write", "false", &cb_iopcachewrite, "Enable write-cache");
3893 	SETCB ("io.pcache.read", "false", &cb_iopcacheread, "Enable read-cache");
3894 	SETCB ("io.ff", "true", &cb_ioff, "Fill invalid buffers with 0xff instead of returning error");
3895 	SETBPREF ("io.exec", "true", "See !!r2 -h~-x");
3896 	SETICB ("io.0xff", 0xff, &cb_io_oxff, "Use this value instead of 0xff to fill unallocated areas");
3897 	SETCB ("io.aslr", "false", &cb_ioaslr, "Disable ASLR for spawn and such");
3898 	SETCB ("io.va", "true", &cb_iova, "Use virtual address layout");
3899 	SETCB ("io.pava", "false", &cb_io_pava, "Use EXPERIMENTAL paddr -> vaddr address mode");
3900 	SETCB ("io.autofd", "true", &cb_ioautofd, "Change fd when opening a new file");
3901 	SETCB ("io.unalloc", "false", &cb_io_unalloc, "Check each byte if it's allocated");
3902 	SETCB ("io.unalloc.ch", ".", &cb_io_unalloc_ch, "Char to display if byte is unallocated");
3903 
3904 	/* file */
3905 	SETBPREF ("file.info", "true", "RBin info loaded");
3906 	SETPREF ("file.offset", "", "Offset where the file will be mapped at");
3907 	SETPREF ("file.type", "", "Type of current file");
3908 	SETI ("file.loadalign", 1024, "Alignment of load addresses");
3909 	SETI ("file.openmany", 1, "Maximum number of files opened at once");
3910 	/* magic */
3911 	SETI ("magic.depth", 100, "Recursivity depth in magic description strings");
3912 
3913 	/* rap */
3914 	SETBPREF ("rap.loop", "true", "Run rap as a forever-listening daemon (=:9090)");
3915 
3916 	/* nkeys */
3917 	SETPREF ("key.s", "", "override step into action");
3918 	SETPREF ("key.S", "", "override step over action");
3919 	for (i = 1; i < 13; i++) {
3920 		snprintf (buf, sizeof (buf), "key.f%d", i);
3921 		snprintf (buf + 10, sizeof (buf) - 10,
3922 				"Run this when F%d key is pressed in visual mode", i);
3923 		switch (i) {
3924 			default: p = ""; break;
3925 		}
3926 		r_config_set (cfg, buf, p);
3927 		r_config_desc (cfg, buf, buf+10);
3928 	}
3929 
3930 	/* zoom */
3931 	SETCB ("zoom.byte", "h", &cb_zoombyte, "Zoom callback to calculate each byte (See pz? for help)");
3932 	SETI ("zoom.from", 0, "Zoom start address");
3933 	SETI ("zoom.maxsz", 512, "Zoom max size of block");
3934 	SETI ("zoom.to", 0, "Zoom end address");
3935 	n = NODECB ("zoom.in", "io.map", &cb_searchin);
3936 	SETDESC (n, "Specify boundaries for zoom");
3937 	SETOPTIONS (n, "raw", "block",
3938 		"bin.section", "bin.sections", "bin.sections.rwx", "bin.sections.r", "bin.sections.rw", "bin.sections.rx", "bin.sections.wx", "bin.sections.x",
3939 		"io.map", "io.maps", "io.maps.rwx", "io.maps.r", "io.maps.rw", "io.maps.rx", "io.maps.wx", "io.maps.x",
3940 		"dbg.stack", "dbg.heap",
3941 		"dbg.map", "dbg.maps", "dbg.maps.rwx", "dbg.maps.r", "dbg.maps.rw", "dbg.maps.rx", "dbg.maps.wx", "dbg.maps.x",
3942 		"anal.fcn", "anal.bb",
3943 	NULL);
3944 	/* lines */
3945 	SETI ("lines.from", 0, "Start address for line seek");
3946 	SETCB ("lines.to", "$s", &cb_linesto, "End address for line seek");
3947 	SETCB ("lines.abs", "false", &cb_linesabs, "Enable absolute line numbers");
3948 
3949 	r_config_lock (cfg, true);
3950 	return true;
3951 }
3952 
r_core_parse_radare2rc(RCore * r)3953 R_API void r_core_parse_radare2rc(RCore *r) {
3954 	bool has_debug = r_sys_getenv_asbool ("R2_DEBUG");
3955 	char *rcfile = r_sys_getenv ("R2_RCFILE");
3956 	char *homerc = NULL;
3957 	if (!R_STR_ISEMPTY (rcfile)) {
3958 		homerc = rcfile;
3959 	} else {
3960 		free (rcfile);
3961 		homerc = r_str_home (".radare2rc");
3962 	}
3963 	if (homerc && r_file_is_regular (homerc)) {
3964 		if (has_debug) {
3965 			eprintf ("USER CONFIG loaded from %s\n", homerc);
3966 		}
3967 		r_core_cmd_file (r, homerc);
3968 	}
3969 	free (homerc);
3970 	homerc = r_str_home (R2_HOME_RC);
3971 	if (homerc && r_file_is_regular (homerc)) {
3972 		if (has_debug) {
3973 			eprintf ("USER CONFIG loaded from %s\n", homerc);
3974 		}
3975 		r_core_cmd_file (r, homerc);
3976 	}
3977 	free (homerc);
3978 	homerc = r_str_home (R2_HOME_RC_DIR);
3979 	if (homerc) {
3980 		if (r_file_is_directory (homerc)) {
3981 			char *file;
3982 			RListIter *iter;
3983 			RList *files = r_sys_dir (homerc);
3984 			r_list_foreach (files, iter, file) {
3985 					if (*file != '.') {
3986 						char *path = r_str_newf ("%s/%s", homerc, file);
3987 						if (r_file_is_regular (path)) {
3988 							if (has_debug) {
3989 								eprintf ("USER CONFIG loaded from %s\n", homerc);
3990 							}
3991 							r_core_cmd_file (r, path);
3992 						}
3993 						free (path);
3994 					}
3995 				}
3996 			r_list_free (files);
3997 		}
3998 		free (homerc);
3999 	}
4000 }
4001 
r_core_config_update(RCore * core)4002 R_API void r_core_config_update(RCore *core) {
4003 	RConfigNode *cmdpdc = r_config_node_get (core->config, "cmd.pdc");
4004 	update_cmdpdc_options (core, cmdpdc);
4005 }
4006