diff options
author | EuAndreh <eu@euandre.org> | 2021-06-27 08:16:17 -0300 |
---|---|---|
committer | EuAndreh <eu@euandre.org> | 2021-06-27 08:16:17 -0300 |
commit | f29de2217171a7e94320b5e754b930dc63e116f7 (patch) | |
tree | 16b92cd97efbc1f6a3b17e0e6efd02af78fc658a /src | |
parent | Makefile: Remove $(LDLIBS) (diff) | |
download | remembering-f29de2217171a7e94320b5e754b930dc63e116f7.tar.gz remembering-f29de2217171a7e94320b5e754b930dc63e116f7.tar.xz |
src/remembering-c.c: Restart C version
Diffstat (limited to '')
-rw-r--r-- | src/remembering-c.c | 965 |
1 files changed, 66 insertions, 899 deletions
diff --git a/src/remembering-c.c b/src/remembering-c.c index 2dda122..3f66473 100644 --- a/src/remembering-c.c +++ b/src/remembering-c.c @@ -2,942 +2,109 @@ #define _POSIX_C_SOURCE 200809L #endif -/* -#include <errno.h> -#include <libgen.h> -#include <stdio.h> #include <stdlib.h> +#include <stdio.h> #include <string.h> -#include <sys/stat.h> #include <unistd.h> -#ifdef FALLIBLE -#include <fallible.h> -#include <fallible/alloc.h> -#include <fallible/string.h> -#endif - -#ifdef TEST -#include <assert.h> - -static void testing(const char *message) { - fprintf(stderr, "testing: %s...", message); -} - -static void test_ok() { - fprintf(stderr, " OK.\n"); -} - -static FILE *testfile() { - char filename[] = "remembering-test.XXXXXX"; - - errno = 0; - int fd = mkstemp(filename); - if (fd == -1) { - perror("tmpfile mkstemp"); - return NULL; - } - - errno = 0; - FILE *f = fdopen(fd, "w"); - if (!f) { - perror("tmpfile fdopen"); - close(fd); - return NULL; - } - - return f; -} - -static char *testdir() { - char dirname[] = "remembering-test.XXXXXX"; - - errno = 0; - char *dircpy = malloc(strlen(dirname) + 1); - if (!dircpy) { - perror("malloc"); - return NULL; - } - - errno = 0; - char *dir = mkdtemp(dirname); - if (!dir) { - perror("mkdtemp"); - free(dircpy); - return NULL; - } - - strcpy(dircpy, dir); - - return dircpy; -} - -static void assert_file_contents(const char *const filename, const char *const contents) { - -} -#endif +const int EXIT_ERROR = 1; +const int EXIT_USAGE = 2; -static int print_usage(FILE *stream, char *name) { - errno = 0; - fprintf(stream, "Usage: %s -p PROFILE -c 'COMMAND'\n", - name ? name : "remembering"); - if (errno) { - perror("fprintf"); +int usage(FILE *stream) { + const char *const msg = "Usage: remembering -p PROFILE -c COMMAND\n"; + if (fprintf(stream, msg) < 0) { + perror("usage()"); return -1; } return 0; } -#ifdef TEST -static void print_usage_test() { - { - testing("print_usage a-name"); - FILE *f = testfile(); - if (!f) { - exit(EXIT_FAILURE); - } - - int ret = print_usage(f, "a-name"); - fclose(f); - if (ret) { - exit(EXIT_FAILURE); - } - - assert_file_contents(f, "Usage: a-name -p PROFILE -c 'COMMAND'\n"); - - test_ok(); - } - { - testing("print_usage NULL"); - FILE *f = testfile(); - if (!f) { - exit(EXIT_FAILURE); - } - - int ret = print_usage(f, NULL); - fclose(f); - if (ret) { - exit(EXIT_FAILURE); - } - - assert_file_contents(f, "Usage: remembering -p PROFILE -c 'COMMAND'\n"); - - test_ok(); - } -} -#endif - -static void print_help(FILE *stream) { - const char *help_text = - "\n" - "Options:\n" - " -p PROFILE profile to be used for gathering and storing data\n" - " -c 'COMMAND' command to be run, reading from STDIN, writing to " - "STDOUT\n" - " -h show this help\n" - " -V print program version\n" - "See remembering(1) manpages for more information.\n"; - fprintf(stream, "%s", help_text); -} - -static void print_missing(FILE *stream, char *text) { - fprintf(stream, "Missing option: %s\n", text); -} - -static void print_version(FILE *stream) { - fprintf(stream, "remembering-%s %s\n", VERSION, DATE); -} - -static int get_options(FILE *out, FILE *err, int argc, char *argv[], - char **command, char **profile) { - for (int i = 0; i < argc; i++) { - if (strcmp(argv[i], "--help") == 0) { - print_usage(out, argv[0]); - print_help(out); - return 1; - } else if (strcmp(argv[i], "--version")) { - print_version(out); - return 1; - } - } - - char *profilearg = NULL; - char *commandarg = NULL; - int option; - while ((option = getopt(argc, argv, "c:p:hV")) != -1) { - switch (option) { - case 'c': - commandarg = optarg; - break; - case 'p': - profilearg = optarg; - break; - case 'h': - print_usage(out, argv[0]); - print_help(out); - return 1; - case 'V': - print_version(out); - return 1; - } - } - - if (!commandarg) { - print_missing(err, "-c 'COMMAND'"); - print_usage(err, argv[0]); - return -1; - } - - if (!profilearg) { - print_missing(err, "-p 'PROFILE'"); - print_usage(err, argv[0]); - return 1; - } - - *command = strdup(commandarg); - if (!*command) { - perror("strdup"); +int help(FILE *stream) { + const char *const msg = + "Options:\n" + " -p, PROFILE profile to be used for gathering and storing data\n" + " -c, COMMAND commant to be run, reading from STDIN, writing to STDOUT\n" + " -h, --help show this help\n" + " -V, --version print the version number\n" + "\nSee \"man remembering\" for more information\n"; + if (fprintf(stream, msg) < 0) { + perror("help()"); return -1; } - *profile = strdup(profilearg); - if (!*profile) { - perror("strdup"); - free(*command); - return -1; - } - return 0; } -#ifdef FALLIBLE -static int fallible_get_options(FILE *out, FILE *err, int argc, char *argv[], - char **command, char **profile, - const char *const filename, int lineno) { - if (fallible_should_fail(filename, lineno)) { +int version(FILE *stream) { + const char *const msg = "remembering-" VERSION " " DATE "\n"; + if (fprintf(stream, msg) < 0) { + perror("version()"); return -1; } - return get_options(out, err, argc, argv, command, profile); -} - -#define get_options(out, err, argc, argv, command, profile) \ - fallible_get_options(out, err, argc, argv, command, profile, __FILE__, \ - __LINE__) -#endif - -#ifdef TEST -int arrlen(char **argv) { - int count = 0; - while (argv[count] != NULL) { - count++; - } - return count; -} - -void get_options_test() { - { - testing("get_options when given -h, -V and --help"); - FILE *f = tmpfile(); - if (!f) { - exit(EXIT_FAILURE); - } - - char *argvs[13][6] = { - {"--help", NULL}, - {"other", "arguments before", "--help", NULL}, - {"some", "--help", "arguments after", NULL}, - {"--help", "all", "arguments after", NULL}, - {"-h", NULL}, - {"-V", NULL}, - {"-hc", "1", NULL}, - {"-hp", "2", NULL}, - {"-hV", NULL}, - {"-Vh", NULL}, - {"-p", "p", "-h", NULL}, - {"-p", "p", "-c", "c", "-h", NULL}, - {NULL}, - }; - int rows = 0; - while (argvs[rows][0] != NULL) { - rows++; - } - -#ifdef DISABLE - int ret; - char *command = NULL; - char *profile = NULL; - for (int i = 0; i < rows; i++) { - char **argv = argvs[i]; - ret = get_options(f, f, arrlen(argvs[i]), argv, &command, &profile); - if (ret == -1) { - fclose(f); - exit(EXIT_FAILURE); - } - - assert(command == NULL); - assert(profile == NULL); - assert(ret == 1); - } -#endif - - fclose(f); - test_ok(); - } - // { "" }, -} -#endif - -static int mkdir_p(char *path, mode_t mode) { - struct stat s; - if (stat(path, &s) == 0 && S_ISDIR(s.st_mode)) { - return 0; - } - - char *parent = dirname(path); - int ret = mkdir_p(parent, mode); - if (ret) { - return ret; - } - return mkdir(path, mode); -} - -#ifdef FALLIBLE -static int fallible_mkdir_p(char *path, mode_t mode, const char *const filename, - int lineno) { - if (fallible_should_fail(filename, lineno)) { - return -1; - } - return mkdir_p(path, mode); -} - -#define mkdir_p(path, mode) fallible_mkdir_p(path, mode, __FILE__, __LINE__) -#endif - -#ifdef TEST -static void mkdir_p_test() { -{ -testing("mkdir_p a single directory"); - -char *dir = tmpdir(); -if (!dir) { -exit(EXIT_FAILURE); -} - -int ret = mkdir_p(dir, 0755); -if (ret) { -free(dir); -exit(EXIT_FAILURE); -} - -free(dir); -test_ok(); -} -{ -testing("mkdir_p nested directories"); - -const char *const dir_suffix = "/a/b/c/d/e"; -char *dir_prefix = tmpdir(); -if (!dir_prefix) { -exit(EXIT_FAILURE); -} - - char *dir = malloc(strlen(dir_prefix) + strlen(dir_suffix) + 1); - if (!dir) { - free(dir_prefix); - exit(EXIT_FAILURE); - } - - strcpy(dir, dir_prefix); - strcat(dir, dir_suffix); - -int ret = mkdir_p(dir, 0755); -if (ret) { - free(dir); - free(dir_prefix); -exit(EXIT_FAILURE); -} - - free(dir); - free(dir_prefix); -test_ok(); -} -} -#endif - -static char *expand_profile_name(const char *const profile_name) { - char *prefix = NULL; - char *env_prefix = getenv("XDG_DATA_HOME"); - if (env_prefix) { - prefix = strdup(env_prefix); - if (!prefix) { - return NULL; - } - } else { - char *home = getenv("HOME"); - char *path = "/.local/share/remembering"; - prefix = malloc(strlen(home) + strlen(path) + 1); - if (!prefix) { - return NULL; - } - strcpy(prefix, home); - strcat(prefix, path); - } - char *separator = "/"; - char *expanded_profile = - malloc(strlen(prefix) + strlen(separator) + strlen(profile_name) + 1); - if (!expanded_profile) { - free(prefix); - return NULL; - } - strcpy(expanded_profile, prefix); - strcat(expanded_profile, separator); - strcat(expanded_profile, profile_name); - - free(prefix); - - errno = 0; - int ret = mkdir_p(dirname(expanded_profile), 0755); - if (ret) { - perror("mkdir_p"); - return NULL; - } - return expanded_profile; -} - -#ifdef FALLIBLE -static char *fallible_expand_profile_name(const char *const profile_name, - const char *const filename, - int lineno) { - if (fallible_should_fail(filename, lineno)) { - return NULL; - } - return expand_profile_name(profile_name); -} - -#define expand_profile_name(profile_name) \ - fallible_expand_profile_name(profile_name, __FILE__, __LINE__) -#endif - -#ifdef TEST -static void expand_profile_name_test() { - { - testing("expand_profile_name"); - if (0) { - expand_profile_name("oij"); - } - test_ok(); - } -} -#endif - -static const size_t RANKINGS_INITIAL_SIZE = 100; -static const int RANKINGS_GROWTH_MULTIPLIER = 2; - -struct Rankings { - size_t count; - size_t size; - char **values; - int *ranks; -}; - -static struct Rankings *rankings_new() { - struct Rankings *r = malloc(sizeof(struct Rankings)); - if (!r) { - return NULL; - } - r->count = 0; - r->size = RANKINGS_INITIAL_SIZE; - r->values = malloc(r->size * sizeof(char *)); - if (!r->values) { - free(r); - return NULL; - } - r->ranks = malloc(r->size * sizeof(int)); - if (!r->ranks) { - free(r->values); - free(r); - return NULL; - } - return r; -} - -#ifdef FALLIBLE -static struct Rankings *fallible_rankings_new(const char *const filename, - int lineno) { - if (fallible_should_fail(filename, lineno)) { - return NULL; - } - return rankings_new(); -} - -#define rankings_new() fallible_rankings_new(__FILE__, __LINE__) -#endif - -static void rankings_free(struct Rankings *r) { - if (!r) { - return; - } - for (size_t i = 0; i < r->count; i++) { - free(r->values[i]); - } - free(r->values); - free(r->ranks); - free(r); -} - -static int rankings_insert(struct Rankings *r, char *value, int rank) { - if (r->count == r->size) { - r->size *= RANKINGS_GROWTH_MULTIPLIER; - char **new_values = realloc(r->values, r->size * sizeof(char *)); - if (!new_values) { - return -1; - } - r->values = new_values; - int *new_ranks = realloc(r->ranks, r->size * sizeof(int)); - if (!new_ranks) { - return -1; - } - r->ranks = new_ranks; - } - r->values[r->count] = value; - r->ranks[r->count] = rank; - r->count++; return 0; } -#ifdef FALLIBLE -static int fallible_rankings_insert(struct Rankings *r, char *value, int rank, - const char *const filename, int lineno) { - if (fallible_should_fail(filename, lineno)) { - return -1; - } - return rankings_insert(r, value, rank); -} - -#define rankings_insert(r, value, rank) \ - fallible_rankings_insert(r, value, rank, __FILE__, __LINE__) -#endif - -#ifdef TEST -static void rankings_test() { - { - testing("struct Rankings expands its size when needed"); - struct Rankings *r = rankings_new(); - if (!r) { - exit(EXIT_FAILURE); - } - size_t some_limit = RANKINGS_INITIAL_SIZE + 1; - int ret; - for (size_t i = 0; i < some_limit; i++) { - char *s = strdup("some string"); - ret = rankings_insert(r, s, i); - if (ret) { - free(s); - rankings_free(r); - exit(EXIT_FAILURE); - } - } - - assert(r->size == RANKINGS_INITIAL_SIZE * RANKINGS_GROWTH_MULTIPLIER); - assert(r->count == some_limit); - - rankings_free(r); - test_ok(); - } - - { - testing("an empty Rankings doesn't leak"); - struct Rankings *r = rankings_new(); - if (!r) { - exit(EXIT_FAILURE); - } - - assert(r->size == RANKINGS_INITIAL_SIZE); - assert(r->count == 0); - - rankings_free(r); - test_ok(); - } -} -#endif - -static const char RANKING_DELIMITER = ':'; - -int parse_ranked_line(FILE *stream, const char *entry, char **value, - int *rank) { - char *value_substr = strchr(entry, RANKING_DELIMITER); - if (value_substr == NULL) { - fprintf(stream, "WARN: Missing delimiter ('%c') in line: %s\n", - RANKING_DELIMITER, entry); - return -1; - } - - int rank_strlen = value_substr - entry; - char *rank_str = strndup(entry, rank_strlen); - if (!rank_str) { +int missing(FILE *stream, const char *const argument) { + const char *const msg = "Missing option: %s\n"; + if (fprintf(stream, msg, argument) < 0) { + perror("missing()"); return -1; } - *rank = atoi(rank_str); - free(rank_str); - - *value = malloc(strlen(value_substr) + 1); - if (!*value) { - return -1; - } - strcpy(*value, entry + (rank_strlen + 1 / * RANKING_DELIMITER * /)); - return 0; } -#ifdef FALLIBLE -int fallible_parse_ranked_line(FILE *stream, const char *entry, char **value, - int *rank, const char *const filename, - int lineno) { - if (fallible_should_fail(filename, lineno)) { - return -1; - } - return parse_ranked_line(stream, entry, value, rank); -} - -#define parse_ranked_line(stream, entry, value, rank) \ - fallible_parse_ranked_line(stream, entry, value, rank, __FILE__, __LINE__) -#endif - +int main(int argc, char *argv[]) { #ifdef TEST -static void parse_ranked_line_test() { - { - testing("parse_ranked_line with an empty string"); - FILE *f = tmpfile(); - if (!f) { - exit(EXIT_FAILURE); - } - - char *value; - int rank; - int ret = parse_ranked_line(f, "", &value, &rank); - assert(ret == -1); - fclose(f); - test_ok(); - } - { - testing("parse_ranked_line when RANKING DELIMITER is missing"); - FILE *f = tmpfile(); - if (!f) { - exit(EXIT_FAILURE); - } - - char *value; - int rank, ret; - - ret = parse_ranked_line(f, "0 command", &value, &rank); - assert(ret == -1); - - ret = parse_ranked_line(f, "1", &value, &rank); - assert(ret == -1); - - fclose(f); - test_ok(); - } - { - testing("parse_ranked_line with a happy path examples"); - char *value; - int rank; - int ret; - - ret = parse_ranked_line(stderr, "0:command", &value, &rank); - if (ret) { - exit(EXIT_FAILURE); - } - assert(ret == 0); - assert(strcmp(value, "command") == 0); - assert(rank == 0); - free(value); - - ret = parse_ranked_line(stderr, "10:another command", &value, &rank); - if (ret) { - exit(EXIT_FAILURE); - } - assert(ret == 0); - assert(strcmp(value, "another command") == 0); - assert(rank == 10); - free(value); - - ret = parse_ranked_line(stderr, "123:123", &value, &rank); - if (ret) { - exit(EXIT_FAILURE); - } - assert(ret == 0); - assert(strcmp(value, "123") == 0); - assert(rank == 123); - free(value); - - ret = parse_ranked_line(stderr, "-123:command", &value, &rank); - if (ret) { - exit(EXIT_FAILURE); - } - assert(ret == 0); - assert(strcmp(value, "command") == 0); - assert(rank == -123); - free(value); - - ret = parse_ranked_line(stderr, "0:0", &value, &rank); - if (ret) { - exit(EXIT_FAILURE); - } - assert(ret == 0); - assert(strcmp(value, "0") == 0); - assert(rank == 0); - free(value); - - ret = parse_ranked_line(stderr, "0:command with : in the middle", &value, - &rank); - if (ret) { - exit(EXIT_FAILURE); - } - assert(ret == 0); - assert(strcmp(value, "command with : in the middle") == 0); - assert(rank == 0); - free(value); - - ret = parse_ranked_line( - stderr, "0:::command:with:multiple:::in:the:middle:", &value, &rank); - if (ret) { - exit(EXIT_FAILURE); - } - assert(ret == 0); - assert(strcmp(value, "::command:with:multiple:::in:the:middle:") == 0); - assert(rank == 0); - free(value); - - test_ok(); - } - { - testing("parse_ranked_line with an empty command"); - char *value; - int rank; - - int ret = parse_ranked_line(stderr, "0:", &value, &rank); - if (ret) { - exit(EXIT_FAILURE); - } - assert(ret == 0); - assert(strcmp(value, "") == 0); - assert(rank == 0); - free(value); - - test_ok(); - } - { - testing("parse_ranked_line with a bad rank numbers"); - char *value; - int rank; - int ret; - - ret = parse_ranked_line(stderr, ":command", &value, &rank); - if (ret) { - exit(EXIT_FAILURE); - } - assert(ret == 0); - assert(strcmp(value, "command") == 0); - assert(rank == 0); - free(value); - - ret = parse_ranked_line(stderr, "1 2 3:command", &value, &rank); - if (ret) { - exit(EXIT_FAILURE); - } - assert(ret == 0); - assert(strcmp(value, "command") == 0); - assert(rank == 1); - free(value); - - ret = parse_ranked_line(stderr, ".1:command", &value, &rank); - if (ret) { - exit(EXIT_FAILURE); - } - assert(ret == 0); - assert(strcmp(value, "command") == 0); - assert(rank == 0); - free(value); - - ret = parse_ranked_line(stderr, "3.14:command", &value, &rank); - if (ret) { - exit(EXIT_FAILURE); - } - assert(ret == 0); - assert(strcmp(value, "command") == 0); - assert(rank == 3); - free(value); - - ret = parse_ranked_line(stderr, ":5:command", &value, &rank); - if (ret) { - exit(EXIT_FAILURE); - } - assert(ret == 0); - assert(strcmp(value, "5:command") == 0); - assert(rank == 0); - free(value); - - ret = parse_ranked_line(stderr, "command:command", &value, &rank); - if (ret) { - exit(EXIT_FAILURE); - } - assert(ret == 0); - assert(strcmp(value, "command") == 0); - assert(rank == 0); - free(value); - - test_ok(); - } -} + return EXIT_SUCCESS; #endif -struct GetlineParams { - char *line; - size_t len; - ssize_t read; - FILE *stream; -}; - -int get_stdin(struct GetlineParams *s_params, struct GetlineParams *p_params, - struct Rankings *p_rankings) { - s_params->read = getline(&s_params->line, &s_params->len, s_params->stream); - if (s_params->read == -1) { - while ((p_params->read = getline(&p_params->line, &p_params->len, - p_params->stream)) != -1) { - char *value; - int rank; - int ret; - if ((ret = parse_ranked_line(stderr, p_params->line, &value, &rank)) == - -1) { - return ret; - } - if ((ret = rankings_insert(p_rankings, value, rank)) == -1) { - return ret; - } - } - return 1; - } - return 0; -} - -int get_profile(struct GetlineParams *s_params, struct GetlineParams *p_params, - struct Rankings *s_rankings, struct Rankings *p_rankings) { - p_params->read = getline(&p_params->line, &p_params->len, p_params->stream); - if (p_params->read == -1) { - while ((s_params->read = getline(&s_params->line, &s_params->len, - s_params->stream)) != -1) { - char *s_value_copy = strdup(s_params->line); - if (!s_value_copy) { - return -1; - } - char *p_value_copy = strdup(s_params->line); - if (!p_value_copy) { - free(s_value_copy); - return -1; - } - - int ret; - if ((ret = rankings_insert(s_rankings, s_value_copy, 0)) == -1) { - free(s_value_copy); - free(p_value_copy); - return -1; - } - - // profile grows with stdin entries - if ((ret = rankings_insert(p_rankings, p_value_copy, 0)) == -1) { - free(s_value_copy); - free(p_value_copy); - return -1; - } + for (int i = 0; i < argc; i++) { + if (strcmp("--", argv[i]) == 0) { + break; + } else if (strcmp("--help", argv[i]) == 0) { + if (usage(stdout)) return EXIT_ERROR; + if (help(stdout)) return EXIT_ERROR; + return EXIT_SUCCESS; + } else if (strcmp("--version", argv[i]) == 0) { + if (version(stdout)) return EXIT_ERROR; + return EXIT_SUCCESS; } - return 1; } - return 0; -} - -int merge_stdin_with_profile(char *profile_name, struct Rankings *s_rankings, - struct Rankings *p_rankings) { - FILE *profile = fopen(profile_name, "r"); - struct GetlineParams s_params = { - .line = NULL, .len = 0, .read = 0, .stream = stdin}; - struct GetlineParams p_params = { - .line = NULL, .len = 0, .read = 0, .stream = profile}; - - int stop = get_stdin(&s_params, &p_params, p_rankings) || - get_profile(&s_params, &p_params, s_rankings, p_rankings); - while (!stop) { - char *value; - int rank; - parse_ranked_line(stderr, p_params.line, &value, &rank); - int cmp = strcmp(s_params.line, value); - if (cmp == 0) { - rankings_insert(s_rankings, value, rank); - rankings_insert(p_rankings, value, rank); // double free - stop = get_stdin(&s_params, &p_params, p_rankings) || - get_profile(&s_params, &p_params, s_rankings, p_rankings); - continue; - } - - if (cmp < 0) { - char *value_copy = malloc(strlen(s_params.line) + 1); - strcpy(value_copy, s_params.line); - int *rank = malloc(sizeof(int)); - *rank = 0; - rankings_insert(s_rankings, value_copy, rank); - rankings_insert(p_rankings, value_copy, rank); - stop = get_stdin(&s_params, &p_params, p_rankings); - tuple_free(&t); - continue; - } - - if (cmp > 0) { - rankings_insert(p_rankings, t.first, t.second); - stop = get_profile(&s_params, &p_params, s_rankings, p_rankings); - tuple_free(&t); - continue; + int option; + const char *profile = NULL; + const char *command = NULL; + while ((option = getopt(argc, argv, "p:c:hV")) != -1) { + switch (option) { + case 'p': + profile = optarg; + break; + case 'c': + command = optarg; + break; + case 'h': + if (usage(stdout)) return EXIT_ERROR; + if (help(stdout)) return EXIT_ERROR; + return EXIT_SUCCESS; + case 'V': + if (version(stdout)) return EXIT_ERROR; + return EXIT_SUCCESS; + default: + if (usage(stderr)) return EXIT_ERROR; + return EXIT_USAGE; } } - free(s_params.line); - free(p_params.line); - fclose(profile); - - if (stop == -1) { - return stop; + if (!profile) { + if (missing(stderr, "-p PROFILE")) return EXIT_ERROR; + if (usage(stderr)) return EXIT_ERROR; + return EXIT_USAGE; } - return 0; -} -#ifdef TEST -static void unit_tests() { - print_usage_test(); - get_options_test(); - mkdir_p_test(); - expand_profile_name_test(); - rankings_test(); - parse_ranked_line_test(); -} -#endif - -int main(int argc, char *argv[]) { -#ifdef TEST - unit_tests(); - return EXIT_SUCCESS; -#endif - - int ret; - - char *command, *profile; - ret = get_options(stdout, stderr, argc, argv, &command, &profile); - if (ret == -1) { - return EXIT_FAILURE; - } else if (ret) { - return EXIT_SUCCESS; + if (!command) { + if (missing(stderr, "-c COMMAND")) return EXIT_ERROR; + if (usage(stderr)) return EXIT_ERROR; + return EXIT_USAGE; } -} -*/ -int main() { return 0; } |