diff --git a/app/src/adb.c b/app/src/adb.c index 630a1952..9ffc752a 100644 --- a/app/src/adb.c +++ b/app/src/adb.c @@ -132,8 +132,12 @@ adb_execute_p(const char *serial, const char *const adb_cmd[], memcpy(&argv[i], adb_cmd, len * sizeof(const char *)); argv[len + i] = NULL; + unsigned inherit = SC_STDERR; + if (!pout) { + inherit |= SC_STDOUT; + } enum sc_process_result r = - sc_process_execute_p(argv, &pid, NULL, pout, NULL); + sc_process_execute_p(argv, &pid, inherit, NULL, pout, NULL); if (r != SC_PROCESS_SUCCESS) { show_adb_err_msg(r, argv); pid = SC_PROCESS_NONE; diff --git a/app/src/sys/unix/process.c b/app/src/sys/unix/process.c index 5f4a9890..d876cc76 100644 --- a/app/src/sys/unix/process.c +++ b/app/src/sys/unix/process.c @@ -11,8 +11,16 @@ #include "util/log.h" enum sc_process_result -sc_process_execute_p(const char *const argv[], sc_pid *pid, +sc_process_execute_p(const char *const argv[], sc_pid *pid, unsigned inherit, int *pin, int *pout, int *perr) { + bool inherit_stdout = inherit & SC_STDOUT; + bool inherit_stderr = inherit & SC_STDERR; + + // If pout is defined, then inherit MUST NOT contain SC_STDOUT. + assert(!pout || !inherit_stdout); + // If perr is defined, then inherit MUST NOT contain SC_STDERR. + assert(!perr || !inherit_stderr); + int in[2]; int out[2]; int err[2]; @@ -90,20 +98,31 @@ sc_process_execute_p(const char *const argv[], sc_pid *pid, } close(in[1]); } + // Do not close stdin in the child process, this makes adb fail on + // Linux + if (pout) { if (out[1] != STDOUT_FILENO) { dup2(out[1], STDOUT_FILENO); close(out[1]); } close(out[0]); + } else if (!inherit_stdout) { + // Close stdout in the child process + close(STDOUT_FILENO); } + if (perr) { if (err[1] != STDERR_FILENO) { dup2(err[1], STDERR_FILENO); close(err[1]); } close(err[0]); + } else if (!inherit_stderr) { + // Close stderr in the child process + close(STDERR_FILENO); } + close(internal[0]); enum sc_process_result err; if (fcntl(internal[1], F_SETFD, FD_CLOEXEC) == 0) { diff --git a/app/src/sys/win/process.c b/app/src/sys/win/process.c index 222a0240..241a47de 100644 --- a/app/src/sys/win/process.c +++ b/app/src/sys/win/process.c @@ -27,12 +27,22 @@ build_cmd(char *cmd, size_t len, const char *const argv[]) { } enum sc_process_result -sc_process_execute_p(const char *const argv[], HANDLE *handle, +sc_process_execute_p(const char *const argv[], HANDLE *handle, unsigned inherit, HANDLE *pin, HANDLE *pout, HANDLE *perr) { - enum sc_process_result ret = SC_PROCESS_ERROR_GENERIC; + bool inherit_stdout = inherit & SC_STDOUT; + bool inherit_stderr = inherit & SC_STDERR; + + // If pout is defined, then inherit MUST NOT contain SC_STDOUT. + assert(!pout || !inherit_stdout); + // If perr is defined, then inherit MUST NOT contain SC_STDERR. + assert(!perr || !inherit_stderr); // Add 1 per non-NULL pointer - unsigned handle_count = !!pin + !!pout + !!perr; + unsigned handle_count = !!pin + + (pout || inherit_stdout) + + (perr || inherit_stderr); + + enum sc_process_result ret = SC_PROCESS_ERROR_GENERIC; SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES); @@ -80,20 +90,24 @@ sc_process_execute_p(const char *const argv[], HANDLE *handle, HANDLE handles[3]; LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList = NULL; - if (handle_count) { - si.StartupInfo.dwFlags = STARTF_USESTDHANDLES; + // Must be set even if handle_count == 0, so that stdin, stdout and stderr + // are NOT inherited in that case + si.StartupInfo.dwFlags = STARTF_USESTDHANDLES; + if (handle_count) { unsigned i = 0; if (pin) { si.StartupInfo.hStdInput = stdin_read_handle; handles[i++] = si.StartupInfo.hStdInput; } - if (pout) { - si.StartupInfo.hStdOutput = stdout_write_handle; + if (pout || inherit_stdout) { + si.StartupInfo.hStdOutput = pout ? stdout_write_handle + : GetStdHandle(STD_OUTPUT_HANDLE); handles[i++] = si.StartupInfo.hStdOutput; } - if (perr) { - si.StartupInfo.hStdError = stderr_write_handle; + if (perr || inherit_stderr) { + si.StartupInfo.hStdError = perr ? stderr_write_handle + : GetStdHandle(STD_ERROR_HANDLE); handles[i++] = si.StartupInfo.hStdError; } diff --git a/app/src/util/process.c b/app/src/util/process.c index 28f51edd..8fcfdd7c 100644 --- a/app/src/util/process.c +++ b/app/src/util/process.c @@ -5,8 +5,8 @@ #include "log.h" enum sc_process_result -sc_process_execute(const char *const argv[], sc_pid *pid) { - return sc_process_execute_p(argv, pid, NULL, NULL, NULL); +sc_process_execute(const char *const argv[], sc_pid *pid, unsigned inherit) { + return sc_process_execute_p(argv, pid, inherit, NULL, NULL, NULL); } bool diff --git a/app/src/util/process.h b/app/src/util/process.h index 7964be5c..6c85a9ed 100644 --- a/app/src/util/process.h +++ b/app/src/util/process.h @@ -67,20 +67,31 @@ enum sc_process_result { SC_PROCESS_ERROR_MISSING_BINARY, }; +#define SC_STDOUT (1 << 0) +#define SC_STDERR (1 << 1) + /** * Execute the command and write the process id to `pid` + * + * The parameter `inherit` is a OR of any of SC_STDOUT and SC_STDERR. It + * indicates if stdout and stderr must be inherited from the scrcpy process (in + * other words, if the process must output to the scrcpy console). */ enum sc_process_result -sc_process_execute(const char *const argv[], sc_pid *pid); +sc_process_execute(const char *const argv[], sc_pid *pid, unsigned inherit); /** * Execute the command and write the process id to `pid` * * If not NULL, provide a pipe for stdin (`pin`), stdout (`pout`) and stderr * (`perr`). + * + * The parameter `inherit` has the same semantics as in `sc_process_execute()`. + * If `pout` is not NULL, then `inherit` MUST NOT contain SC_STDOUT. + * If `perr` is not NULL, then `inherit` MUST NOT contain SC_STDERR. */ enum sc_process_result -sc_process_execute_p(const char *const argv[], sc_pid *pid, +sc_process_execute_p(const char *const argv[], sc_pid *pid, unsigned inherit, sc_pipe *pin, sc_pipe *pout, sc_pipe *perr); /**