1 /*********************************************************************
3 * File : $Source: /cvsroot/ijbswa/current/miscutil.c,v $
5 * Purpose : zalloc, hash_string, strcmpic, strncmpic, and
6 * MinGW32 strdup functions. These are each too small
7 * to deserve their own file but don't really fit in
10 * Copyright : Written by and Copyright (C) 2001-2020 the
11 * Privoxy team. https://www.privoxy.org/
13 * Based on the Internet Junkbuster originally written
14 * by and Copyright (C) 1997 Anonymous Coders and
15 * Junkbusters Corporation. http://www.junkbusters.com
17 * The timegm replacement function was taken from GnuPG,
18 * Copyright (C) 2004 Free Software Foundation, Inc.
20 * This program is free software; you can redistribute it
21 * and/or modify it under the terms of the GNU General
22 * Public License as published by the Free Software
23 * Foundation; either version 2 of the License, or (at
24 * your option) any later version.
26 * This program is distributed in the hope that it will
27 * be useful, but WITHOUT ANY WARRANTY; without even the
28 * implied warranty of MERCHANTABILITY or FITNESS FOR A
29 * PARTICULAR PURPOSE. See the GNU General Public
30 * License for more details.
32 * The GNU General Public License should be included with
33 * this file. If not, you can view it at
34 * http://www.gnu.org/copyleft/gpl.html
35 * or write to the Free Software Foundation, Inc., 59
36 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 *********************************************************************/
44 #include <sys/types.h>
48 #endif /* #if !defined(_WIN32) */
53 #if !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV)
55 #endif /* !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV) */
62 /*********************************************************************
66 * Description : Returns allocated memory that is initialized
70 * 1 : size = Size of memory chunk to return.
72 * Returns : Pointer to newly alloc'd memory chunk.
74 *********************************************************************/
75 void *zalloc(size_t size)
80 ret = calloc(1, size);
82 #warning calloc appears to be unavailable. Your platform will become unsupported in the future
83 if ((ret = (void *)malloc(size)) != NULL)
94 /*********************************************************************
96 * Function : zalloc_or_die
98 * Description : zalloc wrapper that either succeeds or causes
99 * program termination.
101 * Useful in situations were the string length is
102 * "small" and zalloc() failures couldn't be handled
103 * better anyway. In case of debug builds, failures
104 * trigger an assert().
107 * 1 : size = Size of memory chunk to return.
109 * Returns : Pointer to newly malloc'd memory chunk.
111 *********************************************************************/
112 void *zalloc_or_die(size_t size)
116 buffer = zalloc(size);
119 assert(buffer != NULL);
120 log_error(LOG_LEVEL_FATAL, "Out of memory in zalloc_or_die().");
128 /*********************************************************************
130 * Function : strdup_or_die
132 * Description : strdup wrapper that either succeeds or causes
133 * program termination.
135 * Useful in situations were the string length is
136 * "small" and strdup() failures couldn't be handled
137 * better anyway. In case of debug builds, failures
138 * trigger an assert().
141 * 1 : str = String to duplicate
143 * Returns : Pointer to newly strdup'd copy of the string.
145 *********************************************************************/
146 char *strdup_or_die(const char *str)
150 new_str = strdup(str);
154 assert(new_str != NULL);
155 log_error(LOG_LEVEL_FATAL, "Out of memory in strdup_or_die().");
164 /*********************************************************************
166 * Function : malloc_or_die
168 * Description : malloc wrapper that either succeeds or causes
169 * program termination.
171 * Useful in situations were the buffer size is "small"
172 * and malloc() failures couldn't be handled better
173 * anyway. In case of debug builds, failures trigger
177 * 1 : buffer_size = Size of the space to allocate
179 * Returns : Pointer to newly malloc'd memory
181 *********************************************************************/
182 void *malloc_or_die(size_t buffer_size)
186 if (buffer_size == 0)
188 log_error(LOG_LEVEL_ERROR,
189 "malloc_or_die() called with buffer size 0");
190 assert(buffer_size != 0);
194 new_buf = malloc(buffer_size);
198 assert(new_buf != NULL);
199 log_error(LOG_LEVEL_FATAL, "Out of memory in malloc_or_die().");
209 /*********************************************************************
211 * Function : write_pid_file
213 * Description : Writes a pid file with the pid of the main process.
214 * Exits if the file can't be opened
217 * 1 : pid_file = Path of the pid file that gets created.
221 *********************************************************************/
222 void write_pid_file(const char *pid_file)
226 if ((fp = fopen(pid_file, "w")) == NULL)
228 log_error(LOG_LEVEL_FATAL, "can't open pid file '%s': %E", pid_file);
232 fprintf(fp, "%u\n", (unsigned int) getpid());
238 #endif /* def unix */
241 /*********************************************************************
243 * Function : hash_string
245 * Description : Take a string and compute a (hopefuly) unique numeric
246 * integer value. This is useful to "switch" a string.
249 * 1 : s : string to be hashed.
251 * Returns : The string's hash
253 *********************************************************************/
254 unsigned int hash_string(const char* s)
260 h = 5 * h + (unsigned int)*s;
268 /*********************************************************************
270 * Function : strcmpic
272 * Description : Case insensitive string comparison
275 * 1 : s1 = string 1 to compare
276 * 2 : s2 = string 2 to compare
278 * Returns : 0 if s1==s2, Negative if s1<s2, Positive if s1>s2
280 *********************************************************************/
281 int strcmpic(const char *s1, const char *s2)
288 if ((*s1 != *s2) && (privoxy_tolower(*s1) != privoxy_tolower(*s2)))
294 return(privoxy_tolower(*s1) - privoxy_tolower(*s2));
299 /*********************************************************************
301 * Function : strncmpic
303 * Description : Case insensitive string comparison (up to n characters)
306 * 1 : s1 = string 1 to compare
307 * 2 : s2 = string 2 to compare
308 * 3 : n = maximum characters to compare
310 * Returns : 0 if s1==s2, Negative if s1<s2, Positive if s1>s2
312 *********************************************************************/
313 int strncmpic(const char *s1, const char *s2, size_t n)
315 if (n <= (size_t)0) return(0);
321 if ((*s1 != *s2) && (privoxy_tolower(*s1) != privoxy_tolower(*s2)))
326 if (--n <= (size_t)0) break;
330 return(privoxy_tolower(*s1) - privoxy_tolower(*s2));
335 /*********************************************************************
339 * Description : In-situ-eliminate all leading and trailing whitespace
343 * 1 : s : string to be chomped.
345 * Returns : chomped string
347 *********************************************************************/
348 char *chomp(char *string)
353 * strip trailing whitespace
355 p = string + strlen(string);
356 while (p > string && privoxy_isspace(*(p-1)))
363 * find end of leading whitespace
366 while (*q && privoxy_isspace(*q))
372 * if there was any, move the rest forwards
387 /*********************************************************************
389 * Function : string_append
391 * Description : Reallocate target_string and append text to it.
392 * This makes it easier to append to malloc'd strings.
393 * This is similar to the (removed) strsav(), but
394 * running out of memory isn't catastrophic.
398 * The following style provides sufficient error
399 * checking for this routine, with minimal clutter
400 * in the source code. It is recommended if you
401 * have many calls to this function:
403 * char * s = strdup(...); // don't check for error
404 * string_append(&s, ...); // don't check for error
405 * string_append(&s, ...); // don't check for error
406 * string_append(&s, ...); // don't check for error
407 * if (NULL == s) { ... handle error ... }
411 * char * s = strdup(...); // don't check for error
412 * string_append(&s, ...); // don't check for error
413 * string_append(&s, ...); // don't check for error
414 * if (string_append(&s, ...)) {... handle error ...}
417 * 1 : target_string = Pointer to old text that is to be
418 * extended. *target_string will be free()d by this
419 * routine. target_string must be non-NULL.
420 * If *target_string is NULL, this routine will
421 * do nothing and return with an error - this allows
422 * you to make many calls to this routine and only
423 * check for errors after the last one.
424 * 2 : text_to_append = Text to be appended to old.
427 * Returns : JB_ERR_OK on success, and sets *target_string
428 * to newly malloc'ed appended string. Caller
429 * must free(*target_string).
430 * JB_ERR_MEMORY on out-of-memory. (And free()s
431 * *target_string and sets it to NULL).
432 * JB_ERR_MEMORY if *target_string is NULL.
434 *********************************************************************/
435 jb_err string_append(char **target_string, const char *text_to_append)
441 assert(target_string);
442 assert(text_to_append);
444 if (*target_string == NULL)
446 return JB_ERR_MEMORY;
449 if (*text_to_append == '\0')
454 old_len = strlen(*target_string);
456 new_size = strlen(text_to_append) + old_len + 1;
458 if (NULL == (new_string = realloc(*target_string, new_size)))
460 free(*target_string);
462 *target_string = NULL;
463 return JB_ERR_MEMORY;
466 strlcpy(new_string + old_len, text_to_append, new_size - old_len);
468 *target_string = new_string;
473 /*********************************************************************
475 * Function : string_join
477 * Description : Join two strings together. Frees BOTH the original
478 * strings. If either or both input strings are NULL,
479 * fails as if it had run out of memory.
481 * For comparison, string_append requires that the
482 * second string is non-NULL, and doesn't free it.
484 * Rationale: Too often, we want to do
485 * string_append(s, html_encode(s2)). That assert()s
486 * if s2 is NULL or if html_encode() runs out of memory.
487 * It also leaks memory. Proper checking is cumbersome.
488 * The solution: string_join(s, html_encode(s2)) is safe,
489 * and will free the memory allocated by html_encode().
492 * 1 : target_string = Pointer to old text that is to be
493 * extended. *target_string will be free()d by this
494 * routine. target_string must be non-NULL.
495 * 2 : text_to_append = Text to be appended to old.
497 * Returns : JB_ERR_OK on success, and sets *target_string
498 * to newly malloc'ed appended string. Caller
499 * must free(*target_string).
500 * JB_ERR_MEMORY on out-of-memory, or if
501 * *target_string or text_to_append is NULL. (In
502 * this case, frees *target_string and text_to_append,
503 * sets *target_string to NULL).
505 *********************************************************************/
506 jb_err string_join(char **target_string, char *text_to_append)
510 assert(target_string);
512 if (text_to_append == NULL)
514 freez(*target_string);
515 return JB_ERR_MEMORY;
518 err = string_append(target_string, text_to_append);
520 freez(text_to_append);
526 /*********************************************************************
528 * Function : string_toupper
530 * Description : Produce a copy of string with all convertible
531 * characters converted to uppercase.
534 * 1 : string = string to convert
536 * Returns : Uppercase copy of string if possible,
537 * NULL on out-of-memory or if string was NULL.
539 *********************************************************************/
540 char *string_toupper(const char *string)
545 if (!string || ((result = (char *) zalloc(strlen(string) + 1)) == NULL))
555 *p++ = (char)toupper((int) *q++);
563 /*********************************************************************
565 * Function : string_move
567 * Description : memmove wrapper to move the last part of a string
568 * towards the beginning, overwriting the part in
569 * the middle. strlcpy() can't be used here as the
573 * 1 : dst = Destination to overwrite
574 * 2 : src = Source to move.
578 *********************************************************************/
579 void string_move(char *dst, char *src)
583 /* +1 to copy the terminating nul as well. */
584 memmove(dst, src, strlen(src)+1);
588 /*********************************************************************
592 * Description : Duplicate the first n characters of a string that may
593 * contain '\0' characters.
596 * 1 : string = string to be duplicated
597 * 2 : len = number of bytes to duplicate
599 * Returns : pointer to copy, or NULL if failiure
601 *********************************************************************/
602 char *bindup(const char *string, size_t len)
606 duplicate = (char *)malloc(len);
607 if (NULL != duplicate)
609 memcpy(duplicate, string, len);
617 /*********************************************************************
619 * Function : make_path
621 * Description : Takes a directory name and a file name, returns
622 * the complete path. Handles windows/unix differences.
623 * If the file name is already an absolute path, or if
624 * the directory name is NULL or empty, it returns
628 * 1 : dir: Name of directory or NULL for none.
629 * 2 : file: Name of file. Should not be NULL or empty.
631 * Returns : "dir/file" (Or on windows, "dir\file").
632 * It allocates the string on the heap. Caller frees.
633 * Returns NULL in error (i.e. NULL file or out of
636 *********************************************************************/
637 char * make_path(const char * dir, const char * file)
639 if ((file == NULL) || (*file == '\0'))
641 return NULL; /* Error */
644 if ((dir == NULL) || (*dir == '\0') /* No directory specified */
646 || (*file == '\\') || (file[1] == ':') /* Absolute path (DOS) */
647 #else /* ifndef _WIN32 */
648 || (*file == '/') /* Absolute path (U*ix) */
649 #endif /* ifndef _WIN32 */
657 size_t path_size = strlen(dir) + strlen(file) + 2; /* +2 for trailing (back)slash and \0 */
660 if (*dir != '/' && basedir && *basedir)
663 * Relative path, so start with the base directory.
665 path_size += strlen(basedir) + 1; /* +1 for the slash */
666 path = malloc(path_size);
667 if (!path) log_error(LOG_LEVEL_FATAL, "malloc failed!");
668 strlcpy(path, basedir, path_size);
669 strlcat(path, "/", path_size);
670 strlcat(path, dir, path_size);
673 #endif /* defined unix */
675 path = malloc(path_size);
676 if (!path) log_error(LOG_LEVEL_FATAL, "malloc failed!");
677 strlcpy(path, dir, path_size);
680 assert(NULL != path);
682 if (path[strlen(path)-1] != '\\')
684 strlcat(path, "\\", path_size);
686 #else /* ifndef _WIN32 */
687 if (path[strlen(path)-1] != '/')
689 strlcat(path, "/", path_size);
691 #endif /* ifndef _WIN32 */
692 strlcat(path, file, path_size);
699 /*********************************************************************
701 * Function : pick_from_range
703 * Description : Pick a positive number out of a given range.
704 * Should only be used if randomness would be nice,
705 * but isn't really necessary.
708 * 1 : range: Highest possible number to pick.
710 * Returns : Picked number.
712 *********************************************************************/
713 long int pick_from_range(long int range)
717 static unsigned long seed = 0;
718 #endif /* def _WIN32 */
723 if (range <= 0) return 0;
725 #ifdef HAVE_ARC4RANDOM
726 number = arc4random() % range + 1;
727 #elif defined(HAVE_RANDOM)
728 number = random() % range + 1;
729 #elif defined(MUTEX_LOCKS_AVAILABLE)
730 privoxy_mutex_lock(&rand_mutex);
734 seed = (unsigned long)(GetCurrentThreadId()+GetTickCount());
737 seed = (unsigned long)((rand() << 16) + rand());
738 #endif /* def _WIN32 */
739 number = (unsigned long)((rand() << 16) + (rand())) % (unsigned long)(range + 1);
740 privoxy_mutex_unlock(&rand_mutex);
743 * XXX: Which platforms reach this and are there
744 * better options than just using rand() and hoping
747 log_error(LOG_LEVEL_INFO, "No thread-safe PRNG available? Header time randomization "
748 "might cause crashes, predictable results or even combine these fine options.");
749 number = rand() % (long int)(range + 1);
751 #endif /* (def HAVE_ARC4RANDOM) */
757 #ifdef USE_PRIVOXY_STRLCPY
758 /*********************************************************************
760 * Function : privoxy_strlcpy
762 * Description : strlcpy(3) look-alike for those without decent libc.
765 * 1 : destination: buffer to copy into.
766 * 2 : source: String to copy.
767 * 3 : size: Size of destination buffer.
769 * Returns : The length of the string that privoxy_strlcpy() tried to create.
771 *********************************************************************/
772 size_t privoxy_strlcpy(char *destination, const char *source, const size_t size)
776 snprintf(destination, size, "%s", source);
778 * Platforms that lack strlcpy() also tend to have
779 * a broken snprintf implementation that doesn't
780 * guarantee nul termination.
782 * XXX: the configure script should detect and reject those.
784 destination[size-1] = '\0';
786 return strlen(source);
788 #endif /* def USE_PRIVOXY_STRLCPY */
792 /*********************************************************************
794 * Function : privoxy_strlcat
796 * Description : strlcat(3) look-alike for those without decent libc.
799 * 1 : destination: C string.
800 * 2 : source: String to copy.
801 * 3 : size: Size of destination buffer.
803 * Returns : The length of the string that privoxy_strlcat() tried to create.
805 *********************************************************************/
806 size_t privoxy_strlcat(char *destination, const char *source, const size_t size)
808 const size_t old_length = strlen(destination);
809 return old_length + strlcpy(destination + old_length, source, size - old_length);
811 #endif /* ndef HAVE_STRLCAT */
814 /*********************************************************************
816 * Function : privoxy_millisleep
818 * Description : Sleep a number of milliseconds
821 * 1 : delay: Number of milliseconds to sleep
823 * Returns : -1 on error, 0 otherwise
825 *********************************************************************/
826 int privoxy_millisleep(unsigned milliseconds)
828 #ifdef HAVE_NANOSLEEP
829 struct timespec rqtp = {0};
830 struct timespec rmtp = {0};
832 rqtp.tv_sec = milliseconds / 1000;
833 rqtp.tv_nsec = (milliseconds % 1000) * 1000 * 1000;
835 return nanosleep(&rqtp, &rmtp);
836 #elif defined (_WIN32)
841 #warning Missing privoxy_milisleep() implementation. delay-response{} will not work.
844 #endif /* def HAVE_NANOSLEEP */
849 /*********************************************************************
851 * Function : privoxy_gmtime_r
853 * Description : Behave like gmtime_r() and convert a
854 * time_t to a struct tm.
857 * 1 : time_spec: The time to convert
858 * 2 : result: The struct tm to use as storage
860 * Returns : Pointer to the result or NULL on error.
862 *********************************************************************/
863 struct tm *privoxy_gmtime_r(const time_t *time_spec, struct tm *result)
868 timeptr = gmtime_r(time_spec, result);
869 #elif defined(MUTEX_LOCKS_AVAILABLE)
870 privoxy_mutex_lock(&gmtime_mutex);
871 timeptr = gmtime(time_spec);
873 #warning Using unlocked gmtime()
874 timeptr = gmtime(time_spec);
879 #if !defined(HAVE_GMTIME_R) && defined(MUTEX_LOCKS_AVAILABLE)
880 privoxy_mutex_unlock(&gmtime_mutex);
885 #if !defined(HAVE_GMTIME_R)
888 #ifdef MUTEX_LOCKS_AVAILABLE
889 privoxy_mutex_unlock(&gmtime_mutex);
896 #if !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV)
897 /*********************************************************************
901 * Description : libc replacement function for the inverse of gmtime().
902 * Copyright (C) 2004 Free Software Foundation, Inc.
904 * Code originally copied from GnuPG, modifications done
905 * for Privoxy: style changed, #ifdefs for _WIN32 added
906 * to have it work on mingw32.
908 * XXX: It's very unlikely to happen, but if the malloc()
909 * call fails the time zone will be permanently set to UTC.
912 * 1 : tm: Broken-down time struct.
914 * Returns : tm converted into time_t seconds.
916 *********************************************************************/
917 time_t timegm(struct tm *tm)
930 old_zone = malloc(3 + strlen(zone) + 1);
933 strcpy(old_zone, "TZ=");
934 strcat(old_zone, zone);
937 /* http://man7.org/linux/man-pages/man3/putenv.3.html
938 * int putenv(char *string);
939 * The string pointed to by string becomes part of the environment, so altering the
940 * string changes the environment.
941 * In other words, the memory pointed to by *string is used until
942 * a) another call to putenv() with the same e-var name
943 * b) the program exits
945 * Windows e-vars don't work that way, so let's not leak memory.
948 #endif /* def _WIN32 */
955 #elif defined(_WIN32)
965 #endif /* !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV) */