1 /* radare2 - LGPL - Copyright 2009-2020 - pancake */
2 
3 #include <r_core.h>
4 #include <r_socket.h>
5 #include <config.h>
6 #include <r_util.h>
7 #if __UNIX__
8 #include <signal.h>
9 #endif
10 
11 #define DB core->sdb
12 
13 R_LIB_VERSION(r_core);
14 
15 static ut64 letter_divs[R_CORE_ASMQJMPS_LEN_LETTERS - 1] = {
16 	R_CORE_ASMQJMPS_LETTERS * R_CORE_ASMQJMPS_LETTERS * R_CORE_ASMQJMPS_LETTERS * R_CORE_ASMQJMPS_LETTERS,
17 	R_CORE_ASMQJMPS_LETTERS * R_CORE_ASMQJMPS_LETTERS * R_CORE_ASMQJMPS_LETTERS,
18 	R_CORE_ASMQJMPS_LETTERS * R_CORE_ASMQJMPS_LETTERS,
19 	R_CORE_ASMQJMPS_LETTERS
20 };
21 
22 extern bool r_core_is_project (RCore *core, const char *name);
23 
on_fcn_new(RAnal * _anal,void * _user,RAnalFunction * fcn)24 static int on_fcn_new(RAnal *_anal, void* _user, RAnalFunction *fcn) {
25 	RCore *core = (RCore*)_user;
26 	const char *cmd = r_config_get (core->config, "cmd.fcn.new");
27 	if (cmd && *cmd) {
28 		ut64 oaddr = core->offset;
29 		ut64 addr = fcn->addr;
30 		r_core_seek (core, addr, true);
31 		r_core_cmd0 (core, cmd);
32 		r_core_seek (core, oaddr, true);
33 	}
34 	return 0;
35 }
36 
on_fcn_delete(RAnal * _anal,void * _user,RAnalFunction * fcn)37 static int on_fcn_delete(RAnal *_anal, void* _user, RAnalFunction *fcn) {
38 	RCore *core = (RCore*)_user;
39 	const char *cmd = r_config_get (core->config, "cmd.fcn.delete");
40 	if (cmd && *cmd) {
41 		ut64 oaddr = core->offset;
42 		ut64 addr = fcn->addr;
43 		r_core_seek (core, addr, true);
44 		r_core_cmd0 (core, cmd);
45 		r_core_seek (core, oaddr, true);
46 	}
47 	return 0;
48 }
49 
on_fcn_rename(RAnal * _anal,void * _user,RAnalFunction * fcn,const char * oname)50 static int on_fcn_rename(RAnal *_anal, void* _user, RAnalFunction *fcn, const char *oname) {
51 	RCore *core = (RCore*)_user;
52 	const char *cmd = r_config_get (core->config, "cmd.fcn.rename");
53 	if (cmd && *cmd) {
54 		// XXX: wat do with old name here?
55 		ut64 oaddr = core->offset;
56 		ut64 addr = fcn->addr;
57 		r_core_seek (core, addr, true);
58 		r_core_cmd0 (core, cmd);
59 		r_core_seek (core, oaddr, true);
60 	}
61 	return 0;
62 }
63 
r_core_debug_breakpoint_hit(RCore * core,RBreakpointItem * bpi)64 static void r_core_debug_breakpoint_hit(RCore *core, RBreakpointItem *bpi) {
65 	const char *cmdbp = r_config_get (core->config, "cmd.bp");
66 	const bool cmdbp_exists = (cmdbp && *cmdbp);
67 	const bool bpcmd_exists = (bpi->data && bpi->data[0]);
68 	const bool may_output = (cmdbp_exists || bpcmd_exists);
69 	if (may_output) {
70 		r_cons_push ();
71 	}
72 	if (cmdbp_exists) {
73 		r_core_cmd0 (core, cmdbp);
74 	}
75 	if (bpcmd_exists) {
76 		r_core_cmd0 (core, bpi->data);
77 	}
78 	if (may_output) {
79 		r_cons_flush ();
80 		r_cons_pop ();
81 	}
82 }
83 
r_core_debug_syscall_hit(RCore * core)84 static void r_core_debug_syscall_hit(RCore *core) {
85 	const char *cmdhit = r_config_get (core->config, "cmd.onsyscall");
86 
87 	if (cmdhit && cmdhit[0] != 0) {
88 		r_core_cmd0 (core, cmdhit);
89 		r_cons_flush ();
90 	}
91 }
92 
93 struct getreloc_t {
94         ut64 vaddr;
95         int size;
96 };
97 
getreloc_tree(const void * user,const RBNode * n,void * user2)98 static int getreloc_tree(const void *user, const RBNode *n, void *user2) {
99         struct getreloc_t *gr = (struct getreloc_t *)user;
100         const RBinReloc *r = container_of (n, const RBinReloc, vrb);
101         if ((r->vaddr >= gr->vaddr) && (r->vaddr < (gr->vaddr + gr->size))) {
102                 return 0;
103         }
104         if (gr->vaddr > r->vaddr) {
105                 return 1;
106         }
107         if (gr->vaddr < r->vaddr) {
108                 return -1;
109         }
110         return 0;
111 }
112 
r_core_getreloc(RCore * core,ut64 addr,int size)113 R_API RBinReloc *r_core_getreloc(RCore *core, ut64 addr, int size) {
114         if (size < 1 || addr == UT64_MAX) {
115                 return NULL;
116         }
117         RBNode *relocs = r_bin_get_relocs (core->bin);
118         if (!relocs) {
119                 return NULL;
120         }
121         struct getreloc_t gr = { .vaddr = addr, .size = size };
122         RBNode *res = r_rbtree_find (relocs, &gr, getreloc_tree, NULL);
123         return res? container_of (res, RBinReloc, vrb): NULL;
124 }
125 
126 /* returns the address of a jmp/call given a shortcut by the user or UT64_MAX
127  * if there's no valid shortcut. When is_asmqjmps_letter is true, the string
128  * should be of the form XYZWu, where XYZW are uppercase letters and u is a
129  * lowercase one. If is_asmqjmps_letter is false, the string should be a number
130  * between 1 and 9 included. */
r_core_get_asmqjmps(RCore * core,const char * str)131 R_API ut64 r_core_get_asmqjmps(RCore *core, const char *str) {
132 	if (!core->asmqjmps) {
133 		return UT64_MAX;
134 	}
135 	if (core->is_asmqjmps_letter) {
136 		int i, pos = 0;
137 		int len = strlen (str);
138 		for (i = 0; i < len - 1; i++) {
139 			if (!isupper ((ut8)str[i])) {
140 				return UT64_MAX;
141 			}
142 			pos *= R_CORE_ASMQJMPS_LETTERS;
143 			pos += str[i] - 'A' + 1;
144 		}
145 		if (!islower ((ut8)str[i])) {
146 			return UT64_MAX;
147 		}
148 		pos *= R_CORE_ASMQJMPS_LETTERS;
149 		pos += str[i] - 'a';
150 		if (pos < core->asmqjmps_count) {
151 			return core->asmqjmps[pos + 1];
152 		}
153 	} else if (str[0] > '0' && str[1] <= '9') {
154 		int pos = str[0] - '0';
155 		if (pos <= core->asmqjmps_count) {
156 			return core->asmqjmps[pos];
157 		}
158 	}
159 	return UT64_MAX;
160 }
161 
162 /**
163  * Takes addr and returns already saved shortcut or a new one
164  * The returned buffer needs to be freed
165  */
r_core_add_asmqjmp(RCore * core,ut64 addr)166 R_API char* r_core_add_asmqjmp(RCore *core, ut64 addr) {
167 	bool found = false;
168 	if (!core->asmqjmps) {
169 		return NULL;
170 	}
171 	if (core->is_asmqjmps_letter) {
172 		if (core->asmqjmps_count >= R_CORE_ASMQJMPS_MAX_LETTERS) {
173 			return NULL;
174 		}
175 		if (core->asmqjmps_count >= core->asmqjmps_size - 2) {
176 			core->asmqjmps = realloc (core->asmqjmps, core->asmqjmps_size * 2 * sizeof (ut64));
177 			if (!core->asmqjmps) {
178 				return NULL;
179 			}
180 			core->asmqjmps_size *= 2;
181 		}
182 	}
183 	if (core->asmqjmps_count < core->asmqjmps_size - 1) {
184 		int i = 0;
185 		char t[R_CORE_ASMQJMPS_LEN_LETTERS + 1] = {0};
186 		for (i = 0; i < core->asmqjmps_count + 1; i++) {
187 			if (core->asmqjmps[i] == addr) {
188 				found = true;
189 				break;
190 			}
191 		}
192 		if (!found) {
193 			i = ++core->asmqjmps_count;
194 			core->asmqjmps[i] = addr;
195 		}
196 		// This check makes pos never be <1, thefor not fill 't' with trash
197 		if (i < 1) {
198 			return NULL;
199 		}
200 		r_core_set_asmqjmps (core, t, sizeof (t), i);
201 		return strdup (t);
202 	}
203 	return NULL;
204 }
205 
206 /* returns in str a string that represents the shortcut to access the asmqjmp
207  * at position pos. When is_asmqjmps_letter is true, pos is converted into a
208  * multiletter shortcut of the form XYWZu and returned (see r_core_get_asmqjmps
209  * for more info). Otherwise, the shortcut is the string representation of pos. */
r_core_set_asmqjmps(RCore * core,char * str,size_t len,int pos)210 R_API void r_core_set_asmqjmps(RCore *core, char *str, size_t len, int pos) {
211 	if (core->is_asmqjmps_letter) {
212 		int i, j = 0;
213 		// if (pos > 0) {
214 			pos --;
215 		////  }
216 		for (i = 0; i < R_CORE_ASMQJMPS_LEN_LETTERS - 1; i++) {
217 			int div = pos / letter_divs[i];
218 			pos %= letter_divs[i];
219 			if (div > 0 && j < len) {
220 				str[j++] = 'A' + div - 1;
221 			}
222 		}
223 		if (j < len) {
224 			int div = pos % R_CORE_ASMQJMPS_LETTERS;
225 			str[j++] = 'a' + div;
226 		}
227 		str[j] = '\0';
228 	} else {
229 		snprintf (str, len, "%d", pos);
230 	}
231 }
232 
setab(RCore * core,const char * arch,int bits)233 static void setab(RCore *core, const char *arch, int bits) {
234 	if (arch) {
235 		r_config_set (core->config, "asm.arch", arch);
236 	}
237 	if (bits > 0) {
238 		r_config_set_i (core->config, "asm.bits", bits);
239 	}
240 }
241 
getName(RCore * core,ut64 addr)242 static const char *getName(RCore *core, ut64 addr) {
243 	RFlagItem *item = r_flag_get_i (core->flags, addr);
244 	if (item) {
245 		if (core->flags->realnames) {
246 			return item->realname
247 				? item->realname: item->name;
248 		}
249 		return item->name;
250 	}
251 	return NULL;
252 }
253 
getNameDelta(RCore * core,ut64 addr)254 static char *getNameDelta(RCore *core, ut64 addr) {
255 	RFlagItem *item = r_flag_get_at (core->flags, addr, true);
256 	if (item) {
257 		if (item->offset != addr) {
258 			return r_str_newf ("%s + %d", item->name, (int)(addr - item->offset));
259 		}
260 		return strdup (item->name);
261 	}
262 	return NULL;
263 }
264 
archbits(RCore * core,ut64 addr)265 static void archbits(RCore *core, ut64 addr) {
266 	r_core_seek_arch_bits (core, addr);
267 }
268 
cfggeti(RCore * core,const char * k)269 static int cfggeti(RCore *core, const char *k) {
270 	return r_config_get_i (core->config, k);
271 }
272 
cfgget(RCore * core,const char * k)273 static const char *cfgget(RCore *core, const char *k) {
274 	return r_config_get (core->config, k);
275 }
276 
numget(RCore * core,const char * k)277 static ut64 numget(RCore *core, const char *k) {
278 	return r_num_math (core->num, k);
279 }
280 
__isMapped(RCore * core,ut64 addr,int perm)281 static bool __isMapped(RCore *core, ut64 addr, int perm) {
282 	if (r_config_get_i (core->config, "cfg.debug")) {
283 		// RList *maps = core->dbg->maps;
284 		RDebugMap *map = NULL;
285 		RListIter *iter = NULL;
286 
287 		r_list_foreach (core->dbg->maps, iter, map) {
288 			if (addr >= map->addr && addr < map->addr_end) {
289 				if (perm > 0) {
290 					if (map->perm & perm) {
291 						return true;
292 					}
293 				} else {
294 					return true;
295 				}
296 			}
297 		}
298 		return false;
299 	}
300 
301 	return r_io_map_is_mapped (core->io, addr);
302 }
303 
__syncDebugMaps(RCore * core)304 static bool __syncDebugMaps(RCore *core) {
305 	if (r_config_get_i (core->config, "cfg.debug")) {
306 		return r_debug_map_sync (core->dbg);
307 	}
308 	return false;
309 }
310 
r_core_bind(RCore * core,RCoreBind * bnd)311 R_API int r_core_bind(RCore *core, RCoreBind *bnd) {
312 	bnd->core = core;
313 	bnd->bphit = (RCoreDebugBpHit)r_core_debug_breakpoint_hit;
314 	bnd->syshit = (RCoreDebugSyscallHit)r_core_debug_syscall_hit;
315 	bnd->cmd = (RCoreCmd)r_core_cmd0;
316 	bnd->cmdf = (RCoreCmdF)r_core_cmdf;
317 	bnd->cmdstr = (RCoreCmdStr)r_core_cmd_str;
318 	bnd->cmdstrf = (RCoreCmdStrF)r_core_cmd_strf;
319 	bnd->puts = (RCorePuts)r_cons_strcat;
320 	bnd->setab = (RCoreSetArchBits)setab;
321 	bnd->getName = (RCoreGetName)getName;
322 	bnd->getNameDelta = (RCoreGetNameDelta)getNameDelta;
323 	bnd->archbits = (RCoreSeekArchBits)archbits;
324 	bnd->cfggeti = (RCoreConfigGetI)cfggeti;
325 	bnd->cfgGet = (RCoreConfigGet)cfgget;
326 	bnd->numGet = (RCoreNumGet)numget;
327 	bnd->isMapped = (RCoreIsMapped)__isMapped;
328 	bnd->syncDebugMaps = (RCoreDebugMapsSync)__syncDebugMaps;
329 	bnd->pjWithEncoding = (RCorePJWithEncoding)r_core_pj_new;
330 	return true;
331 }
332 
r_core_ncast(ut64 p)333 R_API RCore *r_core_ncast(ut64 p) {
334 	return (RCore*)(size_t)p;
335 }
336 
r_core_cast(void * p)337 R_API RCore *r_core_cast(void *p) {
338 	return (RCore*)p;
339 }
340 
getref(RCore * core,int n,char t,int type)341 static ut64 getref (RCore *core, int n, char t, int type) {
342 	RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, 0);
343 	RListIter *iter;
344 	RAnalRef *r;
345 	RList *list;
346 	int i = 0;
347 	if (!fcn) {
348 		return UT64_MAX;
349 	}
350 	if (t == 'r') {
351 		list = r_anal_function_get_refs (fcn);
352 	} else {
353 		list = r_anal_function_get_xrefs (fcn);
354 	}
355 	r_list_foreach (list, iter, r) {
356 		if (r->type == type) {
357 			if (i == n) {
358 				ut64 addr = r->addr;
359 				r_list_free (list);
360 				return addr;
361 			}
362 			i++;
363 		}
364 	}
365 	r_list_free (list);
366 
367 	return UT64_MAX;
368 }
369 
bbInstructions(RAnalFunction * fcn,ut64 addr)370 static ut64 bbInstructions(RAnalFunction *fcn, ut64 addr) {
371 	RListIter *iter;
372 	RAnalBlock *bb;
373 	r_list_foreach (fcn->bbs, iter, bb) {
374 		if (R_BETWEEN (bb->addr, addr, bb->addr + bb->size - 1)) {
375 			return bb->ninstr;
376 		}
377 	}
378 	return UT64_MAX;
379 }
380 
bbBegin(RAnalFunction * fcn,ut64 addr)381 static ut64 bbBegin(RAnalFunction *fcn, ut64 addr) {
382 	RListIter *iter;
383 	RAnalBlock *bb;
384 	r_list_foreach (fcn->bbs, iter, bb) {
385 		if (R_BETWEEN (bb->addr, addr, bb->addr + bb->size - 1)) {
386 			return bb->addr;
387 		}
388 	}
389 	return UT64_MAX;
390 }
391 
bbJump(RAnalFunction * fcn,ut64 addr)392 static ut64 bbJump(RAnalFunction *fcn, ut64 addr) {
393 	RListIter *iter;
394 	RAnalBlock *bb;
395 	r_list_foreach (fcn->bbs, iter, bb) {
396 		if (R_BETWEEN (bb->addr, addr, bb->addr + bb->size - 1)) {
397 			return bb->jump;
398 		}
399 	}
400 	return UT64_MAX;
401 }
402 
bbFail(RAnalFunction * fcn,ut64 addr)403 static ut64 bbFail(RAnalFunction *fcn, ut64 addr) {
404 	RListIter *iter;
405 	RAnalBlock *bb;
406 	r_list_foreach (fcn->bbs, iter, bb) {
407 		if (R_BETWEEN (bb->addr, addr, bb->addr + bb->size - 1)) {
408 			return bb->fail;
409 		}
410 	}
411 	return UT64_MAX;
412 }
413 
bbSize(RAnalFunction * fcn,ut64 addr)414 static ut64 bbSize(RAnalFunction *fcn, ut64 addr) {
415 	RListIter *iter;
416 	RAnalBlock *bb;
417 	r_list_foreach (fcn->bbs, iter, bb) {
418 		if (R_BETWEEN (bb->addr, addr, bb->addr + bb->size - 1)) {
419 			return bb->size;
420 		}
421 	}
422 	return 0;
423 }
424 
str_callback(RNum * user,ut64 off,int * ok)425 static const char *str_callback(RNum *user, ut64 off, int *ok) {
426 	RFlag *f = (RFlag*)user;
427 	if (ok) {
428 		*ok = 0;
429 	}
430 	if (f) {
431 		RFlagItem *item = r_flag_get_i (f, off);
432 		if (item) {
433 			if (ok) {
434 				*ok = true;
435 			}
436 			return item->name;
437 		}
438 	}
439 	return NULL;
440 }
441 
numvar_instruction_backward(RCore * core,const char * input)442 static ut64 numvar_instruction_backward(RCore *core, const char *input) {
443 	// N forward instructions
444 	int i, ret;
445 	int n = 1;
446 	if (isdigit ((unsigned char)input[0])) {
447 		n = atoi (input);
448 	} else if (input[0] == '{') {
449 		n = atoi (input + 1);
450 	}
451 	if (n < 1) {
452 		r_cons_eprintf ("Invalid negative value%c", 10);
453 		n = 1;
454 	}
455 	int numinstr = n;
456 	// N previous instructions
457 	ut64 addr = core->offset;
458 	ut64 val = addr;
459 	if (r_core_prevop_addr (core, core->offset, numinstr, &addr)) {
460 		val = addr;
461 	} else {
462 		ut8 data[32];
463 		addr = core->offset;
464 		const int mininstrsize = r_anal_archinfo (core->anal, R_ANAL_ARCHINFO_MIN_OP_SIZE);
465 		for (i = 0; i < numinstr; i++) {
466 			ut64 prev_addr = r_core_prevop_addr_force (core, addr, 1);
467 			if (prev_addr == UT64_MAX) {
468 				prev_addr = addr - mininstrsize;
469 			}
470 			if (prev_addr == UT64_MAX || prev_addr >= core->offset) {
471 				break;
472 			}
473 			RAnalOp op = {0};
474 			ret = r_anal_op (core->anal, &op, prev_addr, data,
475 				sizeof (data), R_ANAL_OP_MASK_BASIC);
476 			if (ret < 1) {
477 				ret = 1;
478 			}
479 			if (op.size < mininstrsize) {
480 				op.size = mininstrsize;
481 			}
482 			val -= op.size;
483 			r_anal_op_fini (&op);
484 			addr = prev_addr;
485 		}
486 	}
487 	return val;
488 }
489 
numvar_instruction(RCore * core,const char * input)490 static ut64 numvar_instruction(RCore *core, const char *input) {
491 	ut64 addr = core->offset;
492 	// N forward instructions
493 	ut8 data[32];
494 	int i, ret;
495 	ut64 val = addr;
496 	int n = 1;
497 	if (input[0] == '{') {
498 		n = atoi (input + 1);
499 	}
500 	if (n < 1) {
501 		r_cons_eprintf ("Invalid negative value%c", 10);
502 		n = 1;
503 	}
504 	for (i = 0; i < n; i++) {
505 		r_io_read_at (core->io, val, data, sizeof (data));
506 		RAnalOp op;
507 		ret = r_anal_op (core->anal, &op, val, data,
508 			sizeof (data), R_ANAL_OP_MASK_BASIC);
509 		if (ret < 1) {
510 			ret = 1;
511 		}
512 		val += op.size;
513 		r_anal_op_fini (&op);
514 		//val += ret;
515 	}
516 	return val;
517 
518 }
519 
num_callback(RNum * userptr,const char * str,int * ok)520 static ut64 num_callback(RNum *userptr, const char *str, int *ok) {
521 	RCore *core = (RCore *)userptr; // XXX ?
522 	RAnalFunction *fcn;
523 	char *ptr, *bptr, *out = NULL;
524 	RFlagItem *flag;
525 	RBinSection *s;
526 	RAnalOp op;
527 	ut64 ret = 0;
528 
529 	if (ok) {
530 		*ok = false;
531 	}
532 	switch (*str) {
533 	case '.':
534 		if (str[1] == '.') {
535 			if (ok) {
536 				*ok = true;
537 			}
538 			return r_num_tail (core->num, core->offset, str + 2);
539 		}
540 		if (core->num->nc.curr_tok == '+') {
541 			ut64 off = core->num->nc.number_value.n;
542 			if (!off) {
543 				off = core->offset;
544 			}
545 			RAnalFunction *fcn = r_anal_get_function_at (core->anal, off);
546 			if (fcn) {
547 				if (ok) {
548 					*ok = true;
549 				}
550 				ut64 dst = r_anal_function_get_label (fcn, str + 1);
551 				if (dst == UT64_MAX) {
552 					dst = fcn->addr;
553 				}
554 				st64 delta = dst - off;
555 				if (delta < 0) {
556 					core->num->nc.curr_tok = '-';
557 					delta = off - dst;
558 				}
559 				return delta;
560 			}
561 		}
562 		break;
563 	case '[':
564 {
565 		ut64 n = 0LL;
566 		int refsz = core->rasm->bits / 8;
567 		const char *p = NULL;
568 		if (strlen (str) > 5) {
569 			p = strchr (str + 5, ':');
570 		}
571 		if (p) {
572 			refsz = atoi (str + 1);
573 			str = p;
574 		}
575 		// push state
576 		if (str[0] && str[1]) {
577 			const char *q;
578 			char *o = strdup (str + 1);
579 			if (o) {
580 				q = r_num_calc_index (core->num, NULL);
581 				if (q) {
582 					if (r_str_replace_char (o, ']', 0)>0) {
583 						n = r_num_math (core->num, o);
584 						if (core->num->nc.errors) {
585 							return 0;
586 						}
587 						r_num_calc_index (core->num, q);
588 					}
589 				}
590 				free (o);
591 			}
592 		} else {
593 			return 0;
594 		}
595 		// pop state
596 		if (ok) {
597 			*ok = 1;
598 		}
599 		ut8 buf[sizeof (ut64)] = R_EMPTY;
600 		(void)r_io_read_at (core->io, n, buf, R_MIN (sizeof (buf), refsz));
601 		switch (refsz) {
602 		case 8:
603 			return r_read_ble64 (buf, core->print->big_endian);
604 		case 4:
605 			return r_read_ble32 (buf, core->print->big_endian);
606 		case 2:
607 			return r_read_ble16 (buf, core->print->big_endian);
608 		case 1:
609 			return r_read_ble8 (buf);
610 		default:
611 			r_cons_eprintf ("Invalid reference size: %d (%s)\n", refsz, str);
612 			return 0LL;
613 		}
614 }
615 		break;
616 	case '$':
617 		if (ok) {
618 			*ok = 1;
619 		}
620 		// TODO: group analop-dependant vars after a char, so i can filter
621 		r_anal_op (core->anal, &op, core->offset, core->block, core->blocksize, R_ANAL_OP_MASK_BASIC);
622 		r_anal_op_fini (&op); // we don't need strings or pointers, just values, which are not nullified in fini
623 		// XXX the above line is assuming op after fini keeps jump, fail, ptr, val, size and r_anal_op_is_eob()
624 		switch (str[1]) {
625 		case 'i': // "$i"
626 			if (ok) {
627 				*ok = true;
628 			}
629 			return numvar_instruction (core, str + 2);
630 		case 'I': // "$I"
631 			if (ok) {
632 				*ok = true;
633 			}
634 			return numvar_instruction_backward (core, str + 2);
635 		case '.': // can use pc, sp, a0, a1, ...
636 			return r_debug_reg_get (core->dbg, str + 2);
637 		case 'k': // $k{kv}
638 			if (str[2] != '{') {
639 				r_cons_eprintf ("Expected '{' after 'k'.\n");
640 				break;
641 			}
642 			bptr = strdup (str + 3);
643 			ptr = strchr (bptr, '}');
644 			if (!ptr) {
645 				// invalid json
646 				free (bptr);
647 				break;
648 			}
649 			*ptr = '\0';
650 			ret = 0LL;
651 			out = sdb_querys (core->sdb, NULL, 0, bptr);
652 			if (out && *out) {
653 				if (strstr (out, "$k{")) {
654 					r_cons_eprintf ("Recursivity is not permitted here\n");
655 				} else {
656 					ret = r_num_math (core->num, out);
657 				}
658 			}
659 			free (bptr);
660 			free (out);
661 			return ret;
662 		case '{': // ${ev} eval var
663 			bptr = strdup (str + 2);
664 			ptr = strchr (bptr, '}');
665 			if (ptr) {
666 				ptr[0] = '\0';
667 				ut64 ret = r_config_get_i (core->config, bptr);
668 				free (bptr);
669 				return ret;
670 			}
671 			// take flag here
672 			free (bptr);
673 			break;
674 		case 'c': // $c console width
675 			return r_cons_get_size (NULL);
676 		case 'd': // $d - same as 'op'
677 			if (core->io && core->io->desc) {
678 				return core->io->desc->fd;
679 			}
680 			return 0;
681 		case 'r': // $r
682 			if (str[2] == '{') {
683 				bptr = strdup (str + 3);
684 				ptr = strchr (bptr, '}');
685 				if (!ptr) {
686 					free (bptr);
687 					break;
688 				}
689 				*ptr = 0;
690 				if (r_config_get_i (core->config, "cfg.debug")) {
691 					if (r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, false)) {
692 						RRegItem *r = r_reg_get (core->dbg->reg, bptr, -1);
693 						if (r) {
694 							free (bptr);
695 							return r_reg_get_value (core->dbg->reg, r);
696 						}
697 					}
698 				} else {
699 					RRegItem *r = r_reg_get (core->anal->reg, bptr, -1);
700 					if (r) {
701 						free (bptr);
702 						return r_reg_get_value (core->anal->reg, r);
703 					}
704 				}
705 				free (bptr);
706 				return 0; // UT64_MAX;
707 			} else {
708 				int rows;
709 				(void)r_cons_get_size (&rows);
710 				return rows;
711 			}
712 			break;
713 		case 'e': // $e
714 			if (str[2] == '{') { // $e{flag} flag off + size
715 				char *flagName = strdup (str + 3);
716 				int flagLength = strlen (flagName);
717 				if (flagLength > 0) {
718 					flagName[flagLength - 1] = 0;
719 				}
720 				RFlagItem *flag = r_flag_get (core->flags, flagName);
721 				free (flagName);
722 				if (flag) {
723 					return flag->offset + flag->size;
724 				}
725 				return UT64_MAX;
726 			}
727 			return r_anal_op_is_eob (&op);
728 		case 'j': // $j jump address
729 			return op.jump;
730 		case 'p': // $p
731 			return r_sys_getpid ();
732 		case 'P': // $P
733 			return core->dbg->pid > 0 ? core->dbg->pid : 0;
734 		case 'f': // $f jump fail address
735 			if (str[2] == 'l') { // $fl flag length
736 				RFlagItem *fi = r_flag_get_i (core->flags, core->offset);
737 				if (fi) {
738 					return fi->size;
739 				}
740 				return 0;
741 			}
742 			return op.fail;
743 		case 'm': // $m memref
744 			return op.ptr;
745 		case 'B': // $B base address
746 		case 'M': { // $M map address
747 				ut64 lower = UT64_MAX;
748 				ut64 size = 0LL;
749 				RIOMap *map = r_io_map_get (core->io, core->offset);
750 				if (map) {
751 					lower = r_io_map_begin (map);
752 					size = r_io_map_size (map);
753 				}
754 
755 				if (str[1] == 'B') {
756 					/* clear lower bits of the lowest map address to define the base address */
757 					const int clear_bits = 16;
758 					lower >>= clear_bits;
759 					lower <<= clear_bits;
760 				}
761 				if (str[2] == 'M') {
762 					return size;
763 				}
764 				return (lower == UT64_MAX)? 0LL: lower;
765 			}
766 			break;
767 		case 'v': // $v immediate value
768 			return op.val;
769 		case 'l': // $l opcode length
770 			return op.size;
771 		case 'b': // $b
772 			return core->blocksize;
773 		case 's': // $s file size
774 			if (str[2] == '{') { // $s{flag} flag size
775 				bptr = strdup (str + 3);
776 				ptr = strchr (bptr, '}');
777 				if (!ptr) {
778 					// invalid json
779 					free (bptr);
780 					break;
781 				}
782 				*ptr = '\0';
783 				RFlagItem *flag = r_flag_get (core->flags, bptr);
784 				ret = flag? flag->size: 0LL; // flag
785 				free (bptr);
786 				free (out);
787 				return ret;
788 			} else if (core->io->desc) {
789 				return r_io_fd_size (core->io, core->io->desc->fd);
790 			}
791 			return 0LL;
792 		case 'w': // $w word size
793 			return r_config_get_i (core->config, "asm.bits") / 8;
794 		case 'S': // $S section offset
795 			{
796 				RBinObject *bo = r_bin_cur_object (core->bin);
797 				if (bo && (s = r_bin_get_section_at (bo, core->offset, true))) {
798 					return (str[2] == 'S'? s->size: s->vaddr);
799 				}
800 			}
801 			return 0LL;
802 		case 'D': // $D
803 			if (str[2] == 'B') { // $DD
804 				return r_debug_get_baddr (core->dbg, NULL);
805 			} else if (IS_DIGIT (str[2])) {
806 				return getref (core, atoi (str + 2), 'r', R_ANAL_REF_TYPE_DATA);
807 			} else {
808 				RDebugMap *map;
809 				RListIter *iter;
810 				r_list_foreach (core->dbg->maps, iter, map) {
811 					if (core->offset >= map->addr && core->offset < map->addr_end) {
812 						return (str[2] == 'D')? map->size: map->addr;
813 					}
814 				}
815 			}
816 			return 0LL; // maybe // return UT64_MAX;
817 		case '?': // $?
818 			return core->num->value; // rc;
819 		case '$': // $$ offset
820 			return str[2] == '$' ? core->prompt_offset : core->offset;
821 		case 'o': { // $o
822 			RBinSection *s = r_bin_get_section_at (r_bin_cur_object (core->bin), core->offset, true);
823 			return s ? core->offset - s->vaddr + s->paddr : core->offset;
824 			break;
825 		}
826 		case 'O': // $O
827 			  if (core->print->cur_enabled) {
828 				  return core->offset + core->print->cur;
829 			  }
830 			  return core->offset;
831 		case 'C': // $C nth call
832 			return getref (core, atoi (str + 2), 'r', R_ANAL_REF_TYPE_CALL);
833 		case 'J': // $J nth jump
834 			return getref (core, atoi (str + 2), 'r', R_ANAL_REF_TYPE_CODE);
835 		case 'X': // $X nth xref
836 			return getref (core, atoi (str + 2), 'x', R_ANAL_REF_TYPE_CALL);
837 		case 'F': // $F function size
838 			fcn = r_anal_get_fcn_in (core->anal, core->offset, 0);
839 			if (fcn) {
840 				switch (str[2]) {
841 				/* function bounds (uppercase) */
842 				case 'B': return fcn->addr; // begin
843 				case 'E': return r_anal_function_max_addr (fcn); // end
844 				case 'S': return (str[3]=='S') ? r_anal_function_realsize (fcn) : r_anal_function_linear_size (fcn);
845 				case 'I': return fcn->ninstr;
846 				/* basic blocks (lowercase) */
847 				case 'b': return bbBegin (fcn, core->offset);
848 				case 'e': return bbBegin (fcn, core->offset) + bbSize (fcn, core->offset);
849 				case 'i': return bbInstructions (fcn, core->offset);
850 				case 's': return bbSize (fcn, core->offset);
851 				case 'j': return bbJump (fcn, core->offset); // jump
852 				case 'f': return bbFail (fcn, core->offset); // fail
853 				}
854 				return fcn->addr;
855 			}
856 			return 0;
857 		default:
858 			r_cons_eprintf ("Invalid variable '%s'\n", str);
859 			return 0;
860 		}
861 		break;
862 	default:
863 		if (*str >= 'A' || *str == ':' || *str == '_') {
864 			// NOTE: functions override flags
865 			RAnalFunction *fcn = r_anal_get_function_byname (core->anal, str);
866 			if (fcn) {
867 				if (ok) {
868 					*ok = true;
869 				}
870 				return fcn->addr;
871 			}
872 #if 0
873 			ut64 addr = r_anal_fcn_label_get (core->anal, core->offset, str);
874 			if (addr != 0) {
875 				ret = addr;
876 			} else {
877 				...
878 			}
879 #endif
880 			if ((flag = r_flag_get (core->flags, str))) {
881 				ret = flag->offset;
882 				if (ok) {
883 					*ok = true;
884 				}
885 				return ret;
886 			}
887 
888 			// check for reg alias
889 			struct r_reg_item_t *r = r_reg_get (core->dbg->reg, str, -1);
890 			if (!r) {
891 				int role = r_reg_get_name_idx (str);
892 				if (role != -1) {
893 					const char *alias = r_reg_get_name (core->dbg->reg, role);
894 					if (alias) {
895 						r = r_reg_get (core->dbg->reg, alias, -1);
896 						if (r) {
897 							if (ok) {
898 								*ok = true;
899 							}
900 							ret = r_reg_get_value (core->dbg->reg, r);
901 							return ret;
902 						}
903 					}
904 				}
905 			} else {
906 				if (ok) {
907 					*ok = true;
908 				}
909 				ret = r_reg_get_value (core->dbg->reg, r);
910 				return ret;
911 			}
912 		}
913 		break;
914 	}
915 
916 	return ret;
917 }
918 
r_core_new(void)919 R_API RCore *r_core_new(void) {
920 	RCore *c = R_NEW0 (RCore);
921 	if (c) {
922 		r_core_init (c);
923 	}
924 	return c;
925 }
926 
927 /*-----------------------------------*/
928 #define radare_argc (sizeof (radare_argv) / sizeof(const char*) - 1)
929 #define ms_argc (sizeof (ms_argv) / sizeof (const char*) - 1)
930 static const char *ms_argv[] = {
931 	"?", "!", "ls", "cd", "cat", "get", "mount", "help", "q", "exit", NULL
932 };
933 
934 static const char *radare_argv[] = {
935 	"whereis", "which", "ls", "rm", "mkdir", "pwd", "cat", "sort", "uniq", "join", "less", "exit", "quit",
936 	"#?", "#!", "#sha1", "#crc32", "#pcprint", "#sha256", "#sha512", "#md4", "#md5",
937 	"#!python", "#!vala", "#!pipe",
938 	"*?", "*", "$",
939 	"(", "(*", "(-", "()", ".?", ".", "..", "...", ".:", ".--", ".-", ".!", ".(", "./", ".*",
940 	"_?", "_",
941 	"=?", "=", "=<", "=!", "=+", "=-", "==", "=!=", "!=!", "=:", "=&:",
942 	"=g?", "=g", "=g!", "=h?", "=h", "=h-", "=h--", "=h*", "=h&", "=H?", "=H", "=H&",
943 	"<",
944 	"/?", "/", "/j", "/j!", "/j!x", "/+", "//", "/a", "/a1", "/ab", "/ad", "/aa", "/as", "/asl", "/at", "/atl", "/af", "/afl", "/ae", "/aej", "/ai", "/aij",
945 	"/c", "/ca", "/car", "/d", "/e", "/E", "/Ej", "/f", "/F", "/g", "/gg", "/h", "/ht", "/i", "/m", "/mb", "/mm",
946 	"/o", "/O", "/p", "/P", "/s", "/s*", "/r?", "/r", "/ra", "/rc", "/re", "/rr", "/rw", "/rc",
947 	"/R",
948 	"/v?", "/v", "/v1", "/v2", "/v4", "/v8",
949 	"/V?", "/V", "/V1", "/V2", "/V4", "/V8",
950 	"/w", "/wi", "/x", "/z",
951 	"!?", "!", "!!", "!!!", "!!!-", "!-", "!-*", "!=!",
952 	"a?", "a", "aa", "aa*",
953 	"aaa", "aab", "aac", "aac*", "aad", "aae", "aaf", "aaF", "aaFa", "aai", "aaij", "aan", "aang", "aao", "aap",
954 	"aar?", "aar", "aar*", "aarj", "aas", "aat", "aaT", "aau", "aav",
955 	"a8", "ab", "abb",
956 	"acl", "acll", "aclj", "acl*", "ac?", "ac", "ac-", "acn", "acv", "acvf", "acv-", "acb", "acb-", "acm", "acm-", "acmn",
957 	"aC?", "aC", "aCe", "ad", "ad4", "ad8", "adf", "adfg", "adt", "adk",
958 	"ae?", "ae??", "ae", "aea", "aeA", "aeaf", "aeAf", "aeC", "aec?", "aec", "aecs", "aecc", "aecu", "aecue",
959 	"aef", "aefa",
960 	"aei", "aeim", "aeip", "aek", "aek-", "aeli", "aelir", "aep?", "aep", "aep-", "aepc",
961 	"aer", "aets?", "aets+", "aets-", "aes", "aesp", "aesb", "aeso", "aesou", "aess", "aesu", "aesue", "aetr", "aex",
962 	"af?", "af", "afr", "af+", "af-",
963 	"afa", "afan",
964 	"afb?", "afb", "afb.", "afb+", "afbb", "afbr", "afbi", "afbj", "afbe", "afB", "afbc", "afb=",
965 	"afB", "afC", "afCl", "afCc", "afc?", "afc", "afcr", "afcrj", "afca", "afcf", "afcfj",
966 	"afck", "afcl", "afco", "afcR",
967 	"afd", "aff", "afF", "afi",
968 	"afl?", "afl", "afl+", "aflc", "aflj", "afll", "afllj", "aflm", "aflq", "aflqj", "afls",
969 	"afm", "afM", "afn?", "afna", "afns", "afnsj", "afl=",
970 	"afo", "afs", "afS", "aft?", "aft", "afu",
971 	"afv?", "afv", "afvr?", "afvr", "afvr*", "afvrj", "afvr-", "afvrg", "afvrs",
972 	"afvb?", "afvb", "afvbj", "afvb-", "afvbg", "afvbs",
973 	"afvs?", "afvs", "afvs*", "afvsj", "afvs-", "afvsg", "afvss",
974 	"afv*", "afvR", "afvW", "afva", "afvd", "afvn", "afvt", "afv-", "af*", "afx",
975 	"aF",
976 	"ag?", "ag", "aga", "agA", "agc", "agC", "agd", "agf", "agi", "agr", "agR", "agx", "agg", "ag-",
977 	"agn?", "agn", "agn-", "age?", "age", "age-",
978 	"agl", "agfl",
979 	"ah?", "ah", "ah.", "ah-", "ah*", "aha", "ahb", "ahc", "ahe", "ahf", "ahh", "ahi?", "ahi", "ahj", "aho",
980 	"ahp", "ahr", "ahs", "ahS", "aht",
981 	"ai", "aL", "an",
982 	"ao?", "ao", "aoj", "aoe", "aor", "aos", "aom", "aod", "aoda", "aoc", "ao*",
983 	"aO", "ap",
984 	"ar?", "ar", "ar0", "ara?", "ara", "ara+", "ara-", "aras", "arA", "arC", "arr", "arrj", "ar=",
985 	"arb", "arc", "ard", "arn", "aro", "arp?", "arp", "arpi", "arpg", "arp.", "arpj", "arps",
986 	"ars", "art", "arw",
987 	"as?", "as", "asc", "asca", "asf", "asj", "asl", "ask",
988 	"av?", "av", "avj", "av*", "avr", "avra", "avraj", "avrr", "avrD",
989 	"at",
990 	"ax?", "ax", "ax*", "ax-", "ax-*", "axc", "axC", "axg", "axg*", "axgj", "axd", "axw", "axj", "axF",
991 	"axt", "axf", "ax.", "axff", "axffj", "axs",
992 	"b?", "b", "b+", "b-", "bf", "bm",
993 	"c?", "c", "c1", "c2", "c4", "c8", "cc", "ccd", "cf", "cg?", "cg", "cgf", "cgff", "cgfc", "cgfn", "cgo",
994 	"cu?", "cu", "cu1", "cu2", "cu4", "cu8", "cud",
995 	"cv", "cv1", "cv2", "cv4", "cv8",
996 	"cV", "cV1", "cV2", "cV4", "cV8",
997 	"cw?", "cw", "cw*", "cwr", "cwu",
998 	"cx", "cx*", "cX",
999 	"cl", "cls", "clear",
1000 	"d?", "db ", "db-", "db-*", "db.", "dbj", "dbc", "dbC", "dbd", "dbe", "dbs", "dbf", "dbm", "dbn",
1001 	"db?", "dbi", "dbi.", "dbix", "dbic", "dbie", "dbid", "dbis", "dbite", "dbitd", "dbits", "dbh", "dbh-",
1002 	"dbt", "dbt*", "dbt=", "dbtv", "dbtj", "dbta", "dbte", "dbtd", "dbts", "dbx", "dbw",
1003 	"dc?", "dc", "dca", "dcb", "dcc", "dccu", "dcf", "dck", "dcp", "dcr", "dcs", "dcs*", "dct", "dcu", "dcu.",
1004 	"dd?", "dd", "dd-", "dd*", "dds", "ddd", "ddr", "ddw",
1005 	"de",
1006 	"dg",
1007 	"dH",
1008 	"di?", "di", "di*", "diq", "dij",
1009 	"dk?", "dk", "dko", "dkj",
1010 	"dL?", "dL", "dLq", "dLj",
1011 	"dm?", "dm", "dm=", "dm.", "dm*", "dm-", "dmd",
1012 	"dmh?", "dmh", "dmha", "dmhb", "dmhbg", "dmhc", "dmhf", "dmhg", "dmhi", "dmhm", "dmht",
1013 	"dmi?", "dmi", "dmi*", "dmi.", "dmiv",
1014 	"dmj",
1015 	"dml?", "dml",
1016 	"dmm?", "dmm", "dmm*", "dmm.", "dmmj",
1017 	"dmp?", "dmp",
1018 	"dms?", "dms", "dmsj", "dms*", "dms-", "dmsA", "dmsC", "dmsd", "dmsw", "dmsa", "dmsf", "dmst",
1019 	"dmS", "dmS*",
1020 	"do?", "do", "dor", "doo",
1021 	"dp?", "dp", "dpj", "dpl", "dplj", "dp-", "dp=", "dpa", "dpc", "dpc*", "dpe", "dpf", "dpk", "dpn", "dptn", "dpt",
1022 	"dr?", "dr", "drps", "drpj", "drr", "drrj", "drs", "drs+", "drs-", "drt", "drt*", "drtj", "drw", "drx", "drx-",
1023 	".dr*", ".dr-",
1024 	"ds?", "ds", "dsb", "dsf", "dsi", "dsl", "dso", "dsp", "dss", "dsu", "dsui", "dsuo", "dsue", "dsuf",
1025 	"dt?", "dt", "dt%", "dt*", "dt+", "dt-", "dt=", "dtD", "dta", "dtc", "dtd", "dte", "dte-*", "dtei", "dtek",
1026 	"dtg", "dtg*", "dtgi",
1027 	"dtr",
1028 	"dts?", "dts", "dts+", "dts-", "dtsf", "dtst", "dtsC", "dtt",
1029 	"dw",
1030 	"dx?", "dx", "dxa", "dxe", "dxr", "dxs",
1031 	"e?", "e", "e-", "e*", "e!", "ec", "ee?", "ee", "?ed", "ed", "ej", "env", "er", "es", "et", "ev", "evj",
1032 	"ec?", "ec", "ec*", "ecd", "ecr", "ecs", "ecj", "ecc", "eco", "ecp", "ecn",
1033 	"ecH?", "ecH", "ecHi", "ecHw", "ecH-",
1034 	"f?", "f", "f.", "f*", "f-", "f--", "f+", "f=", "fa", "fb", "fc?", "fc", "fC", "fd", "fe-", "fe",
1035 	"ff", "fi", "fg", "fj",
1036 	"fl", "fla", "fm", "fn", "fnj", "fo", "fO", "fr", "fR", "fR?",
1037 	"fs?", "fs", "fs*", "fsj", "fs-", "fs+", "fs-.", "fsq", "fsm", "fss", "fss*", "fssj", "fsr",
1038 	"ft?", "ft", "ftn", "fV", "fx", "fq",
1039 	"fz?", "fz", "fz-", "fz.", "fz:", "fz*",
1040 	"g?", "g", "gw", "gc", "gl?", "gl", "gs", "gi", "gp", "ge", "gr", "gS",
1041 	"i?", "i", "ij", "iA", "ia", "ib", "ic", "icc", "iC",
1042 	"id?", "id", "idp", "idpi", "idpi*", "idpd", "iD", "ie", "iee", "iE", "iE.",
1043 	"ih", "iHH", "ii", "iI", "ik", "il", "iL", "im", "iM", "io", "iO?", "iO",
1044 	"ir", "iR", "is", "is.", "iS", "iS.", "iS=", "iSS",
1045 	"it", "iV", "iX", "iz", "izj", "izz", "izzz", "iz-", "iZ",
1046 	"k?", "k", "ko", "kd", "ks", "kj",
1047 	"l",
1048 	"L?", "L", "L-", "Ll", "LL", "La", "Lc", "Ld", "Lh", "Li", "Lo",
1049 	"m?", "m", "m*", "ml", "m-", "md", "mf?", "mf", "mg", "mo", "mi", "mp", "ms", "my",
1050 	"o?", "o", "o-", "o--", "o+", "oa", "oa-", "oq", "o*", "o.", "o=",
1051 	"ob?", "ob", "ob*", "obo", "oba", "obf", "obj", "obr", "ob-", "ob-*",
1052 	"oc", "of", "oi", "oj", "oL", "om", "on",
1053 	"oo?", "oo", "oo+", "oob", "ood", "oom", "oon", "oon+", "oonn", "oonn+",
1054 	"op",  "opn", "opp", "opr", "ox",
1055 	"p?", "p-", "p=", "p2", "p3", "p6?", "p6", "p6d", "p6e", "p8?", "p8", "p8f", "p8j",
1056 	"pa?", "paD", "pad", "pade", "pae", "pA",
1057 	"pb?", "pb", "pB", "pxb", "pB?",
1058 	"pc?", "pc", "pc*", "pca", "pcA", "pcd", "pch", "pcj", "pcp", "pcs", "pcS", "pcw",
1059 	"pC?", "pC", "pCa", "pCA", "pCc", "pCd", "pCD", "pCx", "pCw",
1060 	"pd?", "pd", "pd--", "pD", "pda", "pdb", "pdc", "pdC", "pdf", "pdi", "pdj", "pdJ",
1061 	"pdk", "pdl", "pdp", "pdr", "pdr.", "pdR", "pds?", "pds", "pdsb", "pdsf", "pdt",
1062 	"pD",
1063 	"pf?", "pf", "pf??", "pf???", "pf.", "pfj", "pfj.", "pf*", "pf*.", "pfd", "pfd.",
1064 	"pfo", "pfq", "pfv", "pfv.", "pfs", "pfs.",
1065 	"pF?", "pF", "pFa", "pFaq", "pFo", "pFp", "pFx",
1066 	"pg?", "pg", "pg*", "pg-*",
1067 	"ph?", "ph", "ph=",
1068 	"pi?", "pi", "pia", "pib", "pid", "pie", "pif?", "pif", "pifc", "pifcj", "pifj", "pij", "pir",
1069 	"pI?", "pI", "pIa", "pIb", "pId", "pIe", "pIf?", "pIf", "pIfc", "pIfcj", "pIfj", "pIj",	"pIr",
1070 	"pj?", "pj", "pj.", "pj..",
1071 	"pk?", "pk", "pK?", "pK",
1072 	"pm?", "pm",
1073 	"pq?", "pq", "pqi", "pqz",
1074 	"pr?", "pr", "prc", "prl", "prx", "prg?", "prg", "prgi", "prgo", "prz",
1075 	"ps?", "ps", "psb", "psi", "psj", "psp", "pss", "psu", "psw", "psW", "psx", "psz", "ps+",
1076 	"pt?", "pt", "pt.", "ptd", "pth", "ptn",
1077 	"pu?", "pu", "puw", "pU",
1078 	"pv?", "pv", "pv1", "pv2", "pv4", "pv8", "pvz", "pvj", "pvh", "pv1j", "pv2j", "pv4j", "pv8j",
1079 	"pv1h", "pv2h", "pv4h", "pv8h",
1080 	"px?", "px", "px/", "px0", "pxa", "pxA?", "pxA", "pxb", "pxc", "pxd?", "pxd", "pxd2", "pxd4", "pxd8",
1081 	"pxe", "pxf", "pxh", "pxH", "pxi", "pxl", "pxo", "pxq", "pxq", "pxQ", "pxQq", "pxr", "pxrj",
1082 	"pxs", "pxt", "pxt*", "pxt.", "pxw", "pxW", "pxWq", "pxx", "pxX",
1083 	"pz?", "pz", "pzp", "pzf", "pzs", "pz0", "pzF", "pze", "pzh",
1084 	"P?", "P", "Pc", "Pd", "Pi", "Pn", "Pnj", "Po", "Ps", "PS", "P-",
1085 	"q?", "q", "q!", "q!!", "q!!!", "qy", "qn", "qyy", "qyn", "qny", "qnn",
1086 	"r?", "r", "r-", "r+", "rh",
1087 	"s?", "s", "s:", "s-", "s-*", "s--", "s+", "s++", "sj", "s*", "s=", "s!", "s/", "s/x", "s.", "sa", "sb",
1088 	"sC?", "sC", "sC*",
1089 	"sf", "sf.", "sg", "sG", "sl?", "sl", "sl+", "sl-", "slc", "sll", "sn", "sp", "so", "sr", "ss",
1090 	"t?", "t", "tj", "t*", "t-", "t-*", "ta", "tb", "tc", "te?", "te", "tej", "teb", "tec",
1091 	"td?", "td", "td-", "tf", "tk", "tl", "tn", "to", "tos", "tp", "tpx", "ts?", "ts", "tsj", "ts*", "tsc", "tss",
1092 	"tu?", "tu", "tuj", "tu*", "tuc", "tt?", "tt", "ttj", "ttc",
1093 	"T?", "T", "T*", "T-", "Tl", "Tj", "Tm", "Ts", "TT", "T=", "T=.", "T=&",
1094 	"u?", "u", "uw", "us", "uc",
1095 	"v", "V", "v!", "vv", "vV", "vVV", "VV",
1096 	"w?", "w", "w1+", "w1-", "w2+", "w2-", "w4+", "w4-", "w8+", "w8-",
1097 	"w0", "w", "w6", "w6d", "w6e", "wa", "wa*", "waf", "wao?", "wao",
1098 	"wA?", "wA", "wB", "wB-", "wc", "wcj", "wc-", "wc+", "wc*", "wcr", "wci", "wcp", "wcp*", "wcpi",
1099 	"wd", "we?", "we", "wen", "weN", "wes", "wex", "weX",
1100 	"wf?", "wf", "wff", "wfs", "wF", "wh", "wm",
1101 	"wo?", "wo", "wo2", "wo4", "woa", "woA", "wod", "woD", "woe", "woE", "wol", "wom", "woo",
1102 	"wop?", "wop", "wopD", "wopD*", "wopO",
1103 	"wp?", "wp", "wr", "ws",
1104 	"wt?", "wt", "wta", "wtf", "wtf!", "wtff", "wts",
1105 	"wu",
1106 	"wv?", "wv", "wv1", "wv2",  "wv4", "wv8",
1107 	"ww",
1108 	"wx?", "wx", "wxf", "wxs",
1109 	"wz",
1110 	"x?", "x", "x/", "x0", "xa", "xA?", "xA", "xb", "xc", "xd?", "xd", "xd2", "xd4", "xd8",
1111 	"xe", "xf", "xh", "xH", "xi", "xl", "xo", "xq", "xq", "xQ", "xQq", "xr", "xrj",
1112 	"xs", "xt", "xt*", "xt.", "xw", "xW", "xWq", "xx", "xX",
1113 	"y?", "y", "yz", "yp", "yx", "ys", "yt", "ytf", "yf", "yfa", "yfx", "yw", "ywx", "yy",
1114 	"z?", "z", "z*", "zj", "z-", "z-*",
1115 	"za?", "za??", "za", "zaf", "zaF", "zg",
1116 	"zo?", "zo", "zoz", "zos",
1117 	"zf?", "zfd", "zfs", "zfz",
1118 	"z/?", "z/", "z/*",
1119 	"zc",
1120 	"zs?", "zs", "zs-", "zs-*", "zs+", "zsr",
1121 	"zi",
1122 	"?", "?v", "?$?", "?@?", "?>?",
1123 	NULL
1124 };
1125 
autocomplete_mount_point(RLineCompletion * completion,RCore * core,const char * path)1126 static void autocomplete_mount_point (RLineCompletion *completion, RCore *core, const char *path) {
1127 	RFSRoot *r;
1128 	RListIter *iter;
1129 	r_list_foreach (core->fs->roots, iter, r) {
1130 		char *base = strdup (r->path);
1131 		char *ls = (char *) r_str_lchr (base, '/');
1132 		if (ls) {
1133 			ls++;
1134 			*ls = 0;
1135 		}
1136 		if (!strcmp (path, base)) {
1137 			r_line_completion_push (completion, r->path);
1138 		}
1139 		free (base);
1140 	}
1141 }
1142 
autocomplete_ms_path(RLineCompletion * completion,RCore * core,const char * str,const char * path)1143 static void autocomplete_ms_path(RLineCompletion *completion, RCore *core, const char *str, const char *path) {
1144 	char *lpath = NULL, *dirname = NULL , *basename = NULL;
1145 	char *p = NULL;
1146 	char *pwd = (core->rfs && *(core->rfs->cwd)) ? *(core->rfs->cwd): ".";
1147 	int n = 0;
1148 	RList *list;
1149 	RListIter *iter;
1150 	RFSFile *file;
1151 	r_return_if_fail (path);
1152 	lpath = r_str_new (path);
1153 	p = (char *)r_str_last (lpath, R_SYS_DIR);
1154 	if (p) {
1155 		*p = 0;
1156 		if (p == lpath) { // /xxx
1157 			dirname  = r_str_new ("/");
1158 		} else if (lpath[0] == '.') { // ./xxx/yyy
1159 			dirname = r_str_newf ("%s%s", pwd, R_SYS_DIR);
1160 		} else if (lpath[0] == '/') { // /xxx/yyy
1161       			dirname = r_str_newf ("%s%s", lpath, R_SYS_DIR);
1162     		} else { // xxx/yyy
1163       			if (strlen (pwd) == 1) { // if pwd is root
1164         			dirname = r_str_newf ("%s%s%s", R_SYS_DIR, lpath, R_SYS_DIR);
1165       			} else {
1166 				dirname = r_str_newf ("%s%s%s%s", pwd, R_SYS_DIR, lpath, R_SYS_DIR);
1167       			}
1168 		}
1169 		basename = r_str_new (p + 1);
1170 	} else { // xxx
1171     		if (strlen (pwd) == 1) {
1172       			dirname = r_str_newf ("%s", R_SYS_DIR);
1173     		} else {
1174       			dirname = r_str_newf ("%s%s", pwd, R_SYS_DIR);
1175     		}
1176 		basename = r_str_new (lpath);
1177 	}
1178 
1179 	if (!dirname || !basename) {
1180 		goto out;
1181 	}
1182 	list= r_fs_dir (core->fs, dirname);
1183 	n = strlen (basename);
1184 	bool chgdir = !strncmp (str, "cd ", 3);
1185 	if (list) {
1186 		r_list_foreach (list, iter, file) {
1187 			if (!file) {
1188 				continue;
1189 			}
1190 			if (!basename[0] || !strncmp (file->name, basename, n))  {
1191 				char *tmpstring = r_str_newf ("%s%s", dirname, file->name);
1192 				if (r_file_is_directory (tmpstring)) {
1193 					char *s = r_str_newf ("%s/", tmpstring);
1194 					r_line_completion_push (completion, s);
1195 					free (s);
1196 				} else if (!chgdir) {
1197 					r_line_completion_push (completion, tmpstring);
1198 				}
1199 				free (tmpstring);
1200 			}
1201 		}
1202 		r_list_free (list);
1203 	}
1204 	autocomplete_mount_point (completion, core, path);
1205 out:
1206 	free (lpath);
1207 	free (dirname);
1208 	free (basename);
1209 }
1210 
autocomplete_process_path(RLineCompletion * completion,const char * str,const char * path)1211 static void autocomplete_process_path(RLineCompletion *completion, const char *str, const char *path) {
1212 	char *lpath = NULL, *dirname = NULL , *basename = NULL;
1213 	char *home = NULL, *filename = NULL, *p = NULL;
1214 	int n = 0;
1215 	RList *list;
1216 	RListIter *iter;
1217 
1218 	if (!path) {
1219 		goto out;
1220 	}
1221 
1222 	lpath = r_str_new (path);
1223 #if __WINDOWS__
1224 	r_str_replace_ch (lpath, '/', '\\', true);
1225 #endif
1226 	p = (char *)r_str_last (lpath, R_SYS_DIR);
1227 	if (p) {
1228 		*p = 0;
1229 		if (p == lpath) { // /xxx
1230 #if __WINDOWS__
1231 			dirname = strdup ("\\.\\");
1232 #else
1233 			dirname = r_str_new (R_SYS_DIR);
1234 #endif
1235 		} else if (lpath[0] == '~' && lpath[1]) { // ~/xxx/yyy
1236 			dirname = r_str_home (lpath + 2);
1237 		} else if (lpath[0] == '~') { // ~/xxx
1238 			if (!(home = r_str_home (NULL))) {
1239 				goto out;
1240 			}
1241 			dirname = r_str_newf ("%s%s", home, R_SYS_DIR);
1242 			free (home);
1243 		} else if (lpath[0] == '.' || lpath[0] == R_SYS_DIR[0] ) { // ./xxx/yyy || /xxx/yyy
1244 			dirname = r_str_newf ("%s%s", lpath, R_SYS_DIR);
1245 		} else { // xxx/yyy
1246 			char *fmt = ".%s%s%s";
1247 #if __WINDOWS__
1248 			if (strchr (path, ':')) {
1249 				fmt = "%.0s%s%s";
1250 			}
1251 #endif
1252 			dirname = r_str_newf (fmt, R_SYS_DIR, lpath, R_SYS_DIR);
1253 		}
1254 		basename = r_str_new (p + 1);
1255 	} else { // xxx
1256 		dirname = r_str_newf (".%s", R_SYS_DIR);
1257 		basename = r_str_new (lpath);
1258 	}
1259 
1260 	if (!dirname || !basename) {
1261 		goto out;
1262 	}
1263 
1264 	list= r_sys_dir (dirname);
1265 	n = strlen (basename);
1266 	bool chgdir = !strncmp (str, "cd ", 3);
1267 	if (list) {
1268 		r_list_foreach (list, iter, filename) {
1269 			if (*filename == '.') {
1270 				continue;
1271 			}
1272 			if (!basename[0] || !strncmp (filename, basename, n))  {
1273 				char *tmpstring = r_str_newf ("%s%s", dirname, filename);
1274 				if (r_file_is_directory (tmpstring)) {
1275 					char *s = r_str_newf ("%s%s", tmpstring, R_SYS_DIR);
1276 					r_line_completion_push (completion, s);
1277 					free (s);
1278 				} else if (!chgdir) {
1279 					r_line_completion_push (completion, tmpstring);
1280 				}
1281 				free (tmpstring);
1282 			}
1283 		}
1284 		r_list_free (list);
1285 	}
1286 out:
1287 	free (lpath);
1288 	free (dirname);
1289 	free (basename);
1290 }
1291 
autocompleteFilename(RLineCompletion * completion,RLineBuffer * buf,char ** extra_paths,int narg)1292 static void autocompleteFilename(RLineCompletion *completion, RLineBuffer *buf, char **extra_paths, int narg) {
1293 	char *args = NULL, *input = NULL;
1294 	int n = 0, i = 0;
1295 	char *pipe = strchr (buf->data, '>');
1296 	if (pipe) {
1297 		args = r_str_new (pipe + 1);
1298 	} else {
1299 		args = r_str_new (buf->data);
1300 	}
1301 	if (!args) {
1302 		goto out;
1303 	}
1304 
1305 	n = r_str_word_set0 (args);
1306 	if (n < narg) {
1307 		goto out;
1308 	}
1309 
1310 	input = r_str_new (r_str_word_get0 (args, narg));
1311 	if (!input) {
1312 		goto out;
1313 	}
1314 	const char *tinput = r_str_trim_head_ro (input);
1315 
1316 	autocomplete_process_path (completion, buf->data, tinput);
1317 
1318 	if (input[0] == '/' || input[0] == '.' || !extra_paths) {
1319 		goto out;
1320 	}
1321 
1322 	for (i = 0; extra_paths[i]; i ++) {
1323 		char *s = r_str_newf ("%s%s%s", extra_paths[i], R_SYS_DIR, tinput);
1324 		if (!s) {
1325 			break;
1326 		}
1327 		autocomplete_process_path (completion, buf->data, s);
1328 		free (s);
1329 	}
1330 out:
1331 	free (args);
1332 	free (input);
1333 }
1334 
1335 //TODO: make it recursive to handle nested struct
autocomplete_pfele(RCore * core,RLineCompletion * completion,char * key,char * pfx,int idx,char * ptr)1336 static int autocomplete_pfele (RCore *core, RLineCompletion *completion, char *key, char *pfx, int idx, char *ptr) {
1337 	int i, ret = 0;
1338 	int len = strlen (ptr);
1339 	char* fmt = sdb_get (core->print->formats, key, NULL);
1340 	if (fmt) {
1341 		int nargs = r_str_word_set0_stack (fmt);
1342 		if (nargs > 1) {
1343 			for (i = 1; i < nargs; i++) {
1344 				const char *arg = r_str_word_get0 (fmt, i);
1345 				char *p = strchr (arg, '(');
1346 				char *p2 = strchr (arg, ')');
1347 				// remove '(' and ')' from fmt
1348 				if (p && p2) {
1349 					arg = p + 1;
1350 					*p2 = '\0';
1351 				}
1352 				if (!len || !strncmp (ptr, arg, len)) {
1353 					char *s = r_str_newf ("pf%s.%s.%s", pfx, key, arg);
1354 					r_line_completion_push (completion, s);
1355 					free (s);
1356 				}
1357 			}
1358 		}
1359 	}
1360 	free (fmt);
1361 	return ret;
1362 }
1363 
1364 #define ADDARG(x) if (!strncmp (buf->data+chr, x, strlen (buf->data+chr))) { r_line_completion_push (completion, x); }
1365 
autocomplete_default(R_NULLABLE RCore * core,RLineCompletion * completion,RLineBuffer * buf)1366 static void autocomplete_default(R_NULLABLE RCore *core, RLineCompletion *completion, RLineBuffer *buf) {
1367 	RCoreAutocomplete *a = core ? core->autocomplete : NULL;
1368 	int i;
1369 	if (a) {
1370 		for (i = 0; i < a->n_subcmds; i++) {
1371 			if (buf->data[0] == 0 || !strncmp (a->subcmds[i]->cmd, buf->data, a->subcmds[i]->length)) {
1372 				r_line_completion_push (completion, a->subcmds[i]->cmd);
1373 			}
1374 		}
1375 	} else {
1376 		for (i = 0; i < radare_argc && radare_argv[i]; i++) {
1377 			int length = strlen (radare_argv[i]);
1378 			if (!strncmp (radare_argv[i], buf->data, length)) {
1379 				r_line_completion_push (completion, radare_argv[i]);
1380 			}
1381 		}
1382 	}
1383 }
1384 
autocomplete_evals(RCore * core,RLineCompletion * completion,const char * str)1385 static void autocomplete_evals(RCore *core, RLineCompletion *completion, const char *str) {
1386 	r_return_if_fail (str);
1387 	RConfigNode *bt;
1388 	RListIter *iter;
1389 	const char *tmp = strrchr (str, ' ');
1390 	if (tmp) {
1391 		str = tmp + 1;
1392 	}
1393 	size_t n = strlen (str);
1394 	r_list_foreach (core->config->nodes, iter, bt) {
1395 		if (!strncmp (bt->name, str, n)) {
1396 			r_line_completion_push (completion, bt->name);
1397 		}
1398 	}
1399 }
1400 
autocomplete_project(RCore * core,RLineCompletion * completion,const char * str)1401 static void autocomplete_project(RCore *core, RLineCompletion *completion, const char* str) {
1402 	r_return_if_fail (str);
1403 	char *foo, *projects_path = r_file_abspath (r_config_get (core->config, "dir.projects"));
1404 	RList *list = r_sys_dir (projects_path);
1405 	RListIter *iter;
1406 	int n = strlen (str);
1407 	if (projects_path) {
1408 		r_list_foreach (list, iter, foo) {
1409 			if (r_core_is_project (core, foo)) {
1410 				if (!strncmp (foo, str, n)) {
1411 					r_line_completion_push (completion, foo);
1412 				}
1413 			}
1414 		}
1415 		free (projects_path);
1416 		r_list_free (list);
1417 	}
1418 }
1419 
autocomplete_minus(RCore * core,RLineCompletion * completion,const char * str)1420 static void autocomplete_minus(RCore *core, RLineCompletion *completion, const char *str) {
1421 	r_return_if_fail (str);
1422 	int count;
1423 	int length = strlen (str);
1424 	char **keys = r_cmd_alias_keys(core->rcmd, &count);
1425 	if (!keys) {
1426 		return;
1427 	}
1428 	int i;
1429 	for (i = 0; i < count; i++) {
1430 		if (!strncmp (keys[i], str, length)) {
1431 			r_line_completion_push (completion, keys[i]);
1432 		}
1433 	}
1434 }
1435 
autocomplete_breakpoints(RCore * core,RLineCompletion * completion,const char * str)1436 static void autocomplete_breakpoints(RCore *core, RLineCompletion *completion, const char *str) {
1437 	r_return_if_fail (str);
1438 	RListIter *iter;
1439 	RBreakpoint *bp = core->dbg->bp;
1440 	RBreakpointItem *b;
1441 	int n = strlen (str);
1442 	r_list_foreach (bp->bps, iter, b) {
1443 		char *addr = r_str_newf ("0x%"PFMT64x"", b->addr);
1444 		if (!strncmp (addr, str, n)) {
1445 			r_line_completion_push (completion, addr);
1446 		}
1447 		free (addr);
1448 	}
1449 }
1450 
add_argv(RFlagItem * fi,void * user)1451 static bool add_argv(RFlagItem *fi, void *user) {
1452 	RLineCompletion *completion = user;
1453 	r_line_completion_push (completion, fi->name);
1454 	return true;
1455 }
1456 
autocomplete_flags(RCore * core,RLineCompletion * completion,const char * str)1457 static void autocomplete_flags(RCore *core, RLineCompletion *completion, const char* str) {
1458 	r_return_if_fail (str);
1459 	int n = strlen (str);
1460 	r_flag_foreach_prefix (core->flags, str, n, add_argv, completion);
1461 }
1462 
1463 // TODO: Should be refactored
autocomplete_sdb(RCore * core,RLineCompletion * completion,const char * str)1464 static void autocomplete_sdb (RCore *core, RLineCompletion *completion, const char *str) {
1465 	r_return_if_fail (core && completion && str);
1466 	char *pipe = strchr (str, '>');
1467 	Sdb *sdb = core->sdb;
1468 	char *lpath = NULL, *p1 = NULL, *out = NULL, *p2 = NULL;
1469 	char *cur_pos = NULL, *cur_cmd = NULL, *next_cmd = NULL;
1470 	char *temp_cmd = NULL, *temp_pos = NULL, *key = NULL;
1471 	if (pipe) {
1472 		str = r_str_trim_head_ro (pipe + 1);
1473 	}
1474 	lpath = r_str_new (str);
1475 	p1 = strchr (lpath, '/');
1476 	if (p1) {
1477 		*p1 = 0;
1478 		char *ns = p1 + 1;
1479 		p2 = strchr (ns, '/');
1480 		if (!p2) { // anal/m
1481 			char *tmp = p1 + 1;
1482 			int n = strlen (tmp);
1483 			out = sdb_querys (sdb, NULL, 0, "anal/**");
1484 			if (!out) {
1485 				return;
1486 			}
1487 			while (*out) {
1488 				cur_pos = strchr (out, '\n');
1489 				if (!cur_pos) {
1490 					break;
1491 				}
1492 				cur_cmd = r_str_ndup (out, cur_pos - out);
1493 				if (!strncmp (tmp, cur_cmd, n)) {
1494 					char *cmplt = r_str_newf ("anal/%s/", cur_cmd);
1495 					r_line_completion_push (completion, cmplt);
1496 					free (cmplt);
1497 				}
1498 				out += cur_pos - out + 1;
1499 			}
1500 
1501 		} else { // anal/meta/*
1502 			char *tmp = p2 + 1;
1503 			int n = strlen (tmp);
1504 			char *spltr = strchr (ns, '/');
1505 			*spltr = 0;
1506 			next_cmd = r_str_newf ("anal/%s/*", ns);
1507 			out = sdb_querys (sdb, NULL, 0, next_cmd);
1508 			if (!out) {
1509 				free (lpath);
1510 				return;
1511 			}
1512 			while (*out) {
1513 				temp_pos = strchr (out, '\n');
1514 				if (!temp_pos) {
1515 					break;
1516 				}
1517 				temp_cmd = r_str_ndup (out, temp_pos - out); // contains the key=value pair
1518 				key = strchr (temp_cmd, '=');
1519 				*key = 0;
1520 				if (!strncmp (tmp, temp_cmd, n)) {
1521 					char *cmplt = r_str_newf ("anal/%s/%s", ns, temp_cmd);
1522 					r_line_completion_push (completion, cmplt);
1523 					free (cmplt);
1524 				}
1525 				out += temp_pos - out + 1;
1526 			}
1527 		}
1528 	} else {
1529 		int n = strlen (lpath);
1530 		if (!strncmp (lpath, "anal", n)) {
1531 			r_line_completion_push (completion, "anal/");
1532 		}
1533 	}
1534 }
1535 
autocomplete_zignatures(RCore * core,RLineCompletion * completion,const char * msg)1536 static void autocomplete_zignatures(RCore *core, RLineCompletion *completion, const char* msg) {
1537 	r_return_if_fail (msg);
1538 	int length = strlen (msg);
1539 	RSpaces *zs = &core->anal->zign_spaces;
1540 	RSpace *s;
1541 	RSpaceIter it;
1542 
1543 	r_spaces_foreach (zs, it, s) {
1544 		if (!strncmp (msg, s->name, length)) {
1545 			r_line_completion_push (completion, s->name);
1546 		}
1547 	}
1548 
1549 	if (strlen (msg) == 0) {
1550 		r_line_completion_push (completion, "*");
1551 	}
1552 }
1553 
autocomplete_flagspaces(RCore * core,RLineCompletion * completion,const char * msg)1554 static void autocomplete_flagspaces(RCore *core, RLineCompletion *completion, const char* msg) {
1555 	r_return_if_fail (msg);
1556 	int length = strlen (msg);
1557 	RFlag *flag = core->flags;
1558 	RSpaceIter it;
1559 	RSpace *s;
1560 	r_flag_space_foreach (flag, it, s) {
1561 		if (!strncmp (msg, s->name, length)) {
1562 			r_line_completion_push (completion, s->name);
1563 		}
1564 	}
1565 
1566 	if (strlen (msg) == 0) {
1567 		r_line_completion_push (completion, "*");
1568 	}
1569 }
1570 
autocomplete_functions(RCore * core,RLineCompletion * completion,const char * str)1571 static void autocomplete_functions (RCore *core, RLineCompletion *completion, const char* str) {
1572 	r_return_if_fail (str);
1573 	RListIter *iter;
1574 	RAnalFunction *fcn;
1575 	int n = strlen (str);
1576 	r_list_foreach (core->anal->fcns, iter, fcn) {
1577 		char *name = r_core_anal_fcn_name (core, fcn);
1578 		if (!strncmp (name, str, n)) {
1579 			r_line_completion_push (completion, name);
1580 		}
1581 		free (name);
1582 	}
1583 }
1584 
autocomplete_macro(RCore * core,RLineCompletion * completion,const char * str)1585 static void autocomplete_macro(RCore *core, RLineCompletion *completion, const char *str) {
1586 	r_return_if_fail (core && core->rcmd && completion && str);
1587 	RCmdMacroItem *item;
1588 	RListIter *iter;
1589 	size_t n = strlen (str);
1590 	r_list_foreach (core->rcmd->macro.macros, iter, item) {
1591 		char *p = item->name;
1592 		if (!*str || !strncmp (str, p, n)) {
1593 			char *buf = r_str_newf ("%s%s)", str, p);
1594 			if (buf) {
1595 				r_line_completion_push (completion, buf);
1596 				free (buf);
1597 			}
1598 		}
1599 	}
1600 }
1601 
autocomplete_file(RLineCompletion * completion,const char * str)1602 static void autocomplete_file(RLineCompletion *completion, const char *str) {
1603 	r_return_if_fail (str);
1604 	char *pipe = strchr (str, '>');
1605 
1606 	if (pipe) {
1607 		str = r_str_trim_head_ro (pipe + 1);
1608 	}
1609 	if (str && !*str) {
1610 		autocomplete_process_path (completion, str, "./");
1611 	} else {
1612 		autocomplete_process_path (completion, str, str);
1613 	}
1614 
1615 }
1616 
autocomplete_ms_file(RCore * core,RLineCompletion * completion,const char * str)1617 static void autocomplete_ms_file(RCore* core, RLineCompletion *completion, const char *str) {
1618 	r_return_if_fail (str);
1619 	char *pipe = strchr (str, '>');
1620 	char *path = (core->rfs && *(core->rfs->cwd)) ? *(core->rfs->cwd): "/";
1621 	if (pipe) {
1622 		str = r_str_trim_head_ro (pipe + 1);
1623 	}
1624 	if (str && !*str) {
1625 		autocomplete_ms_path (completion, core, str, path);
1626 	} else {
1627 		autocomplete_ms_path (completion, core, str, str);
1628 	}
1629 }
1630 
autocomplete_theme(RCore * core,RLineCompletion * completion,const char * str)1631 static void autocomplete_theme(RCore *core, RLineCompletion *completion, const char *str) {
1632 	r_return_if_fail (str);
1633 	int len = strlen (str);
1634 	char *theme;
1635 	RListIter *iter;
1636 	RList *themes = r_core_list_themes (core);
1637 	r_list_foreach (themes, iter, theme) {
1638 		if (!len || !strncmp (str, theme, len)) {
1639 			r_line_completion_push (completion, theme);
1640 		}
1641 	}
1642 	r_list_free (themes);
1643 }
1644 
find_e_opts(RCore * core,RLineCompletion * completion,RLineBuffer * buf)1645 static bool find_e_opts(RCore *core, RLineCompletion *completion, RLineBuffer *buf) {
1646 	const char *pattern = "e (.*)=";
1647 	RRegex *rx = r_regex_new (pattern, "e");
1648 	const size_t nmatch = 2;
1649 	RRegexMatch pmatch[2] = {0};
1650 	bool ret = false;
1651 
1652 	// required to get the new list of items to autocomplete for cmd.pdc at least
1653 	r_core_config_update (core);
1654 
1655 	if (r_regex_exec (rx, buf->data, nmatch, pmatch, 1)) {
1656 		goto out;
1657 	}
1658 	int i;
1659 	char *str = NULL, *sp;
1660 	for (i = pmatch[1].rm_so; i < pmatch[1].rm_eo; i++) {
1661 		str = r_str_appendch (str, buf->data[i]);
1662 	}
1663 	if (!str) {
1664 		goto out;
1665 	}
1666 	if ((sp = strchr (str, ' '))) {
1667 		// if the name contains a space, just null
1668 		*sp = 0;
1669 	}
1670 	RConfigNode *node = r_config_node_get (core->config, str);
1671 	if (sp) {
1672 		// if nulled, then restore.
1673 		*sp = ' ';
1674 	}
1675 	if (!node) {
1676 		return false;
1677 	}
1678 	RListIter *iter;
1679 	char *option;
1680 	char *p = (char *) strchr (buf->data, '=');
1681 	p = r_str_ichr (p + 1, ' ');
1682 	int n = strlen (p);
1683 	r_list_foreach (node->options, iter, option) {
1684 		if (!strncmp (option, p, n)) {
1685 			r_line_completion_push (completion, option);
1686 		}
1687 	}
1688 	completion->opt = true;
1689 	ret = true;
1690 
1691  out:
1692 	r_regex_free (rx);
1693 	return ret;
1694 }
1695 
find_autocomplete(RCore * core,RLineCompletion * completion,RLineBuffer * buf)1696 static bool find_autocomplete(RCore *core, RLineCompletion *completion, RLineBuffer *buf) {
1697 	RCoreAutocomplete* child = NULL;
1698 	RCoreAutocomplete* parent = core->autocomplete;
1699 	const char* p = buf->data;
1700 	if (!*p) {
1701 		return false;
1702 	}
1703 	char arg[256];
1704 	arg[0] = 0;
1705 	while (*p) {
1706 		const char* e = r_str_trim_head_wp (p);
1707 		if (!e || (e - p) >= 256 || e == p) {
1708 			return false;
1709 		}
1710 		memcpy (arg, p, e - p);
1711 		arg[e - p] = 0;
1712 		child = r_core_autocomplete_find (parent, arg, false);
1713 		if (child && child->length < buf->length && p[child->length] == ' ') {
1714 			// if is spaced then i can provide the
1715 			// next subtree as suggestion..
1716 			p = r_str_trim_head_ro (p + child->length);
1717 			if (child->type == R_CORE_AUTOCMPLT_OPTN) {
1718 				continue;
1719 			}
1720 			parent = child;
1721 		} else {
1722 			break;
1723 		}
1724 	}
1725 	int i;
1726 	/* if something went wrong this will prevent bad behavior */
1727 	r_line_completion_clear (completion);
1728 	switch (parent->type) {
1729 	case R_CORE_AUTOCMPLT_SEEK:
1730 		autocomplete_functions (core, completion, p);
1731 	case R_CORE_AUTOCMPLT_FLAG:
1732 		autocomplete_flags (core, completion, p);
1733 		break;
1734 	case R_CORE_AUTOCMPLT_FLSP:
1735 		autocomplete_flagspaces (core, completion, p);
1736 		break;
1737 	case R_CORE_AUTOCMPLT_FCN:
1738 		autocomplete_functions (core, completion, p);
1739 		break;
1740 	case R_CORE_AUTOCMPLT_ZIGN:
1741 		autocomplete_zignatures (core, completion, p);
1742 		break;
1743 	case R_CORE_AUTOCMPLT_EVAL:
1744 		autocomplete_evals (core, completion, p);
1745 		break;
1746 	case R_CORE_AUTOCMPLT_PRJT:
1747 		autocomplete_project (core, completion, p);
1748 		break;
1749 	case R_CORE_AUTOCMPLT_MINS:
1750 		autocomplete_minus (core, completion, p);
1751 		break;
1752 	case R_CORE_AUTOCMPLT_BRKP:
1753 		autocomplete_breakpoints (core, completion, p);
1754 		break;
1755 	case R_CORE_AUTOCMPLT_MACR:
1756 		autocomplete_macro (core, completion, p);
1757 		break;
1758 	case R_CORE_AUTOCMPLT_MS:
1759 		autocomplete_ms_file(core, completion, p);
1760 		break;
1761 	case R_CORE_AUTOCMPLT_FILE:
1762 		autocomplete_file (completion, p);
1763 		break;
1764 	case R_CORE_AUTOCMPLT_THME:
1765 		autocomplete_theme (core, completion, p);
1766 		break;
1767 	case R_CORE_AUTOCMPLT_SDB:
1768 		autocomplete_sdb (core, completion, p);
1769 		break;
1770 	case R_CORE_AUTOCMPLT_OPTN:
1771 		// handled before
1772 		break;
1773 	default:
1774 		if (r_config_get_i (core->config, "cfg.newtab")) {
1775 			RCmdDescriptor *desc = &core->root_cmd_descriptor;
1776 			for (i = 0; arg[i] && desc; i++) {
1777 				ut8 c = arg[i];
1778 				desc = c < R_ARRAY_SIZE (desc->sub) ? desc->sub[c] : NULL;
1779 			}
1780 			if (desc && desc->help_msg) {
1781 				r_core_cmd_help (core, desc->help_msg);
1782 				r_cons_flush ();
1783 				return true;
1784 			}
1785 			// fallback to command listing
1786 		}
1787 		int length = strlen (arg);
1788 		for (i = 0; i < parent->n_subcmds; i++) {
1789 			if (!strncmp (arg, parent->subcmds[i]->cmd, length)) {
1790 				r_line_completion_push (completion, parent->subcmds[i]->cmd);
1791 			}
1792 		}
1793 		break;
1794 	}
1795 	return true;
1796 }
1797 
r_core_autocomplete(R_NULLABLE RCore * core,RLineCompletion * completion,RLineBuffer * buf,RLinePromptType prompt_type)1798 R_API void r_core_autocomplete(R_NULLABLE RCore *core, RLineCompletion *completion, RLineBuffer *buf, RLinePromptType prompt_type) {
1799 	if (!core) {
1800 		autocomplete_default (core, completion, buf);
1801 		return;
1802 	}
1803 	r_line_completion_clear (completion);
1804 	char *pipe = strchr (buf->data, '>');
1805 	char *ptr = strchr (buf->data, '@');
1806 	if (pipe && strchr (pipe + 1, ' ') && buf->data + buf->index >= pipe) {
1807 		autocompleteFilename (completion, buf, NULL, 1);
1808 	} else if (ptr && strchr (ptr + 1, ' ') && buf->data + buf->index >= ptr) {
1809 		int sdelta, n;
1810 		ptr = (char *)r_str_trim_head_ro (ptr + 1);
1811 		n = strlen (ptr);//(buf->data+sdelta);
1812 		sdelta = (int)(size_t)(ptr - buf->data);
1813 		r_flag_foreach_prefix (core->flags, buf->data + sdelta, n, add_argv, completion);
1814 	} else if (!strncmp (buf->data, "#!pipe ", 7)) {
1815 		if (strchr (buf->data + 7, ' ')) {
1816 			autocompleteFilename (completion, buf, NULL, 2);
1817 		} else {
1818 			int chr = 7;
1819 			ADDARG ("node");
1820 			ADDARG ("vala");
1821 			ADDARG ("ruby");
1822 			ADDARG ("newlisp");
1823 			ADDARG ("perl");
1824 			ADDARG ("python");
1825 		}
1826 	} else if (!strncmp (buf->data, "ec ", 3)) {
1827 		if (strchr (buf->data + 3, ' ')) {
1828 			autocompleteFilename (completion, buf, NULL, 2);
1829 		} else {
1830 			int chr = 3;
1831 			ADDARG("comment")
1832 			ADDARG("usrcmt")
1833 			ADDARG("args")
1834 			ADDARG("fname")
1835 			ADDARG("floc")
1836 			ADDARG("fline")
1837 			ADDARG("flag")
1838 			ADDARG("label")
1839 			ADDARG("help")
1840 			ADDARG("flow")
1841 			ADDARG("prompt")
1842 			ADDARG("offset")
1843 			ADDARG("input")
1844 			ADDARG("invalid")
1845 			ADDARG("other")
1846 			ADDARG("b0x00")
1847 			ADDARG("b0x7f")
1848 			ADDARG("b0xff")
1849 			ADDARG("math")
1850 			ADDARG("bin")
1851 			ADDARG("btext")
1852 			ADDARG("push")
1853 			ADDARG("pop")
1854 			ADDARG("crypto")
1855 			ADDARG("jmp")
1856 			ADDARG("cjmp")
1857 			ADDARG("call")
1858 			ADDARG("nop")
1859 			ADDARG("ret")
1860 			ADDARG("trap")
1861 			ADDARG("swi")
1862 			ADDARG("cmp")
1863 			ADDARG("reg")
1864 			ADDARG("creg")
1865 			ADDARG("num")
1866 			ADDARG("mov")
1867 			ADDARG("func_var")
1868 			ADDARG("func_var_type")
1869 			ADDARG("func_var_addr")
1870 			ADDARG("widget_bg")
1871 			ADDARG("widget_sel")
1872 			ADDARG("ai.read")
1873 			ADDARG("ai.write")
1874 			ADDARG("ai.exec")
1875 			ADDARG("ai.seq")
1876 			ADDARG("ai.ascii")
1877 			ADDARG("ai.unmap")
1878 			ADDARG("graph.box")
1879 			ADDARG("graph.box2")
1880 			ADDARG("graph.box3")
1881 			ADDARG("graph.box4")
1882 			ADDARG("graph.true")
1883 			ADDARG("graph.false")
1884 			ADDARG("graph.trufae")
1885 			ADDARG("graph.current")
1886 			ADDARG("graph.traced")
1887 			ADDARG("gui.cflow")
1888 			ADDARG("gui.dataoffset")
1889 			ADDARG("gui.background")
1890 			ADDARG("gui.alt_background")
1891 			ADDARG("gui.border")
1892 		}
1893 	} else if (!strncmp (buf->data, "pf.", 3)
1894 	|| !strncmp (buf->data, "pf*.", 4)
1895 	|| !strncmp (buf->data, "pfd.", 4)
1896 	|| !strncmp (buf->data, "pfv.", 4)
1897 	|| !strncmp (buf->data, "pfj.", 4)) {
1898 		char pfx[2];
1899 		int chr = (buf->data[2]=='.')? 3: 4;
1900 		if (chr == 4) {
1901 			pfx[0] = buf->data[2];
1902 			pfx[1] = 0;
1903 		} else {
1904 			*pfx = 0;
1905 		}
1906 		SdbList *sls = sdb_foreach_list (core->print->formats, false);
1907 		SdbListIter *iter;
1908 		SdbKv *kv;
1909 		ls_foreach (sls, iter, kv) {
1910 			int len = strlen (buf->data + chr);
1911 			int minlen = R_MIN (len,  strlen (sdbkv_key (kv)));
1912 			if (!len || !strncmp (buf->data + chr, sdbkv_key (kv), minlen)) {
1913 				char *p = strchr (buf->data + chr, '.');
1914 				if (p) {
1915 					autocomplete_pfele (core, completion, sdbkv_key (kv), pfx, 0, p + 1);
1916 					break;
1917 				} else {
1918 					char *s = r_str_newf ("pf%s.%s", pfx, sdbkv_key (kv));
1919 					r_line_completion_push (completion, s);
1920 					free (s);
1921 				}
1922 			}
1923 		}
1924 	} else if ((!strncmp (buf->data, "afvn ", 5))
1925 	|| (!strncmp (buf->data, "afan ", 5))) {
1926 		RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, 0);
1927 		RList *vars;
1928 		if (!strncmp (buf->data, "afvn ", 5)) {
1929 			vars = r_anal_var_list (core->anal, fcn, R_ANAL_VAR_KIND_BPV);
1930 		} else {
1931 			vars = r_list_new (); // TODO wtf r_anal_var_list (core->anal, fcn, R_ANAL_VAR_KIND_ARG);
1932 		}
1933 		const char *f_ptr, *l_ptr;
1934 		RAnalVar *var;
1935 		int len = strlen (buf->data);
1936 
1937 		f_ptr = r_sub_str_lchr (buf->data, 0, buf->index, ' ');
1938 		f_ptr = f_ptr != NULL ? f_ptr + 1 : buf->data;
1939 		l_ptr = r_sub_str_rchr (buf->data, buf->index, len, ' ');
1940 		if (!l_ptr) {
1941 			l_ptr = buf->data + len;
1942 		}
1943 		RListIter *iter;
1944 		r_list_foreach (vars, iter, var) {
1945 			if (!strncmp (f_ptr, var->name, l_ptr - f_ptr)) {
1946 				r_line_completion_push (completion, var->name);
1947 			}
1948 		}
1949 		r_list_free (vars);
1950 	} else if (!strncmp (buf->data, "t ", 2)
1951 	|| !strncmp (buf->data, "t- ", 3)) {
1952 		SdbList *l = sdb_foreach_list (core->anal->sdb_types, true);
1953 		SdbListIter *iter;
1954 		SdbKv *kv;
1955 		int chr = (buf->data[1] == ' ')? 2: 3;
1956 		ls_foreach (l, iter, kv) {
1957 			int len = strlen (buf->data + chr);
1958 			if (!len || !strncmp (buf->data + chr, sdbkv_key (kv), len)) {
1959 				if (!strcmp (sdbkv_value (kv), "type") || !strcmp (sdbkv_value (kv), "enum")
1960 				|| !strcmp (sdbkv_value (kv), "struct")) {
1961 					r_line_completion_push (completion, sdbkv_key (kv));
1962 				}
1963 			}
1964 		}
1965 		ls_free (l);
1966 	} else if ((!strncmp (buf->data, "te ", 3))) {
1967 		SdbList *l = sdb_foreach_list (core->anal->sdb_types, true);
1968 		SdbListIter *iter;
1969 		SdbKv *kv;
1970 		int chr = 3;
1971 		ls_foreach (l, iter, kv) {
1972 			int len = strlen (buf->data + chr);
1973 			if (!len || !strncmp (buf->data + chr, sdbkv_key (kv), len)) {
1974 				if (!strcmp (sdbkv_value (kv), "enum")) {
1975 					r_line_completion_push (completion, sdbkv_key (kv));
1976 				}
1977 			}
1978 		}
1979 		ls_free (l);
1980 	} else if (!strncmp (buf->data, "$", 1)) {
1981 		int i;
1982 		for (i = 0; i < core->rcmd->aliases.count; i++) {
1983 			const char *key = core->rcmd->aliases.keys[i];
1984 			int len = strlen (buf->data);
1985 			if (!len || !strncmp (buf->data, key, len)) {
1986 				r_line_completion_push (completion, key);
1987 			}
1988 		}
1989 	} else if (!strncmp (buf->data, "ts ", 3)
1990 	|| !strncmp (buf->data, "ta ", 3)
1991 	|| !strncmp (buf->data, "tp ", 3)
1992 	|| !strncmp (buf->data, "tl ", 3)
1993 	|| !strncmp (buf->data, "tpx ", 4)
1994 	|| !strncmp (buf->data, "tss ", 4)
1995 	|| !strncmp (buf->data, "ts* ", 4)) {
1996 		SdbList *l = sdb_foreach_list (core->anal->sdb_types, true);
1997 		SdbListIter *iter;
1998 		SdbKv *kv;
1999 		int chr = (buf->data[2] == ' ')? 3: 4;
2000 		ls_foreach (l, iter, kv) {
2001 			int len = strlen (buf->data + chr);
2002 			const char *key = sdbkv_key (kv);
2003 			if (!len || !strncmp (buf->data + chr, key, len)) {
2004 				if (!strncmp (sdbkv_value (kv), "struct", strlen ("struct") + 1)) {
2005 					r_line_completion_push (completion, key);
2006 				}
2007 			}
2008 		}
2009 		ls_free (l);
2010 	} else if (!strncmp (buf->data, "zo ", 3)
2011 	|| !strncmp (buf->data, "zoz ", 4)) {
2012 		if (core->anal->zign_path && core->anal->zign_path[0]) {
2013 			char *zignpath = r_file_abspath (core->anal->zign_path);
2014 			char *paths[2] = { zignpath, NULL };
2015 			autocompleteFilename (completion, buf, paths, 1);
2016 			free (zignpath);
2017 		} else {
2018 			autocompleteFilename (completion, buf, NULL, 1);
2019 		}
2020 	} else if (find_e_opts (core, completion, buf)) {
2021 		return;
2022 	} else if (prompt_type == R_LINE_PROMPT_OFFSET) {
2023 		autocomplete_flags (core, completion, buf->data);
2024 	} else if (prompt_type == R_LINE_PROMPT_FILE) {
2025 		autocomplete_file (completion, buf->data);
2026 	} else if (!find_autocomplete (core, completion, buf)) {
2027 		autocomplete_default (core, completion, buf);
2028 	}
2029 }
2030 
autocomplete(RLineCompletion * completion,RLineBuffer * buf,RLinePromptType prompt_type,void * user)2031 static int autocomplete(RLineCompletion *completion, RLineBuffer *buf, RLinePromptType prompt_type, void *user) {
2032 	RCore *core = user;
2033 	r_core_autocomplete (core, completion, buf, prompt_type);
2034 	return true;
2035 }
2036 
r_core_fgets(char * buf,int len)2037 R_API int r_core_fgets(char *buf, int len) {
2038 	RCons *cons = r_cons_singleton ();
2039 	RLine *rli = cons->line;
2040 	bool prompt = cons->context->is_interactive;
2041 	buf[0] = '\0';
2042 	if (prompt) {
2043 		r_line_completion_set (&rli->completion, radare_argc, radare_argv);
2044 		rli->completion.run = autocomplete;
2045 		rli->completion.run_user = rli->user;
2046 	} else {
2047 		r_line_hist_free ();
2048 		r_line_completion_set (&rli->completion, 0, NULL);
2049 		rli->completion.run = NULL;
2050 		rli->completion.run_user = NULL;
2051 	}
2052 	const char *ptr = r_line_readline ();
2053 	if (!ptr) {
2054 		return -1;
2055 	}
2056 	return r_str_ncpy (buf, ptr, len - 1);
2057 }
2058 
r_core_print_offname(void * p,ut64 addr)2059 static const char *r_core_print_offname(void *p, ut64 addr) {
2060 	RCore *c = (RCore*)p;
2061 	RFlagItem *item = r_flag_get_i (c->flags, addr);
2062 	return item ? item->name : NULL;
2063 }
2064 
r_core_print_offsize(void * p,ut64 addr)2065 static int r_core_print_offsize(void *p, ut64 addr) {
2066 	RCore *c = (RCore*)p;
2067 	RFlagItem *item = r_flag_get_i (c->flags, addr);
2068 	return item ? item->size: -1;
2069 }
2070 
2071 /**
2072  * Disassemble one instruction at specified address.
2073  */
__disasm(void * _core,ut64 addr)2074 static int __disasm(void *_core, ut64 addr) {
2075 	RCore *core = _core;
2076 	ut64 prevaddr = core->offset;
2077 
2078 	r_core_seek (core, addr, true);
2079 	int len = r_core_print_disasm_instructions (core, 0, 1);
2080 	r_core_seek (core, prevaddr, true);
2081 
2082 	return len;
2083 }
2084 
update_sdb(RCore * core)2085 static void update_sdb(RCore *core) {
2086 	Sdb *d;
2087 	RBinObject *o;
2088 	if (!core) {
2089 		return;
2090 	}
2091 	//SDB// anal/
2092 	if (core->anal && core->anal->sdb) {
2093 		sdb_ns_set (DB, "anal", core->anal->sdb);
2094 	}
2095 	//SDB// bin/
2096 	if (core->bin && core->bin->sdb) {
2097 		sdb_ns_set (DB, "bin", core->bin->sdb);
2098 	}
2099 	//SDB// bin/info
2100 	o = r_bin_cur_object (core->bin);
2101 	if (o) {
2102 		sdb_ns_set (sdb_ns (DB, "bin", 1), "info", o->kv);
2103 	}
2104 	//sdb_ns_set (core->sdb, "flags", core->flags->sdb);
2105 	//sdb_ns_set (core->sdb, "bin", core->bin->sdb);
2106 	//SDB// syscall/
2107 	if (core->rasm && core->rasm->syscall && core->rasm->syscall->db) {
2108 		core->rasm->syscall->db->refs++;
2109 		sdb_ns_set (DB, "syscall", core->rasm->syscall->db);
2110 	}
2111 	d = sdb_ns (DB, "debug", 1);
2112 	if (core->dbg->sgnls) {
2113 		core->dbg->sgnls->refs++;
2114 		sdb_ns_set (d, "signals", core->dbg->sgnls);
2115 	}
2116 }
2117 
2118 #define MINLEN 1
is_string(const ut8 * buf,int size,int * len)2119 static int is_string(const ut8 *buf, int size, int *len) {
2120 	int i;
2121 	if (size < 1) {
2122 		return 0;
2123 	}
2124 	if (size > 3 && buf[0] && !buf[1] && buf[2] && !buf[3]) {
2125 		*len = 1; // XXX: TODO: Measure wide string length
2126 		return 2; // is wide
2127 	}
2128 	for (i = 0; i < size; i++) {
2129 		if (!buf[i] && i > MINLEN) {
2130 			*len = i;
2131 			return 1;
2132 		}
2133 		if (buf[i] == 10|| buf[i] == 13|| buf[i] == 9) {
2134 			continue;
2135 		}
2136 		if (buf[i] < 32 || buf[i] > 127) {
2137 			// not ascii text
2138 			return 0;
2139 		}
2140 		if (!IS_PRINTABLE (buf[i])) {
2141 			*len = i;
2142 			return 0;
2143 		}
2144 	}
2145 	*len = i;
2146 	return 1;
2147 }
2148 
r_core_anal_hasrefs(RCore * core,ut64 value,int mode)2149 R_API char *r_core_anal_hasrefs(RCore *core, ut64 value, int mode) {
2150 	if (mode) {
2151 		PJ *pj = (mode == 'j')? pj_new (): NULL;
2152 		const int hex_depth = 1; // r_config_get_i (core->config, "hex.depth");
2153 		char *res = r_core_anal_hasrefs_to_depth (core, value, pj, hex_depth);
2154 		if (pj) {
2155 			free (res);
2156 			return pj_drain (pj);
2157 		}
2158 		return res;
2159 	}
2160 	RFlagItem *fi = r_flag_get_i (core->flags, value);
2161 	return fi? strdup (fi->name): NULL;
2162 }
2163 
getvalue(ut64 value,int bits)2164 static char *getvalue(ut64 value, int bits) {
2165 	switch (bits) {
2166 	case 16: // umf, not in sync with pxr
2167 		{
2168 			st16 v = (st16)(value & UT16_MAX);
2169 			st16 h = UT16_MAX / 0x100;
2170 			if (v > -h && v < h) {
2171 				return r_str_newf ("%hd", v);
2172 			}
2173 		}
2174 		break;
2175 	case 32:
2176 		{
2177 			st32 v = (st32)(value & UT32_MAX);
2178 			st32 h = UT32_MAX / 0x10000;
2179 			if (v > -h && v < h) {
2180 				return r_str_newf ("%d", v);
2181 			}
2182 		}
2183 		break;
2184 	case 64:
2185 		{
2186 			st64 v = (st64)(value);
2187 			st64 h = UT64_MAX / 0x1000000;
2188 			if (v > -h && v < h) {
2189 				return r_str_newf ("%"PFMT64d, v);
2190 			}
2191 		}
2192 		break;
2193 	}
2194 	return NULL;
2195 }
2196 
2197 /*
2198  pxr logic is dupplicated in other places
2199  * ai, ad
2200  * no json support
2201 */
r_core_anal_hasrefs_to_depth(RCore * core,ut64 value,PJ * pj,int depth)2202 R_API char *r_core_anal_hasrefs_to_depth(RCore *core, ut64 value, PJ *pj, int depth) {
2203 	const int bits = core->rasm->bits;
2204 	r_return_val_if_fail (core, NULL);
2205 	RStrBuf *s = r_strbuf_new (NULL);
2206 	if (pj) {
2207 		pj_o (pj);
2208 		pj_kn (pj, "addr", value);
2209 	}
2210 	if (depth < 1 || value == UT64_MAX) {
2211 		if (pj) {
2212 			pj_end (pj);
2213 		}
2214 		return NULL;
2215 	}
2216 
2217 	char *val = getvalue (value, bits);
2218 	if (val) {
2219 		if (pj) {
2220 			pj_ks (pj, "value", val);
2221 		} else {
2222 			r_strbuf_appendf (s, "%s ", val);
2223 		}
2224 		R_FREE (val);
2225 	}
2226 
2227 	if (value && value != UT64_MAX) {
2228 		RDebugMap *map = r_debug_map_get (core->dbg, value);
2229 		if (map && map->name && map->name[0]) {
2230 			if (pj) {
2231 				pj_ks (pj, "map", map->name);
2232 			} else {
2233 				r_strbuf_appendf (s, "%s ", map->name);
2234 			}
2235 		}
2236 	}
2237 	ut64 type = r_core_anal_address (core, value);
2238 	RBinSection *sect = value? r_bin_get_section_at (r_bin_cur_object (core->bin), value, true): NULL;
2239 	if(! ((type & R_ANAL_ADDR_TYPE_HEAP) || (type & R_ANAL_ADDR_TYPE_STACK)) ) {
2240 		// Do not repeat "stack" or "heap" words unnecessarily.
2241 		if (sect && sect->name[0]) {
2242 			if (pj) {
2243 				pj_ks (pj, "section", sect->name);
2244 			} else {
2245 				r_strbuf_appendf (s, "%s ", sect->name);
2246 			}
2247 		}
2248 	}
2249 	if (value != 0 && value != UT64_MAX) {
2250 		if (pj) {
2251 			RListIter *iter;
2252 			RFlagItem *f;
2253 			const RList *flags = r_flag_get_list (core->flags, value);
2254 			if (flags && !r_list_empty (flags)) {
2255 				pj_ka (pj, "flags");
2256 				r_list_foreach (flags, iter, f) {
2257 					pj_s (pj, f->name);
2258 				}
2259 				pj_end (pj);
2260 			}
2261 		} else {
2262 			char *flags = r_flag_get_liststr (core->flags, value);
2263 			if (flags) {
2264 				r_strbuf_appendf (s, "%s ", flags);
2265 				free (flags);
2266 			}
2267 		}
2268 	}
2269 	RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, value, 0);
2270 	if (fcn) {
2271 		if (pj) {
2272 			pj_ks (pj, "fcn", fcn->name);
2273 		} else {
2274 			r_strbuf_appendf (s, "%s ", fcn->name);
2275 		}
2276 	}
2277 	if (type) {
2278 		const char *c = r_core_anal_optype_colorfor (core, value, true);
2279 		const char *cend = (c && *c) ? Color_RESET: "";
2280 		if (!c) {
2281 			c = "";
2282 		}
2283 		if (pj) {
2284 			pj_ka (pj, "attr");
2285 		}
2286 		if (type & R_ANAL_ADDR_TYPE_HEAP) {
2287 			if (pj) {
2288 				pj_s (pj, "heap");
2289 			} else {
2290 				r_strbuf_appendf (s, "%sheap%s ", c, cend);
2291 			}
2292 		} else if (type & R_ANAL_ADDR_TYPE_STACK) {
2293 			if (pj) {
2294 				pj_s (pj, "stack");
2295 			} else {
2296 				r_strbuf_appendf (s, "%sstack%s ", c, cend);
2297 			}
2298 		}
2299 		if (type & R_ANAL_ADDR_TYPE_PROGRAM) {
2300 			if (pj) {
2301 				pj_s (pj, "program");
2302 			} else {
2303 				r_strbuf_appendf (s, "%sprogram%s ", c, cend);
2304 			}
2305 		}
2306 		if (type & R_ANAL_ADDR_TYPE_LIBRARY) {
2307 			if (pj) {
2308 				pj_s (pj, "library");
2309 			} else {
2310 				r_strbuf_appendf (s, "%slibrary%s ", c, cend);
2311 			}
2312 		}
2313 		if (type & R_ANAL_ADDR_TYPE_ASCII) {
2314 			if (pj) {
2315 				pj_s (pj, "ascii");
2316 			} else {
2317 				r_strbuf_appendf (s, "%sascii%s ('%c') ", c, cend, (char)value);
2318 			}
2319 		}
2320 		if (type & R_ANAL_ADDR_TYPE_SEQUENCE) {
2321 			if (pj) {
2322 				pj_s (pj, "sequence");
2323 			} else {
2324 				r_strbuf_appendf (s, "%ssequence%s ", c, cend);
2325 			}
2326 		}
2327 		if (pj) {
2328 			if (type & R_ANAL_ADDR_TYPE_READ) {
2329 				pj_s (pj, "R");
2330 			}
2331 			if (type & R_ANAL_ADDR_TYPE_WRITE) {
2332 				pj_s (pj, "W");
2333 			}
2334 			if (type & R_ANAL_ADDR_TYPE_EXEC) {
2335 				pj_s (pj, "X");
2336 			}
2337 		} else {
2338 			if (type & R_ANAL_ADDR_TYPE_READ) {
2339 				r_strbuf_appendf (s, "%sR%s ", c, cend);
2340 			}
2341 			if (type & R_ANAL_ADDR_TYPE_WRITE) {
2342 				r_strbuf_appendf (s, "%sW%s ", c, cend);
2343 			}
2344 			if (type & R_ANAL_ADDR_TYPE_EXEC) {
2345 				RAsmOp op;
2346 				ut8 buf[32];
2347 				r_strbuf_appendf (s, "%sX%s ", c, cend);
2348 				/* instruction disassembly */
2349 				r_io_read_at (core->io, value, buf, sizeof (buf));
2350 				r_asm_set_pc (core->rasm, value);
2351 				r_asm_disassemble (core->rasm, &op, buf, sizeof (buf));
2352 				r_strbuf_appendf (s, "'%s' ", r_asm_op_get_asm (&op));
2353 				/* get library name */
2354 				{ // NOTE: dup for mapname?
2355 					RDebugMap *map;
2356 					RListIter *iter;
2357 					r_list_foreach (core->dbg->maps, iter, map) {
2358 						if ((value >= map->addr) &&
2359 							(value<map->addr_end)) {
2360 							const char *lastslash = r_str_lchr (map->name, '/');
2361 							r_strbuf_appendf (s, "'%s' ", lastslash?
2362 								lastslash + 1: map->name);
2363 							break;
2364 						}
2365 					}
2366 				}
2367 			} else if (type & R_ANAL_ADDR_TYPE_READ) {
2368 				ut8 buf[32];
2369 				ut32 *n32 = (ut32 *)buf;
2370 				ut64 *n64 = (ut64*)buf;
2371 				if (r_io_read_at (core->io, value, buf, sizeof (buf))) {
2372 					ut64 n = (bits == 64)? *n64: *n32;
2373 					r_strbuf_appendf (s, "0x%"PFMT64x" ", n);
2374 				}
2375 			}
2376 		}
2377 		if (pj) {
2378 			pj_end (pj);
2379 		}
2380 	}
2381 	{
2382 		ut8 buf[128], widebuf[256];
2383 		const char *c = r_config_get_i (core->config, "scr.color")? core->cons->context->pal.ai_ascii: "";
2384 		const char *cend = (c && *c) ? Color_RESET: "";
2385 		int len, r;
2386 		if (r_io_read_at (core->io, value, buf, sizeof (buf))) {
2387 			buf[sizeof (buf) - 1] = 0;
2388 			switch (is_string (buf, sizeof (buf), &len)) {
2389 			case 1:
2390 				if (pj) {
2391 					pj_ks (pj, "string", (const char *)buf);
2392 				} else {
2393 					r_strbuf_appendf (s, "%s%s%s ", c, buf, cend);
2394 				}
2395 				break;
2396 			case 2:
2397 				r = r_utf8_encode_str ((const RRune *)buf, widebuf, sizeof (widebuf) - 1);
2398 				if (r == -1) {
2399 					r_cons_eprintf ("Something was wrong with refs\n");
2400 				} else {
2401 					if (pj) {
2402 						pj_ks (pj, "string", (const char *)widebuf);
2403 					} else {
2404 						r_strbuf_appendf (s, "%s%s%s ", c, widebuf, cend);
2405 					}
2406 				}
2407 				break;
2408 			}
2409 		}
2410 
2411 	}
2412 	if ((type & R_ANAL_ADDR_TYPE_READ) && !(type & R_ANAL_ADDR_TYPE_EXEC) && depth) {
2413 		// Try to telescope further, but only several levels deep.
2414 		ut8 buf[32];
2415 		ut32 *n32 = (ut32 *)buf;
2416 		ut64 *n64 = (ut64*)buf;
2417 		if (r_io_read_at (core->io, value, buf, sizeof (buf))) {
2418 			ut64 n = (bits == 64)? *n64: *n32;
2419 			if (n != value) {
2420 				if (pj) {
2421 					pj_k (pj, "ref");
2422 				}
2423 				char* rrstr = r_core_anal_hasrefs_to_depth (core, n, pj, depth - 1);
2424 				if (rrstr) {
2425 					if (!pj && rrstr[0]) {
2426 						r_strbuf_appendf (s, " -> %s", rrstr);
2427 					}
2428 					free (rrstr);
2429 				}
2430 			}
2431 		}
2432 	}
2433 	if (pj) {
2434 		pj_end (pj);
2435 	}
2436 	char *res = r_strbuf_drain (s);
2437 	r_str_trim_tail (res);
2438 	return res;
2439 }
2440 
r_core_anal_get_comments(RCore * core,ut64 addr)2441 R_API char *r_core_anal_get_comments(RCore *core, ut64 addr) {
2442 	if (core) {
2443 		const char *type = r_meta_get_string (core->anal, R_META_TYPE_VARTYPE, addr);
2444 		const char *cmt = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, addr);
2445 		if (type && cmt) {
2446 			return r_str_newf ("%s %s", type, cmt);
2447 		}
2448 		if (type) {
2449 			return strdup (type);
2450 		}
2451 		if (cmt) {
2452 			return strdup (cmt);
2453 		}
2454 	}
2455 	return NULL;
2456 }
2457 
r_core_anal_optype_colorfor(RCore * core,ut64 addr,bool verbose)2458 R_API const char *r_core_anal_optype_colorfor(RCore *core, ut64 addr, bool verbose) {
2459 	ut64 type;
2460 	if (!(core->print->flags & R_PRINT_FLAGS_COLOR)) {
2461 		return NULL;
2462 	}
2463 	if (!r_config_get_i (core->config, "scr.color")) {
2464 		return NULL;
2465 	}
2466 	type = r_core_anal_address (core, addr);
2467 	if (type & R_ANAL_ADDR_TYPE_EXEC) {
2468 		return core->cons->context->pal.ai_exec; //Color_RED;
2469 	}
2470 	if (type & R_ANAL_ADDR_TYPE_WRITE) {
2471 		return core->cons->context->pal.ai_write; //Color_BLUE;
2472 	}
2473 	if (type & R_ANAL_ADDR_TYPE_READ) {
2474 		return core->cons->context->pal.ai_read; //Color_GREEN;
2475 	}
2476 	if (type & R_ANAL_ADDR_TYPE_SEQUENCE) {
2477 		return core->cons->context->pal.ai_seq; //Color_MAGENTA;
2478 	}
2479 	if (type & R_ANAL_ADDR_TYPE_ASCII) {
2480 		return core->cons->context->pal.ai_ascii; //Color_YELLOW;
2481 	}
2482 	return NULL;
2483 }
2484 
r_core_setenv(RCore * core)2485 static void r_core_setenv (RCore *core) {
2486 	char *e = r_sys_getenv ("PATH");
2487 	char *h = r_str_home (R2_HOME_BIN);
2488 	char *n = r_str_newf ("%s%s%s", h, R_SYS_ENVSEP, e);
2489 	r_sys_setenv ("PATH", n);
2490 	free (n);
2491 	free (h);
2492 	free (e);
2493 }
2494 
mywrite(const ut8 * buf,int len)2495 static int mywrite(const ut8 *buf, int len) {
2496 	return r_cons_memcat ((const char *)buf, len);
2497 }
2498 
exists_var(RPrint * print,ut64 func_addr,char * str)2499 static bool exists_var(RPrint *print, ut64 func_addr, char *str) {
2500 	RAnal *anal = ((RCore*)(print->user))->anal;
2501 	RAnalFunction *fcn = r_anal_get_function_at (anal, func_addr);
2502 	if (!fcn) {
2503 		return false;
2504 	}
2505 	return !!r_anal_function_get_var_byname (fcn, str);
2506 }
2507 
r_core_anal_log(struct r_anal_t * anal,const char * msg)2508 static bool r_core_anal_log(struct r_anal_t *anal, const char *msg) {
2509 	RCore *core = anal->user;
2510 	if (core->cfglog) {
2511 		r_core_log_add (core, msg);
2512 	}
2513 	return true;
2514 }
2515 
r_core_anal_read_at(struct r_anal_t * anal,ut64 addr,ut8 * buf,int len)2516 static bool r_core_anal_read_at(struct r_anal_t *anal, ut64 addr, ut8 *buf, int len) {
2517 	return r_io_read_at (anal->iob.io, addr, buf, len);
2518 }
2519 
r_core_break(RCore * core)2520 static void r_core_break (RCore *core) {
2521 }
2522 
r_core_sleep_begin(RCore * core)2523 static void *r_core_sleep_begin (RCore *core) {
2524 	RCoreTask *task = r_core_task_self (&core->tasks);
2525 	if (task) {
2526 		r_core_task_sleep_begin (task);
2527 	}
2528 	return task;
2529 }
2530 
r_core_sleep_end(RCore * core,void * user)2531 static void r_core_sleep_end (RCore *core, void *user) {
2532 	RCoreTask *task = (RCoreTask *)user;
2533 	if (task) {
2534 		r_core_task_sleep_end (task);
2535 	}
2536 }
2537 
__foreach(RCore * core,const char ** cmds,int type)2538 static void __foreach(RCore *core, const char **cmds, int type) {
2539 	int i;
2540 	for (i = 0; cmds[i]; i++) {
2541 		r_core_autocomplete_add (core->autocomplete, cmds[i], type, true);
2542 	}
2543 }
2544 
__init_autocomplete_default(RCore * core)2545 static void __init_autocomplete_default (RCore* core) {
2546 	const char *fcns[] = {
2547 		"afi", "afcf", "afn", NULL
2548 	};
2549 	const char *seeks[] = {
2550 		"s", NULL
2551 	};
2552 	const char *flags[] = {
2553 		"*", "s", "s+", "b", "f", "fg", "?", "?v", "ad", "bf", "c1", "db", "dbw",
2554 		"f-", "fr", "tf", "/a", "/v", "/r", "/re", "aav", "aep", "aef", "afb",
2555 		"afc", "axg", "axt", "axf", "dcu", "ag", "agfl", "aecu", "aesu", "aeim", NULL
2556 	};
2557 	const char *evals[] = {
2558 		"e", "ee", "et", "e?", "e!", "ev", "evj", NULL
2559 	};
2560 	const char *breaks[] = {
2561 		"db-", "dbc", "dbC", "dbd", "dbe", "dbs", "dbi", "dbte", "dbtd", "dbts", NULL
2562 	};
2563 	const char *files[] = {
2564 		".", "..", ".*", "/F", "/m", "!", "!!", "#!c", "#!v", "#!cpipe", "#!vala",
2565 		"#!rust", "#!zig", "#!pipe", "#!python", "aeli", "arp", "arpg", "dmd", "drp", "drpg", "o",
2566 		"idp", "idpi", "L", "obf", "o+", "oc", "r2", "rabin2", "rasm2", "rahash2", "rax2",
2567 		"rafind2", "cd", "ls", "on", "op", "wf", "rm", "wF", "wp", "Sd", "Sl", "to", "pm",
2568 		"/m", "zos", "zfd", "zfs", "zfz", "cat", "wta", "wtf", "wxf", "dml", "vi",
2569 		"less", "head", "tail", NULL
2570 	};
2571 	const char *projs[] = {
2572 		"Pc", "Pd", "Pi", "Po", "Ps", "P-", NULL
2573 	};
2574 	const char *mounts[] = {
2575 		"md", "mg", "mo", "ms", "mc", "mi", "mw", NULL
2576 	};
2577 	__foreach (core, flags, R_CORE_AUTOCMPLT_FLAG);
2578 	__foreach (core, seeks, R_CORE_AUTOCMPLT_SEEK);
2579 	__foreach (core, fcns, R_CORE_AUTOCMPLT_FCN);
2580 	__foreach (core, evals, R_CORE_AUTOCMPLT_EVAL);
2581 	__foreach (core, breaks, R_CORE_AUTOCMPLT_BRKP);
2582 	__foreach (core, files, R_CORE_AUTOCMPLT_FILE);
2583 	__foreach (core, projs, R_CORE_AUTOCMPLT_PRJT);
2584 	__foreach (core, mounts, R_CORE_AUTOCMPLT_MS);
2585 
2586 	r_core_autocomplete_add (core->autocomplete, "-", R_CORE_AUTOCMPLT_MINS, true);
2587 	r_core_autocomplete_add (core->autocomplete, "zs", R_CORE_AUTOCMPLT_ZIGN, true);
2588 	r_core_autocomplete_add (core->autocomplete, "fs", R_CORE_AUTOCMPLT_FLSP, true);
2589 	r_core_autocomplete_add (
2590 		r_core_autocomplete_add (core->autocomplete, "ls", R_CORE_AUTOCMPLT_DFLT, true),
2591 		"-l", R_CORE_AUTOCMPLT_FILE, true);
2592 	r_core_autocomplete_add (core->autocomplete, "eco", R_CORE_AUTOCMPLT_THME, true);
2593 	r_core_autocomplete_add (core->autocomplete, "k", R_CORE_AUTOCMPLT_SDB, true);
2594 	/* macros */
2595 	r_core_autocomplete_add (core->autocomplete, ".(", R_CORE_AUTOCMPLT_MACR, true);
2596 	r_core_autocomplete_add (core->autocomplete, "(-", R_CORE_AUTOCMPLT_MACR, true);
2597 	/* just for hints */
2598 	int i;
2599 	for (i = 0; i < radare_argc && radare_argv[i]; i++) {
2600 		if (!r_core_autocomplete_find (core->autocomplete, radare_argv[i], true)) {
2601 			r_core_autocomplete_add (core->autocomplete, radare_argv[i], R_CORE_AUTOCMPLT_DFLT, true);
2602 		}
2603 	}
2604 }
2605 
__init_autocomplete(RCore * core)2606 static void __init_autocomplete(RCore* core) {
2607 	int i;
2608 	core->autocomplete = R_NEW0 (RCoreAutocomplete);
2609 	if (core->autocomplete_type == AUTOCOMPLETE_DEFAULT) {
2610 		__init_autocomplete_default (core);
2611 	} else if (core->autocomplete_type == AUTOCOMPLETE_MS) {
2612 		r_core_autocomplete_add (core->autocomplete, "ls", R_CORE_AUTOCMPLT_MS, true);
2613 		r_core_autocomplete_add (core->autocomplete, "cd", R_CORE_AUTOCMPLT_MS, true);
2614 		r_core_autocomplete_add (core->autocomplete, "cat", R_CORE_AUTOCMPLT_MS, true);
2615 		r_core_autocomplete_add (core->autocomplete, "get", R_CORE_AUTOCMPLT_MS, true);
2616 		r_core_autocomplete_add (core->autocomplete, "mount", R_CORE_AUTOCMPLT_MS, true);
2617 		for (i = 0; i < ms_argc && ms_argv[i]; i++) {
2618 			if (!r_core_autocomplete_find (core->autocomplete, ms_argv[i], true)) {
2619 				r_core_autocomplete_add (core->autocomplete, ms_argv[i], R_CORE_AUTOCMPLT_MS, true);
2620 			}
2621 		}
2622 	}
2623 }
2624 
colorfor_cb(void * user,ut64 addr,bool verbose)2625 static const char *colorfor_cb(void *user, ut64 addr, bool verbose) {
2626 	return r_core_anal_optype_colorfor ((RCore *)user, addr, verbose);
2627 }
2628 
hasrefs_cb(void * user,ut64 addr,int mode)2629 static char *hasrefs_cb(void *user, ut64 addr, int mode) {
2630 	return r_core_anal_hasrefs ((RCore *)user, addr, mode);
2631 }
2632 
get_section_name(void * user,ut64 addr)2633 static const char *get_section_name(void *user, ut64 addr) {
2634 	return r_core_get_section_name ((RCore *)user, addr);
2635 }
2636 
get_comments_cb(void * user,ut64 addr)2637 static char *get_comments_cb(void *user, ut64 addr) {
2638 	return r_core_anal_get_comments ((RCore *)user, addr);
2639 }
2640 
cb_event_handler(REvent * ev,int event_type,void * user,void * data)2641 static void cb_event_handler(REvent *ev, int event_type, void *user, void *data) {
2642 	RCore *core = (RCore *)ev->user;
2643 	if (!core->log_events) {
2644 		return;
2645 	}
2646 	REventMeta *rems = data;
2647 	char *str = r_base64_encode_dyn (rems->string, -1);
2648 	switch (event_type) {
2649 	case R_EVENT_META_SET:
2650 		switch (rems->type) {
2651 		case 'C':
2652 			r_core_log_add (ev->user, sdb_fmt (":add-comment 0x%08"PFMT64x" %s\n", rems->addr, r_str_get (str)));
2653 			break;
2654 		default:
2655 			break;
2656 		}
2657 		break;
2658 	case R_EVENT_META_DEL:
2659 		switch (rems->type) {
2660 		case 'C':
2661 			r_core_log_add (ev->user, sdb_fmt (":del-comment 0x%08"PFMT64x, rems->addr));
2662 			break;
2663 		default:
2664 			r_core_log_add (ev->user, sdb_fmt (":del-comment 0x%08"PFMT64x, rems->addr));
2665 			break;
2666 		}
2667 		break;
2668 	case R_EVENT_META_CLEAR:
2669 		switch (rems->type) {
2670 		case 'C':
2671 			r_core_log_add (ev->user, sdb_fmt (":clear-comments 0x%08"PFMT64x, rems->addr));
2672 			break;
2673 		default:
2674 			r_core_log_add (ev->user, sdb_fmt (":clear-comments 0x%08"PFMT64x, rems->addr));
2675 			break;
2676 		}
2677 		break;
2678 	default:
2679 		// TODO
2680 		break;
2681 	}
2682 	free (str);
2683 }
2684 
core_flg_class_set(RFlag * f,const char * name,ut64 addr,ut32 size)2685 static RFlagItem *core_flg_class_set(RFlag *f, const char *name, ut64 addr, ut32 size) {
2686 	r_flag_space_push (f, R_FLAGS_FS_CLASSES);
2687 	RFlagItem *res = r_flag_set (f, name, addr, size);
2688 	r_flag_space_pop (f);
2689 	return res;
2690 }
2691 
core_flg_class_get(RFlag * f,const char * name)2692 static RFlagItem *core_flg_class_get(RFlag *f, const char *name) {
2693 	r_flag_space_push (f, R_FLAGS_FS_CLASSES);
2694 	RFlagItem *res = r_flag_get (f, name);
2695 	r_flag_space_pop (f);
2696 	return res;
2697 }
2698 
core_flg_fcn_set(RFlag * f,const char * name,ut64 addr,ut32 size)2699 static RFlagItem *core_flg_fcn_set(RFlag *f, const char *name, ut64 addr, ut32 size) {
2700 	r_flag_space_push (f, R_FLAGS_FS_FUNCTIONS);
2701 	RFlagItem *res = r_flag_set (f, name, addr, size);
2702 	r_flag_space_pop (f);
2703 	return res;
2704 }
2705 
r_core_autocomplete_reload(RCore * core)2706 R_API void r_core_autocomplete_reload(RCore *core) {
2707 	r_return_if_fail (core);
2708 	r_core_autocomplete_free (core->autocomplete);
2709 	__init_autocomplete (core);
2710 }
2711 
r_core_flag_get_by_spaces(RFlag * f,ut64 off)2712 R_API RFlagItem *r_core_flag_get_by_spaces(RFlag *f, ut64 off) {
2713 	return r_flag_get_by_spaces (f, off,
2714 		R_FLAGS_FS_FUNCTIONS,
2715 		R_FLAGS_FS_SIGNS,
2716 		R_FLAGS_FS_CLASSES,
2717 		R_FLAGS_FS_SYMBOLS,
2718 		R_FLAGS_FS_IMPORTS,
2719 		R_FLAGS_FS_RELOCS,
2720 		R_FLAGS_FS_STRINGS,
2721 		R_FLAGS_FS_RESOURCES,
2722 		R_FLAGS_FS_SYMBOLS_SECTIONS,
2723 		R_FLAGS_FS_SECTIONS,
2724 		R_FLAGS_FS_SEGMENTS,
2725 		NULL);
2726 }
2727 
2728 #if __WINDOWS__
2729 // XXX move to rcons?
win_eprintf(const char * format,...)2730 static int win_eprintf(const char *format, ...) {
2731 	va_list ap;
2732 	va_start (ap, format);
2733 	r_cons_win_vhprintf (STD_ERROR_HANDLE, false, format, ap);
2734 	va_end (ap);
2735 	return 0;
2736 }
2737 #endif
2738 
ev_iowrite_cb(REvent * ev,int type,void * user,void * data)2739 static void ev_iowrite_cb(REvent *ev, int type, void *user, void *data) {
2740 	RCore *core = user;
2741 	REventIOWrite *iow = data;
2742 	if (r_config_get_i (core->config, "anal.detectwrites")) {
2743 		r_anal_update_analysis_range (core->anal, iow->addr, iow->len);
2744 		if (core->cons->event_resize && core->cons->event_data) {
2745 			// Force a reload of the graph
2746 			core->cons->event_resize (core->cons->event_data);
2747 		}
2748 	}
2749 }
2750 
r_core_init(RCore * core)2751 R_API bool r_core_init(RCore *core) {
2752 	core->blocksize = R_CORE_BLOCKSIZE;
2753 	core->block = (ut8 *)calloc (R_CORE_BLOCKSIZE + 1, 1);
2754 	if (!core->block) {
2755 		r_cons_eprintf ("Cannot allocate %d byte(s)\n", R_CORE_BLOCKSIZE);
2756 		/* XXX memory leak */
2757 		return false;
2758 	}
2759 	r_core_setenv (core);
2760 	core->ev = r_event_new (core);
2761 	r_event_hook (core->ev, R_EVENT_ALL, cb_event_handler, NULL);
2762 	core->max_cmd_depth = R_CONS_CMD_DEPTH + 1;
2763 	core->sdb = sdb_new (NULL, "r2kv.sdb", 0); // XXX: path must be in home?
2764 	core->lastsearch = NULL;
2765 	core->cmdfilter = NULL;
2766 	core->switch_file_view = 0;
2767 	core->cmdremote = 0;
2768 	core->incomment = false;
2769 	core->config = NULL;
2770 	core->prj = r_project_new ();
2771 	core->http_up = false;
2772 	core->use_tree_sitter_r2cmd = false;
2773 	ZERO_FILL (core->root_cmd_descriptor);
2774 	core->print = r_print_new ();
2775 	core->ropchain = r_list_newf ((RListFree)free);
2776 	r_core_bind (core, &(core->print->coreb));
2777 	core->print->user = core;
2778 	core->print->num = core->num;
2779 	core->print->offname = r_core_print_offname;
2780 	core->print->offsize = r_core_print_offsize;
2781 	core->print->cb_printf = r_cons_printf;
2782 #if __WINDOWS__
2783 	core->print->cb_eprintf = win_eprintf;
2784 #endif
2785 	core->print->cb_color = r_cons_rainbow_get;
2786 	core->print->write = mywrite;
2787 	core->print->exists_var = exists_var;
2788 	core->print->disasm = __disasm;
2789 	core->print->colorfor = colorfor_cb;
2790 	core->print->hasrefs = hasrefs_cb;
2791 	core->print->get_comments = get_comments_cb;
2792 	core->print->get_section_name = get_section_name;
2793 	core->print->use_comments = false;
2794 	core->rtr_n = 0;
2795 	core->blocksize_max = R_CORE_BLOCKSIZE_MAX;
2796 	r_core_task_scheduler_init (&core->tasks, core);
2797 	core->watchers = r_list_new ();
2798 	core->watchers->free = (RListFree)r_core_cmpwatch_free;
2799 	core->scriptstack = r_list_new ();
2800 	core->scriptstack->free = (RListFree)free;
2801 	core->log = r_core_log_new ();
2802 	core->times = R_NEW0 (RCoreTimes);
2803 	core->vmode = false;
2804 	core->printidx = 0;
2805 	core->lastcmd = NULL;
2806 	core->cmdlog = NULL;
2807 	core->print->charset->db = sdb_ns (core->sdb, "charset", 1);
2808 	core->print->charset->db->refs++; // increase reference counter to avoid double-free
2809 	// ideally sdb_ns_set should be used here, but it doesnt seems to work well. must fix
2810 	// sdb_ns_set (DB, "charset", core->print->charset->db);
2811 	core->stkcmd = NULL;
2812 	core->cmdqueue = NULL;
2813 	core->cmdrepeat = true;
2814 	core->yank_buf = r_buf_new ();
2815 	core->num = r_num_new (&num_callback, &str_callback, core);
2816 	core->egg = r_egg_new ();
2817 	r_egg_setup (core->egg, R_SYS_ARCH, R_SYS_BITS, 0, R_SYS_OS);
2818 
2819 	core->undos = r_list_newf ((RListFree)r_core_undo_free);
2820 	core->fixedarch = false;
2821 	core->fixedbits = false;
2822 
2823 	core->theme = strdup ("default");
2824 	/* initialize libraries */
2825 	core->cons = r_cons_new ();
2826 	if (core->cons->refcnt == 1) {
2827 		core->cons = r_cons_singleton ();
2828 		if (core->cons->line) {
2829 			core->cons->line->user = core;
2830 			core->cons->line->cb_editor = \
2831 				(RLineEditorCb)&r_core_editor;
2832 			core->cons->line->cb_fkey = core->cons->cb_fkey;
2833 		}
2834 #if __EMSCRIPTEN__
2835 		core->cons->user_fgets = NULL;
2836 #else
2837 		core->cons->user_fgets = (void *)r_core_fgets;
2838 #endif
2839 		//r_line_singleton ()->user = (void *)core;
2840 		r_line_hist_load (R2_HOME_HISTORY);
2841 	}
2842 	core->print->cons = core->cons;
2843 	r_cons_bind (&core->print->consbind);
2844 
2845 	// We save the old num ad user, in order to restore it after free
2846 	core->lang = r_lang_new ();
2847 	core->lang->cmd_str = (char *(*)(void *, const char *))r_core_cmd_str;
2848 	core->lang->cmdf = (int (*)(void *, const char *, ...))r_core_cmdf;
2849 	r_core_bind_cons (core);
2850 	core->table = NULL;
2851 	core->lang->cb_printf = r_cons_printf;
2852 	r_lang_define (core->lang, "RCore", "core", core);
2853 	r_lang_set_user_ptr (core->lang, core);
2854 	core->rasm = r_asm_new ();
2855 	core->rasm->num = core->num;
2856 	r_asm_set_user_ptr (core->rasm, core);
2857 	core->anal = r_anal_new ();
2858 	core->gadgets = r_list_newf ((RListFree)r_core_gadget_free);
2859 	core->anal->ev = core->ev;
2860 	core->anal->log = r_core_anal_log;
2861 	core->anal->read_at = r_core_anal_read_at;
2862 	core->anal->flag_get = r_core_flag_get_by_spaces;
2863 	core->anal->cb.on_fcn_new = on_fcn_new;
2864 	core->anal->cb.on_fcn_delete = on_fcn_delete;
2865 	core->anal->cb.on_fcn_rename = on_fcn_rename;
2866 	core->print->sdb_types = core->anal->sdb_types;
2867 	core->rasm->syscall = r_syscall_ref (core->anal->syscall); // BIND syscall anal/asm
2868 	r_anal_set_user_ptr (core->anal, core);
2869 	core->anal->cb_printf = (void *) r_cons_printf;
2870 	core->parser = r_parse_new ();
2871 	r_anal_bind (core->anal, &(core->parser->analb));
2872 	core->parser->varlist = r_anal_function_get_var_fields;
2873 	/// XXX shouhld be using coreb
2874 	r_parse_set_user_ptr (core->parser, core);
2875 	core->bin = r_bin_new ();
2876 	r_cons_bind (&core->bin->consb);
2877 	// XXX we shuold use RConsBind instead of this hardcoded pointer
2878 	core->bin->cb_printf = (PrintfCallback) r_cons_printf;
2879 	r_bin_set_user_ptr (core->bin, core);
2880 	core->io = r_io_new ();
2881 	r_event_hook (core->io->event, R_EVENT_IO_WRITE, ev_iowrite_cb, core);
2882 	core->io->ff = 1;
2883 	core->search = r_search_new (R_SEARCH_KEYWORD);
2884 	r_io_undo_enable (core->io, 1, 0); // TODO: configurable via eval
2885 	core->fs = r_fs_new ();
2886 	core->flags = r_flag_new ();
2887 	core->flags->cb_printf = r_cons_printf;
2888 	core->graph = r_agraph_new (r_cons_canvas_new (1, 1));
2889 	core->graph->need_reload_nodes = false;
2890 	core->asmqjmps_size = R_CORE_ASMQJMPS_NUM;
2891 	if (sizeof (ut64) * core->asmqjmps_size < core->asmqjmps_size) {
2892 		core->asmqjmps_size = 0;
2893 		core->asmqjmps = NULL;
2894 	} else {
2895 		core->asmqjmps = R_NEWS (ut64, core->asmqjmps_size);
2896 	}
2897 
2898 	r_bin_bind (core->bin, &(core->rasm->binb));
2899 	r_bin_bind (core->bin, &(core->anal->binb));
2900 	r_bin_bind (core->bin, &(core->anal->binb));
2901 
2902 	r_io_bind (core->io, &(core->search->iob));
2903 	r_io_bind (core->io, &(core->print->iob));
2904 	r_io_bind (core->io, &(core->anal->iob));
2905 	r_io_bind (core->io, &(core->fs->iob));
2906 	r_cons_bind (&(core->fs->csb));
2907 	r_core_bind (core, &(core->fs->cob));
2908 	r_io_bind (core->io, &(core->bin->iob));
2909 	r_flag_bind (core->flags, &(core->anal->flb));
2910 	core->anal->flg_class_set = core_flg_class_set;
2911 	core->anal->flg_class_get = core_flg_class_get;
2912 	core->anal->flg_fcn_set = core_flg_fcn_set;
2913 	r_anal_bind (core->anal, &(core->parser->analb));
2914 	core->parser->flag_get = r_core_flag_get_by_spaces;
2915 	core->parser->label_get = r_anal_function_get_label_at;
2916 
2917 	r_core_bind (core, &(core->anal->coreb));
2918 
2919 	core->offset = 0LL;
2920 	core->prompt_offset = 0LL;
2921 	r_core_cmd_init (core);
2922 	core->dbg = r_debug_new (true);
2923 
2924 	r_io_bind (core->io, &(core->dbg->iob));
2925 	r_io_bind (core->io, &(core->dbg->bp->iob));
2926 	r_core_bind (core, &core->dbg->corebind);
2927 	r_core_bind (core, &core->dbg->bp->corebind);
2928 	r_core_bind (core, &core->io->corebind);
2929 	core->dbg->anal = core->anal; // XXX: dupped instance.. can cause lost pointerz
2930 	//r_debug_use (core->dbg, "native");
2931 // XXX pushing uninitialized regstate results in trashed reg values
2932 //	r_reg_arena_push (core->dbg->reg); // create a 2 level register state stack
2933 //	core->dbg->anal->reg = core->anal->reg; // XXX: dupped instance.. can cause lost pointerz
2934 	core->io->cb_printf = r_cons_printf;
2935 	core->dbg->cb_printf = r_cons_printf;
2936 	core->dbg->bp->cb_printf = r_cons_printf;
2937 	core->dbg->ev = core->ev;
2938 	// initialize config before any corebind
2939 	r_core_config_init (core);
2940 
2941 	r_core_loadlibs_init (core);
2942 	//r_core_loadlibs (core);
2943 
2944 	// TODO: get arch from r_bin or from native arch
2945 	r_asm_use (core->rasm, R_SYS_ARCH);
2946 	r_anal_use (core->anal, R_SYS_ARCH);
2947 	if (R_SYS_BITS & R_SYS_BITS_64) {
2948 		r_config_set_i (core->config, "asm.bits", 64);
2949 	} else {
2950 		if (R_SYS_BITS & R_SYS_BITS_32) {
2951 			r_config_set_i (core->config, "asm.bits", 32);
2952 		}
2953 	}
2954 	r_config_set (core->config, "asm.arch", R_SYS_ARCH);
2955 	r_bp_use (core->dbg->bp, R_SYS_ARCH, core->anal->bits);
2956 	update_sdb (core);
2957 	{
2958 		char *a = r_str_r2_prefix (R2_FLAGS);
2959 		if (a) {
2960 			char *file = r_str_newf ("%s/tags.r2", a);
2961 			bool p = core->print->enable_progressbar;
2962 			core->print->enable_progressbar = false;
2963 			(void)r_core_run_script (core, file);
2964 			core->print->enable_progressbar = p;
2965 			free (file);
2966 			free (a);
2967 		}
2968 	}
2969 	r_core_anal_type_init (core);
2970 	__init_autocomplete (core);
2971 	return 0;
2972 }
2973 
__cons_cb_fkey(RCore * core,int fkey)2974 R_API void __cons_cb_fkey(RCore *core, int fkey) {
2975 	char buf[32];
2976 	snprintf (buf, sizeof (buf), "key.f%d", fkey);
2977 	const char *v = r_config_get (core->config, buf);
2978 	if (v && *v) {
2979 		r_cons_printf ("%s\n", v);
2980 		r_core_cmd0 (core, v);
2981 		r_cons_flush ();
2982 	}
2983 }
2984 
r_core_bind_cons(RCore * core)2985 R_API void r_core_bind_cons(RCore *core) {
2986 	core->cons->num = core->num;
2987 	core->cons->cb_fkey = (RConsFunctionKey)__cons_cb_fkey;
2988 	core->cons->cb_editor = (RConsEditorCallback)r_core_editor;
2989 	core->cons->cb_break = (RConsBreakCallback)r_core_break;
2990 	core->cons->cb_sleep_begin = (RConsSleepBeginCallback)r_core_sleep_begin;
2991 	core->cons->cb_sleep_end = (RConsSleepEndCallback)r_core_sleep_end;
2992 	core->cons->cb_task_oneshot = (RConsQueueTaskOneshot) r_core_task_enqueue_oneshot;
2993 	core->cons->user = (void*)core;
2994 }
2995 
r_core_fini(RCore * c)2996 R_API void r_core_fini(RCore *c) {
2997 	if (!c) {
2998 		return;
2999 	}
3000 	r_core_task_break_all (&c->tasks);
3001 	r_core_task_join (&c->tasks, NULL, -1);
3002 	r_core_wait (c);
3003 	/* TODO: it leaks as shit */
3004 	//update_sdb (c);
3005 	// avoid double free
3006 	r_list_free (c->ropchain);
3007 	r_table_free (c->table);
3008 	r_event_free (c->ev);
3009 	free (c->cmdlog);
3010 	free (c->lastsearch);
3011 	R_FREE (c->cons->pager);
3012 	free (c->cmdqueue);
3013 	free (c->lastcmd);
3014 	free (c->stkcmd);
3015 	r_project_free (c->prj);
3016 	r_list_free (c->visual.tabs);
3017 	free (c->block);
3018 	r_core_autocomplete_free (c->autocomplete);
3019 
3020 	r_list_free (c->gadgets);
3021 	r_list_free (c->undos);
3022 	r_num_free (c->num);
3023 	// TODO: sync or not? sdb_sync (c->sdb);
3024 	// TODO: sync all dbs?
3025 	//c->file = NULL;
3026 	R_FREE (c->table_query);
3027 	r_list_free (c->watchers);
3028 	r_list_free (c->scriptstack);
3029 	r_core_task_scheduler_fini (&c->tasks);
3030 	c->rcmd = r_cmd_free (c->rcmd);
3031 	r_list_free (c->cmd_descriptors);
3032 	c->anal = r_anal_free (c->anal);
3033 	r_asm_free (c->rasm);
3034 	c->rasm = NULL;
3035 	c->print = r_print_free (c->print);
3036 	c->bin = (r_bin_free (c->bin), NULL);
3037 	c->dbg = (r_debug_free (c->dbg), NULL);
3038 	c->io = (r_io_free (c->io), NULL);
3039 	c->lang = (r_lang_free (c->lang), NULL);
3040 	r_config_free (c->config);
3041 	/* after r_config_free, the value of I.teefile is trashed */
3042 	/* rconfig doesnt knows how to deinitialize vars, so we
3043 	should probably need to add a r_config_free_payload callback */
3044 	r_cons_free ();
3045 	r_cons_singleton ()->teefile = NULL; // HACK
3046 	free (c->theme);
3047 	r_search_free (c->search);
3048 	r_flag_free (c->flags);
3049 	r_fs_free (c->fs);
3050 	r_egg_free (c->egg);
3051 	r_lib_free (c->lib);
3052 	r_buf_free (c->yank_buf);
3053 	r_agraph_free (c->graph);
3054 	free (c->asmqjmps);
3055 	sdb_free (c->sdb);
3056 	r_core_log_free (c->log);
3057 	r_parse_free (c->parser);
3058 	free (c->times);
3059 }
3060 
r_core_free(RCore * c)3061 R_API void r_core_free(RCore *c) {
3062 	if (c) {
3063 		r_core_fini (c);
3064 		free (c);
3065 	}
3066 }
3067 
r_core_prompt_loop(RCore * r)3068 R_API void r_core_prompt_loop(RCore *r) {
3069 	int ret;
3070 	do {
3071 		int err = r_core_prompt (r, false);
3072 		if (err < 1) {
3073 			// handle ^D
3074 			r->num->value = 0; // r.num->value will be read by r_main_radare2() after calling this fcn
3075 			break;
3076 		}
3077 		/* -1 means invalid command, -2 means quit prompt loop */
3078 		if ((ret = r_core_prompt_exec (r)) == -2) {
3079 			break;
3080 		}
3081 	} while (ret != R_CORE_CMD_EXIT);
3082 }
3083 
prompt_flag(RCore * r,char * s,size_t maxlen)3084 static int prompt_flag (RCore *r, char *s, size_t maxlen) {
3085 	const char DOTS[] = "...";
3086 	const RFlagItem *f = r_flag_get_at (r->flags, r->offset, false);
3087 	if (!f) {
3088 		return false;
3089 	}
3090 	if (f->offset < r->offset) {
3091 		snprintf (s, maxlen, "%s + %" PFMT64u, f->name, r->offset - f->offset);
3092 	} else {
3093 		snprintf (s, maxlen, "%s", f->name);
3094 	}
3095 	if (strlen (s) > maxlen - sizeof (DOTS)) {
3096 		s[maxlen - sizeof (DOTS) - 1] = '\0';
3097 		strcat (s, DOTS);
3098 	}
3099 	return true;
3100 }
3101 
prompt_sec(RCore * r,char * s,size_t maxlen)3102 static void prompt_sec(RCore *r, char *s, size_t maxlen) {
3103 	const RBinSection *sec = r_bin_get_section_at (r_bin_cur_object (r->bin), r->offset, true);
3104 	if (!sec) {
3105 		return;
3106 	}
3107 	r_str_ncpy (s, sec->name, maxlen - 2);
3108 	strcat (s, ":");
3109 }
3110 
chop_prompt(const char * filename,char * tmp,size_t max_tmp_size)3111 static void chop_prompt (const char *filename, char *tmp, size_t max_tmp_size) {
3112 	size_t tmp_len, file_len;
3113 	unsigned int OTHRSCH = 3;
3114 	const char DOTS[] = "...";
3115 	int w, p_len;
3116 
3117 	w = r_cons_get_size (NULL);
3118 	file_len = strlen (filename);
3119 	tmp_len = strlen (tmp);
3120 	p_len = R_MAX (0, w - 6);
3121 	if (file_len + tmp_len + OTHRSCH >= p_len) {
3122 		size_t dots_size = sizeof (DOTS);
3123 		size_t chop_point = (size_t)(p_len - OTHRSCH - file_len - dots_size);
3124 		if (chop_point < max_tmp_size - dots_size) {
3125 			snprintf (tmp + chop_point, dots_size, "%s", DOTS);
3126 		}
3127 	}
3128 }
3129 
set_prompt(RCore * r)3130 static void set_prompt (RCore *r) {
3131 	char tmp[128];
3132 	char *filename = strdup ("");
3133 	const char *cmdprompt = r_config_get (r->config, "cmd.prompt");
3134 	const char *BEGIN = "";
3135 	const char *END = "";
3136 	const char *remote = "";
3137 
3138 	if (cmdprompt && *cmdprompt) {
3139 		r_core_cmd (r, cmdprompt, 0);
3140 	}
3141 
3142 	if (r_config_get_i (r->config, "scr.prompt.file")) {
3143 		free (filename);
3144 		filename = r_str_newf ("\"%s\"",
3145 			r->io->desc ? r_file_basename (r->io->desc->name) : "");
3146 	}
3147 	if (r->cmdremote) {
3148 		char *s = r_core_cmd_str (r, "s");
3149 		r->offset = r_num_math (NULL, s);
3150 		free (s);
3151 		remote = "=!";
3152 	}
3153 
3154 	if (r_config_get_i (r->config, "scr.color")) {
3155 		BEGIN = r->cons->context->pal.prompt;
3156 		END = r->cons->context->pal.reset;
3157 	}
3158 
3159 	// TODO: also in visual prompt and disasm/hexdump ?
3160 	if (r_config_get_i (r->config, "asm.segoff")) {
3161 		ut32 a, b;
3162 		unsigned int seggrn = r_config_get_i (r->config, "asm.seggrn");
3163 
3164 		a = ((r->offset >> 16) << (16 - seggrn));
3165 		b = (r->offset & 0xffff);
3166 		snprintf (tmp, 128, "%04x:%04x", a, b);
3167 	} else {
3168 		char p[64], sec[32];
3169 		int promptset = false;
3170 
3171 		sec[0] = '\0';
3172 		if (r_config_get_i (r->config, "scr.prompt.flag")) {
3173 			promptset = prompt_flag (r, p, sizeof (p));
3174 		}
3175 		if (r_config_get_i (r->config, "scr.prompt.sect")) {
3176 			prompt_sec (r, sec, sizeof (sec));
3177 		}
3178 
3179 		if (!promptset) {
3180 			if (r->print->wide_offsets && r->dbg->bits & R_SYS_BITS_64) {
3181 				snprintf (p, sizeof (p), "0x%016" PFMT64x, r->offset);
3182 			} else {
3183 				snprintf (p, sizeof (p), "0x%08" PFMT64x, r->offset);
3184 			}
3185 		}
3186 		snprintf (tmp, sizeof (tmp), "%s%s", sec, p);
3187 	}
3188 
3189 	chop_prompt (filename, tmp, 128);
3190 	char *prompt = r_str_newf ("%s%s[%s%s]>%s ", filename, BEGIN, remote,
3191 		tmp, END);
3192 	r_line_set_prompt (r_str_get (prompt));
3193 
3194 	R_FREE (filename);
3195 	R_FREE (prompt);
3196 }
3197 
r_core_prompt(RCore * r,int sync)3198 R_API int r_core_prompt(RCore *r, int sync) {
3199 	char line[4096];
3200 
3201 	int rnv = r->num->value;
3202 	set_prompt (r);
3203 	int ret = r_cons_fgets (line, sizeof (line), 0, NULL);
3204 	if (ret == -2) {
3205 		return R_CORE_CMD_EXIT; // ^D
3206 	}
3207 	if (ret == -1) {
3208 		return false; // FD READ ERROR
3209 	}
3210 	r->num->value = rnv;
3211 	if (sync) {
3212 		return r_core_prompt_exec (r);
3213 	}
3214 	free (r->cmdqueue);
3215 	r->cmdqueue = strdup (line);
3216         if (r->scr_gadgets && *line && *line != 'q') {
3217                 r_core_cmd0 (r, "pg");
3218         }
3219 	r->num->value = r->rc;
3220 	return true;
3221 }
3222 
3223 extern void r_core_echo(RCore *core, const char *input);
3224 
r_core_prompt_exec(RCore * r)3225 R_API int r_core_prompt_exec(RCore *r) {
3226 	int ret = r_core_cmd (r, r->cmdqueue, true);
3227 	r->rc = r->num->value;
3228 	//int ret = r_core_cmd (r, r->cmdqueue, true);
3229 	if (r->cons && r->cons->use_tts) {
3230 		const char *buf = r_cons_get_buffer();
3231 		r_sys_tts (buf, true);
3232 		r->cons->use_tts = false;
3233 	}
3234 	r_cons_echo (NULL);
3235 	r_cons_flush ();
3236 	if (r->cons && r->cons->line && r->cons->line->zerosep) {
3237 		r_cons_zero ();
3238 	}
3239 	return ret;
3240 }
3241 
r_core_seek_size(RCore * core,ut64 addr,int bsize)3242 R_API int r_core_seek_size(RCore *core, ut64 addr, int bsize) {
3243 	ut8 *bump;
3244 	int ret = false;
3245 	if (bsize < 0) {
3246 		return false;
3247 	}
3248 	if (bsize == core->blocksize) {
3249 		return true;
3250 	}
3251 	if (r_sandbox_enable (0)) {
3252 		// TODO : restrict to filesize?
3253 		if (bsize > 1024 * 32) {
3254 			r_cons_eprintf ("Sandbox mode restricts blocksize bigger than 32k\n");
3255 			return false;
3256 		}
3257 	}
3258 	if (bsize > core->blocksize_max) {
3259 		r_cons_eprintf ("Block size %d is too big\n", bsize);
3260 		return false;
3261 	}
3262 	core->offset = addr;
3263 	if (bsize < 1) {
3264 		bsize = 1;
3265 	} else if (core->blocksize_max && bsize>core->blocksize_max) {
3266 		r_cons_eprintf ("bsize is bigger than `bm`. dimmed to 0x%x > 0x%x\n",
3267 			bsize, core->blocksize_max);
3268 		bsize = core->blocksize_max;
3269 	}
3270 	bump = realloc (core->block, bsize + 1);
3271 	if (!bump) {
3272 		r_cons_eprintf ("Oops. cannot allocate that much (%u)\n", bsize);
3273 		ret = false;
3274 	} else {
3275 		ret = true;
3276 		core->block = bump;
3277 		core->blocksize = bsize;
3278 		memset (core->block, 0xff, core->blocksize);
3279 		r_core_block_read (core);
3280 	}
3281 	return ret;
3282 }
3283 
r_core_block_size(RCore * core,int bsize)3284 R_API int r_core_block_size(RCore *core, int bsize) {
3285 	return r_core_seek_size (core, core->offset, bsize);
3286 }
3287 
r_core_seek_align(RCore * core,ut64 align,int times)3288 R_API int r_core_seek_align(RCore *core, ut64 align, int times) {
3289 	int inc = (times >= 0)? 1: -1;
3290 	ut64 seek = core->offset;
3291 	if (!align) {
3292 		return false;
3293 	}
3294 	int diff = core->offset % align;
3295 	if (!times) {
3296 		diff = -diff;
3297 	} else if (diff) {
3298 		if (inc > 0) {
3299 			diff += align-diff;
3300 		} else {
3301 			diff = -diff;
3302 		}
3303 		if (times) {
3304 			times -= inc;
3305 		}
3306 	}
3307 	while ((times*inc) > 0) {
3308 		times -= inc;
3309 		diff += (align * inc);
3310 	}
3311 	if (diff < 0 && -diff > seek) {
3312 		seek = diff = 0;
3313 	}
3314 	return r_core_seek (core, seek + diff, true);
3315 }
3316 
r_core_op_str(RCore * core,ut64 addr)3317 R_API char *r_core_op_str(RCore *core, ut64 addr) {
3318 	RAsmOp op = {0};
3319 	ut8 buf[64];
3320 	r_asm_set_pc (core->rasm, addr);
3321 	r_io_read_at (core->io, addr, buf, sizeof (buf));
3322 	int ret = r_asm_disassemble (core->rasm, &op, buf, sizeof (buf));
3323 	char *str = (ret > 0)? strdup (r_strbuf_get (&op.buf_asm)): NULL;
3324 	r_asm_op_fini (&op);
3325 	return str;
3326 }
3327 
r_core_op_anal(RCore * core,ut64 addr,RAnalOpMask mask)3328 R_API RAnalOp *r_core_op_anal(RCore *core, ut64 addr, RAnalOpMask mask) {
3329 	ut8 buf[64];
3330 	RAnalOp *op = R_NEW (RAnalOp);
3331 	r_io_read_at (core->io, addr, buf, sizeof (buf));
3332 	r_anal_op (core->anal, op, addr, buf, sizeof (buf), mask);
3333 	return op;
3334 }
3335 
rap_break(void * u)3336 static void rap_break (void *u) {
3337 	RIORap *rior = (RIORap*) u;
3338 	if (u) {
3339 		r_socket_close (rior->fd);
3340 		rior->fd = NULL;
3341 	}
3342 }
3343 
3344 // TODO: PLEASE move into core/io/rap? */
3345 // TODO: use static buffer instead of mallocs all the time. it's network!
r_core_serve(RCore * core,RIODesc * file)3346 R_API bool r_core_serve(RCore *core, RIODesc *file) {
3347 	// TODO: use r_socket_rap_server API instead of duplicating the logic
3348 	ut8 cmd, flg, *ptr = NULL, buf[1024];
3349 	int i, pipefd = -1;
3350 	ut64 x;
3351 
3352 	RIORap *rior = (RIORap *)file->data;
3353 	if (!rior || !rior->fd) {
3354 		r_cons_eprintf ("rap: cannot listen.\n");
3355 		return false;
3356 	}
3357 	RSocket *fd = rior->fd;
3358 	r_cons_eprintf ("RAP Server started (rap.loop=%s)\n",
3359 			r_config_get (core->config, "rap.loop"));
3360 	r_cons_break_push (rap_break, rior);
3361 reaccept:
3362 	while (!r_cons_is_breaked ()) {
3363 		RSocket *c = r_socket_accept (fd);
3364 		if (!c) {
3365 			break;
3366 		}
3367 		if (r_cons_is_breaked ()) {
3368 			goto out_of_function;
3369 		}
3370 		if (!c) {
3371 			r_cons_eprintf ("rap: cannot accept\n");
3372 			r_socket_free (c);
3373 			goto out_of_function;
3374 		}
3375 		r_cons_eprintf ("rap: client connected\n");
3376 		for (;!r_cons_is_breaked ();) {
3377 			if (!r_socket_read_block (c, &cmd, 1)) {
3378 				r_cons_eprintf ("rap: connection closed\n");
3379 				if (r_config_get_i (core->config, "rap.loop")) {
3380 					r_cons_eprintf ("rap: waiting for new connection\n");
3381 					r_socket_free (c);
3382 					goto reaccept;
3383 				}
3384 				goto out_of_function;
3385 			}
3386 			switch (cmd) {
3387 			case RAP_PACKET_OPEN:
3388 				r_socket_read_block (c, &flg, 1); // flags
3389 				r_cons_eprintf ("open (%d): ", cmd);
3390 				r_socket_read_block (c, &cmd, 1); // len
3391 				pipefd = -1;
3392 				if (UT8_ADD_OVFCHK (cmd, 1)) {
3393 					goto out_of_function;
3394 				}
3395 				ptr = malloc ((size_t)cmd + 1);
3396 				if (!ptr) {
3397 					r_cons_eprintf ("Cannot malloc in rmt-open len = %d\n", cmd);
3398 				} else {
3399 					ut64 baddr = r_config_get_i (core->config, "bin.laddr");
3400 					r_socket_read_block (c, ptr, cmd);
3401 					ptr[cmd] = 0;
3402 					ut32 perm = R_PERM_R;
3403 					if (flg & R_PERM_W) {
3404 						perm |= R_PERM_W;
3405 					}
3406 					if (r_core_file_open (core, (const char *)ptr, perm, 0)) {
3407 						int fd = r_io_fd_get_current (core->io);
3408 						r_core_bin_load (core, NULL, baddr);
3409 						r_io_map_add (core->io, fd, perm, 0, 0, r_io_fd_size (core->io, fd));
3410 						if (core->io->desc) {
3411 							pipefd = fd;
3412 						} else {
3413 							pipefd = -1;
3414 						}
3415 						r_cons_eprintf ("(flags: %d) len: %d filename: '%s'\n",
3416 							flg, cmd, ptr); //config.file);
3417 					} else {
3418 						pipefd = -1;
3419 						r_cons_eprintf ("Cannot open file (%s)\n", ptr);
3420 						r_socket_close (c);
3421 						if (r_config_get_i (core->config, "rap.loop")) {
3422 							r_cons_eprintf ("rap: waiting for new connection\n");
3423 							r_socket_free (c);
3424 							goto reaccept;
3425 						}
3426 						goto out_of_function; //XXX: Close connection and goto accept
3427 					}
3428 				}
3429 				buf[0] = RAP_PACKET_OPEN | RAP_PACKET_REPLY;
3430 				r_write_be32 (buf + 1, pipefd);
3431 				r_socket_write (c, buf, 5);
3432 				r_socket_flush (c);
3433 				R_FREE (ptr);
3434 				break;
3435 			case RAP_PACKET_READ:
3436 				r_socket_read_block (c, (ut8*)&buf, 4);
3437 				i = r_read_be32 (buf);
3438 				ptr = (ut8 *)malloc (i + core->blocksize + 5);
3439 				if (ptr) {
3440 					r_core_block_read (core);
3441 					ptr[0] = RAP_PACKET_READ | RAP_PACKET_REPLY;
3442 					if (i > RAP_PACKET_MAX) {
3443 						i = RAP_PACKET_MAX;
3444 					}
3445 					if (i > core->blocksize) {
3446 						r_core_block_size (core, i);
3447 					}
3448 					if (i + 128 < core->blocksize) {
3449 						r_core_block_size (core, i);
3450 					}
3451 					r_write_be32 (ptr + 1, i);
3452 					memcpy (ptr + 5, core->block, i); //core->blocksize);
3453 					r_socket_write (c, ptr, i + 5);
3454 					r_socket_flush (c);
3455 					R_FREE (ptr);
3456 				} else {
3457 					r_cons_eprintf ("Cannot read %d byte(s)\n", i);
3458 					r_socket_free (c);
3459 					// TODO: reply error here
3460 					goto out_of_function;
3461 				}
3462 				break;
3463 			case RAP_PACKET_CMD:
3464 				{
3465 				char *cmd = NULL, *cmd_output = NULL;
3466 				char bufr[8], *bufw = NULL;
3467 				ut32 cmd_len = 0;
3468 				int i;
3469 
3470 				/* read */
3471 				r_socket_read_block (c, (ut8*)&bufr, 4);
3472 				i = r_read_be32 (bufr);
3473 				if (i > 0 && i < RAP_PACKET_MAX) {
3474 					if ((cmd = malloc (i + 1))) {
3475 						r_socket_read_block (c, (ut8*)cmd, i);
3476 						cmd[i] = '\0';
3477 						int scr_interactive = r_config_get_i (core->config, "scr.interactive");
3478 						r_config_set_i (core->config, "scr.interactive", 0);
3479 						cmd_output = r_core_cmd_str (core, cmd);
3480 						r_config_set_i (core->config, "scr.interactive", scr_interactive);
3481 						free (cmd);
3482 					} else {
3483 						r_cons_eprintf ("rap: cannot malloc\n");
3484 					}
3485 				} else {
3486 					r_cons_eprintf ("rap: invalid length '%d'\n", i);
3487 				}
3488 				/* write */
3489 				if (cmd_output) {
3490 					cmd_len = strlen (cmd_output) + 1;
3491 				} else {
3492 					cmd_output = strdup ("");
3493 					cmd_len = 0;
3494 				}
3495 #if DEMO_SERVER_SENDS_CMD_TO_CLIENT
3496 				static bool once = true;
3497 				/* TODO: server can reply a command request to the client only here */
3498 				if (once) {
3499 					const char *cmd = "pd 4";
3500 					int cmd_len = strlen (cmd) + 1;
3501 					ut8 *b = malloc (cmd_len + 5);
3502 					b[0] = RAP_PACKET_CMD;
3503 					r_write_be32 (b + 1, cmd_len);
3504 					strcpy ((char *)b+ 5, cmd);
3505 					r_socket_write (c, b, 5 + cmd_len);
3506 					r_socket_flush (c);
3507 
3508 					/* read response */
3509 					r_socket_read_block (c, b, 5);
3510 					if (b[0] == (RAP_PACKET_CMD | RAP_PACKET_REPLY)) {
3511 						ut32 n = r_read_be32 (b + 1);
3512 						r_cons_eprintf ("REPLY %d\n", n);
3513 						if (n > 0) {
3514 							ut8 *res = calloc (1, n);
3515 							r_socket_read_block (c, res, n);
3516 							r_cons_eprintf ("RESPONSE(%s)\n", (const char *)res);
3517 							free (res);
3518 						}
3519 					}
3520 					r_socket_flush (c);
3521 					free (b);
3522 					once = false;
3523 				}
3524 #endif
3525 				bufw = malloc (cmd_len + 5);
3526 				bufw[0] = (ut8) (RAP_PACKET_CMD | RAP_PACKET_REPLY);
3527 				r_write_be32 (bufw + 1, cmd_len);
3528 				memcpy (bufw + 5, cmd_output, cmd_len);
3529 				r_socket_write (c, bufw, cmd_len+5);
3530 				r_socket_flush (c);
3531 				free (bufw);
3532 				free (cmd_output);
3533 				break;
3534 				}
3535 			case RAP_PACKET_WRITE:
3536 				r_socket_read_block (c, buf, 4);
3537 				x = r_read_at_be32 (buf, 0);
3538 				ptr = malloc (x);
3539 				r_socket_read_block (c, ptr, x);
3540 				int ret = r_core_write_at (core, core->offset, ptr, x);
3541 				buf[0] = RAP_PACKET_WRITE | RAP_PACKET_REPLY;
3542 				r_write_be32 (buf + 1, ret);
3543 				r_socket_write (c, buf, 5);
3544 				r_socket_flush (c);
3545 				R_FREE (ptr);
3546 				break;
3547 			case RAP_PACKET_SEEK:
3548 				r_socket_read_block (c, buf, 9);
3549 				x = r_read_at_be64 (buf, 1);
3550 				if (buf[0] == 2) {
3551 					if (core->io->desc) {
3552 						x = r_io_fd_size (core->io, core->io->desc->fd);
3553 					} else {
3554 						x = 0;
3555 					}
3556 				} else {
3557 					if (buf[0] == 0) {
3558 						r_core_seek (core, x, true); //buf[0]);
3559 					}
3560 					x = core->offset;
3561 				}
3562 				buf[0] = RAP_PACKET_SEEK | RAP_PACKET_REPLY;
3563 				r_write_be64 (buf + 1, x);
3564 				r_socket_write (c, buf, 9);
3565 				r_socket_flush (c);
3566 				break;
3567 			case RAP_PACKET_CLOSE:
3568 				// XXX : proper shutdown
3569 				r_socket_read_block (c, buf, 4);
3570 				i = r_read_be32 (buf);
3571 				{
3572 				//FIXME: Use r_socket_close
3573 				int ret = close (i);
3574 				r_write_be32 (buf + 1, ret);
3575 				buf[0] = RAP_PACKET_CLOSE | RAP_PACKET_REPLY;
3576 				r_socket_write (c, buf, 5);
3577 				r_socket_flush (c);
3578 				}
3579 				break;
3580 			default:
3581 				if (cmd == 'G') {
3582 					// silly http emulation over rap://
3583 					char line[256] = {0};
3584 					r_socket_read_block (c, (ut8*)line, sizeof (line));
3585 					if (!strncmp (line, "ET /cmd/", 8)) {
3586 						char *cmd = line + 8;
3587 						char *http = strstr (cmd, "HTTP");
3588 						if (http) {
3589 							*http = 0;
3590 							http--;
3591 							if (*http == ' ') {
3592 								*http = 0;
3593 							}
3594 						}
3595 						r_str_uri_decode (cmd);
3596 						char *res = r_core_cmd_str (core, cmd);
3597 						if (res) {
3598 							r_socket_printf (c, "HTTP/1.0 %d %s\r\n%s"
3599 									"Connection: close\r\nContent-Length: %d\r\n\r\n",
3600 									200, "OK", "", -1); // strlen (res));
3601 							r_socket_write (c, res, strlen (res));
3602 							free (res);
3603 						}
3604 						r_socket_flush (c);
3605 						r_socket_close (c);
3606 					}
3607 				} else {
3608 					r_cons_eprintf ("[rap] unknown command 0x%02x\n", cmd);
3609 					r_socket_close (c);
3610 					R_FREE (ptr);
3611 				}
3612 				if (r_config_get_i (core->config, "rap.loop")) {
3613 					r_cons_eprintf ("rap: waiting for new connection\n");
3614 					r_socket_free (c);
3615 					goto reaccept;
3616 				}
3617 				goto out_of_function;
3618 			}
3619 		}
3620 		r_cons_eprintf ("client: disconnected\n");
3621 		r_socket_free (c);
3622 	}
3623 out_of_function:
3624 	r_cons_break_pop ();
3625 	return false;
3626 }
3627 
r_core_search_cb(RCore * core,ut64 from,ut64 to,RCoreSearchCallback cb)3628 R_API int r_core_search_cb(RCore *core, ut64 from, ut64 to, RCoreSearchCallback cb) {
3629 	int ret, len = core->blocksize;
3630 	ut8 *buf = malloc (len);
3631 	if (!buf) {
3632 		r_cons_eprintf ("Cannot allocate blocksize\n");
3633 		return false;
3634 	}
3635 	while (from < to) {
3636 		ut64 delta = to-from;
3637 		if (delta < len) {
3638 			len = (int)delta;
3639 		}
3640 		if (!r_io_read_at (core->io, from, buf, len)) {
3641 			r_cons_eprintf ("Cannot read at 0x%"PFMT64x"\n", from);
3642 			break;
3643 		}
3644 		for (ret = 0; ret < len;) {
3645 			int done = cb (core, from, buf+ret, len-ret);
3646 			if (done < 1) { /* interrupted */
3647 				free (buf);
3648 				return false;
3649 			}
3650 			ret += done;
3651 		}
3652 		from += len;
3653 	}
3654 	free (buf);
3655 	return true;
3656 }
3657 
r_core_editor(const RCore * core,const char * file,const char * str)3658 R_API char *r_core_editor(const RCore *core, const char *file, const char *str) {
3659 	const bool interactive = r_cons_is_interactive ();
3660 	const char *editor = r_config_get (core->config, "cfg.editor");
3661 	char *name = NULL, *ret = NULL;
3662 	int fd;
3663 
3664 	if (!interactive || !editor || !*editor) {
3665 		return NULL;
3666 	}
3667 	bool readonly = false;
3668 	if (file && *file != '*') {
3669 		name = strdup (file);
3670 		fd = r_sandbox_open (file, O_RDWR, 0644);
3671 		if (fd == -1) {
3672 			fd = r_sandbox_open (file, O_RDWR | O_CREAT, 0644);
3673 			if (fd == -1) {
3674 				fd = r_sandbox_open (file, O_RDONLY, 0644);
3675 				readonly = true;
3676 			}
3677 		}
3678 	} else {
3679 		fd = r_file_mkstemp (file, &name);
3680 	}
3681 	if (fd == -1) {
3682 		free (name);
3683 		return NULL;
3684 	}
3685 	if (readonly) {
3686 		r_cons_eprintf ("Opening in read-only\n");
3687 	} else {
3688 		if (str) {
3689 			const size_t str_len = strlen (str);
3690 			if (write (fd, str, str_len) != str_len) {
3691 				close (fd);
3692 				free (name);
3693 				return NULL;
3694 			}
3695 		}
3696 	}
3697 	close (fd);
3698 
3699 	if (name && (!editor || !*editor || !strcmp (editor, "-"))) {
3700 		RCons *cons = r_cons_singleton ();
3701 		void *tmp = cons->cb_editor;
3702 		cons->cb_editor = NULL;
3703 		r_cons_editor (name, NULL);
3704 		cons->cb_editor = tmp;
3705 	} else {
3706 		if (editor && name) {
3707 			char *escaped_name = r_str_escape_sh (name);
3708 			r_sys_cmdf ("%s \"%s\"", editor, escaped_name);
3709 			free (escaped_name);
3710 		}
3711 	}
3712 	size_t len = 0;
3713 	ret = name? r_file_slurp (name, &len): 0;
3714 	if (ret) {
3715 		if (len && ret[len - 1] == '\n') {
3716 			ret[len - 1] = 0; // chop
3717 		}
3718 		if (!file) {
3719 			r_file_rm (name);
3720 		}
3721 	}
3722 	free (name);
3723 	return ret;
3724 }
3725 
3726 /* weak getters */
r_core_get_cons(RCore * core)3727 R_API RCons *r_core_get_cons (RCore *core) {
3728 	return core->cons;
3729 }
3730 
r_core_get_config(RCore * core)3731 R_API RConfig *r_core_get_config (RCore *core) {
3732 	return core->config;
3733 }
3734 
r_core_get_bin(RCore * core)3735 R_API RBin *r_core_get_bin (RCore *core) {
3736 	return core->bin;
3737 }
3738 
r_core_syscallf(RCore * core,const char * name,const char * fmt,...)3739 R_API RBuffer *r_core_syscallf (RCore *core, const char *name, const char *fmt, ...) {
3740 	char str[1024];
3741 	RBuffer *buf;
3742 	va_list ap;
3743 	va_start (ap, fmt);
3744 
3745 	vsnprintf (str, sizeof (str), fmt, ap);
3746 	buf = r_core_syscall (core, name, str);
3747 
3748 	va_end (ap);
3749 	return buf;
3750 }
3751 
r_core_syscall(RCore * core,const char * name,const char * args)3752 R_API RBuffer *r_core_syscall (RCore *core, const char *name, const char *args) {
3753 	RBuffer *b = NULL;
3754 	char code[1024];
3755 	int num;
3756 
3757 	//arch check
3758 	if (strcmp (core->anal->cur->arch, "x86")) {
3759 		r_cons_eprintf ("architecture not yet supported!\n");
3760 		return 0;
3761 	}
3762 
3763 	num = r_syscall_get_num (core->anal->syscall, name);
3764 
3765 	//bits check
3766 	switch (core->rasm->bits) {
3767 	case 32:
3768 		if (strcmp (name, "setup") && !num ) {
3769 			r_cons_eprintf ("syscall not found!\n");
3770 			return 0;
3771 		}
3772 		break;
3773 	case 64:
3774 		if (strcmp (name, "read") && !num ) {
3775 			r_cons_eprintf ("syscall not found!\n");
3776 			return 0;
3777 		}
3778 		break;
3779 	default:
3780 		r_cons_eprintf ("syscall not found!\n");
3781 		return 0;
3782 	}
3783 
3784 	snprintf (code, sizeof (code),
3785 		"sc@syscall(%d);\n"
3786 		"main@global(0) { sc(%s);\n"
3787 		":int3\n" /// XXX USE trap
3788 		"}\n", num, args);
3789 	r_egg_reset (core->egg);
3790 	// TODO: setup arch/bits/os?
3791 	r_egg_load (core->egg, code, 0);
3792 
3793 	if (!r_egg_compile (core->egg)) {
3794 		r_cons_eprintf ("Cannot compile.\n");
3795 	}
3796 	if (!r_egg_assemble (core->egg)) {
3797 		r_cons_eprintf ("r_egg_assemble: invalid assembly\n");
3798 	}
3799 	if ((b = r_egg_get_bin (core->egg))) {
3800 #if 0
3801 		if (b->length > 0) {
3802 			for (i = 0; i < b->length; i++) {
3803 				r_cons_printf ("%02x", b->buf[i]);
3804 			}
3805 			r_cons_printf ("\n");
3806 		}
3807 #endif
3808 	}
3809 	return b;
3810 }
3811 
r_core_autocomplete_add(RCoreAutocomplete * parent,const char * cmd,int type,bool lock)3812 R_API RCoreAutocomplete *r_core_autocomplete_add(RCoreAutocomplete *parent, const char* cmd, int type, bool lock) {
3813 	if (!parent || !cmd || type < 0 || type >= R_CORE_AUTOCMPLT_END) {
3814 		return NULL;
3815 	}
3816 	RCoreAutocomplete *autocmpl = R_NEW0 (RCoreAutocomplete);
3817 	if (!autocmpl) {
3818 		return NULL;
3819 	}
3820 	RCoreAutocomplete **updated = realloc (parent->subcmds, (parent->n_subcmds + 1) * sizeof (RCoreAutocomplete*));
3821 	if (!updated) {
3822 		free (autocmpl);
3823 		return NULL;
3824 	}
3825 	parent->subcmds = updated;
3826 	parent->subcmds[parent->n_subcmds] = autocmpl;
3827 	parent->n_subcmds++;
3828 	autocmpl->cmd = strdup (cmd);
3829 	autocmpl->locked = lock;
3830 	autocmpl->type = type;
3831 	autocmpl->length = strlen (cmd);
3832 	return autocmpl;
3833 }
3834 
r_core_autocomplete_free(RCoreAutocomplete * obj)3835 R_API void r_core_autocomplete_free(RCoreAutocomplete *obj) {
3836 	if (!obj) {
3837 		return;
3838 	}
3839 	int i;
3840 	for (i = 0; i < obj->n_subcmds; i++) {
3841 		r_core_autocomplete_free (obj->subcmds[i]);
3842 		obj->subcmds[i] = NULL;
3843 	}
3844 	free (obj->subcmds);
3845 	free ((char*) obj->cmd);
3846 	free (obj);
3847 }
3848 
r_core_autocomplete_find(RCoreAutocomplete * parent,const char * cmd,bool exact)3849 R_API RCoreAutocomplete *r_core_autocomplete_find(RCoreAutocomplete *parent, const char* cmd, bool exact) {
3850 	if (!parent || !cmd) {
3851 		return false;
3852 	}
3853 	int len = strlen (cmd);
3854 	int i;
3855 	for (i = 0; i < parent->n_subcmds; i++) {
3856 		if (exact && len == parent->subcmds[i]->length && !strncmp (cmd, parent->subcmds[i]->cmd, len)) {
3857 			return parent->subcmds[i];
3858 		} else if (!exact && !strncmp (cmd, parent->subcmds[i]->cmd, len)) {
3859 			return parent->subcmds[i];
3860 		}
3861 	}
3862 	return NULL;
3863 }
3864 
r_core_autocomplete_remove(RCoreAutocomplete * parent,const char * cmd)3865 R_API bool r_core_autocomplete_remove(RCoreAutocomplete *parent, const char* cmd) {
3866 	if (!parent || !cmd) {
3867 		return false;
3868 	}
3869 	int i, j;
3870 	for (i = 0; i < parent->n_subcmds; i++) {
3871 		RCoreAutocomplete *ac = parent->subcmds[i];
3872 		if (ac->locked) {
3873 			continue;
3874 		}
3875 		// if (!strncmp (parent->subcmds[i]->cmd, cmd, parent->subcmds[i]->length)) {
3876 		if (r_str_glob (ac->cmd, cmd)) {
3877 			for (j = i + 1; j < parent->n_subcmds; j++) {
3878 				parent->subcmds[j - 1] = parent->subcmds[j];
3879 				parent->subcmds[j] = NULL;
3880 			}
3881 			r_core_autocomplete_free (ac);
3882 			RCoreAutocomplete **updated = realloc (parent->subcmds, (parent->n_subcmds - 1) * sizeof (RCoreAutocomplete*));
3883 			if (!updated && (parent->n_subcmds - 1) > 0) {
3884 				r_cons_eprintf ("Something really bad has happen.. this should never ever happen..\n");
3885 				return false;
3886 			}
3887 			parent->subcmds = updated;
3888 			parent->n_subcmds--;
3889 			i--;
3890 		}
3891 	}
3892 	return false;
3893 }
3894 
r_core_table(RCore * core,const char * name)3895 R_API RTable *r_core_table(RCore *core, const char *name) {
3896 	RTable *table = r_table_new (R_STR_ISEMPTY (name)? "table": name);
3897 	if (table) {
3898 		table->cons = core->cons;
3899 	}
3900 	return table;
3901 }
3902 
3903 /* Config helper function for PJ json encodings */
r_core_pj_new(RCore * core)3904 R_API PJ *r_core_pj_new(RCore *core) {
3905 	const char *config_string_encoding = r_config_get (core->config, "cfg.json.str");
3906 	const char *config_num_encoding = r_config_get (core->config, "cfg.json.num");
3907 	PJEncodingNum number_encoding = PJ_ENCODING_NUM_DEFAULT;
3908 	PJEncodingStr string_encoding = PJ_ENCODING_STR_DEFAULT;
3909 
3910 	if (!strcmp ("string", config_num_encoding)) {
3911 		number_encoding = PJ_ENCODING_NUM_STR;
3912 	} else if (!strcmp ("hex", config_num_encoding)) {
3913 		number_encoding = PJ_ENCODING_NUM_HEX;
3914 	}
3915 
3916 	if (!strcmp ("base64", config_string_encoding)) {
3917 		string_encoding = PJ_ENCODING_STR_BASE64;
3918 	} else if (!strcmp ("hex", config_string_encoding)) {
3919 		string_encoding = PJ_ENCODING_STR_HEX;
3920 	} else if (!strcmp ("array", config_string_encoding)) {
3921 		string_encoding = PJ_ENCODING_STR_ARRAY;
3922 	} else if (!strcmp ("strip", config_string_encoding)) {
3923 		string_encoding = PJ_ENCODING_STR_STRIP;
3924 	}
3925 
3926 	return pj_new_with_encoding (string_encoding, number_encoding);
3927 }
3928