pcrs_compile_replacement(): Remove an assertion that could be triggered with invalid...
[privoxy.git] / miscutil.c
1 const char miscutil_rcs[] = "$Id: miscutil.c,v 1.85 2017/06/08 13:11:08 fabiankeil Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/miscutil.c,v $
5  *
6  * Purpose     :  zalloc, hash_string, strcmpic, strncmpic, and
7  *                MinGW32 strdup functions.  These are each too small
8  *                to deserve their own file but don't really fit in
9  *                any other file.
10  *
11  * Copyright   :  Written by and Copyright (C) 2001-2016 the
12  *                Privoxy team. http://www.privoxy.org/
13  *
14  *                Based on the Internet Junkbuster originally written
15  *                by and Copyright (C) 1997 Anonymous Coders and
16  *                Junkbusters Corporation.  http://www.junkbusters.com
17  *
18  *                The timegm replacement function was taken from GnuPG,
19  *                Copyright (C) 2004 Free Software Foundation, Inc.
20  *
21  *                The snprintf replacement function is written by
22  *                Mark Martinec who also holds the copyright. It can be
23  *                used under the terms of the GPL or the terms of the
24  *                "Frontier Artistic License".
25  *
26  *                This program is free software; you can redistribute it
27  *                and/or modify it under the terms of the GNU General
28  *                Public License as published by the Free Software
29  *                Foundation; either version 2 of the License, or (at
30  *                your option) any later version.
31  *
32  *                This program is distributed in the hope that it will
33  *                be useful, but WITHOUT ANY WARRANTY; without even the
34  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
35  *                PARTICULAR PURPOSE.  See the GNU General Public
36  *                License for more details.
37  *
38  *                The GNU General Public License should be included with
39  *                this file.  If not, you can view it at
40  *                http://www.gnu.org/copyleft/gpl.html
41  *                or write to the Free Software Foundation, Inc., 59
42  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
43  *
44  *********************************************************************/
45
46
47 #include "config.h"
48
49 #include <stdio.h>
50 #include <sys/types.h>
51 #include <stdlib.h>
52 #if !defined(_WIN32) && !defined(__OS2__)
53 #include <unistd.h>
54 #endif /* #if !defined(_WIN32) && !defined(__OS2__) */
55 #include <string.h>
56 #include <ctype.h>
57 #include <assert.h>
58
59 #if !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV)
60 #include <time.h>
61 #endif /* !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV) */
62
63 #include "project.h"
64 #include "miscutil.h"
65 #include "errlog.h"
66 #include "jcc.h"
67
68 const char miscutil_h_rcs[] = MISCUTIL_H_VERSION;
69
70 /*********************************************************************
71  *
72  * Function    :  zalloc
73  *
74  * Description :  Returns allocated memory that is initialized
75  *                with zeros.
76  *
77  * Parameters  :
78  *          1  :  size = Size of memory chunk to return.
79  *
80  * Returns     :  Pointer to newly alloc'd memory chunk.
81  *
82  *********************************************************************/
83 void *zalloc(size_t size)
84 {
85    void * ret;
86
87 #ifdef HAVE_CALLOC
88    ret = calloc(1, size);
89 #else
90 #warning calloc appears to be unavailable. Your platform will become unsupported in the future
91    if ((ret = (void *)malloc(size)) != NULL)
92    {
93       memset(ret, 0, size);
94    }
95 #endif
96
97    return(ret);
98
99 }
100
101
102 /*********************************************************************
103  *
104  * Function    :  zalloc_or_die
105  *
106  * Description :  zalloc wrapper that either succeeds or causes
107  *                program termination.
108  *
109  *                Useful in situations were the string length is
110  *                "small" and zalloc() failures couldn't be handled
111  *                better anyway. In case of debug builds, failures
112  *                trigger an assert().
113  *
114  * Parameters  :
115  *          1  :  size = Size of memory chunk to return.
116  *
117  * Returns     :  Pointer to newly malloc'd memory chunk.
118  *
119  *********************************************************************/
120 void *zalloc_or_die(size_t size)
121 {
122    void *buffer;
123
124    buffer = zalloc(size);
125    if (buffer == NULL)
126    {
127       assert(buffer != NULL);
128       log_error(LOG_LEVEL_FATAL, "Out of memory in zalloc_or_die().");
129       exit(1);
130    }
131
132    return(buffer);
133
134 }
135
136 /*********************************************************************
137  *
138  * Function    :  strdup_or_die
139  *
140  * Description :  strdup wrapper that either succeeds or causes
141  *                program termination.
142  *
143  *                Useful in situations were the string length is
144  *                "small" and strdup() failures couldn't be handled
145  *                better anyway. In case of debug builds, failures
146  *                trigger an assert().
147  *
148  * Parameters  :
149  *          1  :  str = String to duplicate
150  *
151  * Returns     :  Pointer to newly strdup'd copy of the string.
152  *
153  *********************************************************************/
154 char *strdup_or_die(const char *str)
155 {
156    char *new_str;
157
158    new_str = strdup(str);
159
160    if (new_str == NULL)
161    {
162       assert(new_str != NULL);
163       log_error(LOG_LEVEL_FATAL, "Out of memory in strdup_or_die().");
164       exit(1);
165    }
166
167    return(new_str);
168
169 }
170
171
172 /*********************************************************************
173  *
174  * Function    :  malloc_or_die
175  *
176  * Description :  malloc wrapper that either succeeds or causes
177  *                program termination.
178  *
179  *                Useful in situations were the buffer size is "small"
180  *                and malloc() failures couldn't be handled better
181  *                anyway. In case of debug builds, failures trigger
182  *                an assert().
183  *
184  * Parameters  :
185  *          1  :  buffer_size = Size of the space to allocate
186  *
187  * Returns     :  Pointer to newly malloc'd memory
188  *
189  *********************************************************************/
190 void *malloc_or_die(size_t buffer_size)
191 {
192    char *new_buf;
193
194    if (buffer_size == 0)
195    {
196       log_error(LOG_LEVEL_ERROR,
197          "malloc_or_die() called with buffer size 0");
198       assert(buffer_size != 0);
199       buffer_size = 4096;
200    }
201
202    new_buf = malloc(buffer_size);
203
204    if (new_buf == NULL)
205    {
206       assert(new_buf != NULL);
207       log_error(LOG_LEVEL_FATAL, "Out of memory in malloc_or_die().");
208       exit(1);
209    }
210
211    return(new_buf);
212
213 }
214
215
216 #if defined(unix)
217 /*********************************************************************
218  *
219  * Function    :  write_pid_file
220  *
221  * Description :  Writes a pid file with the pid of the main process.
222  *                Exits if the file can't be opened
223  *
224  * Parameters  :  None
225  *
226  * Returns     :  N/A
227  *
228  *********************************************************************/
229 void write_pid_file(void)
230 {
231    FILE   *fp;
232
233    /*
234     * If no --pidfile option was given,
235     * we can live without one.
236     */
237    if (pidfile == NULL) return;
238
239    if ((fp = fopen(pidfile, "w")) == NULL)
240    {
241       log_error(LOG_LEVEL_FATAL, "can't open pidfile '%s': %E", pidfile);
242    }
243    else
244    {
245       fprintf(fp, "%u\n", (unsigned int) getpid());
246       fclose (fp);
247    }
248    return;
249
250 }
251 #endif /* def unix */
252
253
254 /*********************************************************************
255  *
256  * Function    :  hash_string
257  *
258  * Description :  Take a string and compute a (hopefuly) unique numeric
259  *                integer value. This is useful to "switch" a string.
260  *
261  * Parameters  :
262  *          1  :  s : string to be hashed.
263  *
264  * Returns     :  The string's hash
265  *
266  *********************************************************************/
267 unsigned int hash_string(const char* s)
268 {
269    unsigned int h = 0;
270
271    for (; *s; ++s)
272    {
273       h = 5 * h + (unsigned int)*s;
274    }
275
276    return (h);
277
278 }
279
280
281 /*********************************************************************
282  *
283  * Function    :  strcmpic
284  *
285  * Description :  Case insensitive string comparison
286  *
287  * Parameters  :
288  *          1  :  s1 = string 1 to compare
289  *          2  :  s2 = string 2 to compare
290  *
291  * Returns     :  0 if s1==s2, Negative if s1<s2, Positive if s1>s2
292  *
293  *********************************************************************/
294 int strcmpic(const char *s1, const char *s2)
295 {
296    if (!s1) s1 = "";
297    if (!s2) s2 = "";
298
299    while (*s1 && *s2)
300    {
301       if ((*s1 != *s2) && (privoxy_tolower(*s1) != privoxy_tolower(*s2)))
302       {
303          break;
304       }
305       s1++, s2++;
306    }
307    return(privoxy_tolower(*s1) - privoxy_tolower(*s2));
308
309 }
310
311
312 /*********************************************************************
313  *
314  * Function    :  strncmpic
315  *
316  * Description :  Case insensitive string comparison (up to n characters)
317  *
318  * Parameters  :
319  *          1  :  s1 = string 1 to compare
320  *          2  :  s2 = string 2 to compare
321  *          3  :  n = maximum characters to compare
322  *
323  * Returns     :  0 if s1==s2, Negative if s1<s2, Positive if s1>s2
324  *
325  *********************************************************************/
326 int strncmpic(const char *s1, const char *s2, size_t n)
327 {
328    if (n <= (size_t)0) return(0);
329    if (!s1) s1 = "";
330    if (!s2) s2 = "";
331
332    while (*s1 && *s2)
333    {
334       if ((*s1 != *s2) && (privoxy_tolower(*s1) != privoxy_tolower(*s2)))
335       {
336          break;
337       }
338
339       if (--n <= (size_t)0) break;
340
341       s1++, s2++;
342    }
343    return(privoxy_tolower(*s1) - privoxy_tolower(*s2));
344
345 }
346
347
348 /*********************************************************************
349  *
350  * Function    :  chomp
351  *
352  * Description :  In-situ-eliminate all leading and trailing whitespace
353  *                from a string.
354  *
355  * Parameters  :
356  *          1  :  s : string to be chomped.
357  *
358  * Returns     :  chomped string
359  *
360  *********************************************************************/
361 char *chomp(char *string)
362 {
363    char *p, *q, *r;
364
365    /*
366     * strip trailing whitespace
367     */
368    p = string + strlen(string);
369    while (p > string && privoxy_isspace(*(p-1)))
370    {
371       p--;
372    }
373    *p = '\0';
374
375    /*
376     * find end of leading whitespace
377     */
378    q = r = string;
379    while (*q && privoxy_isspace(*q))
380    {
381       q++;
382    }
383
384    /*
385     * if there was any, move the rest forwards
386     */
387    if (q != string)
388    {
389       while (q <= p)
390       {
391          *r++ = *q++;
392       }
393    }
394
395    return(string);
396
397 }
398
399
400 /*********************************************************************
401  *
402  * Function    :  string_append
403  *
404  * Description :  Reallocate target_string and append text to it.
405  *                This makes it easier to append to malloc'd strings.
406  *                This is similar to the (removed) strsav(), but
407  *                running out of memory isn't catastrophic.
408  *
409  *                Programming style:
410  *
411  *                The following style provides sufficient error
412  *                checking for this routine, with minimal clutter
413  *                in the source code.  It is recommended if you
414  *                have many calls to this function:
415  *
416  *                char * s = strdup(...); // don't check for error
417  *                string_append(&s, ...);  // don't check for error
418  *                string_append(&s, ...);  // don't check for error
419  *                string_append(&s, ...);  // don't check for error
420  *                if (NULL == s) { ... handle error ... }
421  *
422  *                OR, equivalently:
423  *
424  *                char * s = strdup(...); // don't check for error
425  *                string_append(&s, ...);  // don't check for error
426  *                string_append(&s, ...);  // don't check for error
427  *                if (string_append(&s, ...)) {... handle error ...}
428  *
429  * Parameters  :
430  *          1  :  target_string = Pointer to old text that is to be
431  *                extended.  *target_string will be free()d by this
432  *                routine.  target_string must be non-NULL.
433  *                If *target_string is NULL, this routine will
434  *                do nothing and return with an error - this allows
435  *                you to make many calls to this routine and only
436  *                check for errors after the last one.
437  *          2  :  text_to_append = Text to be appended to old.
438  *                Must not be NULL.
439  *
440  * Returns     :  JB_ERR_OK on success, and sets *target_string
441  *                   to newly malloc'ed appended string.  Caller
442  *                   must free(*target_string).
443  *                JB_ERR_MEMORY on out-of-memory.  (And free()s
444  *                   *target_string and sets it to NULL).
445  *                JB_ERR_MEMORY if *target_string is NULL.
446  *
447  *********************************************************************/
448 jb_err string_append(char **target_string, const char *text_to_append)
449 {
450    size_t old_len;
451    char *new_string;
452    size_t new_size;
453
454    assert(target_string);
455    assert(text_to_append);
456
457    if (*target_string == NULL)
458    {
459       return JB_ERR_MEMORY;
460    }
461
462    if (*text_to_append == '\0')
463    {
464       return JB_ERR_OK;
465    }
466
467    old_len = strlen(*target_string);
468
469    new_size = strlen(text_to_append) + old_len + 1;
470
471    if (NULL == (new_string = realloc(*target_string, new_size)))
472    {
473       free(*target_string);
474
475       *target_string = NULL;
476       return JB_ERR_MEMORY;
477    }
478
479    strlcpy(new_string + old_len, text_to_append, new_size - old_len);
480
481    *target_string = new_string;
482    return JB_ERR_OK;
483 }
484
485
486 /*********************************************************************
487  *
488  * Function    :  string_join
489  *
490  * Description :  Join two strings together.  Frees BOTH the original
491  *                strings.  If either or both input strings are NULL,
492  *                fails as if it had run out of memory.
493  *
494  *                For comparison, string_append requires that the
495  *                second string is non-NULL, and doesn't free it.
496  *
497  *                Rationale: Too often, we want to do
498  *                string_append(s, html_encode(s2)).  That assert()s
499  *                if s2 is NULL or if html_encode() runs out of memory.
500  *                It also leaks memory.  Proper checking is cumbersome.
501  *                The solution: string_join(s, html_encode(s2)) is safe,
502  *                and will free the memory allocated by html_encode().
503  *
504  * Parameters  :
505  *          1  :  target_string = Pointer to old text that is to be
506  *                extended.  *target_string will be free()d by this
507  *                routine.  target_string must be non-NULL.
508  *          2  :  text_to_append = Text to be appended to old.
509  *
510  * Returns     :  JB_ERR_OK on success, and sets *target_string
511  *                   to newly malloc'ed appended string.  Caller
512  *                   must free(*target_string).
513  *                JB_ERR_MEMORY on out-of-memory, or if
514  *                   *target_string or text_to_append is NULL.  (In
515  *                   this case, frees *target_string and text_to_append,
516  *                   sets *target_string to NULL).
517  *
518  *********************************************************************/
519 jb_err string_join(char **target_string, char *text_to_append)
520 {
521    jb_err err;
522
523    assert(target_string);
524
525    if (text_to_append == NULL)
526    {
527       freez(*target_string);
528       return JB_ERR_MEMORY;
529    }
530
531    err = string_append(target_string, text_to_append);
532
533    freez(text_to_append);
534
535    return err;
536 }
537
538
539 /*********************************************************************
540  *
541  * Function    :  string_toupper
542  *
543  * Description :  Produce a copy of string with all convertible
544  *                characters converted to uppercase.
545  *
546  * Parameters  :
547  *          1  :  string = string to convert
548  *
549  * Returns     :  Uppercase copy of string if possible,
550  *                NULL on out-of-memory or if string was NULL.
551  *
552  *********************************************************************/
553 char *string_toupper(const char *string)
554 {
555    char *result, *p;
556    const char *q;
557
558    if (!string || ((result = (char *) zalloc(strlen(string) + 1)) == NULL))
559    {
560       return NULL;
561    }
562
563    q = string;
564    p = result;
565
566    while (*q != '\0')
567    {
568       *p++ = (char)toupper((int) *q++);
569    }
570
571    return result;
572
573 }
574
575
576 /*********************************************************************
577  *
578  * Function    :  string_move
579  *
580  * Description :  memmove wrapper to move the last part of a string
581  *                towards the beginning, overwriting the part in
582  *                the middle. strlcpy() can't be used here as the
583  *                strings overlap.
584  *
585  * Parameters  :
586  *          1  :  dst = Destination to overwrite
587  *          2  :  src = Source to move.
588  *
589  * Returns     :  N/A
590  *
591  *********************************************************************/
592 void string_move(char *dst, char *src)
593 {
594    assert(dst < src);
595
596    /* +1 to copy the terminating nul as well. */
597    memmove(dst, src, strlen(src)+1);
598 }
599
600
601 /*********************************************************************
602  *
603  * Function    :  bindup
604  *
605  * Description :  Duplicate the first n characters of a string that may
606  *                contain '\0' characters.
607  *
608  * Parameters  :
609  *          1  :  string = string to be duplicated
610  *          2  :  len = number of bytes to duplicate
611  *
612  * Returns     :  pointer to copy, or NULL if failiure
613  *
614  *********************************************************************/
615 char *bindup(const char *string, size_t len)
616 {
617    char *duplicate;
618
619    duplicate = (char *)malloc(len);
620    if (NULL != duplicate)
621    {
622       memcpy(duplicate, string, len);
623    }
624
625    return duplicate;
626
627 }
628
629
630 /*********************************************************************
631  *
632  * Function    :  make_path
633  *
634  * Description :  Takes a directory name and a file name, returns
635  *                the complete path.  Handles windows/unix differences.
636  *                If the file name is already an absolute path, or if
637  *                the directory name is NULL or empty, it returns
638  *                the filename.
639  *
640  * Parameters  :
641  *          1  :  dir: Name of directory or NULL for none.
642  *          2  :  file: Name of file.  Should not be NULL or empty.
643  *
644  * Returns     :  "dir/file" (Or on windows, "dir\file").
645  *                It allocates the string on the heap.  Caller frees.
646  *                Returns NULL in error (i.e. NULL file or out of
647  *                memory)
648  *
649  *********************************************************************/
650 char * make_path(const char * dir, const char * file)
651 {
652 #ifdef AMIGA
653    char path[512];
654
655    if (dir)
656    {
657       if (dir[0] == '.')
658       {
659          if (dir[1] == '/')
660          {
661             strncpy(path,dir+2,512);
662          }
663          else
664          {
665             strncpy(path,dir+1,512);
666          }
667       }
668       else
669       {
670          strncpy(path,dir,512);
671       }
672       path[511]=0;
673    }
674    else
675    {
676       path[0]=0;
677    }
678    if (AddPart(path,file,512))
679    {
680       return strdup(path);
681    }
682    else
683    {
684       return NULL;
685    }
686 #else /* ndef AMIGA */
687
688    if ((file == NULL) || (*file == '\0'))
689    {
690       return NULL; /* Error */
691    }
692
693    if ((dir == NULL) || (*dir == '\0') /* No directory specified */
694 #if defined(_WIN32) || defined(__OS2__)
695       || (*file == '\\') || (file[1] == ':') /* Absolute path (DOS) */
696 #else /* ifndef _WIN32 || __OS2__ */
697       || (*file == '/') /* Absolute path (U*ix) */
698 #endif /* ifndef _WIN32 || __OS2__  */
699       )
700    {
701       return strdup(file);
702    }
703    else
704    {
705       char * path;
706       size_t path_size = strlen(dir) + strlen(file) + 2; /* +2 for trailing (back)slash and \0 */
707
708 #if defined(unix)
709       if (*dir != '/' && basedir && *basedir)
710       {
711          /*
712           * Relative path, so start with the base directory.
713           */
714          path_size += strlen(basedir) + 1; /* +1 for the slash */
715          path = malloc(path_size);
716          if (!path) log_error(LOG_LEVEL_FATAL, "malloc failed!");
717          strlcpy(path, basedir, path_size);
718          strlcat(path, "/", path_size);
719          strlcat(path, dir, path_size);
720       }
721       else
722 #endif /* defined unix */
723       {
724          path = malloc(path_size);
725          if (!path) log_error(LOG_LEVEL_FATAL, "malloc failed!");
726          strlcpy(path, dir, path_size);
727       }
728
729       assert(NULL != path);
730 #if defined(_WIN32) || defined(__OS2__)
731       if (path[strlen(path)-1] != '\\')
732       {
733          strlcat(path, "\\", path_size);
734       }
735 #else /* ifndef _WIN32 || __OS2__ */
736       if (path[strlen(path)-1] != '/')
737       {
738          strlcat(path, "/", path_size);
739       }
740 #endif /* ifndef _WIN32 || __OS2__ */
741       strlcat(path, file, path_size);
742
743       return path;
744    }
745 #endif /* ndef AMIGA */
746 }
747
748
749 /*********************************************************************
750  *
751  * Function    :  pick_from_range
752  *
753  * Description :  Pick a positive number out of a given range.
754  *                Should only be used if randomness would be nice,
755  *                but isn't really necessary.
756  *
757  * Parameters  :
758  *          1  :  range: Highest possible number to pick.
759  *
760  * Returns     :  Picked number.
761  *
762  *********************************************************************/
763 long int pick_from_range(long int range)
764 {
765    long int number;
766 #ifdef _WIN32
767    static unsigned long seed = 0;
768 #endif /* def _WIN32 */
769
770    assert(range != 0);
771    assert(range > 0);
772
773    if (range <= 0) return 0;
774
775 #ifdef HAVE_ARC4RANDOM
776    number = arc4random() % range + 1;
777 #elif defined(HAVE_RANDOM)
778    number = random() % range + 1;
779 #elif defined(MUTEX_LOCKS_AVAILABLE)
780    privoxy_mutex_lock(&rand_mutex);
781 #ifdef _WIN32
782    if (!seed)
783    {
784       seed = (unsigned long)(GetCurrentThreadId()+GetTickCount());
785    }
786    srand(seed);
787    seed = (unsigned long)((rand() << 16) + rand());
788 #endif /* def _WIN32 */
789    number = (unsigned long)((rand() << 16) + (rand())) % (unsigned long)(range + 1);
790    privoxy_mutex_unlock(&rand_mutex);
791 #else
792    /*
793     * XXX: Which platforms reach this and are there
794     * better options than just using rand() and hoping
795     * that it's safe?
796     */
797    log_error(LOG_LEVEL_INFO, "No thread-safe PRNG available? Header time randomization "
798       "might cause crashes, predictable results or even combine these fine options.");
799    number = rand() % (long int)(range + 1);
800
801 #endif /* (def HAVE_ARC4RANDOM) */
802
803    return number;
804 }
805
806
807 #ifdef USE_PRIVOXY_STRLCPY
808 /*********************************************************************
809  *
810  * Function    :  privoxy_strlcpy
811  *
812  * Description :  strlcpy(3) look-alike for those without decent libc.
813  *
814  * Parameters  :
815  *          1  :  destination: buffer to copy into.
816  *          2  :  source: String to copy.
817  *          3  :  size: Size of destination buffer.
818  *
819  * Returns     :  The length of the string that privoxy_strlcpy() tried to create.
820  *
821  *********************************************************************/
822 size_t privoxy_strlcpy(char *destination, const char *source, const size_t size)
823 {
824    if (0 < size)
825    {
826       snprintf(destination, size, "%s", source);
827       /*
828        * Platforms that lack strlcpy() also tend to have
829        * a broken snprintf implementation that doesn't
830        * guarantee nul termination.
831        *
832        * XXX: the configure script should detect and reject those.
833        */
834       destination[size-1] = '\0';
835    }
836    return strlen(source);
837 }
838 #endif /* def USE_PRIVOXY_STRLCPY */
839
840
841 #ifndef HAVE_STRLCAT
842 /*********************************************************************
843  *
844  * Function    :  privoxy_strlcat
845  *
846  * Description :  strlcat(3) look-alike for those without decent libc.
847  *
848  * Parameters  :
849  *          1  :  destination: C string.
850  *          2  :  source: String to copy.
851  *          3  :  size: Size of destination buffer.
852  *
853  * Returns     :  The length of the string that privoxy_strlcat() tried to create.
854  *
855  *********************************************************************/
856 size_t privoxy_strlcat(char *destination, const char *source, const size_t size)
857 {
858    const size_t old_length = strlen(destination);
859    return old_length + strlcpy(destination + old_length, source, size - old_length);
860 }
861 #endif /* ndef HAVE_STRLCAT */
862
863
864 #if !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV)
865 /*********************************************************************
866  *
867  * Function    :  timegm
868  *
869  * Description :  libc replacement function for the inverse of gmtime().
870  *                Copyright (C) 2004 Free Software Foundation, Inc.
871  *
872  *                Code originally copied from GnuPG, modifications done
873  *                for Privoxy: style changed, #ifdefs for _WIN32 added
874  *                to have it work on mingw32.
875  *
876  *                XXX: It's very unlikely to happen, but if the malloc()
877  *                call fails the time zone will be permanently set to UTC.
878  *
879  * Parameters  :
880  *          1  :  tm: Broken-down time struct.
881  *
882  * Returns     :  tm converted into time_t seconds.
883  *
884  *********************************************************************/
885 time_t timegm(struct tm *tm)
886 {
887    time_t answer;
888    char *zone;
889
890    zone = getenv("TZ");
891    putenv("TZ=UTC");
892    tzset();
893    answer = mktime(tm);
894    if (zone)
895    {
896       char *old_zone;
897
898       old_zone = malloc(3 + strlen(zone) + 1);
899       if (old_zone)
900       {
901          strcpy(old_zone, "TZ=");
902          strcat(old_zone, zone);
903          putenv(old_zone);
904 #ifdef _WIN32
905          /* http://man7.org/linux/man-pages/man3/putenv.3.html
906           *   int putenv(char *string);
907           *     The string pointed to by string becomes part of the environment, so altering the
908           *     string changes the environment.
909           * In other words, the memory pointed to by *string is used until
910           *   a) another call to putenv() with the same e-var name
911           *   b) the program exits
912           *
913           * Windows e-vars don't work that way, so let's not leak memory.
914           */
915          free(old_zone);
916 #endif /* def _WIN32 */
917       }
918    }
919    else
920    {
921 #ifdef HAVE_UNSETENV
922       unsetenv("TZ");
923 #elif defined(_WIN32)
924       putenv("TZ=");
925 #else
926       putenv("TZ");
927 #endif
928    }
929    tzset();
930
931    return answer;
932 }
933 #endif /* !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV) */
934
935
936 #ifndef HAVE_SNPRINTF
937 /*
938  * What follows is a portable snprintf routine, written by Mark Martinec.
939  * See: http://www.ijs.si/software/snprintf/
940
941                                   snprintf.c
942                    - a portable implementation of snprintf,
943        including vsnprintf.c, asnprintf, vasnprintf, asprintf, vasprintf
944
945    snprintf is a routine to convert numeric and string arguments to
946    formatted strings. It is similar to sprintf(3) provided in a system's
947    C library, yet it requires an additional argument - the buffer size -
948    and it guarantees never to store anything beyond the given buffer,
949    regardless of the format or arguments to be formatted. Some newer
950    operating systems do provide snprintf in their C library, but many do
951    not or do provide an inadequate (slow or idiosyncratic) version, which
952    calls for a portable implementation of this routine.
953
954 Author
955
956    Mark Martinec <mark.martinec@ijs.si>, April 1999, June 2000
957    Copyright Â© 1999, Mark Martinec
958
959  */
960
961 #define PORTABLE_SNPRINTF_VERSION_MAJOR 2
962 #define PORTABLE_SNPRINTF_VERSION_MINOR 2
963
964 #if defined(NEED_ASPRINTF) || defined(NEED_ASNPRINTF) || defined(NEED_VASPRINTF) || defined(NEED_VASNPRINTF)
965 # if defined(NEED_SNPRINTF_ONLY)
966 # undef NEED_SNPRINTF_ONLY
967 # endif
968 # if !defined(PREFER_PORTABLE_SNPRINTF)
969 # define PREFER_PORTABLE_SNPRINTF
970 # endif
971 #endif
972
973 #if defined(SOLARIS_BUG_COMPATIBLE) && !defined(SOLARIS_COMPATIBLE)
974 #define SOLARIS_COMPATIBLE
975 #endif
976
977 #if defined(HPUX_BUG_COMPATIBLE) && !defined(HPUX_COMPATIBLE)
978 #define HPUX_COMPATIBLE
979 #endif
980
981 #if defined(DIGITAL_UNIX_BUG_COMPATIBLE) && !defined(DIGITAL_UNIX_COMPATIBLE)
982 #define DIGITAL_UNIX_COMPATIBLE
983 #endif
984
985 #if defined(PERL_BUG_COMPATIBLE) && !defined(PERL_COMPATIBLE)
986 #define PERL_COMPATIBLE
987 #endif
988
989 #if defined(LINUX_BUG_COMPATIBLE) && !defined(LINUX_COMPATIBLE)
990 #define LINUX_COMPATIBLE
991 #endif
992
993 #include <sys/types.h>
994 #include <string.h>
995 #include <stdlib.h>
996 #include <stdio.h>
997 #include <stdarg.h>
998 #include <assert.h>
999 #include <errno.h>
1000
1001 #ifdef isdigit
1002 #undef isdigit
1003 #endif
1004 #define isdigit(c) ((c) >= '0' && (c) <= '9')
1005
1006 /* For copying strings longer or equal to 'breakeven_point'
1007  * it is more efficient to call memcpy() than to do it inline.
1008  * The value depends mostly on the processor architecture,
1009  * but also on the compiler and its optimization capabilities.
1010  * The value is not critical, some small value greater than zero
1011  * will be just fine if you don't care to squeeze every drop
1012  * of performance out of the code.
1013  *
1014  * Small values favor memcpy, large values favor inline code.
1015  */
1016 #if defined(__alpha__) || defined(__alpha)
1017 #  define breakeven_point   2    /* AXP (DEC Alpha)     - gcc or cc or egcs */
1018 #endif
1019 #if defined(__i386__)  || defined(__i386)
1020 #  define breakeven_point  12    /* Intel Pentium/Linux - gcc 2.96 */
1021 #endif
1022 #if defined(__hppa)
1023 #  define breakeven_point  10    /* HP-PA               - gcc */
1024 #endif
1025 #if defined(__sparc__) || defined(__sparc)
1026 #  define breakeven_point  33    /* Sun Sparc 5         - gcc 2.8.1 */
1027 #endif
1028
1029 /* some other values of possible interest: */
1030 /* #define breakeven_point  8 */ /* VAX 4000          - vaxc */
1031 /* #define breakeven_point 19 */ /* VAX 4000          - gcc 2.7.0 */
1032
1033 #ifndef breakeven_point
1034 #  define breakeven_point   6    /* some reasonable one-size-fits-all value */
1035 #endif
1036
1037 #define fast_memcpy(d,s,n) \
1038   { register size_t nn = (size_t)(n); \
1039     if (nn >= breakeven_point) memcpy((d), (s), nn); \
1040     else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
1041       register char *dd; register const char *ss; \
1042       for (ss=(s), dd=(d); nn>0; nn--) *dd++ = *ss++; } }
1043
1044 #define fast_memset(d,c,n) \
1045   { register size_t nn = (size_t)(n); \
1046     if (nn >= breakeven_point) memset((d), (int)(c), nn); \
1047     else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
1048       register char *dd; register const int cc=(int)(c); \
1049       for (dd=(d); nn>0; nn--) *dd++ = cc; } }
1050
1051 /* prototypes */
1052
1053 #if defined(NEED_ASPRINTF)
1054 int asprintf   (char **ptr, const char *fmt, /*args*/ ...);
1055 #endif
1056 #if defined(NEED_VASPRINTF)
1057 int vasprintf  (char **ptr, const char *fmt, va_list ap);
1058 #endif
1059 #if defined(NEED_ASNPRINTF)
1060 int asnprintf  (char **ptr, size_t str_m, const char *fmt, /*args*/ ...);
1061 #endif
1062 #if defined(NEED_VASNPRINTF)
1063 int vasnprintf (char **ptr, size_t str_m, const char *fmt, va_list ap);
1064 #endif
1065
1066 #if defined(HAVE_SNPRINTF)
1067 /* declare our portable snprintf  routine under name portable_snprintf  */
1068 /* declare our portable vsnprintf routine under name portable_vsnprintf */
1069 #else
1070 /* declare our portable routines under names snprintf and vsnprintf */
1071 #define portable_snprintf snprintf
1072 #if !defined(NEED_SNPRINTF_ONLY)
1073 #define portable_vsnprintf vsnprintf
1074 #endif
1075 #endif
1076
1077 #if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
1078 int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...);
1079 #if !defined(NEED_SNPRINTF_ONLY)
1080 int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap);
1081 #endif
1082 #endif
1083
1084 /* declarations */
1085
1086 static char credits[] = "\n\
1087 @(#)snprintf.c, v2.2: Mark Martinec, <mark.martinec@ijs.si>\n\
1088 @(#)snprintf.c, v2.2: Copyright 1999, Mark Martinec. Frontier Artistic License applies.\n\
1089 @(#)snprintf.c, v2.2: http://www.ijs.si/software/snprintf/\n";
1090
1091 #if defined(NEED_ASPRINTF)
1092 int asprintf(char **ptr, const char *fmt, /*args*/ ...) {
1093   va_list ap;
1094   size_t str_m;
1095   int str_l;
1096
1097   *ptr = NULL;
1098   va_start(ap, fmt);                            /* measure the required size */
1099   str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap);
1100   va_end(ap);
1101   assert(str_l >= 0);        /* possible integer overflow if str_m > INT_MAX */
1102   *ptr = (char *) malloc(str_m = (size_t)str_l + 1);
1103   if (*ptr == NULL) { errno = ENOMEM; str_l = -1; }
1104   else {
1105     int str_l2;
1106     va_start(ap, fmt);
1107     str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap);
1108     va_end(ap);
1109     assert(str_l2 == str_l);
1110   }
1111   return str_l;
1112 }
1113 #endif
1114
1115 #if defined(NEED_VASPRINTF)
1116 int vasprintf(char **ptr, const char *fmt, va_list ap) {
1117   size_t str_m;
1118   int str_l;
1119
1120   *ptr = NULL;
1121   { va_list ap2;
1122     va_copy(ap2, ap);  /* don't consume the original ap, we'll need it again */
1123     str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap2);/*get required size*/
1124     va_end(ap2);
1125   }
1126   assert(str_l >= 0);        /* possible integer overflow if str_m > INT_MAX */
1127   *ptr = (char *) malloc(str_m = (size_t)str_l + 1);
1128   if (*ptr == NULL) { errno = ENOMEM; str_l = -1; }
1129   else {
1130     int str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap);
1131     assert(str_l2 == str_l);
1132   }
1133   return str_l;
1134 }
1135 #endif
1136
1137 #if defined(NEED_ASNPRINTF)
1138 int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...) {
1139   va_list ap;
1140   int str_l;
1141
1142   *ptr = NULL;
1143   va_start(ap, fmt);                            /* measure the required size */
1144   str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap);
1145   va_end(ap);
1146   assert(str_l >= 0);        /* possible integer overflow if str_m > INT_MAX */
1147   if ((size_t)str_l + 1 < str_m) str_m = (size_t)str_l + 1;      /* truncate */
1148   /* if str_m is 0, no buffer is allocated, just set *ptr to NULL */
1149   if (str_m == 0) {  /* not interested in resulting string, just return size */
1150   } else {
1151     *ptr = (char *) malloc(str_m);
1152     if (*ptr == NULL) { errno = ENOMEM; str_l = -1; }
1153     else {
1154       int str_l2;
1155       va_start(ap, fmt);
1156       str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap);
1157       va_end(ap);
1158       assert(str_l2 == str_l);
1159     }
1160   }
1161   return str_l;
1162 }
1163 #endif
1164
1165 #if defined(NEED_VASNPRINTF)
1166 int vasnprintf (char **ptr, size_t str_m, const char *fmt, va_list ap) {
1167   int str_l;
1168
1169   *ptr = NULL;
1170   { va_list ap2;
1171     va_copy(ap2, ap);  /* don't consume the original ap, we'll need it again */
1172     str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap2);/*get required size*/
1173     va_end(ap2);
1174   }
1175   assert(str_l >= 0);        /* possible integer overflow if str_m > INT_MAX */
1176   if ((size_t)str_l + 1 < str_m) str_m = (size_t)str_l + 1;      /* truncate */
1177   /* if str_m is 0, no buffer is allocated, just set *ptr to NULL */
1178   if (str_m == 0) {  /* not interested in resulting string, just return size */
1179   } else {
1180     *ptr = (char *) malloc(str_m);
1181     if (*ptr == NULL) { errno = ENOMEM; str_l = -1; }
1182     else {
1183       int str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap);
1184       assert(str_l2 == str_l);
1185     }
1186   }
1187   return str_l;
1188 }
1189 #endif
1190
1191 /*
1192  * If the system does have snprintf and the portable routine is not
1193  * specifically required, this module produces no code for snprintf/vsnprintf.
1194  */
1195 #if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
1196
1197 #if !defined(NEED_SNPRINTF_ONLY)
1198 int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...) {
1199   va_list ap;
1200   int str_l;
1201
1202   va_start(ap, fmt);
1203   str_l = portable_vsnprintf(str, str_m, fmt, ap);
1204   va_end(ap);
1205   return str_l;
1206 }
1207 #endif
1208
1209 #if defined(NEED_SNPRINTF_ONLY)
1210 int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...) {
1211 #else
1212 int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) {
1213 #endif
1214
1215 #if defined(NEED_SNPRINTF_ONLY)
1216   va_list ap;
1217 #endif
1218   size_t str_l = 0;
1219   const char *p = fmt;
1220
1221 /* In contrast with POSIX, the ISO C99 now says
1222  * that str can be NULL and str_m can be 0.
1223  * This is more useful than the old:  if (str_m < 1) return -1; */
1224
1225 #if defined(NEED_SNPRINTF_ONLY)
1226   va_start(ap, fmt);
1227 #endif
1228   if (!p) p = "";
1229   while (*p) {
1230     if (*p != '%') {
1231    /* if (str_l < str_m) str[str_l++] = *p++;    -- this would be sufficient */
1232    /* but the following code achieves better performance for cases
1233     * where format string is long and contains few conversions */
1234       const char *q = strchr(p+1,'%');
1235       size_t n = !q ? strlen(p) : (q-p);
1236       if (str_l < str_m) {
1237         size_t avail = str_m-str_l;
1238         fast_memcpy(str+str_l, p, (n>avail?avail:n));
1239       }
1240       p += n; str_l += n;
1241     } else {
1242       const char *starting_p;
1243       size_t min_field_width = 0, precision = 0;
1244       int zero_padding = 0, precision_specified = 0, justify_left = 0;
1245       int alternate_form = 0, force_sign = 0;
1246       int space_for_positive = 1; /* If both the ' ' and '+' flags appear,
1247                                      the ' ' flag should be ignored. */
1248       char length_modifier = '\0';            /* allowed values: \0, h, l, L */
1249       char tmp[32];/* temporary buffer for simple numeric->string conversion */
1250
1251       const char *str_arg;      /* string address in case of string argument */
1252       size_t str_arg_l;         /* natural field width of arg without padding
1253                                    and sign */
1254       unsigned char uchar_arg;
1255         /* unsigned char argument value - only defined for c conversion.
1256            N.B. standard explicitly states the char argument for
1257            the c conversion is unsigned */
1258
1259       size_t number_of_zeros_to_pad = 0;
1260         /* number of zeros to be inserted for numeric conversions
1261            as required by the precision or minimal field width */
1262
1263       size_t zero_padding_insertion_ind = 0;
1264         /* index into tmp where zero padding is to be inserted */
1265
1266       char fmt_spec = '\0';
1267         /* current conversion specifier character */
1268
1269       str_arg = credits;/* just to make compiler happy (defined but not used)*/
1270       str_arg = NULL;
1271       starting_p = p; p++;  /* skip '%' */
1272    /* parse flags */
1273       while (*p == '0' || *p == '-' || *p == '+' ||
1274              *p == ' ' || *p == '#' || *p == '\'') {
1275         switch (*p) {
1276         case '0': zero_padding = 1; break;
1277         case '-': justify_left = 1; break;
1278         case '+': force_sign = 1; space_for_positive = 0; break;
1279         case ' ': force_sign = 1;
1280      /* If both the ' ' and '+' flags appear, the ' ' flag should be ignored */
1281 #ifdef PERL_COMPATIBLE
1282      /* ... but in Perl the last of ' ' and '+' applies */
1283                   space_for_positive = 1;
1284 #endif
1285                   break;
1286         case '#': alternate_form = 1; break;
1287         case '\'': break;
1288         }
1289         p++;
1290       }
1291    /* If the '0' and '-' flags both appear, the '0' flag should be ignored. */
1292
1293    /* parse field width */
1294       if (*p == '*') {
1295         int j;
1296         p++; j = va_arg(ap, int);
1297         if (j >= 0) min_field_width = j;
1298         else { min_field_width = -j; justify_left = 1; }
1299       } else if (isdigit((int)(*p))) {
1300         /* size_t could be wider than unsigned int;
1301            make sure we treat argument like common implementations do */
1302         unsigned int uj = *p++ - '0';
1303         while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0');
1304         min_field_width = uj;
1305       }
1306    /* parse precision */
1307       if (*p == '.') {
1308         p++; precision_specified = 1;
1309         if (*p == '*') {
1310           int j = va_arg(ap, int);
1311           p++;
1312           if (j >= 0) precision = j;
1313           else {
1314             precision_specified = 0; precision = 0;
1315          /* NOTE:
1316           *   Solaris 2.6 man page claims that in this case the precision
1317           *   should be set to 0.  Digital Unix 4.0, HPUX 10 and BSD man page
1318           *   claim that this case should be treated as unspecified precision,
1319           *   which is what we do here.
1320           */
1321           }
1322         } else if (isdigit((int)(*p))) {
1323           /* size_t could be wider than unsigned int;
1324              make sure we treat argument like common implementations do */
1325           unsigned int uj = *p++ - '0';
1326           while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0');
1327           precision = uj;
1328         }
1329       }
1330    /* parse 'h', 'l' and 'll' length modifiers */
1331       if (*p == 'h' || *p == 'l') {
1332         length_modifier = *p; p++;
1333         if (length_modifier == 'l' && *p == 'l') {   /* double l = long long */
1334 #ifdef SNPRINTF_LONGLONG_SUPPORT
1335           length_modifier = '2';                  /* double l encoded as '2' */
1336 #else
1337           length_modifier = 'l';                 /* treat it as a single 'l' */
1338 #endif
1339           p++;
1340         }
1341       }
1342       fmt_spec = *p;
1343    /* common synonyms: */
1344       switch (fmt_spec) {
1345       case 'i': fmt_spec = 'd'; break;
1346       case 'D': fmt_spec = 'd'; length_modifier = 'l'; break;
1347       case 'U': fmt_spec = 'u'; length_modifier = 'l'; break;
1348       case 'O': fmt_spec = 'o'; length_modifier = 'l'; break;
1349       default: break;
1350       }
1351    /* get parameter value, do initial processing */
1352       switch (fmt_spec) {
1353       case '%': /* % behaves similar to 's' regarding flags and field widths */
1354       case 'c': /* c behaves similar to 's' regarding flags and field widths */
1355       case 's':
1356         length_modifier = '\0';          /* wint_t and wchar_t not supported */
1357      /* the result of zero padding flag with non-numeric conversion specifier*/
1358      /* is undefined. Solaris and HPUX 10 does zero padding in this case,    */
1359      /* Digital Unix and Linux does not. */
1360 #if !defined(SOLARIS_COMPATIBLE) && !defined(HPUX_COMPATIBLE)
1361         zero_padding = 0;    /* turn zero padding off for string conversions */
1362 #endif
1363         str_arg_l = 1;
1364         switch (fmt_spec) {
1365         case '%':
1366           str_arg = p; break;
1367         case 'c': {
1368           int j = va_arg(ap, int);
1369           uchar_arg = (unsigned char) j;   /* standard demands unsigned char */
1370           str_arg = (const char *) &uchar_arg;
1371           break;
1372         }
1373         case 's':
1374           str_arg = va_arg(ap, const char *);
1375           if (!str_arg) str_arg_l = 0;
1376        /* make sure not to address string beyond the specified precision !!! */
1377           else if (!precision_specified) str_arg_l = strlen(str_arg);
1378        /* truncate string if necessary as requested by precision */
1379           else if (precision == 0) str_arg_l = 0;
1380           else {
1381        /* memchr on HP does not like n > 2^31  !!! */
1382             const char *q = memchr(str_arg, '\0',
1383                              precision <= 0x7fffffff ? precision : 0x7fffffff);
1384             str_arg_l = !q ? precision : (q-str_arg);
1385           }
1386           break;
1387         default: break;
1388         }
1389         break;
1390       case 'd': case 'u': case 'o': case 'x': case 'X': case 'p': {
1391         /* NOTE: the u, o, x, X and p conversion specifiers imply
1392                  the value is unsigned;  d implies a signed value */
1393
1394         int arg_sign = 0;
1395           /* 0 if numeric argument is zero (or if pointer is NULL for 'p'),
1396             +1 if greater than zero (or nonzero for unsigned arguments),
1397             -1 if negative (unsigned argument is never negative) */
1398
1399         int int_arg = 0;  unsigned int uint_arg = 0;
1400           /* only defined for length modifier h, or for no length modifiers */
1401
1402         long int long_arg = 0;  unsigned long int ulong_arg = 0;
1403           /* only defined for length modifier l */
1404
1405         void *ptr_arg = NULL;
1406           /* pointer argument value -only defined for p conversion */
1407
1408 #ifdef SNPRINTF_LONGLONG_SUPPORT
1409         long long int long_long_arg = 0;
1410         unsigned long long int ulong_long_arg = 0;
1411           /* only defined for length modifier ll */
1412 #endif
1413         if (fmt_spec == 'p') {
1414         /* HPUX 10: An l, h, ll or L before any other conversion character
1415          *   (other than d, i, u, o, x, or X) is ignored.
1416          * Digital Unix:
1417          *   not specified, but seems to behave as HPUX does.
1418          * Solaris: If an h, l, or L appears before any other conversion
1419          *   specifier (other than d, i, u, o, x, or X), the behavior
1420          *   is undefined. (Actually %hp converts only 16-bits of address
1421          *   and %llp treats address as 64-bit data which is incompatible
1422          *   with (void *) argument on a 32-bit system).
1423          */
1424 #ifdef SOLARIS_COMPATIBLE
1425 #  ifdef SOLARIS_BUG_COMPATIBLE
1426           /* keep length modifiers even if it represents 'll' */
1427 #  else
1428           if (length_modifier == '2') length_modifier = '\0';
1429 #  endif
1430 #else
1431           length_modifier = '\0';
1432 #endif
1433           ptr_arg = va_arg(ap, void *);
1434           if (ptr_arg != NULL) arg_sign = 1;
1435         } else if (fmt_spec == 'd') {  /* signed */
1436           switch (length_modifier) {
1437           case '\0':
1438           case 'h':
1439          /* It is non-portable to specify a second argument of char or short
1440           * to va_arg, because arguments seen by the called function
1441           * are not char or short.  C converts char and short arguments
1442           * to int before passing them to a function.
1443           */
1444             int_arg = va_arg(ap, int);
1445             if      (int_arg > 0) arg_sign =  1;
1446             else if (int_arg < 0) arg_sign = -1;
1447             break;
1448           case 'l':
1449             long_arg = va_arg(ap, long int);
1450             if      (long_arg > 0) arg_sign =  1;
1451             else if (long_arg < 0) arg_sign = -1;
1452             break;
1453 #ifdef SNPRINTF_LONGLONG_SUPPORT
1454           case '2':
1455             long_long_arg = va_arg(ap, long long int);
1456             if      (long_long_arg > 0) arg_sign =  1;
1457             else if (long_long_arg < 0) arg_sign = -1;
1458             break;
1459 #endif
1460           }
1461         } else {  /* unsigned */
1462           switch (length_modifier) {
1463           case '\0':
1464           case 'h':
1465             uint_arg = va_arg(ap, unsigned int);
1466             if (uint_arg) arg_sign = 1;
1467             break;
1468           case 'l':
1469             ulong_arg = va_arg(ap, unsigned long int);
1470             if (ulong_arg) arg_sign = 1;
1471             break;
1472 #ifdef SNPRINTF_LONGLONG_SUPPORT
1473           case '2':
1474             ulong_long_arg = va_arg(ap, unsigned long long int);
1475             if (ulong_long_arg) arg_sign = 1;
1476             break;
1477 #endif
1478           }
1479         }
1480         str_arg = tmp; str_arg_l = 0;
1481      /* NOTE:
1482       *   For d, i, u, o, x, and X conversions, if precision is specified,
1483       *   the '0' flag should be ignored. This is so with Solaris 2.6,
1484       *   Digital UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl.
1485       */
1486 #ifndef PERL_COMPATIBLE
1487         if (precision_specified) zero_padding = 0;
1488 #endif
1489         if (fmt_spec == 'd') {
1490           if (force_sign && arg_sign >= 0)
1491             tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
1492          /* leave negative numbers for sprintf to handle,
1493             to avoid handling tricky cases like (short int)(-32768) */
1494 #ifdef LINUX_COMPATIBLE
1495         } else if (fmt_spec == 'p' && force_sign && arg_sign > 0) {
1496           tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
1497 #endif
1498         } else if (alternate_form) {
1499           if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X') )
1500             { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = fmt_spec; }
1501          /* alternate form should have no effect for p conversion, but ... */
1502 #ifdef HPUX_COMPATIBLE
1503           else if (fmt_spec == 'p'
1504          /* HPUX 10: for an alternate form of p conversion,
1505           *          a nonzero result is prefixed by 0x. */
1506 #ifndef HPUX_BUG_COMPATIBLE
1507          /* Actually it uses 0x prefix even for a zero value. */
1508                    && arg_sign != 0
1509 #endif
1510                   ) { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = 'x'; }
1511 #endif
1512         }
1513         zero_padding_insertion_ind = str_arg_l;
1514         if (!precision_specified) precision = 1;   /* default precision is 1 */
1515         if (precision == 0 && arg_sign == 0
1516 #if defined(HPUX_BUG_COMPATIBLE) || defined(LINUX_COMPATIBLE)
1517             && fmt_spec != 'p'
1518          /* HPUX 10 man page claims: With conversion character p the result of
1519           * converting a zero value with a precision of zero is a null string.
1520           * Actually HP returns all zeroes, and Linux returns "(nil)". */
1521 #endif
1522         ) {
1523          /* converted to null string */
1524          /* When zero value is formatted with an explicit precision 0,
1525             the resulting formatted string is empty (d, i, u, o, x, X, p).   */
1526         } else {
1527           char f[5]; int f_l = 0;
1528           f[f_l++] = '%';    /* construct a simple format string for sprintf */
1529           if (!length_modifier) { }
1530           else if (length_modifier=='2') { f[f_l++] = 'l'; f[f_l++] = 'l'; }
1531           else f[f_l++] = length_modifier;
1532           f[f_l++] = fmt_spec; f[f_l++] = '\0';
1533           if (fmt_spec == 'p') str_arg_l += sprintf(tmp+str_arg_l, f, ptr_arg);
1534           else if (fmt_spec == 'd') {  /* signed */
1535             switch (length_modifier) {
1536             case '\0':
1537             case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, int_arg);  break;
1538             case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, long_arg); break;
1539 #ifdef SNPRINTF_LONGLONG_SUPPORT
1540             case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,long_long_arg); break;
1541 #endif
1542             }
1543           } else {  /* unsigned */
1544             switch (length_modifier) {
1545             case '\0':
1546             case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, uint_arg);  break;
1547             case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, ulong_arg); break;
1548 #ifdef SNPRINTF_LONGLONG_SUPPORT
1549             case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,ulong_long_arg);break;
1550 #endif
1551             }
1552           }
1553          /* include the optional minus sign and possible "0x"
1554             in the region before the zero padding insertion point */
1555           if (zero_padding_insertion_ind < str_arg_l &&
1556               tmp[zero_padding_insertion_ind] == '-') {
1557             zero_padding_insertion_ind++;
1558           }
1559           if (zero_padding_insertion_ind+1 < str_arg_l &&
1560               tmp[zero_padding_insertion_ind]   == '0' &&
1561              (tmp[zero_padding_insertion_ind+1] == 'x' ||
1562               tmp[zero_padding_insertion_ind+1] == 'X') ) {
1563             zero_padding_insertion_ind += 2;
1564           }
1565         }
1566         { size_t num_of_digits = str_arg_l - zero_padding_insertion_ind;
1567           if (alternate_form && fmt_spec == 'o'
1568 #ifdef HPUX_COMPATIBLE                                  /* ("%#.o",0) -> ""  */
1569               && (str_arg_l > 0)
1570 #endif
1571 #ifdef DIGITAL_UNIX_BUG_COMPATIBLE                      /* ("%#o",0) -> "00" */
1572 #else
1573               /* unless zero is already the first character */
1574               && !(zero_padding_insertion_ind < str_arg_l
1575                    && tmp[zero_padding_insertion_ind] == '0')
1576 #endif
1577           ) {        /* assure leading zero for alternate-form octal numbers */
1578             if (!precision_specified || precision < num_of_digits+1) {
1579              /* precision is increased to force the first character to be zero,
1580                 except if a zero value is formatted with an explicit precision
1581                 of zero */
1582               precision = num_of_digits+1; precision_specified = 1;
1583             }
1584           }
1585        /* zero padding to specified precision? */
1586           if (num_of_digits < precision)
1587             number_of_zeros_to_pad = precision - num_of_digits;
1588         }
1589      /* zero padding to specified minimal field width? */
1590         if (!justify_left && zero_padding) {
1591           int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
1592           if (n > 0) number_of_zeros_to_pad += n;
1593         }
1594         break;
1595       }
1596       default: /* unrecognized conversion specifier, keep format string as-is*/
1597         zero_padding = 0;  /* turn zero padding off for non-numeric convers. */
1598 #ifndef DIGITAL_UNIX_COMPATIBLE
1599         justify_left = 1; min_field_width = 0;                /* reset flags */
1600 #endif
1601 #if defined(PERL_COMPATIBLE) || defined(LINUX_COMPATIBLE)
1602      /* keep the entire format string unchanged */
1603         str_arg = starting_p; str_arg_l = p - starting_p;
1604      /* well, not exactly so for Linux, which does something between,
1605       * and I don't feel an urge to imitate it: "%+++++hy" -> "%+y"  */
1606 #else
1607      /* discard the unrecognized conversion, just keep *
1608       * the unrecognized conversion character          */
1609         str_arg = p; str_arg_l = 0;
1610 #endif
1611         if (*p) str_arg_l++;  /* include invalid conversion specifier unchanged
1612                                  if not at end-of-string */
1613         break;
1614       }
1615       if (*p) p++;      /* step over the just processed conversion specifier */
1616    /* insert padding to the left as requested by min_field_width;
1617       this does not include the zero padding in case of numerical conversions*/
1618       if (!justify_left) {                /* left padding with blank or zero */
1619         int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
1620         if (n > 0) {
1621           if (str_l < str_m) {
1622             size_t avail = str_m-str_l;
1623             fast_memset(str+str_l, (zero_padding?'0':' '), (n>avail?avail:n));
1624           }
1625           str_l += n;
1626         }
1627       }
1628    /* zero padding as requested by the precision or by the minimal field width
1629     * for numeric conversions required? */
1630       if (number_of_zeros_to_pad <= 0) {
1631      /* will not copy first part of numeric right now, *
1632       * force it to be copied later in its entirety    */
1633         zero_padding_insertion_ind = 0;
1634       } else {
1635      /* insert first part of numerics (sign or '0x') before zero padding */
1636         int n = zero_padding_insertion_ind;
1637         if (n > 0) {
1638           if (str_l < str_m) {
1639             size_t avail = str_m-str_l;
1640             fast_memcpy(str+str_l, str_arg, (n>avail?avail:n));
1641           }
1642           str_l += n;
1643         }
1644      /* insert zero padding as requested by the precision or min field width */
1645         n = number_of_zeros_to_pad;
1646         if (n > 0) {
1647           if (str_l < str_m) {
1648             size_t avail = str_m-str_l;
1649             fast_memset(str+str_l, '0', (n>avail?avail:n));
1650           }
1651           str_l += n;
1652         }
1653       }
1654    /* insert formatted string
1655     * (or as-is conversion specifier for unknown conversions) */
1656       { int n = str_arg_l - zero_padding_insertion_ind;
1657         if (n > 0) {
1658           if (str_l < str_m) {
1659             size_t avail = str_m-str_l;
1660             fast_memcpy(str+str_l, str_arg+zero_padding_insertion_ind,
1661                         (n>avail?avail:n));
1662           }
1663           str_l += n;
1664         }
1665       }
1666    /* insert right padding */
1667       if (justify_left) {          /* right blank padding to the field width */
1668         int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
1669         if (n > 0) {
1670           if (str_l < str_m) {
1671             size_t avail = str_m-str_l;
1672             fast_memset(str+str_l, ' ', (n>avail?avail:n));
1673           }
1674           str_l += n;
1675         }
1676       }
1677     }
1678   }
1679 #if defined(NEED_SNPRINTF_ONLY)
1680   va_end(ap);
1681 #endif
1682   if (str_m > 0) { /* make sure the string is null-terminated
1683                       even at the expense of overwriting the last character
1684                       (shouldn't happen, but just in case) */
1685     str[str_l <= str_m-1 ? str_l : str_m-1] = '\0';
1686   }
1687   /* Return the number of characters formatted (excluding trailing null
1688    * character), that is, the number of characters that would have been
1689    * written to the buffer if it were large enough.
1690    *
1691    * The value of str_l should be returned, but str_l is of unsigned type
1692    * size_t, and snprintf is int, possibly leading to an undetected
1693    * integer overflow, resulting in a negative return value, which is illegal.
1694    * Both XSH5 and ISO C99 (at least the draft) are silent on this issue.
1695    * Should errno be set to EOVERFLOW and EOF returned in this case???
1696    */
1697   return (int) str_l;
1698 }
1699 #endif
1700 #endif /* ndef HAVE_SNPRINTF */
1701 /*
1702   Local Variables:
1703   tab-width: 3
1704   end:
1705 */