* (c) 2005 Straylight/Edgeware
*/
-/*----- Licensing notice --------------------------------------------------*
+/*----- Licensing notice --------------------------------------------------*
*
* This file is part of Catacomb.
*
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
- *
+ *
* Catacomb is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Library General Public
* License along with Catacomb; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
/*----- Header files ------------------------------------------------------*/
+#define _FILE_OFFSET_BITS 64
+
#include "config.h"
#include <ctype.h>
#define F_BUFFER 256u
#define F_UTC 512u
#define F_NOCHECK 1024u
+#define F_PROGRESS 2048u
/*----- Chunk I/O ---------------------------------------------------------*/
unsigned f;
FILE *fp;
enc *e;
+ fprogress ff;
size_t (*read)(struct msgcanon *, void *);
void (*write)(struct msgcanon *, const void *, size_t);
void (*close)(struct msgcanon *);
ungetc(ch, m->fp);
done:
m->f = f;
+ if (m->f & F_PROGRESS) fprogress_update(&m->ff, n);
return (n);
}
}
static size_t binreadembed(msgcanon *m, void *bp)
- { return (chunk_read(m->e, bp)); }
+{
+ size_t n = chunk_read(m->e, bp);
+ if (m->f & F_PROGRESS) fprogress_update(&m->ff, n);
+ return (n);
+}
+
static size_t binreaddetach(msgcanon *m, void *bp)
- { return (fread(bp, 1, MSGBUFSZ, m->fp)); }
+{
+ size_t n = fread(bp, 1, MSGBUFSZ - 1, m->fp);
+ if (m->f & F_PROGRESS) fprogress_update(&m->ff, n);
+ return (n);
+}
static void binwriteembed(msgcanon *m, const void *bp, size_t n)
{ chunk_write(m->e, bp, n); }
static void mcsetup_readfile(msgcanon *m, unsigned f, const char *fn)
{
- m->f = F_DETACH | (f & F_BINARY);
+ m->f = F_DETACH | (f & (F_BINARY | F_PROGRESS));
if (!fn || strcmp(fn, "-") == 0) {
m->fp = stdin;
m->f |= F_NOCLOSE;
} else if ((m->fp = fopen(fn, (f & F_BINARY) ? "rb" : "r")) == 0)
die(EXIT_FAILURE, "couldn't open file `%s': %s", fn, strerror(errno));
+ if (m->f & F_PROGRESS) {
+ if (fprogress_init(&m->ff, fn, m->fp)) {
+ die(EXIT_FAILURE, "failed to initialize progress indicator: %s",
+ strerror(errno));
+ }
+ }
m->read = (f & F_BINARY) ? binreaddetach : textread;
}
static void mcsetup_writenull(msgcanon *m) { m->write = nullwrite; }
-static void mcsetup_read(msgcanon *m, unsigned f, enc **ee, const char *dfn)
+static void mcsetup_read(msgcanon *m, unsigned f, enc **ee,
+ const char *fn, const char *dfn)
{
enc *e = *ee;
*ee = 0;
m->fp = e->fp;
m->read = binreadembed;
+ if (m->f & F_PROGRESS) {
+ if (fprogress_init(&m->ff, fn, m->fp)) {
+ die(EXIT_FAILURE, "failed to initialize progress indicator: %s",
+ strerror(errno));
+ }
+ }
} else {
m->read = binreaddetach;
if (!dfn || strcmp(dfn, "-") == 0)
die(EXIT_FAILURE, "can't open `%s': %s", dfn, strerror(errno));
else
m->f &= ~F_NOCLOSE;
+ if (m->f & F_PROGRESS) {
+ if (fprogress_init(&m->ff, dfn, m->fp)) {
+ die(EXIT_FAILURE, "failed to initialize progress indicator: %s",
+ strerror(errno));
+ }
+ }
}
} else {
m->read = textread;
m->fp = e->fp;
e->ops->destroy(e);
*ee = 0;
- } else if (!dfn || strcmp(dfn, "-") == 0)
- m->fp = stdin;
- else if ((m->fp = fopen(dfn, "r")) == 0)
- die(EXIT_FAILURE, "can't read file `%s': %s", dfn, strerror(errno));
- else
- m->f &= ~F_NOCLOSE;
+ if (m->f & F_PROGRESS) {
+ if (fprogress_init(&m->ff, fn, m->fp)) {
+ die(EXIT_FAILURE, "failed to initialize progress indicator: %s",
+ strerror(errno));
+ }
+ }
+ } else {
+ if (!dfn || strcmp(dfn, "-") == 0)
+ m->fp = stdin;
+ else if ((m->fp = fopen(dfn, "r")) == 0)
+ die(EXIT_FAILURE, "can't read file `%s': %s", dfn, strerror(errno));
+ else
+ m->f &= ~F_NOCLOSE;
+ if (m->f & F_PROGRESS) {
+ if (fprogress_init(&m->ff, dfn, m->fp)) {
+ die(EXIT_FAILURE, "failed to initialize progress indicator: %s",
+ strerror(errno));
+ }
+ }
+ }
}
}
if (m->fp && !(m->f & F_NOCLOSE)) {
if (ferror(m->fp) || fclose(m->fp))
die(EXIT_FAILURE, "error closing message file: %s", strerror(errno));
- }
+ }
+ if (m->f & F_PROGRESS) fprogress_done(&m->ff);
}
static void mc_endwrite(msgcanon *m, const encops *eops, enc **ee)
if (m->fp && !(m->f & F_NOCLOSE)) {
if (fflush(m->fp) || ferror(m->fp) || fclose(m->fp))
die(EXIT_FAILURE, "error closing message file: %s", strerror(errno));
- }
+ }
}
/*----- Signature reading and writing -------------------------------------*/
ghash *h;
key_filter kf;
- h = GH_INIT(GH_CLASS(s->h));
+ h = GH_INIT(s->ch);
kf.f = KCAT_PUB;
kf.m = KF_CATMASK;
key_fingerprint(k, h, &kf);
int i;
char bb[MSGBUFSZ];
size_t n;
- dstr d = DSTR_INIT;
+ dstr d = DSTR_INIT;
const encops *eo;
msgcanon mc_in = MC_INIT, mc_out = MC_INIT;
enc *e;
{ "key", OPTF_ARGREQ, 0, 'k' },
{ "format", OPTF_ARGREQ, 0, 'f' },
{ "output", OPTF_ARGREQ, 0, 'o' },
+ { "progress", 0, 0, 'p' },
{ "text", 0, 0, 't' },
{ "nocheck", 0, 0, 'C' },
{ 0, 0, 0, 0 }
};
- i = mdwopt(argc, argv, "k:f:o:abdtC", opt, 0, 0, 0);
+ i = mdwopt(argc, argv, "k:f:o:abdptC", opt, 0, 0, 0);
if (i < 0) break;
switch (i) {
case 'k': kn = optarg; break;
case 'b': f |= F_BINARY; break;
case 'd': f |= F_DETACH; break;
case 'C': f |= F_NOCHECK; break;
+ case 'p': f |= F_PROGRESS; break;
default: f |= F_BOGUS; break;
}
}
static int verify(int argc, char *argv[])
{
- const char *ef = "binary", *of = 0, *dfn = 0, *kn = 0, *err;
+ const char *ef = "binary", *of = 0, *fn, *dfn = 0, *kn = 0, *err;
vrfctx v = { 0, 0, 1 };
key_file kf;
key *k, *kk = 0;
sigmsg s;
FILE *fp, *ofp = 0, *rfp = 0;
+ fprogress ff;
struct tm *tm;
int i;
char bb[MSGBUFSZ];
{ "key", OPTF_ARGREQ, 0, 'k' },
{ "format", OPTF_ARGREQ, 0, 'f' },
{ "output", OPTF_ARGREQ, 0, 'o' },
+ { "progress", 0, 0, 'p' },
{ "quiet", 0, 0, 'q' },
{ "utc", 0, 0, 'u' },
{ "fresh-time", 0, 0, 't' },
{ "nocheck", 0, 0, 'C' },
{ 0, 0, 0, 0 }
};
- i = mdwopt(argc, argv, "k:f:o:abqt:uv", opt, 0, 0, 0);
+ i = mdwopt(argc, argv, "k:f:o:abpqt:uvC", opt, 0, 0, 0);
if (i < 0) break;
switch (i) {
case 'a': ef = "pem"; break;
case 'C': v.f |= F_NOCHECK; break;
case 't':
if (strcmp(optarg, "always") == 0) t_fresh = 0;
- else if ((t_fresh = get_date(optarg, 0)) < 0)
+ else if ((t_fresh = get_date(optarg, 0)) < 0)
die(EXIT_FAILURE, "bad freshness time");
break;
case 'q': if (v.verb > 0) v.verb--; break;
case 'v': if (v.verb < 10) v.verb++; break;
+ case 'p': v.f |= F_PROGRESS; break;
default: v.f |= F_BOGUS; break;
}
}
if ((eo = getenc(ef)) == 0)
die(EXIT_FAILURE, "encoding `%s' not found", ef);
- if (optind >= argc)
- fp = stdin;
- else if (strcmp(argv[optind], "-") == 0) {
+ fn = optind < argc ? argv[optind++] : "-";
+ if (strcmp(fn, "-") == 0)
fp = stdin;
- optind++;
- } else if ((fp = fopen(argv[optind], eo->rmode)) == 0) {
+ else if ((fp = fopen(fn, eo->rmode)) == 0) {
die(EXIT_FAILURE, "couldn't open file `%s': %s",
- argv[optind], strerror(errno));
- } else
- optind++;
+ fn, strerror(errno));
+ }
if (key_open(&kf, keyring, KOPEN_READ, key_moan, 0))
die(EXIT_FAILURE, "can't open keyring `%s'", keyring);
if (dd.len != s.kh.len || memcmp(dd.buf, s.kh.buf, dd.len) != 0) {
if (v.verb) printf("FAIL key hash mismatch\n");
exit(EXIT_FAILURE);
- }
+ }
/* --- Now a merry dance --- */
sig_readsig(e, &s);
if (optind < argc)
dfn = argv[optind++];
- mcsetup_read(&mc_in, v.f, &e, dfn);
+ mcsetup_read(&mc_in, v.f, &e, fn, dfn);
if (!of && (v.f & F_DETACH)) {
rfp = ofp = 0;
of, strerror(errno));
}
rewind(rfp);
+ if (v.f & F_PROGRESS) fprogress_init(&ff, "copying buffer", rfp);
if (v.verb && ofp == stdout) printf("DATA\n");
for (;;) {
n = fread(bb, 1, sizeof(bb), rfp);
if (!n) break;
- if (fwrite(bb, 1, n, ofp) < n)
+ if (v.f & F_PROGRESS) fprogress_update(&ff, n);
+ if (fwrite(bb, 1, n, ofp) < n) {
+ if (v.f & F_PROGRESS) fprogress_done(&ff);
die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
+ }
}
+ if (v.f & F_PROGRESS) fprogress_done(&ff);
if (ferror(rfp) || fclose(rfp))
die(EXIT_FAILURE, "error unbuffering output: %s", strerror(errno));
}
if (ofp && (fflush(ofp) || ferror(ofp) || fclose(ofp)))
- die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
+ die(EXIT_FAILURE, "error writing output: %s", strerror(errno));
/* --- Tidy up --- */
sig_destroy(&s);
dstr_destroy(&d);
dstr_destroy(&dd);
- return (0);
+ return (0);
}
/*----- Reformatting ------------------------------------------------------*/
static int format(int argc, char *argv[])
{
const char *ief = "binary", *oef = "binary";
- const char *dfn = 0, *of = 0, *mf = 0;
+ const char *fn, *dfn = 0, *of = 0, *mf = 0;
sigmsg s;
FILE *fp, *ofp = 0, *mfp = 0;
int i;
{ "embed", 0, 0, 'E' },
{ "format-in", OPTF_ARGREQ, 0, 'f' },
{ "format-out", OPTF_ARGREQ, 0, 'F' },
- { "message", OPTF_ARGREQ, 0, 'm' },
- { "output", OPTF_ARGREQ, 0, 'o' },
+ { "message", OPTF_ARGREQ, 0, 'm' },
+ { "output", OPTF_ARGREQ, 0, 'o' },
+ { "progress", 0, 0, 'p' },
{ 0, 0, 0, 0 }
};
- i = mdwopt(argc, argv, "f:F:m:o:aADE", opt, 0, 0, 0);
+ i = mdwopt(argc, argv, "f:F:m:o:apADE", opt, 0, 0, 0);
if (i < 0) break;
switch (i) {
case 'a': ief = "pem"; break;
case 'E': f &= ~F_DETACH; fm |= F_DETACH; break;
case 'm': mf = optarg; break;
case 'o': of = optarg; break;
+ case 'p': f |= F_PROGRESS; break;
default: f |= F_BOGUS; break;
}
}
if ((oeo = getenc(oef)) == 0)
die(EXIT_FAILURE, "encoding `%s' not found", oef);
- if (optind >= argc)
+ fn = optind < argc ? argv[optind++] : "-";
+ if (strcmp(fn, "-") == 0)
fp = stdin;
- else if (strcmp(argv[optind], "-") == 0) {
- fp = stdin;
- optind++;
- } else if ((fp = fopen(argv[optind], ieo->rmode)) == 0) {
+ else if ((fp = fopen(fn, ieo->rmode)) == 0) {
die(EXIT_FAILURE, "couldn't open file `%s': %s",
- argv[optind], strerror(errno));
- } else
- optind++;
+ fn, strerror(errno));
+ }
if (optind < argc)
dfn = argv[optind++];
if (((s.f ^ v.f) & v.m) != 0)
moan("boundary string inconsistent with contents (ignoring)");
-
- mcsetup_read(&mc_in, s.f, &ie, dfn);
+
+ mcsetup_read(&mc_in, s.f, &ie, fn, dfn);
/* --- Prepare the output stuff --- */
CMD_ENCODE,
CMD_DECODE,
{ "sign", sign,
- "sign [-adtC] [-k TAG] [-f FORMAT] [-o OUTPUT] [FILE]", "\
+ "sign [-adptC] [-k TAG] [-f FORMAT] [-o OUTPUT] [FILE]", "\
Options:\n\
\n\
-a, --armour Same as `-f pem'.\n\
-f, --format=FORMAT Encode as FORMAT.\n\
-k, --key=TAG Use public encryption key named by TAG.\n\
-o, --output=FILE Write output to FILE.\n\
+-p, --progress Show progress on large files.\n\
-t, --text Canonify input message as a text file.\n\
-C, --nocheck Don't check the private key.\n\
" },
{ "verify", verify,
- "verify [-abquvC] [-f FORMAT] [-k TAG] [-o OUTPUT]\n\t\
+ "verify [-abpquvC] [-f FORMAT] [-k TAG] [-o OUTPUT]\n\t\
[FILE [MESSAGE]]", "\
Options:\n\
\n\
-f, --format=FORMAT Decode as FORMAT.\n\
-k, --key=TAG Require that the message be signed by key TAG.\n\
-o, --output=FILE Write message to FILE.\n\
+-p, --progress Show progress on large files.\n\
-q, --quiet Produce fewer messages.\n\
-t, --freshtime=TIME Only accept signatures made after this time.\n\
-u, --utc Show dates in UTC rather than local time.\n\
-u, --utc Show dates in UTC rather than local time.\n\
"},
{ "format", format,
- "format [-auADE] [-f FORMAT] [-F format] [-m FILE] [-o FILE]\n\t\
+ "format [-apuADE] [-f FORMAT] [-F format] [-m FILE] [-o FILE]\n\t\
[FILE [MESSAGE]]", "\
Options:\n\
\n\
-F, --format-out=FORMAT Encode output as FORMAT.\n\
-m, --message=FILE Write message to FILE.\n\
-o, --output=FILE Write new signature to FILE.\n\
+-p, --progress Show progress on large files.\n\
"},
{ 0, 0, 0 }
}; /* " Emacs seems confused. */