1 /*
2  * ircaux.c: some extra routines... not specific to irc... that I needed
3  *
4  * Written By Michael Sandrof
5  *
6  * Copyright(c) 1990, 1991
7  *
8  * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
9  */
10 #include "irc.h"
11 static char cvsrevision[] = "$Id: ircaux.c 432 2013-11-07 03:00:24Z tcava $";
12 CVS_REVISION(ircaux_c)
13 #include "struct.h"
14 
15 #include "alias.h"
16 #include "log.h"
17 #include "misc.h"
18 #include "vars.h"
19 #include "screen.h"
20 
21 #include <pwd.h>
22 
23 #include <sys/stat.h>
24 
25 #include "ircaux.h"
26 #include "output.h"
27 #include "ircterm.h"
28 #define MAIN_SOURCE
29 #include "modval.h"
30 
31 #ifndef MAXPATHLEN
32 #define MAXPATHLEN PATHLEN
33 #endif
34 
35 /*
36  * These are used by the malloc routines.  We actually ask for an int-size
37  * more of memory, and in that extra int we store the malloc size.  Very
38  * handy for debugging and other hackeries.
39  */
40 
41 /*#define MEM_DEBUG 1*/
42 
43 #ifdef MEM_DEBUG
44 #include <dmalloc.h>
45 #endif
46 
47 /* This union is used to ensure that the resulting address
48  * will be aligned correctly for all types we use. */
49 union alloc_info {
50 	size_t size;
51 
52 	void *dummy1;
53 	long dummy2;
54 	double dummy3;
55 };
56 
57 #define alloc_start(ptr) ((void *)((char *)(ptr) - sizeof(union alloc_info)))
58 #define alloc_size(ptr) (((union alloc_info *)alloc_start(ptr))->size)
59 
60 #define FREE_DEBUG 1
61 #define FREED_VAL (size_t)-3
62 #define ALLOC_MAGIC 0xafbdce70
63 
64 char compress_buffer[10000];
65 
start_memdebug(void)66 void start_memdebug(void)
67 {
68 #ifdef MEM_DEBUG
69 	dmalloc_debug(/*0x2202*/0x14f41d83);
70 #endif
71 }
72 
73 /*
74  * really_new_malloc is the general interface to the malloc(3) call.
75  * It is only called by way of the ``new_malloc'' #define.
76  * It wont ever return NULL.
77  */
78 
79 /*
80  * Malloc allocator with size caching.
81  */
n_malloc(size_t size,const char * module,const char * file,const int line)82 void * n_malloc (size_t size, const char *module, const char *file, const int line)
83 {
84 	char *ptr;
85 
86 	if (size < FREED_VAL - sizeof(union alloc_info))
87 	{
88 #ifdef MEM_DEBUG
89 		ptr = _calloc_leap(file, line, 1, size + sizeof(union alloc_info));
90 #else
91 		ptr = calloc(1, size + sizeof(union alloc_info));
92 #endif
93 	}
94 	else
95 	{
96 		ptr = NULL;
97 	}
98 
99 	if (!ptr)
100 	{
101 		yell("Malloc() failed, giving up!");
102 		putlog(LOG_ALL, "*", "*** failed calloc %s %s (%d)", module?module:empty_string, file, line);
103 		term_reset();
104 		exit(1);
105 	}
106 	/* Store the size of the allocation in the buffer. */
107 	ptr += sizeof(union alloc_info);
108 	alloc_size(ptr) = size;
109 	return ptr;
110 }
111 
112 /*
113  * new_free:  Why do this?  Why not?  Saves me a bit of trouble here and there
114  */
n_free(void * ptr,const char * module,const char * file,const int line)115 void *	n_free(void *ptr, const char *module, const char *file, const int line)
116 {
117 	if (ptr)
118 	{
119 #ifdef FREE_DEBUG
120 		/* Check to make sure its not been freed before */
121 		if (alloc_size(ptr) == FREED_VAL)
122 		{
123 			yell("free()ing a already free'd pointer, giving up!");
124 			putlog(LOG_ALL, "*", "*** failed free %s %s (%d)", module?module:empty_string, file, line);
125 			term_reset();
126 			exit(1);
127 		}
128 #endif
129 		alloc_size(ptr) = FREED_VAL;
130 
131 #ifdef MEM_DEBUG
132 		_free_leap(file, line, alloc_start(ptr));
133 #else
134 		free(alloc_start(ptr));
135 #endif
136 		ptr = NULL;
137 	}
138 	return ptr;
139 }
140 
n_realloc(void * ptr,size_t size,const char * module,const char * file,const int line)141 void * n_realloc (void *ptr, size_t size, const char *module, const char *file, const int line)
142 {
143 	char *ptr2 = NULL;
144 
145 	if (ptr)
146 	{
147 		if (size)
148 		{
149 			size_t msize = alloc_size(ptr);
150 
151 			if (msize >= size)
152 				return ptr;
153 
154 			ptr2 = n_malloc(size, module, file, line);
155 			memmove(ptr2, ptr, msize);
156 			n_free(ptr, module, file, line);
157 			return ptr2;
158 		}
159 		return n_free(ptr, module, file, line);
160 	}
161 	else if (size)
162 		ptr2 = n_malloc(size, module, file, line);
163 	return ptr2;
164 }
165 
166 /*
167  * malloc_strcpy:  Mallocs enough space for src to be copied in to where
168  * ptr points to.
169  *
170  * Never call this with ptr pointinng to an uninitialised string, as the
171  * call to new_free() might crash the client... - phone, jan, 1993.
172  */
n_malloc_strcpy(char ** ptr,const char * src,const char * module,const char * file,const int line)173 char *	n_malloc_strcpy (char **ptr, const char *src, const char *module, const char *file, const int line)
174 {
175 	if (!src)
176 		return *ptr = n_free(*ptr, module, file, line);
177 	if (ptr && *ptr)
178 	{
179 		if (*ptr == src)
180 			return *ptr;
181 		if (alloc_size(*ptr) > strlen(src))
182 			return strcpy(*ptr, src);
183 		*ptr = n_free(*ptr, module, file, line);
184 	}
185 	*ptr = n_malloc(strlen(src) + 1, module, file, line);
186 	return strcpy(*ptr, src);
187 	return *ptr;
188 }
189 
190 /* malloc_strcat: Yeah, right */
n_malloc_strcat(char ** ptr,const char * src,const char * module,const char * file,const int line)191 char *	n_malloc_strcat (char **ptr, const char *src, const char *module, const char *file, const int line)
192 {
193 	size_t  msize;
194 
195 	if (*ptr)
196 	{
197 		if (!src)
198 			return *ptr;
199 		msize = strlen(*ptr) + strlen(src) + 1;
200 		*ptr = n_realloc(*ptr, sizeof(char)*msize, module, file, line);
201 		return strcat(*ptr, src);
202 	}
203 	return (*ptr = n_m_strdup(src, module, file, line));
204 }
205 
BX_malloc_str2cpy(char ** ptr,const char * src1,const char * src2)206 char *BX_malloc_str2cpy(char **ptr, const char *src1, const char *src2)
207 {
208 	if (!src1 && !src2)
209 		return new_free(ptr);
210 
211 	if (*ptr)
212 	{
213 		if (alloc_size(*ptr) > strlen(src1) + strlen(src2))
214 			return strcat(strcpy(*ptr, src1), src2);
215 		new_free(ptr);
216 	}
217 
218 	*ptr = new_malloc(strlen(src1) + strlen(src2) + 1);
219 	return strcat(strcpy(*ptr, src1), src2);
220 }
221 
BX_m_3dup(const char * str1,const char * str2,const char * str3)222 char *BX_m_3dup (const char *str1, const char *str2, const char *str3)
223 {
224 	size_t msize = strlen(str1) + strlen(str2) + strlen(str3) + 1;
225 	return strcat(strcat(strcpy((char *)new_malloc(msize), str1), str2), str3);
226 }
227 
BX_m_opendup(const char * str1,...)228 char *BX_m_opendup (const char *str1, ...)
229 {
230 	va_list args;
231 	int size;
232 	char *this_arg = NULL;
233 	char *retval = NULL;
234 
235 	size = strlen(str1);
236 	va_start(args, str1);
237 	while ((this_arg = va_arg(args, char *)))
238 		size += strlen(this_arg);
239 
240 	retval = (char *)new_malloc(size + 1);
241 
242 	strcpy(retval, str1);
243 	va_start(args, str1);
244 	while ((this_arg = va_arg(args, char *)))
245 		strcat(retval, this_arg);
246 
247 	va_end(args);
248 	return retval;
249 }
250 
n_m_strdup(const char * str,const char * module,const char * file,const int line)251 char	*n_m_strdup (const char *str, const char *module, const char *file, const int line)
252 {
253 	char *ptr;
254 
255 	if (!str)
256 		str = empty_string;
257 	ptr = (char *)n_malloc(strlen(str) + 1, module, file, line);
258 	return strcpy(ptr, str);
259 }
260 
BX_m_s3cat(char ** one,const char * maybe,const char * definitely)261 char	*BX_m_s3cat (char **one, const char *maybe, const char *definitely)
262 {
263 	if (*one && **one)
264 		return m_3cat(one, maybe, definitely);
265 	return malloc_strcpy(one, definitely);
266 }
267 
BX_m_s3cat_s(char ** one,const char * maybe,const char * ifthere)268 char *BX_m_s3cat_s (char **one, const char *maybe, const char *ifthere)
269 {
270 	if (ifthere && *ifthere)
271 		return m_3cat(one, maybe, ifthere);
272 	return *one;
273 }
274 
BX_m_3cat(char ** one,const char * two,const char * three)275 char	*BX_m_3cat(char **one, const char *two, const char *three)
276 {
277 	int len = 0;
278 	char *str;
279 
280 	if (*one)
281 		len = strlen(*one);
282 	if (two)
283 		len += strlen(two);
284 	if (three)
285 		len += strlen(three);
286 	len += 1;
287 
288 	str = (char *)new_malloc(len);
289 	if (*one)
290 		strcpy(str, *one);
291 	if (two)
292 		strcat(str, two);
293 	if (three)
294 		strcat(str, three);
295 
296 	new_free(one);
297 	return ((*one = str));
298 }
299 
BX_upper(char * str)300 char	*BX_upper (char *str)
301 {
302 register char	*ptr = NULL;
303 
304 	if (str)
305 	{
306 		ptr = str;
307 		for (; *str; str++)
308 		{
309 			if (islower((unsigned char)*str))
310 				*str = toupper(*str);
311 		}
312 	}
313 	return (ptr);
314 }
315 
BX_lower(char * str)316 char	*BX_lower (char *str)
317 {
318 register char	*ptr = NULL;
319 
320 	if (str)
321 	{
322 		ptr = str;
323 		for (; *str; str++)
324 		{
325 			if (isupper((unsigned char)*str))
326 				*str = tolower(*str);
327 		}
328 	}
329 	return (ptr);
330 }
331 
BX_malloc_sprintf(char ** to,const char * pattern,...)332 char *BX_malloc_sprintf (char **to, const char *pattern, ...)
333 {
334 	char booya[BIG_BUFFER_SIZE*3+1];
335 	*booya = 0;
336 
337 	if (pattern)
338 	{
339 		va_list args;
340 		va_start (args, pattern);
341 		vsnprintf(booya, BIG_BUFFER_SIZE * 3, pattern, args);
342 		va_end(args);
343 	}
344 	malloc_strcpy(to, booya);
345 	return *to;
346 }
347 
348 /* same thing, different variation */
BX_m_sprintf(const char * pattern,...)349 char *BX_m_sprintf (const char *pattern, ...)
350 {
351 	char booya[BIG_BUFFER_SIZE * 3 + 1];
352 	*booya = 0;
353 
354 	if (pattern)
355 	{
356 		va_list args;
357 		va_start (args, pattern);
358 		vsnprintf(booya, BIG_BUFFER_SIZE * 3, pattern, args);
359 		va_end(args);
360 	}
361 	return m_strdup(booya);
362 }
363 
364 /* case insensitive string searching */
BX_stristr(const char * source,const char * search)365 char	*BX_stristr (const char *source, const char *search)
366 {
367         int     x = 0;
368 
369         if (!source || !*source || !search || !*search || strlen(source) < strlen(search))
370 		return NULL;
371 
372         while (*source)
373         {
374                 if (source[x] && toupper(source[x]) == toupper(search[x]))
375 			x++;
376                 else if (search[x])
377 			source++, x = 0;
378 		else
379 			return (char *)source;
380         }
381 	return NULL;
382 }
383 
384 /* case insensitive string searching from the end */
BX_rstristr(char * source,char * search)385 char	*BX_rstristr (char *source, char *search)
386 {
387 	char *ptr;
388 	int x = 0;
389 
390         if (!source || !*source || !search || !*search || strlen(source) < strlen(search))
391 		return NULL;
392 
393 	ptr = source + strlen(source) - strlen(search);
394 
395 	while (ptr >= source)
396         {
397 		if (!search[x])
398 			return ptr;
399 
400 		if (toupper(ptr[x]) == toupper(search[x]))
401 			x++;
402 		else
403 			ptr--, x = 0;
404 	}
405 	return NULL;
406 }
407 
408 /*
409  * word_count:  Efficient way to find out how many words are in
410  * a given string.  Relies on isspace() not being broken.
411  */
BX_word_count(char * str)412 int     BX_word_count (char *str)
413 {
414         int cocs = 0;
415         int isv = 1;
416 register char *foo = str;
417 
418         if (!foo)
419                 return 0;
420 
421         while (*foo)
422         {
423 		if (*foo == '"' && isv)
424 		{
425 			while (*(foo+1) && *++foo != '"')
426 				;
427 			isv = 0;
428 			cocs++;
429 		}
430                 if (!my_isspace(*foo) != !isv)
431                 {
432                         isv = my_isspace(*foo);
433                         cocs++;
434                 }
435                 foo++;
436         }
437         return (cocs + 1) / 2;
438 }
439 
440 #if 0
441 extern  int     word_scount (char *str)
442 {
443         int cocs = 0;
444         char *foo = str;
445 	int isv = 1;
446 
447         if (!foo)
448                 return 0;
449 
450         while (*foo)
451         {
452                 if (my_isspace(*foo) != !isv)
453                 {
454                         isv = my_isspace(*foo);
455                         cocs++;
456                 }
457                 foo++;
458         }
459         return (cocs + 1) / 2;
460 }
461 #endif
462 
BX_next_arg(char * str,char ** new_ptr)463 char	*BX_next_arg (char *str, char **new_ptr)
464 {
465 	char	*ptr;
466 
467 	/* added by Sheik (kilau@prairie.nodak.edu) -- sanity */
468 	if (!str || !*str)
469 		return NULL;
470 
471 	if ((ptr = sindex(str, "^ ")) != NULL)
472 	{
473 		if ((str = sindex(ptr, space)) != NULL)
474 			*str++ = (char) 0;
475 		else
476 			str = empty_string;
477 	}
478 	else
479 		str = empty_string;
480 	if (new_ptr)
481 		*new_ptr = str;
482 	return ptr;
483 }
484 
BX_remove_trailing_spaces(char * foo)485 extern char *BX_remove_trailing_spaces (char *foo)
486 {
487 	char *end;
488 	if (!*foo)
489 		return foo;
490 
491 	end = foo + strlen(foo) - 1;
492 	while (end > foo && my_isspace(*end))
493 		end--;
494 	end[1] = 0;
495 	return foo;
496 }
497 
498 /*
499  * yanks off the last word from 'src'
500  * kinda the opposite of next_arg
501  */
BX_last_arg(char ** src)502 char *BX_last_arg (char **src)
503 {
504 	char *ptr;
505 
506 	if (!src || !*src)
507 		return NULL;
508 
509 	remove_trailing_spaces(*src);
510 	ptr = *src + strlen(*src) - 1;
511 
512 	if (*ptr == '"')
513 	{
514 		for (ptr--;;ptr--)
515 		{
516 			if (*ptr == '"')
517 			{
518 				if (ptr == *src)
519 					break;
520 				if (ptr[-1] == ' ')
521 				{
522 					ptr--;
523 					break;
524 				}
525 			}
526 			if (ptr == *src)
527 				break;
528 		}
529 	}
530 	else
531 	{
532 		for (;;ptr--)
533 		{
534 			if (*ptr == ' ')
535 				break;
536 			if (ptr == *src)
537 				break;
538 		}
539 	}
540 
541 	if (ptr == *src)
542 	{
543 		ptr = *src;
544 		*src = empty_string;
545 	}
546 	else
547 	{
548 		*ptr++ = 0;
549 		remove_trailing_spaces(*src);
550 	}
551 	return ptr;
552 
553 }
554 
555 #define risspace(c) (c == ' ')
BX_new_next_arg(char * str,char ** new_ptr)556 char	*BX_new_next_arg (char *str, char **new_ptr)
557 {
558 	char	*ptr,
559 		*start;
560 
561 	if (!str || !*str)
562 		return NULL;
563 
564 	ptr = str;
565 	while (*ptr && risspace(*ptr))
566 		ptr++;
567 
568 	if (*ptr == '"')
569 	{
570 		start = ++ptr;
571 		for (str = start; *str; str++)
572 		{
573 			if (*str == '\\' && str[1])
574 				str++;
575 			else if (*str == '"')
576 			{
577 				*(str++) = 0;
578 				if (risspace(*str))
579 					str++;
580 				break;
581 			}
582 		}
583 	}
584 	else if (*ptr)
585 	{
586 		str = ptr;
587 		while (*str && !risspace(*str))
588 			str++;
589 		if (*str)
590 			*str++ = 0;
591 	}
592 
593 	if (!*str || !*ptr)
594 		str = empty_string;
595 
596 	if (new_ptr)
597 		*new_ptr = str;
598 
599 	return ptr;
600 }
601 
602 /*
603  * This function is "safe" because it doesnt ever return NULL.
604  * XXXX - this is an ugly kludge that needs to go away
605  */
safe_new_next_arg(char * str,char ** new_ptr)606 char	*safe_new_next_arg (char *str, char **new_ptr)
607 {
608 	char	*ptr,
609 		*start;
610 
611 	if (!str || !*str)
612 		return empty_string;
613 
614 	if ((ptr = sindex(str, "^ \t")) != NULL)
615 	{
616 		if (*ptr == '"')
617 		{
618 			start = ++ptr;
619 			while ((str = sindex(ptr, "\"\\")) != NULL)
620 			{
621 				switch (*str)
622 				{
623 					case '"':
624 						*str++ = '\0';
625 						if (*str == ' ')
626 							str++;
627 						if (new_ptr)
628 							*new_ptr = str;
629 						return (start);
630 					case '\\':
631 						if (*(str + 1) == '"')
632 							ov_strcpy(str, str + 1);
633 						ptr = str + 1;
634 				}
635 			}
636 			str = empty_string;
637 		}
638 		else
639 		{
640 			if ((str = sindex(ptr, " \t")) != NULL)
641 				*str++ = '\0';
642 			else
643 				str = empty_string;
644 		}
645 	}
646 	else
647 		str = empty_string;
648 
649 	if (new_ptr)
650 		*new_ptr = str;
651 
652 	if (!ptr)
653 		return empty_string;
654 
655 	return ptr;
656 }
657 
BX_new_new_next_arg(char * str,char ** new_ptr,char * type)658 char	*BX_new_new_next_arg (char *str, char **new_ptr, char *type)
659 {
660 	char	*ptr,
661 		*start;
662 
663 	if (!str || !*str)
664 		return NULL;
665 
666 	if ((ptr = sindex(str, "^ \t")) != NULL)
667 	{
668 		if ((*ptr == '"') || (*ptr == '\''))
669 		{
670 			char blah[3];
671 			blah[0] = *ptr;
672 			blah[1] = '\\';
673 			blah[2] = '\0';
674 
675 			*type = *ptr;
676 			start = ++ptr;
677 			while ((str = sindex(ptr, blah)) != NULL)
678 			{
679 				switch (*str)
680 				{
681 				case '\'':
682 				case '"':
683 					*str++ = '\0';
684 					if (*str == ' ')
685 						str++;
686 					if (new_ptr)
687 						*new_ptr = str;
688 					return (start);
689 				case '\\':
690 					if (str[1] == *type)
691 						ov_strcpy(str, str + 1);
692 					ptr = str + 1;
693 				}
694 			}
695 			str = empty_string;
696 		}
697 		else
698 		{
699 			*type = '\"';
700 			if ((str = sindex(ptr, " \t")) != NULL)
701 				*str++ = 0;
702 			else
703 				str = empty_string;
704 		}
705 	}
706 	else
707 		str = empty_string;
708 	if (new_ptr)
709 		*new_ptr = str;
710 	return ptr;
711 }
712 
713 unsigned char stricmp_table [] =
714 {
715 	0,	1,	2,	3,	4,	5,	6,	7,
716 	8,	9,	10,	11,	12,	13,	14,	15,
717 	16,	17,	18,	19,	20,	21,	22,	23,
718 	24,	25,	26,	27,	28,	29,	30,	31,
719 	32,	33,	34,	35,	36,	37,	38,	39,
720 	40,	41,	42,	43,	44,	45,	46,	47,
721 	48,	49,	50,	51,	52,	53,	54,	55,
722 	56,	57,	58,	59,	60,	61,	62,	63,
723 	64,	65,	66,	67,	68,	69,	70,	71,
724 	72,	73,	74,	75,	76,	77,	78,	79,
725 	80,	81,	82,	83,	84,	85,	86,	87,
726 	88,	89,	90,	91,	92,	93,	94,	95,
727 	96,	65,	66,	67,	68,	69,	70,	71,
728 	72,	73,	74,	75,	76,	77,	78,	79,
729 	80,	81,	82,	83,	84,	85,	86,	87,
730 	88,	89,	90,	91,	92,	93,	126,	127,
731 
732 	128,	129,	130,	131,	132,	133,	134,	135,
733 	136,	137,	138,	139,	140,	141,	142,	143,
734 	144,	145,	146,	147,	148,	149,	150,	151,
735 	152,	153,	154,	155,	156,	157,	158,	159,
736 	160,	161,	162,	163,	164,	165,	166,	167,
737 	168,	169,	170,	171,	172,	173,	174,	175,
738 	176,	177,	178,	179,	180,	181,	182,	183,
739 	184,	185,	186,	187,	188,	189,	190,	191,
740 	192,	193,	194,	195,	196,	197,	198,	199,
741 	200,	201,	202,	203,	204,	205,	206,	207,
742 	208,	209,	210,	211,	212,	213,	214,	215,
743 	216,	217,	218,	219,	220,	221,	222,	223,
744 	224,	225,	226,	227,	228,	229,	230,	231,
745 	232,	233,	234,	235,	236,	237,	238,	239,
746 	240,	241,	242,	243,	244,	245,	246,	247,
747 	248,	249,	250,	251,	252,	253,	254,	255
748 };
749 
750 /* my_stricmp: case insensitive version of strcmp */
BX_my_stricmp(const char * str1,const char * str2)751 int	BX_my_stricmp (const char *str1, const char *str2)
752 {
753 	while (*str1 && *str2 && (stricmp_table[(unsigned char)*str1] == stricmp_table[(unsigned char)*str2]))
754 		str1++, str2++;
755 	return (stricmp_table[(unsigned char)*str1] -
756 		stricmp_table[(unsigned char)*str2]);
757 
758 }
759 
760 /* my_strnicmp: case insensitive version of strncmp */
BX_my_strnicmp(const char * str1,const char * str2,size_t n)761 int	BX_my_strnicmp (const char *str1, const char *str2, size_t n)
762 {
763 	while (n && *str1 && *str2 && (stricmp_table[(unsigned char)*str1] == stricmp_table[(unsigned char)*str2]))
764 		str1++, str2++, n--;
765 	return (n ?
766 		(stricmp_table[(unsigned char)*str1] -
767 		stricmp_table[(unsigned char)*str2]) : 0);
768 }
769 
770 /* my_strnstr: case insensitive version of strstr */
BX_my_strnstr(register const unsigned char * str1,register const unsigned char * str2,register size_t n)771 int	BX_my_strnstr (register const unsigned char *str1, register const unsigned char *str2, register size_t n)
772 {
773 	char *p = (char *)str1;
774 	if (!p) return 0;
775 	for (; *p; p++)
776 		if (!strncasecmp(p, str2, strlen(str2)))
777 			return 1;
778 	return 0;
779 }
780 
781 /* chop -- chops off the last character. capiche? */
BX_chop(char * stuff,int nchar)782 char *BX_chop (char *stuff, int nchar)
783 {
784 	size_t sl = strlen(stuff);
785 	if (nchar > 0 && sl > 0 && nchar <= sl)
786 		stuff[sl - nchar] = 0;
787 	else if (nchar > sl)
788 		stuff[0] = 0;
789 	return stuff;
790 }
791 
792 /*
793  * strext: Makes a copy of the string delmited by two char pointers and
794  * returns it in malloced memory.  Useful when you dont want to munge up
795  * the original string with a null.  end must be one place beyond where
796  * you want to copy, ie, its the first character you dont want to copy.
797  */
strext(char * start,char * end)798 char *strext(char *start, char *end)
799 {
800 	char *ptr, *retval;
801 
802 	ptr = retval = (char *)new_malloc(end-start+1);
803 	while (start < end)
804 		*ptr++ = *start++;
805 	*ptr = 0;
806 	return retval;
807 }
808 
809 
810 /*
811  * strmcpy: Well, it's like this, strncpy doesn't append a trailing null if
812  * strlen(str) == maxlen.  strmcpy always makes sure there is a trailing null
813  */
BX_strmcpy(char * dest,const char * src,int maxlen)814 char *	BX_strmcpy (char *dest, const char *src, int maxlen)
815 {
816 	strlcpy(dest, src, maxlen + 1);
817 	return dest;
818 }
819 
820 /*
821  * strmcat: like strcat, but truncs the dest string to maxlen (thus the dest
822  * should be able to handle maxlen+1 (for the null))
823  */
BX_strmcat(char * dest,const char * src,int maxlen)824 char *	BX_strmcat(char *dest, const char *src, int maxlen)
825 {
826 	strlcat(dest, src, maxlen + 1);
827 	return dest;
828 }
829 
830 #ifdef INCLUDE_DEADCODE
831 /*
832  * strmcat_ue: like strcat, but truncs the dest string to maxlen (thus the dest
833  * should be able to handle maxlen + 1 (for the null)). Also unescapes
834  * backslashes.
835  */
strmcat_ue(char * dest,const char * src,int maxlen)836 char *	strmcat_ue(char *dest, const char *src, int maxlen)
837 {
838 	int	dstlen;
839 
840 	dstlen = strlen(dest);
841 	dest += dstlen;
842 	maxlen -= dstlen;
843 	while (*src && maxlen > 0)
844 	{
845 		if (*src == '\\')
846 		{
847 			if (strchr("npr0", src[1]))
848 				*dest++ = '\020';
849 			else if (*(src + 1))
850 				*dest++ = *++src;
851 			else
852 				*dest++ = '\\';
853 		}
854 		else
855 			*dest++ = *src;
856 		src++;
857 	}
858 	*dest = '\0';
859 	return dest;
860 }
861 #endif
862 
863 /*
864  * m_strcat_ues: Given two strings, concatenate the 2nd string to
865  * the end of the first one, but if the "unescape" argument is 1, do
866  * unescaping (like in strmcat_ue).
867  * (Malloc_STRCAT_UnEscape Special, in case you were wondering. ;-))
868  *
869  * This uses a cheating, "not-as-efficient-as-possible" algorithm,
870  * but it works with negligible cpu lossage.
871  */
n_m_strcat_ues(char ** dest,char * src,int unescape,const char * module,const char * file,const int line)872 char *	n_m_strcat_ues(char **dest, char *src, int unescape, const char *module, const char *file, const int line)
873 {
874 	int total_length;
875 	char *ptr, *ptr2;
876 	int z;
877 
878 	if (!unescape)
879 	{
880 		n_malloc_strcat(dest, src, module, file, line);
881 		return *dest;
882 	}
883 
884 	z = total_length = (*dest) ? strlen(*dest) : 0;
885 	total_length += strlen(src);
886 
887 /*	RESIZE(*dest, char, total_length + 2);*/
888 	*dest = n_realloc(*dest, sizeof(char) * (total_length + 2), module, file,  line);
889 	if (z == 0)
890 		**dest = 0;
891 
892 	ptr2 = *dest + z;
893 	for (ptr = src; *ptr; ptr++)
894 	{
895 		if (*ptr == '\\')
896 		{
897 			switch (*++ptr)
898 			{
899 				case 'n': case 'p': case 'r': case '0':
900 					*ptr2++ = '\020';
901 					break;
902 				case (char) 0:
903 					*ptr2++ = '\\';
904 					goto end_strcat_ues;
905 					break;
906 				default:
907 					*ptr2++ = *ptr;
908 			}
909 		}
910 		else
911 			*ptr2++ = *ptr;
912 	}
913 end_strcat_ues:
914 	*ptr2 = '\0';
915 
916 	return *dest;
917 }
918 
919 /*
920  * scanstr: looks for an occurrence of str in source.  If not found, returns
921  * 0.  If it is found, returns the position in source (1 being the first
922  * position).  Not the best way to handle this, but what the hell
923  */
BX_scanstr(char * str,char * source)924 extern	int	BX_scanstr (char *str, char *source)
925 {
926 	int	i,
927 		max,
928 		len;
929 
930 	len = strlen(str);
931 	max = strlen(source) - len;
932 	for (i = 0; i <= max; i++, source++)
933 	{
934 		if (!my_strnicmp(source, str, len))
935 			return (i + 1);
936 	}
937 	return (0);
938 }
939 
940 #if defined(WINNT) || defined(__EMX__)
convert_dos(char * str)941 char *convert_dos(char *str)
942 {
943 register char *p;
944 	for (p = str; *p; p++)
945 		if (*p == '/')
946 			*p = '\\';
947 	return str;
948 }
949 
convert_unix(char * arg)950 char *convert_unix(char *arg)
951 {
952 register char *x = arg;
953 	while (*x)
954 	{
955 		if (*x == '\\')
956 			*x = '/';
957 		x++;
958 	}
959 	return arg;
960 }
961 
is_dos(char * filename)962 int is_dos(char *filename)
963 {
964 	if (strlen(filename) > 3 && ( (*(filename+1) == ':') && (*(filename+2) == '/' || *(filename+2) == '\\')) )
965 		return 1;
966 	else
967 		return 0;
968 }
969 
970 #endif
971 
972 
973 /* expand_twiddle: expands ~ in pathnames. */
BX_expand_twiddle(char * str)974 char	*BX_expand_twiddle (char *str)
975 {
976 	char	buffer[BIG_BUFFER_SIZE/4 + 1];
977 	char *str2;
978 
979 #ifdef WINNT
980 	convert_unix(str);
981 #endif
982 	if (*str == '~')
983 	{
984 		str++;
985 
986 #if defined(WINNT) || defined(__EMX__)
987 		if (*str == '\\' || *str == '/')
988 #else
989 		if (*str == '/')
990 #endif
991 		{
992 			strlcpy(buffer, my_path, sizeof buffer);
993 			strlcat(buffer, str, sizeof buffer);
994 		}
995 		else
996 		{
997 			char	*rest;
998 			struct	passwd *entry;
999 			char	*p = NULL;
1000 
1001 			if ((rest = strchr(str, '/')) != NULL)
1002 				*rest++ = '\0';
1003 #if defined(WINNT) || defined(__EMX__)
1004 			if (((entry = getpwnam(str)) != NULL) || (p = getenv("HOME")))
1005 			{
1006 				if (p)
1007 					strlcpy(buffer, p, sizeof buffer);
1008 				else
1009 					strlcpy(buffer, entry->pw_dir, sizeof buffer);
1010 #else
1011 			if ((entry = getpwnam(str)) != NULL || (p = getenv("HOME")))
1012 			{
1013 				if (p)
1014 					strlcpy(buffer, p, sizeof buffer);
1015 				else
1016 					strlcpy(buffer, entry->pw_dir, sizeof buffer);
1017 #endif
1018 				if (rest)
1019 				{
1020 					strlcat(buffer, "/", sizeof buffer);
1021 					strlcat(buffer, rest, sizeof buffer);
1022 				}
1023 			}
1024 			else
1025 				return (char *) NULL;
1026 		}
1027 	}
1028 	else
1029 		strlcpy(buffer, str, sizeof buffer);
1030 
1031 	/* This isnt legal! */
1032 	str2 = NULL;
1033 	malloc_strcpy(&str2, buffer);
1034 #ifdef __EMX__
1035 	convert_unix(str2);
1036 #endif
1037 	return str2;
1038 }
1039 
1040 /* islegal: true if c is a legal nickname char anywhere but first char */
1041 #define islegal(c) ((((c) >= 'A') && ((c) <= '}')) || \
1042 		    (((c) >= '0') && ((c) <= '9')) || \
1043 		     ((c) == '-') || ((c) == '_'))
1044 
1045 /*
1046  * check_nickname: checks is a nickname is legal.  If the first character is
1047  * bad new, null is returned.  If the first character is bad, the string is
1048  * truncd down to only legal characters and returned
1049  *
1050  * rewritten, with help from do_nick_name() from the server code (2.8.5),
1051  * phone, april 1993.
1052  */
1053 char	*BX_check_nickname (char *nick)
1054 {
1055 	char	*s;
1056 	int	len = 0;
1057 	if (!nick || *nick == '-' || isdigit((unsigned char)*nick) ||
1058 	    !islegal(*nick))
1059 		return NULL;
1060 
1061 	for (s = nick; *s && (s - nick) < NICKNAME_LEN ; s++, len++)
1062 		if (!islegal(*s) || my_isspace(*s))
1063 			break;
1064 	*s = '\0';
1065 
1066 	return *nick ? nick : NULL;
1067 }
1068 
1069 /*
1070  * sindex: much like index(), but it looks for a match of any character in
1071  * the group, and returns that position.  If the first character is a ^, then
1072  * this will match the first occurence not in that group.
1073  */
1074 char	*BX_sindex (register char *string, char *group)
1075 {
1076 	char	*ptr;
1077 
1078 	if (!string || !group)
1079 		return (char *) NULL;
1080 	if (*group == '^')
1081 	{
1082 		group++;
1083 		for (; *string; string++)
1084 		{
1085 			for (ptr = group; *ptr; ptr++)
1086 			{
1087 				if (*ptr == *string)
1088 					break;
1089 			}
1090 			if (*ptr == '\0')
1091 				return string;
1092 		}
1093 	}
1094 	else
1095 	{
1096 		for (; *string; string++)
1097 		{
1098 			for (ptr = group; *ptr; ptr++)
1099 			{
1100 				if (*ptr == *string)
1101 					return string;
1102 			}
1103 		}
1104 	}
1105 	return (char *) NULL;
1106 }
1107 
1108 /*
1109  * rsindex: much like rindex(), but it looks for a match of any character in
1110  * the group, and returns that position.  If the first character is a ^, then
1111  * this will match the first occurence not in that group.
1112  */
1113 char	*BX_rsindex (register char *string, char *start, char *group, int howmany)
1114 {
1115 	register char	*ptr;
1116 
1117 	if (howmany && string && start && group && start <= string)
1118 	{
1119 		if (*group == '^')
1120 		{
1121 			group++;
1122 			for (ptr = string; (ptr >= start) && howmany; ptr--)
1123 			{
1124 				if (!strchr(group, *ptr))
1125 				{
1126 					if (--howmany == 0)
1127 						return ptr;
1128 				}
1129 			}
1130 		}
1131 		else
1132 		{
1133 			for (ptr = string; (ptr >= start) && howmany; ptr--)
1134 			{
1135 				if (strchr(group, *ptr))
1136 				{
1137 					if (--howmany == 0)
1138 						return ptr;
1139 				}
1140 			}
1141 		}
1142 	}
1143 	return NULL;
1144 }
1145 
1146 /* is_number: returns true if the given string is a number, false otherwise */
1147 int	BX_is_number (const char *str)
1148 {
1149 	if (!str || !*str)
1150 		return 0;
1151 	while (*str == ' ')
1152 		str++;
1153 	if (*str == '-' || *str == '+')
1154 		str++;
1155 	if (*str)
1156 	{
1157 		for (; *str; str++)
1158 		{
1159 			if (!isdigit((unsigned char)(*str)))
1160 				return (0);
1161 		}
1162 		return 1;
1163 	}
1164 	else
1165 		return 0;
1166 }
1167 
1168 /* rfgets: exactly like fgets, cept it works backwards through a file!  */
1169 char	*BX_rfgets (char *buffer, int size, FILE *file)
1170 {
1171 	char	*ptr;
1172 	off_t	pos;
1173 
1174 	if (fseek(file, -2L, SEEK_CUR))
1175 		return NULL;
1176 	do
1177 	{
1178 		switch (fgetc(file))
1179 		{
1180 		case EOF:
1181 			return NULL;
1182 		case '\n':
1183 			pos = ftell(file);
1184 			ptr = fgets(buffer, size, file);
1185 			fseek(file, pos, 0);
1186 			return ptr;
1187 		}
1188 	}
1189 	while (fseek(file, -2L, SEEK_CUR) == 0);
1190 	rewind(file);
1191 	pos = 0L;
1192 	ptr = fgets(buffer, size, file);
1193 	fseek(file, pos, 0);
1194 	return ptr;
1195 }
1196 
1197 /*
1198  * path_search: given a file called name, this will search each element of
1199  * the given path to locate the file.  If found in an element of path, the
1200  * full path name of the file is returned in a static string.  If not, null
1201  * is returned.  Path is a colon separated list of directories
1202  */
1203 char	*BX_path_search (char *name, char *path)
1204 {
1205 	char *free_path, *ptr;
1206 	static char buffer[BIG_BUFFER_SIZE/2];
1207 
1208 	/* A "relative" path is valid if the file exists */
1209 	/* A "relative" path is searched in the path if the
1210 	   filename doesn't really exist from where we are */
1211 	if (strchr(name, '/'))
1212 		if (!access(name, F_OK))
1213 			return name;
1214 
1215 	/* an absolute path is always checked, never searched */
1216 #if defined(WINNT) || defined(__EMX__)
1217 	if (name[0] == '/' || name[0] == '\\')
1218 #else
1219 	if (name[0] == '/')
1220 #endif
1221 		return (access(name, F_OK) ? NULL : name);
1222 
1223 	if (!path)
1224 		return NULL;
1225 
1226 	/* This is cheating. >;-) */
1227 	free_path = LOCAL_COPY(path);
1228 	path = free_path;
1229 
1230 #ifdef __EMX__
1231 	convert_unix(path);
1232 #endif
1233 	while (path)
1234 	{
1235 #if defined(WINNT) || defined(__EMX__)
1236 		if (((ptr = strchr(path, ';')) != NULL) || ((ptr = strchr(path, ':')) != NULL))
1237 #else
1238 		if ((ptr = strchr(path, ':')) != NULL)
1239 #endif
1240 			*ptr++ = '\0';
1241 		*buffer = 0;
1242 		if (path[0] == '~')
1243 		{
1244 			strlcat(buffer, my_path, sizeof buffer);
1245 			path++;
1246 		}
1247 		strlcat(buffer, path, sizeof buffer);
1248 		strlcat(buffer, "/", sizeof buffer);
1249 		strlcat(buffer, name, sizeof buffer);
1250 
1251 		if (access(buffer, F_OK) == 0)
1252 			break;
1253 		path = ptr;
1254 	}
1255 
1256 	return (path != NULL) ? buffer : NULL;
1257 }
1258 
1259 /*
1260  * double_quote: Given a str of text, this will quote any character in the
1261  * set stuff with the QUOTE_CHAR. It returns a malloced quoted, null
1262  * terminated string
1263  */
1264 char	*BX_double_quote (const char *str, const char *stuff, char *buffer)
1265 {
1266 	register char	c;
1267 	register int	pos;
1268 
1269 	*buffer = 0;
1270 	if (!stuff)
1271 		return buffer;
1272 	for (pos = 0; (c = *str); str++)
1273 	{
1274 		if (strchr(stuff, c))
1275 		{
1276 			if (c == '$')
1277 				buffer[pos++] = '$';
1278 			else
1279 				buffer[pos++] = '\\';
1280 		}
1281 		buffer[pos++] = c;
1282 	}
1283 	buffer[pos] = '\0';
1284 	return buffer;
1285 }
1286 
1287 char	*quote_it (const char *str, const char *stuff, char *buffer)
1288 {
1289 	register char	c;
1290 	register int	pos;
1291 
1292 	*buffer = 0;
1293 	for (pos = 0; (c = *str); str++)
1294 	{
1295 		if (stuff && strchr(stuff, c))
1296 		{
1297 			if (c == '%')
1298 				buffer[pos++] = '%';
1299 			else
1300 				buffer[pos++] = '\\';
1301 		}
1302 		else if (c == '%')
1303 			buffer[pos++] = '%';
1304 		buffer[pos++] = c;
1305 	}
1306 	buffer[pos] = '\0';
1307 	return buffer;
1308 }
1309 
1310 void	BX_ircpanic (char *format, ...)
1311 {
1312 	char buffer[3 * BIG_BUFFER_SIZE + 1];
1313 	extern char cx_function[];
1314 	static int recursion = 0;
1315 	if (recursion || x_debug & DEBUG_CRASH)
1316 		abort();
1317 
1318 	recursion++;
1319 	if (format)
1320 	{
1321 		va_list arglist;
1322 		va_start(arglist, format);
1323 		vsnprintf(buffer, BIG_BUFFER_SIZE, format, arglist);
1324 		va_end(arglist);
1325 	}
1326 
1327 	yell("An unrecoverable logic error has occured.");
1328 	yell("Please email " BUG_EMAIL " and include the following message:");
1329 
1330 	yell("Panic: [%s:%s %s]", irc_version, buffer, cx_function);
1331 	dump_call_stack();
1332 	irc_exit(1, "BitchX panic... Could it possibly be a bug?  Nahhhh...", NULL);
1333 }
1334 
1335 /* Not very complicated, but very handy function to have */
1336 int BX_end_strcmp (const char *one, const char *two, int bytes)
1337 {
1338 	if (bytes < strlen(one))
1339 		return (strcmp(one + strlen (one) - (size_t) bytes, two));
1340 	else
1341 		return -1;
1342 }
1343 
1344 /* beep_em: Not hard to figure this one out */
1345 void BX_beep_em (int beeps)
1346 {
1347 	int	cnt,
1348 		i;
1349 
1350 	for (cnt = beeps, i = 0; i < cnt; i++)
1351 		term_beep();
1352 }
1353 
1354 
1355 
1356 FILE *open_compression (char *executable, char *filename, int hook)
1357 {
1358 	FILE *file_pointer = NULL;
1359 	int pipes[2];
1360 
1361 
1362 	pipes[0] = -1;
1363 	pipes[1] = -1;
1364 
1365 	if (pipe (pipes) == -1)
1366 	{
1367 		if (hook)
1368 			yell("Cannot start decompression: %s\n", strerror(errno));
1369 		if (pipes[0] != -1)
1370 		{
1371 			close (pipes[0]);
1372 			close (pipes[1]);
1373 		}
1374 		return NULL;
1375 	}
1376 
1377 	switch (fork ())
1378 	{
1379 		case -1:
1380 		{
1381 			if (hook)
1382 				yell("Cannot start decompression: %s\n", strerror(errno));
1383 			return NULL;
1384 		}
1385 		case 0:
1386 		{
1387 			int i;
1388 #if !defined(WINNT) && !defined(__EMX__)
1389 			setsid();
1390 #endif
1391 			setuid (getuid ());
1392 			setgid (getgid ());
1393 			dup2 (pipes[1], 1);
1394 			close (pipes[0]);
1395 			for (i = 2; i < 256; i++)
1396 				close(i);
1397 #ifdef ZARGS
1398 			execl (executable, executable, "-c", ZARGS, filename, NULL);
1399 #else
1400 			execl (executable, executable, "-c", filename, NULL);
1401 #endif
1402 			_exit (0);
1403 		}
1404 		default :
1405 		{
1406 			close (pipes[1]);
1407 			if ((file_pointer = fdopen(pipes[0], "r")) == NULL)
1408 			{
1409 				if (hook)
1410 					yell("Cannot start decompression: %s\n", strerror(errno));
1411 				return NULL;
1412 			}
1413 #if 0
1414 			setlinebuf(file_pointer);
1415 			setvbuf(file_pointer, NULL, _IONBF, 0);
1416 #endif
1417 			break;
1418 		}
1419 	}
1420 	return file_pointer;
1421 }
1422 
1423 /* Front end to fopen() that will open ANY file, compressed or not, and
1424  * is relatively smart about looking for the possibilities, and even
1425  * searches a path for you! ;-)
1426  */
1427 FILE *BX_uzfopen (char **filename, char *path, int hook)
1428 {
1429 	static int	setup				= 0;
1430 	int 		ok_to_decompress 		= 0;
1431 	char *		filename_path;
1432 	char 		*filename_trying;
1433 	char		*filename_blah;
1434 	static char 	*path_to_gunzip = NULL;
1435 	static char	*path_to_uncompress = NULL;
1436 	static char	*path_to_bunzip2 = NULL;
1437 	FILE *		doh = NULL;
1438 
1439 	filename_trying = alloca(MAXPATHLEN+1);
1440 
1441 	if (!setup)
1442 	{
1443 		char *gzip = path_search("gunzip", getenv("PATH"));
1444 		char *compress = NULL;
1445 		char *bzip = NULL;
1446 		if (!gzip)
1447 			gzip = empty_string;
1448 		path_to_gunzip = m_strdup(gzip);
1449 
1450 		if (!(compress = path_search("uncompress", getenv("PATH"))))
1451 			compress = empty_string;
1452 		path_to_uncompress = m_strdup(compress);
1453 
1454 		if (!(bzip = path_search("bunzip2", getenv("PATH"))))
1455 			bzip = empty_string;
1456 		path_to_bunzip2 = m_strdup(bzip);
1457 		setup = 1;
1458 	}
1459 
1460 	/* It is allowed to pass to this function either a true filename
1461 	   with the compression extention, or to pass it the base name of
1462 	   the filename, and this will look to see if there is a compressed
1463 	   file that matches the base name */
1464 
1465 	/* Start with what we were given as an initial guess */
1466 	if (**filename == '~')
1467 	{
1468 		filename_blah = expand_twiddle(*filename);
1469 		strlcpy(filename_trying, filename_blah, MAXPATHLEN);
1470 		new_free(&filename_blah);
1471 	}
1472 	else
1473 		strlcpy(filename_trying, *filename, MAXPATHLEN);
1474 
1475 	/* Look to see if the passed filename is a full compressed filename */
1476 	if ((! end_strcmp (filename_trying, ".gz", 3)) ||
1477 	    (! end_strcmp (filename_trying, ".z", 2)))
1478 	{
1479 		if (path_to_gunzip)
1480 		{
1481 			ok_to_decompress = 1;
1482 			filename_path = path_search (filename_trying, path);
1483 		}
1484 		else
1485 		{
1486 			if (hook)
1487 				yell("Cannot open file %s because gunzip was not found", filename_trying);
1488 			new_free(filename);
1489 			return NULL;
1490 		}
1491 	}
1492 	else if (! end_strcmp (filename_trying, ".Z", 2))
1493 	{
1494 		if (path_to_gunzip || path_to_uncompress)
1495 		{
1496 			ok_to_decompress = 1;
1497 			filename_path = path_search (filename_trying, path);
1498 		}
1499 		else
1500 		{
1501 			if (hook)
1502 				yell("Cannot open file %s because uncompress was not found", filename_trying);
1503 			new_free(filename);
1504 			return NULL;
1505 		}
1506 	}
1507 	else if (!end_strcmp(filename_trying, ".bz2", 4))
1508 	{
1509 		if (*path_to_bunzip2)
1510 		{
1511 			ok_to_decompress = 3;
1512 			filename_path = path_search(filename_trying, path);
1513 		}
1514 		else
1515 		{
1516 			if (hook)
1517 				yell("Cannot open file %s because bunzip2 was not found", filename_trying);
1518 			new_free(filename);
1519 			return NULL;
1520 		}
1521 	}
1522 	/* Right now it doesnt look like the file is a full compressed fn */
1523 	else
1524 	{
1525 		struct stat file_info;
1526 
1527 		/* Trivially, see if the file we were passed exists */
1528 		filename_path = path_search (filename_trying, path);
1529 
1530 		/* Nope. it doesnt exist. */
1531 		if (!filename_path)
1532 		{
1533 			/* Is there a "filename.gz"? */
1534 			strlcpy (filename_trying, *filename, MAXPATHLEN);
1535 			strlcat (filename_trying, ".gz", MAXPATHLEN);
1536 			filename_path = path_search (filename_trying, path);
1537 
1538 			/* Nope. no "filename.gz" */
1539 			if (!filename_path)
1540 			{
1541 				/* Is there a "filename.Z"? */
1542 				strlcpy (filename_trying, *filename, MAXPATHLEN);
1543 				strlcat (filename_trying, ".Z", MAXPATHLEN);
1544 				filename_path = path_search (filename_trying, path);
1545 
1546 				/* Nope. no "filename.Z" */
1547 				if (!filename_path)
1548 				{
1549 					/* Is there a "filename.z"? */
1550 					strlcpy (filename_trying, *filename, MAXPATHLEN);
1551 					strlcat (filename_trying, ".z", MAXPATHLEN);
1552 					filename_path = path_search (filename_trying, path);
1553 
1554 					if (!filename_path)
1555 					{
1556 						strlcpy(filename_trying, *filename, MAXPATHLEN);
1557 						strlcat(filename_trying, ".bz2", MAXPATHLEN);
1558 						filename_path = path_search(filename_trying, path);
1559 						if (!filename_path)
1560 						{
1561 							if (hook)
1562 								yell("File not found: %s", *filename);
1563 							new_free(filename);
1564 							return NULL;
1565 						}
1566 						else
1567 							/* found a bz2 */
1568 							ok_to_decompress = 3;
1569 					}
1570 					/* Yep. there's a "filename.z" */
1571 					else
1572 						ok_to_decompress = 2;
1573 				}
1574 				/* Yep. there's a "filename.Z" */
1575 				else
1576 					ok_to_decompress = 1;
1577 			}
1578 			/* Yep. There's a "filename.gz" */
1579 			else
1580 				ok_to_decompress = 2;
1581 		}
1582 		/* Imagine that! the file exists as-is (no decompression) */
1583 		else
1584 			ok_to_decompress = 0;
1585 
1586 		stat (filename_path, &file_info);
1587 		if (file_info.st_mode & S_IFDIR)
1588 		{
1589 			if (hook)
1590 				yell("%s is a directory", filename_trying);
1591 			new_free(filename);
1592 			return NULL;
1593 		}
1594 #ifndef WINNT
1595 		if (file_info.st_mode & 0111)
1596 		{
1597 			char *p;
1598 			if ((p = strrchr(filename_path, '.')))
1599 			{
1600 				p++;
1601 				if (!strcmp(p, "so"))
1602 				{
1603 					malloc_strcpy(filename, filename_path);
1604 					return NULL;
1605 				}
1606 			}
1607 			if (hook)
1608 				yell("Cannot open %s -- executable file", filename_trying);
1609 			new_free(filename);
1610 			return NULL;
1611 		}
1612 #endif
1613 	}
1614 
1615 	malloc_strcpy (filename, filename_path);
1616 
1617 	/* at this point, we should have a filename in the variable
1618 	   filename_trying, and it should exist.  If ok_to_decompress
1619 	   is one, then we can gunzip the file if guzip is available,
1620 	   else we uncompress the file */
1621 	if (ok_to_decompress)
1622 	{
1623 		if (ok_to_decompress <= 2 && *path_to_gunzip)
1624 			return open_compression (path_to_gunzip, filename_path, hook);
1625 		else if ((ok_to_decompress == 1) && *path_to_uncompress)
1626 			return open_compression (path_to_uncompress, filename_path, hook);
1627 		else if ((ok_to_decompress == 3) && *path_to_bunzip2)
1628 			return open_compression(path_to_bunzip2, filename_path, hook);
1629 
1630 		if (hook)
1631 			yell("Cannot open compressed file %s because no uncompressor was found", filename_trying);
1632 		new_free(filename);
1633 		return NULL;
1634 	}
1635 
1636 	/* Its not a compressed file... Try to open it regular-like. */
1637 	if ((doh = fopen(filename_path, "r")) != NULL)
1638 		return doh;
1639 
1640 	/* nope.. we just cant seem to open this file... */
1641 	if (hook)
1642 		yell("Cannot open file %s: %s", filename_path, strerror(errno));
1643 	new_free(filename);
1644 	return NULL;
1645 }
1646 
1647 
1648 #ifdef INCLUDE_DEADCODE
1649 /* some more string manips by hop (june, 1995) */
1650 extern int fw_strcmp(comp_len_func *compar, char *one, char *two)
1651 {
1652 	int len = 0;
1653 	char *pos = one;
1654 
1655 	while (!my_isspace(*pos))
1656 		pos++, len++;
1657 
1658 	return compar(one, two, len);
1659 }
1660 
1661 
1662 /*
1663  * Compares the last word in 'one' to the string 'two'.  You must provide
1664  * the compar function.  my_stricmp is a good default.
1665  */
1666 extern int lw_strcmp(comp_func *compar, char *one, char *two)
1667 {
1668 	char *pos = one + strlen(one) - 1;
1669 
1670 	if (pos > one)			/* cant do pos[-1] if pos == one */
1671 		while (!my_isspace(pos[-1]) && (pos > one))
1672 			pos--;
1673 	else
1674 		pos = one;
1675 
1676 	if (compar)
1677 		return compar(pos, two);
1678 	else
1679 		return my_stricmp(pos, two);
1680 }
1681 
1682 /*
1683  * you give it a filename, some flags, and a position, and it gives you an
1684  * fd with the file pointed at the 'position'th byte.
1685  */
1686 extern int opento(char *filename, int flags, off_t position)
1687 {
1688 	int file;
1689 
1690 	file = open(filename, flags, 777);
1691 	lseek(file, position, SEEK_SET);
1692 	return file;
1693 }
1694 #endif
1695 
1696 /* swift and easy -- returns the size of the file */
1697 off_t file_size (char *filename)
1698 {
1699 	struct stat statbuf;
1700 
1701 	if (!stat(filename, &statbuf))
1702 		return (off_t)(statbuf.st_size);
1703 	else
1704 		return -1;
1705 }
1706 
1707 /* Gets the time in second/usecond if you can,  second/0 if you cant. */
1708 struct timeval BX_get_time(struct timeval *timer)
1709 {
1710 	static struct timeval timer2;
1711 #ifdef HAVE_GETTIMEOFDAY
1712 	if (timer)
1713 	{
1714 		gettimeofday(timer, NULL);
1715 		return *timer;
1716 	}
1717 	gettimeofday(&timer2, NULL);
1718 	return timer2;
1719 #else
1720 	time_t time2 = time(NULL);
1721 
1722 	if (timer)
1723 	{
1724 		timer->tv_sec = time2;
1725 		timer->tv_usec = 0;
1726 		return *timer;
1727 	}
1728 	timer2.tv_sec = time2;
1729 	timer2.tv_usec = 0;
1730 	return timer2;
1731 #endif
1732 }
1733 
1734 /*
1735  * calculates the time elapsed between 'one' and 'two' where they were
1736  * gotten probably with a call to get_time.  'one' should be the older
1737  * timer and 'two' should be the most recent timer.
1738  */
1739 double BX_time_diff (struct timeval one, struct timeval two)
1740 {
1741 	struct timeval td;
1742 
1743 	td.tv_sec = two.tv_sec - one.tv_sec;
1744 	td.tv_usec = two.tv_usec - one.tv_usec;
1745 
1746 	return (double)td.tv_sec + ((double)td.tv_usec / 1000000.0);
1747 }
1748 
1749 int BX_time_to_next_minute (void)
1750 {
1751 	time_t now = time(NULL);
1752 	static int which = 0;
1753 
1754 	if (which == 1)
1755 		return 60 - now % 60;
1756 	else
1757 	{
1758 		struct tm *now_tm = gmtime(&now);
1759 
1760 		if (!which)
1761 		{
1762 			if (now_tm->tm_sec == now % 60)
1763 				which = 1;
1764 			else
1765 				which = 2;
1766 		}
1767 		return 60-now_tm->tm_sec;
1768 	}
1769 }
1770 
1771 char *BX_plural (int number)
1772 {
1773 	return (number != 1) ? "s" : empty_string;
1774 }
1775 
1776 char *BX_my_ctime (time_t when)
1777 {
1778 	return chop(ctime(&when), 1);
1779 }
1780 
1781 char *BX_my_ltoa (long foo)
1782 {
1783 	static char buffer[BIG_BUFFER_SIZE/8+1];
1784 	char *pos = buffer + BIG_BUFFER_SIZE/8-1;
1785 	unsigned long my_absv;
1786 	int negative;
1787 
1788 	my_absv = (foo < 0) ? (unsigned long)-foo : (unsigned long)foo;
1789 	negative = (foo < 0) ? 1 : 0;
1790 
1791 	buffer[BIG_BUFFER_SIZE/8] = 0;
1792 	for (; my_absv > 9; my_absv /= 10)
1793 		*pos-- = (my_absv % 10) + '0';
1794 	*pos = (my_absv) + '0';
1795 
1796 	if (negative)
1797 		*--pos = '-';
1798 
1799 	return pos;
1800 }
1801 
1802 /*
1803  * Formats "src" into "dest" using the given length.  If "length" is
1804  * negative, then the string is right-justified.  If "length" is
1805  * zero, nothing happens.  Sure, i cheat, but its cheaper then doing
1806  * two sprintf's.
1807  */
1808 char *BX_strformat (char *dest, const char *src, int length, char pad_char)
1809 {
1810 	char *ptr1 = dest,
1811 	     *ptr2 = (char *)src;
1812 	int tmplen = length;
1813 	int abslen;
1814 	char padc;
1815 
1816 	abslen = (length >= 0 ? length : -length);
1817 	if (!(padc = pad_char))
1818 		padc = ' ';
1819 
1820 	/* Cheat by spacing out 'dest' */
1821 	for (tmplen = abslen - 1; tmplen >= 0; tmplen--)
1822 		dest[tmplen] = padc;
1823 	dest[abslen] = 0;
1824 
1825 	/* Then cheat further by deciding where the string should go. */
1826 	if (length > 0)		/* left justified */
1827 	{
1828 		while ((length-- > 0) && *ptr2)
1829 			*ptr1++ = *ptr2++;
1830 	}
1831 	else if (length < 0)	/* right justified */
1832 	{
1833 		length = -length;
1834 		ptr1 = dest;
1835 		ptr2 = (char *)src;
1836 		if (strlen(src) < length)
1837 			ptr1 += length - strlen(src);
1838 		while ((length-- > 0) && *ptr2)
1839 			*ptr1++ = *ptr2++;
1840 	}
1841 	return dest;
1842 }
1843 
1844 
1845 /* MatchingBracket returns the next unescaped bracket of the given type */
1846 char	*BX_MatchingBracket(register char *string, register char left, register char right)
1847 {
1848 	int	bracket_count = 1;
1849 
1850 	if (left == '(')
1851 	{
1852 		for (; *string; string++)
1853 		{
1854 			switch (*string)
1855 			{
1856 				case '(':
1857 					bracket_count++;
1858 					break;
1859 				case ')':
1860 					bracket_count--;
1861 					if (bracket_count == 0)
1862 						return string;
1863 					break;
1864 				case '\\':
1865 					if (string[1])
1866 						string++;
1867 					break;
1868 			}
1869 		}
1870 	}
1871 	else if (left == '[')
1872 	{
1873 		for (; *string; string++)
1874 		{
1875 			switch (*string)
1876 	    		{
1877 				case '[':
1878 					bracket_count++;
1879 					break;
1880 				case ']':
1881 					bracket_count--;
1882 					if (bracket_count == 0)
1883 						return string;
1884 					break;
1885 				case '\\':
1886 					if (string[1])
1887 						string++;
1888 					break;
1889 			}
1890 		}
1891 	}
1892 	else		/* Fallback for everyone else */
1893 	{
1894 		while (*string && bracket_count)
1895 		{
1896 			if (*string == '\\' && string[1])
1897 				string++;
1898 			else if (*string == left)
1899 				bracket_count++;
1900 			else if (*string == right)
1901 			{
1902 				if (--bracket_count == 0)
1903 					return string;
1904 			}
1905 			string++;
1906 		}
1907 	}
1908 
1909 	return NULL;
1910 }
1911 
1912 /*
1913  * parse_number: returns the next number found in a string and moves the
1914  * string pointer beyond that point	in the string.  Here's some examples:
1915  *
1916  * "123harhar"  returns 123 and str as "harhar"
1917  *
1918  * while:
1919  *
1920  * "hoohar"     returns -1  and str as "hoohar"
1921  */
1922 extern	int	BX_parse_number(char **str)
1923 {
1924 	long ret;
1925 	char *ptr = *str;	/* sigh */
1926 
1927 	ret = strtol(ptr, str, 10);
1928 	if (*str == ptr)
1929 		ret = -1;
1930 
1931 	return (int)ret;
1932 }
1933 
1934 #if 0
1935 extern char *chop_word(char *str)
1936 {
1937 	char *end = str + strlen(str) - 1;
1938 
1939 	while (my_isspace(*end) && (end > str))
1940 		end--;
1941 	while (!my_isspace(*end) && (end > str))
1942 		end--;
1943 
1944 	if (end >= str)
1945 		*end = 0;
1946 
1947 	return str;
1948 }
1949 #endif
1950 
1951 extern int BX_splitw (char *str, char ***to)
1952 {
1953 	int numwords = word_count(str);
1954 	int counter;
1955 	if (numwords)
1956 	{
1957 		*to = (char **)new_malloc(sizeof(char *) * numwords);
1958 		for (counter = 0; counter < numwords; counter++)
1959 			(*to)[counter] = new_next_arg(str, &str);
1960 	}
1961 	else
1962 		*to = NULL;
1963 	return numwords;
1964 }
1965 
1966 char * BX_unsplitw (char ***container, int howmany)
1967 {
1968 	char *retval = NULL;
1969 	char **str = *container;
1970 
1971 	while (howmany)
1972 	{
1973 		m_s3cat(&retval, space, *str);
1974 		str++, howmany--;
1975 	}
1976 
1977 	new_free((char **)container);
1978 	return retval;
1979 }
1980 
1981 char *BX_m_2dup (const char *str1, const char *str2)
1982 {
1983 	size_t msize = strlen(str1) + strlen(str2) + 1;
1984 	return strcat(strcpy((char *)new_malloc(msize), str1), str2);
1985 }
1986 
1987 char *BX_m_e3cat (char **one, const char *yes1, const char *yes2)
1988 {
1989 	if (*one && **one)
1990 		return m_3cat(one, yes1, yes2);
1991 	else
1992 		*one = m_2dup(yes1, yes2);
1993 	return *one;
1994 }
1995 
1996 
1997 double strtod();
1998 extern int BX_check_val (char *sub)
1999 {
2000 	long sval;
2001 	char *endptr;
2002 
2003 	if (!sub || !*sub)
2004 		return 0;
2005 
2006 #ifdef __EMX__
2007 	if(strlen(sub) > 4 && strnicmp(sub, "infin", 5) == 0)
2008 		return 0;
2009 #endif
2010 
2011 	/* get the numeric value (if any). */
2012 	sval = strtod(sub, &endptr);
2013 
2014 	/* Its OK if:
2015 	 *  1) the f-val is not zero.
2016 	 *  2) the first illegal character was not a null.
2017 	 *  3) there were no valid f-chars.
2018 	 */
2019 	if (sval || *endptr || (sub == endptr))
2020 		return 1;
2021 
2022 	return 0;
2023 }
2024 
2025 char *BX_on_off(int var)
2026 {
2027 	if (var)
2028 		return ("On");
2029 	return ("Off");
2030 }
2031 
2032 
2033 /*
2034  * Appends 'num' copies of 'app' to the end of 'str'.
2035  */
2036 extern char *BX_strextend(char *str, char app, int num)
2037 {
2038 	char *ptr = str + strlen(str);
2039 
2040 	for (;num;num--)
2041 		*ptr++ = app;
2042 
2043 	*ptr = (char) 0;
2044 	return str;
2045 }
2046 
2047 const char *BX_strfill(char c, int num)
2048 {
2049 static char buffer[BIG_BUFFER_SIZE/4+1];
2050 int i = 0;
2051 	if (num > BIG_BUFFER_SIZE/4)
2052 		num = BIG_BUFFER_SIZE/4;
2053 	for (i = 0; i < num; i++)
2054 		buffer[i] = c;
2055 	buffer[num] = 0;
2056 	return buffer;
2057 }
2058 
2059 #ifdef INCLUDE_DEADCODE
2060 /*
2061  * Appends the given character to the string
2062  */
2063 char *strmccat(char *str, char c, int howmany)
2064 {
2065 	int x = strlen(str);
2066 
2067 	if (x < howmany)
2068 		str[x] = c;
2069 	str[x+1] = 0;
2070 
2071 	return str;
2072 }
2073 
2074 /*
2075  * Pull a substring out of a larger string
2076  * If the ending delimiter doesnt occur, then we dont pass
2077  * anything (by definition).  This is because we dont want
2078  * to introduce a back door into CTCP handlers.
2079  */
2080 extern char *BX_pullstr (char *source_string, char *dest_string)
2081 {
2082 	char delim = *source_string;
2083 	char *end;
2084 
2085 	end = strchr(source_string + 1, delim);
2086 
2087 	/* If there is no closing delim, then we punt. */
2088 	if (!end)
2089 		return NULL;
2090 
2091 	*end = 0;
2092 	end++;
2093 
2094 	strcpy(dest_string, source_string + 1);
2095 	strcpy(source_string, end);
2096 	return dest_string;
2097 }
2098 #endif
2099 
2100 extern int BX_empty (const char *str)
2101 {
2102 	while (str && *str && *str == ' ')
2103 		str++;
2104 
2105 	if (str && *str)
2106 		return 0;
2107 
2108 	return 1;
2109 }
2110 
2111 /* makes foo[one][two] look like tmp.one.two -- got it? */
2112 char *BX_remove_brackets (const char *name, const char *args, int *arg_flag)
2113 {
2114 	char *ptr, *right, *result1, *rptr, *retval = NULL;
2115 
2116 	/* XXXX - ugh. */
2117 	rptr = m_strdup(name);
2118 
2119 	while ((ptr = strchr(rptr, '[')))
2120 	{
2121 		*ptr++ = 0;
2122 		right = ptr;
2123 		if ((ptr = MatchingBracket(right, '[', ']')))
2124 			*ptr++ = 0;
2125 
2126 		if (args)
2127 			result1 = expand_alias(right, args, arg_flag, NULL);
2128 		else
2129 			result1 = right;
2130 
2131 		retval = m_3dup(rptr, ".", result1);
2132 		if (ptr)
2133 			malloc_strcat(&retval, ptr);
2134 
2135 		if (args)
2136 			new_free(&result1);
2137 		if (rptr)
2138 			new_free(&rptr);
2139 		rptr = retval;
2140 	}
2141 	return upper(rptr);
2142 }
2143 
2144 long BX_my_atol (const char *str)
2145 {
2146 	if (str)
2147 		return (long) strtol(str, NULL, 0);
2148 	else
2149 		return 0L;
2150 }
2151 
2152 #if 0
2153 u_long hashpjw (char *text, u_long prime)
2154 {
2155 	char *p;
2156 	u_long h = 0, g;
2157 
2158 	for (p = text; *p; p++)
2159 	{
2160 		h <<= 4;
2161 		h += *p;
2162 		if ((g = h & 0xf0000000))
2163 		{
2164 			h ^= (g >> 24);
2165 			h ^= g;
2166 		}
2167 	}
2168 	return h % prime;
2169 }
2170 #endif
2171 
2172 char *BX_m_dupchar(int i)
2173 {
2174 	char c = (char) i;	/* blah */
2175 	char *ret = (char *)new_malloc(2);
2176 
2177 	ret[0] = c;
2178 	ret[1] = 0;
2179 	return ret;
2180 }
2181 
2182 #ifdef INCLUDE_DEADCODE
2183 /*
2184  * This checks to see if ``root'' is a proper subname for ``var''.
2185  */
2186 int is_root (char *root, char *var, int descend)
2187 {
2188 	int rootl, varl;
2189 
2190 	/* ``root'' must end in a dot */
2191 	rootl = strlen(root);
2192 	if (root[rootl] != '.')
2193 		return 0;
2194 
2195 	/* ``root'' must be shorter than ``var'' */
2196 	varl = strlen(var);
2197 	if (varl <= rootl)
2198 		return 0;
2199 
2200 	/* ``var'' must contain ``root'' as a leading subset */
2201 	if (my_strnicmp(root, var, rootl))
2202 		return 0;
2203 
2204 	/*
2205 	 * ``var'' must not contain any additional dots
2206 	 * if we are checking for the current level only
2207 	 */
2208 	if (!descend && strchr(var + rootl, '.'))
2209 		return 0;
2210 
2211 	/* Looks like its ok */
2212 	return 1;
2213 }
2214 #endif
2215 
2216 /* Returns the number of characters they are equal at. */
2217 size_t BX_streq (const char *one, const char *two)
2218 {
2219 	size_t cnt = 0;
2220 
2221 	while (*one && *two && (*one == *two))
2222 		cnt++, one++, two++;
2223 
2224 	return cnt;
2225 }
2226 
2227 /* Returns the number of characters they are equal at. */
2228 size_t BX_strieq (const char *one, const char *two)
2229 {
2230 	size_t cnt = 0;
2231 
2232 	while (*one && *two && (toupper(*one) == toupper(*two)))
2233 		cnt++, one++, two++;
2234 
2235 	return cnt;
2236 }
2237 
2238 char *n_m_strndup (const char *str, size_t len, const char *module, const char *file, const int line)
2239 {
2240 	char *retval = (char *)n_malloc(len + 1, module, file, line);
2241 	return strmcpy(retval, (char *)str, len);
2242 }
2243 
2244 #if 0
2245 char *remove_nl (char *str)
2246 {
2247 	char *ptr;
2248 
2249 	if ((ptr = strrchr(str, '\n')))
2250 		*ptr = 0;
2251 
2252 	return str;
2253 }
2254 
2255 char *spanstr (const char *str, const char *tar)
2256 {
2257 	int cnt = 1;
2258 	const char *p;
2259 
2260 	for ( ; *str; str++, cnt++)
2261 	{
2262 		for (p = tar; *p; p++)
2263 		{
2264 			if (*p == *str)
2265 				return (char *)p;
2266 		}
2267 	}
2268 
2269 	return 0;
2270 }
2271 
2272 char *s_next_arg (char **from)
2273 {
2274 	char *next = strchr(*from, ' ');
2275 	char *keep = *from;
2276 	*from = next;
2277 	return keep;
2278 }
2279 #endif
2280 
2281 char *BX_strmopencat (char *dest, int maxlen, ...)
2282 {
2283 	va_list args;
2284 	int size;
2285 	char *this_arg = NULL;
2286 	int this_len;
2287 
2288 	size = strlen(dest);
2289 	va_start(args, maxlen);
2290 
2291 	while (size < maxlen)
2292 	{
2293 		if (!(this_arg = va_arg(args, char *)))
2294 			break;
2295 
2296 		if (size + ((this_len = strlen(this_arg))) > maxlen)
2297 			strncat(dest, this_arg, maxlen - size);
2298 		else
2299 			strcat(dest, this_arg);
2300 
2301 		size += this_len;
2302 	}
2303 
2304 	va_end(args);
2305 	return dest;
2306 }
2307 
2308 /*
2309  * An strcpy that is guaranteed to be safe for overlaps.
2310  */
2311 char *BX_ov_strcpy (char *one, const char *two)
2312 {
2313 	if (two > one)
2314 	{
2315 		while (two && *two)
2316 			*one++ = *two++;
2317 		*one = 0;
2318  	}
2319 	return one;
2320 }
2321 
2322 char *BX_next_in_comma_list (char *str, char **after)
2323 {
2324 	*after = str;
2325 
2326 	while (*after && **after && **after != ',')
2327 		(*after)++;
2328 
2329 	if (*after && **after == ',')
2330 	{
2331 		**after = 0;
2332 		(*after)++;
2333 	}
2334 
2335 	return str;
2336 }
2337 
2338 #ifdef INCLUDE_DEADCODE
2339 /*
2340  * Checks if ansi string only sets colors/attributes
2341  * ^[[m won't work anymore !!!!
2342  */
2343 void FixColorAnsi(unsigned char *str)
2344 {
2345 #if !defined(WINNT) && !defined(__EMX__)
2346     register unsigned char *tmpstr;
2347     register unsigned char *tmpstr1=NULL;
2348     int  what=0;
2349     int  numbers=0;
2350     int	 val = 0;
2351 
2352 	tmpstr=str;
2353 	while (*tmpstr)
2354 	{
2355 		if ((*tmpstr>='0' && *tmpstr<='9'))
2356 		{
2357 			numbers = 1;
2358 			val = val * 10 + (*tmpstr - '0');
2359 		}
2360 		else if (*tmpstr==';')
2361 			numbers = 1, val = 0;
2362 		else if (!(*tmpstr=='m' || *tmpstr=='C'))
2363 			numbers = val = 0;
2364 		if (*tmpstr==0x1B)
2365 		{
2366 			if (what && tmpstr1)
2367 				*tmpstr1+=64;
2368 			what=1;
2369 			tmpstr1=tmpstr;
2370 		}
2371 		else if (*tmpstr==0x18 || *tmpstr==0x0E)
2372 			*tmpstr+=64;
2373 		if (what && numbers && (val > 130))
2374 		{
2375 			what = numbers = val = 0;
2376 			*tmpstr1+=64;
2377 		}
2378 		if (what && *tmpstr=='m')
2379 		{
2380 			if (!numbers || (val == 12))
2381 			{
2382 				*tmpstr1+=64;
2383 				tmpstr1=tmpstr;
2384 			}
2385 			what=0;
2386 			numbers = val = 0;
2387 		}
2388 		else if (what && *tmpstr=='C')
2389 		{
2390 			if (!numbers)
2391 			{
2392 				*tmpstr1+=64;
2393 				tmpstr1=tmpstr;
2394 			}
2395 			what=0;
2396 			numbers = val = 0;
2397 		}
2398 		else if (what && *tmpstr=='J')
2399 		{
2400 			val = numbers = 0;
2401 			*tmpstr1 +=64;
2402 			tmpstr1=tmpstr;
2403 			what = 0;
2404 		}
2405 		else if (what && *tmpstr=='(')
2406 			what=2;
2407 		else if (what == 2 && (*tmpstr == '0'))
2408 			*tmpstr1 += 64;
2409 		else if (what == 2 && (*tmpstr=='U' || *tmpstr=='B'))
2410 			what=0;
2411 		tmpstr++;
2412 	}
2413 	if (what && tmpstr1 && *tmpstr1)
2414 		*tmpstr1+=64;
2415 #endif
2416 }
2417 
2418 #endif
2419 /* Dest should be big enough to hold "src" */
2420 void	BX_strip_control (const char *src, char *dest)
2421 {
2422 	for (; *src; src++)
2423 	{
2424 		if (isgraph((unsigned char)*src) || isspace((unsigned char)*src))
2425 			*dest++ = *src;
2426 	}
2427 
2428 	*dest++ = 0;
2429 }
2430 
2431 /*
2432  * figure_out_address
2433  */
2434 int	BX_figure_out_address (char *nuh, char **nick, char **user, char **host, char **domain, int *ip)
2435 {
2436 	static char 	*mystuff = NULL;
2437 	char 	*firstback, *secondback, *thirdback, *fourthback;
2438 	char 	*bang, *at, *myhost = star, *endstring;
2439 	int	number;
2440 
2441 	/* Dont bother with channels, theyre ok. */
2442 	if (*nuh == '#' || *nuh == '&')
2443 		return -1;
2444 
2445 	malloc_strcpy(&mystuff, nuh);
2446 
2447 	*nick = *user = *host = *domain = star;
2448 	*ip = 0;
2449 
2450 	bang = strchr(mystuff, '!');
2451 	at = strchr(mystuff, '@');
2452 
2453 	if (!bang && !at)
2454 	{
2455 		if (strchr(mystuff, '.') || strchr(mystuff, ':'))
2456 			myhost = mystuff;
2457 		else
2458 		{
2459 			*nick = mystuff;
2460 			return 0;
2461 		}
2462 	}
2463 
2464 	if (bang == mystuff)
2465 		*user = bang + 1;
2466 	else if (bang)
2467 	{
2468 		*nick = mystuff;
2469 		*bang = 0;
2470 		*user = bang + 1;
2471 	}
2472 	else
2473 		*user = mystuff;
2474 
2475 	if (at)
2476 	{
2477 		if (*user == star)
2478 			*user = mystuff;
2479 		*at = 0;
2480 		myhost = at + 1;
2481 	}
2482 
2483 	/*
2484 	 * At this point, 'myhost' points what what we think the hostname
2485 	 * is.  We chop it up into discrete parts and see what we end up with.
2486 	 */
2487 	endstring = myhost + strlen(myhost);
2488 	firstback = strnrchr(myhost, '.', 1);
2489 	secondback = strnrchr(myhost, '.', 2);
2490 	thirdback = strnrchr(myhost, '.', 3);
2491 	fourthback = strnrchr(myhost, '.', 4);
2492 
2493 	/* Track foo@bar or some such thing. */
2494 	if (!firstback)
2495 	{
2496 		*host = myhost;
2497 		return 0;
2498 	}
2499 
2500 	/*
2501 	 * IP address (A.B.C.D)
2502 	 */
2503 	if (my_atol(firstback + 1))
2504 	{
2505 		*ip = 1;
2506 		*domain = myhost;
2507 
2508 		number = my_atol(myhost);
2509 		if (number < 128)
2510 			*host = thirdback;
2511 		else if (number < 192)
2512 			*host = secondback;
2513 		else
2514 			*host = firstback;
2515 
2516 		**host = 0;
2517 		(*host)++;
2518 	}
2519 	/*
2520 	 *	(*).(*.???)
2521 	 *			Handles *.com, *.net, *.edu, etc
2522 	 */
2523 	else if (secondback && (endstring - firstback == 4))
2524 	{
2525 		*host = myhost;
2526 		*domain = secondback;
2527 		**domain = 0;
2528 		(*domain)++;
2529 	}
2530 	/*
2531 	 *	(*).(*.k12.??.us)
2532 	 *			Handles host.school.k12.state.us
2533 	 */
2534 	else if (fourthback &&
2535 			(firstback - secondback == 3) &&
2536 			!strncmp(thirdback, ".k12.", 5) &&
2537 			!strncmp(firstback, ".us", 3))
2538 	{
2539 		*host = myhost;
2540 		*domain = fourthback;
2541 		**domain = 0;
2542 		(*domain)++;
2543 	}
2544 	/*
2545 	 *	()(*.k12.??.us)
2546 	 *			Handles school.k12.state.us
2547 	 */
2548 	else if (thirdback && !fourthback &&
2549 			(firstback - secondback == 3) &&
2550 			!strncmp(thirdback, ".k12.", 5) &&
2551 			!strncmp(firstback, ".us", 3))
2552 	{
2553 		*host = empty_string;
2554 		*domain = myhost;
2555 	}
2556 	/*
2557 	 *	(*).(*.???.??)
2558 	 *			Handles host.domain.com.au
2559 	 */
2560 	else if (thirdback &&
2561 			(endstring - firstback == 3) &&
2562 			(firstback - secondback == 4))
2563 	{
2564 		*host = myhost;
2565 		*domain = thirdback;
2566 		**domain = 0;
2567 		(*domain)++;
2568 	}
2569 	/*
2570 	 *	()(*.???.??)
2571 	 *			Handles domain.com.au
2572 	 */
2573 	else if (secondback && !thirdback &&
2574 			(endstring - firstback == 3) &&
2575 		 	(firstback - secondback == 4))
2576 	{
2577 		*host = empty_string;
2578 		*domain = myhost;
2579 	}
2580 	/*
2581 	 *	(*).(*.??.??)
2582 	 *			Handles host.domain.co.uk
2583 	 */
2584 	else if (thirdback &&
2585 			(endstring - firstback == 3) &&
2586 			(firstback - secondback == 3))
2587 	{
2588 		*host = myhost;
2589 		*domain = thirdback;
2590 		**domain = 0;
2591 		(*domain)++;
2592 	}
2593 	/*
2594 	 *	()(*.??.??)
2595 	 *			Handles domain.co.uk
2596 	 */
2597 	else if (secondback && !thirdback &&
2598 			(endstring - firstback == 3) &&
2599 			(firstback - secondback == 3))
2600 	{
2601 		*host = empty_string;
2602 		*domain = myhost;
2603 	}
2604 	/*
2605 	 *	(*).(*.??)
2606 	 *			Handles domain.de
2607 	 */
2608 	else if (secondback && (endstring - firstback == 3))
2609 	{
2610 		*host = myhost;
2611 		*domain = secondback;
2612 		**domain = 0;
2613 		(*domain)++;
2614 	}
2615 	/*
2616 	 *	Everything else...
2617 	 */
2618 	else
2619 	{
2620 		*host = empty_string;
2621 		*domain = myhost;
2622 	}
2623 
2624 	return 0;
2625 }
2626 
2627 #ifdef INCLUDE_DEADCODE
2628 int count_char (const unsigned char *src, const unsigned char look)
2629 {
2630 	const unsigned char *t;
2631 	int	cnt = 0;
2632 
2633 	while ((t = strchr(src, look)))
2634 		cnt++, src = t + 1;
2635 
2636 	return cnt;
2637 }
2638 #endif
2639 
2640 char 	*BX_strnrchr(char *start, char which, int howmany)
2641 {
2642 	char *ends = start + strlen(start);
2643 
2644 	while (ends > start && howmany)
2645 	{
2646 		if (*--ends == which)
2647 			howmany--;
2648 	}
2649 	if (ends == start)
2650 		return NULL;
2651 	else
2652 		return ends;
2653 }
2654 
2655 /*
2656  * This replaces some number of numbers (1 or more) with a single asterisk.
2657  * We know that the final strcpy() is safe, since we never make a string that
2658  * is longer than the source string, always less than or equal in size.
2659  */
2660 void	BX_mask_digits (char **hostname)
2661 {
2662 	char	*src_ptr;
2663 	char 	*retval, *retval_ptr;
2664 
2665 	retval = retval_ptr = alloca(strlen(*hostname) + 1);
2666 	src_ptr = *hostname;
2667 
2668 	while (*src_ptr)
2669 	{
2670 		if (isdigit((unsigned char)*src_ptr))
2671 		{
2672 			while (*src_ptr && isdigit((unsigned char)*src_ptr))
2673 				src_ptr++;
2674 
2675 			*retval_ptr++ = '*';
2676 		}
2677 		else
2678 			*retval_ptr++ = *src_ptr++;
2679 	}
2680 
2681 	*retval_ptr = 0;
2682 	strcpy(*hostname, retval);
2683 	return;
2684 }
2685 
2686 /*
2687  * Its like strcspn, except the seconD arg is NOT a string.
2688  */
2689 size_t 	BX_ccspan (const char *string, int s)
2690 {
2691 	size_t count = 0;
2692 	char c = (char) s;
2693 
2694 	while (string && *string && *string != c)
2695 		string++, count++;
2696 
2697 	return count;
2698 }
2699 
2700 #ifdef INCLUDE_DEADCODE
2701 int 	last_char (const char *string)
2702 {
2703 	while (string && string[0] && string[1])
2704 		string++;
2705 
2706 	return (int)*string;
2707 }
2708 #endif
2709 
2710 int	BX_charcount (const char *string, char what)
2711 {
2712 	int x = 0;
2713 	const char *place = string;
2714 
2715 	while (*place)
2716 		if (*place++ == what)
2717 			x++;
2718 
2719 	return x;
2720 }
2721 
2722 char *	encode(const char *str, int len)
2723 {
2724 	char *retval;
2725 	char *ptr;
2726 
2727 	if (len == -1)
2728 		len = strlen(str);
2729 
2730 	ptr = retval = new_malloc(len * 2 + 1);
2731 
2732 	while (len)
2733 	{
2734 		*ptr++ = (*str >> 4) + 0x41;
2735 		*ptr++ = (*str & 0x0f) + 0x41;
2736 		str++;
2737 		len--;
2738  	}
2739 	*ptr = 0;
2740 	return retval;
2741 }
2742 
2743 char *	decode(const char *str)
2744 {
2745 	char *retval;
2746 	char *ptr;
2747 	int len = strlen(str);
2748 
2749 	ptr = retval = new_malloc(len / 2 + 1);
2750 	while (len >= 2)
2751 	{
2752 		*ptr++ = ((str[0] - 0x41) << 4) | (str[1] - 0x41);
2753 		str += 2;
2754 		len -= 2;
2755 	}
2756 	*ptr = 0;
2757 	return retval;
2758 }
2759 
2760 char *	chomp (char *s)
2761 {
2762 	char *e = s + strlen(s);
2763 
2764 	if (e == s)
2765 		return s;
2766 
2767 	while (*--e == '\n')
2768 	{
2769 		*e = 0;
2770 		if (e == s)
2771 			break;
2772 	}
2773 
2774 	return s;
2775 }
2776 
2777 char	*BX_strpcat (char *source, const char *format, ...)
2778 {
2779 	va_list args;
2780 	char	buffer[BIG_BUFFER_SIZE + 1];
2781 
2782 	va_start(args, format);
2783 	vsnprintf(buffer, BIG_BUFFER_SIZE, format, args);
2784 	va_end(args);
2785 
2786 	strcat(source, buffer);
2787 	return source;
2788 }
2789 
2790 char *	BX_strmpcat (char *source, size_t siz, const char *format, ...)
2791 {
2792 	va_list args;
2793 	char	buffer[BIG_BUFFER_SIZE + 1];
2794 
2795 	va_start(args, format);
2796 	vsnprintf(buffer, BIG_BUFFER_SIZE, format, args);
2797 	va_end(args);
2798 
2799 	strmcat(source, buffer, siz);
2800 	return source;
2801 }
2802 
2803 
2804 
2805 u_char	*BX_strcpy_nocolorcodes (u_char *dest, const u_char *source)
2806 {
2807 	u_char	*save = dest;
2808 
2809 	do
2810 	{
2811 		while (*source == 3)
2812 			source = skip_ctl_c_seq(source, NULL, NULL, 0);
2813 		*dest++ = *source;
2814 	}
2815 	while (*source++);
2816 
2817 	return save;
2818 }
2819 
2820 char *crypt();
2821 
2822 char *BX_cryptit(const char *string)
2823 {
2824 static char saltChars[] =
2825 	"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./0123456789";
2826 char *cpass = (char *)string;
2827 char salt[3];
2828 	salt[0] = saltChars[random_number(0) % (sizeof(saltChars) - 1)];
2829 	salt[1] = saltChars[random_number(0) % (sizeof(saltChars) - 1)];
2830 	salt[2] = 0;
2831 #if !defined(WINNT)
2832 	cpass = crypt(string, salt);
2833 #endif
2834 	return cpass;
2835 }
2836 
2837 int checkpass(const char *password, const char *old)
2838 {
2839 	char seed[3], *p;
2840 	seed[0] = old[0];
2841 	seed[1] = old[1];
2842 	seed[2] = 0;
2843 #if !defined(WINNT)
2844 	p = crypt(password, seed);
2845 #else
2846 	p = password;
2847 #endif
2848 	return strcmp(p, old);
2849 }
2850 
2851 
2852 char *BX_stripdev(char *ttynam)
2853 {
2854 	if (ttynam == NULL)
2855 		return NULL;
2856 #ifdef SVR4
2857   /* unixware has /dev/pts012 as synonym for /dev/pts/12 */
2858 	if (!strncmp(ttynam, "/dev/pts", 8) && ttynam[8] >= '0' && ttynam[8] <= '9')
2859 	{
2860 		static char b[13];
2861 		sprintf(b, "pts/%d", atoi(ttynam + 8));
2862 		return b;
2863 	}
2864 #endif /* SVR4 */
2865 	if (!strncmp(ttynam, "/dev/", 5))
2866 		return ttynam + 5;
2867 	return ttynam;
2868 }
2869 
2870 
2871 void init_socketpath(void)
2872 {
2873 #if !defined(__EMX__) && !defined(WINNT)
2874 struct stat st;
2875 extern char socket_path[], attach_ttyname[];
2876 
2877 	sprintf(socket_path, "%s/.BitchX/screens", my_path);
2878 	if (access(socket_path, F_OK))
2879 	{
2880 		if (mkdir(socket_path, 0700) != -1)
2881 			(void) chown(socket_path, getuid(), getgid());
2882 		else
2883 			return;
2884 	}
2885 	if (stat(socket_path, &st) != -1)
2886 	{
2887 		char host[BIG_BUFFER_SIZE+1];
2888 		char *ap;
2889 		if (!S_ISDIR(st.st_mode))
2890 			return;
2891 		gethostname(host, BIG_BUFFER_SIZE);
2892 		if ((ap = strchr(host, '.')))
2893 			*ap = 0;
2894 		ap = &socket_path[strlen(socket_path)];
2895 		sprintf(ap, "/%%d.%s.%s", stripdev(attach_ttyname), host);
2896 		ap++;
2897 		for ( ; *ap; ap++)
2898 			if (*ap == '/')
2899 				*ap = '-';
2900 	}
2901 #endif
2902 }
2903 
2904 /*
2905  * This mangles up 'incoming' corresponding to the current values of
2906  * /set mangle_inbound or /set mangle_outbound.
2907  * 'incoming' needs to be at _least_ thrice as big as neccesary
2908  * (ie, sizeof(incoming) >= strlen(incoming) * 3 + 1)
2909  */
2910 size_t	BX_mangle_line	(char *incoming, int how, size_t how_much)
2911 {
2912 	int	stuff;
2913 	char	*buffer;
2914 	int	i;
2915 	char	*s;
2916 
2917 	stuff = how;
2918 	buffer = alloca(how_much + 1);	/* Absurdly large */
2919 
2920 #if notyet
2921 	if (stuff & STRIP_CTCP2)
2922 	{
2923 		char *output;
2924 
2925 		output = strip_ctcp2(incoming);
2926 		strlcpy(incoming, output, how_much);
2927 		new_free(&output);
2928 	}
2929 	else if (stuff & MANGLE_INBOUND_CTCP2)
2930 	{
2931 		char *output;
2932 
2933 		output = ctcp2_to_ircII(incoming);
2934 		strlcpy(incoming, output, how_much);
2935 		new_free(&output);
2936 	}
2937 	else if (stuff & MANGLE_OUTBOUND_CTCP2)
2938 	{
2939 		char *output;
2940 
2941 		output = ircII_to_ctcp2(incoming);
2942 		strlcpy(incoming, output, how_much);
2943 		new_free(&output);
2944 	}
2945 #endif
2946 
2947 	if (stuff & MANGLE_ESCAPES)
2948 	{
2949 		for (i = 0; incoming[i]; i++)
2950 		{
2951 			if (incoming[i] == 0x1b)
2952 				incoming[i] = 0x5b;
2953 		}
2954 	}
2955 
2956 	if (stuff & MANGLE_ANSI_CODES)
2957 	{
2958 		/* strip_ansi can expand up to three times */
2959 		char *output;
2960 
2961 		strip_ansi_never_xlate = 1;	/* XXXXX */
2962 		output = strip_ansi(incoming);
2963 		strip_ansi_never_xlate = 0;	/* XXXXX */
2964 		if (strlcpy(incoming, output, how_much) > how_much)
2965 			say("Mangle_line truncating results (%d > %d) - "
2966 				"please email " BUG_EMAIL,
2967 				strlen(output), how_much);
2968 		new_free(&output);
2969 	}
2970 
2971 	/*
2972 	 * Now we mangle the individual codes
2973 	 */
2974 	for (i = 0, s = incoming; *s; s++)
2975 	{
2976 		switch (*s)
2977 		{
2978 			case 003:		/* color codes */
2979 			{
2980 				int 		lhs = 0,
2981 						rhs = 0;
2982 				char 		*end;
2983 
2984 				end = (char *)skip_ctl_c_seq(s, &lhs, &rhs, 0);
2985 				if (!(stuff & STRIP_COLOR))
2986 				{
2987 					while (s < end)
2988 						buffer[i++] = *s++;
2989 				}
2990 				s = end - 1;
2991 				break;
2992 			}
2993 			case REV_TOG:		/* Reverse */
2994 			{
2995 				if (!(stuff & STRIP_REVERSE))
2996 					buffer[i++] = REV_TOG;
2997 				break;
2998 			}
2999 			case UND_TOG:		/* Underline */
3000 			{
3001 				if (!(stuff & STRIP_UNDERLINE))
3002 					buffer[i++] = UND_TOG;
3003 				break;
3004 			}
3005 			case BOLD_TOG:		/* Bold */
3006 			{
3007 				if (!(stuff & STRIP_BOLD))
3008 					buffer[i++] = BOLD_TOG;
3009 				break;
3010 			}
3011 			case BLINK_TOG: 	/* Flashing */
3012 			{
3013 				if (!(stuff & STRIP_BLINK))
3014 					buffer[i++] = BLINK_TOG;
3015 				break;
3016 			}
3017 			case ROM_CHAR:		/* Special rom-chars */
3018 			{
3019 				if (!(stuff & STRIP_ROM_CHAR))
3020 					buffer[i++] = ROM_CHAR;
3021 				break;
3022 			}
3023 			case ND_SPACE:		/* Nondestructive spaces */
3024 			{
3025 				if (!(stuff & STRIP_ND_SPACE))
3026 					buffer[i++] = ND_SPACE;
3027 				break;
3028 			}
3029 			case ALT_TOG:		/* Alternate character set */
3030 			{
3031 				if (!(stuff & STRIP_ALT_CHAR))
3032 					buffer[i++] = ALT_TOG;
3033 				break;
3034 			}
3035 			case ALL_OFF:		/* ALL OFF attribute */
3036 			{
3037 				if (!(stuff & STRIP_ALL_OFF))
3038 					buffer[i++] = ALL_OFF;
3039 				break;
3040 			}
3041 			default:
3042 				buffer[i++] = *s;
3043 		}
3044 	}
3045 
3046 	buffer[i] = 0;
3047 	return strlcpy(incoming, buffer, how_much);
3048 }
3049 
3050 void strip_chars(char *buffer, char *strip, char replace)
3051 {
3052 char *p;
3053 	if (!buffer || !*buffer || !strip || !*strip || !replace)
3054 		return;
3055 	while (*strip)
3056 	{
3057 		while ((p = strchr(buffer, *strip)))
3058 			*p = replace;
3059 		strip++;
3060 	}
3061 }
3062 
3063 char *longcomma(long val)
3064 {
3065 char buffer[40];
3066 static char buff[40];
3067 char *s = buff;
3068 int i = 0, j = 0, len;
3069 	sprintf(buffer, "%ld", val);
3070 	len = strlen(buffer);
3071 	for (i = len % 3; i > 0; i--)
3072 		*s++ = buffer[j++];
3073 	if (len > 3 && len % 3)
3074 		*s++ = ',';
3075 	len -= (len % 3);
3076 	while (len --)
3077 	{
3078 		*s++ = buffer[j++];
3079 		if (!(len % 3) && len)
3080 			*s++ = ',';
3081 	}
3082 	*s = 0;
3083 	return buff;
3084 }
3085 
3086 char *ulongcomma(unsigned long val)
3087 {
3088 char buffer[40];
3089 static char buff[40];
3090 char *s = buff;
3091 int i = 0, j = 0, len;
3092 	sprintf(buffer, "%lu", val);
3093 	len = strlen(buffer);
3094 	for (i = len % 3; i > 0; i--)
3095 		*s++ = buffer[j++];
3096 	if (len > 3 && len % 3)
3097 		*s++ = ',';
3098 	len -= (len % 3);
3099 	while (len --)
3100 	{
3101 		*s++ = buffer[j++];
3102 		if (!(len % 3) && len)
3103 			*s++ = ',';
3104 	}
3105 	*s = 0;
3106 	return buff;
3107 }
3108 
3109 /* XXXX this doesnt belong here. im not sure where it goes, though. */
3110 char *	get_userhost (void)
3111 {
3112 	strlcpy(userhost, username, sizeof userhost);
3113 	strlcat(userhost, "@", sizeof userhost);
3114 	strlcat(userhost, hostname, sizeof userhost);
3115 	return userhost;
3116 }
3117 
3118 
3119 
3120 /* RANDOM NUMBERS */
3121 /*
3122  * Random number generator #1 -- psuedo-random sequence
3123  * If you do not have /dev/random and do not want to use gettimeofday(), then
3124  * you can use the psuedo-random number generator.  Its performance varies
3125  * from weak to moderate.  It is a predictable mathematical sequence that
3126  * varies depending on the seed, and it provides very little repetition,
3127  * but with 4 or 5 samples, it should be trivial for an outside person to
3128  * find the next numbers in your sequence.
3129  *
3130  * If 'l' is not zero, then it is considered a "seed" value.  You want
3131  * to call it once to set the seed.  Subsequent calls should use 'l'
3132  * as 0, and it will return a value.
3133  */
3134 unsigned long randm(unsigned long l)
3135 {
3136 	/* patch from Sarayan to make $rand() better */
3137 	static const long RAND_A = 16807L;
3138 	static const long RAND_M = 2147483647L;
3139 	static const long RAND_Q = 127773L;
3140 	static const int RAND_R = 2836L;
3141 	static unsigned long z = 0;
3142 
3143 	if (z == 0)
3144 	{
3145 		struct timeval tv;
3146 
3147 		get_time(&tv);
3148 		z = tv.tv_usec << 12;
3149 		z ^= (unsigned long)tv.tv_sec;
3150 		z ^= (unsigned long)getuid() << 16;
3151 		z ^= (unsigned long)getpid();
3152 	}
3153 
3154 	if (l == 0)
3155 	{
3156 		long t = RAND_A * (z % RAND_Q) - RAND_R * (z / RAND_Q);
3157 		if (t > 0)
3158 			z = t;
3159 		else
3160 			z = t + RAND_M;
3161 		return (z >> 8) | ((z & 255) << 23);
3162 	}
3163 	else
3164 	{
3165 		z = l;
3166 		return 0;
3167 	}
3168 }
3169 
3170 /*
3171  * Random number generator #2 -- gettimeofday().
3172  * If you have gettimeofday(), then we could use it.  Its performance varies
3173  * from weak to moderate.  At best, it is a source of modest entropy, with
3174  * distinct linear qualities. At worst, it is a linear sequence.  If you do
3175  * not have gettimeofday(), then it uses randm() instead.
3176  */
3177 static unsigned long randt_2 (void)
3178 {
3179 	struct timeval 	tp1;
3180 	get_time(&tp1);
3181 	return (unsigned long) tp1.tv_usec;
3182 }
3183 
3184 unsigned long randt(unsigned long l)
3185 {
3186 #ifdef HAVE_GETTIMEOFDAY
3187 	unsigned long t1, t2, t;
3188 
3189 	if (l != 0)
3190 		return 0;
3191 
3192 	t1 = randt_2();
3193 	t2 = randt_2();
3194 	t = (t1 & 65535) * 65536 + (t2 & 65535);
3195 	return t;
3196 #else
3197 	return randm(0);
3198 #endif
3199 }
3200 
3201 
3202 /*
3203  * Random number generator #3 -- /dev/urandom.
3204  * If you have the /dev/urandom device, then we will use it.  Its performance
3205  * varies from moderate to very strong.  At best, it is a source of pretty
3206  * substantial unpredictable numbers.  At worst, it is mathematical psuedo-
3207  * random sequence (which randm() is).
3208  */
3209 unsigned long randd(unsigned long l)
3210 {
3211 	unsigned long	value;
3212 static	int		random_fd = -1;
3213 
3214 	if (l != 0)
3215 		return 0;	/* No seeding appropriate */
3216 
3217 	if (random_fd == -2)
3218 		return randm(0);
3219 
3220 	else if (random_fd == -1)
3221 	{
3222 		if ((random_fd = open("/dev/urandom", O_RDONLY)) == -1)
3223 		{
3224 			random_fd = -2;
3225 			return randm(0);	/* Fall back to randm */
3226 		}
3227 	}
3228 
3229 	read(random_fd, (void *)&value, sizeof(value));
3230 	return value;
3231 }
3232 
3233 unsigned long BX_random_number(unsigned long l)
3234 {
3235 	/* Always use the strongest random source for internal client use. */
3236 	return randd(l);
3237 }
3238 
3239 /*
3240  * Copyright (c) 1995-2001 Kungliga Tekniska H�gskolan
3241  * (Royal Institute of Technology, Stockholm, Sweden).
3242  * All rights reserved.
3243  *
3244  * This is licensed under the 3-clause BSD license, which is found above.
3245  */
3246 /*
3247  * Return a malloced, base64 string representation of the first 'size' bytes
3248  * starting at 'data'.
3249  */
3250 char *base64_encode(const void *data, size_t size)
3251 {
3252 	static const char base64_chars[] =
3253 		"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
3254 	char *s, *p;
3255 	size_t i;
3256 	unsigned c;
3257 	const unsigned char * const q = data;
3258 
3259 	p = s = new_malloc((size + 2) / 3 * 4 + 1);
3260 
3261 	for (i = 0; i < size;) {
3262 		c = q[i++];
3263 		c *= 256;
3264 		if (i < size)
3265 			c += q[i];
3266 		i++;
3267 		c *= 256;
3268 		if (i < size)
3269 			c += q[i];
3270 		i++;
3271 		p[0] = base64_chars[(c & 0x00fc0000) >> 18];
3272 		p[1] = base64_chars[(c & 0x0003f000) >> 12];
3273 		p[2] = base64_chars[(c & 0x00000fc0) >> 6];
3274 		p[3] = base64_chars[(c & 0x0000003f) >> 0];
3275 		if (i > size)
3276 			p[3] = '=';
3277 		if (i > size + 1)
3278 			p[2] = '=';
3279 		p += 4;
3280 	}
3281 	*p = 0;
3282 
3283 	return s;
3284 }
3285