summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/catcho.c204
-rw-r--r--tools/genhex.cpp33
-rw-r--r--tools/hexbin.c24
3 files changed, 261 insertions, 0 deletions
diff --git a/tools/catcho.c b/tools/catcho.c
new file mode 100644
index 0000000..3426e50
--- /dev/null
+++ b/tools/catcho.c
@@ -0,0 +1,204 @@
+/*
+ * catcho - outputing text to the standard output
+ *
+ * Usage
+ * -----
+ * catcho [options]
+ *
+ * Options
+ * -------
+ * -m --mode MODE Set the initial text mode (Default: passthrough)
+ * -v --version Display program information and exit
+ * -V --verbose Duplicate stdout on stderr
+ *
+ * Modes
+ * -----
+ * passthru / passthrough / normal / n - Input is copied to output verbatim.
+ * null / z - Input is dropped.
+ * hb - Input (interpreted as hex) is compressed to bytes on the output.
+ * bh - The opposite of hb.
+ * ib - Input (interpreted as bit-bytes) is compressed to bytes on the output.
+ * bi - The opposite of ib.
+ *
+ * Append 'f' to any mode (eg: bhf): Input is interpreted as '\n'-delimited
+ * filenames. File contents are filtered based on mode and sent to output.
+ *
+ * Switching modes
+ * ---------------
+ * When catcho receives signal SIGINT (ctrl-C from the terminal, for example),
+ * any pending input/output is flushed and catcho then interprets the input
+ * as a mode name terminated by a '\n'. Once the input provides a string\n,
+ * it switches the desired mode and input processing resumes.
+ *
+ * Exiting catcho
+ * --------------
+ * Since SIGINT is used for mode switching, the 'normal' way to terminate
+ * catcho is by sending it an End-Of-File byte on its input. (ctrl-D on your
+ * terminal)
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <signal.h>
+
+#define LAST_STR_CHAR(s) (s[strlen(s)-1])
+
+/* modes */
+enum mode
+{
+ N,
+ Z,
+ HB,
+ BH,
+ IB,
+ BI
+};
+
+/* global state */
+static enum mode current_mode = N;
+static int current_mode_f = 0;
+static int current_verbose = 0;
+
+static size_t ccfwrite(const void *ptr, size_t size, size_t nmemb)
+{
+ size_t ret;
+ ret = fwrite(ptr, size, nmemb, stdout);
+
+ if (current_verbose)
+ fwrite(ptr, size, nmemb, stderr);
+
+ return ret;
+}
+
+static void sigint(int sig)
+{
+ (void)sig;
+ ccfwrite("in signal handler\n", 18, 1);
+}
+
+static int set_mode(const char *mode)
+{
+ if (!mode)
+ return 0;
+
+ if (!strcmp(mode, "passthru") || // these don't support 'f' suffix
+ !strcmp(mode, "passthrough") ||
+ !strcmp(mode, "normal"))
+ {
+ current_mode = N;
+ current_mode_f = 0;
+ }
+ else if (!strcmp(mode, "null")) // this doesn't support 'f' suffix
+ {
+ current_mode = Z;
+ current_mode_f = 0;
+ }
+ else if (!strncmp(mode, "n", 1))
+ {
+ current_mode = N;
+ current_mode_f = (LAST_STR_CHAR(mode) == 'f');
+ }
+ else if (!strncmp(mode, "z", 1))
+ {
+ current_mode = Z;
+ current_mode_f = (LAST_STR_CHAR(mode) == 'f');
+ }
+ else if (!strncmp(mode, "hb", 2))
+ {
+ current_mode = HB;
+ current_mode_f = (LAST_STR_CHAR(mode) == 'f');
+ }
+ else if (!strncmp(mode, "bh", 2))
+ {
+ current_mode = BH;
+ current_mode_f = (LAST_STR_CHAR(mode) == 'f');
+ }
+ else if (!strncmp(mode, "ib", 2))
+ {
+ current_mode = IB;
+ current_mode_f = (LAST_STR_CHAR(mode) == 'f');
+ }
+ else if (!strncmp(mode, "bi", 2))
+ {
+ current_mode = BI;
+ current_mode_f = (LAST_STR_CHAR(mode) == 'f');
+ }
+ else
+ {
+ fprintf(stderr, "Mode string '%s' not recognized\n", mode);
+ return 0;
+ }
+
+ return 1;
+}
+
+void show_version(const char *name)
+{
+ printf("%s version 1.0\n", name);
+}
+
+int main(int argc, char **argv)
+{
+ /*
+ * handling command-line arguments:
+ * i'm going to leave opterr alone (defaults to non-zero)
+ * \this causes getopt to print its own error messages to
+ * stderr if things go wrong, which is fine.
+ */
+
+ const char *shortopts = "m:vV";
+
+ const struct option longopts[] = {
+ { "mode", required_argument, NULL, 'm' },
+ { "version", no_argument, NULL, 'v' },
+ { "verbose", no_argument, NULL, 'V' },
+ { NULL, 0, NULL, 0 }
+ };
+
+ int opt;
+
+ while ((opt = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1)
+ {
+ switch (opt)
+ {
+ case '?':
+ return 1;
+
+ case 'm':
+ if (!set_mode(optarg))
+ return 1;
+ break;
+
+ case 'v':
+ show_version(argv[0]);
+ return 0;
+
+ case 'V':
+ current_verbose = 1;
+ break;
+ }
+ }
+
+ /* setup signals (mode switch) */
+ signal(SIGINT, &sigint);
+
+
+ char memes[4];
+ fread(memes, 4, 1, stdin);
+ switch (current_mode)
+ {
+ case N: printf("NORMAL\n"); break;
+ case Z: printf("NULL\n"); break;
+ case HB: printf("hex to bytes\n"); break;
+ case BH: printf("bytes to hex\n"); break;
+ case IB: printf("bits to bytes\n"); break;
+ case BI: printf("bytes to bits\n"); break;
+ }
+
+ printf("file mode: %i\n", current_mode_f);
+ printf("verbose mode: %i\n", current_verbose);
+
+ return 0;
+}
diff --git a/tools/genhex.cpp b/tools/genhex.cpp
new file mode 100644
index 0000000..a37f91e
--- /dev/null
+++ b/tools/genhex.cpp
@@ -0,0 +1,33 @@
+#include <iostream>
+#include <string>
+
+/*
+ * Read in all of stdin (should be piped from objdump), look for bytecode hex,
+ * and print this code, escaped in a C-string literal, to stdout.
+ *
+ * EG output: "\x01\x02\x03\x04"
+ */
+
+int main()
+{
+ std::string tmp;
+ unsigned int hex;
+
+ std::cout << "\"";
+
+ while (true)
+ {
+ std::cin >> tmp;
+
+ if (std::cin.eof())
+ break;
+
+ if (tmp.size() == 2 &&
+ tmp.find(":") == std::string::npos &&
+ sscanf(tmp.c_str(), "%x", &hex) > 0)
+ std::cout << "\\x" << tmp;
+ }
+
+ std::cout << "\"\n";
+ return 0;
+}
diff --git a/tools/hexbin.c b/tools/hexbin.c
new file mode 100644
index 0000000..9356fff
--- /dev/null
+++ b/tools/hexbin.c
@@ -0,0 +1,24 @@
+/*
+ * hexbin.c
+ *
+ * This program takes no arguments, it simply interprets its input as hex
+ * and outputs bytes.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+
+int main()
+{
+ uint8_t b;
+
+ while (1)
+ {
+ scanf("%hhx", &b);
+ if (feof(stdin))
+ break;
+ fwrite(&b, 1, 1, stdout);
+ }
+
+ return 0;
+}