1 /*********************************************************************
2  *
3  * File        :  $Source: /cvsroot/ijbswa/current/miscutil.c,v $
4  *
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
8  *                any other file.
9  *
10  * Copyright   :  Written by and Copyright (C) 2001-2020 the
11  *                Privoxy team. https://www.privoxy.org/
12  *
13  *                Based on the Internet Junkbuster originally written
14  *                by and Copyright (C) 1997 Anonymous Coders and
15  *                Junkbusters Corporation.  http://www.junkbusters.com
16  *
17  *                The timegm replacement function was taken from GnuPG,
18  *                Copyright (C) 2004 Free Software Foundation, Inc.
19  *
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.
25  *
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.
31  *
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.
37  *
38  *********************************************************************/
39 
40 
41 #include "config.h"
42 
43 #include <stdio.h>
44 #include <sys/types.h>
45 #include <stdlib.h>
46 #if !defined(_WIN32)
47 #include <unistd.h>
48 #endif /* #if !defined(_WIN32) */
49 #include <string.h>
50 #include <ctype.h>
51 #include <assert.h>
52 
53 #if !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV)
54 #include <time.h>
55 #endif /* !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV) */
56 
57 #include "project.h"
58 #include "miscutil.h"
59 #include "jcc.h"
60 #include "errlog.h"
61 
62 /*********************************************************************
63  *
64  * Function    :  zalloc
65  *
66  * Description :  Returns allocated memory that is initialized
67  *                with zeros.
68  *
69  * Parameters  :
70  *          1  :  size = Size of memory chunk to return.
71  *
72  * Returns     :  Pointer to newly alloc'd memory chunk.
73  *
74  *********************************************************************/
zalloc(size_t size)75 void *zalloc(size_t size)
76 {
77    void * ret;
78 
79 #ifdef HAVE_CALLOC
80    ret = calloc(1, size);
81 #else
82 #warning calloc appears to be unavailable. Your platform will become unsupported in the future
83    if ((ret = (void *)malloc(size)) != NULL)
84    {
85       memset(ret, 0, size);
86    }
87 #endif
88 
89    return(ret);
90 
91 }
92 
93 
94 /*********************************************************************
95  *
96  * Function    :  zalloc_or_die
97  *
98  * Description :  zalloc wrapper that either succeeds or causes
99  *                program termination.
100  *
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().
105  *
106  * Parameters  :
107  *          1  :  size = Size of memory chunk to return.
108  *
109  * Returns     :  Pointer to newly malloc'd memory chunk.
110  *
111  *********************************************************************/
zalloc_or_die(size_t size)112 void *zalloc_or_die(size_t size)
113 {
114    void *buffer;
115 
116    buffer = zalloc(size);
117    if (buffer == NULL)
118    {
119       assert(buffer != NULL);
120       log_error(LOG_LEVEL_FATAL, "Out of memory in zalloc_or_die().");
121       exit(1);
122    }
123 
124    return(buffer);
125 
126 }
127 
128 /*********************************************************************
129  *
130  * Function    :  strdup_or_die
131  *
132  * Description :  strdup wrapper that either succeeds or causes
133  *                program termination.
134  *
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().
139  *
140  * Parameters  :
141  *          1  :  str = String to duplicate
142  *
143  * Returns     :  Pointer to newly strdup'd copy of the string.
144  *
145  *********************************************************************/
strdup_or_die(const char * str)146 char *strdup_or_die(const char *str)
147 {
148    char *new_str;
149 
150    new_str = strdup(str);
151 
152    if (new_str == NULL)
153    {
154       assert(new_str != NULL);
155       log_error(LOG_LEVEL_FATAL, "Out of memory in strdup_or_die().");
156       exit(1);
157    }
158 
159    return(new_str);
160 
161 }
162 
163 
164 /*********************************************************************
165  *
166  * Function    :  malloc_or_die
167  *
168  * Description :  malloc wrapper that either succeeds or causes
169  *                program termination.
170  *
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
174  *                an assert().
175  *
176  * Parameters  :
177  *          1  :  buffer_size = Size of the space to allocate
178  *
179  * Returns     :  Pointer to newly malloc'd memory
180  *
181  *********************************************************************/
malloc_or_die(size_t buffer_size)182 void *malloc_or_die(size_t buffer_size)
183 {
184    char *new_buf;
185 
186    if (buffer_size == 0)
187    {
188       log_error(LOG_LEVEL_ERROR,
189          "malloc_or_die() called with buffer size 0");
190       assert(buffer_size != 0);
191       buffer_size = 4096;
192    }
193 
194    new_buf = malloc(buffer_size);
195 
196    if (new_buf == NULL)
197    {
198       assert(new_buf != NULL);
199       log_error(LOG_LEVEL_FATAL, "Out of memory in malloc_or_die().");
200       exit(1);
201    }
202 
203    return(new_buf);
204 
205 }
206 
207 
208 #if defined(unix)
209 /*********************************************************************
210  *
211  * Function    :  write_pid_file
212  *
213  * Description :  Writes a pid file with the pid of the main process.
214  *                Exits if the file can't be opened
215  *
216  * Parameters  :
217  *          1  :  pid_file = Path of the pid file that gets created.
218  *
219  * Returns     :  N/A
220  *
221  *********************************************************************/
write_pid_file(const char * pid_file)222 void write_pid_file(const char *pid_file)
223 {
224    FILE   *fp;
225 
226    if ((fp = fopen(pid_file, "w")) == NULL)
227    {
228       log_error(LOG_LEVEL_FATAL, "can't open pid file '%s': %E", pid_file);
229    }
230    else
231    {
232       fprintf(fp, "%u\n", (unsigned int) getpid());
233       fclose (fp);
234    }
235    return;
236 
237 }
238 #endif /* def unix */
239 
240 
241 /*********************************************************************
242  *
243  * Function    :  hash_string
244  *
245  * Description :  Take a string and compute a (hopefully) unique numeric
246  *                integer value. This is useful to "switch" a string.
247  *
248  * Parameters  :
249  *          1  :  s : string to be hashed.
250  *
251  * Returns     :  The string's hash
252  *
253  *********************************************************************/
hash_string(const char * s)254 unsigned int hash_string(const char* s)
255 {
256    unsigned int h = 0;
257 
258    for (; *s; ++s)
259    {
260       h = 5 * h + (unsigned int)*s;
261    }
262 
263    return (h);
264 
265 }
266 
267 
268 /*********************************************************************
269  *
270  * Function    :  strcmpic
271  *
272  * Description :  Case insensitive string comparison
273  *
274  * Parameters  :
275  *          1  :  s1 = string 1 to compare
276  *          2  :  s2 = string 2 to compare
277  *
278  * Returns     :  0 if s1==s2, Negative if s1<s2, Positive if s1>s2
279  *
280  *********************************************************************/
strcmpic(const char * s1,const char * s2)281 int strcmpic(const char *s1, const char *s2)
282 {
283    if (!s1) s1 = "";
284    if (!s2) s2 = "";
285 
286    while (*s1 && *s2)
287    {
288       if ((*s1 != *s2) && (privoxy_tolower(*s1) != privoxy_tolower(*s2)))
289       {
290          break;
291       }
292       s1++, s2++;
293    }
294    return(privoxy_tolower(*s1) - privoxy_tolower(*s2));
295 
296 }
297 
298 
299 /*********************************************************************
300  *
301  * Function    :  strncmpic
302  *
303  * Description :  Case insensitive string comparison (up to n characters)
304  *
305  * Parameters  :
306  *          1  :  s1 = string 1 to compare
307  *          2  :  s2 = string 2 to compare
308  *          3  :  n = maximum characters to compare
309  *
310  * Returns     :  0 if s1==s2, Negative if s1<s2, Positive if s1>s2
311  *
312  *********************************************************************/
strncmpic(const char * s1,const char * s2,size_t n)313 int strncmpic(const char *s1, const char *s2, size_t n)
314 {
315    if (n <= (size_t)0) return(0);
316    if (!s1) s1 = "";
317    if (!s2) s2 = "";
318 
319    while (*s1 && *s2)
320    {
321       if ((*s1 != *s2) && (privoxy_tolower(*s1) != privoxy_tolower(*s2)))
322       {
323          break;
324       }
325 
326       if (--n <= (size_t)0) break;
327 
328       s1++, s2++;
329    }
330    return(privoxy_tolower(*s1) - privoxy_tolower(*s2));
331 
332 }
333 
334 
335 /*********************************************************************
336  *
337  * Function    :  chomp
338  *
339  * Description :  In-situ-eliminate all leading and trailing whitespace
340  *                from a string.
341  *
342  * Parameters  :
343  *          1  :  s : string to be chomped.
344  *
345  * Returns     :  chomped string
346  *
347  *********************************************************************/
chomp(char * string)348 char *chomp(char *string)
349 {
350    char *p, *q, *r;
351 
352    /*
353     * strip trailing whitespace
354     */
355    p = string + strlen(string);
356    while (p > string && privoxy_isspace(*(p-1)))
357    {
358       p--;
359    }
360    *p = '\0';
361 
362    /*
363     * find end of leading whitespace
364     */
365    q = r = string;
366    while (*q && privoxy_isspace(*q))
367    {
368       q++;
369    }
370 
371    /*
372     * if there was any, move the rest forwards
373     */
374    if (q != string)
375    {
376       while (q <= p)
377       {
378          *r++ = *q++;
379       }
380    }
381 
382    return(string);
383 
384 }
385 
386 
387 /*********************************************************************
388  *
389  * Function    :  string_append
390  *
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.
395  *
396  *                Programming style:
397  *
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:
402  *
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 ... }
408  *
409  *                OR, equivalently:
410  *
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 ...}
415  *
416  * Parameters  :
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.
425  *                Must not be NULL.
426  *
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.
433  *
434  *********************************************************************/
string_append(char ** target_string,const char * text_to_append)435 jb_err string_append(char **target_string, const char *text_to_append)
436 {
437    size_t old_len;
438    char *new_string;
439    size_t new_size;
440 
441    assert(target_string);
442    assert(text_to_append);
443 
444    if (*target_string == NULL)
445    {
446       return JB_ERR_MEMORY;
447    }
448 
449    if (*text_to_append == '\0')
450    {
451       return JB_ERR_OK;
452    }
453 
454    old_len = strlen(*target_string);
455 
456    new_size = strlen(text_to_append) + old_len + 1;
457 
458    if (NULL == (new_string = realloc(*target_string, new_size)))
459    {
460       free(*target_string);
461 
462       *target_string = NULL;
463       return JB_ERR_MEMORY;
464    }
465 
466    strlcpy(new_string + old_len, text_to_append, new_size - old_len);
467 
468    *target_string = new_string;
469    return JB_ERR_OK;
470 }
471 
472 
473 /*********************************************************************
474  *
475  * Function    :  string_join
476  *
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.
480  *
481  *                For comparison, string_append requires that the
482  *                second string is non-NULL, and doesn't free it.
483  *
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().
490  *
491  * Parameters  :
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.
496  *
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).
504  *
505  *********************************************************************/
string_join(char ** target_string,char * text_to_append)506 jb_err string_join(char **target_string, char *text_to_append)
507 {
508    jb_err err;
509 
510    assert(target_string);
511 
512    if (text_to_append == NULL)
513    {
514       freez(*target_string);
515       return JB_ERR_MEMORY;
516    }
517 
518    err = string_append(target_string, text_to_append);
519 
520    freez(text_to_append);
521 
522    return err;
523 }
524 
525 
526 /*********************************************************************
527  *
528  * Function    :  string_toupper
529  *
530  * Description :  Produce a copy of string with all convertible
531  *                characters converted to uppercase.
532  *
533  * Parameters  :
534  *          1  :  string = string to convert
535  *
536  * Returns     :  Uppercase copy of string if possible,
537  *                NULL on out-of-memory or if string was NULL.
538  *
539  *********************************************************************/
string_toupper(const char * string)540 char *string_toupper(const char *string)
541 {
542    char *result, *p;
543    const char *q;
544 
545    if (!string || ((result = (char *) zalloc(strlen(string) + 1)) == NULL))
546    {
547       return NULL;
548    }
549 
550    q = string;
551    p = result;
552 
553    while (*q != '\0')
554    {
555       *p++ = (char)toupper((int) *q++);
556    }
557 
558    return result;
559 
560 }
561 
562 
563 /*********************************************************************
564  *
565  * Function    :  string_tolower
566  *
567  * Description :  Produce a copy of string with all convertible
568  *                characters converted to lowercase.
569  *
570  * Parameters  :
571  *          1  :  string = string to convert
572  *
573  * Returns     :  Lowercase copy of string if possible,
574  *                NULL on out-of-memory or if string was NULL.
575  *
576  *********************************************************************/
string_tolower(const char * string)577 char *string_tolower(const char *string)
578 {
579    char *result, *p;
580    const char *q;
581 
582    if (!string || ((result = (char *)zalloc(strlen(string) + 1)) == NULL))
583    {
584       return NULL;
585    }
586 
587    q = string;
588    p = result;
589 
590    while (*q != '\0')
591    {
592       *p++ = (char)privoxy_tolower(*q++);
593    }
594 
595    return result;
596 
597 }
598 
599 
600 /*********************************************************************
601  *
602  * Function    :  string_move
603  *
604  * Description :  memmove wrapper to move the last part of a string
605  *                towards the beginning, overwriting the part in
606  *                the middle. strlcpy() can't be used here as the
607  *                strings overlap.
608  *
609  * Parameters  :
610  *          1  :  dst = Destination to overwrite
611  *          2  :  src = Source to move.
612  *
613  * Returns     :  N/A
614  *
615  *********************************************************************/
string_move(char * dst,char * src)616 void string_move(char *dst, char *src)
617 {
618    assert(dst < src);
619 
620    /* +1 to copy the terminating nul as well. */
621    memmove(dst, src, strlen(src)+1);
622 }
623 
624 
625 /*********************************************************************
626  *
627  * Function    :  bindup
628  *
629  * Description :  Duplicate the first n characters of a string that may
630  *                contain '\0' characters.
631  *
632  * Parameters  :
633  *          1  :  string = string to be duplicated
634  *          2  :  len = number of bytes to duplicate
635  *
636  * Returns     :  pointer to copy, or NULL if failure
637  *
638  *********************************************************************/
bindup(const char * string,size_t len)639 char *bindup(const char *string, size_t len)
640 {
641    char *duplicate;
642 
643    duplicate = (char *)malloc(len);
644    if (NULL != duplicate)
645    {
646       memcpy(duplicate, string, len);
647    }
648 
649    return duplicate;
650 
651 }
652 
653 
654 /*********************************************************************
655  *
656  * Function    :  make_path
657  *
658  * Description :  Takes a directory name and a file name, returns
659  *                the complete path.  Handles windows/unix differences.
660  *                If the file name is already an absolute path, or if
661  *                the directory name is NULL or empty, it returns
662  *                the filename.
663  *
664  * Parameters  :
665  *          1  :  dir: Name of directory or NULL for none.
666  *          2  :  file: Name of file.  Should not be NULL or empty.
667  *
668  * Returns     :  "dir/file" (Or on windows, "dir\file").
669  *                It allocates the string on the heap.  Caller frees.
670  *                Returns NULL in error (i.e. NULL file or out of
671  *                memory)
672  *
673  *********************************************************************/
make_path(const char * dir,const char * file)674 char * make_path(const char * dir, const char * file)
675 {
676    if ((file == NULL) || (*file == '\0'))
677    {
678       return NULL; /* Error */
679    }
680 
681    if ((dir == NULL) || (*dir == '\0') /* No directory specified */
682 #if defined(_WIN32)
683       || (*file == '\\') || (file[1] == ':') /* Absolute path (DOS) */
684 #else /* ifndef _WIN32 */
685       || (*file == '/') /* Absolute path (U*ix) */
686 #endif /* ifndef _WIN32 */
687       )
688    {
689       return strdup(file);
690    }
691    else
692    {
693       char * path;
694       size_t path_size = strlen(dir) + strlen(file) + 2; /* +2 for trailing (back)slash and \0 */
695 
696 #if defined(unix)
697       if (*dir != '/' && basedir && *basedir)
698       {
699          /*
700           * Relative path, so start with the base directory.
701           */
702          path_size += strlen(basedir) + 1; /* +1 for the slash */
703          path = malloc(path_size);
704          if (!path) log_error(LOG_LEVEL_FATAL, "malloc failed!");
705          strlcpy(path, basedir, path_size);
706          strlcat(path, "/", path_size);
707          strlcat(path, dir, path_size);
708       }
709       else
710 #endif /* defined unix */
711       {
712          path = malloc(path_size);
713          if (!path) log_error(LOG_LEVEL_FATAL, "malloc failed!");
714          strlcpy(path, dir, path_size);
715       }
716 
717       assert(NULL != path);
718 #if defined(_WIN32)
719       if (path[strlen(path)-1] != '\\')
720       {
721          strlcat(path, "\\", path_size);
722       }
723 #else /* ifndef _WIN32 */
724       if (path[strlen(path)-1] != '/')
725       {
726          strlcat(path, "/", path_size);
727       }
728 #endif /* ifndef _WIN32 */
729       strlcat(path, file, path_size);
730 
731       return path;
732    }
733 }
734 
735 
736 /*********************************************************************
737  *
738  * Function    :  pick_from_range
739  *
740  * Description :  Pick a positive number out of a given range.
741  *                Should only be used if randomness would be nice,
742  *                but isn't really necessary.
743  *
744  * Parameters  :
745  *          1  :  range: Highest possible number to pick.
746  *
747  * Returns     :  Picked number.
748  *
749  *********************************************************************/
pick_from_range(long int range)750 long int pick_from_range(long int range)
751 {
752    long int number;
753 #ifdef _WIN32
754    static unsigned long seed = 0;
755 #endif /* def _WIN32 */
756 
757    assert(range != 0);
758    assert(range > 0);
759 
760    if (range <= 0) return 0;
761 
762 #ifdef HAVE_ARC4RANDOM
763    number = arc4random() % range + 1;
764 #elif defined(HAVE_RANDOM)
765    number = random() % range + 1;
766 #elif defined(MUTEX_LOCKS_AVAILABLE)
767    privoxy_mutex_lock(&rand_mutex);
768 #ifdef _WIN32
769    if (!seed)
770    {
771       seed = (unsigned long)(GetCurrentThreadId()+GetTickCount());
772    }
773    srand(seed);
774    seed = (unsigned long)((rand() << 16) + rand());
775 #endif /* def _WIN32 */
776    number = (unsigned long)((rand() << 16) + (rand())) % (unsigned long)(range + 1);
777    privoxy_mutex_unlock(&rand_mutex);
778 #else
779    /*
780     * XXX: Which platforms reach this and are there
781     * better options than just using rand() and hoping
782     * that it's safe?
783     */
784    log_error(LOG_LEVEL_INFO, "No thread-safe PRNG available? Header time randomization "
785       "might cause crashes, predictable results or even combine these fine options.");
786    number = rand() % (long int)(range + 1);
787 
788 #endif /* (def HAVE_ARC4RANDOM) */
789 
790    return number;
791 }
792 
793 
794 #ifdef USE_PRIVOXY_STRLCPY
795 /*********************************************************************
796  *
797  * Function    :  privoxy_strlcpy
798  *
799  * Description :  strlcpy(3) look-alike for those without decent libc.
800  *
801  * Parameters  :
802  *          1  :  destination: buffer to copy into.
803  *          2  :  source: String to copy.
804  *          3  :  size: Size of destination buffer.
805  *
806  * Returns     :  The length of the string that privoxy_strlcpy() tried to create.
807  *
808  *********************************************************************/
privoxy_strlcpy(char * destination,const char * source,const size_t size)809 size_t privoxy_strlcpy(char *destination, const char *source, const size_t size)
810 {
811    if (0 < size)
812    {
813       snprintf(destination, size, "%s", source);
814       /*
815        * Platforms that lack strlcpy() also tend to have
816        * a broken snprintf implementation that doesn't
817        * guarantee nul termination.
818        *
819        * XXX: the configure script should detect and reject those.
820        */
821       destination[size-1] = '\0';
822    }
823    return strlen(source);
824 }
825 #endif /* def USE_PRIVOXY_STRLCPY */
826 
827 
828 #ifndef HAVE_STRLCAT
829 /*********************************************************************
830  *
831  * Function    :  privoxy_strlcat
832  *
833  * Description :  strlcat(3) look-alike for those without decent libc.
834  *
835  * Parameters  :
836  *          1  :  destination: C string.
837  *          2  :  source: String to copy.
838  *          3  :  size: Size of destination buffer.
839  *
840  * Returns     :  The length of the string that privoxy_strlcat() tried to create.
841  *
842  *********************************************************************/
privoxy_strlcat(char * destination,const char * source,const size_t size)843 size_t privoxy_strlcat(char *destination, const char *source, const size_t size)
844 {
845    const size_t old_length = strlen(destination);
846    return old_length + strlcpy(destination + old_length, source, size - old_length);
847 }
848 #endif /* ndef HAVE_STRLCAT */
849 
850 
851 /*********************************************************************
852  *
853  * Function    :  privoxy_millisleep
854  *
855  * Description :  Sleep a number of milliseconds
856  *
857  * Parameters  :
858  *          1  :  delay: Number of milliseconds to sleep
859  *
860  * Returns     :  -1 on error, 0 otherwise
861  *
862  *********************************************************************/
privoxy_millisleep(unsigned milliseconds)863 int privoxy_millisleep(unsigned milliseconds)
864 {
865 #ifdef HAVE_NANOSLEEP
866    struct timespec rqtp = {0};
867    struct timespec rmtp = {0};
868 
869    rqtp.tv_sec = milliseconds / 1000;
870    rqtp.tv_nsec = (milliseconds % 1000) * 1000 * 1000;
871 
872    return nanosleep(&rqtp, &rmtp);
873 #elif defined (_WIN32)
874    Sleep(milliseconds);
875 
876    return 0;
877 #else
878 #warning Missing privoxy_milisleep() implementation. delay-response{} will not work.
879 
880    return -1;
881 #endif /* def HAVE_NANOSLEEP */
882 
883 }
884 
885 
886 /*********************************************************************
887  *
888  * Function    :  privoxy_gmtime_r
889  *
890  * Description :  Behave like gmtime_r() and convert a
891  *                time_t to a struct tm.
892  *
893  * Parameters  :
894  *          1  :  time_spec: The time to convert
895  *          2  :  result: The struct tm to use as storage
896  *
897  * Returns     :  Pointer to the result or NULL on error.
898  *
899  *********************************************************************/
privoxy_gmtime_r(const time_t * time_spec,struct tm * result)900 struct tm *privoxy_gmtime_r(const time_t *time_spec, struct tm *result)
901 {
902    struct tm *timeptr;
903 
904 #ifdef HAVE_GMTIME_R
905    timeptr = gmtime_r(time_spec, result);
906 #elif defined(MUTEX_LOCKS_AVAILABLE)
907    privoxy_mutex_lock(&gmtime_mutex);
908    timeptr = gmtime(time_spec);
909 #else
910 #warning Using unlocked gmtime()
911    timeptr = gmtime(time_spec);
912 #endif
913 
914    if (timeptr == NULL)
915    {
916 #if !defined(HAVE_GMTIME_R) && defined(MUTEX_LOCKS_AVAILABLE)
917       privoxy_mutex_unlock(&gmtime_mutex);
918 #endif
919       return NULL;
920    }
921 
922 #if !defined(HAVE_GMTIME_R)
923    *result = *timeptr;
924    timeptr = result;
925 #ifdef MUTEX_LOCKS_AVAILABLE
926    privoxy_mutex_unlock(&gmtime_mutex);
927 #endif
928 #endif
929 
930    return timeptr;
931 }
932 
933 #if !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV)
934 /*********************************************************************
935  *
936  * Function    :  timegm
937  *
938  * Description :  libc replacement function for the inverse of gmtime().
939  *                Copyright (C) 2004 Free Software Foundation, Inc.
940  *
941  *                Code originally copied from GnuPG, modifications done
942  *                for Privoxy: style changed, #ifdefs for _WIN32 added
943  *                to have it work on mingw32.
944  *
945  *                XXX: It's very unlikely to happen, but if the malloc()
946  *                call fails the time zone will be permanently set to UTC.
947  *
948  * Parameters  :
949  *          1  :  tm: Broken-down time struct.
950  *
951  * Returns     :  tm converted into time_t seconds.
952  *
953  *********************************************************************/
timegm(struct tm * tm)954 time_t timegm(struct tm *tm)
955 {
956    time_t answer;
957    char *zone;
958 
959    zone = getenv("TZ");
960    putenv("TZ=UTC");
961    tzset();
962    answer = mktime(tm);
963    if (zone)
964    {
965       char *old_zone;
966 
967       old_zone = malloc(3 + strlen(zone) + 1);
968       if (old_zone)
969       {
970          strcpy(old_zone, "TZ=");
971          strcat(old_zone, zone);
972          putenv(old_zone);
973 #ifdef _WIN32
974          /* http://man7.org/linux/man-pages/man3/putenv.3.html
975           *   int putenv(char *string);
976           *     The string pointed to by string becomes part of the environment, so altering the
977           *     string changes the environment.
978           * In other words, the memory pointed to by *string is used until
979           *   a) another call to putenv() with the same e-var name
980           *   b) the program exits
981           *
982           * Windows e-vars don't work that way, so let's not leak memory.
983           */
984          free(old_zone);
985 #endif /* def _WIN32 */
986       }
987    }
988    else
989    {
990 #ifdef HAVE_UNSETENV
991       unsetenv("TZ");
992 #elif defined(_WIN32)
993       putenv("TZ=");
994 #else
995       putenv("TZ");
996 #endif
997    }
998    tzset();
999 
1000    return answer;
1001 }
1002 #endif /* !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV) */
1003 
1004 
1005 /*
1006   Local Variables:
1007   tab-width: 3
1008   end:
1009 */
1010