math/mpreduce.h: Missing include files.
[u/mdw/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>
d11a0bf7 37#include <mLib/sym.h>
38
39#include "key.h"
40
41/*----- Main code ---------------------------------------------------------*/
42
43/* --- @key_chkident@ --- *
44 *
45 * Arguments: @const char *p@ = pointer to a type string
46 *
47 * Returns: Zero if OK, -1 on error.
48 *
49 * Use: Checks whether an identification component string is OK.
50 */
51
52int key_chkident(const char *p)
53{
981bf127 54 if (!p || !*p || strlen(p) > 255)
d11a0bf7 55 return (-1);
56 while (*p) {
57 if (*p == ':' || *p == '.' || isspace((unsigned char)*p))
58 return (-1);
59 p++;
60 }
61 return (0);
62}
63
64/* --- @key_chkcomment@ --- *
65 *
66 * Arguments: @const char *p@ = pointer to a comment string
67 *
68 * Returns: Zero if OK, -1 on error.
69 *
70 * Use: Checks whether a comment string is OK.
71 */
72
73int key_chkcomment(const char *p)
74{
75 if (!p)
76 return (0);
77 if (!*p)
78 return (-1);
79 while (*p) {
80 if (*p == '\n')
81 return (-1);
82 p++;
83 }
84 return (0);
85}
86
87/* --- @key_mkattriter@ --- *
88 *
89 * Arguments: @key_attriter *i@ = pointer to attribute iterator
90 * @key *k@ = pointer to key
91 *
92 * Returns: ---
93 *
94 * Use: Initializes an attribute iterator. The attributes are
95 * returned by @key_nextattr@.
96 */
97
98void key_mkattriter(key_attriter *i, key *k)
99{
100 sym_mkiter(&i->i, &k->a);
101}
102
103/* --- @key_nextattr@ --- *
104 *
105 * Arguments: @key_attriter *i@ = pointer to attribute iterator
106 * @const char **n, **v@ = pointers to name and value
107 *
108 * Returns: Zero if no attribute available, or nonzero if returned OK.
109 *
110 * Use: Returns the next attribute.
111 */
112
113int key_nextattr(key_attriter *i, const char **n, const char **v)
114{
115 key_attr *a = sym_next(&i->i);
116 if (!a)
117 return (0);
9c5a3dd8 118 if (n) *n = SYM_NAME(a);
119 if (v) *v = a->p;
d11a0bf7 120 return (1);
121}
122
123/* --- @key_getattr@ --- *
124 *
125 * Arguments: @key_file *f@ = pointer to file
126 * @key *k@ = pointer to key
127 * @const char *n@ = pointer to attribute name
128 *
129 * Returns: Pointer to attribute value, or null if not found.
130 *
131 * Use: Returns the value of a key attribute.
132 */
133
134const char *key_getattr(key_file *f, key *k, const char *n)
135{
136 key_attr *a;
137 if ((a = sym_find(&k->a, n, -1, 0, 0)) == 0)
138 return (0);
139 return (a->p);
140}
141
142/* --- @key_putattr@ --- *
143 *
144 * Arguments: @key_file *f@ = pointer to file
145 * @key *k@ = pointer to key
146 * @const char *n@ = pointer to attribute name
147 * @const char *v@ = pointer to attribute value or null
148 *
149 * Returns: Error code (one of the @KERR@ constants).
150 *
151 * Use: Inserts an attribute on a key. If an attribute with the same
152 * name already exists, it is deleted. Setting a null value
153 * removes the attribute.
154 */
155
156int key_putattr(key_file *f, key *k, const char *n, const char *v)
157{
158 key_attr *a;
159 unsigned found;
160
161 if (!(f->f & KF_WRITE))
162 return (KERR_READONLY);
981bf127 163 if (strlen(n) > 255)
164 return (KERR_BADATTR);
d11a0bf7 165
166 if (v) {
167 a = sym_find(&k->a, n, -1, sizeof(*a), &found);
168 if (found)
12ed8a1f 169 xfree(a->p);
d11a0bf7 170 a->p = xstrdup(v);
171 } else if ((a = sym_find(&k->a, n, -1, 0, 0)) != 0) {
12ed8a1f 172 xfree(a->p);
d11a0bf7 173 sym_remove(&k->a, a);
174 }
175
176 f->f |= KF_MODIFIED;
177 return (0);
178}
179
ef13e9a4 180/* --- @key_setkeydata@ --- *
181 *
182 * Arguments: @key_file *kf@ = pointer to key file
183 * @key *k@ = pointer to key
184 * @key_data *kd@ = new key data
185 *
186 * Returns: Zero on success, or a @KERR_@ error code on failure.
187 *
188 * Use: Sets the key data for a key.
189 */
190
191int key_setkeydata(key_file *kf, key *k, key_data *kd)
192{
193 if (!(kf->f & KF_WRITE))
194 return (KERR_READONLY);
ef13e9a4 195 key_incref(kd);
21dfa64d 196 key_drop(k->k);
ef13e9a4 197 k->k = kd;
198 kf->f |= KF_MODIFIED;
199 return (0);
200}
201
d11a0bf7 202/* --- @key_setcomment@ --- *
203 *
204 * Arguments: @key_file *f@ = pointer to key file block
205 * @key *k@ = pointer to key block
206 * @const char *c@ = pointer to comment to set, or zero
207 *
208 * Returns: Error code (one of the @KERR@ constants).
209 *
210 * Use: Replaces the key's current comment with a new one.
211 */
212
213int key_setcomment(key_file *f, key *k, const char *c)
214{
215 if (!(f->f & KF_WRITE))
216 return (KERR_READONLY);
217 if (key_chkcomment(c))
218 return (KERR_BADCOMMENT);
219 if (k->c)
12ed8a1f 220 xfree(k->c);
d11a0bf7 221 if (c)
222 k->c = xstrdup(c);
223 else
224 k->c = 0;
225 f->f |= KF_MODIFIED;
226 return (0);
227}
228
229/* --- @key_settag@ --- *
230 *
231 * Arguments: @key_file *f@ = pointer to key file block
232 * @key *k@ = pointer to key block
233 * @const char *tag@ = pointer to comment to set, or zero
234 *
235 * Returns: Error code (one of the @KERR@ constants).
236 *
237 * Use: Replaces the key's current tag with a new one.
238 */
239
240int key_settag(key_file *f, key *k, const char *tag)
241{
242 key_ref *kr;
243 unsigned found;
244
245 if (!(f->f & KF_WRITE))
246 return (KERR_READONLY);
247
248 /* --- Make sure the tag is OK --- */
249
250 if (tag && key_chkident(tag))
251 return (KERR_BADTAG);
252
253 /* --- See if the new tag is the same as the old one --- */
254
255 if ((!tag && !k->tag) ||
256 (tag && k->tag && strcmp(tag, k->tag) == 0))
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 -------------------------------------------------*/