From 46375802f5c69b407140aab51854943e1c8e363c Mon Sep 17 00:00:00 2001 From: Evadne Wu Date: Wed, 3 Jul 2019 21:18:28 +0100 Subject: Prototype using erlexec --- src/apprentice.c | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 src/apprentice.c (limited to 'src') diff --git a/src/apprentice.c b/src/apprentice.c new file mode 100644 index 0000000..04f08aa --- /dev/null +++ b/src/apprentice.c @@ -0,0 +1,216 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "--file [--file ...]" +#define DELIMINTER "\t" + +#define ANSI_INFO "\x1b[37m" // gray +#define ANSI_OK "\x1b[32m" // green +#define ANSI_ERROR "\x1b[31m" // red +#define ANSI_IGNORE "\x1b[90m" // red +#define ANSI_RESET "\x1b[0m" + +#define MAGIC_FLAGS_COMMON (MAGIC_CHECK|MAGIC_ERROR) +magic_t magic_setup(int flags); + +void setup_environment(); +void setup_options(int argc, char **argv); +void setup_options_file(char *optarg); +void setup_system(); +void process_line(char *line); +void process_file(char *path); +void print_info(const char *format, ...); +void print_ok(const char *format, ...); +void print_error(const char *format, ...); + +struct file { + char *path; + struct file *next; +}; + +static struct file* magic_database; +static magic_t magic_mime_type; // MAGIC_MIME_TYPE +static magic_t magic_mime_encoding; // MAGIC_MIME_ENCODING +static magic_t magic_type_name; // MAGIC_NONE + +int main (int argc, char **argv) { + setup_environment(); + setup_options(argc, argv); + setup_system(); + printf("ok\n"); + fflush(stdout); + + char line[4096]; + while (fgets(line, 4096, stdin)) { + process_line(line); + } + + return 0; +} + +void setup_environment() { + // setbuf(stdout, NULL); + opterr = 0; +} + +void setup_options(int argc, char **argv) { + const char *option_string = "f:"; + static struct option long_options[] = { + {"file", required_argument, 0, 'f'}, + {0, 0, 0, 0} + }; + + int option_character; + while (1) { + int option_index = 0; + option_character = getopt_long(argc, argv, option_string, long_options, &option_index); + if (-1 == option_character) { + break; + } + switch (option_character) { + case 'f': { + setup_options_file(optarg); + break; + } + case '?': + default: { + print_info("%s %s\n", basename(argv[0]), USAGE); + exit(1); + break; + } + } + } +} + +void setup_options_file(char *optarg) { + print_info("Magic Database: %s", optarg); + if (0 != access(optarg, R_OK)) { + print_error("no_database"); + exit(1); + } + struct file *next = malloc(sizeof(struct file)); + next->path = strdup(optarg); + next->next = magic_database; + magic_database = next; +} + +void setup_system() { + print_info("Starting System"); + magic_mime_encoding = magic_setup(MAGIC_FLAGS_COMMON|MAGIC_MIME_ENCODING); + magic_mime_type = magic_setup(MAGIC_FLAGS_COMMON|MAGIC_MIME_TYPE); + magic_type_name = magic_setup(MAGIC_FLAGS_COMMON|MAGIC_NONE); +} + +magic_t magic_setup(int flags) { + magic_t magic = magic_open(flags); + struct file *current_database = magic_database; + while (current_database) { + if (isatty(STDERR_FILENO)) { + fprintf(stderr, ANSI_IGNORE); + } + magic_load(magic, current_database->path); + if (isatty(STDERR_FILENO)) { + fprintf(stderr, ANSI_RESET); + } + current_database = current_database->next; + } + return magic; +} + +void process_line(char *line) { + char path[4096]; + + if (0 == strcmp(line, "exit\n")) { + exit(0); + } + + if (1 != sscanf(line, "file; %[^\n]s", path)) { + print_error("bad_path"); + return; + } + + if (0 != access(path, R_OK)) { + print_error("no_file"); + return; + } + + process_file(path); +} + +void process_file(char *path) { + const char *mime_type_result = magic_file(magic_mime_type, path); + const char *mime_type_error = magic_error(magic_mime_type); + const char *mine_encoding_result = magic_file(magic_mime_encoding, path); + const char *mine_encoding_error = magic_error(magic_mime_encoding); + const char *type_name_result = magic_file(magic_type_name, path); + const char *type_name_error = magic_error(magic_type_name); + + if (mime_type_error) { + print_error(mime_type_error); + return; + } + + if (mine_encoding_error) { + print_error(mine_encoding_error); + return; + } + + if (type_name_error) { + print_error(type_name_error); + return; + } + + print_ok("%s%s%s%s%s", mime_type_result, DELIMINTER, mine_encoding_result, DELIMINTER, type_name_result); +} + +void print_info(const char *format, ...) { + if (!isatty(STDOUT_FILENO)) { + return; + } + + printf(ANSI_INFO "[INFO] " ANSI_RESET); + va_list arguments; + va_start(arguments, format); + vprintf(format, arguments); + va_end(arguments); + printf("\n"); +} + +void print_ok(const char *format, ...) { + if (isatty(STDOUT_FILENO)) { + printf(ANSI_OK "[OK] " ANSI_RESET); + } else { + printf("ok; "); + } + + va_list arguments; + va_start(arguments, format); + vprintf(format, arguments); + va_end(arguments); + printf("\n"); + fflush(stdout); +} + +void print_error(const char *format, ...) { + if (isatty(STDERR_FILENO)) { + fprintf(stderr, ANSI_ERROR "[ERROR] " ANSI_RESET); + } else { + fprintf(stderr, "error; "); + } + + va_list arguments; + va_start(arguments, format); + vfprintf(stderr, format, arguments); + va_end(arguments); + fprintf(stderr, "\n"); + fflush(stderr); +} -- cgit v1.2.3