From 1753e2b151cbb4af75a4e9ea61720b3704b03805 Mon Sep 17 00:00:00 2001 From: Jan200101 Date: Mon, 10 Aug 2020 12:43:26 +0200 Subject: a lot of changes […] - go to next entry of argv and decrement argc the deeper it goes - add basic lutris functionality - remove "help" from help message and as a command - replace all stderr prints with stdout prints (usually stderr is better for directly informing the user but in this case I don't think it will help much) - add libarchive dependency to the README - bump version number MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 2 +- README.md | 1 + src/common.c | 2 +- src/common.h | 1 + src/dxvk.c | 9 ++- src/lutris.c | 218 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lutris.h | 61 +++++++++++++++++ src/main.c | 11 +-- src/main.h | 4 +- src/net.c | 5 +- src/tar.c | 12 ++-- src/wine.c | 38 +++++------ 12 files changed, 322 insertions(+), 42 deletions(-) create mode 100644 src/lutris.c create mode 100644 src/lutris.h diff --git a/Makefile b/Makefile index 5aedaf9..7bef6be 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # GENERAL VARIABLES NAME := polecat -VERSION := 0.1.2 +VERSION := 0.1.3 TARGET ?= debug DEBUG := 0 ifeq ($(TARGET),debug) diff --git a/README.md b/README.md index 09ba819..83f470a 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ polecat depends on: - libcurl - json-c +- libarchive ### License MIT \ No newline at end of file diff --git a/src/common.c b/src/common.c index f3131e0..ca08f07 100644 --- a/src/common.c +++ b/src/common.c @@ -16,6 +16,6 @@ void print_help(const struct Command* commands, const size_t size) for (size_t i = 0; i < size; ++i) { - printf("\t%-*s\t%s\n", longestCommand, commands[i].name, commands[i].description); + printf("\t%-*s\t %s\n", longestCommand, commands[i].name, commands[i].description); } } diff --git a/src/common.h b/src/common.h index 54882df..3b071cc 100644 --- a/src/common.h +++ b/src/common.h @@ -8,6 +8,7 @@ #define WINE_API "https://lutris.net/api/runners/wine" #define DXVK_API "https://api.github.com/repos/lutris/dxvk/releases" +#define INSTALLER_API "https://lutris.net/api/installers/" #define USER_AGENT NAME "/" VERSION diff --git a/src/dxvk.c b/src/dxvk.c index f0ebc86..c5ac1d0 100644 --- a/src/dxvk.c +++ b/src/dxvk.c @@ -10,16 +10,15 @@ const static struct Command dxvk_commands[] = { { .name = "install", .func = dxvk_install, .description = "download and install a dxvk version" }, { .name = "list", .func = dxvk_list, .description = "list available dxvk versions" }, - { .name = "help", .func = dxvk_help, .description = "shows this message" }, }; int dxvk(int argc, char** argv) { - if (argc > 2) + if (argc > 1) { for (int i = 0; i < ARRAY_LEN(dxvk_commands); ++i) { - if (!strcmp(dxvk_commands[i].name, argv[2])) return dxvk_commands[i].func(argc, argv); + if (!strcmp(dxvk_commands[i].name, argv[1])) return dxvk_commands[i].func(argc-1, argv+1); } } @@ -29,14 +28,14 @@ int dxvk(int argc, char** argv) int dxvk_install(int argc, char** argv) { - if (argc == 4) + if (argc == 2) { struct json_object* runner = fetchJSON(DXVK_API); if (runner) { - int choice = atoi(argv[3]); + int choice = atoi(argv[1]); if (choice > json_object_array_length(runner) - 1 || choice < 0) { diff --git a/src/lutris.c b/src/lutris.c new file mode 100644 index 0000000..4adaa81 --- /dev/null +++ b/src/lutris.c @@ -0,0 +1,218 @@ +#include +#include +#include + +#include "lutris.h" +#include "net.h" +#include "common.h" + +const static struct Command lutris_commands[] = { + { .name = "install", .func = lutris_install, .description = "install a lutris script" }, + { .name = "info", .func = lutris_info, .description = "show information about a lutris script" }, +}; + +int lutris(int argc, char** argv) +{ + if (argc > 1) + { + for (int i = 0; i < ARRAY_LEN(lutris_commands); ++i) + { + if (!strcmp(lutris_commands[i].name, argv[1])) return lutris_commands[i].func(argc-1, argv+1); + } + } + + + return lutris_help(argc, argv); +} + + +int lutris_install(int argc, char** argv) +{ + +} + +int lutris_info(int argc, char** argv) +{ + if (argc == 2) + { + char installerurl[PATH_MAX]; + lutris_getInstallerURL(installerurl, argv[1]); + + struct json_object* installer = fetchJSON(installerurl); + + if (installer) + { + struct json_object* count, *results, *slug; + + json_object_object_get_ex(installer, "count", &count); + json_object_object_get_ex(installer, "results", &results); + slug = json_object_array_get_idx(results, 0); + + if (json_object_get_int(count) != 0) + { + struct json_object* name, *version, *runner, *description, *notes, *script, *scriptinstall, *wine, *winever; + json_object_object_get_ex(slug, "name", &name); + json_object_object_get_ex(slug, "version", &version); + json_object_object_get_ex(slug, "runner", &runner); + json_object_object_get_ex(slug, "description", &description); + json_object_object_get_ex(slug, "notes", ¬es); + json_object_object_get_ex(slug, "script", &script); + json_object_object_get_ex(script, "installer", &scriptinstall); + + json_object_object_get_ex(script, "wine", &wine); + json_object_object_get_ex(wine, "version", &winever); + + printf("[%s]", json_object_get_string(runner)); + if (winever) printf("[%s]", json_object_get_string(winever)); + + printf(" %s - %s\n", json_object_get_string(name), json_object_get_string(version)); + + if (description) printf("\n%s\n", json_object_get_string(description)); + if (notes) printf("\n%s\n", json_object_get_string(notes)); + + if (scriptinstall) + { + puts("\ninstall script:"); + for (int i = 0; i < json_object_array_length(scriptinstall); ++i) + { + struct json_object* step = json_object_array_get_idx(scriptinstall, i); + struct json_object* directive; + + for (int l = 0; l < KEYWORDMAX; ++l) + { + json_object_object_get_ex(step, keywordstr[l], &directive); + if (directive) + { + struct json_object* options[5]; + printf(" - "); + switch (l) + { + case MOVE: + case COPY: + case MERGE: + json_object_object_get_ex(directive, "src", &options[0]); + json_object_object_get_ex(directive, "dst", &options[1]); + printf("%s %s %s\n", keywordstr[l], json_object_get_string(options[0]), json_object_get_string(options[1])); + break; + + case EXTRACT: + json_object_object_get_ex(directive, "file", &options[0]); + printf("%s %s\n", keywordstr[l], json_object_get_string(options[0])); + break; + + case CHMODX: + printf("%s %s\n", keywordstr[l], json_object_get_string(directive)); + break; + + case EXECUTE: + json_object_object_get_ex(directive, "file", &options[0]); + printf("%s %s\n", keywordstr[l], json_object_get_string(options[0])); + break; + + case WRITE_FILE: + json_object_object_get_ex(directive, "file", &options[0]); + printf("%s %s\n", keywordstr[l], json_object_get_string(options[0])); + break; + + case WRITE_CONFIG: + json_object_object_get_ex(directive, "file", &options[0]); + json_object_object_get_ex(directive, "section", &options[1]); + json_object_object_get_ex(directive, "key", &options[2]); + json_object_object_get_ex(directive, "value", &options[3]); + + printf("%s %s [%s] %s = %s\n", keywordstr[l], json_object_get_string(options[0]), json_object_get_string(options[1]), json_object_get_string(options[2]), json_object_get_string(options[3])); + break; + + case WRITE_JSON: + printf("%s\n", keywordstr[l]); + break; + + case INPUT_MENU: + json_object_object_get_ex(directive, "description", &options[0]); + printf("%s `%s'\n", keywordstr[l], json_object_get_string(options[0])); + break; + + case INSERT_DISC: + json_object_object_get_ex(directive, "requires", &options[0]); + printf("%s %s\n", keywordstr[l], json_object_get_string(options[0])); + break; + + case TASK: + json_object_object_get_ex(directive, "name", &options[0]); + const char* name = json_object_get_string(options[0]); + for (int k = 0; k <= TASKKEYWORDMAX; ++k) + { + if (!strcmp(name, taskKeywordstr[k])) + { + switch(k) + { + case WINEEXEC: + json_object_object_get_ex(directive, "executable", &options[1]); + printf("%s %s\n", name, json_object_get_string(options[1])); + break; + + case WINETRICKS: + json_object_object_get_ex(directive, "app", &options[1]); + printf("%s %s\n", name, json_object_get_string(options[1])); + break; + + case CREATE_PREFIX: + case WINEKILL: + json_object_object_get_ex(directive, "prefix", &options[1]); + printf("%s %s\n", name, json_object_get_string(options[1])); + break; + + case SET_REGEDIT: + json_object_object_get_ex(directive, "path", &options[1]); + json_object_object_get_ex(directive, "key", &options[2]); + json_object_object_get_ex(directive, "value", &options[3]); + + printf("%s %s\\%s = %s\n", name, json_object_get_string(options[1]), json_object_get_string(options[2]), json_object_get_string(options[3])); + break; + + default: + puts(name); + break; + } + break; + } + if (k == TASKKEYWORDMAX) printf("FIXME: unknown task %s\n", name); + } + break; + + default: + printf("FIXME: unknown %s\n", keywordstr[l]); + } + break; + } + } + } + } + else puts("no install script found"); + } + else + { + printf("`%s' does not exist on lutris\n", argv[1]); + } + + json_object_put(installer); + } + } + else puts(USAGE_STR " lutris info \nInstaller IDs are obtained from the lutris website"); + + return 0; +} + +void lutris_getInstallerURL(char* buffer, char* name) +{ + strcpy(buffer, INSTALLER_API); + strcat(buffer, name); +} +int lutris_help(int argc, char** argv) +{ + puts(USAGE_STR " lutris \n\nList of commands:"); + + print_help(lutris_commands, ARRAY_LEN(lutris_commands)); + + return 0; +} \ No newline at end of file diff --git a/src/lutris.h b/src/lutris.h new file mode 100644 index 0000000..6f5fa40 --- /dev/null +++ b/src/lutris.h @@ -0,0 +1,61 @@ +#ifndef LUTRIS_H +#define LUTRIS_H + +enum keywords { + MOVE = 0, + MERGE, + EXTRACT, + COPY, + CHMODX, + EXECUTE, + WRITE_FILE, + WRITE_CONFIG, + WRITE_JSON, + INPUT_MENU, + INSERT_DISC, + TASK, + + KEYWORDMAX +}; + +static const char keywordstr[KEYWORDMAX][0xF] = { + "move", + "merge", + "extract", + "copy", + "chmodx", + "execute", + "write_file", + "write_config", + "write_json", + "input_menu", + "insert-disc", + "task", +}; + +enum taskKeywords { + WINEEXEC = 0, + WINETRICKS, + CREATE_PREFIX, + SET_REGEDIT, + WINEKILL, + + TASKKEYWORDMAX +}; + +static const char taskKeywordstr[TASKKEYWORDMAX][0xF] = +{ + "wineexec", + "winetricks", + "create_prefix", + "set_regedit", + "winekill" +}; + +int lutris(int, char**); +int lutris_install(int, char**); +int lutris_info(int, char**); +int lutris_help(int, char**); +void lutris_getInstallerURL(char*, char*); + +#endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index d56ac28..aa4f356 100644 --- a/src/main.c +++ b/src/main.c @@ -5,14 +5,15 @@ #include "main.h" #include "wine.h" #include "dxvk.h" +#include "lutris.h" #include "common.h" #include "config.h" const static struct Command main_commands[] = { - { .name = "wine", .func = wine, .description = "manage wine versions" }, - //{ .name = "dxvk", .func = dxvk, .description = "manage dxvk versions (TODO)" }, - { .name = "info", .func = main_info, .description = "show some information about polecat" }, - { .name = "help", .func = main_help, .description = "displays this message" }, + { .name = "wine", .func = wine, .description = "manage wine versions" }, + //{ .name = "dxvk", .func = dxvk, .description = "manage dxvk versions (TODO)" }, + { .name = "lutris", .func = lutris, .description = "run lutris instraller"}, + { .name = "info", .func = main_info, .description = "show some information about polecat" }, }; @@ -22,7 +23,7 @@ int main(int argc, char** argv) { for (int i = 0; i < ARRAY_LEN(main_commands); ++i) { - if (!strcmp(main_commands[i].name, argv[1])) return main_commands[i].func(argc, argv); + if (!strcmp(main_commands[i].name, argv[1])) return main_commands[i].func(argc-1, argv+1); } } diff --git a/src/main.h b/src/main.h index 594b29e..e64eb9a 100644 --- a/src/main.h +++ b/src/main.h @@ -1,7 +1,7 @@ #ifndef MAIN_H #define MAIN_H -extern int main_help(int, char**); -extern int main_info(int, char**); +int main_help(int, char**); +int main_info(int, char**); #endif \ No newline at end of file diff --git a/src/net.c b/src/net.c index a1c574a..a23f772 100644 --- a/src/net.c +++ b/src/net.c @@ -56,13 +56,12 @@ struct MemoryStruct* downloadToRam(const char* URL) curl_easy_getinfo (curl_handle, CURLINFO_RESPONSE_CODE, &http_code); if(res != CURLE_OK) { - fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + printf("libcurl error: %s\n", curl_easy_strerror(res)); return NULL; } else if (http_code != 200) { - fprintf(stderr, "Server didn't respond as expected [HTTP Error %li]\n", http_code); + printf("HTTP Error %li\n", http_code); return NULL; } diff --git a/src/tar.c b/src/tar.c index 8894676..0fd4fc3 100644 --- a/src/tar.c +++ b/src/tar.c @@ -19,7 +19,7 @@ static int copy_data(struct archive* ar, struct archive* aw) return (r); r = archive_write_data_block(aw, buff, size, offset); if (r < ARCHIVE_OK) { - fprintf(stderr, "%s\n", archive_error_string(aw)); + printf("%s\n", archive_error_string(aw)); return (r); } } @@ -32,7 +32,7 @@ void extract(const char* filename, const char* outputdir) if (chdir(outputdir) < 0) { - fprintf(stderr, "Cannot change to %s\n", outputdir); + printf("Cannot change to %s\n", outputdir); return; } @@ -67,7 +67,7 @@ void extract(const char* filename, const char* outputdir) if (r < ARCHIVE_OK) { - fprintf(stderr, "%s\n", archive_error_string(a)); + printf("%s\n", archive_error_string(a)); } if (r < ARCHIVE_WARN) @@ -78,20 +78,20 @@ void extract(const char* filename, const char* outputdir) r = archive_write_header(ext, entry); if (r < ARCHIVE_OK) { - fprintf(stderr, "%s\n", archive_error_string(ext)); + printf("%s\n", archive_error_string(ext)); } else if (archive_entry_size(entry) > 0) { r = copy_data(a, ext); if (r < ARCHIVE_OK) - fprintf(stderr, "%s\n", archive_error_string(ext)); + printf("%s\n", archive_error_string(ext)); if (r < ARCHIVE_WARN) return; } r = archive_write_finish_entry(ext); if (r < ARCHIVE_OK) - fprintf(stderr, "%s\n", archive_error_string(ext)); + printf("%s\n", archive_error_string(ext)); if (r < ARCHIVE_WARN) return; } diff --git a/src/wine.c b/src/wine.c index 3f50eee..c6f445e 100644 --- a/src/wine.c +++ b/src/wine.c @@ -17,29 +17,29 @@ const static struct Command wine_commands[] = { - { .name = "download", .func = wine_download, .description = "download and extract a wine version from lutris" }, - { .name = "list", .func = wine_list, .description = "list installable wine versions" }, - { .name = "run", .func = wine_run, .description = "run a installed wine version" }, - { .name = "list-installed", .func = wine_installed, .description = "list installed wine versions" }, - { .name = "help", .func = wine_help, .description = "shows this message" }, + { .name = "download", .func = wine_download, .description = "download and extract a wine version from lutris" }, + { .name = "list", .func = wine_list, .description = "list installable wine versions" }, + { .name = "run", .func = wine_run, .description = "run a installed wine version" }, + { .name = "installed", .func = wine_installed, .description = "list installed wine versions" }, }; int wine(int argc, char** argv) { - if (argc > 2) + if (argc > 1) { for (int i = 0; i < ARRAY_LEN(wine_commands); ++i) { - if (!strcmp(wine_commands[i].name, argv[2])) return wine_commands[i].func(argc, argv); + if (!strcmp(wine_commands[i].name, argv[1])) return wine_commands[i].func(argc-1, argv+1); } } + return wine_help(argc, argv); } int wine_download(int argc, char** argv) { - if (argc == 4) + if (argc == 2) { struct json_object* runner = fetchJSON(WINE_API); @@ -48,11 +48,11 @@ int wine_download(int argc, char** argv) struct json_object* versions; json_object_object_get_ex(runner, "versions", &versions); - int choice = atoi(argv[3]); + int choice = atoi(argv[1]); if (choice > json_object_array_length(versions) - 1 || choice < 0) { - fprintf(stderr, "`%i' is not a valid ID\n\nrun `polecat wine list' to get a valid ID\n", choice); + printf("`%i' is not a valid ID\n\nrun `polecat wine list' to get a valid ID\n", choice); } else { @@ -72,11 +72,11 @@ int wine_download(int argc, char** argv) strcat(downloadpath, "/"); strcat(downloadpath, name); - fprintf(stderr, "Downloading %s\n", name); + printf("Downloading %s\n", name); downloadFile(json_object_get_string(url), downloadpath); - fprintf(stderr, "Extracting %s\n", name); + printf("Extracting %s\n", name); extract(downloadpath, datadir); - fprintf(stderr, "Done\n"); + printf("Done\n"); } json_object_put(runner); @@ -115,17 +115,17 @@ int wine_list(int argc, char** argv) int wine_run(int argc, char** argv) { - if (argc > 3) + if (argc > 1) { char winepath[PATH_MAX]; getDataDir(winepath); - char* winever = argv[3]; + char* winever = argv[1]; strcat(winepath, "/"); strcat(winepath, winever); strcat(winepath, "/bin/wine"); - for (int i = 4; i < argc; ++i) + for (int i = 2; i < argc; ++i) { strcat(winepath, " "); strcat(winepath, argv[i]); @@ -134,7 +134,7 @@ int wine_run(int argc, char** argv) return system(winepath); } - fprintf(stderr, "Specify a what wine version to run.\nUse `" NAME " wine list-installed' to list available versions\n"); + printf("Specify a what wine version to run.\nUse `" NAME " wine list-installed' to list available versions\n"); return 0; } @@ -147,7 +147,7 @@ int wine_installed(int argc, char** argv) DIR *dir; struct dirent *ent; - fprintf(stderr, "Installed wine versions:\n"); + printf("Installed wine versions:\n"); if ((dir = opendir(datadir)) != NULL) { while ((ent = readdir (dir)) != NULL) @@ -158,7 +158,7 @@ int wine_installed(int argc, char** argv) */ if (ent->d_name[0] != '.' && ent->d_type == DT_DIR) { - fprintf(stderr, " - %s\n", ent->d_name); + printf(" - %s\n", ent->d_name); } } closedir (dir); -- cgit v1.2.3