+/*********************************************************************
+ *
+ * Function : pick_from_range
+ *
+ * Description : Pick a positive number out of a given range.
+ * Should only be used if randomness would be nice,
+ * but isn't really necessary.
+ *
+ * Parameters :
+ * 1 : range: Highest possible number to pick.
+ *
+ * Returns : Picked number.
+ *
+ *********************************************************************/
+long int pick_from_range(long int range)
+{
+ long int number;
+
+ assert(range != 0);
+ assert(range > 0);
+
+ if (range <= 0) return 0;
+
+#ifdef HAVE_RANDOM
+ number = random() % range + 1;
+#elif defined(FEATURE_PTHREAD)
+ pthread_mutex_lock(&rand_mutex);
+ number = rand() % (long int)(range + 1);
+ pthread_mutex_unlock(&rand_mutex);
+#else
+#ifdef _WIN32
+ /*
+ * On Windows and mingw32 srand() has to be called in every
+ * rand()-using thread, but can cause crashes if it's not
+ * mutex protected.
+ *
+ * Currently we don't have mutexes for mingw32, and for
+ * our purpose this cludge is probably preferable to crashes.
+ *
+ * The warning is shown once on startup from jcc.c.
+ */
+ number = (range + GetCurrentThreadId() % range) / 2;
+#else
+ /*
+ * XXX: Which platforms reach this and are there
+ * better options than just using rand() and hoping
+ * that it's safe?
+ */
+ log_error(LOG_LEVEL_INFO, "No thread-safe PRNG available? Header time randomization might cause "
+ "crashes, predictable results or even combine these fine options.");
+ number = rand() % (long int)(range + 1);
+#endif /* def _WIN32 */
+
+#endif /* (def HAVE_RANDOM) */
+
+ return number;
+}
+
+
+#ifdef USE_PRIVOXY_STRLCPY
+/*********************************************************************
+ *
+ * Function : privoxy_strlcpy
+ *
+ * Description : strlcpy(3) look-alike for those without decent libc.
+ *
+ * Parameters :
+ * 1 : destination: buffer to copy into.
+ * 2 : source: String to copy.
+ * 3 : size: Size of destination buffer.
+ *
+ * Returns : The length of the string that privoxy_strlcpy() tried to create.
+ *
+ *********************************************************************/
+size_t privoxy_strlcpy(char *destination, const char *source, const size_t size)
+{
+ if (0 < size)
+ {
+ snprintf(destination, size, "%s", source);
+ /*
+ * Platforms that lack strlcpy() also tend to have
+ * a broken snprintf implementation that doesn't
+ * guarantee nul termination.
+ *
+ * XXX: the configure script should detect and reject those.
+ */
+ destination[size-1] = '\0';
+ }
+ return strlen(source);
+}
+#endif /* def USE_PRIVOXY_STRLCPY */
+
+
+#ifndef HAVE_STRLCAT
+/*********************************************************************
+ *
+ * Function : privoxy_strlcat
+ *
+ * Description : strlcat(3) look-alike for those without decent libc.
+ *
+ * Parameters :
+ * 1 : destination: C string.
+ * 2 : source: String to copy.
+ * 3 : size: Size of destination buffer.
+ *
+ * Returns : The length of the string that privoxy_strlcat() tried to create.
+ *
+ *********************************************************************/
+size_t privoxy_strlcat(char *destination, const char *source, const size_t size)
+{
+ const size_t old_length = strlen(destination);
+ return old_length + strlcpy(destination + old_length, source, size - old_length);
+}
+#endif /* ndef HAVE_STRLCAT */
+
+
+#if !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV)
+/*********************************************************************
+ *
+ * Function : timegm
+ *
+ * Description : libc replacement function for the inverse of gmtime().
+ * Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * Code originally copied from GnuPG, modifications done
+ * for Privoxy: style changed, #ifdefs for _WIN32 added
+ * to have it work on mingw32.
+ *
+ * XXX: It's very unlikely to happen, but if the malloc()
+ * call fails the time zone will be permanently set to UTC.
+ *
+ * Parameters :
+ * 1 : tm: Broken-down time struct.
+ *
+ * Returns : tm converted into time_t seconds.
+ *
+ *********************************************************************/
+time_t timegm(struct tm *tm)
+{
+ time_t answer;
+ char *zone;
+
+ zone = getenv("TZ");
+ putenv("TZ=UTC");
+ tzset();
+ answer = mktime(tm);
+ if (zone)
+ {
+ char *old_zone;
+
+ old_zone = malloc(3 + strlen(zone) + 1);
+ if (old_zone)
+ {
+ strcpy(old_zone, "TZ=");
+ strcat(old_zone, zone);
+ putenv(old_zone);
+#ifdef _WIN32
+ free(old_zone);
+#endif /* def _WIN32 */
+ }
+ }
+ else
+ {
+#ifdef HAVE_UNSETENV
+ unsetenv("TZ");
+#elif defined(_WIN32)
+ putenv("TZ=");
+#else
+ putenv("TZ");
+#endif
+ }
+ tzset();
+
+ return answer;
+}
+#endif /* !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV) */
+
+
+#ifndef HAVE_SNPRINTF