No empty .Rs/.Re
[netbsd-mini2440.git] / sbin / cgdconfig / utils.c
blobaff0b783807cb283e7f269c09206c33a86bd9a98
1 /* $NetBSD: utils.c,v 1.19 2008/05/11 03:15:21 elric Exp $ */
3 /*-
4 * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Roland C. Dowdeswell.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 #ifndef lint
34 __RCSID("$NetBSD: utils.c,v 1.19 2008/05/11 03:15:21 elric Exp $");
35 #endif
37 #include <sys/param.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <err.h>
42 #include <util.h>
44 /* include the resolver gunk in order that we can use b64 routines */
45 #include <netinet/in.h>
46 #include <arpa/nameser.h>
47 #include <resolv.h>
49 #include "utils.h"
52 /* just strsep(3), but skips empty fields. */
54 static char *
55 strsep_getnext(char **stringp, const char *delim)
57 char *ret;
59 ret = strsep(stringp, delim);
60 while (ret && index(delim, *ret))
61 ret = strsep(stringp, delim);
62 return ret;
66 * this function returns a dynamically sized char ** of the words
67 * in the line. the caller is responsible for both free(3)ing
68 * each word and the superstructure by calling words_free().
70 char **
71 words(const char *line, int *num)
73 int i = 0;
74 int nwords = 0;
75 char *cur;
76 char **ret;
77 const char *tmp;
78 char *tmp1, *tmpf;
80 *num = 0;
81 tmp = line;
82 if (tmp[0] == '\0')
83 return NULL;
84 while (tmp[0]) {
85 if ((tmp[1] == ' ' || tmp[1] == '\t' || tmp[1] == '\0') &&
86 (tmp[0] != ' ' && tmp[0] != '\t'))
87 nwords++;
88 tmp++;
90 ret = emalloc((nwords+1) * sizeof(char *));
91 tmp1 = tmpf = estrdup(line);
92 while ((cur = strsep_getnext(&tmpf, " \t")) != NULL)
93 ret[i++] = estrdup(cur);
94 ret[i] = NULL;
95 free(tmp1);
96 *num = nwords;
97 return ret;
100 void
101 words_free(char **w, int num)
103 int i;
105 for (i=0; i < num; i++)
106 free(w[i]);
110 * this is a simple xor that has the same calling conventions as
111 * memcpy(3).
114 void
115 memxor(void *res, const void *src, size_t len)
117 char *r;
118 const char *s;
119 size_t i;
121 r = res;
122 s = src;
123 for (i = 0; i < len; i++)
124 r[i] ^= s[i];
128 * well, a very simple set of string functions...
130 * The goal here is basically to manage length encoded strings,
131 * but just for safety we nul terminate them anyway.
134 /* for now we use a very simple encoding */
136 struct string {
137 char *text;
138 size_t length;
141 string_t *
142 string_zero()
144 string_t *out;
146 out = emalloc(sizeof(*out));
147 out->length = 0;
148 out->text = NULL;
149 return out;
152 string_t *
153 string_new(const char *intext, size_t inlength)
155 string_t *out;
157 out = emalloc(sizeof(*out));
158 out->length = inlength;
159 out->text = emalloc(out->length + 1);
160 (void)memcpy(out->text, intext, out->length);
161 out->text[out->length] = '\0';
162 return out;
165 string_t *
166 string_dup(const string_t *in)
169 return string_new(in->text, in->length);
172 void
173 string_free(string_t *s)
176 if (!s)
177 return;
178 free(s->text);
179 free(s);
182 void
183 string_assign(string_t **lhs, string_t *rhs)
186 string_free(*lhs);
187 *lhs = rhs;
190 string_t *
191 string_add(const string_t *a1, const string_t *a2)
193 string_t *sum;
195 sum = emalloc(sizeof(*sum));
196 sum->length = a1->length + a2->length;
197 sum->text = emalloc(sum->length + 1);
198 (void)memcpy(sum->text, a1->text, a1->length);
199 (void)memcpy(sum->text + a1->length, a2->text, a2->length);
200 sum->text[sum->length] = '\0';
201 return sum;
204 string_t *
205 string_add_d(string_t *a1, string_t *a2)
207 string_t *sum;
209 sum = string_add(a1, a2);
210 string_free(a1);
211 string_free(a2);
212 return sum;
215 string_t *
216 string_fromcharstar(const char *in)
219 return string_new(in, strlen(in));
222 const char *
223 string_tocharstar(const string_t *in)
226 return in->text;
229 string_t *
230 string_fromint(int in)
232 string_t *ret;
234 ret = emalloc(sizeof(*ret));
235 ret->length = asprintf(&ret->text, "%d", in);
236 if (ret->text == NULL)
237 err(1, NULL);
238 return ret;
241 void
242 string_fprint(FILE *f, const string_t *s)
244 (void)fwrite(s->text, s->length, 1, f);
247 struct bits {
248 size_t length;
249 char *text;
252 bits_t *
253 bits_new(const void *buf, size_t len)
255 bits_t *b;
257 b = emalloc(sizeof(*b));
258 b->length = len;
259 b->text = emalloc(BITS2BYTES(b->length));
260 (void)memcpy(b->text, buf, BITS2BYTES(b->length));
261 return b;
264 bits_t *
265 bits_dup(const bits_t *in)
268 return bits_new(in->text, in->length);
271 void
272 bits_free(bits_t *b)
275 if (!b)
276 return;
277 free(b->text);
278 free(b);
281 void
282 bits_assign(bits_t **lhs, bits_t *rhs)
285 bits_free(*lhs);
286 *lhs = rhs;
289 const void *
290 bits_getbuf(bits_t *in)
293 return in->text;
296 size_t
297 bits_len(bits_t *in)
300 return in->length;
304 bits_match(const bits_t *b1, const bits_t *b2)
306 size_t i;
308 if (b1->length != b2->length)
309 return 0;
311 for (i = 0; i < BITS2BYTES(b1->length); i++)
312 if (b1->text[i] != b2->text[i])
313 return 0;
315 return 1;
318 bits_t *
319 bits_xor(const bits_t *x1, const bits_t *x2)
321 bits_t *b;
322 size_t i;
324 b = emalloc(sizeof(*b));
325 b->length = MAX(x1->length, x2->length);
326 b->text = ecalloc(1, BITS2BYTES(b->length));
327 for (i=0; i < BITS2BYTES(MIN(x1->length, x2->length)); i++)
328 b->text[i] = x1->text[i] ^ x2->text[i];
329 return b;
332 bits_t *
333 bits_xor_d(bits_t *x1, bits_t *x2)
335 bits_t *ret;
337 ret = bits_xor(x1, x2);
338 bits_free(x1);
339 bits_free(x2);
340 return ret;
344 * bits_decode() reads an encoded base64 stream. We interpret
345 * the first 32 bits as an unsigned integer in network byte order
346 * specifying the number of bits in the stream to give a little
347 * resilience.
350 bits_t *
351 bits_decode(const string_t *in)
353 bits_t *ret;
354 size_t len;
355 size_t nbits;
356 u_int32_t *tmp;
358 len = in->length;
359 tmp = emalloc(len);
361 len = __b64_pton(in->text, (void *)tmp, len);
363 if (len == (size_t)-1) {
364 warnx("bits_decode: mangled base64 stream");
365 warnx(" %s", in->text);
366 free(tmp);
367 return NULL;
370 nbits = ntohl(*tmp);
371 if (nbits > (len - sizeof(*tmp)) * NBBY) {
372 warnx("bits_decode: encoded bits claim to be "
373 "longer than they are (nbits=%zu, stream len=%zu bytes)",
374 nbits, len);
375 free(tmp);
376 return NULL;
379 ret = bits_new(tmp + 1, nbits);
380 free(tmp);
381 return ret;
384 bits_t *
385 bits_decode_d(string_t *in)
387 bits_t *ret;
389 ret = bits_decode(in);
390 string_free(in);
391 return ret;
394 string_t *
395 bits_encode(const bits_t *in)
397 string_t *ret;
398 size_t len;
399 char *out;
400 u_int32_t *tmp;
402 if (!in)
403 return NULL;
405 /* compute the total size of the input stream */
406 len = BITS2BYTES(in->length) + sizeof(*tmp);
408 tmp = emalloc(len);
409 out = emalloc(len * 2);
410 /* stuff the length up front */
411 *tmp = htonl(in->length);
412 (void)memcpy(tmp + 1, in->text, len - sizeof(*tmp));
414 if ((len = __b64_ntop((void *)tmp, len, out, len * 2)) == (size_t)-1) {
415 free(out);
416 free(tmp);
417 return NULL;
419 ret = string_new(out, len);
420 free(tmp);
421 free(out);
422 return ret;
425 string_t *
426 bits_encode_d(bits_t *in)
428 string_t *ret;
430 ret = bits_encode(in);
431 bits_free(in);
432 return ret;
435 bits_t *
436 bits_fget(FILE *f, size_t len)
438 bits_t *bits;
439 int ret;
441 bits = emalloc(sizeof(*bits));
442 bits->length = len;
443 bits->text = emalloc(BITS2BYTES(bits->length));
444 ret = fread(bits->text, BITS2BYTES(bits->length), 1, f);
445 if (ret != 1) {
446 bits_free(bits);
447 return NULL;
449 return bits;
452 bits_t *
453 bits_cget(const char *fn, size_t len)
455 bits_t *bits;
456 FILE *f;
458 f = fopen(fn, "r");
459 if (!f)
460 return NULL;
462 bits = bits_fget(f, len);
463 (void)fclose(f);
464 return bits;
467 bits_t *
468 bits_getrandombits(size_t len, int hard)
471 return bits_cget((hard ? "/dev/random" : "/dev/urandom"), len);
474 void
475 bits_fprint(FILE *f, const bits_t *bits)
477 string_t *s;
479 s = bits_encode(bits);
480 string_fprint(f, s);
481 free(s);