Rizin
unix-like reverse engineering framework and cli tools
cmd_system.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 RizinOrg <info@rizin.re>
2 // SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
3 // SPDX-FileCopyrightText: 2021 ret2libc <sirmy15@gmail.com>
4 // SPDX-License-Identifier: LGPL-3.0-only
5 
6 #include <rz_core.h>
7 
8 #if __WINDOWS__
9 #define START_ENV_CHAR "%"
10 #define END_ENV_CHAR "%"
11 #else // __WINDOWS__
12 #define START_ENV_CHAR "${"
13 #define END_ENV_CHAR "}"
14 #endif
15 
16 static char *config_path(RzCore *core) {
17  char *path = NULL;
18  int fd = rz_file_mkstemp(NULL, &path);
19  if (fd >= 0) {
20  close(fd);
21  }
22  if (!path) {
23  return NULL;
24  }
25 
26  Sdb *sdb = sdb_new(NULL, path, 0);
27  if (!sdb) {
28  free(path);
29  return NULL;
30  }
31  rz_config_serialize(core->config, sdb);
32  sdb_sync(sdb);
33  sdb_free(sdb);
34 
35  return path;
36 }
37 
38 static const char *system_apply_env_var(const char *env, const char *value, const char *arg, char **alloc_str) {
39  size_t len = strlen(arg);
40  if (!strstr(arg, env)) {
41  return arg;
42  } else if (strlen(env) == len) {
43  return value;
44  }
45 
46  if (!*alloc_str) {
47  *alloc_str = strdup(arg);
48  }
49 
50  *alloc_str = rz_str_replace(*alloc_str, env, value, 1);
51  return *alloc_str;
52 }
53 
54 static int system_exec(RzCore *core, int argc, const char **argv, char **output, int *length, int *ret) {
55  char file_size[32];
56  char core_offset[32];
57  char block_size[32];
58  const char *file_path = rz_config_get(core->config, "file.path");
59  const char *asm_arch = rz_config_get(core->config, "asm.arch");
60  const char *asm_bits = rz_config_get(core->config, "asm.bits");
61  const char *bin_demangle = rz_config_get(core->config, "bin.demangle");
62  const char *bin_lang = rz_config_get(core->config, "bin.lang");
63  const char *cfg_debug = rz_config_get(core->config, "cfg.debug");
64  const char *io_va = rz_config_get(core->config, "io.va");
65  const char *pdb_server = rz_config_get(core->config, "pdb.server");
66  const char *scr_color = rz_config_get(core->config, "scr.color");
67  const char *endian = rz_str_bool(core->rasm->big_endian);
68  char *cfg_path = config_path(core);
69 
70  rz_strf(file_size, "%" PFMT64u, core->file ? rz_io_fd_size(core->io, core->file->fd) : 0);
71  rz_strf(core_offset, "%" PFMT64u, core->offset);
72  rz_strf(block_size, "%u", core->blocksize);
73 
74  const char *envvars[] = {
75  "RZ_FILE",
76  "RZ_SIZE",
77  "RZ_ARCH",
78  "RZ_BITS",
79  "RZ_OFFSET",
80  "RZ_ENDIAN",
81  "RZ_BIN_DEMANGLE",
82  "RZ_BIN_LANG",
83  "RZ_BIN_PDBSERVER",
84  "RZ_IOVA",
85  "RZ_COLOR",
86  "RZ_BSIZE",
87  "RZ_DEBUG",
88  "RZ_CONFIG"
89  };
90  const char *envvals[] = {
91  file_path,
92  file_size,
93  asm_arch,
94  asm_bits,
95  core_offset,
96  endian,
97  bin_demangle,
98  bin_lang,
99  pdb_server,
100  io_va,
101  scr_color,
102  block_size,
103  cfg_debug,
104  rz_str_get(cfg_path)
105  };
106 
107  bool success = false;
108 
109  RzList *alloc = rz_list_newf(free);
110  if (!alloc) {
111  RZ_LOG_ERROR("Cannot allocate list of allocated strings.\n");
112  goto alloc_err;
113  }
114 
115  const char **args = RZ_NEWS0(const char *, argc);
116  if (!args) {
117  RZ_LOG_ERROR("Cannot allocate list of args.\n");
118  goto args_err;
119  }
120 
121  if (!rz_subprocess_init()) {
122  RZ_LOG_ERROR("Cannot initialize subprocess.\n");
123  goto subprocess_err;
124  }
125 
126  for (int i = 0; i < argc; ++i) {
127  char *alloc_str = NULL;
128  args[i] = system_apply_env_var(START_ENV_CHAR "RZ_FILE" END_ENV_CHAR, file_path, argv[i], &alloc_str);
129  args[i] = system_apply_env_var(START_ENV_CHAR "RZ_SIZE" END_ENV_CHAR, file_size, args[i], &alloc_str);
130  args[i] = system_apply_env_var(START_ENV_CHAR "RZ_ARCH" END_ENV_CHAR, asm_arch, args[i], &alloc_str);
131  args[i] = system_apply_env_var(START_ENV_CHAR "RZ_BITS" END_ENV_CHAR, asm_bits, args[i], &alloc_str);
132  args[i] = system_apply_env_var(START_ENV_CHAR "RZ_OFFSET" END_ENV_CHAR, core_offset, args[i], &alloc_str);
133  args[i] = system_apply_env_var(START_ENV_CHAR "RZ_ENDIAN" END_ENV_CHAR, endian, args[i], &alloc_str);
134  args[i] = system_apply_env_var(START_ENV_CHAR "RZ_BIN_DEMANGLE" END_ENV_CHAR, bin_demangle, args[i], &alloc_str);
135  args[i] = system_apply_env_var(START_ENV_CHAR "RZ_BIN_LANG" END_ENV_CHAR, bin_lang, args[i], &alloc_str);
136  args[i] = system_apply_env_var(START_ENV_CHAR "RZ_BIN_PDBSERVER" END_ENV_CHAR, pdb_server, args[i], &alloc_str);
137  args[i] = system_apply_env_var(START_ENV_CHAR "RZ_IOVA" END_ENV_CHAR, io_va, args[i], &alloc_str);
138  args[i] = system_apply_env_var(START_ENV_CHAR "RZ_COLOR" END_ENV_CHAR, scr_color, args[i], &alloc_str);
139  args[i] = system_apply_env_var(START_ENV_CHAR "RZ_BSIZE" END_ENV_CHAR, block_size, args[i], &alloc_str);
140  args[i] = system_apply_env_var(START_ENV_CHAR "RZ_DEBUG" END_ENV_CHAR, cfg_debug, args[i], &alloc_str);
141  args[i] = system_apply_env_var(START_ENV_CHAR "RZ_CONFIG" END_ENV_CHAR, cfg_path, args[i], &alloc_str);
142  if (alloc_str) {
143  rz_list_append(alloc, alloc_str);
144  }
145  }
146 
147  RzSubprocessOpt opt = {
148  .file = args[0],
149  .args = &args[1],
150  .args_size = argc - 1,
151  .envvars = envvars,
152  .envvals = envvals,
153  .env_size = RZ_ARRAY_SIZE(envvars),
154  .stdin_pipe = RZ_SUBPROCESS_PIPE_NONE,
156  .stderr_pipe = RZ_SUBPROCESS_PIPE_NONE,
157  };
158 
160  if (!proc) {
161  RZ_LOG_ERROR("Cannot start subprocess.\n");
162  goto proc_start_err;
163  }
164 
166  *ret = rz_subprocess_ret(proc);
167 
168  if (output) {
169  *output = (char *)rz_subprocess_out(proc, length);
170  }
171  success = true;
172 
174 proc_start_err:
176 subprocess_err:
177  free(args);
178 args_err:
179  rz_list_free(alloc);
180 alloc_err:
181  rz_file_rm(cfg_path);
182  free(cfg_path);
183 
184  return success;
185 }
186 
187 static RzCmdStatus system_common_handler(RzCore *core, bool force_rzcons, int argc, const char **argv) {
188  char *out = NULL;
189  int length = 0;
190  void *bed = rz_cons_sleep_begin();
191  bool need_rzcons = force_rzcons || core->is_pipe;
192  int ret = -1;
193  bool succ = system_exec(core, argc - 1, &argv[1], need_rzcons ? &out : NULL, &length, &ret);
194  rz_cons_sleep_end(bed);
195  if (need_rzcons) {
196 #if __WINDOWS__
197  char *src = out;
198  char *dest = src;
199  char *end = out + length;
200  while (src != end) {
201  *dest = *src;
202  if (src[0] == '\r' && src + 1 != end && src[1] == '\n') {
203  // dest does not move
204  length--;
205  } else {
206  dest++;
207  }
208  src++;
209  }
210 #endif
212  }
213  free(out);
214  core->num->value = (ut64)ret;
215  return succ ? RZ_CMD_STATUS_OK : RZ_CMD_STATUS_ERROR;
216 }
217 
218 RZ_IPI RzCmdStatus rz_system_handler(RzCore *core, int argc, const char **argv) {
219  return system_common_handler(core, false, argc, argv);
220 }
221 
222 RZ_IPI RzCmdStatus rz_system_to_cons_handler(RzCore *core, int argc, const char **argv) {
223  return system_common_handler(core, true, argc, argv);
224 }
225 
226 #undef START_ENV_CHAR
227 #undef END_ENV_CHAR
size_t len
Definition: 6502dis.c:15
#define RZ_IPI
Definition: analysis_wasm.c:11
lzma_index ** i
Definition: index.h:629
lzma_index * src
Definition: index.h:567
static const char * arg(RzAnalysis *a, csh *handle, cs_insn *insn, char *buf, int n)
Definition: arm_esil32.c:136
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
static int value
Definition: cmd_api.c:93
static RzCmdStatus system_common_handler(RzCore *core, bool force_rzcons, int argc, const char **argv)
Definition: cmd_system.c:187
#define START_ENV_CHAR
Definition: cmd_system.c:12
RZ_IPI RzCmdStatus rz_system_handler(RzCore *core, int argc, const char **argv)
Definition: cmd_system.c:218
#define END_ENV_CHAR
Definition: cmd_system.c:13
static const char * system_apply_env_var(const char *env, const char *value, const char *arg, char **alloc_str)
Definition: cmd_system.c:38
static char * config_path(RzCore *core)
Definition: cmd_system.c:16
static int system_exec(RzCore *core, int argc, const char **argv, char **output, int *length, int *ret)
Definition: cmd_system.c:54
RZ_IPI RzCmdStatus rz_system_to_cons_handler(RzCore *core, int argc, const char **argv)
Definition: cmd_system.c:222
RZ_API RZ_BORROW const char * rz_config_get(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:75
RZ_API void rz_config_serialize(RZ_NONNULL RzConfig *config, RZ_NONNULL Sdb *db)
Definition: config.c:547
RZ_API int rz_cons_memcat(const char *str, int len)
Definition: cons.c:1224
RZ_API void * rz_cons_sleep_begin(void)
Definition: cons.c:443
RZ_API void rz_cons_sleep_end(void *user)
Definition: cons.c:450
#define NULL
Definition: cris-opc.c:27
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
static static fork const void static count close
Definition: sflib.h:33
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
static static fork const void static count static fd const char const char static newpath char char argv
Definition: sflib.h:40
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
char * dest
Definition: lz4.h:697
int args
Definition: mipsasm.c:18
enum rz_cmd_status_t RzCmdStatus
@ RZ_CMD_STATUS_OK
command handler exited in the right way
Definition: rz_cmd.h:24
@ RZ_CMD_STATUS_ERROR
command handler had issues while running (e.g. allocation error, etc.)
Definition: rz_cmd.h:26
RZ_API int rz_file_mkstemp(RZ_NULLABLE const char *prefix, char **oname)
Definition: file.c:1058
RZ_API bool rz_file_rm(const char *file)
Definition: file.c:865
RZ_API ut64 rz_io_fd_size(RzIO *io, int fd)
Definition: io_fd.c:42
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
static const char * rz_str_get(const char *str)
Definition: rz_str.h:187
RZ_API const char * rz_str_bool(int b)
Definition: str.c:3896
RZ_API char * rz_str_replace(char *str, const char *key, const char *val, int g)
Definition: str.c:1110
#define rz_strf(buf,...)
Convenience macro for local temporary strings.
Definition: rz_str.h:59
RZ_API RzSubprocessWaitReason rz_subprocess_wait(RzSubprocess *proc, ut64 timeout_ms)
Definition: subprocess.c:1185
RZ_API void rz_subprocess_free(RzSubprocess *proc)
Definition: subprocess.c:1273
RZ_API ut8 * rz_subprocess_out(RzSubprocess *proc, int *length)
Definition: subprocess.c:1301
RZ_API RzSubprocess * rz_subprocess_start_opt(RzSubprocessOpt *opt)
Definition: subprocess.c:893
RZ_API void rz_subprocess_fini(void)
Definition: subprocess.c:814
RZ_API bool rz_subprocess_init(void)
Definition: subprocess.c:787
@ RZ_SUBPROCESS_PIPE_NONE
No pipe should be created. It can be used for stdin, stdout and stderr.
Definition: rz_subprocess.h:16
@ RZ_SUBPROCESS_PIPE_CREATE
Re-use the same pipe as stdout. It can be used for stderr only.
Definition: rz_subprocess.h:18
RZ_API int rz_subprocess_ret(RzSubprocess *proc)
Definition: subprocess.c:1297
#define RZ_NEWS0(x, y)
Definition: rz_types.h:282
#define PFMT64u
Definition: rz_types.h:395
#define RZ_ARRAY_SIZE(x)
Definition: rz_types.h:300
#define UT64_MAX
Definition: rz_types_base.h:86
RZ_API Sdb * sdb_new(const char *path, const char *name, int lock)
Definition: sdb.c:47
RZ_API bool sdb_free(Sdb *s)
Definition: sdb.c:206
RZ_API bool sdb_sync(Sdb *s)
Definition: sdb.c:803
int big_endian
Definition: rz_asm.h:101
ut64 offset
Definition: rz_core.h:301
RzAsm * rasm
Definition: rz_core.h:323
RzIO * io
Definition: rz_core.h:313
RzNum * num
Definition: rz_core.h:316
bool is_pipe
Definition: rz_core.h:339
RzCoreFile * file
Definition: rz_core.h:314
ut32 blocksize
Definition: rz_core.h:303
RzConfig * config
Definition: rz_core.h:300
ut64 value
Definition: rz_num.h:63
const char * file
< Name of the executable to run. It is searched also in PATH
Definition: rz_subprocess.h:59
Definition: sdb.h:63
struct Proc * proc
static char ** env
Definition: sys.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static const z80_opcode fd[]
Definition: z80_tab.h:997
diff_output_t output
Definition: zipcmp.c:237