Rearrange the file tree.
[u/mdw/catacomb] / key / key-flags.c
diff --git a/key/key-flags.c b/key/key-flags.c
new file mode 100644 (file)
index 0000000..169de2c
--- /dev/null
@@ -0,0 +1,202 @@
+/* -*-c-*-
+ *
+ * Reading and writing key flag strings
+ *
+ * (c) 1999 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * 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,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/dstr.h>
+
+#include "key-data.h"
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct key_flags {
+  unsigned f;
+  unsigned m;
+} key_flags;
+
+/*----- Flags table -------------------------------------------------------*/
+
+typedef struct flagent {
+  const char *name;
+  unsigned f;
+  unsigned m;
+} flagent;
+
+static const flagent flagtab[] = {
+
+  /* --- Encoding types --- */
+
+  { "binary",          KENC_BINARY,    KF_ENCMASK },
+  { "integer",         KENC_MP,        KF_ENCMASK },
+  { "struct",          KENC_STRUCT,    KF_ENCMASK },
+  { "encrypt",         KENC_ENCRYPT,   KF_ENCMASK },
+  { "string",          KENC_STRING,    KF_ENCMASK },
+  { "ec",              KENC_EC,        KF_ENCMASK },
+
+  /* --- Classes of keys --- */
+
+  { "shared",          KCAT_SHARE,     KF_CATMASK },
+  { "public",          KCAT_PUB,       KF_CATMASK },
+  { "private",         KCAT_PRIV,      KF_CATMASK },
+  { "symmetric",       KCAT_SYMM,      KF_CATMASK },
+  { "secret",          0,              KF_NONSECRET },
+  { "-secret",         KF_NONSECRET,   KF_NONSECRET },
+
+  /* --- Other flags --- */
+
+  { "burn",            KF_BURN,        KF_BURN },
+  { "-burn",           0,              KF_BURN },
+
+  /* --- End marker --- */
+
+  { 0,                 0,              0 }
+};
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @key_readflags@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to string to read
+ *             @char **pp@ = where to store the end pointer
+ *             @unsigned *ff@ = where to store the flags
+ *             @unsigned *mm@ = where to store the mask
+ *
+ * Returns:    Zero if all went well, nonzero if there was an error.
+ *
+ * Use:                Reads a flag string.
+ */
+
+int key_readflags(const char *p, char **pp, unsigned *ff, unsigned *mm)
+{
+  unsigned f = 0, m = 0;
+
+  for (;;) {
+    size_t sz = strcspn(p, ",:");
+    const flagent *e, *ee = 0;
+
+    /* --- Look up the string in the flags table --- */
+
+    if (sz == 4 && strncmp(p, "none", 4) == 0)
+      goto next;
+    for (e = flagtab; e->name; e++) {
+      if (strncmp(e->name, p, sz) == 0) {
+       if (e->name[sz] == 0) {
+         ee = e;
+         break;
+       } else if (ee)
+         return (KERR_BADFLAGS);
+       else
+         ee = e;
+      }
+    }
+    if (!ee)
+      return (KERR_BADFLAGS);
+
+    /* --- Adjust the flag words --- *
+     *
+     * Ensure that the flags set are disjoint.
+     */
+
+    if (m & ee->m)
+      return (KERR_BADFLAGS);
+    m |= ee->m;
+    f |= ee->f;
+  next:
+    p += sz;
+    if (*p == 0 || *p == ':')
+      break;
+    p++;
+  }
+
+  /* --- Report the results --- */
+
+  if (ff) *ff = f;
+  if (mm) *mm = m;
+  if (pp) *pp = (char *)p;
+  return (0);
+}
+
+/* --- @key_writeflags@ --- *
+ *
+ * Arguments:  @unsigned f@ = flags to write
+ *             @dstr *d@ = pointer to destination string
+ *
+ * Returns:    ---
+ *
+ * Use:                Emits a flags word as a string representation.
+ */
+
+void key_writeflags(unsigned f, dstr *d)
+{
+  int del = 0;
+  const flagent *e;
+  unsigned m = 0;
+
+  for (e = flagtab; e->name; e++) {
+    if (m & e->m || e->name[0] == '-' || (f & e->m) != e->f)
+      continue;
+    if (del)
+      DPUTC(d, ',');
+    DPUTS(d, e->name);
+    m |= e->m;
+    del = 1;
+  }
+}
+
+/* --- @key_match@ --- *
+ *
+ * Arguments:  @key_data *k@ = pointer to key data block
+ *             @const key_filter *kf@ = pointer to filter block
+ *
+ * Returns:    Nonzero if the key matches the filter.
+ *
+ * Use:                Checks whether a key matches a filter.
+ */
+
+int key_match(key_data *k, const key_filter *kf)
+{
+  key_subkeyiter i;
+  const char *tag;
+  key_data *kd;
+
+  if (!kf)
+    return (1);
+  if ((k->e & KF_ENCMASK) != KENC_STRUCT)
+    return ((k->e & kf->m) == kf->f);
+
+  for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); ) {
+    if (key_match(kd, kf))
+      return (1);
+  }
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/