Line data Source code
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 : *********************************************************************/
75 3903662 : void *zalloc(size_t size)
76 : {
77 : void * ret;
78 :
79 : #ifdef HAVE_CALLOC
80 3903662 : 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 3903662 : 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 : *********************************************************************/
112 420465 : void *zalloc_or_die(size_t size)
113 : {
114 : void *buffer;
115 :
116 420465 : buffer = zalloc(size);
117 420465 : if (buffer == NULL)
118 : {
119 0 : assert(buffer != NULL);
120 0 : log_error(LOG_LEVEL_FATAL, "Out of memory in zalloc_or_die().");
121 0 : exit(1);
122 : }
123 :
124 420465 : 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 : *********************************************************************/
146 2290074 : char *strdup_or_die(const char *str)
147 : {
148 : char *new_str;
149 :
150 2290074 : new_str = strdup(str);
151 :
152 2290074 : if (new_str == NULL)
153 : {
154 0 : assert(new_str != NULL);
155 0 : log_error(LOG_LEVEL_FATAL, "Out of memory in strdup_or_die().");
156 0 : exit(1);
157 : }
158 :
159 2290074 : 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 : *********************************************************************/
182 193395 : void *malloc_or_die(size_t buffer_size)
183 : {
184 : char *new_buf;
185 :
186 193395 : if (buffer_size == 0)
187 : {
188 0 : log_error(LOG_LEVEL_ERROR,
189 : "malloc_or_die() called with buffer size 0");
190 0 : assert(buffer_size != 0);
191 0 : buffer_size = 4096;
192 : }
193 :
194 193395 : new_buf = malloc(buffer_size);
195 :
196 193395 : if (new_buf == NULL)
197 : {
198 0 : assert(new_buf != NULL);
199 0 : log_error(LOG_LEVEL_FATAL, "Out of memory in malloc_or_die().");
200 0 : exit(1);
201 : }
202 :
203 193395 : 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 : *********************************************************************/
222 0 : void write_pid_file(const char *pid_file)
223 : {
224 : FILE *fp;
225 :
226 0 : if ((fp = fopen(pid_file, "w")) == NULL)
227 : {
228 0 : log_error(LOG_LEVEL_FATAL, "can't open pid file '%s': %E", pid_file);
229 : }
230 : else
231 : {
232 0 : fprintf(fp, "%u\n", (unsigned int) getpid());
233 0 : fclose (fp);
234 : }
235 0 : 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 : *********************************************************************/
254 173488 : unsigned int hash_string(const char* s)
255 : {
256 173488 : unsigned int h = 0;
257 :
258 2518674 : for (; *s; ++s)
259 : {
260 2345186 : h = 5 * h + (unsigned int)*s;
261 : }
262 :
263 173488 : 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 : *********************************************************************/
281 13399934 : int strcmpic(const char *s1, const char *s2)
282 : {
283 13399934 : if (!s1) s1 = "";
284 13399934 : if (!s2) s2 = "";
285 :
286 29717741 : while (*s1 && *s2)
287 : {
288 29145733 : if ((*s1 != *s2) && (privoxy_tolower(*s1) != privoxy_tolower(*s2)))
289 : {
290 12827926 : break;
291 : }
292 16317807 : s1++, s2++;
293 : }
294 13399934 : 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 : *********************************************************************/
313 13932347 : int strncmpic(const char *s1, const char *s2, size_t n)
314 : {
315 13932347 : if (n <= (size_t)0) return(0);
316 13122572 : if (!s1) s1 = "";
317 13122572 : if (!s2) s2 = "";
318 :
319 19054418 : while (*s1 && *s2)
320 : {
321 18943736 : if ((*s1 != *s2) && (privoxy_tolower(*s1) != privoxy_tolower(*s2)))
322 : {
323 12240437 : break;
324 : }
325 :
326 6703299 : if (--n <= (size_t)0) break;
327 :
328 5931846 : s1++, s2++;
329 : }
330 13122572 : 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 : *********************************************************************/
348 1055466 : char *chomp(char *string)
349 : {
350 : char *p, *q, *r;
351 :
352 : /*
353 : * strip trailing whitespace
354 : */
355 1055466 : p = string + strlen(string);
356 1226774 : while (p > string && privoxy_isspace(*(p-1)))
357 : {
358 171308 : p--;
359 : }
360 1055466 : *p = '\0';
361 :
362 : /*
363 : * find end of leading whitespace
364 : */
365 1055466 : q = r = string;
366 1113088 : while (*q && privoxy_isspace(*q))
367 : {
368 57622 : q++;
369 : }
370 :
371 : /*
372 : * if there was any, move the rest forwards
373 : */
374 1055466 : if (q != string)
375 : {
376 4768865 : while (q <= p)
377 : {
378 4727913 : *r++ = *q++;
379 : }
380 : }
381 :
382 1055466 : 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 : *********************************************************************/
435 12315316 : 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 12315316 : assert(target_string);
442 12315316 : assert(text_to_append);
443 :
444 12315316 : if (*target_string == NULL)
445 : {
446 0 : return JB_ERR_MEMORY;
447 : }
448 :
449 12315316 : if (*text_to_append == '\0')
450 : {
451 62753 : return JB_ERR_OK;
452 : }
453 :
454 12252563 : old_len = strlen(*target_string);
455 :
456 12252563 : new_size = strlen(text_to_append) + old_len + 1;
457 :
458 12252563 : if (NULL == (new_string = realloc(*target_string, new_size)))
459 : {
460 0 : free(*target_string);
461 :
462 0 : *target_string = NULL;
463 0 : return JB_ERR_MEMORY;
464 : }
465 :
466 12252563 : strlcpy(new_string + old_len, text_to_append, new_size - old_len);
467 :
468 12252563 : *target_string = new_string;
469 12252563 : 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 : *********************************************************************/
506 1126725 : jb_err string_join(char **target_string, char *text_to_append)
507 : {
508 : jb_err err;
509 :
510 1126725 : assert(target_string);
511 :
512 1126725 : if (text_to_append == NULL)
513 : {
514 0 : freez(*target_string);
515 0 : return JB_ERR_MEMORY;
516 : }
517 :
518 1126725 : err = string_append(target_string, text_to_append);
519 :
520 1126725 : freez(text_to_append);
521 :
522 1126725 : 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 : *********************************************************************/
540 388760 : char *string_toupper(const char *string)
541 : {
542 : char *result, *p;
543 : const char *q;
544 :
545 388760 : if (!string || ((result = (char *) zalloc(strlen(string) + 1)) == NULL))
546 : {
547 0 : return NULL;
548 : }
549 :
550 388760 : q = string;
551 388760 : p = result;
552 :
553 6259220 : while (*q != '\0')
554 : {
555 5870460 : *p++ = (char)toupper((int) *q++);
556 : }
557 :
558 388760 : 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 : *********************************************************************/
577 52471 : char *string_tolower(const char *string)
578 : {
579 : char *result, *p;
580 : const char *q;
581 :
582 52471 : if (!string || ((result = (char *)zalloc(strlen(string) + 1)) == NULL))
583 : {
584 0 : return NULL;
585 : }
586 :
587 52471 : q = string;
588 52471 : p = result;
589 :
590 636727 : while (*q != '\0')
591 : {
592 584256 : *p++ = (char)privoxy_tolower(*q++);
593 : }
594 :
595 52471 : 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 : *********************************************************************/
616 5766 : void string_move(char *dst, char *src)
617 : {
618 5766 : assert(dst < src);
619 :
620 : /* +1 to copy the terminating nul as well. */
621 5766 : memmove(dst, src, strlen(src)+1);
622 5766 : }
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 : *********************************************************************/
639 1426 : char *bindup(const char *string, size_t len)
640 : {
641 : char *duplicate;
642 :
643 1426 : duplicate = (char *)malloc(len);
644 1426 : if (NULL != duplicate)
645 : {
646 1426 : memcpy(duplicate, string, len);
647 : }
648 :
649 1426 : 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 : *********************************************************************/
674 242349 : char * make_path(const char * dir, const char * file)
675 : {
676 242349 : if ((file == NULL) || (*file == '\0'))
677 : {
678 0 : return NULL; /* Error */
679 : }
680 :
681 242349 : if ((dir == NULL) || (*dir == '\0') /* No directory specified */
682 : #if defined(_WIN32)
683 : || (*file == '\\') || (file[1] == ':') /* Absolute path (DOS) */
684 : #else /* ifndef _WIN32 */
685 211369 : || (*file == '/') /* Absolute path (U*ix) */
686 : #endif /* ifndef _WIN32 */
687 : )
688 : {
689 30980 : return strdup(file);
690 : }
691 : else
692 : {
693 : char * path;
694 211369 : size_t path_size = strlen(dir) + strlen(file) + 2; /* +2 for trailing (back)slash and \0 */
695 :
696 : #if defined(unix)
697 211369 : if (*dir != '/' && basedir && *basedir)
698 : {
699 : /*
700 : * Relative path, so start with the base directory.
701 : */
702 107543 : path_size += strlen(basedir) + 1; /* +1 for the slash */
703 107543 : path = malloc(path_size);
704 107543 : if (!path) log_error(LOG_LEVEL_FATAL, "malloc failed!");
705 107543 : strlcpy(path, basedir, path_size);
706 107543 : strlcat(path, "/", path_size);
707 107543 : strlcat(path, dir, path_size);
708 : }
709 : else
710 : #endif /* defined unix */
711 : {
712 103826 : path = malloc(path_size);
713 103826 : if (!path) log_error(LOG_LEVEL_FATAL, "malloc failed!");
714 103826 : strlcpy(path, dir, path_size);
715 : }
716 :
717 211369 : 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 211369 : if (path[strlen(path)-1] != '/')
725 : {
726 201740 : strlcat(path, "/", path_size);
727 : }
728 : #endif /* ifndef _WIN32 */
729 211369 : strlcat(path, file, path_size);
730 :
731 211369 : 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 : *********************************************************************/
750 918 : 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 918 : assert(range != 0);
758 918 : assert(range > 0);
759 :
760 918 : if (range <= 0) return 0;
761 :
762 : #ifdef HAVE_ARC4RANDOM
763 : number = arc4random() % range + 1;
764 : #elif defined(HAVE_RANDOM)
765 918 : 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 918 : 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 : *********************************************************************/
809 27003053 : size_t privoxy_strlcpy(char *destination, const char *source, const size_t size)
810 : {
811 27003053 : if (0 < size)
812 : {
813 27003053 : 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 27003053 : destination[size-1] = '\0';
822 : }
823 27003053 : 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 : *********************************************************************/
843 635345 : size_t privoxy_strlcat(char *destination, const char *source, const size_t size)
844 : {
845 635345 : const size_t old_length = strlen(destination);
846 635345 : 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 : *********************************************************************/
863 0 : int privoxy_millisleep(unsigned milliseconds)
864 : {
865 : #ifdef HAVE_NANOSLEEP
866 0 : struct timespec rqtp = {0};
867 0 : struct timespec rmtp = {0};
868 :
869 0 : rqtp.tv_sec = milliseconds / 1000;
870 0 : rqtp.tv_nsec = (milliseconds % 1000) * 1000 * 1000;
871 :
872 0 : 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 : *********************************************************************/
900 2382 : 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 2382 : 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 2382 : if (timeptr == NULL)
915 : {
916 : #if !defined(HAVE_GMTIME_R) && defined(MUTEX_LOCKS_AVAILABLE)
917 : privoxy_mutex_unlock(&gmtime_mutex);
918 : #endif
919 0 : 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 2382 : 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 : *********************************************************************/
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 : */
|