R_API char *r_type_enum_getbitfield(Sdb *TDB, const char *name, ut64 val) { char *q, *ret = NULL; const char *res; int i; if (r_type_kind (TDB, name) != R_TYPE_ENUM) { return NULL; } bool isFirst = true; ret = r_str_appendf (ret, "0x%08"PFMT64x" : ", val); for (i = 0; i < 32; i++) { if (!(val & (1 << i))) { continue; } q = sdb_fmt ("enum.%s.0x%x", name, (1<<i)); res = sdb_const_get (TDB, q, 0); if (isFirst) { isFirst = false; } else { ret = r_str_append (ret, " | "); } if (res) { ret = r_str_append (ret, res); } else { ret = r_str_appendf (ret, "0x%x", (1<<i)); } } return ret; }
// XXX buffers_static doesnt constructs the correct string in this callback static int tostring(RDiff *d, void *user, RDiffOp *op) { RDiffUser *u = (RDiffUser*)user; if (op->a_len > 0) { char *a_str = r_str_ndup ((const char *)op->a_buf + op->a_off, op->a_len); u->str = r_str_appendf (u->str, "+(%s)", a_str); #if 0 char *bufasm = r_str_prefix_all (a_str, "- "); u->str = r_str_appendf (u->str, "-(%s)", bufasm); free (bufasm); #endif free (a_str); } if (op->b_len > 0) { char *b_str = r_str_ndup ((const char *)op->b_buf + op->b_off, op->b_len); u->str = r_str_appendf (u->str, "+(%s)", b_str); #if 0 char *bufasm = r_str_prefix_all (b_str, "+ "); u->str = r_str_appendf (u->str, "+(%s)", bufasm); free (bufasm); #endif free (b_str); } if (op->a_len == op->b_len) { char *b_str = r_str_ndup ((const char *)op->a_buf + op->a_off, op->a_len); // char *bufasm = r_str_prefix_all (b_str, " "); u->str = r_str_appendf (u->str, "%s", b_str); // free (bufasm); free (b_str); } return 1; }
// - name should be allocated on the heap R_API char *r_bin_filter_name(RBinFile *bf, Sdb *db, ut64 vaddr, char *name) { r_return_val_if_fail (db && name, NULL); char *resname = name; const char *uname = sdb_fmt ("%" PFMT64x ".%s", vaddr, resname); ut32 vhash = sdb_hash (uname); // vaddr hash - unique ut32 hash = sdb_hash (resname); // name hash - if dupped and not in unique hash must insert int count = sdb_num_inc (db, sdb_fmt ("%x", hash), 1, 0); if (sdb_exists (db, sdb_fmt ("%x", vhash))) { // TODO: symbol is dupped, so symbol can be removed! return resname; } sdb_num_set (db, sdb_fmt ("%x", vhash), 1, 0); if (vaddr) { char *p = hashify (resname, vaddr); if (p) { resname = p; } } if (count > 1) { char *p = r_str_appendf (resname, "_%d", count - 1); if (p) { resname = p; } // two symbols at different addresses and same name wtf // eprintf ("Symbol '%s' dupped!\n", sym->name); } return resname; }
static int lang_lib_file_run (RLang *user, const char *file) { char *libpath; void *lib; if (!(libpath = r_str_new (file))) { return -1; } if (!r_str_startswith (libpath, "/") && !r_str_startswith (libpath, "./")) { libpath = r_str_prefix (libpath, "./"); } if (!r_file_exists (libpath)) { if (!r_str_endswith (libpath, R_LIB_EXT)) { libpath = r_str_appendf (libpath, ".%s", R_LIB_EXT); } } if (!r_file_exists (libpath)) { free (libpath); return -1; } lib = r_lib_dl_open (libpath); if (lib) { void (*fcn)(RCore *); fcn = r_lib_dl_sym (lib, "entry"); if (fcn) { fcn (user->user); } else { eprintf ("Cannot find 'entry' symbol in library\n"); } r_lib_dl_close (lib); } free (libpath); return 0; }
static void fork_child_callback(void *user) { fork_child_data *data = user; if (data->runprofile) { char **argv = r_str_argv (data->cmd, NULL); if (!argv) { exit (1); } RRunProfile *rp = _get_run_profile (data->io, data->bits, argv); if (!rp) { r_str_argv_free (argv); exit (1); } trace_me (); r_run_start (rp); r_run_free (rp); r_str_argv_free (argv); exit (1); } else { char *_cmd = data->io->args ? r_str_appendf (strdup (data->cmd), " %s", data->io->args) : strdup (data->cmd); trace_me (); char **argv = r_str_argv (_cmd, NULL); if (!argv) { free (_cmd); return; } if (argv && *argv) { int i; for (i = 3; i < 1024; i++) { (void)close (i); } for (i = 0; argv[i]; i++) { r_str_arg_unescape (argv[i]); } if (execvp (argv[0], argv) == -1) { eprintf ("Could not execvp: %s\n", strerror (errno)); exit (MAGIC_EXIT); } } else { eprintf ("Invalid execvp\n"); } r_str_argv_free (argv); free (_cmd); } }
// TODO: add support for byte-per-byte opcode search R_API RList *r_core_asm_strsearch(RCore *core, const char *input, ut64 from, ut64 to, int maxhits, int regexp) { RCoreAsmHit *hit; RAsmOp op; RList *hits; ut64 at, toff = core->offset; ut8 *buf; int align = core->search->align; RRegex* rx = NULL; char *tok, *tokens[1024], *code = NULL, *ptr; int idx, tidx = 0, len; int tokcount, matchcount, count = 0; int matches = 0, addrbytes = core->assembler->addrbytes; if (!*input) { return NULL; } if (core->blocksize <= OPSZ) { eprintf ("error: block size too small\n"); return NULL; } if (!(buf = (ut8 *)calloc (core->blocksize, 1))) { return NULL; } if (!(ptr = strdup (input))) { free (buf); return NULL; } if (!(hits = r_core_asm_hit_list_new ())) { free (buf); free (ptr); return NULL; } tokens[0] = NULL; for (tokcount = 0; tokcount < R_ARRAY_SIZE (tokens) - 1; tokcount++) { tok = strtok (tokcount? NULL: ptr, ";"); if (!tok) break; tokens[tokcount] = r_str_trim_head_tail (tok); } tokens[tokcount] = NULL; r_cons_break_push (NULL, NULL); for (at = from, matchcount = 0; at < to; at += core->blocksize) { matches = 0; if (r_cons_is_breaked ()) { break; } if (!r_io_read_at (core->io, at, buf, core->blocksize)) { break; } idx = 0, matchcount = 0; while (addrbytes * (idx + 1) <= core->blocksize) { ut64 addr = at + idx; r_asm_set_pc (core->assembler, addr); if (!(len = r_asm_disassemble ( core->assembler, &op, buf + addrbytes * idx, core->blocksize - addrbytes * idx))) { idx = (matchcount)? tidx + 1: idx + 1; matchcount = 0; continue; } matches = strcmp (op.buf_asm, "invalid") && strcmp (op.buf_asm, "unaligned"); if (matches && tokens[matchcount]) { if (!regexp) { matches = strstr(op.buf_asm, tokens[matchcount]) != NULL; } else { rx = r_regex_new (tokens[matchcount], ""); matches = r_regex_exec (rx, op.buf_asm, 0, 0, 0) == 0; r_regex_free (rx); } } if (align && align > 1) { if (addr % align) { matches = false; } } if (matches) { code = r_str_appendf (code, "%s; ", op.buf_asm); if (matchcount == tokcount - 1) { if (tokcount == 1) { tidx = idx; } if (!(hit = r_core_asm_hit_new ())) { r_list_purge (hits); free (hits); hits = NULL; goto beach; } hit->addr = addr; hit->len = idx + len - tidx; if (hit->len == -1) { r_core_asm_hit_free (hit); goto beach; } code[strlen (code)-2] = 0; hit->code = strdup (code); r_list_append (hits, hit); R_FREE (code); matchcount = 0; idx = tidx + 1; if (maxhits) { count++; if (count >= maxhits) { //eprintf ("Error: search.maxhits reached\n"); goto beach; } } } else if (!matchcount) { tidx = idx; matchcount++; idx += len; } else { matchcount++; idx += len; } } else { idx = matchcount? tidx + 1: idx + 1; R_FREE (code); matchcount = 0; } } } r_cons_break_pop (); r_asm_set_pc (core->assembler, toff); beach: free (buf); free (ptr); free (code); r_cons_break_pop (); return hits; }
// __UNIX__ (not windows) static int fork_and_ptraceme_for_mac(RIO *io, int bits, const char *cmd) { bool runprofile = io->runprofile && *(io->runprofile); pid_t p = -1; char **argv; posix_spawn_file_actions_t fileActions; ut32 ps_flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; sigset_t no_signals; sigset_t all_signals; size_t copied = 1; cpu_type_t cpu = CPU_TYPE_ANY; posix_spawnattr_t attr = {0}; posix_spawnattr_init (&attr); sigemptyset (&no_signals); sigfillset (&all_signals); posix_spawnattr_setsigmask (&attr, &no_signals); posix_spawnattr_setsigdefault (&attr, &all_signals); posix_spawn_file_actions_init (&fileActions); posix_spawn_file_actions_addinherit_np (&fileActions, STDIN_FILENO); posix_spawn_file_actions_addinherit_np (&fileActions, STDOUT_FILENO); posix_spawn_file_actions_addinherit_np (&fileActions, STDERR_FILENO); ps_flags |= POSIX_SPAWN_CLOEXEC_DEFAULT; ps_flags |= POSIX_SPAWN_START_SUSPENDED; #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 if (!runprofile) { int ret, useASLR = io->aslr; char *_cmd = io->args ? r_str_appendf (strdup (cmd), " %s", io->args) : strdup (cmd); argv = r_str_argv (_cmd, NULL); if (!argv) { free (_cmd); return -1; } if (!*argv) { r_str_argv_free (argv); free (_cmd); eprintf ("Invalid execvp\n"); return -1; } if (useASLR != -1) { if (!useASLR) { ps_flags |= _POSIX_SPAWN_DISABLE_ASLR; } } (void)posix_spawnattr_setflags (&attr, ps_flags); #if __x86_64__ if (bits == 32) { cpu = CPU_TYPE_I386; // cpu |= CPU_ARCH_ABI64; } #endif posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &copied); { char *dst = r_file_readlink (argv[0]); if (dst) { argv[0] = dst; } } // XXX: this is a workaround to fix spawning programs with spaces in path if (strstr (argv[0], "\\ ")) { argv[0] = r_str_replace (argv[0], "\\ ", " ", true); } ret = posix_spawnp (&p, argv[0], &fileActions, &attr, argv, NULL); handle_posix_error (ret); posix_spawn_file_actions_destroy (&fileActions); r_str_argv_free (argv); free (_cmd); return p; } int ret; argv = r_str_argv (cmd, NULL); if (!argv) { posix_spawn_file_actions_destroy (&fileActions); return -1; } RRunProfile *rp = _get_run_profile (io, bits, argv); if (!rp) { r_str_argv_free (argv); posix_spawn_file_actions_destroy (&fileActions); return -1; } handle_posix_redirection (rp, &fileActions); if (rp->_args[0]) { if (!rp->_aslr) { ps_flags |= _POSIX_SPAWN_DISABLE_ASLR; } #if __x86_64__ if (rp->_bits == 32) { cpu = CPU_TYPE_I386; } #endif (void)posix_spawnattr_setflags (&attr, ps_flags); posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &copied); ret = posix_spawnp (&p, rp->_args[0], &fileActions, &attr, rp->_args, NULL); handle_posix_error (ret); } r_str_argv_free (argv); r_run_free (rp); posix_spawn_file_actions_destroy (&fileActions); return p; // -1 ? }
static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) { PROCESS_INFORMATION pi; STARTUPINFO si = { 0 } ; DEBUG_EVENT de; int pid, tid; HANDLE th = INVALID_HANDLE_VALUE; if (!*cmd) { return -1; } setup_tokens (); char *_cmd = io->args ? r_str_appendf (strdup (cmd), " %s", io->args) : strdup (cmd); char **argv = r_str_argv (_cmd, NULL); // We need to build a command line with quoted argument and escaped quotes int cmd_len = 0; int i = 0; si.cb = sizeof (si); while (argv[i]) { char *current = argv[i]; int quote_count = 0; while ((current = strchr (current, '"'))) { quote_count ++; } cmd_len += strlen (argv[i]); cmd_len += quote_count; // The quotes will add one backslash each cmd_len += 2; // Add two enclosing quotes; i++; } cmd_len += i-1; // Add argc-1 spaces char *cmdline = malloc ((cmd_len + 1) * sizeof (char)); int cmd_i = 0; // Next character to write in cmdline i = 0; while (argv[i]) { if (i != 0) { cmdline[cmd_i++] = ' '; } cmdline[cmd_i++] = '"'; int arg_i = 0; // Index of current character in orginal argument while (argv[i][arg_i]) { char c = argv[i][arg_i]; if (c == '"') { cmdline[cmd_i++] = '\\'; } cmdline[cmd_i++] = c; arg_i++; } cmdline[cmd_i++] = '"'; i++; } cmdline[cmd_i] = '\0'; LPTSTR appname_ = r_sys_conv_utf8_to_utf16 (argv[0]); LPTSTR cmdline_ = r_sys_conv_utf8_to_utf16 (cmdline); if (!CreateProcess (appname_, cmdline_, NULL, NULL, FALSE, CREATE_NEW_CONSOLE | DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &si, &pi)) { r_sys_perror ("fork_and_ptraceme/CreateProcess"); free (appname_); free (cmdline_); return -1; } free (appname_); free (cmdline_); free (cmdline); r_str_argv_free (argv); /* get process id and thread id */ pid = pi.dwProcessId; tid = pi.dwThreadId; /* catch create process event */ if (!WaitForDebugEvent (&de, 10000)) goto err_fork; /* check if is a create process debug event */ if (de.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT) { eprintf ("exception code 0x%04x\n", (ut32)de.dwDebugEventCode); goto err_fork; } if (th != INVALID_HANDLE_VALUE) { CloseHandle (th); } eprintf ("Spawned new process with pid %d, tid = %d\n", pid, tid); winbase = (ut64)de.u.CreateProcessInfo.lpBaseOfImage; wintid = tid; return pid; err_fork: eprintf ("ERRFORK\n"); TerminateProcess (pi.hProcess, 1); if (th != INVALID_HANDLE_VALUE) CloseHandle (th); return -1; }
// TODO: add support for byte-per-byte opcode search R_API RList *r_core_asm_strsearch(RCore *core, const char *input, ut64 from, ut64 to, int maxhits, int regexp, int everyByte, int mode) { RCoreAsmHit *hit; RAsmOp op; RList *hits; ut64 at, toff = core->offset; ut8 *buf; int align = core->search->align; RRegex* rx = NULL; char *tok, *tokens[1024], *code = NULL, *ptr; int idx, tidx = 0, len = 0; int tokcount, matchcount, count = 0; int matches = 0; const int addrbytes = core->io->addrbytes; if (!input || !*input) { return NULL; } ut64 usrimm = r_num_math (core->num, input + 1); if (core->blocksize < 8) { eprintf ("error: block size too small\n"); return NULL; } if (!(buf = (ut8 *)calloc (core->blocksize, 1))) { return NULL; } if (!(ptr = strdup (input))) { free (buf); return NULL; } if (!(hits = r_core_asm_hit_list_new ())) { free (buf); free (ptr); return NULL; } tokens[0] = NULL; for (tokcount = 0; tokcount < R_ARRAY_SIZE (tokens) - 1; tokcount++) { tok = strtok (tokcount? NULL: ptr, ";"); if (!tok) { break; } tokens[tokcount] = r_str_trim_head_tail (tok); } tokens[tokcount] = NULL; r_cons_break_push (NULL, NULL); char *opst = NULL; for (at = from, matchcount = 0; at < to; at += core->blocksize) { if (r_cons_is_breaked ()) { break; } if (!r_io_is_valid_offset (core->io, at, 0)) { break; } (void)r_io_read_at (core->io, at, buf, core->blocksize); idx = 0, matchcount = 0; while (addrbytes * (idx + 1) <= core->blocksize) { ut64 addr = at + idx; if (addr >= to) { break; } r_asm_set_pc (core->assembler, addr); if (mode == 'i') { RAnalOp analop = {0}; if (r_anal_op (core->anal, &analop, addr, buf + idx, 15, 0) < 1) { idx ++; // TODO: honor mininstrsz continue; } if (analop.val == usrimm) { if (!(hit = r_core_asm_hit_new ())) { r_list_purge (hits); R_FREE (hits); goto beach; } hit->addr = addr; hit->len = analop.size; // idx + len - tidx; if (hit->len == -1) { r_core_asm_hit_free (hit); goto beach; } r_asm_disassemble (core->assembler, &op, buf + addrbytes * idx, core->blocksize - addrbytes * idx); hit->code = r_str_newf (r_strbuf_get (&op.buf_asm)); idx = (matchcount)? tidx + 1: idx + 1; matchcount = 0; r_list_append (hits, hit); continue; } r_anal_op_fini (&analop); idx ++; // TODO: honor mininstrsz continue; } else if (mode == 'e') { RAnalOp analop = {0}; if (r_anal_op (core->anal, &analop, addr, buf + idx, 15, R_ANAL_OP_MASK_ESIL) < 1) { idx ++; // TODO: honor mininstrsz continue; } //opsz = analop.size; opst = strdup (r_strbuf_get (&analop.esil)); r_anal_op_fini (&analop); } else { if (!(len = r_asm_disassemble ( core->assembler, &op, buf + addrbytes * idx, core->blocksize - addrbytes * idx))) { idx = (matchcount)? tidx + 1: idx + 1; matchcount = 0; continue; } //opsz = op.size; opst = strdup (r_strbuf_get (&op.buf_asm)); } if (opst) { matches = strcmp (opst, "invalid") && strcmp (opst, "unaligned"); } if (matches && tokens[matchcount]) { if (!regexp) { matches = strstr (opst, tokens[matchcount]) != NULL; } else { rx = r_regex_new (tokens[matchcount], ""); if (r_regex_comp (rx, tokens[matchcount], R_REGEX_EXTENDED|R_REGEX_NOSUB) == 0) { matches = r_regex_exec (rx, opst, 0, 0, 0) == 0; } r_regex_free (rx); } } if (align && align > 1) { if (addr % align) { matches = false; } } if (matches) { code = r_str_appendf (code, "%s; ", opst); if (matchcount == tokcount - 1) { if (tokcount == 1) { tidx = idx; } if (!(hit = r_core_asm_hit_new ())) { r_list_purge (hits); R_FREE (hits); goto beach; } hit->addr = addr; hit->len = idx + len - tidx; if (hit->len == -1) { r_core_asm_hit_free (hit); goto beach; } code[strlen (code) - 2] = 0; hit->code = strdup (code); r_list_append (hits, hit); R_FREE (code); matchcount = 0; idx = tidx + 1; if (maxhits) { count++; if (count >= maxhits) { //eprintf ("Error: search.maxhits reached\n"); goto beach; } } } else if (!matchcount) { tidx = idx; matchcount++; idx += len; } else { matchcount++; idx += len; } } else { if (everyByte) { idx = matchcount? tidx + 1: idx + 1; } else { idx += R_MAX (1, len); } R_FREE (code); matchcount = 0; } R_FREE (opst); } } r_cons_break_pop (); r_asm_set_pc (core->assembler, toff); beach: free (buf); free (ptr); free (code); R_FREE (opst); r_cons_break_pop (); return hits; }
// __UNIX__ (not windows) static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) { bool runprofile = io->runprofile && *(io->runprofile); char **argv; #if __APPLE__ && !__POWERPC__ pid_t p = -1; posix_spawn_file_actions_t fileActions; ut32 ps_flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; sigset_t no_signals; sigset_t all_signals; size_t copied = 1; cpu_type_t cpu = CPU_TYPE_ANY; posix_spawnattr_t attr = {0}; posix_spawnattr_init (&attr); sigemptyset (&no_signals); sigfillset (&all_signals); posix_spawnattr_setsigmask (&attr, &no_signals); posix_spawnattr_setsigdefault (&attr, &all_signals); posix_spawn_file_actions_init (&fileActions); posix_spawn_file_actions_addinherit_np (&fileActions, STDIN_FILENO); posix_spawn_file_actions_addinherit_np (&fileActions, STDOUT_FILENO); posix_spawn_file_actions_addinherit_np (&fileActions, STDERR_FILENO); ps_flags |= POSIX_SPAWN_CLOEXEC_DEFAULT; ps_flags |= POSIX_SPAWN_START_SUSPENDED; #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 if (!runprofile) { int ret, useASLR = io->aslr; char *_cmd = io->args ? r_str_appendf (strdup (cmd), " %s", io->args) : strdup (cmd); argv = r_str_argv (_cmd, NULL); if (!argv) { free (_cmd); return -1; } if (!*argv) { r_str_argv_free (argv); free (_cmd); eprintf ("Invalid execvp\n"); return -1; } if (useASLR != -1) { if (!useASLR) { ps_flags |= _POSIX_SPAWN_DISABLE_ASLR; } } (void)posix_spawnattr_setflags (&attr, ps_flags); #if __x86_64__ if (bits == 32) { cpu = CPU_TYPE_I386; // cpu |= CPU_ARCH_ABI64; } #endif posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &copied); { char *dst = r_file_readlink (argv[0]); if (dst) { argv[0] = dst; } } ret = posix_spawnp (&p, argv[0], NULL, &attr, argv, NULL); handle_posix_error (ret); posix_spawn_file_actions_destroy (&fileActions); r_str_argv_free (argv); free (_cmd); return p; } else { int ret; argv = r_str_argv (cmd, NULL); if (!argv) { posix_spawn_file_actions_destroy (&fileActions); return -1; } RRunProfile *rp = _get_run_profile (io, bits, argv); if (!rp) { r_str_argv_free (argv); posix_spawn_file_actions_destroy (&fileActions); return -1; } handle_posix_redirection (rp, &fileActions); if (rp->_args[0]) { if (!rp->_aslr) { ps_flags |= _POSIX_SPAWN_DISABLE_ASLR; } #if __x86_64__ if (rp->_bits == 32) { cpu = CPU_TYPE_I386; } #endif (void)posix_spawnattr_setflags (&attr, ps_flags); posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &copied); ret = posix_spawnp (&p, rp->_args[0], &fileActions, &attr, rp->_args, NULL); handle_posix_error (ret); } r_str_argv_free (argv); r_run_free (rp); posix_spawn_file_actions_destroy (&fileActions); return p; } posix_spawn_file_actions_destroy (&fileActions); return -1; #endif int ret, status, child_pid; child_pid = r_sys_fork (); switch (child_pid) { case -1: perror ("fork_and_ptraceme"); break; case 0: if (runprofile) { argv = r_str_argv (cmd, NULL); if (!argv) { exit(1); } RRunProfile *rp = _get_run_profile (io, bits, argv); if (!rp) { r_str_argv_free (argv); exit (1); } trace_me (); r_run_start (rp); r_run_free (rp); r_str_argv_free (argv); exit (1); } else { char *_cmd = io->args ? r_str_appendf (strdup (cmd), " %s", io->args) : strdup (cmd); trace_me (); argv = r_str_argv (_cmd, NULL); if (!argv) { free (_cmd); return -1; } if (argv && *argv) { int i; for (i = 3; i < 1024; i++) (void)close (i); execvp (argv[0], argv); } else { eprintf ("Invalid execvp\n"); } r_str_argv_free (argv); free (_cmd); } perror ("fork_and_attach: execv"); //printf(stderr, "[%d] %s execv failed.\n", getpid(), ps.filename); exit (MAGIC_EXIT); /* error */ return 0; // invalid pid // if exit is overriden.. :) default: /* XXX: clean this dirty code */ do { ret = wait (&status); if (ret == -1) return -1; if (ret != child_pid) { eprintf ("Wait event received by " "different pid %d\n", ret); } } while (ret != child_pid); if (WIFSTOPPED (status)) { eprintf ("Process with PID %d started...\n", (int)child_pid); } if (WEXITSTATUS (status) == MAGIC_EXIT) { child_pid = -1; } // XXX kill (pid, SIGSTOP); break; } return child_pid; }
static RList *hud_filter(RList *list, char *user_input, int top_entry_n, int *current_entry_n, char **selected_entry) { RListIter *iter; char *current_entry; char mask[HUD_BUF_SIZE]; char *p, *x; int j, rows; (void) r_cons_get_size (&rows); int counter = 0; bool first_line = true; RList *res = r_list_newf (free); r_list_foreach (list, iter, current_entry) { memset (mask, 0, HUD_BUF_SIZE); if (*user_input && !strmatch (current_entry, user_input, mask, HUD_BUF_SIZE)) { continue; } if (++counter == rows + top_entry_n) { break; } // if the user scrolled down the list, do not print the first entries if (!top_entry_n || *current_entry_n >= top_entry_n) { // remove everything after a tab (in ??, it contains the commands) x = strchr (current_entry, '\t'); if (x) { *x = 0; } p = strdup (current_entry); // if the filter is empty, print the entry and move on if (!user_input[0]) { r_list_append (res, r_str_newf (" %c %s", first_line? '-': ' ', p)); } else { // otherwise we need to emphasize the matching part if (I (context->color)) { int last_color_change = 0; int last_mask = 0; char *str = r_str_newf (" %c ", first_line? '-': ' '); // Instead of printing one char at the time // (which would be slow), we group substrings of the same color for (j = 0; p[j] && j < HUD_BUF_SIZE; j++) { if (mask[j] != last_mask) { char tmp = p[j]; p[j] = 0; if (mask[j]) { str = r_str_appendf (str, Color_RESET "%s", p + last_color_change); } else { str = r_str_appendf (str, Color_GREEN "%s", p + last_color_change); } p[j] = tmp; last_color_change = j; last_mask = mask[j]; } } if (last_mask) { str = r_str_appendf (str, Color_GREEN "%s"Color_RESET, p + last_color_change); } else { str = r_str_appendf (str, Color_RESET "%s", p + last_color_change); } r_list_append (res, str); } else { // Otherwise we print the matching characters uppercase for (j = 0; p[j]; j++) { if (mask[j]) { p[j] = toupper ((unsigned char) p[j]); } } r_list_append (res, r_str_newf (" %c %s", first_line? '-': ' ', p)); } } // Clean up and restore the tab character (if any) free (p); if (x) { *x = '\t'; } if (first_line) { *selected_entry = current_entry; } first_line = false; } (*current_entry_n)++; }
static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) { #if __APPLE__ && !__POWERPC__ return fork_and_ptraceme_for_mac(io, bits, cmd); #else int ret, status, child_pid; bool runprofile = io->runprofile && *(io->runprofile); char **argv; child_pid = r_sys_fork (); switch (child_pid) { case -1: perror ("fork_and_ptraceme"); break; case 0: if (runprofile) { argv = r_str_argv (cmd, NULL); if (!argv) { exit(1); } RRunProfile *rp = _get_run_profile (io, bits, argv); if (!rp) { r_str_argv_free (argv); exit (1); } trace_me (); r_run_start (rp); r_run_free (rp); r_str_argv_free (argv); exit (1); } else { char *_cmd = io->args ? r_str_appendf (strdup (cmd), " %s", io->args) : strdup (cmd); trace_me (); argv = r_str_argv (_cmd, NULL); if (!argv) { free (_cmd); return -1; } if (argv && *argv) { int i; for (i = 3; i < 1024; i++) { (void)close (i); } if (execvp (argv[0], argv) == -1) { eprintf ("Could not execvp: %s\n", strerror (errno)); exit (MAGIC_EXIT); } } else { eprintf ("Invalid execvp\n"); } r_str_argv_free (argv); free (_cmd); } perror ("fork_and_attach: execv"); //printf(stderr, "[%d] %s execv failed.\n", getpid(), ps.filename); exit (MAGIC_EXIT); /* error */ return 0; // invalid pid // if exit is overriden.. :) default: /* XXX: clean this dirty code */ do { ret = wait (&status); if (ret == -1) return -1; if (ret != child_pid) { eprintf ("Wait event received by " "different pid %d\n", ret); } } while (ret != child_pid); if (WIFSTOPPED (status)) { eprintf ("Process with PID %d started...\n", (int)child_pid); } if (WEXITSTATUS (status) == MAGIC_EXIT) { child_pid = -1; } // XXX kill (pid, SIGSTOP); break; } return child_pid; #endif }