uint32 k; /* Keyid */
} block;
-/* --- @getstring@ --- *
- *
- * Arguments: @FILE *fp@ = stream from which to read
- * @dstr *d@ = destination string
- * @unsigned raw@ = raw or cooked read
- *
- * Returns: Zero if OK, nonzero on end-of-file.
- *
- * Use: Reads a filename (or something similar) from a stream.
- */
-
-static int getstring(FILE *fp, dstr *d, unsigned raw)
-{
- int ch;
- int q = 0;
-
- /* --- Raw: just read exactly what's written up to a null byte --- */
-
- if (raw) {
- if ((ch = getc(fp)) == EOF)
- return (EOF);
- for (;;) {
- if (!ch)
- break;
- DPUTC(d, ch);
- if ((ch = getc(fp)) == EOF)
- break;
- }
- DPUTZ(d);
- return (0);
- }
-
- /* --- Skip as far as whitespace --- *
- *
- * Also skip past comments.
- */
-
-again:
- ch = getc(fp);
- while (isspace(ch))
- ch = getc(fp);
- if (ch == '#') {
- do ch = getc(fp); while (ch != '\n' && ch != EOF);
- goto again;
- }
- if (ch == EOF)
- return (EOF);
-
- /* --- If the character is a quote then read a quoted string --- */
-
- switch (ch) {
- case '`':
- ch = '\'';
- case '\'':
- case '\"':
- q = ch;
- ch = getc(fp);
- break;
- }
-
- /* --- Now read all sorts of interesting things --- */
-
- for (;;) {
-
- /* --- Handle an escaped thing --- */
-
- if (ch == '\\') {
- ch = getc(fp);
- if (ch == EOF)
- break;
- switch (ch) {
- case 'a': ch = '\a'; break;
- case 'b': ch = '\b'; break;
- case 'f': ch = '\f'; break;
- case 'n': ch = '\n'; break;
- case 'r': ch = '\r'; break;
- case 't': ch = '\t'; break;
- case 'v': ch = '\v'; break;
- }
- DPUTC(d, ch);
- ch = getc(fp);
- continue;
- }
-
- /* --- If it's a quote or some other end marker then stop --- */
-
- if (ch == q || (!q && isspace((unsigned char)ch)))
- break;
-
- /* --- Otherwise contribute and continue --- */
-
- DPUTC(d, ch);
- if ((ch = getc(fp)) == EOF)
- break;
- }
-
- /* --- Done --- */
-
- DPUTZ(d);
- return (0);
-}
-
-/* --- @putstring@ --- *
- *
- * Arguments: @FILE *fp@ = stream to write on
- * @const char *p@ = pointer to text
- * @unsigned raw@ = whether the string is to be written raw
- *
- * Returns: ---
- *
- * Use: Emits a string to a stream.
- */
-
-static void putstring(FILE *fp, const char *p, unsigned raw)
-{
- size_t sz = strlen(p);
- unsigned qq;
- const char *q;
-
- /* --- Just write the string null terminated if raw --- */
-
- if (raw) {
- fwrite(p, 1, sz + 1, fp);
- return;
- }
-
- /* --- Check for any dodgy characters --- */
-
- qq = 0;
- for (q = p; *q; q++) {
- if (isspace((unsigned char)*q)) {
- qq = '\"';
- break;
- }
- }
-
- if (qq)
- putc(qq, fp);
-
- /* --- Emit the string --- */
-
- for (q = p; *q; q++) {
- switch (*q) {
- case '\a': fputc('\\', fp); fputc('a', fp); break;
- case '\b': fputc('\\', fp); fputc('b', fp); break;
- case '\f': fputc('\\', fp); fputc('f', fp); break;
- case '\n': fputc('\\', fp); fputc('n', fp); break;
- case '\r': fputc('\\', fp); fputc('r', fp); break;
- case '\t': fputc('\\', fp); fputc('t', fp); break;
- case '\v': fputc('\\', fp); fputc('v', fp); break;
- case '`': fputc('\\', fp); fputc('`', fp); break;
- case '\'': fputc('\\', fp); fputc('\'', fp); break;
- case '\"': fputc('\\', fp); fputc('\"', fp); break;
- default:
- putc(*q, fp);
- break;
- }
- }
-
- /* --- Done --- */
-
- if (qq)
- putc(qq, fp);
-}
-
/* --- @timestring@ --- *
*
* Arguments: @time_t t@ = a timestamp
tag = getc(fp);
else {
dstr d = DSTR_INIT;
- if (getstring(fp, &d, 0))
+ if (getstring(fp, &d, GSF_FILE))
return (E_EOF);
for (tag = 0; tagtab[tag]; tag++) {
if (strcmp(tagtab[tag], d.buf) == 0)
case T_IDENT:
case T_COMMENT:
- if (getstring(fp, &b->d, bin))
+ if (getstring(fp, &b->d, GSF_FILE | (bin ? GSF_RAW : 0)))
return (E_EOF);
break;
b->t = ((time_t)(((LOAD32(buf + 0) << 16) << 16) & ~MASK32) |
(time_t)LOAD32(buf + 4));
} else {
- if (getstring(fp, &b->d, 0))
+ if (getstring(fp, &b->d, GSF_FILE))
return (E_EOF);
if (strcmp(b->d.buf, "forever") == 0)
b->t = KEXP_FOREVER;
return (E_EOF);
b->k = LOAD32(buf);
} else {
- if (getstring(fp, &b->d, 0))
+ if (getstring(fp, &b->d, GSF_FILE))
return (E_EOF);
b->k = strtoul(b->d.buf, 0, 16);
}
b->b.len += sz;
} else {
base64_ctx b64;
- if (getstring(fp, &b->d, 0))
+ if (getstring(fp, &b->d, GSF_FILE))
return (E_EOF);
base64_init(&b64);
base64_decode(&b64, b->d.buf, b->d.len, &b->b);
base64_decode(&b64, 0, 0, &b->b);
DRESET(&b->d);
}
- if (tag == T_FILE && getstring(fp, &b->d, bin))
+ if (tag == T_FILE &&
+ getstring(fp, &b->d, GSF_FILE | (bin ? GSF_RAW : 0)))
return (E_EOF);
break;
/*----- Other shared functions --------------------------------------------*/
-/* --- @fhash@ --- *
- *
- * Arguments: @const gchash *c@ = pointer to hash class
- * @unsigned f@ = flags
- * @const char *file@ = file to hash
- * @void *b@ = pointer to output buffer
- *
- * Returns: Zero if it worked, or nonzero for a system error.
- *
- * Use: Hashes a file.
- */
-
-#define FHF_PROGRESS 256u
-
-static int fhash(const gchash *c, unsigned f, const char *file, void *b)
-{
- FILE *fp = fopen(file, "rb");
- fprogress ff;
- ghash *h = GH_INIT(c);
- char buf[4096];
- size_t sz;
- int rc = 0;
-
- if (!fp)
- return (-1);
- if (f & FHF_PROGRESS) {
- if (fprogress_init(&ff, file, fp)) return (-1);
- }
- while ((sz = fread(buf, 1, sizeof(buf), fp)) > 0) {
- GH_HASH(h, buf, sz);
- if (f & FHF_PROGRESS) fprogress_update(&ff, sz);
- }
- if (ferror(fp))
- rc = -1;
- if (f & FHF_PROGRESS) fprogress_done(&ff);
- GH_DONE(h, b);
- GH_DESTROY(h);
- fclose(fp);
- return (rc);
-}
-
/* --- @fhex@ --- *
*
* Arguments: @FILE *fp@ = file to write on
static int sign(int argc, char *argv[])
{
-#define f_raw 1u
+#define f_bogus 1u
#define f_bin 2u
-#define f_bogus 4u
-#define f_nocheck 8u
+#define f_nocheck 4u
unsigned f = 0;
const char *ki = "dsig";
break;
switch (i) {
case '0':
- f |= f_raw;
+ f |= GSF_RAW;
break;
case 'b':
f |= f_bin;
/* --- Open files --- */
- if (!ifile)
+ if (!ifile || strcmp(ifile, "-") == 0)
ifp = stdin;
- else if ((ifp = fopen(ifile, (f & f_raw) ? "rb" : "r")) == 0) {
+ else if ((ifp = fopen(ifile, (f & f_bin) ? "rb" : "r")) == 0) {
die(EXIT_FAILURE, "couldn't open input file `%s': %s",
ifile, strerror(errno));
}
- if (!ofile)
+ if (!ofile || strcmp(ofile, "-") == 0)
ofp = stdout;
else if ((ofp = fopen(ofile, (f & f_bin) ? "wb" : "w")) == 0) {
die(EXIT_FAILURE, "couldn't open output file `%s': %s",
/* --- Read the next filename to hash --- */
breset(&b);
- if (getstring(ifp, &b.d, f & f_raw))
+ if (getstring(ifp, &b.d, GSF_FILE | f))
break;
b.tag = T_FILE;
DENSURE(&b.b, GH_CLASS(s->h)->hashsz);
- if (fhash(GH_CLASS(s->h), f, b.d.buf, b.b.buf)) {
+ if (fhash(GH_CLASS(s->h), f | FHF_BINARY, b.d.buf, b.b.buf)) {
moan("Error reading `%s': %s", b.d.buf, strerror(errno));
f |= f_bogus;
} else {
die(EXIT_FAILURE, "error(s) occurred while creating signature");
return (EXIT_SUCCESS);
-#undef f_raw
#undef f_bin
#undef f_bogus
#undef f_nocheck
case T_FILE:
DRESET(&d);
DENSURE(&d, GH_CLASS(s->h)->hashsz);
- if (fhash(GH_CLASS(s->h), f, b.d.buf, d.buf)) {
+ if (fhash(GH_CLASS(s->h), f | FHF_BINARY, b.d.buf, d.buf)) {
if (verb > 1) {
printf("BAD error reading file `%s': %s\n",
b.d.buf, strerror(errno));