From aa011832c155ad57230e8241932c3331218c95b3 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Thu, 11 Nov 2021 17:48:41 +0100 Subject: [PATCH] Improve process API Prefix symbols and constants names and improve documentation. --- app/src/adb.c | 71 +++++++++++------------ app/src/adb.h | 21 ++++--- app/src/file_handler.c | 32 +++++------ app/src/file_handler.h | 2 +- app/src/server.c | 38 ++++++------- app/src/server.h | 2 +- app/src/sys/unix/process.c | 80 +++++++++++++------------- app/src/sys/win/process.c | 75 ++++++++++++------------ app/src/util/process.c | 21 +++---- app/src/util/process.h | 113 +++++++++++++++++++++++-------------- 10 files changed, 240 insertions(+), 215 deletions(-) diff --git a/app/src/adb.c b/app/src/adb.c index 1eb8d9ed..c7a64501 100644 --- a/app/src/adb.c +++ b/app/src/adb.c @@ -81,7 +81,7 @@ show_adb_installation_msg() { } static void -show_adb_err_msg(enum process_result err, const char *const argv[]) { +show_adb_err_msg(enum sc_process_result err, const char *const argv[]) { #define MAX_COMMAND_STRING_LEN 1024 char *buf = malloc(MAX_COMMAND_STRING_LEN); if (!buf) { @@ -90,18 +90,18 @@ show_adb_err_msg(enum process_result err, const char *const argv[]) { } switch (err) { - case PROCESS_ERROR_GENERIC: + case SC_PROCESS_ERROR_GENERIC: argv_to_string(argv, buf, MAX_COMMAND_STRING_LEN); LOGE("Failed to execute: %s", buf); break; - case PROCESS_ERROR_MISSING_BINARY: + case SC_PROCESS_ERROR_MISSING_BINARY: argv_to_string(argv, buf, MAX_COMMAND_STRING_LEN); LOGE("Command not found: %s", buf); LOGE("(make 'adb' accessible from your PATH or define its full" "path in the ADB environment variable)"); show_adb_installation_msg(); break; - case PROCESS_SUCCESS: + case SC_PROCESS_SUCCESS: // do nothing break; } @@ -109,16 +109,15 @@ show_adb_err_msg(enum process_result err, const char *const argv[]) { free(buf); } -process_t -adb_execute_redirect(const char *serial, const char *const adb_cmd[], - size_t len, pipe_t *pipe_stdin, pipe_t *pipe_stdout, - pipe_t *pipe_stderr) { +sc_pid +adb_execute_p(const char *serial, const char *const adb_cmd[], + size_t len, sc_pipe *pin, sc_pipe *pout, sc_pipe *perr) { int i; - process_t process; + sc_pid pid; const char **argv = malloc((len + 4) * sizeof(*argv)); if (!argv) { - return PROCESS_NONE; + return SC_PROCESS_NONE; } argv[0] = get_adb_command(); @@ -132,24 +131,23 @@ adb_execute_redirect(const char *serial, const char *const adb_cmd[], memcpy(&argv[i], adb_cmd, len * sizeof(const char *)); argv[len + i] = NULL; - enum process_result r = - process_execute_redirect(argv, &process, pipe_stdin, pipe_stdout, - pipe_stderr); - if (r != PROCESS_SUCCESS) { + enum sc_process_result r = + sc_process_execute_p(argv, &pid, pin, pout, perr); + if (r != SC_PROCESS_SUCCESS) { show_adb_err_msg(r, argv); - process = PROCESS_NONE; + pid = SC_PROCESS_NONE; } free(argv); - return process; + return pid; } -process_t +sc_pid adb_execute(const char *serial, const char *const adb_cmd[], size_t len) { - return adb_execute_redirect(serial, adb_cmd, len, NULL, NULL, NULL); + return adb_execute_p(serial, adb_cmd, len, NULL, NULL, NULL); } -process_t +sc_pid adb_forward(const char *serial, uint16_t local_port, const char *device_socket_name) { char local[4 + 5 + 1]; // tcp:PORT @@ -160,7 +158,7 @@ adb_forward(const char *serial, uint16_t local_port, return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd)); } -process_t +sc_pid adb_forward_remove(const char *serial, uint16_t local_port) { char local[4 + 5 + 1]; // tcp:PORT sprintf(local, "tcp:%" PRIu16, local_port); @@ -168,7 +166,7 @@ adb_forward_remove(const char *serial, uint16_t local_port) { return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd)); } -process_t +sc_pid adb_reverse(const char *serial, const char *device_socket_name, uint16_t local_port) { char local[4 + 5 + 1]; // tcp:PORT @@ -179,7 +177,7 @@ adb_reverse(const char *serial, const char *device_socket_name, return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd)); } -process_t +sc_pid adb_reverse_remove(const char *serial, const char *device_socket_name) { char remote[108 + 14 + 1]; // localabstract:NAME snprintf(remote, sizeof(remote), "localabstract:%s", device_socket_name); @@ -187,66 +185,65 @@ adb_reverse_remove(const char *serial, const char *device_socket_name) { return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd)); } -process_t +sc_pid adb_push(const char *serial, const char *local, const char *remote) { #ifdef __WINDOWS__ // Windows will parse the string, so the paths must be quoted // (see sys/win/command.c) local = strquote(local); if (!local) { - return PROCESS_NONE; + return SC_PROCESS_NONE; } remote = strquote(remote); if (!remote) { free((void *) local); - return PROCESS_NONE; + return SC_PROCESS_NONE; } #endif const char *const adb_cmd[] = {"push", local, remote}; - process_t proc = adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd)); + sc_pid pid = adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd)); #ifdef __WINDOWS__ free((void *) remote); free((void *) local); #endif - return proc; + return pid; } -process_t +sc_pid adb_install(const char *serial, const char *local) { #ifdef __WINDOWS__ // Windows will parse the string, so the local name must be quoted // (see sys/win/command.c) local = strquote(local); if (!local) { - return PROCESS_NONE; + return SC_PROCESS_NONE; } #endif const char *const adb_cmd[] = {"install", "-r", local}; - process_t proc = adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd)); + sc_pid pid = adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd)); #ifdef __WINDOWS__ free((void *) local); #endif - return proc; + return pid; } static ssize_t adb_execute_for_output(const char *serial, const char *const adb_cmd[], size_t adb_cmd_len, char *buf, size_t buf_len, const char *name) { - pipe_t pipe_stdout; - process_t proc = adb_execute_redirect(serial, adb_cmd, adb_cmd_len, NULL, - &pipe_stdout, NULL); + sc_pipe pout; + sc_pid pid = adb_execute_p(serial, adb_cmd, adb_cmd_len, NULL, &pout, NULL); - ssize_t r = read_pipe_all(pipe_stdout, buf, buf_len); - close_pipe(pipe_stdout); + ssize_t r = sc_pipe_read_all(pout, buf, buf_len); + sc_pipe_close(pout); - if (!process_check_success(proc, name, true)) { + if (!sc_process_check_success(pid, name, true)) { return -1; } diff --git a/app/src/adb.h b/app/src/adb.h index 34182fd3..085b3e6b 100644 --- a/app/src/adb.h +++ b/app/src/adb.h @@ -8,32 +8,31 @@ #include "util/process.h" -process_t +sc_pid adb_execute(const char *serial, const char *const adb_cmd[], size_t len); -process_t -adb_execute_redirect(const char *serial, const char *const adb_cmd[], - size_t len, pipe_t *pipe_stdin, pipe_t *pipe_stdout, - pipe_t *pipe_stderr); +sc_pid +adb_execute_p(const char *serial, const char *const adb_cmd[], + size_t len, sc_pipe *pin, sc_pipe *pout, sc_pipe *perr); -process_t +sc_pid adb_forward(const char *serial, uint16_t local_port, const char *device_socket_name); -process_t +sc_pid adb_forward_remove(const char *serial, uint16_t local_port); -process_t +sc_pid adb_reverse(const char *serial, const char *device_socket_name, uint16_t local_port); -process_t +sc_pid adb_reverse_remove(const char *serial, const char *device_socket_name); -process_t +sc_pid adb_push(const char *serial, const char *local, const char *remote); -process_t +sc_pid adb_install(const char *serial, const char *local); // Return the result of "adb get-serialno". diff --git a/app/src/file_handler.c b/app/src/file_handler.c index 27fe6fa3..fe0ab857 100644 --- a/app/src/file_handler.c +++ b/app/src/file_handler.c @@ -46,7 +46,7 @@ file_handler_init(struct file_handler *file_handler, const char *serial, file_handler->initialized = false; file_handler->stopped = false; - file_handler->current_process = PROCESS_NONE; + file_handler->current_process = SC_PROCESS_NONE; file_handler->push_target = push_target ? push_target : DEFAULT_PUSH_TARGET; @@ -65,12 +65,12 @@ file_handler_destroy(struct file_handler *file_handler) { } } -static process_t +static sc_pid install_apk(const char *serial, const char *file) { return adb_install(serial, file); } -static process_t +static sc_pid push_file(const char *serial, const char *file, const char *push_target) { return adb_push(serial, file, push_target); } @@ -109,7 +109,7 @@ run_file_handler(void *data) { for (;;) { sc_mutex_lock(&file_handler->mutex); - file_handler->current_process = PROCESS_NONE; + file_handler->current_process = SC_PROCESS_NONE; while (!file_handler->stopped && cbuf_is_empty(&file_handler->queue)) { sc_cond_wait(&file_handler->event_cond, &file_handler->mutex); } @@ -123,26 +123,26 @@ run_file_handler(void *data) { assert(non_empty); (void) non_empty; - process_t process; + sc_pid pid; if (req.action == ACTION_INSTALL_APK) { LOGI("Installing %s...", req.file); - process = install_apk(file_handler->serial, req.file); + pid = install_apk(file_handler->serial, req.file); } else { LOGI("Pushing %s...", req.file); - process = push_file(file_handler->serial, req.file, - file_handler->push_target); + pid = push_file(file_handler->serial, req.file, + file_handler->push_target); } - file_handler->current_process = process; + file_handler->current_process = pid; sc_mutex_unlock(&file_handler->mutex); if (req.action == ACTION_INSTALL_APK) { - if (process_check_success(process, "adb install", false)) { + if (sc_process_check_success(pid, "adb install", false)) { LOGI("%s successfully installed", req.file); } else { LOGE("Failed to install %s", req.file); } } else { - if (process_check_success(process, "adb push", false)) { + if (sc_process_check_success(pid, "adb push", false)) { LOGI("%s successfully pushed to %s", req.file, file_handler->push_target); } else { @@ -152,11 +152,11 @@ run_file_handler(void *data) { } sc_mutex_lock(&file_handler->mutex); - // Close the process (it is necessary already terminated) + // Close the process (it is necessarily already terminated) // Execute this call with mutex locked to avoid race conditions with // file_handler_stop() - process_close(file_handler->current_process); - file_handler->current_process = PROCESS_NONE; + sc_process_close(file_handler->current_process); + file_handler->current_process = SC_PROCESS_NONE; sc_mutex_unlock(&file_handler->mutex); file_handler_request_destroy(&req); @@ -183,8 +183,8 @@ file_handler_stop(struct file_handler *file_handler) { sc_mutex_lock(&file_handler->mutex); file_handler->stopped = true; sc_cond_signal(&file_handler->event_cond); - if (file_handler->current_process != PROCESS_NONE) { - if (!process_terminate(file_handler->current_process)) { + if (file_handler->current_process != SC_PROCESS_NONE) { + if (!sc_process_terminate(file_handler->current_process)) { LOGW("Could not terminate push/install process"); } } diff --git a/app/src/file_handler.h b/app/src/file_handler.h index fe1d1804..e2067533 100644 --- a/app/src/file_handler.h +++ b/app/src/file_handler.h @@ -29,7 +29,7 @@ struct file_handler { sc_cond event_cond; bool stopped; bool initialized; - process_t current_process; + sc_pid current_process; struct file_handler_request_queue queue; }; diff --git a/app/src/server.c b/app/src/server.c index 25d786c4..326d0e79 100644 --- a/app/src/server.c +++ b/app/src/server.c @@ -73,33 +73,33 @@ push_server(const char *serial) { free(server_path); return false; } - process_t process = adb_push(serial, server_path, DEVICE_SERVER_PATH); + sc_pid pid = adb_push(serial, server_path, DEVICE_SERVER_PATH); free(server_path); - return process_check_success(process, "adb push", true); + return sc_process_check_success(pid, "adb push", true); } static bool enable_tunnel_reverse(const char *serial, uint16_t local_port) { - process_t process = adb_reverse(serial, SOCKET_NAME, local_port); - return process_check_success(process, "adb reverse", true); + sc_pid pid = adb_reverse(serial, SOCKET_NAME, local_port); + return sc_process_check_success(pid, "adb reverse", true); } static bool disable_tunnel_reverse(const char *serial) { - process_t process = adb_reverse_remove(serial, SOCKET_NAME); - return process_check_success(process, "adb reverse --remove", true); + sc_pid pid = adb_reverse_remove(serial, SOCKET_NAME); + return sc_process_check_success(pid, "adb reverse --remove", true); } static bool enable_tunnel_forward(const char *serial, uint16_t local_port) { - process_t process = adb_forward(serial, local_port, SOCKET_NAME); - return process_check_success(process, "adb forward", true); + sc_pid pid = adb_forward(serial, local_port, SOCKET_NAME); + return sc_process_check_success(pid, "adb forward", true); } static bool disable_tunnel_forward(const char *serial, uint16_t local_port) { - process_t process = adb_forward_remove(serial, local_port); - return process_check_success(process, "adb forward --remove", true); + sc_pid pid = adb_forward_remove(serial, local_port); + return sc_process_check_success(pid, "adb forward --remove", true); } static bool @@ -228,7 +228,7 @@ log_level_to_server_string(enum sc_log_level level) { } } -static process_t +static sc_pid execute_server(struct server *server, const struct server_params *params) { char max_size_string[6]; char bit_rate_string[11]; @@ -327,7 +327,7 @@ connect_to_server(uint16_t port, uint32_t attempts, uint32_t delay) { bool server_init(struct server *server) { server->serial = NULL; - server->process = PROCESS_NONE; + server->process = SC_PROCESS_NONE; bool ok = sc_mutex_init(&server->mutex); if (!ok) { @@ -357,7 +357,7 @@ server_init(struct server *server) { static int run_wait_server(void *data) { struct server *server = data; - process_wait(server->process, false); // ignore exit code + sc_process_wait(server->process, false); // ignore exit code sc_mutex_lock(&server->mutex); server->process_terminated = true; @@ -396,7 +396,7 @@ server_start(struct server *server, const struct server_params *params) { // server will connect to our server socket server->process = execute_server(server, params); - if (server->process == PROCESS_NONE) { + if (server->process == SC_PROCESS_NONE) { goto error; } @@ -409,8 +409,8 @@ server_start(struct server *server, const struct server_params *params) { bool ok = sc_thread_create(&server->wait_server_thread, run_wait_server, "wait-server", server); if (!ok) { - process_terminate(server->process); - process_wait(server->process, true); // ignore exit code + sc_process_terminate(server->process); + sc_process_wait(server->process, true); // ignore exit code goto error; } @@ -508,7 +508,7 @@ server_stop(struct server *server) { } } - assert(server->process != PROCESS_NONE); + assert(server->process != SC_PROCESS_NONE); if (server->tunnel_enabled) { // ignore failure @@ -533,11 +533,11 @@ server_stop(struct server *server) { // The process is terminated, but not reaped (closed) yet, so its PID // is still valid. LOGW("Killing the server..."); - process_terminate(server->process); + sc_process_terminate(server->process); } sc_thread_join(&server->wait_server_thread, NULL); - process_close(server->process); + sc_process_close(server->process); } void diff --git a/app/src/server.h b/app/src/server.h index 242b0525..18721cf7 100644 --- a/app/src/server.h +++ b/app/src/server.h @@ -22,7 +22,7 @@ struct server_info { struct server { char *serial; - process_t process; + sc_pid process; sc_thread wait_server_thread; sc_mutex mutex; diff --git a/app/src/sys/unix/process.c b/app/src/sys/unix/process.c index ef5d9d79..5f4a9890 100644 --- a/app/src/sys/unix/process.c +++ b/app/src/sys/unix/process.c @@ -10,9 +10,9 @@ #include "util/log.h" -enum process_result -process_execute_redirect(const char *const argv[], pid_t *pid, int *pipe_stdin, - int *pipe_stdout, int *pipe_stderr) { +enum sc_process_result +sc_process_execute_p(const char *const argv[], sc_pid *pid, + int *pin, int *pout, int *perr) { int in[2]; int out[2]; int err[2]; @@ -20,44 +20,44 @@ process_execute_redirect(const char *const argv[], pid_t *pid, int *pipe_stdin, if (pipe(internal) == -1) { perror("pipe"); - return PROCESS_ERROR_GENERIC; + return SC_PROCESS_ERROR_GENERIC; } - if (pipe_stdin) { + if (pin) { if (pipe(in) == -1) { perror("pipe"); close(internal[0]); close(internal[1]); - return PROCESS_ERROR_GENERIC; + return SC_PROCESS_ERROR_GENERIC; } } - if (pipe_stdout) { + if (pout) { if (pipe(out) == -1) { perror("pipe"); // clean up - if (pipe_stdin) { + if (pin) { close(in[0]); close(in[1]); } close(internal[0]); close(internal[1]); - return PROCESS_ERROR_GENERIC; + return SC_PROCESS_ERROR_GENERIC; } } - if (pipe_stderr) { + if (perr) { if (pipe(err) == -1) { perror("pipe"); // clean up - if (pipe_stdout) { + if (pout) { close(out[0]); close(out[1]); } - if (pipe_stdin) { + if (pin) { close(in[0]); close(in[1]); } close(internal[0]); close(internal[1]); - return PROCESS_ERROR_GENERIC; + return SC_PROCESS_ERROR_GENERIC; } } @@ -65,39 +65,39 @@ process_execute_redirect(const char *const argv[], pid_t *pid, int *pipe_stdin, if (*pid == -1) { perror("fork"); // clean up - if (pipe_stderr) { + if (perr) { close(err[0]); close(err[1]); } - if (pipe_stdout) { + if (pout) { close(out[0]); close(out[1]); } - if (pipe_stdin) { + if (pin) { close(in[0]); close(in[1]); } close(internal[0]); close(internal[1]); - return PROCESS_ERROR_GENERIC; + return SC_PROCESS_ERROR_GENERIC; } if (*pid == 0) { - if (pipe_stdin) { + if (pin) { if (in[0] != STDIN_FILENO) { dup2(in[0], STDIN_FILENO); close(in[0]); } close(in[1]); } - if (pipe_stdout) { + if (pout) { if (out[1] != STDOUT_FILENO) { dup2(out[1], STDOUT_FILENO); close(out[1]); } close(out[0]); } - if (pipe_stderr) { + if (perr) { if (err[1] != STDERR_FILENO) { dup2(err[1], STDERR_FILENO); close(err[1]); @@ -105,15 +105,15 @@ process_execute_redirect(const char *const argv[], pid_t *pid, int *pipe_stdin, close(err[0]); } close(internal[0]); - enum process_result err; + enum sc_process_result err; if (fcntl(internal[1], F_SETFD, FD_CLOEXEC) == 0) { execvp(argv[0], (char *const *) argv); perror("exec"); - err = errno == ENOENT ? PROCESS_ERROR_MISSING_BINARY - : PROCESS_ERROR_GENERIC; + err = errno == ENOENT ? SC_PROCESS_ERROR_MISSING_BINARY + : SC_PROCESS_ERROR_GENERIC; } else { perror("fcntl"); - err = PROCESS_ERROR_GENERIC; + err = SC_PROCESS_ERROR_GENERIC; } // send err to the parent if (write(internal[1], &err, sizeof(err)) == -1) { @@ -128,25 +128,25 @@ process_execute_redirect(const char *const argv[], pid_t *pid, int *pipe_stdin, close(internal[1]); - enum process_result res = PROCESS_SUCCESS; + enum sc_process_result res = SC_PROCESS_SUCCESS; // wait for EOF or receive err from child if (read(internal[0], &res, sizeof(res)) == -1) { perror("read"); - res = PROCESS_ERROR_GENERIC; + res = SC_PROCESS_ERROR_GENERIC; } close(internal[0]); - if (pipe_stdin) { + if (pin) { close(in[0]); - *pipe_stdin = in[1]; + *pin = in[1]; } - if (pipe_stdout) { - *pipe_stdout = out[0]; + if (pout) { + *pout = out[0]; close(out[1]); } - if (pipe_stderr) { - *pipe_stderr = err[0]; + if (perr) { + *perr = err[0]; close(err[1]); } @@ -154,7 +154,7 @@ process_execute_redirect(const char *const argv[], pid_t *pid, int *pipe_stdin, } bool -process_terminate(pid_t pid) { +sc_process_terminate(pid_t pid) { if (pid <= 0) { LOGC("Requested to kill %d, this is an error. Please report the bug.\n", (int) pid); @@ -163,8 +163,8 @@ process_terminate(pid_t pid) { return kill(pid, SIGKILL) != -1; } -exit_code_t -process_wait(pid_t pid, bool close) { +sc_exit_code +sc_process_wait(pid_t pid, bool close) { int code; int options = WEXITED; if (!close) { @@ -175,7 +175,7 @@ process_wait(pid_t pid, bool close) { int r = waitid(P_PID, pid, &info, options); if (r == -1 || info.si_code != CLD_EXITED) { // could not wait, or exited unexpectedly, probably by a signal - code = NO_EXIT_CODE; + code = SC_EXIT_CODE_NONE; } else { code = info.si_status; } @@ -183,17 +183,17 @@ process_wait(pid_t pid, bool close) { } void -process_close(pid_t pid) { - process_wait(pid, true); // ignore exit code +sc_process_close(pid_t pid) { + sc_process_wait(pid, true); // ignore exit code } ssize_t -read_pipe(int pipe, char *data, size_t len) { +sc_pipe_read(int pipe, char *data, size_t len) { return read(pipe, data, len); } void -close_pipe(int pipe) { +sc_pipe_close(int pipe) { if (close(pipe)) { perror("close pipe"); } diff --git a/app/src/sys/win/process.c b/app/src/sys/win/process.c index 257427f3..971806d6 100644 --- a/app/src/sys/win/process.c +++ b/app/src/sys/win/process.c @@ -15,17 +15,16 @@ build_cmd(char *cmd, size_t len, const char *const argv[]) { // (don't handle escaping nor quotes) size_t ret = xstrjoin(cmd, argv, ' ', len); if (ret >= len) { - LOGE("Command too long (%" PRIsizet " chars)", len - 1); + LOGE("Command too long (%" SC_PRIsizet " chars)", len - 1); return false; } return true; } -enum process_result -process_execute_redirect(const char *const argv[], HANDLE *handle, - HANDLE *pipe_stdin, HANDLE *pipe_stdout, - HANDLE *pipe_stderr) { - enum process_result ret = PROCESS_ERROR_GENERIC; +enum sc_process_result +sc_process_execute_p(const char *const argv[], HANDLE *handle, + HANDLE *pin, HANDLE *pout, HANDLE *perr) { + enum sc_process_result ret = SC_PROCESS_ERROR_GENERIC; SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES); @@ -35,32 +34,32 @@ process_execute_redirect(const char *const argv[], HANDLE *handle, HANDLE stdin_read_handle; HANDLE stdout_write_handle; HANDLE stderr_write_handle; - if (pipe_stdin) { - if (!CreatePipe(&stdin_read_handle, pipe_stdin, &sa, 0)) { + if (pin) { + if (!CreatePipe(&stdin_read_handle, pin, &sa, 0)) { perror("pipe"); - return PROCESS_ERROR_GENERIC; + return SC_PROCESS_ERROR_GENERIC; } - if (!SetHandleInformation(*pipe_stdin, HANDLE_FLAG_INHERIT, 0)) { + if (!SetHandleInformation(*pin, HANDLE_FLAG_INHERIT, 0)) { LOGE("SetHandleInformation stdin failed"); goto error_close_stdin; } } - if (pipe_stdout) { - if (!CreatePipe(pipe_stdout, &stdout_write_handle, &sa, 0)) { + if (pout) { + if (!CreatePipe(pout, &stdout_write_handle, &sa, 0)) { perror("pipe"); goto error_close_stdin; } - if (!SetHandleInformation(*pipe_stdout, HANDLE_FLAG_INHERIT, 0)) { + if (!SetHandleInformation(*pout, HANDLE_FLAG_INHERIT, 0)) { LOGE("SetHandleInformation stdout failed"); goto error_close_stdout; } } - if (pipe_stderr) { - if (!CreatePipe(pipe_stderr, &stderr_write_handle, &sa, 0)) { + if (perr) { + if (!CreatePipe(perr, &stderr_write_handle, &sa, 0)) { perror("pipe"); goto error_close_stdout; } - if (!SetHandleInformation(*pipe_stderr, HANDLE_FLAG_INHERIT, 0)) { + if (!SetHandleInformation(*perr, HANDLE_FLAG_INHERIT, 0)) { LOGE("SetHandleInformation stderr failed"); goto error_close_stderr; } @@ -70,15 +69,15 @@ process_execute_redirect(const char *const argv[], HANDLE *handle, PROCESS_INFORMATION pi; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); - if (pipe_stdin || pipe_stdout || pipe_stderr) { + if (pin || pout || perr) { si.dwFlags = STARTF_USESTDHANDLES; - if (pipe_stdin) { + if (pin) { si.hStdInput = stdin_read_handle; } - if (pipe_stdout) { + if (pout) { si.hStdOutput = stdout_write_handle; } - if (pipe_stderr) { + if (perr) { si.hStdError = stderr_write_handle; } } @@ -102,40 +101,40 @@ process_execute_redirect(const char *const argv[], HANDLE *handle, *handle = NULL; if (GetLastError() == ERROR_FILE_NOT_FOUND) { - ret = PROCESS_ERROR_MISSING_BINARY; + ret = SC_PROCESS_ERROR_MISSING_BINARY; } goto error_close_stderr; } // These handles are used by the child process, close them for this process - if (pipe_stdin) { + if (pin) { CloseHandle(stdin_read_handle); } - if (pipe_stdout) { + if (pout) { CloseHandle(stdout_write_handle); } - if (pipe_stderr) { + if (perr) { CloseHandle(stderr_write_handle); } free(wide); *handle = pi.hProcess; - return PROCESS_SUCCESS; + return SC_PROCESS_SUCCESS; error_close_stderr: - if (pipe_stderr) { - CloseHandle(*pipe_stderr); + if (perr) { + CloseHandle(*perr); CloseHandle(stderr_write_handle); } error_close_stdout: - if (pipe_stdout) { - CloseHandle(*pipe_stdout); + if (pout) { + CloseHandle(*pout); CloseHandle(stdout_write_handle); } error_close_stdin: - if (pipe_stdin) { - CloseHandle(*pipe_stdin); + if (pin) { + CloseHandle(*pin); CloseHandle(stdin_read_handle); } @@ -143,17 +142,17 @@ error_close_stdin: } bool -process_terminate(HANDLE handle) { +sc_process_terminate(HANDLE handle) { return TerminateProcess(handle, 1); } -exit_code_t -process_wait(HANDLE handle, bool close) { +sc_exit_code +sc_process_wait(HANDLE handle, bool close) { DWORD code; if (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0 || !GetExitCodeProcess(handle, &code)) { // could not wait or retrieve the exit code - code = NO_EXIT_CODE; // max value, it's unsigned + code = SC_EXIT_CODE_NONE; } if (close) { CloseHandle(handle); @@ -162,14 +161,14 @@ process_wait(HANDLE handle, bool close) { } void -process_close(HANDLE handle) { +sc_process_close(HANDLE handle) { bool closed = CloseHandle(handle); assert(closed); (void) closed; } ssize_t -read_pipe(HANDLE pipe, char *data, size_t len) { +sc_read_pipe(HANDLE pipe, char *data, size_t len) { DWORD r; if (!ReadFile(pipe, data, len, &r, NULL)) { return -1; @@ -178,7 +177,7 @@ read_pipe(HANDLE pipe, char *data, size_t len) { } void -close_pipe(HANDLE pipe) { +sc_close_pipe(HANDLE pipe) { if (!CloseHandle(pipe)) { LOGW("Cannot close pipe"); } diff --git a/app/src/util/process.c b/app/src/util/process.c index dcb715e6..6743438e 100644 --- a/app/src/util/process.c +++ b/app/src/util/process.c @@ -3,21 +3,22 @@ #include #include "log.h" -enum process_result -process_execute(const char *const argv[], process_t *pid) { - return process_execute_redirect(argv, pid, NULL, NULL, NULL); +enum sc_process_result +sc_process_execute(const char *const argv[], sc_pid *pid) { + return sc_process_execute_p(argv, pid, NULL, NULL, NULL); } bool -process_check_success(process_t proc, const char *name, bool close) { - if (proc == PROCESS_NONE) { +sc_process_check_success(sc_pid pid, const char *name, bool close) { + if (pid == SC_PROCESS_NONE) { LOGE("Could not execute \"%s\"", name); return false; } - exit_code_t exit_code = process_wait(proc, close); + sc_exit_code exit_code = sc_process_wait(pid, close); if (exit_code) { - if (exit_code != NO_EXIT_CODE) { - LOGE("\"%s\" returned with value %" PRIexitcode, name, exit_code); + if (exit_code != SC_EXIT_CODE_NONE) { + LOGE("\"%s\" returned with value %" SC_PRIexitcode, name, + exit_code); } else { LOGE("\"%s\" exited unexpectedly", name); } @@ -27,10 +28,10 @@ process_check_success(process_t proc, const char *name, bool close) { } ssize_t -read_pipe_all(pipe_t pipe, char *data, size_t len) { +sc_pipe_read_all(sc_pipe pipe, char *data, size_t len) { size_t copied = 0; while (len > 0) { - ssize_t r = read_pipe(pipe, data, len); + ssize_t r = sc_pipe_read(pipe, data, len); if (r <= 0) { return copied ? (ssize_t) copied : r; } diff --git a/app/src/util/process.h b/app/src/util/process.h index 08a70657..b4980b43 100644 --- a/app/src/util/process.h +++ b/app/src/util/process.h @@ -10,71 +10,100 @@ // not needed here, but winsock2.h must never be included AFTER windows.h # include # include -# define PRIexitcode "lu" +# define SC_PRIexitcode "lu" // -# define PRIsizet "Iu" -# define PROCESS_NONE NULL -# define NO_EXIT_CODE -1u // max value as unsigned - typedef HANDLE process_t; - typedef DWORD exit_code_t; - typedef HANDLE pipe_t; +# define SC_PRIsizet "Iu" +# define SC_PROCESS_NONE NULL +# define SC_EXIT_CODE_NONE -1u // max value as unsigned + typedef HANDLE sc_pid; + typedef DWORD sc_exit_code; + typedef HANDLE sc_pipe; #else # include -# define PRIsizet "zu" -# define PRIexitcode "d" -# define PROCESS_NONE -1 -# define NO_EXIT_CODE -1 - typedef pid_t process_t; - typedef int exit_code_t; - typedef int pipe_t; +# define SC_PRIsizet "zu" +# define SC_PRIexitcode "d" +# define SC_PROCESS_NONE -1 +# define SC_EXIT_CODE_NONE -1 + typedef pid_t sc_pid; + typedef int sc_exit_code; + typedef int sc_pipe; #endif -enum process_result { - PROCESS_SUCCESS, - PROCESS_ERROR_GENERIC, - PROCESS_ERROR_MISSING_BINARY, +enum sc_process_result { + SC_PROCESS_SUCCESS, + SC_PROCESS_ERROR_GENERIC, + SC_PROCESS_ERROR_MISSING_BINARY, }; -// execute the command and write the result to the output parameter "process" -enum process_result -process_execute(const char *const argv[], process_t *process); +/** + * Execute the command and write the process id to `pid` + */ +enum sc_process_result +sc_process_execute(const char *const argv[], sc_pid *pid); -enum process_result -process_execute_redirect(const char *const argv[], process_t *process, - pipe_t *pipe_stdin, pipe_t *pipe_stdout, - pipe_t *pipe_stderr); +/** + * Execute the command and write the process id to `pid` + * + * If not NULL, provide a pipe for stdin (`pin`), stdout (`pout`) and stderr + * (`perr`). + */ +enum sc_process_result +sc_process_execute_p(const char *const argv[], sc_pid *pid, + sc_pipe *pin, sc_pipe *pout, sc_pipe *perr); -// kill the process +/** + * Kill the process + */ bool -process_terminate(process_t pid); +sc_process_terminate(sc_pid pid); -// wait and close the process (like waitpid()) -// the "close" flag indicates if the process must be "closed" (reaped) -// (passing false is equivalent to enable WNOWAIT in waitid()) -exit_code_t -process_wait(process_t pid, bool close); +/** + * Wait and close the process (similar to waitpid()) + * + * The `close` flag indicates if the process must be _closed_ (reaped) (passing + * false is equivalent to enable WNOWAIT in waitid()). + */ +sc_exit_code +sc_process_wait(sc_pid pid, bool close); -// close the process -// -// Semantically, process_wait(close) = process_wait(noclose) + process_close +/** + * Close (reap) the process + * + * Semantically: + * sc_process_wait(close) = sc_process_wait(noclose) + sc_process_close() + */ void -process_close(process_t pid); +sc_process_close(sc_pid pid); -// convenience function to wait for a successful process execution -// automatically log process errors with the provided process name +/** + * Convenience function to wait for a successful process execution + * + * Automatically log process errors with the provided process name. + */ bool -process_check_success(process_t proc, const char *name, bool close); +sc_process_check_success(sc_pid pid, const char *name, bool close); +/** + * Read from the pipe + * + * Same semantic as read(). + */ ssize_t -read_pipe(pipe_t pipe, char *data, size_t len); +sc_pipe_read(sc_pipe pipe, char *data, size_t len); +/** + * Read exactly `len` chars from a pipe (unless EOF) + */ ssize_t -read_pipe_all(pipe_t pipe, char *data, size_t len); +sc_pipe_read_all(sc_pipe pipe, char *data, size_t len); +/** + * Close the pipe + */ void -close_pipe(pipe_t pipe); +sc_pipe_close(sc_pipe pipe); #endif