Home | History | Annotate | Line # | Download | only in cgdconfig
utils.c revision 1.16
      1 /* $NetBSD: utils.c,v 1.16 2007/02/06 00:48:37 cbiere Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Roland C. Dowdeswell.
      9  *
     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.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *        This product includes software developed by the NetBSD
     21  *        Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 #include <sys/cdefs.h>
     40 #ifndef lint
     41 __RCSID("$NetBSD: utils.c,v 1.16 2007/02/06 00:48:37 cbiere Exp $");
     42 #endif
     43 
     44 #include <sys/param.h>
     45 
     46 #include <stdlib.h>
     47 #include <string.h>
     48 #include <err.h>
     49 #include <util.h>
     50 
     51 /* include the resolver gunk in order that we can use b64 routines */
     52 #include <netinet/in.h>
     53 #include <arpa/nameser.h>
     54 #include <resolv.h>
     55 
     56 #include "utils.h"
     57 
     58 
     59 /* just strsep(3), but skips empty fields. */
     60 
     61 static char *
     62 strsep_getnext(char **stringp, const char *delim)
     63 {
     64 	char	*ret;
     65 
     66 	ret = strsep(stringp, delim);
     67 	while (ret && index(delim, *ret))
     68 		ret = strsep(stringp, delim);
     69 	return ret;
     70 }
     71 
     72 /*
     73  * this function returns a dynamically sized char ** of the words
     74  * in the line.  the caller is responsible for both free(3)ing
     75  * each word and the superstructure by calling words_free().
     76  */
     77 char **
     78 words(const char *line, int *num)
     79 {
     80 	int	  i = 0;
     81 	int	  nwords = 0;
     82 	char	 *cur;
     83 	char	**ret;
     84 	const char	 *tmp;
     85 	char	 *tmp1, *tmpf;
     86 
     87 	*num = 0;
     88 	tmp = line;
     89 	if (tmp[0] == '\0')
     90 		return NULL;
     91 	while (tmp[0]) {
     92 		if ((tmp[1] == ' ' || tmp[1] == '\t' || tmp[1] == '\0') &&
     93 		    (tmp[0] != ' ' && tmp[0] != '\t'))
     94 			nwords++;
     95 		tmp++;
     96 	}
     97 	ret = emalloc((nwords+1) * sizeof(char *));
     98 	tmp1 = tmpf = estrdup(line);
     99 	while ((cur = strsep_getnext(&tmpf, " \t")) != NULL)
    100 		ret[i++] = estrdup(cur);
    101 	ret[i] = NULL;
    102 	free(tmp1);
    103 	*num = nwords;
    104 	return ret;
    105 }
    106 
    107 void
    108 words_free(char **w, int num)
    109 {
    110 	int	i;
    111 
    112 	for (i=0; i < num; i++)
    113 		free(w[i]);
    114 }
    115 
    116 /*
    117  * this is a simple xor that has the same calling conventions as
    118  * memcpy(3).
    119  */
    120 
    121 void
    122 memxor(void *res, const void *src, size_t len)
    123 {
    124 	char *r;
    125 	const char *s;
    126 	size_t i;
    127 
    128 	r = res;
    129 	s = src;
    130 	for (i = 0; i < len; i++)
    131 		r[i] ^= s[i];
    132 }
    133 
    134 /*
    135  * well, a very simple set of string functions...
    136  *
    137  * The goal here is basically to manage length encoded strings,
    138  * but just for safety we nul terminate them anyway.
    139  */
    140 
    141 /* for now we use a very simple encoding */
    142 
    143 struct string {
    144 	int	 length;
    145 	char	*text;
    146 };
    147 
    148 string_t *
    149 string_new(const char *intext, int inlength)
    150 {
    151 	string_t *out;
    152 
    153 	out = emalloc(sizeof(*out));
    154 	out->length = inlength;
    155 	out->text = emalloc(out->length + 1);
    156 	memcpy(out->text, intext, out->length);
    157 	out->text[out->length] = '\0';
    158 	return out;
    159 }
    160 
    161 string_t *
    162 string_dup(const string_t *in)
    163 {
    164 
    165 	return string_new(in->text, in->length);
    166 }
    167 
    168 void
    169 string_free(string_t *s)
    170 {
    171 
    172 	if (!s)
    173 		return;
    174 	free(s->text);
    175 	free(s);
    176 }
    177 
    178 void
    179 string_assign(string_t **lhs, string_t *rhs)
    180 {
    181 
    182 	string_free(*lhs);
    183 	*lhs = rhs;
    184 }
    185 
    186 string_t *
    187 string_add(const string_t *a1, const string_t *a2)
    188 {
    189 	string_t *sum;
    190 
    191 	sum = emalloc(sizeof(*sum));
    192 	sum->length = a1->length + a2->length;
    193 	sum->text = emalloc(sum->length + 1);
    194 	memcpy(sum->text, a1->text, a1->length);
    195 	memcpy(sum->text + a1->length, a2->text, a2->length);
    196 	sum->text[sum->length] = '\0';
    197 	return sum;
    198 }
    199 
    200 string_t *
    201 string_add_d(string_t *a1, string_t *a2)
    202 {
    203 	string_t *sum;
    204 
    205 	sum = string_add(a1, a2);
    206 	string_free(a1);
    207 	string_free(a2);
    208 	return sum;
    209 }
    210 
    211 string_t *
    212 string_fromcharstar(const char *in)
    213 {
    214 
    215 	return string_new(in, strlen(in));
    216 }
    217 
    218 const char *
    219 string_tocharstar(const string_t *in)
    220 {
    221 
    222 	return in->text;
    223 }
    224 
    225 string_t *
    226 string_fromint(int in)
    227 {
    228 	string_t *ret;
    229 
    230 	ret = emalloc(sizeof(*ret));
    231 	ret->length = asprintf(&ret->text, "%d", in);
    232 	if (ret->length == -1)
    233 		err(1, NULL);
    234 	return ret;
    235 }
    236 
    237 void
    238 string_fprint(FILE *f, const string_t *s)
    239 {
    240 
    241 	fwrite(s->text, s->length, 1, f);
    242 }
    243 
    244 struct bits {
    245 	int	 length;
    246 	char	*text;
    247 };
    248 
    249 bits_t *
    250 bits_new(const void *buf, int len)
    251 {
    252 	bits_t	*b;
    253 
    254 	b = emalloc(sizeof(*b));
    255 	b->length = len;
    256 	b->text = emalloc(BITS2BYTES(b->length));
    257 	memcpy(b->text, buf, BITS2BYTES(b->length));
    258 	return b;
    259 }
    260 
    261 bits_t *
    262 bits_dup(const bits_t *in)
    263 {
    264 
    265 	return bits_new(in->text, in->length);
    266 }
    267 
    268 void
    269 bits_free(bits_t *b)
    270 {
    271 
    272 	if (!b)
    273 		return;
    274 	free(b->text);
    275 	free(b);
    276 }
    277 
    278 void
    279 bits_assign(bits_t **lhs, bits_t *rhs)
    280 {
    281 
    282 	bits_free(*lhs);
    283 	*lhs = rhs;
    284 }
    285 
    286 const void *
    287 bits_getbuf(bits_t *in)
    288 {
    289 
    290 	return in->text;
    291 }
    292 
    293 int
    294 bits_len(bits_t *in)
    295 {
    296 
    297 	return in->length;
    298 }
    299 
    300 int
    301 bits_match(const bits_t *b1, const bits_t *b2)
    302 {
    303 	int i;
    304 
    305 	if (b1->length != b2->length)
    306 		return 0;
    307 
    308 	for (i = 0; i < BITS2BYTES(b1->length); i++)
    309 		if (b1->text[i] != b2->text[i])
    310 			return 0;
    311 
    312 	return 1;
    313 }
    314 
    315 bits_t *
    316 bits_xor(const bits_t *x1, const bits_t *x2)
    317 {
    318 	bits_t	*b;
    319 	int	 i;
    320 
    321 	b = emalloc(sizeof(*b));
    322 	b->length = MAX(x1->length, x2->length);
    323 	b->text = ecalloc(1, BITS2BYTES(b->length));
    324 	for (i=0; i < BITS2BYTES(MIN(x1->length, x2->length)); i++)
    325 		b->text[i] = x1->text[i] ^ x2->text[i];
    326 	return b;
    327 }
    328 
    329 bits_t *
    330 bits_xor_d(bits_t *x1, bits_t *x2)
    331 {
    332 	bits_t	*ret;
    333 
    334 	ret = bits_xor(x1, x2);
    335 	bits_free(x1);
    336 	bits_free(x2);
    337 	return ret;
    338 }
    339 
    340 /*
    341  * bits_decode() reads an encoded base64 stream.  We interpret
    342  * the first 32 bits as an unsigned integer in network byte order
    343  * specifying the number of bits in the stream to give a little
    344  * resilience.
    345  */
    346 
    347 bits_t *
    348 bits_decode(const string_t *in)
    349 {
    350 	bits_t	*ret;
    351 	int	 len;
    352 	int	 nbits;
    353 	u_char	*tmp;
    354 
    355 	len = in->length;
    356 	tmp = emalloc(len);
    357 
    358 	len = __b64_pton(in->text, tmp, len);
    359 
    360 	if (len == -1) {
    361 		fprintf(stderr, "bits_decode: mangled base64 stream\n");
    362 		fprintf(stderr, "  %s\n", in->text);
    363 		free(tmp);
    364 		return NULL;
    365 	}
    366 
    367 	nbits = ntohl(*((u_int32_t *)tmp));
    368 	if (nbits > (len - 4) * 8) {
    369 		fprintf(stderr, "bits_decode: encoded bits claim to be "
    370 		    "longer than they are (nbits=%u, stream len=%u bytes)\n",
    371 		    (unsigned)nbits, (unsigned)len);
    372 		free(tmp);
    373 		return NULL;
    374 	}
    375 
    376 	ret = bits_new(tmp+4, nbits);
    377 	free(tmp);
    378 	return ret;
    379 }
    380 
    381 bits_t *
    382 bits_decode_d(string_t *in)
    383 {
    384 	bits_t *ret;
    385 
    386 	ret = bits_decode(in);
    387 	string_free(in);
    388 	return ret;
    389 }
    390 
    391 string_t *
    392 bits_encode(const bits_t *in)
    393 {
    394 	string_t *ret;
    395 	int	 len;
    396 	char	*out;
    397 	u_char	*tmp;
    398 
    399 	if (!in)
    400 		return NULL;
    401 
    402 	/* compute the total size of the input stream */
    403 	len = BITS2BYTES(in->length) + 4;
    404 
    405 	tmp = emalloc(len);
    406 	out = emalloc(len * 2);
    407 	/* stuff the length up front */
    408 	*((u_int32_t *)tmp) = htonl(in->length);
    409 	memcpy(tmp + 4, in->text, len - 4);
    410 
    411 	if ((len = __b64_ntop(tmp, len, out, len * 2)) == -1) {
    412 		free(out);
    413 		free(tmp);
    414 		return NULL;
    415 	}
    416 	ret = string_new(out, len);
    417 	free(tmp);
    418 	free(out);
    419 	return ret;
    420 }
    421 
    422 string_t *
    423 bits_encode_d(bits_t *in)
    424 {
    425 	string_t *ret;
    426 
    427 	ret = bits_encode(in);
    428 	bits_free(in);
    429 	return ret;
    430 }
    431 
    432 bits_t *
    433 bits_fget(FILE *f, int len)
    434 {
    435 	bits_t	*bits;
    436 	int	 ret;
    437 
    438 	bits = emalloc(sizeof(*bits));
    439 	bits->length = len;
    440 	bits->text = emalloc(BITS2BYTES(bits->length));
    441 	ret = fread(bits->text, BITS2BYTES(bits->length), 1, f);
    442 	if (ret != 1) {
    443 		bits_free(bits);
    444 		return NULL;
    445 	}
    446 	return bits;
    447 }
    448 
    449 bits_t *
    450 bits_cget(const char *fn, int len)
    451 {
    452 	bits_t	*bits;
    453 	FILE	*f;
    454 
    455 	f = fopen(fn, "r");
    456 	if (!f)
    457 		return NULL;
    458 
    459 	bits = bits_fget(f, len);
    460 	fclose(f);
    461 	return bits;
    462 }
    463 
    464 bits_t *
    465 bits_getrandombits(int len, int hard)
    466 {
    467 
    468 	return bits_cget((hard ? "/dev/random" : "/dev/urandom"), len);
    469 }
    470 
    471 void
    472 bits_fprint(FILE *f, const bits_t *bits)
    473 {
    474 	string_t *s;
    475 
    476 	s = bits_encode(bits);
    477 	string_fprint(f, s);
    478 	free(s);
    479 }
    480