Home | History | Annotate | Line # | Download | only in cgdconfig
utils.c revision 1.10
      1 /* $NetBSD: utils.c,v 1.10 2006/03/20 00:53:39 christos 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.10 2006/03/20 00:53:39 christos Exp $");
     42 #endif
     43 
     44 #include <sys/param.h>
     45 
     46 #include <stdlib.h>
     47 #include <string.h>
     48 #include <err.h>
     49 
     50 /* include the resolver gunk in order that we can use b64 routines */
     51 #include <netinet/in.h>
     52 #include <arpa/nameser.h>
     53 #include <resolv.h>
     54 
     55 #include "utils.h"
     56 
     57 
     58 void *
     59 emalloc(size_t len)
     60 {
     61 	void *ptr = malloc(len);
     62 	if (ptr == NULL)
     63 		err(1, NULL);
     64 	return ptr;
     65 }
     66 
     67 void *
     68 ecalloc(size_t nel, size_t len)
     69 {
     70 	void *ptr = calloc(nel, len);
     71 	if (ptr == NULL)
     72 		err(1, NULL);
     73 	return ptr;
     74 }
     75 
     76 char *
     77 estrdup(const char *str)
     78 {
     79 	char *ptr = strdup(str);
     80 	if (ptr == NULL)
     81 		err(1, NULL);
     82 	return ptr;
     83 }
     84 
     85 /* just strsep(3), but skips empty fields. */
     86 
     87 static char *
     88 strsep_getnext(char **stringp, const char *delim)
     89 {
     90 	char	*ret;
     91 
     92 	ret = strsep(stringp, delim);
     93 	while (ret && index(delim, *ret))
     94 		ret = strsep(stringp, delim);
     95 	return ret;
     96 }
     97 
     98 /*
     99  * this function returns a dynamically sized char ** of the words
    100  * in the line.  the caller is responsible for both free(3)ing
    101  * each word and the superstructure by calling words_free().
    102  */
    103 char **
    104 words(const char *line, int *num)
    105 {
    106 	int	  i = 0;
    107 	int	  nwords = 0;
    108 	char	 *cur;
    109 	char	**ret;
    110 	const char	 *tmp;
    111 	char	 *tmp1, *tmpf;
    112 
    113 	*num = 0;
    114 	tmp = line;
    115 	if (tmp[0] == '\0')
    116 		return NULL;
    117 	while (tmp[0]) {
    118 		if ((tmp[1] == ' ' || tmp[1] == '\t' || tmp[1] == '\0') &&
    119 		    (tmp[0] != ' ' && tmp[0] != '\t'))
    120 			nwords++;
    121 		tmp++;
    122 	}
    123 	ret = emalloc((nwords+1) * sizeof(char *));
    124 	tmp1 = tmpf = estrdup(line);
    125 	while ((cur = strsep_getnext(&tmpf, " \t")) != NULL)
    126 		ret[i++] = estrdup(cur);
    127 	ret[i] = NULL;
    128 	free(tmp1);
    129 	*num = nwords;
    130 	return ret;
    131 }
    132 
    133 void
    134 words_free(char **w, int num)
    135 {
    136 	int	i;
    137 
    138 	for (i=0; i < num; i++)
    139 		free(w[i]);
    140 }
    141 
    142 /*
    143  * this is a simple xor that has the same calling conventions as
    144  * memcpy(3).
    145  */
    146 
    147 void
    148 memxor(void *res, const void *src, size_t len)
    149 {
    150 	int i;
    151 	char *r;
    152 	const char *s;
    153 
    154 	r = res;
    155 	s = src;
    156 	for (i=0; i < len; i++)
    157 		r[i] ^= s[i];
    158 }
    159 
    160 /*
    161  * well, a very simple set of string functions...
    162  *
    163  * The goal here is basically to manage length encoded strings,
    164  * but just for safety we nul terminate them anyway.
    165  */
    166 
    167 /* for now we use a very simple encoding */
    168 
    169 struct string {
    170 	int	 length;
    171 	char	*text;
    172 };
    173 
    174 string_t *
    175 string_new(const char *intext, int inlength)
    176 {
    177 	string_t *out;
    178 
    179 	out = emalloc(sizeof(*out));
    180 	out->length = inlength;
    181 	out->text = emalloc(out->length + 1);
    182 	memcpy(out->text, intext, out->length);
    183 	out->text[out->length] = '\0';
    184 	return out;
    185 }
    186 
    187 string_t *
    188 string_dup(const string_t *in)
    189 {
    190 
    191 	return string_new(in->text, in->length);
    192 }
    193 
    194 void
    195 string_free(string_t *s)
    196 {
    197 
    198 	if (!s)
    199 		return;
    200 	free(s->text);
    201 	free(s);
    202 }
    203 
    204 void
    205 string_assign(string_t **lhs, string_t *rhs)
    206 {
    207 
    208 	string_free(*lhs);
    209 	*lhs = rhs;
    210 }
    211 
    212 string_t *
    213 string_add(const string_t *a1, const string_t *a2)
    214 {
    215 	string_t *sum;
    216 
    217 	sum = emalloc(sizeof(*sum));
    218 	sum->length = a1->length + a2->length;
    219 	sum->text = emalloc(sum->length + 1);
    220 	memcpy(sum->text, a1->text, a1->length);
    221 	memcpy(sum->text + a1->length, a2->text, a2->length);
    222 	sum->text[sum->length] = '\0';
    223 	return sum;
    224 }
    225 
    226 string_t *
    227 string_add_d(string_t *a1, string_t *a2)
    228 {
    229 	string_t *sum;
    230 
    231 	sum = string_add(a1, a2);
    232 	string_free(a1);
    233 	string_free(a2);
    234 	return sum;
    235 }
    236 
    237 string_t *
    238 string_fromcharstar(const char *in)
    239 {
    240 
    241 	return string_new(in, strlen(in));
    242 }
    243 
    244 const char *
    245 string_tocharstar(const string_t *in)
    246 {
    247 
    248 	return in->text;
    249 }
    250 
    251 string_t *
    252 string_fromint(int in)
    253 {
    254 	string_t *ret;
    255 
    256 	ret = emalloc(sizeof(*ret));
    257 	ret->length = asprintf(&ret->text, "%d", in);
    258 	if (ret->length == -1)
    259 		err(1, NULL);
    260 	return ret;
    261 }
    262 
    263 void
    264 string_fprint(FILE *f, const string_t *s)
    265 {
    266 
    267 	fwrite(s->text, s->length, 1, f);
    268 }
    269 
    270 struct bits {
    271 	int	 length;
    272 	char	*text;
    273 };
    274 
    275 bits_t *
    276 bits_new(const void *buf, int len)
    277 {
    278 	bits_t	*b;
    279 
    280 	b = emalloc(sizeof(*b));
    281 	b->length = len;
    282 	b->text = emalloc(BITS2BYTES(b->length));
    283 	memcpy(b->text, buf, BITS2BYTES(b->length));
    284 	return b;
    285 }
    286 
    287 bits_t *
    288 bits_dup(const bits_t *in)
    289 {
    290 
    291 	return bits_new(in->text, in->length);
    292 }
    293 
    294 void
    295 bits_free(bits_t *b)
    296 {
    297 
    298 	if (!b)
    299 		return;
    300 	free(b->text);
    301 	free(b);
    302 }
    303 
    304 void
    305 bits_assign(bits_t **lhs, bits_t *rhs)
    306 {
    307 
    308 	bits_free(*lhs);
    309 	*lhs = rhs;
    310 }
    311 
    312 const void *
    313 bits_getbuf(bits_t *in)
    314 {
    315 
    316 	return in->text;
    317 }
    318 
    319 int
    320 bits_len(bits_t *in)
    321 {
    322 
    323 	return in->length;
    324 }
    325 
    326 int
    327 bits_match(const bits_t *b1, const bits_t *b2)
    328 {
    329 	int i;
    330 
    331 	if (b1->length != b2->length)
    332 		return 0;
    333 
    334 	for (i = 0; i < BITS2BYTES(b1->length); i++)
    335 		if (b1->text[i] != b2->text[i])
    336 			return 0;
    337 
    338 	return 1;
    339 }
    340 
    341 bits_t *
    342 bits_xor(const bits_t *x1, const bits_t *x2)
    343 {
    344 	bits_t	*b;
    345 	int	 i;
    346 
    347 	b = emalloc(sizeof(*b));
    348 	b->length = MAX(x1->length, x2->length);
    349 	b->text = ecalloc(1, BITS2BYTES(b->length));
    350 	for (i=0; i < BITS2BYTES(MIN(x1->length, x2->length)); i++)
    351 		b->text[i] = x1->text[i] ^ x2->text[i];
    352 	return b;
    353 }
    354 
    355 bits_t *
    356 bits_xor_d(bits_t *x1, bits_t *x2)
    357 {
    358 	bits_t	*ret;
    359 
    360 	ret = bits_xor(x1, x2);
    361 	bits_free(x1);
    362 	bits_free(x2);
    363 	return ret;
    364 }
    365 
    366 /*
    367  * bits_decode() reads an encoded base64 stream.  We interpret
    368  * the first 32 bits as an unsigned integer in network byte order
    369  * specifying the number of bits in the stream to give a little
    370  * resilience.
    371  */
    372 
    373 bits_t *
    374 bits_decode(const string_t *in)
    375 {
    376 	bits_t	*ret;
    377 	int	 len;
    378 	int	 nbits;
    379 	char	*tmp;
    380 
    381 	len = in->length;
    382 	tmp = emalloc(len);
    383 
    384 	len = __b64_pton(in->text, tmp, len);
    385 
    386 	if (len == -1) {
    387 		fprintf(stderr, "bits_decode: mangled base64 stream\n");
    388 		fprintf(stderr, "  %s\n", in->text);
    389 		return NULL;
    390 	}
    391 
    392 	nbits = ntohl(*((u_int32_t *)tmp));
    393 	if (nbits > (len - 4) * 8) {
    394 		fprintf(stderr, "bits_decode: encoded bits claim to be "
    395 		    "longer than they are (nbits=%u, stream len=%u bytes)\n",
    396 		    (unsigned)nbits, (unsigned)len);
    397 		return NULL;
    398 	}
    399 
    400 	ret = bits_new(tmp+4, nbits);
    401 	free(tmp);
    402 	return ret;
    403 }
    404 
    405 bits_t *
    406 bits_decode_d(string_t *in)
    407 {
    408 	bits_t *ret;
    409 
    410 	ret = bits_decode(in);
    411 	string_free(in);
    412 	return ret;
    413 }
    414 
    415 string_t *
    416 bits_encode(const bits_t *in)
    417 {
    418 	string_t *ret;
    419 	int	 len;
    420 	char	*out;
    421 	char	*tmp;
    422 
    423 	if (!in)
    424 		return NULL;
    425 
    426 	/* compute the total size of the input stream */
    427 	len = BITS2BYTES(in->length) + 4;
    428 
    429 	tmp = emalloc(len);
    430 	out = emalloc(len * 2);
    431 	/* stuff the length up front */
    432 	*((u_int32_t *)tmp) = htonl(in->length);
    433 	memcpy(tmp + 4, in->text, len - 4);
    434 
    435 	if ((len = __b64_ntop(tmp, len, out, len * 2)) == -1) {
    436 		free(tmp);
    437 		free(malloc);
    438 		return NULL;
    439 	}
    440 	ret = string_new(out, len);
    441 	free(tmp);
    442 	free(out);
    443 	return ret;
    444 }
    445 
    446 string_t *
    447 bits_encode_d(bits_t *in)
    448 {
    449 	string_t *ret;
    450 
    451 	ret = bits_encode(in);
    452 	bits_free(in);
    453 	return ret;
    454 }
    455 
    456 bits_t *
    457 bits_fget(FILE *f, int len)
    458 {
    459 	bits_t	*bits;
    460 	int	 ret;
    461 
    462 	bits = emalloc(sizeof(*bits));
    463 	bits->length = len;
    464 	bits->text = emalloc(BITS2BYTES(bits->length));
    465 	ret = fread(bits->text, BITS2BYTES(bits->length), 1, f);
    466 	if (ret != 1) {
    467 		bits_free(bits);
    468 		return NULL;
    469 	}
    470 	return bits;
    471 }
    472 
    473 bits_t *
    474 bits_cget(const char *fn, int len)
    475 {
    476 	bits_t	*bits;
    477 	FILE	*f;
    478 
    479 	f = fopen(fn, "r");
    480 	if (!f)
    481 		return NULL;
    482 
    483 	bits = bits_fget(f, len);
    484 	fclose(f);
    485 	return bits;
    486 }
    487 
    488 bits_t *
    489 bits_getrandombits(int len, int hard)
    490 {
    491 
    492 	return bits_cget((hard ? "/dev/random" : "/dev/urandom"), len);
    493 }
    494 
    495 void
    496 bits_fprint(FILE *f, const bits_t *bits)
    497 {
    498 	string_t *s;
    499 
    500 	s = bits_encode(bits);
    501 	string_fprint(f, s);
    502 	free(s);
    503 }
    504