227 lines
6.4 KiB
C
227 lines
6.4 KiB
C
// SPDX-FileCopyrightText: 2021 RizinOrg <info@rizin.re>
|
|
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
|
|
// SPDX-FileCopyrightText: 2021 ret2libc <sirmy15@gmail.com>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
#include <rz_core.h>
|
|
|
|
#if __WINDOWS__
|
|
#define START_ENV_CHAR "%"
|
|
#define END_ENV_CHAR "%"
|
|
#else // __WINDOWS__
|
|
#define START_ENV_CHAR "${"
|
|
#define END_ENV_CHAR "}"
|
|
#endif
|
|
|
|
static char *config_path(RzCore *core) {
|
|
char *path = NULL;
|
|
int fd = rz_file_mkstemp(NULL, &path);
|
|
if (fd >= 0) {
|
|
close(fd);
|
|
}
|
|
if (!path) {
|
|
return NULL;
|
|
}
|
|
|
|
Sdb *sdb = sdb_new(NULL, path, 0);
|
|
if (!sdb) {
|
|
free(path);
|
|
return NULL;
|
|
}
|
|
rz_config_serialize(core->config, sdb);
|
|
sdb_sync(sdb);
|
|
sdb_free(sdb);
|
|
|
|
return path;
|
|
}
|
|
|
|
static const char *system_apply_env_var(const char *env, const char *value, const char *arg, char **alloc_str) {
|
|
size_t len = strlen(arg);
|
|
if (!strstr(arg, env)) {
|
|
return arg;
|
|
} else if (strlen(env) == len) {
|
|
return value;
|
|
}
|
|
|
|
if (!*alloc_str) {
|
|
*alloc_str = strdup(arg);
|
|
}
|
|
|
|
*alloc_str = rz_str_replace(*alloc_str, env, value, 1);
|
|
return *alloc_str;
|
|
}
|
|
|
|
static int system_exec(RzCore *core, int argc, const char **argv, char **output, int *length, int *ret) {
|
|
char file_size[32];
|
|
char core_offset[32];
|
|
char block_size[32];
|
|
const char *file_path = rz_config_get(core->config, "file.path");
|
|
const char *asm_arch = rz_config_get(core->config, "asm.arch");
|
|
const char *asm_bits = rz_config_get(core->config, "asm.bits");
|
|
const char *bin_demangle = rz_config_get(core->config, "bin.demangle");
|
|
const char *bin_lang = rz_config_get(core->config, "bin.lang");
|
|
const char *cfg_debug = rz_config_get(core->config, "cfg.debug");
|
|
const char *io_va = rz_config_get(core->config, "io.va");
|
|
const char *pdb_server = rz_config_get(core->config, "pdb.server");
|
|
const char *scr_color = rz_config_get(core->config, "scr.color");
|
|
const char *endian = rz_str_bool(core->rasm->big_endian);
|
|
char *cfg_path = config_path(core);
|
|
|
|
rz_strf(file_size, "%" PFMT64u, core->file ? rz_io_fd_size(core->io, core->file->fd) : 0);
|
|
rz_strf(core_offset, "%" PFMT64u, core->offset);
|
|
rz_strf(block_size, "%u", core->blocksize);
|
|
|
|
const char *envvars[] = {
|
|
"RZ_FILE",
|
|
"RZ_SIZE",
|
|
"RZ_ARCH",
|
|
"RZ_BITS",
|
|
"RZ_OFFSET",
|
|
"RZ_ENDIAN",
|
|
"RZ_BIN_DEMANGLE",
|
|
"RZ_BIN_LANG",
|
|
"RZ_BIN_PDBSERVER",
|
|
"RZ_IOVA",
|
|
"RZ_COLOR",
|
|
"RZ_BSIZE",
|
|
"RZ_DEBUG",
|
|
"RZ_CONFIG"
|
|
};
|
|
const char *envvals[] = {
|
|
file_path,
|
|
file_size,
|
|
asm_arch,
|
|
asm_bits,
|
|
core_offset,
|
|
endian,
|
|
bin_demangle,
|
|
bin_lang,
|
|
pdb_server,
|
|
io_va,
|
|
scr_color,
|
|
block_size,
|
|
cfg_debug,
|
|
rz_str_get(cfg_path)
|
|
};
|
|
|
|
bool success = false;
|
|
|
|
RzList *alloc = rz_list_newf(free);
|
|
if (!alloc) {
|
|
RZ_LOG_ERROR("Cannot allocate list of allocated strings.\n");
|
|
goto alloc_err;
|
|
}
|
|
|
|
const char **args = RZ_NEWS0(const char *, argc);
|
|
if (!args) {
|
|
RZ_LOG_ERROR("Cannot allocate list of args.\n");
|
|
goto args_err;
|
|
}
|
|
|
|
if (!rz_subprocess_init()) {
|
|
RZ_LOG_ERROR("Cannot initialize subprocess.\n");
|
|
goto subprocess_err;
|
|
}
|
|
|
|
for (int i = 0; i < argc; ++i) {
|
|
char *alloc_str = NULL;
|
|
args[i] = system_apply_env_var(START_ENV_CHAR "RZ_FILE" END_ENV_CHAR, file_path, argv[i], &alloc_str);
|
|
args[i] = system_apply_env_var(START_ENV_CHAR "RZ_SIZE" END_ENV_CHAR, file_size, args[i], &alloc_str);
|
|
args[i] = system_apply_env_var(START_ENV_CHAR "RZ_ARCH" END_ENV_CHAR, asm_arch, args[i], &alloc_str);
|
|
args[i] = system_apply_env_var(START_ENV_CHAR "RZ_BITS" END_ENV_CHAR, asm_bits, args[i], &alloc_str);
|
|
args[i] = system_apply_env_var(START_ENV_CHAR "RZ_OFFSET" END_ENV_CHAR, core_offset, args[i], &alloc_str);
|
|
args[i] = system_apply_env_var(START_ENV_CHAR "RZ_ENDIAN" END_ENV_CHAR, endian, args[i], &alloc_str);
|
|
args[i] = system_apply_env_var(START_ENV_CHAR "RZ_BIN_DEMANGLE" END_ENV_CHAR, bin_demangle, args[i], &alloc_str);
|
|
args[i] = system_apply_env_var(START_ENV_CHAR "RZ_BIN_LANG" END_ENV_CHAR, bin_lang, args[i], &alloc_str);
|
|
args[i] = system_apply_env_var(START_ENV_CHAR "RZ_BIN_PDBSERVER" END_ENV_CHAR, pdb_server, args[i], &alloc_str);
|
|
args[i] = system_apply_env_var(START_ENV_CHAR "RZ_IOVA" END_ENV_CHAR, io_va, args[i], &alloc_str);
|
|
args[i] = system_apply_env_var(START_ENV_CHAR "RZ_COLOR" END_ENV_CHAR, scr_color, args[i], &alloc_str);
|
|
args[i] = system_apply_env_var(START_ENV_CHAR "RZ_BSIZE" END_ENV_CHAR, block_size, args[i], &alloc_str);
|
|
args[i] = system_apply_env_var(START_ENV_CHAR "RZ_DEBUG" END_ENV_CHAR, cfg_debug, args[i], &alloc_str);
|
|
args[i] = system_apply_env_var(START_ENV_CHAR "RZ_CONFIG" END_ENV_CHAR, cfg_path, args[i], &alloc_str);
|
|
if (alloc_str) {
|
|
rz_list_append(alloc, alloc_str);
|
|
}
|
|
}
|
|
|
|
RzSubprocessOpt opt = {
|
|
.file = args[0],
|
|
.args = &args[1],
|
|
.args_size = argc - 1,
|
|
.envvars = envvars,
|
|
.envvals = envvals,
|
|
.env_size = RZ_ARRAY_SIZE(envvars),
|
|
.stdin_pipe = RZ_SUBPROCESS_PIPE_NONE,
|
|
.stdout_pipe = output ? RZ_SUBPROCESS_PIPE_CREATE : RZ_SUBPROCESS_PIPE_NONE,
|
|
.stderr_pipe = RZ_SUBPROCESS_PIPE_NONE,
|
|
};
|
|
|
|
RzSubprocess *proc = rz_subprocess_start_opt(&opt);
|
|
if (!proc) {
|
|
RZ_LOG_ERROR("Cannot start subprocess.\n");
|
|
goto proc_start_err;
|
|
}
|
|
|
|
rz_subprocess_wait(proc, UT64_MAX);
|
|
*ret = rz_subprocess_ret(proc);
|
|
|
|
if (output) {
|
|
*output = (char *)rz_subprocess_out(proc, length);
|
|
}
|
|
success = true;
|
|
|
|
rz_subprocess_free(proc);
|
|
proc_start_err:
|
|
rz_subprocess_fini();
|
|
subprocess_err:
|
|
free(args);
|
|
args_err:
|
|
rz_list_free(alloc);
|
|
alloc_err:
|
|
rz_file_rm(cfg_path);
|
|
free(cfg_path);
|
|
|
|
return success;
|
|
}
|
|
|
|
static RzCmdStatus system_common_handler(RzCore *core, bool force_rzcons, int argc, const char **argv) {
|
|
char *out = NULL;
|
|
int length = 0;
|
|
void *bed = rz_cons_sleep_begin();
|
|
bool need_rzcons = force_rzcons || core->is_pipe;
|
|
int ret = -1;
|
|
bool succ = system_exec(core, argc - 1, &argv[1], need_rzcons ? &out : NULL, &length, &ret);
|
|
rz_cons_sleep_end(bed);
|
|
if (need_rzcons) {
|
|
#if __WINDOWS__
|
|
char *src = out;
|
|
char *dest = src;
|
|
char *end = out + length;
|
|
while (src != end) {
|
|
*dest = *src;
|
|
if (src[0] == '\r' && src + 1 != end && src[1] == '\n') {
|
|
// dest does not move
|
|
length--;
|
|
} else {
|
|
dest++;
|
|
}
|
|
src++;
|
|
}
|
|
#endif
|
|
rz_cons_memcat(out, length);
|
|
}
|
|
free(out);
|
|
core->num->value = (ut64)ret;
|
|
return succ ? RZ_CMD_STATUS_OK : RZ_CMD_STATUS_ERROR;
|
|
}
|
|
|
|
RZ_IPI RzCmdStatus rz_system_handler(RzCore *core, int argc, const char **argv) {
|
|
return system_common_handler(core, false, argc, argv);
|
|
}
|
|
|
|
RZ_IPI RzCmdStatus rz_system_to_cons_handler(RzCore *core, int argc, const char **argv) {
|
|
return system_common_handler(core, true, argc, argv);
|
|
}
|
|
|
|
#undef START_ENV_CHAR
|
|
#undef END_ENV_CHAR
|