endrilo

Implementation of the endrilo cipher in c
git clone https://noxz.tech/git/endrilo.git
Log | Files

endrilo.c
1#include <stdlib.h>
2#include <stdio.h>
3#include <getopt.h>
4
5static void print_octet(char, int, char);
6static void print_char(char, char, char);
7static void encode(void);
8static void decode(void);
9
10static const char *usage = "usage: endrilo [-dh]";
11static char working_char = 0;
12static char working_bit = 0;
13
14void
15print_octet(char octet, int o, char last)
16{
17    int i;
18
19    for (i = 0; i < 3; i++) {
20        if (1U & (octet >> (i % 8)))
21            working_char |= 1U << ((o * 3 + i) % 8);
22        if ((o * 3 + i) % 8 == 7 || (i == 2 && last)) {
23            fputc(working_char, stdout);
24            working_char = 0;
25        }
26    }
27}
28
29void
30print_char(char count, char zero, char last)
31{
32    int i;
33
34    for (i = 0; i < count; i++) {
35        if (!zero)
36            working_char |= 1U << working_bit;
37        if (working_bit++ == 7 || (i + 1 == count && last)) {
38            fputc(working_char, stdout);
39            working_char = 0;
40            working_bit = 0;
41        }
42    }
43}
44
45void
46encode(void)
47{
48    char input = 0;
49    char current = 0;
50    char last = 0;
51    int b, /* bit counter */
52        o, /* octet counter */
53        s; /* succession counter */
54
55    for (b = 0, o = 0, s = 0;; s++, b++) {
56        if (b == 8 || b == 0) {
57            input = fgetc(stdin);
58
59            /* last character, so print what's left */
60            if (feof(stdin)) {
61                print_octet(s, o++, 1);
62                break;
63            }
64        }
65        current = 1U & (input >> (b % 8));
66
67        if (current != last) {
68            do {
69                if (s > 7) {
70                    print_octet(7, o++, 0);
71                    print_octet(0, o++, 0);
72                } else {
73                    print_octet(s, o++, 0);
74                }
75                s -= 7;
76            } while (s > 0);
77            last = current;
78            s = 0;
79        }
80
81        /* circulate counters */
82        if (o >= 8)
83            o %= 8;
84        if (b == 8)
85            b = 0;
86    }
87}
88
89void
90decode(void)
91{
92    char input = 0;
93    char current = 0;
94    char eof = 0;
95    int b, /* bit counter */
96        o; /* octet counter */
97
98    for (o = 0; !eof; current = 0, o++) {
99        for (b = 0; b < 3; b++) {
100            if ((o * 3 + b) % 8 == 0) {
101                input = fgetc(stdin);
102                if (feof(stdin)) {
103                    eof = 1;
104                    break;
105                }
106            }
107            current |= (1U & (input >> ((o * 3 + b) % 8))) << b;
108        }
109        print_char(current, o % 2 == 0, eof);
110
111        /* circulate counters */
112        if (o == 8)
113            o = 0;
114    }
115}
116
117int
118main(int argc, char *argv[])
119{
120    char c;
121    int doencode = 1;
122
123    while ((c = getopt(argc, argv, "dh")) != -1) {
124         switch (c) {
125         case 'd': doencode = 0; break;
126         case 'h': printf("%s\n", usage); exit(0); break;
127         }
128    }
129
130    if (doencode)
131        encode();
132    else
133        decode();
134}