From df1df2929646abd77955b80e3ded3574ac005179 Mon Sep 17 00:00:00 2001 From: Jan200101 Date: Thu, 27 May 2021 23:37:23 +0200 Subject: allow flags to exit prematurely, move defines, add no networking flag --- src/command.h | 55 +++++++++++++++++---------- src/common.c | 8 ++++ src/common.h | 53 +++----------------------- src/defines.h | 53 ++++++++++++++++++++++++++ src/dxvk.c | 3 +- src/lutris.c | 3 +- src/main.c | 6 +-- src/mock/CMakeLists.txt | 3 +- src/mock/libcurl.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++ src/mock/libcurl/libcurl.c | 93 --------------------------------------------- src/net.c | 6 +++ src/wine.c | 3 +- 12 files changed, 213 insertions(+), 168 deletions(-) create mode 100644 src/defines.h create mode 100644 src/mock/libcurl.c delete mode 100644 src/mock/libcurl/libcurl.c diff --git a/src/command.h b/src/command.h index 0a8f412..8fec1c7 100644 --- a/src/command.h +++ b/src/command.h @@ -41,33 +41,48 @@ #define COMMAND_GROUP(GROUP) \ int GROUP(int argc, char** argv) +#define COMMAND_GROUP_BODY_COMMANDS(GROUP) \ + for (unsigned long i = 0; i < ARRAY_LEN(GROUP##_commands); ++i) \ + if (!strcmp(GROUP##_commands[i].name, argv[1])) return GROUP##_commands[i].func(argc-1, argv+1); -/* - * the body is split up so we can construct our own group function for - * e.g. ARGV0 parsing - */ -#define COMMAND_GROUP_BODY(GROUP) \ - if (argc > 1) \ +#define COMMAND_GROUP_BODY_FLAGS(GROUP) \ + uint8_t found; \ + \ + for (int j = 1; j < argc; ++j) \ { \ - for (unsigned long i = 0; i < ARRAY_LEN(GROUP##_commands); ++i) \ - if (!strcmp(GROUP##_commands[i].name, argv[1])) return GROUP##_commands[i].func(argc-1, argv+1); \ + found = 0; \ + if (argv[j][0] != '-') continue; \ \ - for (int j = 1; j < argc; ++j) \ + for (unsigned long i = 0; i < ARRAY_LEN(GROUP##_flags); ++i) \ { \ - if (argv[j][0] != '-') continue; \ - \ - for (unsigned long i = 0; i < ARRAY_LEN(GROUP##_flags); ++i) \ + if ((GROUP##_flags[i].variant & ONE && argv[j][1] == GROUP##_flags[i].name[0]) || \ + (GROUP##_flags[i].variant & TWO && argv[j][1] == '-' \ + && !strcmp(GROUP##_flags[i].name, argv[j]+2))) \ { \ - if ((GROUP##_flags[i].variant & ONE && argv[j][1] == GROUP##_flags[i].name[0]) || \ - (GROUP##_flags[i].variant & TWO && argv[j][1] == '-' \ - && !strcmp(GROUP##_flags[i].name, argv[j]+2))) \ - { \ - return GROUP##_flags[i].func(0, NULL); \ - } \ + found = 1; \ + int retval = GROUP##_flags[i].func(0, NULL); \ + if (GROUP##_flags[i].returns) return retval; \ } \ } \ \ - fprintf(stderr, NAME ": '%s' is not a command or flag\n", argv[1]); \ + if (!found) \ + { \ + fprintf(stderr, NAME ": '%s' is not a flag\n", argv[j]); \ + return 0; \ + } \ + } + +/* + * the body is split up so we can construct our own group function for + * e.g. ARGV0 parsing + */ +#define COMMAND_GROUP_BODY(GROUP, FIRST, SECOND) \ + if (argc > 1) \ + { \ + COMMAND_GROUP_BODY_##FIRST(GROUP) \ + COMMAND_GROUP_BODY_##SECOND(GROUP) \ + \ + fprintf(stderr, NAME ": '%s' is not a command\n", argv[1]); \ return 0; \ } \ return GROUP##_help(argc-1, argv+1); @@ -84,7 +99,7 @@ #define COMMAND_GROUP_FUNC(GROUP) \ COMMAND_GROUP(GROUP) \ { \ - COMMAND_GROUP_BODY(GROUP) \ + COMMAND_GROUP_BODY(GROUP, FLAGS, COMMANDS) \ } \ diff --git a/src/common.c b/src/common.c index fdc30af..66a470b 100644 --- a/src/common.c +++ b/src/common.c @@ -9,6 +9,14 @@ #include "common.h" +uint8_t no_net = 0; + +int set_no_net(UNUSED int argc, UNUSED char** argv) +{ + no_net = 1; + return 0; +} + void print_help(const struct Command* commands, const size_t commands_size, const struct Flag* flags, size_t flags_size) { diff --git a/src/common.h b/src/common.h index 17b372c..21bd727 100644 --- a/src/common.h +++ b/src/common.h @@ -6,57 +6,11 @@ #include #include -#define ARRAY_LEN(arr) sizeof(arr) / sizeof(arr[0]) - -#define GITHUB_API "https://api.github.com" -#define LUTRIS_API "https://lutris.net/api" -#define WINE_API LUTRIS_API "/runners/wine" -#define DXVK_API GITHUB_API"/repos/lutris/dxvk/releases" -#define INSTALLER_API LUTRIS_API "/installers/" -#define GAME_API LUTRIS_API "/games" -#define GAME_SEARCH_API GAME_API "?search=%s" -#define GAME_INSTALLER_API GAME_API "/%s/installers" - - -#ifndef NAME -#warning "no name specified, setting it to \"polecat\"" -#define NAME "polecat" -#endif - -#ifndef VERSION -#warning "no version specified, setting it to \"0.0.0\"" -#define VERSION "0.0.0" -#endif - -#define USER_AGENT NAME "/" VERSION - -#define USAGE_STR "Usage: " NAME - -#ifdef DEBUG -#define UNREACHABLE printf("unreachable code reached\n" __FILE__ ":L%i\n", __LINE__); exit(0); -#else -#define UNREACHABLE -#endif - -#ifdef __GNUC__ -#define UNUSED __attribute__((__unused__)) -#else -#define UNUSED -#endif +#include "defines.h" #include -// since json-c 0.13 json_object_array_length returns a size_t -#if defined(JSON_C_MINOR_VERSION) && JSON_C_MINOR_VERSION >= 13 -#define JSON_LENGTH_TYPE size_t -#else -#define JSON_LENGTH_TYPE int -#endif - -#ifdef _WIN32 -#define mkdir(path, perm) mkdir(path) -#endif - +extern uint8_t no_net; struct MemoryStruct { uint8_t* memory; @@ -78,10 +32,13 @@ enum flag_variants { struct Flag { char* name; enum flag_variants variant; + uint8_t returns; int (*func)(int, char**); char* description; }; +int set_no_net(UNUSED int argc, UNUSED char** argv); + void print_help(const struct Command*, size_t, const struct Flag*, size_t); struct stat getStat(const char* path); diff --git a/src/defines.h b/src/defines.h new file mode 100644 index 0000000..82d5f05 --- /dev/null +++ b/src/defines.h @@ -0,0 +1,53 @@ +#ifndef DEFINES_H +#define DEFINES_H + +#define ARRAY_LEN(arr) sizeof(arr) / sizeof(arr[0]) + +#define GITHUB_API "https://api.github.com" +#define LUTRIS_API "https://lutris.net/api" +#define WINE_API LUTRIS_API "/runners/wine" +#define DXVK_API GITHUB_API"/repos/lutris/dxvk/releases" +#define INSTALLER_API LUTRIS_API "/installers/" +#define GAME_API LUTRIS_API "/games" +#define GAME_SEARCH_API GAME_API "?search=%s" +#define GAME_INSTALLER_API GAME_API "/%s/installers" + + +#ifndef NAME +#warning "no name specified, setting it to \"polecat\"" +#define NAME "polecat" +#endif + +#ifndef VERSION +#warning "no version specified, setting it to \"0.0.0\"" +#define VERSION "0.0.0" +#endif + +#define USER_AGENT NAME "/" VERSION + +#define USAGE_STR "Usage: " NAME + +#ifdef DEBUG +#define UNREACHABLE printf("unreachable code reached\n" __FILE__ ":L%i\n", __LINE__); exit(0); +#else +#define UNREACHABLE +#endif + +#ifdef __GNUC__ +#define UNUSED __attribute__((__unused__)) +#else +#define UNUSED +#endif + +// since json-c 0.13 json_object_array_length returns a size_t +#if defined(JSON_C_MINOR_VERSION) && JSON_C_MINOR_VERSION >= 13 +#define JSON_LENGTH_TYPE size_t +#else +#define JSON_LENGTH_TYPE int +#endif + +#ifdef _WIN32 +#define mkdir(path, perm) mkdir(path) +#endif + +#endif \ No newline at end of file diff --git a/src/dxvk.c b/src/dxvk.c index 1a24045..356d81d 100644 --- a/src/dxvk.c +++ b/src/dxvk.c @@ -20,7 +20,8 @@ static const struct Command dxvk_commands[] = { }; static const struct Flag dxvk_flags[] = { - { .name = "help", .variant = TWO, .func = dxvk_help, .description = "show this message"} + { .name = "help", .variant = TWO, .returns = 1, .func = dxvk_help, .description = "show this message"}, + { .name = "no-net", .variant = TWO, .returns = 0, .func = set_no_net, .description = "run commands without commitment"} }; COMMAND_GROUP_FUNC(dxvk) diff --git a/src/lutris.c b/src/lutris.c index b7c4da6..d885ae8 100644 --- a/src/lutris.c +++ b/src/lutris.c @@ -17,7 +17,8 @@ static const struct Command lutris_commands[] = { }; static const struct Flag lutris_flags[] = { - { .name = "help", .variant = TWO, .func = lutris_help, .description = "show this message"} + { .name = "help", .variant = TWO, .returns = 1, .func = lutris_help, .description = "show this message"}, + { .name = "no-net", .variant = TWO, .returns = 0, .func = set_no_net, .description = "run commands without commitment"} }; static char* getpwd() diff --git a/src/main.c b/src/main.c index d6dd008..689d2b4 100644 --- a/src/main.c +++ b/src/main.c @@ -25,8 +25,8 @@ static const struct Command main_commands[] = { }; static const struct Flag main_flags[] = { - { .name = "help", .variant = TWO, .func = main_help, .description = "show this message"}, - { .name = "version", .variant = BOTH, .func = main_version, .description = "prints the program version"} + { .name = "help", .variant = TWO, .returns = 1, .func = main_help, .description = "show this message"}, + { .name = "version", .variant = BOTH, .returns = 1, .func = main_version, .description = "prints the program version"} }; COMMAND_GROUP(main) @@ -55,7 +55,7 @@ COMMAND_GROUP(main) atexit(free_nargv); } #endif - COMMAND_GROUP_BODY(main) + COMMAND_GROUP_BODY(main, COMMANDS, FLAGS) } COMMAND(main, env) diff --git a/src/mock/CMakeLists.txt b/src/mock/CMakeLists.txt index c2634d5..8b48c04 100644 --- a/src/mock/CMakeLists.txt +++ b/src/mock/CMakeLists.txt @@ -1,8 +1,9 @@ SET(CURL_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/libcurl/libcurl.c + ${CMAKE_CURRENT_SOURCE_DIR}/libcurl.c ) add_library(mockcurl STATIC ${CURL_SOURCES}) +target_compile_options(mockcurl PUBLIC ${CFLAGS}) target_include_directories(mockcurl PUBLIC ${LIBCURL_INCLUDE_DIRS}) set(NAME ${CMAKE_PROJECT_NAME}_mock) diff --git a/src/mock/libcurl.c b/src/mock/libcurl.c new file mode 100644 index 0000000..95901be --- /dev/null +++ b/src/mock/libcurl.c @@ -0,0 +1,95 @@ +#include +#include +#include + +#include "../defines.h" + +char* url = NULL; +void* data = NULL; + +#ifdef curl_easy_setopt +#undef curl_easy_setopt +#endif + +CURLcode curl_global_init(UNUSED long flags) +{ + puts("[MOCK] curl_global_init(...)"); + return CURLE_OK; +} + +CURL* curl_easy_init() +{ + puts("[MOCK] curl_easy_init(...)"); + return NULL; +} + +CURLcode curl_easy_setopt(UNUSED CURL *handle, CURLoption option, ...) +{ + puts("[MOCK] curl_easy_setopt(...)"); + + va_list arg; + va_start(arg, option); + + switch (option) + { + case CURLOPT_URL: + url = va_arg(arg, char*); + printf("CURLOPT_URL\t%s\n", url); + break; + + case CURLOPT_WRITEDATA: + data = va_arg(arg, void*); + printf("CURLOPT_WRITEDATA\t%p\n", data); + break; + + default: + break; + } + + va_end(arg); + + return CURLE_OK; +} + +CURLcode curl_easy_perform(UNUSED CURL *easy_handle) +{ + puts("[MOCK] curl_easy_perform(...)"); + return CURLE_OK; +} + +#ifdef curl_easy_getinfo +#undef curl_easy_getinfo +#endif + +CURLcode curl_easy_getinfo(UNUSED CURL *curl, CURLINFO info, ...) +{ + puts("[MOCK] curl_easy_getinfo(...)"); + + if (info == CURLINFO_RESPONSE_CODE) + { + va_list arg; + va_start(arg, info); + long* http_code = va_arg(arg, long*); + *http_code = 200; + va_end(arg); + } + + + return CURLE_OK; +} + +const char* curl_easy_strerror(UNUSED CURLcode error) +{ + puts("[MOCK] curl_easy_strerror(...)"); + return "error"; +} + +void curl_easy_cleanup(CURL *handle) +{ + puts("[MOCK] curl_easy_cleanup(...)"); +} + +void curl_global_cleanup() +{ + puts("[MOCK] curl_global_cleanup(...)"); +} \ No newline at end of file diff --git a/src/mock/libcurl/libcurl.c b/src/mock/libcurl/libcurl.c deleted file mode 100644 index b4f332c..0000000 --- a/src/mock/libcurl/libcurl.c +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include -#include - -char* url = NULL; -void* data = NULL; - -#ifdef curl_easy_setopt -#undef curl_easy_setopt -#endif - -CURLcode curl_global_init(long flags) -{ - puts("[MOCK] curl_global_init(...)"); - return CURLE_OK; -} - -CURL* curl_easy_init() -{ - puts("[MOCK] curl_easy_init(...)"); - return NULL; -} - -CURLcode curl_easy_setopt(CURL *handle, CURLoption option, ...) -{ - puts("[MOCK] curl_easy_setopt(...)"); - - va_list arg; - va_start(arg, option); - - switch (option) - { - case CURLOPT_URL: - url = va_arg(arg, char*); - printf("CURLOPT_URL\t%s\n", url); - break; - - case CURLOPT_WRITEDATA: - data = va_arg(arg, void*); - printf("CURLOPT_WRITEDATA\t%p\n", data); - break; - - default: - break; - } - - va_end(arg); - - return CURLE_OK; -} - -CURLcode curl_easy_perform(CURL *easy_handle) -{ - puts("[MOCK] curl_easy_perform(...)"); - return CURLE_OK; -} - -#ifdef curl_easy_getinfo -#undef curl_easy_getinfo -#endif - -CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...) -{ - puts("[MOCK] curl_easy_getinfo(...)"); - - if (info == CURLINFO_RESPONSE_CODE) - { - va_list arg; - va_start(arg, info); - long* http_code = va_arg(arg, long*); - *http_code = 200; - va_end(arg); - } - - - return CURLE_OK; -} - -const char* curl_easy_strerror(CURLcode error) -{ - puts("[MOCK] curl_easy_strerror(...)"); - return "error"; -} - -void curl_easy_cleanup(CURL *handle) -{ - puts("[MOCK] curl_easy_cleanup(...)"); -} - -void curl_global_cleanup() -{ - puts("[MOCK] curl_global_cleanup(...)"); -} \ No newline at end of file diff --git a/src/net.c b/src/net.c index bf03a07..f58e8fe 100644 --- a/src/net.c +++ b/src/net.c @@ -44,6 +44,8 @@ static inline int xferinfo(UNUSED void *p, curl_off_t dltotal, curl_off_t dlnow, struct MemoryStruct* downloadToRam(const char* URL, int progress) { + if (no_net) return NULL; + CURL* curl_handle; CURLcode res = CURLE_OK; @@ -138,6 +140,10 @@ struct json_object* fetchJSON(const char* URL) free(chunk->memory); free(chunk); } + else if (isatty(STDERR_FILENO)) + { + fprintf(stderr, "Couldn't fetch JSON\n"); + } return json; } diff --git a/src/wine.c b/src/wine.c index 3f1e5c4..4db7d4f 100644 --- a/src/wine.c +++ b/src/wine.c @@ -25,7 +25,8 @@ static const struct Command wine_commands[] = { }; static const struct Flag wine_flags[] = { - { .name = "help", .variant = TWO, .func = wine_help, .description = "show this message"} + { .name = "help", .variant = TWO, .returns = 1, .func = wine_help, .description = "show this message"}, + { .name = "no-net", .variant = TWO, .returns = 0, .func = set_no_net, .description = "run commands without commitment"} }; COMMAND_GROUP_FUNC(wine) -- cgit v1.2.3