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