Add alternative main() for a simple `cat' program
diff --git a/fscat.gpr b/fscat.gpr
new file mode 100644
index 0000000..67c92ac
--- /dev/null
+++ b/fscat.gpr
@@ -0,0 +1,15 @@
+project Default is
+   for Languages use ("ada", "c");
+   for Main use ("cat.c");
+   for Source_Dirs use ("src");
+   for Object_Dir use "build";
+
+   package Builder is
+      for Global_Configuration_Pragmas use "default.adc";
+   end Builder;
+
+   package Compiler is
+      for Switches ("Ada") use ("-gnat2022");
+   end Compiler;
+
+end Default;
diff --git a/src/cat.c b/src/cat.c
new file mode 100644
index 0000000..dfe7196
--- /dev/null
+++ b/src/cat.c
@@ -0,0 +1,116 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <getopt.h>
+#include <ctype.h>
+
+#include "blockdev.h"
+#include "vfs.h"
+
+extern void adainit (void);
+extern void adafinal (void);
+
+struct program_options {
+	char *devname;
+};
+
+static int get_options(int argc, char* argv[], struct program_options* opt);
+static void cat(int argc, char *argv[]);
+static void cat_file(const char *path);
+
+int main(int argc, char* argv[])
+{
+	struct program_options opt = { 0, };
+	int ret = -1;
+
+	adainit();
+
+	if (get_options(argc, argv, &opt)) {
+		goto final;
+	}
+
+	if (devopen(opt.devname, NULL) != 1) {
+		goto final;
+	}
+
+	cat(argc - optind, argv + optind);
+
+	devclose();
+	ret = 0;
+
+final:
+	adafinal();
+	return ret;
+}
+
+static void fprint_help(FILE* to, char * pname)
+{
+	fprintf(to, "Usage: %s\n"
+		"  -d | --dev <path> \t File to use as block device\n"
+		, pname);
+}
+
+static int get_options(int argc, char* argv[], struct program_options *opt){
+	const struct option long_options[] = {
+		{"dev", required_argument, NULL, 'd'},
+		{NULL, 0, NULL, 0},
+	};
+
+	int c, option_index = 0;
+	while ((c = getopt_long(argc, argv, "d:", long_options, &option_index)) != -1) {
+		switch (c) {
+		case 'd':
+			opt->devname = optarg;
+			break;
+		default:
+			fprint_help(stderr, argv[0]);
+			return -1;
+		}
+	}
+
+	if (argc == 1) {
+		fprintf(stderr, "%s needs arguments.\n", argv[0]);
+		fprint_help(stderr, argv[0]);
+		return -1;
+	}
+
+	if (opt->devname == NULL) {
+		fprintf(stderr, "Argument \"--dev/-d\" missing.\n");
+		return -1;
+	}
+	return 0;
+}
+
+static void cat(int argc, char *argv[])
+{
+	if (!mount_fs(NULL)) {
+		fprintf(stderr, "ERROR: Failed to mount FS.\n");
+		return;
+	}
+
+	for (; argc; --argc, ++argv)
+		cat_file(*argv);
+}
+
+static void cat_file(const char *path)
+{
+	if (!file_open(path)) {
+		fprintf(stderr, "ERROR: Failed to open `%s'.\n", path);
+		return;
+	}
+
+	unsigned char motd[1024];
+	int read;
+
+	do {
+		read = file_read(motd, sizeof(motd));
+		if (read > 0)
+			fwrite(motd, 1, read, stdout);
+	} while (read == sizeof(motd));
+	fflush(stdout);
+	file_close();
+
+	if (read < 0) {
+		fprintf(stderr, "ERROR: Failed to read from `%s'.\n", path);
+		return;
+	}
+}