1aaed0ba |
1 | /* -*-c-*- |
2 | * |
3 | * $Id: key-fetch.c,v 1.1 2000/06/17 10:42:54 mdw Exp $ |
4 | * |
5 | * Higher-level key unpacking |
6 | * |
7 | * (c) 2000 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 | /*----- Revision history --------------------------------------------------* |
31 | * |
32 | * $Log: key-fetch.c,v $ |
33 | * Revision 1.1 2000/06/17 10:42:54 mdw |
34 | * Convenient table-driven extraction of structured keys. |
35 | * |
36 | */ |
37 | |
38 | /*----- Header files ------------------------------------------------------*/ |
39 | |
40 | #include <mLib/dstr.h> |
41 | |
42 | #include "key.h" |
43 | #include "key-data.h" |
44 | |
45 | /*----- Main code ---------------------------------------------------------*/ |
46 | |
47 | /* --- @key_fetchinit@ --- * |
48 | * |
49 | * Arguments: @const key_fetchdef *kf@ = pointer to base definition |
50 | * @key_packstruct *kps@ = pointer to destination packing def |
51 | * @void *p@ = pointer to destination block |
52 | * |
53 | * Returns: Pointer to packing definition. |
54 | * |
55 | * Use: Initializes a packing definition (@key_packdef@ structure). |
56 | * If @kps@ is null on entry, an appropriately sized block is |
57 | * allocated automatically. Otherwise it must be large enough. |
58 | */ |
59 | |
60 | static size_t kfcount(const key_fetchdef *kf) |
61 | { |
62 | size_t n = 1; |
63 | while (kf->name) { |
64 | n++; |
65 | if (kf->kf) |
66 | n += kfcount(kf->kf); |
67 | kf++; |
68 | } |
69 | return (n); |
70 | } |
71 | |
72 | key_packdef *key_fetchinit(const key_fetchdef *kf, |
73 | key_packstruct *kp, void *p) |
74 | { |
75 | size_t n = 1 + kfcount(kf); |
76 | key_packdef *kpd; |
77 | key_packstruct *kps; |
78 | char *cp = p; |
79 | |
80 | /* --- If @kps@ is null, count the entries and allocate --- */ |
81 | |
82 | if (kp) |
83 | kp->name = 0; |
84 | else { |
85 | kp = xmalloc(n * sizeof(*kp)); |
86 | kp->name = (char *)kp; |
87 | } |
88 | |
89 | /* --- Fill in the top part --- */ |
90 | |
91 | kp->kp.kd.e = KENC_STRUCT; |
92 | kp->kp.p = &kp[1]; |
93 | kpd = &kp->kp; |
94 | |
95 | /* --- Initialize for the main loop --- */ |
96 | |
97 | kps = kp + n; |
98 | n = 0; |
99 | kp++; |
100 | |
101 | /* --- Iterate over the entries in the table --- * |
102 | * |
103 | * The end of the target block is used as a stack to record where |
104 | * substructure is meant to occur. The integer @n@ is the depth of the |
105 | * stack; @kps@ is a full descending stack pointer. The @kp.p@ member of a |
106 | * stack element points back to an entry with substructure, the @kp.p@ |
107 | * member of which refers to the @kf@ table for the substructure. |
108 | * |
109 | * This should all be about as clear as mud. |
110 | */ |
111 | |
112 | for (;;) { |
113 | |
114 | /* --- Blat out a level's worth --- */ |
115 | |
116 | while (kf->name) { |
117 | kp->name = kf->name; |
118 | kp->kp.kd.e = kf->e; |
119 | if ((kf->e & KF_ENCMASK) != KENC_STRUCT) |
120 | kp->kp.p = cp + kf->off; |
121 | else { |
122 | (--kps)->kp.p = kp; |
123 | kp->kp.p = (void *)kf->kf; |
124 | n++; |
125 | } |
126 | kf++; |
127 | kp++; |
128 | } |
129 | (kp++)->name = 0; |
130 | if (!n) |
131 | break; |
132 | |
133 | /* --- Pop an entry from the stack --- */ |
134 | |
135 | { |
136 | key_packstruct *kkp = (kps++)->kp.p; |
137 | kf = kkp->kp.p; |
138 | kkp->kp.p = kp; |
139 | n--; |
140 | } |
141 | } |
142 | |
143 | /* --- We're done --- */ |
144 | |
145 | return (kpd); |
146 | } |
147 | |
148 | /* --- @key_fetch@ --- * |
149 | * |
150 | * Arguments: @key_packdef *kp@ = pointer to packing structure |
151 | * @key *k@ = key file containing desired key |
152 | * |
153 | * Returns: Error code, or zero. |
154 | * |
155 | * Use: Fetches an unpacked key from a packed one. |
156 | */ |
157 | |
158 | int key_fetch(key_packdef *kp, key *k) |
159 | { |
160 | dstr d = DSTR_INIT; |
161 | int e; |
162 | |
163 | key_fulltag(k, &d); |
164 | e = key_unpack(kp, &k->k, &d); |
165 | dstr_destroy(&d); |
166 | return (e); |
167 | } |
168 | |
169 | /* --- @key_fetchbyname@ --- * |
170 | * |
171 | * Arguments: @key_packdef *kp@ = pointer to packing structure |
172 | * @key_file *kf@ = key file containing desired key |
173 | * @const char *tag@ = user's tag describing the key |
174 | * |
175 | * Returns: Error code, or zero. |
176 | * |
177 | * Use: Fetches a named key from a key file and unpacks it |
178 | * conveniently. |
179 | */ |
180 | |
181 | int key_fetchbyname(key_packdef *kp, key_file *kf, const char *tag) |
182 | { |
183 | dstr d = DSTR_INIT; |
184 | key_data *kd; |
185 | int e; |
186 | |
187 | if (key_qtag(kf, tag, &d, 0, &kd)) |
188 | e = KERR_NOTFOUND; |
189 | else |
190 | e = key_unpack(kp, kd, &d); |
191 | dstr_destroy(&d); |
192 | return (e); |
193 | } |
194 | |
195 | /* --- @key_fetchdone@ --- * |
196 | * |
197 | * Arguments: @key_packdef *kp@ = pointer to packing structure |
198 | * |
199 | * Returns: --- |
200 | * |
201 | * Use: Frees a packing structure. If the structure was allocated by |
202 | * @key_fetchinit@ then it is freed. |
203 | */ |
204 | |
205 | void key_fetchdone(key_packdef *kp) |
206 | { |
207 | key_packstruct *kps = (key_packstruct *)(((char *)kp) - |
208 | offsetof(key_packstruct, kp)); |
209 | key_unpackdone(kp); |
210 | if (kps->name) |
211 | free(kps); |
212 | } |
213 | |
214 | /*----- That's all, folks -------------------------------------------------*/ |