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