Split command into process and adb

The process API provides the system-specific implementation, the adb API
uses it to expose adb commands.
This commit is contained in:
Romain Vimont 2021-01-03 14:55:15 +01:00
parent aa8b571389
commit 4bd9da4c93
12 changed files with 97 additions and 80 deletions

View file

@ -1,7 +1,7 @@
src = [ src = [
'src/main.c', 'src/main.c',
'src/adb.c',
'src/cli.c', 'src/cli.c',
'src/command.c',
'src/control_msg.c', 'src/control_msg.c',
'src/controller.c', 'src/controller.c',
'src/decoder.c', 'src/decoder.c',
@ -21,6 +21,7 @@ src = [
'src/tiny_xpm.c', 'src/tiny_xpm.c',
'src/video_buffer.c', 'src/video_buffer.c',
'src/util/net.c', 'src/util/net.c',
'src/util/process.c',
'src/util/str_util.c' 'src/util/str_util.c'
] ]
@ -76,10 +77,10 @@ endif
cc = meson.get_compiler('c') cc = meson.get_compiler('c')
if host_machine.system() == 'windows' if host_machine.system() == 'windows'
src += [ 'src/sys/win/command.c' ] src += [ 'src/sys/win/process.c' ]
dependencies += cc.find_library('ws2_32') dependencies += cc.find_library('ws2_32')
else else
src += [ 'src/sys/unix/command.c' ] src += [ 'src/sys/unix/process.c' ]
endif endif
conf = configuration_data() conf = configuration_data()

View file

@ -1,4 +1,4 @@
#include "command.h" #include "adb.h"
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
@ -70,7 +70,7 @@ show_adb_installation_msg() {
{"pacman", "pacman -S android-tools"}, {"pacman", "pacman -S android-tools"},
}; };
for (size_t i = 0; i < ARRAY_LEN(pkg_managers); ++i) { for (size_t i = 0; i < ARRAY_LEN(pkg_managers); ++i) {
if (cmd_search(pkg_managers[i].binary)) { if (search_executable(pkg_managers[i].binary)) {
LOGI("You may install 'adb' by \"%s\"", pkg_managers[i].command); LOGI("You may install 'adb' by \"%s\"", pkg_managers[i].command);
return; return;
} }
@ -118,7 +118,7 @@ adb_execute(const char *serial, const char *const adb_cmd[], size_t len) {
memcpy(&cmd[i], adb_cmd, len * sizeof(const char *)); memcpy(&cmd[i], adb_cmd, len * sizeof(const char *));
cmd[len + i] = NULL; cmd[len + i] = NULL;
enum process_result r = cmd_execute(cmd, &process); enum process_result r = process_execute(cmd, &process);
if (r != PROCESS_SUCCESS) { if (r != PROCESS_SUCCESS) {
show_adb_err_msg(r, cmd); show_adb_err_msg(r, cmd);
return PROCESS_NONE; return PROCESS_NONE;
@ -211,21 +211,3 @@ adb_install(const char *serial, const char *local) {
return proc; return proc;
} }
bool
process_check_success(process_t proc, const char *name) {
if (proc == PROCESS_NONE) {
LOGE("Could not execute \"%s\"", name);
return false;
}
exit_code_t exit_code;
if (!cmd_simple_wait(proc, &exit_code)) {
if (exit_code != NO_EXIT_CODE) {
LOGE("\"%s\" returned with value %" PRIexitcode, name, exit_code);
} else {
LOGE("\"%s\" exited unexpectedly", name);
}
return false;
}
return true;
}

34
app/src/adb.h Normal file
View file

@ -0,0 +1,34 @@
#ifndef SC_ADB_H
#define SC_ADB_H
#include <stdbool.h>
#include <inttypes.h>
#include "config.h"
#include "util/process.h"
process_t
adb_execute(const char *serial, const char *const adb_cmd[], size_t len);
process_t
adb_forward(const char *serial, uint16_t local_port,
const char *device_socket_name);
process_t
adb_forward_remove(const char *serial, uint16_t local_port);
process_t
adb_reverse(const char *serial, const char *device_socket_name,
uint16_t local_port);
process_t
adb_reverse_remove(const char *serial, const char *device_socket_name);
process_t
adb_push(const char *serial, const char *local, const char *remote);
process_t
adb_install(const char *serial, const char *local);
#endif

View file

@ -4,7 +4,7 @@
#include <string.h> #include <string.h>
#include "config.h" #include "config.h"
#include "command.h" #include "adb.h"
#include "util/lock.h" #include "util/lock.h"
#include "util/log.h" #include "util/log.h"
@ -176,10 +176,10 @@ file_handler_stop(struct file_handler *file_handler) {
file_handler->stopped = true; file_handler->stopped = true;
cond_signal(file_handler->event_cond); cond_signal(file_handler->event_cond);
if (file_handler->current_process != PROCESS_NONE) { if (file_handler->current_process != PROCESS_NONE) {
if (!cmd_terminate(file_handler->current_process)) { if (!process_terminate(file_handler->current_process)) {
LOGW("Could not terminate install process"); LOGW("Could not terminate install process");
} }
cmd_simple_wait(file_handler->current_process, NULL); process_simple_wait(file_handler->current_process, NULL);
file_handler->current_process = PROCESS_NONE; file_handler->current_process = PROCESS_NONE;
} }
mutex_unlock(file_handler->mutex); mutex_unlock(file_handler->mutex);

View file

@ -6,7 +6,7 @@
#include <SDL2/SDL_thread.h> #include <SDL2/SDL_thread.h>
#include "config.h" #include "config.h"
#include "command.h" #include "adb.h"
#include "util/cbuf.h" #include "util/cbuf.h"
typedef enum { typedef enum {

View file

@ -14,7 +14,6 @@
#endif #endif
#include "config.h" #include "config.h"
#include "command.h"
#include "common.h" #include "common.h"
#include "compat.h" #include "compat.h"
#include "controller.h" #include "controller.h"

View file

@ -10,7 +10,7 @@
#include <SDL2/SDL_platform.h> #include <SDL2/SDL_platform.h>
#include "config.h" #include "config.h"
#include "command.h" #include "adb.h"
#include "util/lock.h" #include "util/lock.h"
#include "util/log.h" #include "util/log.h"
#include "util/net.h" #include "util/net.h"
@ -392,7 +392,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;
cmd_simple_wait(server->process, NULL); // ignore exit code process_simple_wait(server->process, NULL); // ignore exit code
mutex_lock(server->mutex); mutex_lock(server->mutex);
server->process_terminated = true; server->process_terminated = true;
@ -447,8 +447,8 @@ server_start(struct server *server, const char *serial,
server->wait_server_thread = server->wait_server_thread =
SDL_CreateThread(run_wait_server, "wait-server", server); SDL_CreateThread(run_wait_server, "wait-server", server);
if (!server->wait_server_thread) { if (!server->wait_server_thread) {
cmd_terminate(server->process); process_terminate(server->process);
cmd_simple_wait(server->process, NULL); // ignore exit code process_simple_wait(server->process, NULL); // ignore exit code
goto error2; goto error2;
} }
@ -554,7 +554,7 @@ server_stop(struct server *server) {
// the process is already terminated, and the PID assigned to a new // the process is already terminated, and the PID assigned to a new
// process. // process.
LOGW("Killing the server..."); LOGW("Killing the server...");
cmd_terminate(server->process); process_terminate(server->process);
} }
SDL_WaitThread(server->wait_server_thread, NULL); SDL_WaitThread(server->wait_server_thread, NULL);

View file

@ -7,7 +7,7 @@
#include <SDL2/SDL_thread.h> #include <SDL2/SDL_thread.h>
#include "config.h" #include "config.h"
#include "command.h" #include "adb.h"
#include "common.h" #include "common.h"
#include "scrcpy.h" #include "scrcpy.h"
#include "util/log.h" #include "util/log.h"

View file

@ -9,7 +9,7 @@
# define _DARWIN_C_SOURCE // for strdup(), strtok_r(), memset_pattern4() # define _DARWIN_C_SOURCE // for strdup(), strtok_r(), memset_pattern4()
#endif #endif
#include "command.h" #include "util/process.h"
#include "config.h" #include "config.h"
@ -27,7 +27,7 @@
#include "util/log.h" #include "util/log.h"
bool bool
cmd_search(const char *file) { search_executable(const char *file) {
char *path = getenv("PATH"); char *path = getenv("PATH");
if (!path) if (!path)
return false; return false;
@ -63,7 +63,7 @@ cmd_search(const char *file) {
} }
enum process_result enum process_result
cmd_execute(const char *const argv[], pid_t *pid) { process_execute(const char *const argv[], pid_t *pid) {
int fd[2]; int fd[2];
if (pipe(fd) == -1) { if (pipe(fd) == -1) {
@ -125,7 +125,7 @@ end:
} }
bool bool
cmd_terminate(pid_t pid) { 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);
@ -135,7 +135,7 @@ cmd_terminate(pid_t pid) {
} }
bool bool
cmd_simple_wait(pid_t pid, int *exit_code) { process_simple_wait(pid_t pid, int *exit_code) {
int status; int status;
int code; int code;
if (waitpid(pid, &status, 0) == -1 || !WIFEXITED(status)) { if (waitpid(pid, &status, 0) == -1 || !WIFEXITED(status)) {

View file

@ -1,4 +1,4 @@
#include "command.h" #include "util/process.h"
#include <sys/stat.h> #include <sys/stat.h>
@ -21,7 +21,7 @@ build_cmd(char *cmd, size_t len, const char *const argv[]) {
} }
enum process_result enum process_result
cmd_execute(const char *const argv[], HANDLE *handle) { process_execute(const char *const argv[], HANDLE *handle) {
STARTUPINFOW si; STARTUPINFOW si;
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si)); memset(&si, 0, sizeof(si));
@ -55,12 +55,12 @@ cmd_execute(const char *const argv[], HANDLE *handle) {
} }
bool bool
cmd_terminate(HANDLE handle) { process_terminate(HANDLE handle) {
return TerminateProcess(handle, 1); return TerminateProcess(handle, 1);
} }
bool bool
cmd_simple_wait(HANDLE handle, DWORD *exit_code) { process_simple_wait(HANDLE handle, DWORD *exit_code) {
DWORD code; DWORD code;
if (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0 if (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0
|| !GetExitCodeProcess(handle, &code)) { || !GetExitCodeProcess(handle, &code)) {

21
app/src/util/process.c Normal file
View file

@ -0,0 +1,21 @@
#include "process.h"
#include "log.h"
bool
process_check_success(process_t proc, const char *name) {
if (proc == PROCESS_NONE) {
LOGE("Could not execute \"%s\"", name);
return false;
}
exit_code_t exit_code;
if (!process_simple_wait(proc, &exit_code)) {
if (exit_code != NO_EXIT_CODE) {
LOGE("\"%s\" returned with value %" PRIexitcode, name, exit_code);
} else {
LOGE("\"%s\" exited unexpectedly", name);
}
return false;
}
return true;
}

View file

@ -1,8 +1,9 @@
#ifndef COMMAND_H #ifndef SC_PROCESS_H
#define COMMAND_H #define SC_PROCESS_H
#include <stdbool.h> #include <stdbool.h>
#include <inttypes.h>
#include "config.h"
#ifdef _WIN32 #ifdef _WIN32
@ -31,56 +32,35 @@
#endif #endif
#include "config.h"
enum process_result { enum process_result {
PROCESS_SUCCESS, PROCESS_SUCCESS,
PROCESS_ERROR_GENERIC, PROCESS_ERROR_GENERIC,
PROCESS_ERROR_MISSING_BINARY, PROCESS_ERROR_MISSING_BINARY,
}; };
#ifndef __WINDOWS__ // execute the command and write the result to the output parameter "process"
bool
cmd_search(const char *file);
#endif
enum process_result enum process_result
cmd_execute(const char *const argv[], process_t *process); process_execute(const char *const argv[], process_t *process);
// kill the process
bool bool
cmd_terminate(process_t pid); process_terminate(process_t pid);
// wait and close the process
bool bool
cmd_simple_wait(process_t pid, exit_code_t *exit_code); process_simple_wait(process_t pid, exit_code_t *exit_code);
process_t
adb_execute(const char *serial, const char *const adb_cmd[], size_t len);
process_t
adb_forward(const char *serial, uint16_t local_port,
const char *device_socket_name);
process_t
adb_forward_remove(const char *serial, uint16_t local_port);
process_t
adb_reverse(const char *serial, const char *device_socket_name,
uint16_t local_port);
process_t
adb_reverse_remove(const char *serial, const char *device_socket_name);
process_t
adb_push(const char *serial, const char *local, const char *remote);
process_t
adb_install(const char *serial, const char *local);
// convenience function to wait for a successful process execution // convenience function to wait for a successful process execution
// automatically log process errors with the provided process name // automatically log process errors with the provided process name
bool bool
process_check_success(process_t proc, const char *name); process_check_success(process_t proc, const char *name);
#ifndef _WIN32
// only used to find package manager, not implemented for Windows
bool
search_executable(const char *file);
#endif
// return the absolute path of the executable (the scrcpy binary) // return the absolute path of the executable (the scrcpy binary)
// may be NULL on error; to be freed by SDL_free // may be NULL on error; to be freed by SDL_free
char * char *