summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEvadne Wu <ev@radi.ws>2019-07-03 21:18:28 +0100
committerJames Every <devstopfix@gmail.com>2019-07-03 21:18:28 +0100
commit46375802f5c69b407140aab51854943e1c8e363c (patch)
treef0aa7c89fcad13ba423604c914ab7c1aa3a528e3 /src
Prototype using erlexec
Diffstat (limited to 'src')
-rw-r--r--src/apprentice.c216
1 files changed, 216 insertions, 0 deletions
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 <errno.h>
+#include <getopt.h>
+#include <libgen.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <magic.h>
+
+#define USAGE "--file <path/to/magic.mgc> [--file <path/to/custom.mgc> ...]"
+#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);
+}