/*----- Header files ------------------------------------------------------*/
+#include <errno.h>
#include <stdio.h>
#include <mLib/alloc.h>
#include <mLib/base64.h>
#include <mLib/dstr.h>
+#include <mLib/mdwopt.h>
#include <mLib/report.h>
#include <mLib/sub.h>
#include "cc.h"
+typedef int encbdryp(const char *, void *);
+
/*----- Main code ---------------------------------------------------------*/
/* --- Binary --- */
-static enc *bin_init(FILE *fp, const char *msg)
+static enc *bin_encinit(FILE *fp, const char *msg)
+ { enc *e = CREATE(enc); return (e); }
+static enc *bin_decinit(FILE *fp, encbdryp *func, void *p)
{ enc *e = CREATE(enc); return (e); }
static int bin_read(enc *e, void *p, size_t sz)
return (&pe->e);
}
-static enc *pem_decinit(FILE *fp, const char *msg)
+int checkbdry(const char *b, void *p) { return (!p || strcmp(b, p) == 0); }
+
+static enc *pem_decinit(FILE *fp, encbdryp *func, void *p)
{
char buf[128];
int i, d;
/* --- Check we have the right framing --- */
if (d != 5) goto top;
- if (strncmp(buf, "BEGIN ", 6) != 0 ||
- (msg && strcmp(buf + 6, msg) != 0))
+ if (strncmp(buf, "BEGIN ", 6) != 0 || (func && !func(buf + 6, p)))
goto top;
/* --- Ready --- */
const encops enctab[] = {
{ "binary", "rb", "wb",
- bin_init, bin_init,
+ bin_encinit, bin_decinit,
bin_read, bin_write,
bin_done, bin_done,
bin_destroy },
* Arguments: @const encops *eo@ = operations (from @getenc@)
* @FILE *fp@ = file handle to attach
* @const char *msg@ = banner message
- * @int wantenc@ = nonzero if we want to encode
*
* Returns: The encoder object.
*
* Use: Initializes an encoder.
*/
-enc *initenc(const encops *eo, FILE *fp, const char *msg, int wantenc)
+enc *initenc(const encops *eo, FILE *fp, const char *msg)
{
- enc *e = (wantenc ? eo->initenc : eo->initdec)(fp, msg);
+ enc *e = eo->initenc(fp, msg);
e->ops = eo;
e->fp = fp;
return (e);
}
+/* --- @initdec@ --- *
+ *
+ * Arguments: @const encops *eo@ = operations (from @getenc@)
+ * @FILE *fp@ = file handle to attach
+ * @int (*func)(const char *, void *)@ = banner check function
+ * @void *p@ = argument for @func@
+ *
+ * Returns: The encoder object.
+ *
+ * Use: Initializes an encoder.
+ */
+
+enc *initdec(const encops *eo, FILE *fp,
+ int (*func)(const char *, void *), void *p)
+{
+ enc *e = eo->initdec(fp, func, p);
+ e->ops = eo;
+ e->fp = fp;
+ return (e);
+}
+
/* --- @freeenc@ --- *
*
* Arguments: @enc *e@ = encoder object
void freeenc(enc *e) { e->ops->destroy(e); }
+/*----- Encoding and decoding commands ------------------------------------*/
+
+int cmd_encode(int argc, char *argv[])
+{
+ const char *of = 0;
+ FILE *ofp = 0;
+ FILE *fp = 0;
+ const char *ef = "binary";
+ const char *bd = "MESSAGE";
+ int i;
+ size_t n;
+ char buf[4096];
+ unsigned f = 0;
+ const encops *eo;
+ enc *e;
+
+#define f_bogus 1u
+
+ for (;;) {
+ static const struct option opt[] = {
+ { "format", OPTF_ARGREQ, 0, 'f' },
+ { "boundary", OPTF_ARGREQ, 0, 'b' },
+ { "output", OPTF_ARGREQ, 0, 'o' },
+ { 0, 0, 0, 0 }
+ };
+ i = mdwopt(argc, argv, "f:b:o:", opt, 0, 0, 0);
+ if (i < 0) break;
+ switch (i) {
+ case 'f': ef = optarg; break;
+ case 'b': bd = optarg; break;
+ case 'o': of = optarg; break;
+ default: f |= f_bogus; break;
+ }
+ }
+ if (argc - optind > 1 || (f & f_bogus))
+ die(EXIT_FAILURE, "Usage: encode [-OPTIONS] [FILE]");
+
+ if ((eo = getenc(ef)) == 0)
+ die(EXIT_FAILURE, "encoding `%s' not found", ef);
+
+ if (optind == argc)
+ fp = stdin;
+ else if (strcmp(argv[optind], "-") == 0) {
+ fp = stdin;
+ optind++;
+ } else if ((fp = fopen(argv[optind], "rb")) == 0) {
+ die(EXIT_FAILURE, "couldn't open file `%s': %s",
+ argv[optind], strerror(errno));
+ } else
+ optind++;
+
+ if (!of || strcmp(of, "-") == 0)
+ ofp = stdout;
+ else if ((ofp = fopen(of, eo->wmode)) == 0) {
+ die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
+ ofp, strerror(errno));
+ }
+
+ e = initenc(eo, ofp, bd);
+
+ do {
+ n = fread(buf, 1, sizeof(buf), fp);
+ if (e->ops->write(e, buf, n))
+ die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
+ } while (n == sizeof(buf));
+ e->ops->encdone(e);
+ freeenc(e);
+ return (0);
+
+#undef f_bogus
+}
+
+int cmd_decode(int argc, char *argv[])
+{
+ const char *of = 0;
+ FILE *ofp = 0;
+ FILE *fp = 0;
+ const char *ef = "binary";
+ const char *bd = 0;
+ int i;
+ char buf[4096];
+ unsigned f = 0;
+ const encops *eo;
+ enc *e;
+
+#define f_bogus 1u
+
+ for (;;) {
+ static const struct option opt[] = {
+ { "format", OPTF_ARGREQ, 0, 'f' },
+ { "boundary", OPTF_ARGREQ, 0, 'b' },
+ { "output", OPTF_ARGREQ, 0, 'o' },
+ { 0, 0, 0, 0 }
+ };
+ i = mdwopt(argc, argv, "f:b:o:", opt, 0, 0, 0);
+ if (i < 0) break;
+ switch (i) {
+ case 'f': ef = optarg; break;
+ case 'b': bd = optarg; break;
+ case 'o': of = optarg; break;
+ default: f |= f_bogus; break;
+ }
+ }
+ if (argc - optind > 1 || (f & f_bogus))
+ die(EXIT_FAILURE, "Usage: decode [-OPTIONS] [FILE]");
+
+ if ((eo = getenc(ef)) == 0)
+ die(EXIT_FAILURE, "encoding `%s' not found", ef);
+
+ if (optind == argc)
+ fp = stdin;
+ else if (strcmp(argv[optind], "-") == 0) {
+ fp = stdin;
+ optind++;
+ } else if ((fp = fopen(argv[optind], eo->rmode)) == 0) {
+ die(EXIT_FAILURE, "couldn't open file `%s': %s",
+ argv[optind], strerror(errno));
+ } else
+ optind++;
+
+ if (!of || strcmp(of, "-") == 0)
+ ofp = stdout;
+ else if ((ofp = fopen(of, "wb")) == 0) {
+ die(EXIT_FAILURE, "couldn't open file `%s' for output: %s",
+ ofp, strerror(errno));
+ }
+
+ e = initdec(eo, fp, checkbdry, (/*unconst*/ void *)bd);
+
+ do {
+ if ((i = e->ops->read(e, buf, sizeof(buf))) < 0)
+ die(EXIT_FAILURE, "error reading input: %s", strerror(errno));
+ if (fwrite(buf, 1, i, ofp) < i)
+ die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
+ } while (i == sizeof(buf));
+ e->ops->decdone(e);
+ freeenc(e);
+ return (0);
+
+#undef f_bogus
+}
+
/*----- That's all, folks -------------------------------------------------*/