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