command.c 2.6 KB
Newer Older
R
Romain Vimont 已提交
1
#include "command.h"
R
Romain Vimont 已提交
2

R
Romain Vimont 已提交
3 4
#include <sys/stat.h>

5
#include "config.h"
R
Romain Vimont 已提交
6 7
#include "util/log.h"
#include "util/str_util.h"
R
Romain Vimont 已提交
8

R
Romain Vimont 已提交
9 10
static int
build_cmd(char *cmd, size_t len, const char *const argv[]) {
R
Romain Vimont 已提交
11 12 13 14 15 16 17 18 19 20 21 22
    // Windows command-line parsing is WTF:
    // <http://daviddeley.com/autohotkey/parameters/parameters.htm#WINPASS>
    // only make it work for this very specific program
    // (don't handle escaping nor quotes)
    size_t ret = xstrjoin(cmd, argv, ' ', len);
    if (ret >= len) {
        LOGE("Command too long (%" PRIsizet " chars)", len - 1);
        return -1;
    }
    return 0;
}

R
Romain Vimont 已提交
23
enum process_result
24
cmd_execute(const char *const argv[], HANDLE *handle) {
25
    STARTUPINFOW si;
R
Romain Vimont 已提交
26 27 28 29 30
    PROCESS_INFORMATION pi;
    memset(&si, 0, sizeof(si));
    si.cb = sizeof(si);

    char cmd[256];
R
Romain Vimont 已提交
31
    if (build_cmd(cmd, sizeof(cmd), argv)) {
Y
yuchenlin 已提交
32
        *handle = NULL;
33
        return PROCESS_ERROR_GENERIC;
R
Romain Vimont 已提交
34 35
    }

36 37
    wchar_t *wide = utf8_to_wide_char(cmd);
    if (!wide) {
R
Romain Vimont 已提交
38
        LOGC("Could not allocate wide char string");
39 40 41
        return PROCESS_ERROR_GENERIC;
    }

42
    if (!CreateProcessW(NULL, wide, NULL, NULL, FALSE, 0, NULL, NULL, &si,
R
Romain Vimont 已提交
43
                        &pi)) {
44
        SDL_free(wide);
Y
yuchenlin 已提交
45
        *handle = NULL;
46 47 48
        if (GetLastError() == ERROR_FILE_NOT_FOUND) {
            return PROCESS_ERROR_MISSING_BINARY;
        }
49
        return PROCESS_ERROR_GENERIC;
R
Romain Vimont 已提交
50 51
    }

52
    SDL_free(wide);
Y
yuchenlin 已提交
53
    *handle = pi.hProcess;
54
    return PROCESS_SUCCESS;
R
Romain Vimont 已提交
55 56
}

57
bool
R
Romain Vimont 已提交
58
cmd_terminate(HANDLE handle) {
59
    return TerminateProcess(handle, 1);
R
Romain Vimont 已提交
60 61
}

62
bool
R
Romain Vimont 已提交
63
cmd_simple_wait(HANDLE handle, DWORD *exit_code) {
R
Romain Vimont 已提交
64
    DWORD code;
R
Romain Vimont 已提交
65 66
    if (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0
            || !GetExitCodeProcess(handle, &code)) {
R
Romain Vimont 已提交
67
        // could not wait or retrieve the exit code
R
Romain Vimont 已提交
68 69 70 71 72
        code = -1; // max value, it's unsigned
    }
    if (exit_code) {
        *exit_code = code;
    }
73
    CloseHandle(handle);
R
Romain Vimont 已提交
74 75
    return !code;
}
R
Romain Vimont 已提交
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90

char *
get_executable_path(void) {
    HMODULE hModule = GetModuleHandleW(NULL);
    if (!hModule) {
        return NULL;
    }
    WCHAR buf[MAX_PATH + 1]; // +1 for the null byte
    int len = GetModuleFileNameW(hModule, buf, MAX_PATH);
    if (!len) {
        return NULL;
    }
    buf[len] = '\0';
    return utf8_from_wide_char(buf);
}
Y
Yu-Chen Lin 已提交
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

bool
is_regular_file(const char *path) {
    wchar_t *wide_path = utf8_to_wide_char(path);
    if (!wide_path) {
        LOGC("Could not allocate wide char string");
        return false;
    }

    struct _stat path_stat;
    int r = _wstat(wide_path, &path_stat);
    SDL_free(wide_path);

    if (r) {
        perror("stat");
        return false;
    }
    return S_ISREG(path_stat.st_mode);
}