commit: 2a71881538c0c43d7c247221569262899280fdd4
parent:
author: Chris Noxz <chris@noxz.tech>
date: Thu, 27 Feb 2020 21:01:15 +0100
initial commit
4 files changed, 181 insertions(+)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,2 @@
+endrilo
+endrilo.o
diff --git a/Makefile b/Makefile
@@ -0,0 +1,37 @@
+.POSIX:
+
+include config.mk
+
+SRC = endrilo.c
+OBJ = $(SRC:.c=.o)
+
+all: options endrilo
+
+options:
+ @echo endrilo build options:
+ @echo "VERSION = $(VERSION)"
+ @echo "PREFIX = $(PREFIX)"
+ @echo "CFLAGS = $(STCFLAGS)"
+ @echo "CC = $(CC)"
+
+.c.o:
+ $(CC) $(STCFLAGS) -c $<
+
+$(OBJ): config.mk
+
+endrilo: $(OBJ)
+ $(CC) -o $@ $(OBJ) $(STCFLAGS)
+
+clean:
+ rm -f endrilo $(OBJ)
+
+install: endrilo
+ @echo installing executable to ${PREFIX}/bin
+ mkdir -p $(PREFIX)/bin
+ cp -f endrilo $(PREFIX)/bin
+ chmod 755 $(PREFIX)/bin/endrilo
+
+uninstall:
+ rm -f $(PREFIX)/bin/endrilo
+
+.PHONY: all options clean install uninstall
diff --git a/config.mk b/config.mk
@@ -0,0 +1,8 @@
+VERSION = 0.0.1
+
+PREFIX = /usr/local
+MANPREFIX = $(PREFIX)/share/man
+
+CFLAGS = -Wall -pedantic -std=c99
+CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600
+STCFLAGS = $(CPPFLAGS) $(CFLAGS)
diff --git a/endrilo.c b/endrilo.c
@@ -0,0 +1,134 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+
+static void print_octet(char, int, char);
+static void print_char(char, char, char);
+static void encode(void);
+static void decode(void);
+
+static const char *usage = "usage: endrilo [-dh]";
+static char working_char = 0;
+static char working_bit = 0;
+
+void
+print_octet(char octet, int o, char last)
+{
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ if (1U & (octet >> (i % 8)))
+ working_char |= 1U << ((o * 3 + i) % 8);
+ if ((o * 3 + i) % 8 == 7 || (i == 2 && last)) {
+ fputc(working_char, stdout);
+ working_char = 0;
+ }
+ }
+}
+
+void
+print_char(char count, char zero, char last)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if (!zero)
+ working_char |= 1U << working_bit;
+ if (working_bit++ == 7 || (i + 1 == count && last)) {
+ fputc(working_char, stdout);
+ working_char = 0;
+ working_bit = 0;
+ }
+ }
+}
+
+void
+encode(void)
+{
+ char input = 0;
+ char current = 0;
+ char last = 0;
+ int b, /* bit counter */
+ o, /* octet counter */
+ s; /* succession counter */
+
+ for (b = 0, o = 0, s = 0;; s++, b++) {
+ if (b == 8 || b == 0) {
+ input = fgetc(stdin);
+
+ /* last character, so print what's left */
+ if (feof(stdin)) {
+ print_octet(s, o++, 1);
+ break;
+ }
+ }
+ current = 1U & (input >> (b % 8));
+
+ if (current != last) {
+ do {
+ if (s > 7) {
+ print_octet(7, o++, 0);
+ print_octet(0, o++, 0);
+ } else {
+ print_octet(s, o++, 0);
+ }
+ s -= 7;
+ } while (s > 0);
+ last = current;
+ s = 0;
+ }
+
+ /* circulate counters */
+ if (o >= 8)
+ o %= 8;
+ if (b == 8)
+ b = 0;
+ }
+}
+
+void
+decode(void)
+{
+ char input = 0;
+ char current = 0;
+ char eof = 0;
+ int b, /* bit counter */
+ o; /* octet counter */
+
+ for (o = 0; !eof; current = 0, o++) {
+ for (b = 0; b < 3; b++) {
+ if ((o * 3 + b) % 8 == 0) {
+ input = fgetc(stdin);
+ if (feof(stdin)) {
+ eof = 1;
+ break;
+ }
+ }
+ current |= (1U & (input >> ((o * 3 + b) % 8))) << b;
+ }
+ print_char(current, o % 2 == 0, eof);
+
+ /* circulate counters */
+ if (o == 8)
+ o = 0;
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ char c;
+ int doencode = 1;
+
+ while ((c = getopt(argc, argv, "dh")) != -1) {
+ switch (c) {
+ case 'd': doencode = 0; break;
+ case 'h': printf(usage); exit(0); break;
+ }
+ }
+
+ if (doencode)
+ encode();
+ else
+ decode();
+}