+/*----- Encoding and decoding commands ------------------------------------*/
+
+int cmd_encode(int argc, char *argv[])
+{
+ const char *fn, *of = 0;
+ FILE *ofp = 0;
+ FILE *fp = 0;
+ const char *ef = "binary";
+ const char *bd = "MESSAGE";
+ fprogress ff;
+ int i;
+ size_t n;
+ char buf[4096];
+ unsigned f = 0;
+ const encops *eo;
+ enc *e;
+
+#define f_bogus 1u
+#define f_progress 2u
+
+ for (;;) {
+ static const struct option opt[] = {
+ { "format", OPTF_ARGREQ, 0, 'f' },
+ { "boundary", OPTF_ARGREQ, 0, 'b' },
+ { "output", OPTF_ARGREQ, 0, 'o' },
+ { "progress", 0, 0, 'p' },
+ { 0, 0, 0, 0 }
+ };
+ i = mdwopt(argc, argv, "f:b:o:p", 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;
+ case 'p': f |= f_progress; 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);
+
+ fn = optind < argc ? argv[optind++] : "-";
+ if (strcmp(fn, "-") == 0)
+ fp = stdin;
+ else if ((fp = fopen(fn, "rb")) == 0) {
+ die(EXIT_FAILURE, "couldn't open file `%s': %s",
+ fn, strerror(errno));
+ }
+
+ 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);
+
+ if (f & f_progress) {
+ if (fprogress_init(&ff, fn, fp)) {
+ die(EXIT_FAILURE, "failed to initialize progress display: %s",
+ strerror(errno));
+ }
+ }
+
+ do {
+ n = fread(buf, 1, sizeof(buf), fp);
+ if (f & f_progress) fprogress_update(&ff, n);
+ if (e->ops->write(e, buf, n)) {
+ if (f & f_progress) fprogress_done(&ff);
+ die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
+ }
+ } while (n == sizeof(buf));
+ if (f & f_progress) fprogress_done(&ff);
+ e->ops->encdone(e);
+ freeenc(e);
+ return (0);
+
+#undef f_bogus
+#undef f_progress
+}
+
+int cmd_decode(int argc, char *argv[])
+{
+ const char *fn, *of = 0;
+ FILE *ofp = 0;
+ FILE *fp = 0;
+ const char *ef = "binary";
+ const char *bd = 0;
+ fprogress ff;
+ int i;
+ char buf[4096];
+ unsigned f = 0;
+ const encops *eo;
+ enc *e;
+
+#define f_bogus 1u
+#define f_progress 2u
+
+ for (;;) {
+ static const struct option opt[] = {
+ { "format", OPTF_ARGREQ, 0, 'f' },
+ { "boundary", OPTF_ARGREQ, 0, 'b' },
+ { "output", OPTF_ARGREQ, 0, 'o' },
+ { "progress", 0, 0, 'p' },
+ { 0, 0, 0, 0 }
+ };
+ i = mdwopt(argc, argv, "f:b:o:p", 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;
+ case 'p': f |= f_progress; 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);
+
+ fn = optind < argc ? argv[optind++] : "-";
+ if (strcmp(fn, "-") == 0)
+ fp = stdin;
+ else if ((fp = fopen(fn, eo->rmode)) == 0) {
+ die(EXIT_FAILURE, "couldn't open file `%s': %s",
+ fn, strerror(errno));
+ }
+
+ 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);
+
+ if (f & f_progress) {
+ if (fprogress_init(&ff, fn, fp)) {
+ die(EXIT_FAILURE, "failed to initialize progress display: %s",
+ strerror(errno));
+ }
+ }
+
+ do {
+ if ((i = e->ops->read(e, buf, sizeof(buf))) < 0) {
+ if (f & f_progress) fprogress_done(&ff);
+ die(EXIT_FAILURE, "error reading input: %s", strerror(errno));
+ }
+ if (f & f_progress)
+ fprogress_update(&ff, i*e->ops->ncook/e->ops->nraw);
+ if (fwrite(buf, 1, i, ofp) < i) {
+ if (f & f_progress) fprogress_done(&ff);
+ die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
+ }
+ } while (i == sizeof(buf));
+ e->ops->decdone(e);
+ if (f & f_progress) fprogress_done(&ff);
+ freeenc(e);
+ return (0);
+
+#undef f_bogus
+#undef f_progress
+}
+