Improve process API
Prefix symbols and constants names and improve documentation.
This commit is contained in:
parent
7e93abcf6d
commit
aa011832c1
10 changed files with 240 additions and 215 deletions
|
@ -81,7 +81,7 @@ show_adb_installation_msg() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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
|
#define MAX_COMMAND_STRING_LEN 1024
|
||||||
char *buf = malloc(MAX_COMMAND_STRING_LEN);
|
char *buf = malloc(MAX_COMMAND_STRING_LEN);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
|
@ -90,18 +90,18 @@ show_adb_err_msg(enum process_result err, const char *const argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case PROCESS_ERROR_GENERIC:
|
case SC_PROCESS_ERROR_GENERIC:
|
||||||
argv_to_string(argv, buf, MAX_COMMAND_STRING_LEN);
|
argv_to_string(argv, buf, MAX_COMMAND_STRING_LEN);
|
||||||
LOGE("Failed to execute: %s", buf);
|
LOGE("Failed to execute: %s", buf);
|
||||||
break;
|
break;
|
||||||
case PROCESS_ERROR_MISSING_BINARY:
|
case SC_PROCESS_ERROR_MISSING_BINARY:
|
||||||
argv_to_string(argv, buf, MAX_COMMAND_STRING_LEN);
|
argv_to_string(argv, buf, MAX_COMMAND_STRING_LEN);
|
||||||
LOGE("Command not found: %s", buf);
|
LOGE("Command not found: %s", buf);
|
||||||
LOGE("(make 'adb' accessible from your PATH or define its full"
|
LOGE("(make 'adb' accessible from your PATH or define its full"
|
||||||
"path in the ADB environment variable)");
|
"path in the ADB environment variable)");
|
||||||
show_adb_installation_msg();
|
show_adb_installation_msg();
|
||||||
break;
|
break;
|
||||||
case PROCESS_SUCCESS:
|
case SC_PROCESS_SUCCESS:
|
||||||
// do nothing
|
// do nothing
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -109,16 +109,15 @@ show_adb_err_msg(enum process_result err, const char *const argv[]) {
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
process_t
|
sc_pid
|
||||||
adb_execute_redirect(const char *serial, const char *const adb_cmd[],
|
adb_execute_p(const char *serial, const char *const adb_cmd[],
|
||||||
size_t len, pipe_t *pipe_stdin, pipe_t *pipe_stdout,
|
size_t len, sc_pipe *pin, sc_pipe *pout, sc_pipe *perr) {
|
||||||
pipe_t *pipe_stderr) {
|
|
||||||
int i;
|
int i;
|
||||||
process_t process;
|
sc_pid pid;
|
||||||
|
|
||||||
const char **argv = malloc((len + 4) * sizeof(*argv));
|
const char **argv = malloc((len + 4) * sizeof(*argv));
|
||||||
if (!argv) {
|
if (!argv) {
|
||||||
return PROCESS_NONE;
|
return SC_PROCESS_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
argv[0] = get_adb_command();
|
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 *));
|
memcpy(&argv[i], adb_cmd, len * sizeof(const char *));
|
||||||
argv[len + i] = NULL;
|
argv[len + i] = NULL;
|
||||||
enum process_result r =
|
enum sc_process_result r =
|
||||||
process_execute_redirect(argv, &process, pipe_stdin, pipe_stdout,
|
sc_process_execute_p(argv, &pid, pin, pout, perr);
|
||||||
pipe_stderr);
|
if (r != SC_PROCESS_SUCCESS) {
|
||||||
if (r != PROCESS_SUCCESS) {
|
|
||||||
show_adb_err_msg(r, argv);
|
show_adb_err_msg(r, argv);
|
||||||
process = PROCESS_NONE;
|
pid = SC_PROCESS_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(argv);
|
free(argv);
|
||||||
return process;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
process_t
|
sc_pid
|
||||||
adb_execute(const char *serial, const char *const adb_cmd[], size_t len) {
|
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,
|
adb_forward(const char *serial, uint16_t local_port,
|
||||||
const char *device_socket_name) {
|
const char *device_socket_name) {
|
||||||
char local[4 + 5 + 1]; // tcp:PORT
|
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));
|
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
process_t
|
sc_pid
|
||||||
adb_forward_remove(const char *serial, uint16_t local_port) {
|
adb_forward_remove(const char *serial, uint16_t local_port) {
|
||||||
char local[4 + 5 + 1]; // tcp:PORT
|
char local[4 + 5 + 1]; // tcp:PORT
|
||||||
sprintf(local, "tcp:%" PRIu16, local_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));
|
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
process_t
|
sc_pid
|
||||||
adb_reverse(const char *serial, const char *device_socket_name,
|
adb_reverse(const char *serial, const char *device_socket_name,
|
||||||
uint16_t local_port) {
|
uint16_t local_port) {
|
||||||
char local[4 + 5 + 1]; // tcp: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));
|
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) {
|
adb_reverse_remove(const char *serial, const char *device_socket_name) {
|
||||||
char remote[108 + 14 + 1]; // localabstract:NAME
|
char remote[108 + 14 + 1]; // localabstract:NAME
|
||||||
snprintf(remote, sizeof(remote), "localabstract:%s", device_socket_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));
|
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) {
|
adb_push(const char *serial, const char *local, const char *remote) {
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
// Windows will parse the string, so the paths must be quoted
|
// Windows will parse the string, so the paths must be quoted
|
||||||
// (see sys/win/command.c)
|
// (see sys/win/command.c)
|
||||||
local = strquote(local);
|
local = strquote(local);
|
||||||
if (!local) {
|
if (!local) {
|
||||||
return PROCESS_NONE;
|
return SC_PROCESS_NONE;
|
||||||
}
|
}
|
||||||
remote = strquote(remote);
|
remote = strquote(remote);
|
||||||
if (!remote) {
|
if (!remote) {
|
||||||
free((void *) local);
|
free((void *) local);
|
||||||
return PROCESS_NONE;
|
return SC_PROCESS_NONE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char *const adb_cmd[] = {"push", local, remote};
|
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__
|
#ifdef __WINDOWS__
|
||||||
free((void *) remote);
|
free((void *) remote);
|
||||||
free((void *) local);
|
free((void *) local);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return proc;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
process_t
|
sc_pid
|
||||||
adb_install(const char *serial, const char *local) {
|
adb_install(const char *serial, const char *local) {
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
// Windows will parse the string, so the local name must be quoted
|
// Windows will parse the string, so the local name must be quoted
|
||||||
// (see sys/win/command.c)
|
// (see sys/win/command.c)
|
||||||
local = strquote(local);
|
local = strquote(local);
|
||||||
if (!local) {
|
if (!local) {
|
||||||
return PROCESS_NONE;
|
return SC_PROCESS_NONE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char *const adb_cmd[] = {"install", "-r", local};
|
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__
|
#ifdef __WINDOWS__
|
||||||
free((void *) local);
|
free((void *) local);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return proc;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
adb_execute_for_output(const char *serial, const char *const adb_cmd[],
|
adb_execute_for_output(const char *serial, const char *const adb_cmd[],
|
||||||
size_t adb_cmd_len, char *buf, size_t buf_len,
|
size_t adb_cmd_len, char *buf, size_t buf_len,
|
||||||
const char *name) {
|
const char *name) {
|
||||||
pipe_t pipe_stdout;
|
sc_pipe pout;
|
||||||
process_t proc = adb_execute_redirect(serial, adb_cmd, adb_cmd_len, NULL,
|
sc_pid pid = adb_execute_p(serial, adb_cmd, adb_cmd_len, NULL, &pout, NULL);
|
||||||
&pipe_stdout, NULL);
|
|
||||||
|
|
||||||
ssize_t r = read_pipe_all(pipe_stdout, buf, buf_len);
|
ssize_t r = sc_pipe_read_all(pout, buf, buf_len);
|
||||||
close_pipe(pipe_stdout);
|
sc_pipe_close(pout);
|
||||||
|
|
||||||
if (!process_check_success(proc, name, true)) {
|
if (!sc_process_check_success(pid, name, true)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,32 +8,31 @@
|
||||||
|
|
||||||
#include "util/process.h"
|
#include "util/process.h"
|
||||||
|
|
||||||
process_t
|
sc_pid
|
||||||
adb_execute(const char *serial, const char *const adb_cmd[], size_t len);
|
adb_execute(const char *serial, const char *const adb_cmd[], size_t len);
|
||||||
|
|
||||||
process_t
|
sc_pid
|
||||||
adb_execute_redirect(const char *serial, const char *const adb_cmd[],
|
adb_execute_p(const char *serial, const char *const adb_cmd[],
|
||||||
size_t len, pipe_t *pipe_stdin, pipe_t *pipe_stdout,
|
size_t len, sc_pipe *pin, sc_pipe *pout, sc_pipe *perr);
|
||||||
pipe_t *pipe_stderr);
|
|
||||||
|
|
||||||
process_t
|
sc_pid
|
||||||
adb_forward(const char *serial, uint16_t local_port,
|
adb_forward(const char *serial, uint16_t local_port,
|
||||||
const char *device_socket_name);
|
const char *device_socket_name);
|
||||||
|
|
||||||
process_t
|
sc_pid
|
||||||
adb_forward_remove(const char *serial, uint16_t local_port);
|
adb_forward_remove(const char *serial, uint16_t local_port);
|
||||||
|
|
||||||
process_t
|
sc_pid
|
||||||
adb_reverse(const char *serial, const char *device_socket_name,
|
adb_reverse(const char *serial, const char *device_socket_name,
|
||||||
uint16_t local_port);
|
uint16_t local_port);
|
||||||
|
|
||||||
process_t
|
sc_pid
|
||||||
adb_reverse_remove(const char *serial, const char *device_socket_name);
|
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);
|
adb_push(const char *serial, const char *local, const char *remote);
|
||||||
|
|
||||||
process_t
|
sc_pid
|
||||||
adb_install(const char *serial, const char *local);
|
adb_install(const char *serial, const char *local);
|
||||||
|
|
||||||
// Return the result of "adb get-serialno".
|
// Return the result of "adb get-serialno".
|
||||||
|
|
|
@ -46,7 +46,7 @@ file_handler_init(struct file_handler *file_handler, const char *serial,
|
||||||
file_handler->initialized = false;
|
file_handler->initialized = false;
|
||||||
|
|
||||||
file_handler->stopped = 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;
|
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) {
|
install_apk(const char *serial, const char *file) {
|
||||||
return adb_install(serial, file);
|
return adb_install(serial, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
static process_t
|
static sc_pid
|
||||||
push_file(const char *serial, const char *file, const char *push_target) {
|
push_file(const char *serial, const char *file, const char *push_target) {
|
||||||
return adb_push(serial, file, push_target);
|
return adb_push(serial, file, push_target);
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ run_file_handler(void *data) {
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
sc_mutex_lock(&file_handler->mutex);
|
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)) {
|
while (!file_handler->stopped && cbuf_is_empty(&file_handler->queue)) {
|
||||||
sc_cond_wait(&file_handler->event_cond, &file_handler->mutex);
|
sc_cond_wait(&file_handler->event_cond, &file_handler->mutex);
|
||||||
}
|
}
|
||||||
|
@ -123,26 +123,26 @@ run_file_handler(void *data) {
|
||||||
assert(non_empty);
|
assert(non_empty);
|
||||||
(void) non_empty;
|
(void) non_empty;
|
||||||
|
|
||||||
process_t process;
|
sc_pid pid;
|
||||||
if (req.action == ACTION_INSTALL_APK) {
|
if (req.action == ACTION_INSTALL_APK) {
|
||||||
LOGI("Installing %s...", req.file);
|
LOGI("Installing %s...", req.file);
|
||||||
process = install_apk(file_handler->serial, req.file);
|
pid = install_apk(file_handler->serial, req.file);
|
||||||
} else {
|
} else {
|
||||||
LOGI("Pushing %s...", req.file);
|
LOGI("Pushing %s...", req.file);
|
||||||
process = push_file(file_handler->serial, req.file,
|
pid = push_file(file_handler->serial, req.file,
|
||||||
file_handler->push_target);
|
file_handler->push_target);
|
||||||
}
|
}
|
||||||
file_handler->current_process = process;
|
file_handler->current_process = pid;
|
||||||
sc_mutex_unlock(&file_handler->mutex);
|
sc_mutex_unlock(&file_handler->mutex);
|
||||||
|
|
||||||
if (req.action == ACTION_INSTALL_APK) {
|
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);
|
LOGI("%s successfully installed", req.file);
|
||||||
} else {
|
} else {
|
||||||
LOGE("Failed to install %s", req.file);
|
LOGE("Failed to install %s", req.file);
|
||||||
}
|
}
|
||||||
} else {
|
} 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,
|
LOGI("%s successfully pushed to %s", req.file,
|
||||||
file_handler->push_target);
|
file_handler->push_target);
|
||||||
} else {
|
} else {
|
||||||
|
@ -152,11 +152,11 @@ run_file_handler(void *data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_mutex_lock(&file_handler->mutex);
|
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
|
// Execute this call with mutex locked to avoid race conditions with
|
||||||
// file_handler_stop()
|
// file_handler_stop()
|
||||||
process_close(file_handler->current_process);
|
sc_process_close(file_handler->current_process);
|
||||||
file_handler->current_process = PROCESS_NONE;
|
file_handler->current_process = SC_PROCESS_NONE;
|
||||||
sc_mutex_unlock(&file_handler->mutex);
|
sc_mutex_unlock(&file_handler->mutex);
|
||||||
|
|
||||||
file_handler_request_destroy(&req);
|
file_handler_request_destroy(&req);
|
||||||
|
@ -183,8 +183,8 @@ file_handler_stop(struct file_handler *file_handler) {
|
||||||
sc_mutex_lock(&file_handler->mutex);
|
sc_mutex_lock(&file_handler->mutex);
|
||||||
file_handler->stopped = true;
|
file_handler->stopped = true;
|
||||||
sc_cond_signal(&file_handler->event_cond);
|
sc_cond_signal(&file_handler->event_cond);
|
||||||
if (file_handler->current_process != PROCESS_NONE) {
|
if (file_handler->current_process != SC_PROCESS_NONE) {
|
||||||
if (!process_terminate(file_handler->current_process)) {
|
if (!sc_process_terminate(file_handler->current_process)) {
|
||||||
LOGW("Could not terminate push/install process");
|
LOGW("Could not terminate push/install process");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ struct file_handler {
|
||||||
sc_cond event_cond;
|
sc_cond event_cond;
|
||||||
bool stopped;
|
bool stopped;
|
||||||
bool initialized;
|
bool initialized;
|
||||||
process_t current_process;
|
sc_pid current_process;
|
||||||
struct file_handler_request_queue queue;
|
struct file_handler_request_queue queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -73,33 +73,33 @@ push_server(const char *serial) {
|
||||||
free(server_path);
|
free(server_path);
|
||||||
return false;
|
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);
|
free(server_path);
|
||||||
return process_check_success(process, "adb push", true);
|
return sc_process_check_success(pid, "adb push", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
enable_tunnel_reverse(const char *serial, uint16_t local_port) {
|
enable_tunnel_reverse(const char *serial, uint16_t local_port) {
|
||||||
process_t process = adb_reverse(serial, SOCKET_NAME, local_port);
|
sc_pid pid = adb_reverse(serial, SOCKET_NAME, local_port);
|
||||||
return process_check_success(process, "adb reverse", true);
|
return sc_process_check_success(pid, "adb reverse", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
disable_tunnel_reverse(const char *serial) {
|
disable_tunnel_reverse(const char *serial) {
|
||||||
process_t process = adb_reverse_remove(serial, SOCKET_NAME);
|
sc_pid pid = adb_reverse_remove(serial, SOCKET_NAME);
|
||||||
return process_check_success(process, "adb reverse --remove", true);
|
return sc_process_check_success(pid, "adb reverse --remove", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
enable_tunnel_forward(const char *serial, uint16_t local_port) {
|
enable_tunnel_forward(const char *serial, uint16_t local_port) {
|
||||||
process_t process = adb_forward(serial, local_port, SOCKET_NAME);
|
sc_pid pid = adb_forward(serial, local_port, SOCKET_NAME);
|
||||||
return process_check_success(process, "adb forward", true);
|
return sc_process_check_success(pid, "adb forward", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
disable_tunnel_forward(const char *serial, uint16_t local_port) {
|
disable_tunnel_forward(const char *serial, uint16_t local_port) {
|
||||||
process_t process = adb_forward_remove(serial, local_port);
|
sc_pid pid = adb_forward_remove(serial, local_port);
|
||||||
return process_check_success(process, "adb forward --remove", true);
|
return sc_process_check_success(pid, "adb forward --remove", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
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) {
|
execute_server(struct server *server, const struct server_params *params) {
|
||||||
char max_size_string[6];
|
char max_size_string[6];
|
||||||
char bit_rate_string[11];
|
char bit_rate_string[11];
|
||||||
|
@ -327,7 +327,7 @@ connect_to_server(uint16_t port, uint32_t attempts, uint32_t delay) {
|
||||||
bool
|
bool
|
||||||
server_init(struct server *server) {
|
server_init(struct server *server) {
|
||||||
server->serial = NULL;
|
server->serial = NULL;
|
||||||
server->process = PROCESS_NONE;
|
server->process = SC_PROCESS_NONE;
|
||||||
|
|
||||||
bool ok = sc_mutex_init(&server->mutex);
|
bool ok = sc_mutex_init(&server->mutex);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
|
@ -357,7 +357,7 @@ server_init(struct server *server) {
|
||||||
static int
|
static int
|
||||||
run_wait_server(void *data) {
|
run_wait_server(void *data) {
|
||||||
struct server *server = 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);
|
sc_mutex_lock(&server->mutex);
|
||||||
server->process_terminated = true;
|
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 will connect to our server socket
|
||||||
server->process = execute_server(server, params);
|
server->process = execute_server(server, params);
|
||||||
if (server->process == PROCESS_NONE) {
|
if (server->process == SC_PROCESS_NONE) {
|
||||||
goto error;
|
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,
|
bool ok = sc_thread_create(&server->wait_server_thread, run_wait_server,
|
||||||
"wait-server", server);
|
"wait-server", server);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
process_terminate(server->process);
|
sc_process_terminate(server->process);
|
||||||
process_wait(server->process, true); // ignore exit code
|
sc_process_wait(server->process, true); // ignore exit code
|
||||||
goto error;
|
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) {
|
if (server->tunnel_enabled) {
|
||||||
// ignore failure
|
// ignore failure
|
||||||
|
@ -533,11 +533,11 @@ server_stop(struct server *server) {
|
||||||
// The process is terminated, but not reaped (closed) yet, so its PID
|
// The process is terminated, but not reaped (closed) yet, so its PID
|
||||||
// is still valid.
|
// is still valid.
|
||||||
LOGW("Killing the server...");
|
LOGW("Killing the server...");
|
||||||
process_terminate(server->process);
|
sc_process_terminate(server->process);
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_thread_join(&server->wait_server_thread, NULL);
|
sc_thread_join(&server->wait_server_thread, NULL);
|
||||||
process_close(server->process);
|
sc_process_close(server->process);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -22,7 +22,7 @@ struct server_info {
|
||||||
|
|
||||||
struct server {
|
struct server {
|
||||||
char *serial;
|
char *serial;
|
||||||
process_t process;
|
sc_pid process;
|
||||||
sc_thread wait_server_thread;
|
sc_thread wait_server_thread;
|
||||||
|
|
||||||
sc_mutex mutex;
|
sc_mutex mutex;
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
|
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
|
|
||||||
enum process_result
|
enum sc_process_result
|
||||||
process_execute_redirect(const char *const argv[], pid_t *pid, int *pipe_stdin,
|
sc_process_execute_p(const char *const argv[], sc_pid *pid,
|
||||||
int *pipe_stdout, int *pipe_stderr) {
|
int *pin, int *pout, int *perr) {
|
||||||
int in[2];
|
int in[2];
|
||||||
int out[2];
|
int out[2];
|
||||||
int err[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) {
|
if (pipe(internal) == -1) {
|
||||||
perror("pipe");
|
perror("pipe");
|
||||||
return PROCESS_ERROR_GENERIC;
|
return SC_PROCESS_ERROR_GENERIC;
|
||||||
}
|
}
|
||||||
if (pipe_stdin) {
|
if (pin) {
|
||||||
if (pipe(in) == -1) {
|
if (pipe(in) == -1) {
|
||||||
perror("pipe");
|
perror("pipe");
|
||||||
close(internal[0]);
|
close(internal[0]);
|
||||||
close(internal[1]);
|
close(internal[1]);
|
||||||
return PROCESS_ERROR_GENERIC;
|
return SC_PROCESS_ERROR_GENERIC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pipe_stdout) {
|
if (pout) {
|
||||||
if (pipe(out) == -1) {
|
if (pipe(out) == -1) {
|
||||||
perror("pipe");
|
perror("pipe");
|
||||||
// clean up
|
// clean up
|
||||||
if (pipe_stdin) {
|
if (pin) {
|
||||||
close(in[0]);
|
close(in[0]);
|
||||||
close(in[1]);
|
close(in[1]);
|
||||||
}
|
}
|
||||||
close(internal[0]);
|
close(internal[0]);
|
||||||
close(internal[1]);
|
close(internal[1]);
|
||||||
return PROCESS_ERROR_GENERIC;
|
return SC_PROCESS_ERROR_GENERIC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pipe_stderr) {
|
if (perr) {
|
||||||
if (pipe(err) == -1) {
|
if (pipe(err) == -1) {
|
||||||
perror("pipe");
|
perror("pipe");
|
||||||
// clean up
|
// clean up
|
||||||
if (pipe_stdout) {
|
if (pout) {
|
||||||
close(out[0]);
|
close(out[0]);
|
||||||
close(out[1]);
|
close(out[1]);
|
||||||
}
|
}
|
||||||
if (pipe_stdin) {
|
if (pin) {
|
||||||
close(in[0]);
|
close(in[0]);
|
||||||
close(in[1]);
|
close(in[1]);
|
||||||
}
|
}
|
||||||
close(internal[0]);
|
close(internal[0]);
|
||||||
close(internal[1]);
|
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) {
|
if (*pid == -1) {
|
||||||
perror("fork");
|
perror("fork");
|
||||||
// clean up
|
// clean up
|
||||||
if (pipe_stderr) {
|
if (perr) {
|
||||||
close(err[0]);
|
close(err[0]);
|
||||||
close(err[1]);
|
close(err[1]);
|
||||||
}
|
}
|
||||||
if (pipe_stdout) {
|
if (pout) {
|
||||||
close(out[0]);
|
close(out[0]);
|
||||||
close(out[1]);
|
close(out[1]);
|
||||||
}
|
}
|
||||||
if (pipe_stdin) {
|
if (pin) {
|
||||||
close(in[0]);
|
close(in[0]);
|
||||||
close(in[1]);
|
close(in[1]);
|
||||||
}
|
}
|
||||||
close(internal[0]);
|
close(internal[0]);
|
||||||
close(internal[1]);
|
close(internal[1]);
|
||||||
return PROCESS_ERROR_GENERIC;
|
return SC_PROCESS_ERROR_GENERIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*pid == 0) {
|
if (*pid == 0) {
|
||||||
if (pipe_stdin) {
|
if (pin) {
|
||||||
if (in[0] != STDIN_FILENO) {
|
if (in[0] != STDIN_FILENO) {
|
||||||
dup2(in[0], STDIN_FILENO);
|
dup2(in[0], STDIN_FILENO);
|
||||||
close(in[0]);
|
close(in[0]);
|
||||||
}
|
}
|
||||||
close(in[1]);
|
close(in[1]);
|
||||||
}
|
}
|
||||||
if (pipe_stdout) {
|
if (pout) {
|
||||||
if (out[1] != STDOUT_FILENO) {
|
if (out[1] != STDOUT_FILENO) {
|
||||||
dup2(out[1], STDOUT_FILENO);
|
dup2(out[1], STDOUT_FILENO);
|
||||||
close(out[1]);
|
close(out[1]);
|
||||||
}
|
}
|
||||||
close(out[0]);
|
close(out[0]);
|
||||||
}
|
}
|
||||||
if (pipe_stderr) {
|
if (perr) {
|
||||||
if (err[1] != STDERR_FILENO) {
|
if (err[1] != STDERR_FILENO) {
|
||||||
dup2(err[1], STDERR_FILENO);
|
dup2(err[1], STDERR_FILENO);
|
||||||
close(err[1]);
|
close(err[1]);
|
||||||
|
@ -105,15 +105,15 @@ process_execute_redirect(const char *const argv[], pid_t *pid, int *pipe_stdin,
|
||||||
close(err[0]);
|
close(err[0]);
|
||||||
}
|
}
|
||||||
close(internal[0]);
|
close(internal[0]);
|
||||||
enum process_result err;
|
enum sc_process_result err;
|
||||||
if (fcntl(internal[1], F_SETFD, FD_CLOEXEC) == 0) {
|
if (fcntl(internal[1], F_SETFD, FD_CLOEXEC) == 0) {
|
||||||
execvp(argv[0], (char *const *) argv);
|
execvp(argv[0], (char *const *) argv);
|
||||||
perror("exec");
|
perror("exec");
|
||||||
err = errno == ENOENT ? PROCESS_ERROR_MISSING_BINARY
|
err = errno == ENOENT ? SC_PROCESS_ERROR_MISSING_BINARY
|
||||||
: PROCESS_ERROR_GENERIC;
|
: SC_PROCESS_ERROR_GENERIC;
|
||||||
} else {
|
} else {
|
||||||
perror("fcntl");
|
perror("fcntl");
|
||||||
err = PROCESS_ERROR_GENERIC;
|
err = SC_PROCESS_ERROR_GENERIC;
|
||||||
}
|
}
|
||||||
// send err to the parent
|
// send err to the parent
|
||||||
if (write(internal[1], &err, sizeof(err)) == -1) {
|
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]);
|
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
|
// wait for EOF or receive err from child
|
||||||
if (read(internal[0], &res, sizeof(res)) == -1) {
|
if (read(internal[0], &res, sizeof(res)) == -1) {
|
||||||
perror("read");
|
perror("read");
|
||||||
res = PROCESS_ERROR_GENERIC;
|
res = SC_PROCESS_ERROR_GENERIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(internal[0]);
|
close(internal[0]);
|
||||||
|
|
||||||
if (pipe_stdin) {
|
if (pin) {
|
||||||
close(in[0]);
|
close(in[0]);
|
||||||
*pipe_stdin = in[1];
|
*pin = in[1];
|
||||||
}
|
}
|
||||||
if (pipe_stdout) {
|
if (pout) {
|
||||||
*pipe_stdout = out[0];
|
*pout = out[0];
|
||||||
close(out[1]);
|
close(out[1]);
|
||||||
}
|
}
|
||||||
if (pipe_stderr) {
|
if (perr) {
|
||||||
*pipe_stderr = err[0];
|
*perr = err[0];
|
||||||
close(err[1]);
|
close(err[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ process_execute_redirect(const char *const argv[], pid_t *pid, int *pipe_stdin,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
process_terminate(pid_t pid) {
|
sc_process_terminate(pid_t pid) {
|
||||||
if (pid <= 0) {
|
if (pid <= 0) {
|
||||||
LOGC("Requested to kill %d, this is an error. Please report the bug.\n",
|
LOGC("Requested to kill %d, this is an error. Please report the bug.\n",
|
||||||
(int) pid);
|
(int) pid);
|
||||||
|
@ -163,8 +163,8 @@ process_terminate(pid_t pid) {
|
||||||
return kill(pid, SIGKILL) != -1;
|
return kill(pid, SIGKILL) != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_code_t
|
sc_exit_code
|
||||||
process_wait(pid_t pid, bool close) {
|
sc_process_wait(pid_t pid, bool close) {
|
||||||
int code;
|
int code;
|
||||||
int options = WEXITED;
|
int options = WEXITED;
|
||||||
if (!close) {
|
if (!close) {
|
||||||
|
@ -175,7 +175,7 @@ process_wait(pid_t pid, bool close) {
|
||||||
int r = waitid(P_PID, pid, &info, options);
|
int r = waitid(P_PID, pid, &info, options);
|
||||||
if (r == -1 || info.si_code != CLD_EXITED) {
|
if (r == -1 || info.si_code != CLD_EXITED) {
|
||||||
// could not wait, or exited unexpectedly, probably by a signal
|
// could not wait, or exited unexpectedly, probably by a signal
|
||||||
code = NO_EXIT_CODE;
|
code = SC_EXIT_CODE_NONE;
|
||||||
} else {
|
} else {
|
||||||
code = info.si_status;
|
code = info.si_status;
|
||||||
}
|
}
|
||||||
|
@ -183,17 +183,17 @@ process_wait(pid_t pid, bool close) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
process_close(pid_t pid) {
|
sc_process_close(pid_t pid) {
|
||||||
process_wait(pid, true); // ignore exit code
|
sc_process_wait(pid, true); // ignore exit code
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
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);
|
return read(pipe, data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
close_pipe(int pipe) {
|
sc_pipe_close(int pipe) {
|
||||||
if (close(pipe)) {
|
if (close(pipe)) {
|
||||||
perror("close pipe");
|
perror("close pipe");
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,17 +15,16 @@ build_cmd(char *cmd, size_t len, const char *const argv[]) {
|
||||||
// (don't handle escaping nor quotes)
|
// (don't handle escaping nor quotes)
|
||||||
size_t ret = xstrjoin(cmd, argv, ' ', len);
|
size_t ret = xstrjoin(cmd, argv, ' ', len);
|
||||||
if (ret >= len) {
|
if (ret >= len) {
|
||||||
LOGE("Command too long (%" PRIsizet " chars)", len - 1);
|
LOGE("Command too long (%" SC_PRIsizet " chars)", len - 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum process_result
|
enum sc_process_result
|
||||||
process_execute_redirect(const char *const argv[], HANDLE *handle,
|
sc_process_execute_p(const char *const argv[], HANDLE *handle,
|
||||||
HANDLE *pipe_stdin, HANDLE *pipe_stdout,
|
HANDLE *pin, HANDLE *pout, HANDLE *perr) {
|
||||||
HANDLE *pipe_stderr) {
|
enum sc_process_result ret = SC_PROCESS_ERROR_GENERIC;
|
||||||
enum process_result ret = PROCESS_ERROR_GENERIC;
|
|
||||||
|
|
||||||
SECURITY_ATTRIBUTES sa;
|
SECURITY_ATTRIBUTES sa;
|
||||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
|
@ -35,32 +34,32 @@ process_execute_redirect(const char *const argv[], HANDLE *handle,
|
||||||
HANDLE stdin_read_handle;
|
HANDLE stdin_read_handle;
|
||||||
HANDLE stdout_write_handle;
|
HANDLE stdout_write_handle;
|
||||||
HANDLE stderr_write_handle;
|
HANDLE stderr_write_handle;
|
||||||
if (pipe_stdin) {
|
if (pin) {
|
||||||
if (!CreatePipe(&stdin_read_handle, pipe_stdin, &sa, 0)) {
|
if (!CreatePipe(&stdin_read_handle, pin, &sa, 0)) {
|
||||||
perror("pipe");
|
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");
|
LOGE("SetHandleInformation stdin failed");
|
||||||
goto error_close_stdin;
|
goto error_close_stdin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pipe_stdout) {
|
if (pout) {
|
||||||
if (!CreatePipe(pipe_stdout, &stdout_write_handle, &sa, 0)) {
|
if (!CreatePipe(pout, &stdout_write_handle, &sa, 0)) {
|
||||||
perror("pipe");
|
perror("pipe");
|
||||||
goto error_close_stdin;
|
goto error_close_stdin;
|
||||||
}
|
}
|
||||||
if (!SetHandleInformation(*pipe_stdout, HANDLE_FLAG_INHERIT, 0)) {
|
if (!SetHandleInformation(*pout, HANDLE_FLAG_INHERIT, 0)) {
|
||||||
LOGE("SetHandleInformation stdout failed");
|
LOGE("SetHandleInformation stdout failed");
|
||||||
goto error_close_stdout;
|
goto error_close_stdout;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pipe_stderr) {
|
if (perr) {
|
||||||
if (!CreatePipe(pipe_stderr, &stderr_write_handle, &sa, 0)) {
|
if (!CreatePipe(perr, &stderr_write_handle, &sa, 0)) {
|
||||||
perror("pipe");
|
perror("pipe");
|
||||||
goto error_close_stdout;
|
goto error_close_stdout;
|
||||||
}
|
}
|
||||||
if (!SetHandleInformation(*pipe_stderr, HANDLE_FLAG_INHERIT, 0)) {
|
if (!SetHandleInformation(*perr, HANDLE_FLAG_INHERIT, 0)) {
|
||||||
LOGE("SetHandleInformation stderr failed");
|
LOGE("SetHandleInformation stderr failed");
|
||||||
goto error_close_stderr;
|
goto error_close_stderr;
|
||||||
}
|
}
|
||||||
|
@ -70,15 +69,15 @@ process_execute_redirect(const char *const argv[], HANDLE *handle,
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
memset(&si, 0, sizeof(si));
|
memset(&si, 0, sizeof(si));
|
||||||
si.cb = sizeof(si);
|
si.cb = sizeof(si);
|
||||||
if (pipe_stdin || pipe_stdout || pipe_stderr) {
|
if (pin || pout || perr) {
|
||||||
si.dwFlags = STARTF_USESTDHANDLES;
|
si.dwFlags = STARTF_USESTDHANDLES;
|
||||||
if (pipe_stdin) {
|
if (pin) {
|
||||||
si.hStdInput = stdin_read_handle;
|
si.hStdInput = stdin_read_handle;
|
||||||
}
|
}
|
||||||
if (pipe_stdout) {
|
if (pout) {
|
||||||
si.hStdOutput = stdout_write_handle;
|
si.hStdOutput = stdout_write_handle;
|
||||||
}
|
}
|
||||||
if (pipe_stderr) {
|
if (perr) {
|
||||||
si.hStdError = stderr_write_handle;
|
si.hStdError = stderr_write_handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,40 +101,40 @@ process_execute_redirect(const char *const argv[], HANDLE *handle,
|
||||||
*handle = NULL;
|
*handle = NULL;
|
||||||
|
|
||||||
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
|
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
|
||||||
ret = PROCESS_ERROR_MISSING_BINARY;
|
ret = SC_PROCESS_ERROR_MISSING_BINARY;
|
||||||
}
|
}
|
||||||
goto error_close_stderr;
|
goto error_close_stderr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// These handles are used by the child process, close them for this process
|
// These handles are used by the child process, close them for this process
|
||||||
if (pipe_stdin) {
|
if (pin) {
|
||||||
CloseHandle(stdin_read_handle);
|
CloseHandle(stdin_read_handle);
|
||||||
}
|
}
|
||||||
if (pipe_stdout) {
|
if (pout) {
|
||||||
CloseHandle(stdout_write_handle);
|
CloseHandle(stdout_write_handle);
|
||||||
}
|
}
|
||||||
if (pipe_stderr) {
|
if (perr) {
|
||||||
CloseHandle(stderr_write_handle);
|
CloseHandle(stderr_write_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(wide);
|
free(wide);
|
||||||
*handle = pi.hProcess;
|
*handle = pi.hProcess;
|
||||||
|
|
||||||
return PROCESS_SUCCESS;
|
return SC_PROCESS_SUCCESS;
|
||||||
|
|
||||||
error_close_stderr:
|
error_close_stderr:
|
||||||
if (pipe_stderr) {
|
if (perr) {
|
||||||
CloseHandle(*pipe_stderr);
|
CloseHandle(*perr);
|
||||||
CloseHandle(stderr_write_handle);
|
CloseHandle(stderr_write_handle);
|
||||||
}
|
}
|
||||||
error_close_stdout:
|
error_close_stdout:
|
||||||
if (pipe_stdout) {
|
if (pout) {
|
||||||
CloseHandle(*pipe_stdout);
|
CloseHandle(*pout);
|
||||||
CloseHandle(stdout_write_handle);
|
CloseHandle(stdout_write_handle);
|
||||||
}
|
}
|
||||||
error_close_stdin:
|
error_close_stdin:
|
||||||
if (pipe_stdin) {
|
if (pin) {
|
||||||
CloseHandle(*pipe_stdin);
|
CloseHandle(*pin);
|
||||||
CloseHandle(stdin_read_handle);
|
CloseHandle(stdin_read_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,17 +142,17 @@ error_close_stdin:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
process_terminate(HANDLE handle) {
|
sc_process_terminate(HANDLE handle) {
|
||||||
return TerminateProcess(handle, 1);
|
return TerminateProcess(handle, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_code_t
|
sc_exit_code
|
||||||
process_wait(HANDLE handle, bool close) {
|
sc_process_wait(HANDLE handle, bool close) {
|
||||||
DWORD code;
|
DWORD code;
|
||||||
if (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0
|
if (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0
|
||||||
|| !GetExitCodeProcess(handle, &code)) {
|
|| !GetExitCodeProcess(handle, &code)) {
|
||||||
// could not wait or retrieve the exit 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) {
|
if (close) {
|
||||||
CloseHandle(handle);
|
CloseHandle(handle);
|
||||||
|
@ -162,14 +161,14 @@ process_wait(HANDLE handle, bool close) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
process_close(HANDLE handle) {
|
sc_process_close(HANDLE handle) {
|
||||||
bool closed = CloseHandle(handle);
|
bool closed = CloseHandle(handle);
|
||||||
assert(closed);
|
assert(closed);
|
||||||
(void) closed;
|
(void) closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
read_pipe(HANDLE pipe, char *data, size_t len) {
|
sc_read_pipe(HANDLE pipe, char *data, size_t len) {
|
||||||
DWORD r;
|
DWORD r;
|
||||||
if (!ReadFile(pipe, data, len, &r, NULL)) {
|
if (!ReadFile(pipe, data, len, &r, NULL)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -178,7 +177,7 @@ read_pipe(HANDLE pipe, char *data, size_t len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
close_pipe(HANDLE pipe) {
|
sc_close_pipe(HANDLE pipe) {
|
||||||
if (!CloseHandle(pipe)) {
|
if (!CloseHandle(pipe)) {
|
||||||
LOGW("Cannot close pipe");
|
LOGW("Cannot close pipe");
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,21 +3,22 @@
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
enum process_result
|
enum sc_process_result
|
||||||
process_execute(const char *const argv[], process_t *pid) {
|
sc_process_execute(const char *const argv[], sc_pid *pid) {
|
||||||
return process_execute_redirect(argv, pid, NULL, NULL, NULL);
|
return sc_process_execute_p(argv, pid, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
process_check_success(process_t proc, const char *name, bool close) {
|
sc_process_check_success(sc_pid pid, const char *name, bool close) {
|
||||||
if (proc == PROCESS_NONE) {
|
if (pid == SC_PROCESS_NONE) {
|
||||||
LOGE("Could not execute \"%s\"", name);
|
LOGE("Could not execute \"%s\"", name);
|
||||||
return false;
|
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) {
|
||||||
if (exit_code != NO_EXIT_CODE) {
|
if (exit_code != SC_EXIT_CODE_NONE) {
|
||||||
LOGE("\"%s\" returned with value %" PRIexitcode, name, exit_code);
|
LOGE("\"%s\" returned with value %" SC_PRIexitcode, name,
|
||||||
|
exit_code);
|
||||||
} else {
|
} else {
|
||||||
LOGE("\"%s\" exited unexpectedly", name);
|
LOGE("\"%s\" exited unexpectedly", name);
|
||||||
}
|
}
|
||||||
|
@ -27,10 +28,10 @@ process_check_success(process_t proc, const char *name, bool close) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
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;
|
size_t copied = 0;
|
||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
ssize_t r = read_pipe(pipe, data, len);
|
ssize_t r = sc_pipe_read(pipe, data, len);
|
||||||
if (r <= 0) {
|
if (r <= 0) {
|
||||||
return copied ? (ssize_t) copied : r;
|
return copied ? (ssize_t) copied : r;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,71 +10,100 @@
|
||||||
// not needed here, but winsock2.h must never be included AFTER windows.h
|
// not needed here, but winsock2.h must never be included AFTER windows.h
|
||||||
# include <winsock2.h>
|
# include <winsock2.h>
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
# define PRIexitcode "lu"
|
# define SC_PRIexitcode "lu"
|
||||||
// <https://stackoverflow.com/a/44383330/1987178>
|
// <https://stackoverflow.com/a/44383330/1987178>
|
||||||
# define PRIsizet "Iu"
|
# define SC_PRIsizet "Iu"
|
||||||
# define PROCESS_NONE NULL
|
# define SC_PROCESS_NONE NULL
|
||||||
# define NO_EXIT_CODE -1u // max value as unsigned
|
# define SC_EXIT_CODE_NONE -1u // max value as unsigned
|
||||||
typedef HANDLE process_t;
|
typedef HANDLE sc_pid;
|
||||||
typedef DWORD exit_code_t;
|
typedef DWORD sc_exit_code;
|
||||||
typedef HANDLE pipe_t;
|
typedef HANDLE sc_pipe;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
# define PRIsizet "zu"
|
# define SC_PRIsizet "zu"
|
||||||
# define PRIexitcode "d"
|
# define SC_PRIexitcode "d"
|
||||||
# define PROCESS_NONE -1
|
# define SC_PROCESS_NONE -1
|
||||||
# define NO_EXIT_CODE -1
|
# define SC_EXIT_CODE_NONE -1
|
||||||
typedef pid_t process_t;
|
typedef pid_t sc_pid;
|
||||||
typedef int exit_code_t;
|
typedef int sc_exit_code;
|
||||||
typedef int pipe_t;
|
typedef int sc_pipe;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum process_result {
|
enum sc_process_result {
|
||||||
PROCESS_SUCCESS,
|
SC_PROCESS_SUCCESS,
|
||||||
PROCESS_ERROR_GENERIC,
|
SC_PROCESS_ERROR_GENERIC,
|
||||||
PROCESS_ERROR_MISSING_BINARY,
|
SC_PROCESS_ERROR_MISSING_BINARY,
|
||||||
};
|
};
|
||||||
|
|
||||||
// execute the command and write the result to the output parameter "process"
|
/**
|
||||||
enum process_result
|
* Execute the command and write the process id to `pid`
|
||||||
process_execute(const char *const argv[], process_t *process);
|
*/
|
||||||
|
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,
|
* Execute the command and write the process id to `pid`
|
||||||
pipe_t *pipe_stdin, pipe_t *pipe_stdout,
|
*
|
||||||
pipe_t *pipe_stderr);
|
* 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
|
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)
|
* Wait and close the process (similar to waitpid())
|
||||||
// (passing false is equivalent to enable WNOWAIT in waitid())
|
*
|
||||||
exit_code_t
|
* The `close` flag indicates if the process must be _closed_ (reaped) (passing
|
||||||
process_wait(process_t pid, bool close);
|
* false is equivalent to enable WNOWAIT in waitid()).
|
||||||
|
*/
|
||||||
|
sc_exit_code
|
||||||
|
sc_process_wait(sc_pid pid, bool close);
|
||||||
|
|
||||||
// close the process
|
/**
|
||||||
//
|
* Close (reap) the process
|
||||||
// Semantically, process_wait(close) = process_wait(noclose) + process_close
|
*
|
||||||
|
* Semantically:
|
||||||
|
* sc_process_wait(close) = sc_process_wait(noclose) + sc_process_close()
|
||||||
|
*/
|
||||||
void
|
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
|
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
|
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
|
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
|
void
|
||||||
close_pipe(pipe_t pipe);
|
sc_pipe_close(sc_pipe pipe);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue