Deploy the new <ctype.h> and `foocmp' macros from mLib.
[catacomb] / key / key-flags.c
1 /* -*-c-*-
2 *
3 * Reading and writing key flag strings
4 *
5 * (c) 1999 Straylight/Edgeware
6 */
7
8 /*----- Licensing notice --------------------------------------------------*
9 *
10 * This file is part of Catacomb.
11 *
12 * Catacomb is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
16 *
17 * Catacomb is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
21 *
22 * You should have received a copy of the GNU Library General Public
23 * License along with Catacomb; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 * MA 02111-1307, USA.
26 */
27
28 /*----- Header files ------------------------------------------------------*/
29
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include <mLib/bits.h>
34 #include <mLib/dstr.h>
35 #include <mLib/macros.h>
36
37 #include "key-data.h"
38
39 /*----- Data structures ---------------------------------------------------*/
40
41 typedef struct key_flags {
42 unsigned f;
43 unsigned m;
44 } key_flags;
45
46 /*----- Flags table -------------------------------------------------------*/
47
48 typedef struct flagent {
49 const char *name;
50 unsigned f;
51 unsigned m;
52 } flagent;
53
54 static const flagent flagtab[] = {
55
56 /* --- Encoding types --- */
57
58 { "binary", KENC_BINARY, KF_ENCMASK },
59 { "integer", KENC_MP, KF_ENCMASK },
60 { "struct", KENC_STRUCT, KF_ENCMASK },
61 { "encrypt", KENC_ENCRYPT, KF_ENCMASK },
62 { "string", KENC_STRING, KF_ENCMASK },
63 { "ec", KENC_EC, KF_ENCMASK },
64
65 /* --- Classes of keys --- */
66
67 { "shared", KCAT_SHARE, KF_CATMASK },
68 { "public", KCAT_PUB, KF_CATMASK },
69 { "private", KCAT_PRIV, KF_CATMASK },
70 { "symmetric", KCAT_SYMM, KF_CATMASK },
71 { "secret", 0, KF_NONSECRET },
72 { "-secret", KF_NONSECRET, KF_NONSECRET },
73
74 /* --- Other flags --- */
75
76 { "burn", KF_BURN, KF_BURN },
77 { "-burn", 0, KF_BURN },
78
79 /* --- End marker --- */
80
81 { 0, 0, 0 }
82 };
83
84 /*----- Main code ---------------------------------------------------------*/
85
86 /* --- @key_readflags@ --- *
87 *
88 * Arguments: @const char *p@ = pointer to string to read
89 * @char **pp@ = where to store the end pointer
90 * @unsigned *ff@ = where to store the flags
91 * @unsigned *mm@ = where to store the mask
92 *
93 * Returns: Zero if all went well, nonzero if there was an error.
94 *
95 * Use: Reads a flag string.
96 */
97
98 int key_readflags(const char *p, char **pp, unsigned *ff, unsigned *mm)
99 {
100 unsigned f = 0, m = 0;
101
102 for (;;) {
103 size_t sz = strcspn(p, ",:");
104 const flagent *e, *ee = 0;
105
106 /* --- Look up the string in the flags table --- */
107
108 if (sz == 4 && STRNCMP(p, ==, "none", 4))
109 goto next;
110 for (e = flagtab; e->name; e++) {
111 if (STRNCMP(e->name, ==, p, sz)) {
112 if (e->name[sz] == 0) {
113 ee = e;
114 break;
115 } else if (ee)
116 return (KERR_BADFLAGS);
117 else
118 ee = e;
119 }
120 }
121 if (!ee)
122 return (KERR_BADFLAGS);
123
124 /* --- Adjust the flag words --- *
125 *
126 * Ensure that the flags set are disjoint.
127 */
128
129 if (m & ee->m)
130 return (KERR_BADFLAGS);
131 m |= ee->m;
132 f |= ee->f;
133 next:
134 p += sz;
135 if (*p == 0 || *p == ':')
136 break;
137 p++;
138 }
139
140 /* --- Report the results --- */
141
142 if (ff) *ff = f;
143 if (mm) *mm = m;
144 if (pp) *pp = (char *)p;
145 return (0);
146 }
147
148 /* --- @key_writeflags@ --- *
149 *
150 * Arguments: @unsigned f@ = flags to write
151 * @dstr *d@ = pointer to destination string
152 *
153 * Returns: ---
154 *
155 * Use: Emits a flags word as a string representation.
156 */
157
158 void key_writeflags(unsigned f, dstr *d)
159 {
160 int del = 0;
161 const flagent *e;
162 unsigned m = 0;
163
164 for (e = flagtab; e->name; e++) {
165 if (m & e->m || e->name[0] == '-' || (f & e->m) != e->f)
166 continue;
167 if (del)
168 DPUTC(d, ',');
169 DPUTS(d, e->name);
170 m |= e->m;
171 del = 1;
172 }
173 }
174
175 /* --- @key_match@ --- *
176 *
177 * Arguments: @key_data *k@ = pointer to key data block
178 * @const key_filter *kf@ = pointer to filter block
179 *
180 * Returns: Nonzero if the key matches the filter.
181 *
182 * Use: Checks whether a key matches a filter.
183 */
184
185 int key_match(key_data *k, const key_filter *kf)
186 {
187 key_subkeyiter i;
188 const char *tag;
189 key_data *kd;
190
191 if (!kf)
192 return (1);
193 if ((k->e & KF_ENCMASK) != KENC_STRUCT)
194 return ((k->e & kf->m) == kf->f);
195
196 for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); ) {
197 if (key_match(kd, kf))
198 return (1);
199 }
200 return (0);
201 }
202
203 /*----- That's all, folks -------------------------------------------------*/