8 #define BUFFER_SIZE 0x500
13 #if NTDDI_VERSION >= NTDDI_VISTA
14 typedef _Success_(
return !=
FALSE) BOOL(WINAPI *InitializeProcThreadAttributeList_t)(
15 _Out_writes_bytes_to_opt_(*lpSize, *lpSize) LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
16 _In_
DWORD dwAttributeCount,
17 _Reserved_
DWORD dwFlags,
18 _When_(lpAttributeList ==
nullptr, _Out_) _When_(lpAttributeList !=
nullptr, _Inout_) PSIZE_T lpSize);
20 typedef BOOL(WINAPI *UpdateProcThreadAttribute_t)(
21 _Inout_ LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
24 _In_reads_bytes_opt_(cbSize)
PVOID lpValue,
26 _Out_writes_bytes_opt_(cbSize)
PVOID lpPreviousValue,
27 _In_opt_ PSIZE_T lpReturnSize);
29 typedef VOID(WINAPI *DeleteProcThreadAttributeList_t)(
30 _Inout_ LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList);
32 static InitializeProcThreadAttributeList_t lpInitializeProcThreadAttributeList =
NULL;
33 static UpdateProcThreadAttribute_t lpUpdateProcThreadAttribute =
NULL;
34 static DeleteProcThreadAttributeList_t lpDeleteProcThreadAttributeList =
NULL;
47 #define INVALID_POINTER_VALUE ((void *)PTRDIFF_MAX)
50 static long refcount = 0;
51 static bool has_procthreadattr =
false;
52 static volatile long pipe_id = 0;
53 static DWORD mode_stdin;
54 static DWORD mode_stdout;
55 static DWORD mode_stderr;
57 static bool create_pipe_overlap(
HANDLE *pipe_read,
HANDLE *pipe_write, LPSECURITY_ATTRIBUTES attrs,
DWORD sz,
DWORD read_mode,
DWORD write_mode) {
64 *pipe_read = CreateNamedPipeW(
name, PIPE_ACCESS_INBOUND | read_mode, PIPE_TYPE_BYTE | PIPE_WAIT, 1, sz, sz, 120 * 1000, attrs);
68 *pipe_write = CreateFileW(
name, GENERIC_WRITE, 0, attrs, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | write_mode,
NULL);
70 CloseHandle(*pipe_read);
74 SetEnvironmentVariableW(
L"RZ_PIPE_PATH",
name);
81 lock = InterlockedCompareExchangePointer(&subproc_mutex, INVALID_POINTER_VALUE, INVALID_POINTER_VALUE);
92 InterlockedExchangePointer(&subproc_mutex, INVALID_POINTER_VALUE);
98 InterlockedExchangePointer(&subproc_mutex,
lock);
101 lock = get_subprocess_lock();
102 if (
lock == INVALID_POINTER_VALUE) {
115 GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode_stdin);
116 GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &mode_stdout);
117 GetConsoleMode(GetStdHandle(STD_ERROR_HANDLE), &mode_stderr);
119 #if NTDDI_VERSION >= NTDDI_VISTA
120 if (!has_procthreadattr && IsWindowsVistaOrGreater()) {
121 HMODULE kernel32 = LoadLibraryW(
L"kernel32");
126 lpInitializeProcThreadAttributeList = (InitializeProcThreadAttributeList_t)GetProcAddress(kernel32,
"InitializeProcThreadAttributeList");
127 lpUpdateProcThreadAttribute = (UpdateProcThreadAttribute_t)GetProcAddress(kernel32,
"UpdateProcThreadAttribute");
128 lpDeleteProcThreadAttributeList = (DeleteProcThreadAttributeList_t)GetProcAddress(kernel32,
"DeleteProcThreadAttributeList");
129 if (lpInitializeProcThreadAttributeList && lpUpdateProcThreadAttribute && lpDeleteProcThreadAttributeList) {
130 has_procthreadattr =
true;
132 FreeLibrary(kernel32);
147 lock = InterlockedExchangePointer(&subproc_mutex,
NULL);
150 InterlockedExchangePointer(&subproc_mutex,
lock);
153 SetEnvironmentVariableW(
L"RZ_PIPE_PATH",
NULL);
155 SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode_stdin);
156 SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), mode_stdout);
157 SetConsoleMode(GetStdHandle(STD_ERROR_HANDLE), mode_stderr);
162 static LPWCH override_env(
const char *envvars[],
const char *envvals[],
size_t env_size) {
164 LPWCH parent_env =
NULL;
168 parent_env = GetEnvironmentStringsW();
169 if (!wenvvars || !wenvvals || !parent_env) {
173 for (
i = 0;
i < env_size;
i++) {
174 wenvvars[
i] = rz_utf8_to_utf16(envvars[
i]);
175 wenvvals[
i] = rz_utf8_to_utf16(envvals[
i]);
176 if (!wenvvars[
i] || !wenvvals[
i]) {
183 LPWCH cur = parent_env;
185 LPWCH var_begin = cur;
187 while (*cur && *cur !=
L'=') {
197 bool overridden =
false;
198 for (
i = 0;
i < env_size;
i++) {
199 size_t overlen = lstrlenW(wenvvars[
i]);
200 size_t curlen = cur - var_begin;
201 if (overlen == curlen && !memcmp(var_begin, wenvvars[
i], overlen)) {
220 for (
i = 0;
i < env_size;
i++) {
234 FreeEnvironmentStringsW(parent_env);
236 for (
i = 0;
i < env_size;
i++) {
251 const HANDLE curr_stdin_handle = (
HANDLE)_get_osfhandle(fileno(stdin));
252 const HANDLE curr_stdout_handle = (
HANDLE)_get_osfhandle(fileno(stdout));
253 const HANDLE curr_stderr_handle = (
HANDLE)_get_osfhandle(fileno(stderr));
254 HANDLE stdin_read = curr_stdin_handle;
255 HANDLE stdout_write = curr_stdout_handle;
256 HANDLE stderr_write = curr_stderr_handle;
258 PWCHAR cmd_exe =
RZ_NEWS0(WCHAR, MAX_PATH);
259 #if NTDDI_VERSION >= NTDDI_VISTA
260 LPPROC_THREAD_ATTRIBUTE_LIST attr_list =
NULL;
264 PWCHAR
file = rz_utf8_to_utf16(opt->
file);
271 if ((
len = SearchPathW(
NULL,
file,
L".exe", MAX_PATH, cmd_exe, &lpFilePart)) < 1) {
276 if (
len > MAX_PATH) {
284 SearchPathW(
NULL,
file,
L".exe",
len, cmd_exe, &lpFilePart);
304 PWCHAR cmdline = rz_utf8_to_utf16(
cmd);
310 char *log_executable = rz_utf16_to_utf8(cmd_exe);
311 if (log_executable) {
313 free(log_executable);
326 SECURITY_ATTRIBUTES sattrs;
327 sattrs.nLength =
sizeof(sattrs);
328 sattrs.bInheritHandle =
TRUE;
329 sattrs.lpSecurityDescriptor =
NULL;
332 if (!create_pipe_overlap(&
proc->stdout_read, &stdout_write, &sattrs, 0, FILE_FLAG_OVERLAPPED, 0)) {
333 proc->stdout_read = stdout_write =
NULL;
336 if (!SetHandleInformation(
proc->stdout_read, HANDLE_FLAG_INHERIT, 0)) {
341 if (!create_pipe_overlap(&
proc->stderr_read, &stderr_write, &sattrs, 0, FILE_FLAG_OVERLAPPED, 0)) {
342 proc->stdout_read = stderr_write =
NULL;
345 if (!SetHandleInformation(
proc->stderr_read, HANDLE_FLAG_INHERIT, 0)) {
349 proc->stderr_read =
proc->stdout_read;
350 stderr_write = stdout_write;
354 if (!CreatePipe(&stdin_read, &
proc->stdin_write, &sattrs, 0)) {
355 stdin_read =
proc->stdin_write =
NULL;
358 if (!SetHandleInformation(
proc->stdin_write, HANDLE_FLAG_INHERIT, 0)) {
363 PROCESS_INFORMATION proc_info = { 0 };
364 DWORD dwCreationFlags = CREATE_UNICODE_ENVIRONMENT;
365 STARTUPINFOW start_info_short = { .cb =
sizeof(STARTUPINFOW) };
366 STARTUPINFOW *start_info = &start_info_short;
367 #if NTDDI_VERSION >= NTDDI_VISTA
368 STARTUPINFOEXW start_infoex = { .StartupInfo.cb =
sizeof(STARTUPINFOEXW) };
369 if (has_procthreadattr) {
370 SIZE_T attr_list_size = 0;
371 if (!lpInitializeProcThreadAttributeList(
NULL, 1, 0, &attr_list_size) &&
372 GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
375 attr_list =
malloc(attr_list_size);
379 if (!lpInitializeProcThreadAttributeList(attr_list, 1, 0, &attr_list_size)) {
382 HANDLE handle_list[3] = { stdin_read, stdout_write };
384 handle_list[2] = stderr_write;
387 if (!lpUpdateProcThreadAttribute(attr_list, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, handle_list, num_handles *
sizeof(
HANDLE),
NULL,
NULL)) {
390 start_info = (STARTUPINFOW *)&start_infoex;
391 start_infoex.lpAttributeList = attr_list;
392 dwCreationFlags |= EXTENDED_STARTUPINFO_PRESENT;
394 lock = get_subprocess_lock();
397 lock = get_subprocess_lock();
400 start_info->hStdError = stderr_write;
401 start_info->hStdOutput = stdout_write;
402 start_info->hStdInput = stdin_read;
403 start_info->dwFlags = STARTF_USESTDHANDLES;
423 CloseHandle(proc_info.hThread);
424 proc->proc = proc_info.hProcess;
431 #if NTDDI_VERSION >= NTDDI_VISTA
433 lpDeleteProcThreadAttributeList(attr_list);
438 if (stdin_read && stdin_read != curr_stdin_handle) {
439 CloseHandle(stdin_read);
441 if (stderr_write && stderr_write != curr_stderr_handle && stderr_write != stdout_write) {
442 CloseHandle(stderr_write);
444 if (stdout_write && stdout_write != curr_stdout_handle) {
445 CloseHandle(stdout_write);
452 if (
proc->stderr_read &&
proc->stderr_read !=
proc->stdout_read) {
453 CloseHandle(
proc->stderr_read);
455 if (
proc->stdout_read) {
456 CloseHandle(
proc->stdout_read);
458 if (
proc->stdin_write) {
459 CloseHandle(
proc->stdin_write);
469 if (n_bytes && to_read > n_bytes) {
472 if (!ReadFile(
f,
buf, to_read,
NULL, overlapped)) {
473 if (GetLastError() != ERROR_IO_PENDING) {
484 DWORD bytes_transferred;
485 if (GetOverlappedResult(
f, overlapped, &bytes_transferred,
TRUE) || GetLastError() == ERROR_OPERATION_ABORTED) {
490 CloseHandle(overlapped->hEvent);
494 OVERLAPPED stdout_overlapped = { 0 };
495 OVERLAPPED stderr_overlapped = { 0 };
505 bool stdout_eof =
false;
506 bool stderr_eof =
false;
507 bool child_dead =
false;
508 bool bytes_enabled = n_bytes != 0;
510 if (stdout_enabled) {
512 if (!stdout_overlapped.hEvent) {
516 if (stderr_enabled) {
518 if (!stderr_overlapped.hEvent) {
519 CloseHandle(stdout_overlapped.hEvent);
523 if (stdout_enabled) {
524 stdout_eof =
do_read(
proc->stdout_read, stdout_buf,
sizeof(stdout_buf) - 1, n_bytes, &stdout_overlapped);
526 if (stderr_enabled) {
527 stderr_eof =
do_read(
proc->stderr_read, stderr_buf,
sizeof(stderr_buf) - 1, n_bytes, &stderr_overlapped);
533 bool did_once =
false;
535 while ((!bytes_enabled || n_bytes) && !child_dead) {
537 size_t stdout_index = 0;
538 size_t stderr_index = 0;
539 size_t proc_index = 0;
540 if (stdout_enabled && !stdout_eof) {
541 stdout_index = handles.
len;
544 if (stderr_enabled && !stderr_eof) {
545 stderr_index = handles.
len;
549 proc_index = handles.
len;
555 if (now >= timeout_us_abs) {
558 if (stdout_enabled) {
559 cancel_read(
proc->stderr_read, &
proc->out, stdout_buf, &stderr_overlapped);
561 if (stderr_enabled) {
562 cancel_read(
proc->stderr_read, &
proc->err, stderr_buf, &stderr_overlapped);
573 if (stdout_enabled && !stdout_eof && signaled == stdout_index) {
575 BOOL res = GetOverlappedResult(
proc->stdout_read, &stdout_overlapped, &
r,
TRUE);
581 ResetEvent(stdout_overlapped.hEvent);
582 if (
r >= 0 && n_bytes) {
588 stdout_eof =
do_read(
proc->stdout_read, stdout_buf,
sizeof(stdout_buf) - 1, n_bytes, &stdout_overlapped);
591 if (stderr_enabled && !stderr_eof && signaled == stderr_index) {
593 BOOL res = GetOverlappedResult(
proc->stderr_read, &stderr_overlapped, &
r,
TRUE);
599 if (
r >= 0 && n_bytes) {
605 ResetEvent(stderr_overlapped.hEvent);
606 stderr_eof =
do_read(
proc->stderr_read, stderr_buf,
sizeof(stderr_buf) - 1, n_bytes, &stderr_overlapped);
609 if (!child_dead && signaled == proc_index) {
612 if (GetExitCodeProcess(
proc->proc, &exit_code)) {
613 proc->ret = exit_code;
620 if (stdout_overlapped.hEvent) {
621 CloseHandle(stdout_overlapped.hEvent);
623 if (stderr_overlapped.hEvent) {
624 CloseHandle(stderr_overlapped.hEvent);
630 CloseHandle(
proc->stdin_write);
641 TerminateProcess(
proc->proc, 255);
645 if (!
proc->stdin_write) {
655 if (
proc->stdout_read) {
664 if (
proc->stdout_read) {
691 if (
proc->stdin_write) {
692 CloseHandle(
proc->stdin_write);
694 if (
proc->stderr_read &&
proc->stderr_read !=
proc->stdout_read) {
695 CloseHandle(
proc->stderr_read);
697 if (
proc->stdout_read) {
698 CloseHandle(
proc->stdout_read);
700 CloseHandle(
proc->proc);
706 #include <sys/wait.h>
743 if (errno ==
EINTR) {
755 pid_t pid = waitpid(-1, &wstat, WNOHANG);
774 if (WIFEXITED(wstat)) {
775 proc->ret = WEXITSTATUS(wstat);
826 static char **
create_child_env(
const char *envvars[],
const char *envvals[],
size_t env_size) {
828 size_t new_env_size = env_size,
size = 0;
829 size_t *positions =
RZ_NEWS(
size_t, env_size);
833 for (
size_t i = 0;
i < env_size;
i++) {
841 for (j = 0; j < env_size; j++) {
845 size_t namelen = strlen(envvars[j]);
846 if (!strncmp(*ep, envvars[j], namelen) && (*ep)[namelen] ==
'=') {
854 char **new_env =
RZ_NEWS(
char *,
size + new_env_size + 1);
859 for (
size_t i = 0;
i <
size;
i++) {
862 for (
size_t i = 0;
i <= new_env_size;
i++) {
866 for (
size_t i = 0;
i < env_size;
i++) {
867 char *new_var =
rz_str_newf(
"%s=%s", envvars[
i], envvals[
i]);
871 new_env[
size++] = new_var;
874 free(new_env[positions[
i]]);
875 new_env[positions[
i]] = new_var;
887 for (ep = child_env; *ep; ep++) {
895 char **child_env =
NULL;
910 proc->killpipe[0] =
proc->killpipe[1] = -1;
913 proc->stdout_fd = -1;
914 proc->stderr_fd = -1;
929 int stderr_pipe[2] = { -1, -1 };
959 proc->stderr_fd = stderr_pipe[0];
971 if (
proc->pid == -1) {
975 }
else if (
proc->pid == 0) {
977 if (stderr_pipe[1] != -1) {
980 if (
proc->stderr_fd !=
proc->stdout_fd) {
1014 if (stderr_pipe[1] != -1 &&
proc->stderr_fd !=
proc->stdout_fd) {
1025 if (
proc &&
proc->killpipe[0] == -1) {
1028 if (
proc &&
proc->killpipe[1] == -1) {
1032 if (stderr_pipe[0] != -1 && stderr_pipe[0] !=
stdout_pipe[0]) {
1035 if (stderr_pipe[1] != -1 && stderr_pipe[1] !=
stdout_pipe[1]) {
1057 size_t to_read =
sizeof(
buf);
1058 if (n_bytes && to_read > n_bytes) {
1064 }
else if (sz == 0) {
1094 bool stdout_eof =
false;
1095 bool stderr_eof =
false;
1096 bool child_dead =
false;
1097 bool timedout =
true;
1098 bool bytes_enabled = n_bytes != 0;
1099 while ((!bytes_enabled || n_bytes) && ((stdout_enabled && !stdout_eof) || (stderr_enabled && !stderr_eof) || !child_dead)) {
1103 if (stdout_enabled && !stdout_eof) {
1109 if (stderr_enabled && !stderr_eof) {
1127 if (now >= timeout_abs) {
1137 if (errno ==
EINTR) {
1144 if (stdout_enabled &&
FD_ISSET(
proc->stdout_fd, &rfds)) {
1147 if (
r > 0 && n_bytes) {
1151 if (stderr_enabled &&
FD_ISSET(
proc->stderr_fd, &rfds)) {
1154 if (
r > 0 && n_bytes) {
1171 }
else if (timedout) {
1186 if (
proc->stdin_fd != -1) {
1189 proc->stdin_fd = -1;
1208 if (
proc->stdin_fd == -1) {
1228 if (
proc->stdout_fd != -1) {
1244 if (
proc->stdout_fd != -1) {
1267 out->timeout =
false;
1284 if (
proc->stdin_fd != -1) {
1287 if (
proc->stdout_fd != -1) {
1290 if (
proc->stderr_fd != -1 &&
proc->stderr_fd !=
proc->stdout_fd) {
1346 const char *
file,
const char *
args[],
size_t args_size,
1347 const char *envvars[],
const char *envvals[],
size_t env_size) {
1351 .args_size = args_size,
1354 .env_size = env_size,
const lzma_allocator const uint8_t size_t uint8_t * out
struct java_attribute_t Attribute
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 cmd
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 fcntl
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
static int do_read(zip_t *z, const char *name, zip_flags_t flags, enum when when_ex, int ze_ex, int se_ex)
RZ_API void Ht_() free(HtName_(Ht) *ht)
#define INVALID_HANDLE_VALUE
InterlockedCompareExchange
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
RZ_API void rz_th_free(RZ_NULLABLE RzThread *th)
Frees a RzThread structure.
RZ_API RZ_OWN RzThread * rz_th_new(RZ_NONNULL RzThreadFunction function, RZ_NULLABLE void *user)
Creates and starts a new thread.
RZ_API bool rz_th_wait(RZ_NONNULL RzThread *th)
Awaits indefinetely for a thread to join.
void * realloc(void *ptr, size_t size)
void * malloc(size_t size)
void * calloc(size_t number, size_t size)
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc kill
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc pid
static static fork const void static count static fd const char const char static newpath char char argv
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz select
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")
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync const char const char static newpath const char static pathname unsigned long static filedes void static end_data_segment static handler static getegid char static len static pgid const char static path dup2
static const char struct stat static buf struct stat static buf static vhangup int struct rusage static rusage struct sysinfo static info unsigned static __unused struct utsname static buf const char static size const char static name static pid unsigned static persona static fsgid const void static flags const struct iovec static count static fd const void static len static munlockall struct sched_param static p static sched_yield static policy const struct timespec struct timespec static rem uid_t uid_t uid_t static suid struct pollfd unsigned nfds
#define rz_warn_if_reached()
RZ_API bool rz_file_exists(const char *str)
#define RZ_LOG_DEBUG(fmtstr,...)
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API char RZ_API char * rz_str_newlen(const char *str, int len)
RZ_API char * rz_str_format_msvc_argv(size_t argc, const char **argv)
RZ_API char * rz_strbuf_get(RzStrBuf *sb)
RZ_API void rz_strbuf_fini(RzStrBuf *sb)
RZ_API ut8 * rz_strbuf_getbin(RzStrBuf *sb, int *len)
RZ_API void rz_strbuf_init(RzStrBuf *sb)
RZ_API int rz_strbuf_length(RzStrBuf *sb)
RZ_API bool rz_strbuf_append_n(RzStrBuf *sb, const char *s, size_t l)
#define RZ_SUBPROCESS_STDOUT
@ RZ_SUBPROCESS_BYTESREAD
enum rz_process_wait_reason_t RzSubprocessWaitReason
#define RZ_SUBPROCESS_STDERR
@ RZ_SUBPROCESS_PIPE_STDOUT
@ RZ_SUBPROCESS_PIPE_CREATE
Re-use the same pipe as stdout. It can be used for stderr only.
RZ_API void rz_sys_set_environ(char **e)
RZ_API int rz_sys_pipe(int pipefd[2], bool close_on_exec)
RZ_API void rz_sys_exit(int status, bool nocleanup)
RZ_API int rz_sys_fork(void)
RZ_API int rz_sys_pipe_close(int fd)
RZ_API int rz_sys_execvp(const char *file, char *const argv[])
RZ_API int rz_sys_signal(int sig, void(*handler)(int))
RZ_API char ** rz_sys_get_environ(void)
RZ_API ut64 rz_time_now_mono(void)
Returns the current time in microseconds, using the monotonic clock.
#define rz_xwrite(fd, buf, count)
RZ_API void rz_pvector_remove_data(RzPVector *vec, void *x)
RZ_API void rz_pvector_init(RzPVector *vec, RzPVectorFree free)
RZ_API void * rz_vector_push(RzVector *vec, void *x)
static void ** rz_pvector_push(RzPVector *vec, void *x)
RZ_API void * rz_vector_insert_range(RzVector *vec, size_t index, void *first, size_t count)
RZ_API void rz_vector_clear(RzVector *vec)
RZ_API void rz_vector_init(RzVector *vec, size_t elem_size, RzVectorFree free, void *free_user)
RZ_API void rz_pvector_clear(RzPVector *vec)
#define rz_pvector_foreach(vec, it)
size_t env_size
Specify how to deal with subprocess stdin.
const char * file
< Name of the executable to run. It is searched also in PATH
RzSubprocessPipeCreate stderr_pipe
RzSubprocessPipeCreate stdout_pipe
Specify how to deal with subprocess stderr.
size_t args_size
Names of environment variables that subprocess should have differently from parent.
const char ** envvals
Number of elements contained in both envvars and envvals.
const char ** args
Number of arguments in args array.
RzSubprocessPipeCreate stdin_pipe
Specify how to deal with subprocess stdout.
const char ** envvars
Values of environment variables that subprocess should have differently from parent.
RZ_API RzSubprocessOutput * rz_subprocess_drain(RzSubprocess *proc)
RZ_API RzSubprocessWaitReason rz_subprocess_wait(RzSubprocess *proc, ut64 timeout_ms)
static RzThreadLock * subprocs_mutex
static size_t read_to_strbuf(RzStrBuf *sb, int fd, bool *fd_eof, size_t n_bytes)
static void * sigchld_th(void *th)
RZ_API void rz_subprocess_free(RzSubprocess *proc)
RZ_API ut8 * rz_subprocess_out(RzSubprocess *proc, int *length)
static char ** create_child_env(const char *envvars[], const char *envvals[], size_t env_size)
static RzThread * sigchld_thread
RZ_API RzSubprocess * rz_subprocess_start_opt(RzSubprocessOpt *opt)
RZ_API void rz_subprocess_fini(void)
RZ_API RzSubprocess * rz_subprocess_start(const char *file, const char *args[], size_t args_size, const char *envvars[], const char *envvals[], size_t env_size)
RZ_API void rz_subprocess_output_free(RzSubprocessOutput *out)
static void destroy_child_env(char **child_env)
static RzSubprocessWaitReason subprocess_wait(RzSubprocess *proc, ut64 timeout_ms, int pipe_fd, size_t n_bytes)
Wait for subprocess to do something, for a maximum of timeout_ms millisecond.
RZ_API ut8 * rz_subprocess_err(RzSubprocess *proc, int *length)
RZ_API ssize_t rz_subprocess_stdin_write(RzSubprocess *proc, const ut8 *buf, size_t buf_size)
static RzPVector subprocs
RZ_API bool rz_subprocess_init(void)
RZ_API RzStrBuf * rz_subprocess_stdout_read(RzSubprocess *proc, size_t n, ut64 timeout_ms)
static int sigchld_pipe[2]
static void subprocess_unlock(void)
RZ_API int rz_subprocess_ret(RzSubprocess *proc)
RZ_API void rz_subprocess_kill(RzSubprocess *proc)
RZ_API RzStrBuf * rz_subprocess_stdout_readline(RzSubprocess *proc, ut64 timeout_ms)
static void handle_sigchld(int sig)
static void subprocess_lock(void)
RZ_API void rz_th_lock_leave(RZ_NONNULL RzThreadLock *thl)
Releases a RzThreadLock structure.
RZ_API void rz_th_lock_free(RZ_NULLABLE RzThreadLock *thl)
Frees a RzThreadLock structure.
RZ_API RZ_OWN RzThreadLock * rz_th_lock_new(bool recursive)
Allocates and initialize a RzThreadLock structure.
RZ_API void rz_th_lock_enter(RZ_NONNULL RzThreadLock *thl)
Acquires a RzThreadLock structure.
static void lock(volatile int *lk)
void error(const char *msg)
if(dbg->bits==RZ_SYS_BITS_64)
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static const z80_opcode fd[]
int read(izstream &zs, T *x, Items items)