--- /dev/null
+/* -*-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 -------------------------------------------------*/