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