Deploy the new <ctype.h> and `foocmp' macros from mLib.
[catacomb] / key / key-attr.c
CommitLineData
d11a0bf7 1/* -*-c-*-
2 *
d11a0bf7 3 * Key attribute manipulation
4 *
5 * (c) 1999 Straylight/Edgeware
6 */
7
45c0fd36 8/*----- Licensing notice --------------------------------------------------*
d11a0bf7 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.
45c0fd36 16 *
d11a0bf7 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.
45c0fd36 21 *
d11a0bf7 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
d11a0bf7 28/*----- Header files ------------------------------------------------------*/
29
30#include <ctype.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <time.h>
35
052b36d0 36#include <mLib/dstr.h>
141c1284 37#include <mLib/macros.h>
d11a0bf7 38#include <mLib/sym.h>
39
40#include "key.h"
41
42/*----- Main code ---------------------------------------------------------*/
43
44/* --- @key_chkident@ --- *
45 *
46 * Arguments: @const char *p@ = pointer to a type string
47 *
48 * Returns: Zero if OK, -1 on error.
49 *
50 * Use: Checks whether an identification component string is OK.
51 */
52
53int key_chkident(const char *p)
54{
981bf127 55 if (!p || !*p || strlen(p) > 255)
d11a0bf7 56 return (-1);
57 while (*p) {
141c1284 58 if (*p == ':' || *p == '.' || ISSPACE(*p))
d11a0bf7 59 return (-1);
60 p++;
61 }
62 return (0);
63}
64
65/* --- @key_chkcomment@ --- *
66 *
67 * Arguments: @const char *p@ = pointer to a comment string
68 *
69 * Returns: Zero if OK, -1 on error.
70 *
71 * Use: Checks whether a comment string is OK.
72 */
73
74int key_chkcomment(const char *p)
75{
76 if (!p)
77 return (0);
78 if (!*p)
79 return (-1);
80 while (*p) {
81 if (*p == '\n')
82 return (-1);
83 p++;
84 }
85 return (0);
86}
87
88/* --- @key_mkattriter@ --- *
89 *
90 * Arguments: @key_attriter *i@ = pointer to attribute iterator
91 * @key *k@ = pointer to key
92 *
93 * Returns: ---
94 *
95 * Use: Initializes an attribute iterator. The attributes are
96 * returned by @key_nextattr@.
97 */
98
99void key_mkattriter(key_attriter *i, key *k)
100{
101 sym_mkiter(&i->i, &k->a);
102}
103
104/* --- @key_nextattr@ --- *
105 *
106 * Arguments: @key_attriter *i@ = pointer to attribute iterator
107 * @const char **n, **v@ = pointers to name and value
108 *
109 * Returns: Zero if no attribute available, or nonzero if returned OK.
110 *
111 * Use: Returns the next attribute.
112 */
113
114int key_nextattr(key_attriter *i, const char **n, const char **v)
115{
116 key_attr *a = sym_next(&i->i);
117 if (!a)
118 return (0);
9c5a3dd8 119 if (n) *n = SYM_NAME(a);
120 if (v) *v = a->p;
d11a0bf7 121 return (1);
122}
123
124/* --- @key_getattr@ --- *
125 *
126 * Arguments: @key_file *f@ = pointer to file
127 * @key *k@ = pointer to key
128 * @const char *n@ = pointer to attribute name
129 *
130 * Returns: Pointer to attribute value, or null if not found.
131 *
132 * Use: Returns the value of a key attribute.
133 */
134
135const char *key_getattr(key_file *f, key *k, const char *n)
136{
137 key_attr *a;
138 if ((a = sym_find(&k->a, n, -1, 0, 0)) == 0)
139 return (0);
140 return (a->p);
141}
142
143/* --- @key_putattr@ --- *
144 *
145 * Arguments: @key_file *f@ = pointer to file
146 * @key *k@ = pointer to key
147 * @const char *n@ = pointer to attribute name
148 * @const char *v@ = pointer to attribute value or null
149 *
150 * Returns: Error code (one of the @KERR@ constants).
151 *
152 * Use: Inserts an attribute on a key. If an attribute with the same
153 * name already exists, it is deleted. Setting a null value
154 * removes the attribute.
155 */
156
157int key_putattr(key_file *f, key *k, const char *n, const char *v)
158{
159 key_attr *a;
160 unsigned found;
161
162 if (!(f->f & KF_WRITE))
163 return (KERR_READONLY);
981bf127 164 if (strlen(n) > 255)
165 return (KERR_BADATTR);
d11a0bf7 166
167 if (v) {
168 a = sym_find(&k->a, n, -1, sizeof(*a), &found);
169 if (found)
12ed8a1f 170 xfree(a->p);
d11a0bf7 171 a->p = xstrdup(v);
172 } else if ((a = sym_find(&k->a, n, -1, 0, 0)) != 0) {
12ed8a1f 173 xfree(a->p);
d11a0bf7 174 sym_remove(&k->a, a);
175 }
176
177 f->f |= KF_MODIFIED;
178 return (0);
179}
180
ef13e9a4 181/* --- @key_setkeydata@ --- *
182 *
183 * Arguments: @key_file *kf@ = pointer to key file
184 * @key *k@ = pointer to key
185 * @key_data *kd@ = new key data
186 *
187 * Returns: Zero on success, or a @KERR_@ error code on failure.
188 *
189 * Use: Sets the key data for a key.
190 */
191
192int key_setkeydata(key_file *kf, key *k, key_data *kd)
193{
194 if (!(kf->f & KF_WRITE))
195 return (KERR_READONLY);
ef13e9a4 196 key_incref(kd);
21dfa64d 197 key_drop(k->k);
ef13e9a4 198 k->k = kd;
199 kf->f |= KF_MODIFIED;
200 return (0);
201}
202
d11a0bf7 203/* --- @key_setcomment@ --- *
204 *
205 * Arguments: @key_file *f@ = pointer to key file block
206 * @key *k@ = pointer to key block
207 * @const char *c@ = pointer to comment to set, or zero
208 *
209 * Returns: Error code (one of the @KERR@ constants).
210 *
211 * Use: Replaces the key's current comment with a new one.
212 */
213
214int key_setcomment(key_file *f, key *k, const char *c)
215{
216 if (!(f->f & KF_WRITE))
217 return (KERR_READONLY);
218 if (key_chkcomment(c))
219 return (KERR_BADCOMMENT);
220 if (k->c)
12ed8a1f 221 xfree(k->c);
d11a0bf7 222 if (c)
223 k->c = xstrdup(c);
224 else
225 k->c = 0;
226 f->f |= KF_MODIFIED;
227 return (0);
228}
229
230/* --- @key_settag@ --- *
231 *
232 * Arguments: @key_file *f@ = pointer to key file block
233 * @key *k@ = pointer to key block
234 * @const char *tag@ = pointer to comment to set, or zero
235 *
236 * Returns: Error code (one of the @KERR@ constants).
237 *
238 * Use: Replaces the key's current tag with a new one.
239 */
240
241int key_settag(key_file *f, key *k, const char *tag)
242{
243 key_ref *kr;
244 unsigned found;
245
246 if (!(f->f & KF_WRITE))
247 return (KERR_READONLY);
248
249 /* --- Make sure the tag is OK --- */
250
251 if (tag && key_chkident(tag))
252 return (KERR_BADTAG);
253
254 /* --- See if the new tag is the same as the old one --- */
255
141c1284 256 if ((!tag && !k->tag) || (tag && k->tag && STRCMP(tag, ==, k->tag)))
d11a0bf7 257 return (0);
258
259 /* --- Allocate an entry for the new tag --- */
260
261 if (tag) {
262 kr = sym_find(&f->bytag, tag, -1, sizeof(*kr), &found);
8c0e800f 263 if (found && !KEY_EXPIRED(time(0), kr->k->del))
d11a0bf7 264 return (KERR_DUPTAG);
265 kr->k = k;
266 }
267
268 /* --- Remove any existing tag --- */
269
270 if (k->tag) {
271 kr = sym_find(&f->bytag, k->tag, -1, 0, 0);
272 assert(((void)"No bytag link", kr));
273 sym_remove(&f->bytag, kr);
12ed8a1f 274 xfree(k->tag);
d11a0bf7 275 }
276
277 /* --- Done --- */
278
279 f->f |= KF_MODIFIED;
280 if (tag)
281 k->tag = xstrdup(tag);
282 else
283 k->tag = 0;
284 return (0);
285}
286
287/* --- @key_fulltag@ --- *
288 *
289 * Arguments: @key *k@ = pointer to key
290 * @dstr *d@ = pointer to destination string
291 *
292 * Returns: ---
293 *
294 * Use: Emits the key's full tag, which has the form
295 * `ID:TYPE[:TAG]'. This is used in the textual file format,
296 * and to identify passphrases for locked keys.
297 */
298
299void key_fulltag(key *k, dstr *d)
300{
301 dstr_putf(d, "%08lx:%s", (unsigned long)k->id, k->type);
302 if (k->tag)
303 dstr_putf(d, ":%s", k->tag);
304}
305
306/*----- That's all, folks -------------------------------------------------*/