xref: /netbsd-src/sbin/cgdconfig/utils.c (revision cf7ed4c9cc7d1677cb423b89108b8d571974f460)
1*cf7ed4c9Smatt /* $NetBSD: utils.c,v 1.21 2012/03/20 18:50:30 matt Exp $ */
249ec72f4Selric 
349ec72f4Selric /*-
48c6033d2Selric  * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
549ec72f4Selric  * All rights reserved.
649ec72f4Selric  *
749ec72f4Selric  * This code is derived from software contributed to The NetBSD Foundation
849ec72f4Selric  * by Roland C. Dowdeswell.
949ec72f4Selric  *
1049ec72f4Selric  * Redistribution and use in source and binary forms, with or without
1149ec72f4Selric  * modification, are permitted provided that the following conditions
1249ec72f4Selric  * are met:
1349ec72f4Selric  * 1. Redistributions of source code must retain the above copyright
1449ec72f4Selric  *    notice, this list of conditions and the following disclaimer.
1549ec72f4Selric  * 2. Redistributions in binary form must reproduce the above copyright
1649ec72f4Selric  *    notice, this list of conditions and the following disclaimer in the
1749ec72f4Selric  *    documentation and/or other materials provided with the distribution.
1849ec72f4Selric  *
1949ec72f4Selric  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2049ec72f4Selric  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2149ec72f4Selric  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2249ec72f4Selric  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2349ec72f4Selric  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2449ec72f4Selric  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2549ec72f4Selric  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2649ec72f4Selric  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2749ec72f4Selric  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2849ec72f4Selric  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2949ec72f4Selric  * POSSIBILITY OF SUCH DAMAGE.
3049ec72f4Selric  */
3149ec72f4Selric 
3249ec72f4Selric #include <sys/cdefs.h>
3349ec72f4Selric #ifndef lint
34*cf7ed4c9Smatt __RCSID("$NetBSD: utils.c,v 1.21 2012/03/20 18:50:30 matt Exp $");
3549ec72f4Selric #endif
3649ec72f4Selric 
378c6033d2Selric #include <sys/param.h>
388c6033d2Selric 
398c6033d2Selric #include <stdlib.h>
4049ec72f4Selric #include <string.h>
41f8ce51d4Schristos #include <err.h>
422a1607d0Schristos #include <util.h>
4349ec72f4Selric 
448c6033d2Selric /* include the resolver gunk in order that we can use b64 routines */
458c6033d2Selric #include <netinet/in.h>
468c6033d2Selric #include <arpa/nameser.h>
478c6033d2Selric #include <resolv.h>
488c6033d2Selric 
4949ec72f4Selric #include "utils.h"
5049ec72f4Selric 
51f8ce51d4Schristos 
5249ec72f4Selric /* just strsep(3), but skips empty fields. */
5349ec72f4Selric 
5449ec72f4Selric static char *
strsep_getnext(char ** stringp,const char * delim)5549ec72f4Selric strsep_getnext(char **stringp, const char *delim)
5649ec72f4Selric {
5749ec72f4Selric 	char	*ret;
5849ec72f4Selric 
5949ec72f4Selric 	ret = strsep(stringp, delim);
6049ec72f4Selric 	while (ret && index(delim, *ret))
6149ec72f4Selric 		ret = strsep(stringp, delim);
6249ec72f4Selric 	return ret;
6349ec72f4Selric }
6449ec72f4Selric 
6549ec72f4Selric /*
6649ec72f4Selric  * this function returns a dynamically sized char ** of the words
6749ec72f4Selric  * in the line.  the caller is responsible for both free(3)ing
6849ec72f4Selric  * each word and the superstructure by calling words_free().
6949ec72f4Selric  */
7049ec72f4Selric char **
words(const char * line,int * num)7149ec72f4Selric words(const char *line, int *num)
7249ec72f4Selric {
7349ec72f4Selric 	int	  i = 0;
7449ec72f4Selric 	int	  nwords = 0;
7549ec72f4Selric 	char	 *cur;
7649ec72f4Selric 	char	**ret;
77cc9c2b57Schristos 	const char	 *tmp;
78cc9c2b57Schristos 	char	 *tmp1, *tmpf;
7949ec72f4Selric 
8049ec72f4Selric 	*num = 0;
81cc9c2b57Schristos 	tmp = line;
8249ec72f4Selric 	if (tmp[0] == '\0')
8349ec72f4Selric 		return NULL;
8449ec72f4Selric 	while (tmp[0]) {
8549ec72f4Selric 		if ((tmp[1] == ' ' || tmp[1] == '\t' || tmp[1] == '\0') &&
8649ec72f4Selric 		    (tmp[0] != ' ' && tmp[0] != '\t'))
8749ec72f4Selric 			nwords++;
8849ec72f4Selric 		tmp++;
8949ec72f4Selric 	}
90f8ce51d4Schristos 	ret = emalloc((nwords+1) * sizeof(char *));
91cc9c2b57Schristos 	tmp1 = tmpf = estrdup(line);
92cc9c2b57Schristos 	while ((cur = strsep_getnext(&tmpf, " \t")) != NULL)
93f8ce51d4Schristos 		ret[i++] = estrdup(cur);
9449ec72f4Selric 	ret[i] = NULL;
9549ec72f4Selric 	free(tmp1);
9649ec72f4Selric 	*num = nwords;
9749ec72f4Selric 	return ret;
9849ec72f4Selric }
9949ec72f4Selric 
10049ec72f4Selric void
words_free(char ** w,int num)10149ec72f4Selric words_free(char **w, int num)
10249ec72f4Selric {
10349ec72f4Selric 	int	i;
10449ec72f4Selric 
10549ec72f4Selric 	for (i=0; i < num; i++)
10649ec72f4Selric 		free(w[i]);
10749ec72f4Selric }
10849ec72f4Selric 
10949ec72f4Selric /*
11049ec72f4Selric  * this is a simple xor that has the same calling conventions as
11149ec72f4Selric  * memcpy(3).
11249ec72f4Selric  */
11349ec72f4Selric 
11449ec72f4Selric void
memxor(void * res,const void * src,size_t len)11549ec72f4Selric memxor(void *res, const void *src, size_t len)
11649ec72f4Selric {
11749ec72f4Selric 	char *r;
11849ec72f4Selric 	const char *s;
119b90361afScbiere 	size_t i;
12049ec72f4Selric 
12149ec72f4Selric 	r = res;
12249ec72f4Selric 	s = src;
12349ec72f4Selric 	for (i = 0; i < len; i++)
12449ec72f4Selric 		r[i] ^= s[i];
12549ec72f4Selric }
1268c6033d2Selric 
1278c6033d2Selric /*
1288c6033d2Selric  * well, a very simple set of string functions...
1298c6033d2Selric  *
1308c6033d2Selric  * The goal here is basically to manage length encoded strings,
1318c6033d2Selric  * but just for safety we nul terminate them anyway.
1328c6033d2Selric  */
1338c6033d2Selric 
1348c6033d2Selric /* for now we use a very simple encoding */
1358c6033d2Selric 
1368c6033d2Selric struct string {
1378c6033d2Selric 	char	*text;
138ad18d2e4Schristos 	size_t	 length;
1398c6033d2Selric };
1408c6033d2Selric 
1418c6033d2Selric string_t *
string_zero(void)142*cf7ed4c9Smatt string_zero(void)
14398059cd5Selric {
14498059cd5Selric 	string_t *out;
14598059cd5Selric 
14698059cd5Selric 	out = emalloc(sizeof(*out));
14798059cd5Selric 	out->length = 0;
14898059cd5Selric 	out->text = NULL;
14998059cd5Selric 	return out;
15098059cd5Selric }
15198059cd5Selric 
15298059cd5Selric string_t *
string_new(const char * intext,size_t inlength)153ad18d2e4Schristos string_new(const char *intext, size_t inlength)
1548c6033d2Selric {
1558c6033d2Selric 	string_t *out;
1568c6033d2Selric 
157f8ce51d4Schristos 	out = emalloc(sizeof(*out));
1588c6033d2Selric 	out->length = inlength;
159f8ce51d4Schristos 	out->text = emalloc(out->length + 1);
160ad18d2e4Schristos 	(void)memcpy(out->text, intext, out->length);
1618c6033d2Selric 	out->text[out->length] = '\0';
1628c6033d2Selric 	return out;
1638c6033d2Selric }
1648c6033d2Selric 
1658c6033d2Selric string_t *
string_dup(const string_t * in)1668c6033d2Selric string_dup(const string_t *in)
1678c6033d2Selric {
1688c6033d2Selric 
1698c6033d2Selric 	return string_new(in->text, in->length);
1708c6033d2Selric }
1718c6033d2Selric 
1728c6033d2Selric void
string_free(string_t * s)1738c6033d2Selric string_free(string_t *s)
1748c6033d2Selric {
1758c6033d2Selric 
1768c6033d2Selric 	if (!s)
1778c6033d2Selric 		return;
178f8ce51d4Schristos 	free(s->text);
1798c6033d2Selric 	free(s);
1808c6033d2Selric }
1818c6033d2Selric 
1828c6033d2Selric void
string_assign(string_t ** lhs,string_t * rhs)1838c6033d2Selric string_assign(string_t **lhs, string_t *rhs)
1848c6033d2Selric {
1858c6033d2Selric 
1868c6033d2Selric 	string_free(*lhs);
1878c6033d2Selric 	*lhs = rhs;
1888c6033d2Selric }
1898c6033d2Selric 
1908c6033d2Selric string_t *
string_add(const string_t * a1,const string_t * a2)1918c6033d2Selric string_add(const string_t *a1, const string_t *a2)
1928c6033d2Selric {
1938c6033d2Selric 	string_t *sum;
1948c6033d2Selric 
195f8ce51d4Schristos 	sum = emalloc(sizeof(*sum));
1968c6033d2Selric 	sum->length = a1->length + a2->length;
197f8ce51d4Schristos 	sum->text = emalloc(sum->length + 1);
198ad18d2e4Schristos 	(void)memcpy(sum->text, a1->text, a1->length);
199ad18d2e4Schristos 	(void)memcpy(sum->text + a1->length, a2->text, a2->length);
2008c6033d2Selric 	sum->text[sum->length] = '\0';
2018c6033d2Selric 	return sum;
2028c6033d2Selric }
2038c6033d2Selric 
2048c6033d2Selric string_t *
string_add_d(string_t * a1,string_t * a2)2058c6033d2Selric string_add_d(string_t *a1, string_t *a2)
2068c6033d2Selric {
2078c6033d2Selric 	string_t *sum;
2088c6033d2Selric 
2098c6033d2Selric 	sum = string_add(a1, a2);
2108c6033d2Selric 	string_free(a1);
2118c6033d2Selric 	string_free(a2);
2128c6033d2Selric 	return sum;
2138c6033d2Selric }
2148c6033d2Selric 
2158c6033d2Selric string_t *
string_fromcharstar(const char * in)2168c6033d2Selric string_fromcharstar(const char *in)
2178c6033d2Selric {
2188c6033d2Selric 
2198c6033d2Selric 	return string_new(in, strlen(in));
2208c6033d2Selric }
2218c6033d2Selric 
2228c6033d2Selric const char *
string_tocharstar(const string_t * in)2238c6033d2Selric string_tocharstar(const string_t *in)
2248c6033d2Selric {
2258c6033d2Selric 
2268c6033d2Selric 	return in->text;
2278c6033d2Selric }
2288c6033d2Selric 
2298c6033d2Selric string_t *
string_fromint(int in)2308c6033d2Selric string_fromint(int in)
2318c6033d2Selric {
2328c6033d2Selric 	string_t *ret;
2338c6033d2Selric 
234f8ce51d4Schristos 	ret = emalloc(sizeof(*ret));
2358c6033d2Selric 	ret->length = asprintf(&ret->text, "%d", in);
236ad18d2e4Schristos 	if (ret->text == NULL)
237f8ce51d4Schristos 		err(1, NULL);
2388c6033d2Selric 	return ret;
2398c6033d2Selric }
2408c6033d2Selric 
2418c6033d2Selric void
string_fprint(FILE * f,const string_t * s)2428c6033d2Selric string_fprint(FILE *f, const string_t *s)
2438c6033d2Selric {
244ad18d2e4Schristos 	(void)fwrite(s->text, s->length, 1, f);
2458c6033d2Selric }
2468c6033d2Selric 
2478c6033d2Selric struct bits {
248ad18d2e4Schristos 	size_t	 length;
2498c6033d2Selric 	char	*text;
2508c6033d2Selric };
2518c6033d2Selric 
2528c6033d2Selric bits_t *
bits_new(const void * buf,size_t len)253ad18d2e4Schristos bits_new(const void *buf, size_t len)
2548c6033d2Selric {
2558c6033d2Selric 	bits_t	*b;
2568c6033d2Selric 
257646d61aaSelric 	b = emalloc(sizeof(*b));
2588c6033d2Selric 	b->length = len;
259f8ce51d4Schristos 	b->text = emalloc(BITS2BYTES(b->length));
260ad18d2e4Schristos 	(void)memcpy(b->text, buf, BITS2BYTES(b->length));
2618c6033d2Selric 	return b;
2628c6033d2Selric }
2638c6033d2Selric 
2648c6033d2Selric bits_t *
bits_dup(const bits_t * in)2658c6033d2Selric bits_dup(const bits_t *in)
2668c6033d2Selric {
2678c6033d2Selric 
2688c6033d2Selric 	return bits_new(in->text, in->length);
2698c6033d2Selric }
2708c6033d2Selric 
2718c6033d2Selric void
bits_free(bits_t * b)2728c6033d2Selric bits_free(bits_t *b)
2738c6033d2Selric {
2748c6033d2Selric 
2758c6033d2Selric 	if (!b)
2768c6033d2Selric 		return;
277f8ce51d4Schristos 	free(b->text);
2788c6033d2Selric 	free(b);
2798c6033d2Selric }
2808c6033d2Selric 
2818c6033d2Selric void
bits_assign(bits_t ** lhs,bits_t * rhs)2828c6033d2Selric bits_assign(bits_t **lhs, bits_t *rhs)
2838c6033d2Selric {
2848c6033d2Selric 
2858c6033d2Selric 	bits_free(*lhs);
2868c6033d2Selric 	*lhs = rhs;
2878c6033d2Selric }
2888c6033d2Selric 
2898c6033d2Selric const void *
bits_getbuf(bits_t * in)2908c6033d2Selric bits_getbuf(bits_t *in)
2918c6033d2Selric {
2928c6033d2Selric 
2938c6033d2Selric 	return in->text;
2948c6033d2Selric }
2958c6033d2Selric 
296ad18d2e4Schristos size_t
bits_len(bits_t * in)2978c6033d2Selric bits_len(bits_t *in)
2988c6033d2Selric {
2998c6033d2Selric 
3008c6033d2Selric 	return in->length;
3018c6033d2Selric }
3028c6033d2Selric 
3037543b55cScb int
bits_match(const bits_t * b1,const bits_t * b2)3047543b55cScb bits_match(const bits_t *b1, const bits_t *b2)
3057543b55cScb {
306002fe605Slukem 	size_t i;
3077543b55cScb 
3087543b55cScb 	if (b1->length != b2->length)
3097543b55cScb 		return 0;
3107543b55cScb 
3117543b55cScb 	for (i = 0; i < BITS2BYTES(b1->length); i++)
3127543b55cScb 		if (b1->text[i] != b2->text[i])
3137543b55cScb 			return 0;
3147543b55cScb 
3157543b55cScb 	return 1;
3167543b55cScb }
3177543b55cScb 
3188c6033d2Selric bits_t *
bits_xor(const bits_t * x1,const bits_t * x2)3198c6033d2Selric bits_xor(const bits_t *x1, const bits_t *x2)
3208c6033d2Selric {
3218c6033d2Selric 	bits_t	*b;
322002fe605Slukem 	size_t	 i;
3238c6033d2Selric 
324f8ce51d4Schristos 	b = emalloc(sizeof(*b));
3258c6033d2Selric 	b->length = MAX(x1->length, x2->length);
326f8ce51d4Schristos 	b->text = ecalloc(1, BITS2BYTES(b->length));
3278c6033d2Selric 	for (i=0; i < BITS2BYTES(MIN(x1->length, x2->length)); i++)
3288c6033d2Selric 		b->text[i] = x1->text[i] ^ x2->text[i];
3298c6033d2Selric 	return b;
3308c6033d2Selric }
3318c6033d2Selric 
3328c6033d2Selric bits_t *
bits_xor_d(bits_t * x1,bits_t * x2)3338c6033d2Selric bits_xor_d(bits_t *x1, bits_t *x2)
3348c6033d2Selric {
3358c6033d2Selric 	bits_t	*ret;
3368c6033d2Selric 
3378c6033d2Selric 	ret = bits_xor(x1, x2);
3388c6033d2Selric 	bits_free(x1);
3398c6033d2Selric 	bits_free(x2);
3408c6033d2Selric 	return ret;
3418c6033d2Selric }
3428c6033d2Selric 
3438c6033d2Selric /*
3448c6033d2Selric  * bits_decode() reads an encoded base64 stream.  We interpret
3458c6033d2Selric  * the first 32 bits as an unsigned integer in network byte order
3468c6033d2Selric  * specifying the number of bits in the stream to give a little
3478c6033d2Selric  * resilience.
3488c6033d2Selric  */
3498c6033d2Selric 
3508c6033d2Selric bits_t *
bits_decode(const string_t * in)3518c6033d2Selric bits_decode(const string_t *in)
3528c6033d2Selric {
3538c6033d2Selric 	bits_t	*ret;
354ad18d2e4Schristos 	size_t	 len;
355ad18d2e4Schristos 	size_t	 nbits;
356ad18d2e4Schristos 	u_int32_t	*tmp;
3578c6033d2Selric 
3588c6033d2Selric 	len = in->length;
359f8ce51d4Schristos 	tmp = emalloc(len);
3608c6033d2Selric 
361ad18d2e4Schristos 	len = __b64_pton(in->text, (void *)tmp, len);
3628c6033d2Selric 
363ad18d2e4Schristos 	if (len == (size_t)-1) {
364ad18d2e4Schristos 		warnx("bits_decode: mangled base64 stream");
365ad18d2e4Schristos 		warnx("  %s", in->text);
366bd5a805fSchristos 		free(tmp);
3678c6033d2Selric 		return NULL;
3688c6033d2Selric 	}
3698c6033d2Selric 
370ad18d2e4Schristos 	nbits = ntohl(*tmp);
371ad18d2e4Schristos 	if (nbits > (len - sizeof(*tmp)) * NBBY) {
372ad18d2e4Schristos 		warnx("bits_decode: encoded bits claim to be "
373ad18d2e4Schristos 		    "longer than they are (nbits=%zu, stream len=%zu bytes)",
374ad18d2e4Schristos 		    nbits, len);
375bd5a805fSchristos 		free(tmp);
3768c6033d2Selric 		return NULL;
3778c6033d2Selric 	}
3788c6033d2Selric 
379ad18d2e4Schristos 	ret = bits_new(tmp + 1, nbits);
3808c6033d2Selric 	free(tmp);
3818c6033d2Selric 	return ret;
3828c6033d2Selric }
3838c6033d2Selric 
3848c6033d2Selric bits_t *
bits_decode_d(string_t * in)3858c6033d2Selric bits_decode_d(string_t *in)
3868c6033d2Selric {
3878c6033d2Selric 	bits_t *ret;
3888c6033d2Selric 
3898c6033d2Selric 	ret = bits_decode(in);
3908c6033d2Selric 	string_free(in);
3918c6033d2Selric 	return ret;
3928c6033d2Selric }
3938c6033d2Selric 
3948c6033d2Selric string_t *
bits_encode(const bits_t * in)3958c6033d2Selric bits_encode(const bits_t *in)
3968c6033d2Selric {
3978c6033d2Selric 	string_t *ret;
398ad18d2e4Schristos 	size_t	 len;
3998c6033d2Selric 	char	*out;
400ad18d2e4Schristos 	u_int32_t *tmp;
4018c6033d2Selric 
4028c6033d2Selric 	if (!in)
4038c6033d2Selric 		return NULL;
4048c6033d2Selric 
4058c6033d2Selric 	/* compute the total size of the input stream */
406ad18d2e4Schristos 	len = BITS2BYTES(in->length) + sizeof(*tmp);
4078c6033d2Selric 
408f8ce51d4Schristos 	tmp = emalloc(len);
409f8ce51d4Schristos 	out = emalloc(len * 2);
4108c6033d2Selric 	/* stuff the length up front */
411ad18d2e4Schristos 	*tmp = htonl(in->length);
412ad18d2e4Schristos 	(void)memcpy(tmp + 1, in->text, len - sizeof(*tmp));
4138c6033d2Selric 
414ad18d2e4Schristos 	if ((len = __b64_ntop((void *)tmp, len, out, len * 2)) == (size_t)-1) {
415fbdfb6fbSchristos 		free(out);
41625207a23Schristos 		free(tmp);
41725207a23Schristos 		return NULL;
41825207a23Schristos 	}
4198c6033d2Selric 	ret = string_new(out, len);
4208c6033d2Selric 	free(tmp);
4218c6033d2Selric 	free(out);
4228c6033d2Selric 	return ret;
4238c6033d2Selric }
4248c6033d2Selric 
4258c6033d2Selric string_t *
bits_encode_d(bits_t * in)4268c6033d2Selric bits_encode_d(bits_t *in)
4278c6033d2Selric {
4288c6033d2Selric 	string_t *ret;
4298c6033d2Selric 
4308c6033d2Selric 	ret = bits_encode(in);
4318c6033d2Selric 	bits_free(in);
4328c6033d2Selric 	return ret;
4338c6033d2Selric }
4348c6033d2Selric 
4358c6033d2Selric bits_t *
bits_fget(FILE * f,size_t len)436ad18d2e4Schristos bits_fget(FILE *f, size_t len)
4378c6033d2Selric {
4388c6033d2Selric 	bits_t	*bits;
4398c6033d2Selric 	int	 ret;
4408c6033d2Selric 
441f8ce51d4Schristos 	bits = emalloc(sizeof(*bits));
4428c6033d2Selric 	bits->length = len;
443f8ce51d4Schristos 	bits->text = emalloc(BITS2BYTES(bits->length));
4448c6033d2Selric 	ret = fread(bits->text, BITS2BYTES(bits->length), 1, f);
4458c6033d2Selric 	if (ret != 1) {
4468c6033d2Selric 		bits_free(bits);
4478c6033d2Selric 		return NULL;
4488c6033d2Selric 	}
4498c6033d2Selric 	return bits;
4508c6033d2Selric }
4518c6033d2Selric 
4528c6033d2Selric bits_t *
bits_cget(const char * fn,size_t len)453ad18d2e4Schristos bits_cget(const char *fn, size_t len)
4548c6033d2Selric {
4558c6033d2Selric 	bits_t	*bits;
4568c6033d2Selric 	FILE	*f;
4578c6033d2Selric 
4588c6033d2Selric 	f = fopen(fn, "r");
4592d447a3bSlukem 	if (!f)
4608c6033d2Selric 		return NULL;
4618c6033d2Selric 
4628c6033d2Selric 	bits = bits_fget(f, len);
463ad18d2e4Schristos 	(void)fclose(f);
4648c6033d2Selric 	return bits;
4658c6033d2Selric }
4668c6033d2Selric 
4678c6033d2Selric bits_t *
bits_getrandombits(size_t len,int hard)468ad18d2e4Schristos bits_getrandombits(size_t len, int hard)
4698c6033d2Selric {
4708c6033d2Selric 
47121840e45Stv 	return bits_cget((hard ? "/dev/random" : "/dev/urandom"), len);
4728c6033d2Selric }
4738c6033d2Selric 
4748c6033d2Selric void
bits_fprint(FILE * f,const bits_t * bits)4758c6033d2Selric bits_fprint(FILE *f, const bits_t *bits)
4768c6033d2Selric {
4778c6033d2Selric 	string_t *s;
4788c6033d2Selric 
4798c6033d2Selric 	s = bits_encode(bits);
4808c6033d2Selric 	string_fprint(f, s);
4818c6033d2Selric 	free(s);
4828c6033d2Selric }
483