1 /* $NetBSD: utils.c,v 1.19 2008/05/11 03:15:21 elric Exp $ */
4 * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
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
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>
34 __RCSID("$NetBSD: utils.c,v 1.19 2008/05/11 03:15:21 elric Exp $");
37 #include <sys/param.h>
44 /* include the resolver gunk in order that we can use b64 routines */
45 #include <netinet/in.h>
46 #include <arpa/nameser.h>
52 /* just strsep(3), but skips empty fields. */
55 strsep_getnext(char **stringp
, const char *delim
)
59 ret
= strsep(stringp
, delim
);
60 while (ret
&& index(delim
, *ret
))
61 ret
= strsep(stringp
, delim
);
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().
71 words(const char *line
, int *num
)
85 if ((tmp
[1] == ' ' || tmp
[1] == '\t' || tmp
[1] == '\0') &&
86 (tmp
[0] != ' ' && tmp
[0] != '\t'))
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
);
101 words_free(char **w
, int num
)
105 for (i
=0; i
< num
; i
++)
110 * this is a simple xor that has the same calling conventions as
115 memxor(void *res
, const void *src
, size_t len
)
123 for (i
= 0; i
< len
; 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 */
146 out
= emalloc(sizeof(*out
));
153 string_new(const char *intext
, size_t inlength
)
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';
166 string_dup(const string_t
*in
)
169 return string_new(in
->text
, in
->length
);
173 string_free(string_t
*s
)
183 string_assign(string_t
**lhs
, string_t
*rhs
)
191 string_add(const string_t
*a1
, const string_t
*a2
)
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';
205 string_add_d(string_t
*a1
, string_t
*a2
)
209 sum
= string_add(a1
, a2
);
216 string_fromcharstar(const char *in
)
219 return string_new(in
, strlen(in
));
223 string_tocharstar(const string_t
*in
)
230 string_fromint(int in
)
234 ret
= emalloc(sizeof(*ret
));
235 ret
->length
= asprintf(&ret
->text
, "%d", in
);
236 if (ret
->text
== NULL
)
242 string_fprint(FILE *f
, const string_t
*s
)
244 (void)fwrite(s
->text
, s
->length
, 1, f
);
253 bits_new(const void *buf
, size_t len
)
257 b
= emalloc(sizeof(*b
));
259 b
->text
= emalloc(BITS2BYTES(b
->length
));
260 (void)memcpy(b
->text
, buf
, BITS2BYTES(b
->length
));
265 bits_dup(const bits_t
*in
)
268 return bits_new(in
->text
, in
->length
);
282 bits_assign(bits_t
**lhs
, bits_t
*rhs
)
290 bits_getbuf(bits_t
*in
)
304 bits_match(const bits_t
*b1
, const bits_t
*b2
)
308 if (b1
->length
!= b2
->length
)
311 for (i
= 0; i
< BITS2BYTES(b1
->length
); i
++)
312 if (b1
->text
[i
] != b2
->text
[i
])
319 bits_xor(const bits_t
*x1
, const bits_t
*x2
)
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
];
333 bits_xor_d(bits_t
*x1
, bits_t
*x2
)
337 ret
= bits_xor(x1
, x2
);
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
351 bits_decode(const string_t
*in
)
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
);
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)",
379 ret
= bits_new(tmp
+ 1, nbits
);
385 bits_decode_d(string_t
*in
)
389 ret
= bits_decode(in
);
395 bits_encode(const bits_t
*in
)
405 /* compute the total size of the input stream */
406 len
= BITS2BYTES(in
->length
) + sizeof(*tmp
);
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) {
419 ret
= string_new(out
, len
);
426 bits_encode_d(bits_t
*in
)
430 ret
= bits_encode(in
);
436 bits_fget(FILE *f
, size_t len
)
441 bits
= emalloc(sizeof(*bits
));
443 bits
->text
= emalloc(BITS2BYTES(bits
->length
));
444 ret
= fread(bits
->text
, BITS2BYTES(bits
->length
), 1, f
);
453 bits_cget(const char *fn
, size_t len
)
462 bits
= bits_fget(f
, len
);
468 bits_getrandombits(size_t len
, int hard
)
471 return bits_cget((hard
? "/dev/random" : "/dev/urandom"), len
);
475 bits_fprint(FILE *f
, const bits_t
*bits
)
479 s
= bits_encode(bits
);