From 9b1fe95a8e6145758b8a4f560b05de52cfaf580c Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 26 May 2025 00:06:22 +0200 Subject: [PATCH] first commit --- .gitignore | 2 ++ Makefile | 13 ++++++++ input.c | 37 +++++++++++++++++++++ input.h | 15 +++++++++ main.c | 58 ++++++++++++++++++++++++++++++++ trans.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ trans.h | 12 +++++++ 7 files changed, 234 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 input.c create mode 100644 input.h create mode 100644 main.c create mode 100644 trans.c create mode 100644 trans.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b17b358 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +b64 +*.o diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a870852 --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +CFLAGS = -g -Wall -Wextra -Werror + +objects = main.o input.o trans.o + +b64 : $(objects) + cc -o b64 $(objects) + +main.o trans.o input.o : input.h +main.o trans.o : trans.h + +.PHONY : clean +clean : + rm -f b64 $(objects) diff --git a/input.c b/input.c new file mode 100644 index 0000000..855445a --- /dev/null +++ b/input.c @@ -0,0 +1,37 @@ +#include "input.h" + +#define OBUFSIZE 4 +#define SBUFSIZE 5 + +#define PADDING '=' + +unsigned char o[OBUFSIZE]; +unsigned char s[SBUFSIZE]; + +unsigned char * +getocts(FILE *fp, int *np) +{ + int n, c; + + n = 0; + while (n < OBUFSIZE-1 && (c = fgetc(fp)) != EOF) + o[n++] = c; + *np = n; + + return (*np) ? o : NULL; +} + +unsigned char * +getsxts(FILE *fp, int *np) +{ + int n, p, c; + + n = p = 0; + while (n < SBUFSIZE-1 && (c = fgetc(fp)) != EOF && c != PADDING) + s[n++] = c; + while (n+p < SBUFSIZE-1) + s[n+p++] = PADDING; + *np = n; + + return (n) ? s : NULL; +} diff --git a/input.h b/input.h new file mode 100644 index 0000000..178f17b --- /dev/null +++ b/input.h @@ -0,0 +1,15 @@ +#ifndef HEADER_INPUT +#define HEADER_INPUT + +#include + +extern unsigned char o[]; +extern unsigned char s[]; + +unsigned char * +getocts(FILE *fp, int *np); + +unsigned char * +getsxts(FILE *fp, int *np); + +#endif diff --git a/main.c b/main.c new file mode 100644 index 0000000..b657c99 --- /dev/null +++ b/main.c @@ -0,0 +1,58 @@ +#include +#include +#include "input.h" +#include "trans.h" + +int +main(int argc, char *argv[]) +{ + int c, n, dec, hlp; + char *prog = *argv; + unsigned char *b; + FILE *fp; + + dec = hlp = 0; + while (--argc > 0 && (*++argv)[0] == '-') + while ((c = *++argv[0])) + switch (c) { + case 'd': + dec = 1; + break; + case 'h': + hlp = 1; + break; + default: + fprintf(stderr, "%s: illegal option %c\n", prog, c); + exit(EXIT_FAILURE); + break; + } + if (hlp) { + fprintf(stdout, "Usage: %s -d -h file\n", prog); + } else if (argc != 1) { + if (dec) { + while ((b = getsxts(stdin, &n))) { + b = decode(b, &n); + fwrite(b, sizeof(*b), n, stdout); + } + } else { + while ((b = getocts(stdin, &n))) + printf("%s", encode(b, n)); + } + } else { + if ((fp = fopen(*argv, "r")) == NULL) { + fprintf(stderr, "%s: can't open %s\n", prog, *argv); + exit(EXIT_FAILURE); + } + else if (dec) { + while ((b = getsxts(fp, &n))) { + b = decode(b, &n); + fwrite(b, sizeof(*b), n, stdout); + } + } else { + while ((b = getocts(fp, &n))) + printf("%s", encode(b, n)); + } + fclose(fp); + } + exit(EXIT_SUCCESS); +} diff --git a/trans.c b/trans.c new file mode 100644 index 0000000..c29c576 --- /dev/null +++ b/trans.c @@ -0,0 +1,97 @@ +#include "trans.h" + +#define PADDING '=' + +unsigned char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ + "abcdefghijklmnopqrstuvwxyz" \ + "0123456789" \ + "+/"; + +unsigned char * +encode(unsigned char *op, int np) +{ + extern unsigned char s[]; + unsigned char *sp; + int n; + + sp = s; + switch (np) { + case 3: + *sp++ = b64[(*op & ~3) >> 2]; + n = (*op++ & 3) << 4; + *sp++ = b64[n + ((*op & ~15) >> 4)]; + n = (*op++ & 15) << 2; + *sp++ = b64[n + ((*op & 192) >> 6)]; + *sp = b64[*op & ~192]; + break; + case 2: + *sp++ = b64[(*op & ~3) >> 2]; + n = (*op++ & 3) << 4; + *sp++ = b64[n + ((*op & ~15) >> 4)]; + *sp++ = b64[(*op & 15) << 2]; + *sp = PADDING; + break; + case 1: + *sp++ = b64[(*op & ~3) >> 2]; + *sp++ = b64[(*op & 3) << 4]; + *sp++ = PADDING; + *sp = PADDING; + break; + } + + return s; +} + +unsigned char * +decode(unsigned char *sp, int *np) +{ + extern unsigned char o[]; + unsigned char *op; + int n, b, atob(int c); + + op = o; + switch (*np) { + case 4: + n = atob(*sp++) << 2; + b = atob(*sp++); + *op++ = n + ((b & ~15) >> 4); + + n = (b & 15) << 4; + b = atob(*sp++); + *op++ = n + ((b & ~3) >> 2); + + *op = ((b & 3) << 6) + atob(*sp); + break; + case 3: + n = atob(*sp++) << 2; + b = atob(*sp++); + *op++ = n + ((b & ~15) >> 4); + + n = (b & 15) << 4; + *op = n + ((atob(*sp) & ~3) >> 2); + break; + case 2: + n = atob(*sp++) << 2; + *op = n + ((atob(*sp) & ~15) >> 4); + break; + } + *np = op-o+1; + + return o; +} + +int atob(int c) +{ + if (c >= 'A' && c <= 'Z') + c -= 'A'; + else if (c >= 'a' && c <= 'z') + c = c - 'a' + 26; + else if (c >= '0' && c <= '9') + c = c - '0' + 26 * 2; + else if (c == '+') + c = 62; + else + c = 63; + + return c; +} diff --git a/trans.h b/trans.h new file mode 100644 index 0000000..845a2d2 --- /dev/null +++ b/trans.h @@ -0,0 +1,12 @@ +#ifndef HEADER_TRANS +#define HEADER_TRANS + +#include "input.h" + +unsigned char * +encode(unsigned char *op, int np); + +unsigned char * +decode(unsigned char *sp, int *np); + +#endif