Don't include replacement timegm() if
[privoxy.git] / miscutil.c
1 const char miscutil_rcs[] = "$Id: miscutil.c,v 1.45 2006/12/26 17:31:41 fabiankeil Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/miscutil.c,v $
5  *
6  * Purpose     :  zalloc, hash_string, safe_strerror, strcmpic,
7  *                strncmpic, chomp, and MinGW32 strdup
8  *                functions. 
9  *                These are each too small to deserve their own file
10  *                but don't really fit in any other file.
11  *
12  * Copyright   :  Written by and Copyright (C) 2001-2003, 2006
13  *                the SourceForge Privoxy team. http://www.privoxy.org/
14  *
15  *                Based on the Internet Junkbuster originally written
16  *                by and Copyright (C) 1997 Anonymous Coders and 
17  *                Junkbusters Corporation.  http://www.junkbusters.com
18  *
19  *                This program is free software; you can redistribute it 
20  *                and/or modify it under the terms of the GNU General
21  *                Public License as published by the Free Software
22  *                Foundation; either version 2 of the License, or (at
23  *                your option) any later version.
24  *
25  *                This program is distributed in the hope that it will
26  *                be useful, but WITHOUT ANY WARRANTY; without even the
27  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
28  *                PARTICULAR PURPOSE.  See the GNU General Public
29  *                License for more details.
30  *
31  *                The GNU General Public License should be included with
32  *                this file.  If not, you can view it at
33  *                http://www.gnu.org/copyleft/gpl.html
34  *                or write to the Free Software Foundation, Inc., 59
35  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
36  *
37  * Revisions   :
38  *    $Log: miscutil.c,v $
39  *    Revision 1.45  2006/12/26 17:31:41  fabiankeil
40  *    Mutex protect rand() if POSIX threading
41  *    is used, warn the user if that's not possible
42  *    and stop using it on _WIN32 where it could
43  *    cause crashes.
44  *
45  *    Revision 1.44  2006/11/07 12:46:43  fabiankeil
46  *    Silence compiler warning on NetBSD 3.1.
47  *
48  *    Revision 1.43  2006/09/23 13:26:38  roro
49  *    Replace TABs by spaces in source code.
50  *
51  *    Revision 1.42  2006/09/09 14:01:45  fabiankeil
52  *    Integrated Oliver Yeoh's domain pattern fix
53  *    to make sure *x matches xx. Closes Patch 1217393
54  *    and Bug 1170767.
55  *
56  *    Revision 1.41  2006/08/18 16:03:17  david__schmidt
57  *    Tweak for OS/2 build happiness.
58  *
59  *    Revision 1.40  2006/08/17 17:15:10  fabiankeil
60  *    - Back to timegm() using GnuPG's replacement if necessary.
61  *      Using mktime() and localtime() could add a on hour offset if
62  *      the randomize factor was big enough to lead to a summer/wintertime
63  *      switch.
64  *
65  *    - Removed now-useless Privoxy 3.0.3 compatibility glue.
66  *
67  *    - Moved randomization code into pick_from_range().
68  *
69  *    - Changed parse_header_time definition.
70  *      time_t isn't guaranteed to be signed and
71  *      if it isn't, -1 isn't available as error code.
72  *      Changed some variable types in client_if_modified_since()
73  *      because of the same reason.
74  *
75  *    Revision 1.39  2006/07/18 14:48:46  david__schmidt
76  *    Reorganizing the repository: swapping out what was HEAD (the old 3.1 branch)
77  *    with what was really the latest development (the v_3_0_branch branch)
78  *
79  *    Revision 1.37.2.4  2003/12/01 14:45:14  oes
80  *    Fixed two more problems with wildcarding in simplematch()
81  *
82  *    Revision 1.37.2.3  2003/11/20 11:39:24  oes
83  *    Bugfix: The "?" wildcard for domain names had never been implemented. Ooops\!
84  *
85  *    Revision 1.37.2.2  2002/11/12 14:28:18  oes
86  *    Proper backtracking in simplematch; fixes bug #632888
87  *
88  *    Revision 1.37.2.1  2002/09/25 12:58:51  oes
89  *    Made strcmpic and strncmpic safe against NULL arguments
90  *    (which are now treated as empty strings).
91  *
92  *    Revision 1.37  2002/04/26 18:29:43  jongfoster
93  *    Fixing this Visual C++ warning:
94  *    miscutil.c(710) : warning C4090: '=' : different 'const' qualifiers
95  *
96  *    Revision 1.36  2002/04/26 12:55:38  oes
97  *    New function string_toupper
98  *
99  *    Revision 1.35  2002/03/26 22:29:55  swa
100  *    we have a new homepage!
101  *
102  *    Revision 1.34  2002/03/24 13:25:43  swa
103  *    name change related issues
104  *
105  *    Revision 1.33  2002/03/07 03:46:53  oes
106  *    Fixed compiler warnings etc
107  *
108  *    Revision 1.32  2002/03/06 23:02:57  jongfoster
109  *    Removing tabs
110  *
111  *    Revision 1.31  2002/03/05 04:52:42  oes
112  *    Deleted non-errlog debugging code
113  *
114  *    Revision 1.30  2002/03/04 18:27:42  oes
115  *    - Deleted deletePidFile
116  *    - Made write_pid_file use the --pidfile option value
117  *      (or no PID file, if the option was absent)
118  *    - Played styleguide police
119  *
120  *    Revision 1.29  2002/03/04 02:08:02  david__schmidt
121  *    Enable web editing of actions file on OS/2 (it had been broken all this time!)
122  *
123  *    Revision 1.28  2002/03/03 09:18:03  joergs
124  *    Made jumbjuster work on AmigaOS again.
125  *
126  *    Revision 1.27  2002/01/21 00:52:32  jongfoster
127  *    Adding string_join()
128  *
129  *    Revision 1.26  2001/12/30 14:07:32  steudten
130  *    - Add signal handling (unix)
131  *    - Add SIGHUP handler (unix)
132  *    - Add creation of pidfile (unix)
133  *    - Add action 'top' in rc file (RH)
134  *    - Add entry 'SIGNALS' to manpage
135  *    - Add exit message to logfile (unix)
136  *
137  *    Revision 1.25  2001/11/13 00:16:38  jongfoster
138  *    Replacing references to malloc.h with the standard stdlib.h
139  *    (See ANSI or K&R 2nd Ed)
140  *
141  *    Revision 1.24  2001/11/05 21:41:43  steudten
142  *    Add changes to be a real daemon just for unix os.
143  *    (change cwd to /, detach from controlling tty, set
144  *    process group and session leader to the own process.
145  *    Add DBG() Macro.
146  *    Add some fatal-error log message for failed malloc().
147  *    Add '-d' if compiled with 'configure --with-debug' to
148  *    enable debug output.
149  *
150  *    Revision 1.23  2001/10/29 03:48:10  david__schmidt
151  *    OS/2 native needed a snprintf() routine.  Added one to miscutil, brackedted
152  *    by and __OS2__ ifdef.
153  *
154  *    Revision 1.22  2001/10/26 17:39:38  oes
155  *    Moved ijb_isspace and ijb_tolower to project.h
156  *
157  *    Revision 1.21  2001/10/23 21:27:50  jongfoster
158  *    Standardising error codes in string_append
159  *    make_path() no longer adds '\\' if the dir already ends in '\\' (this
160  *    is just copying a UNIX-specific fix to the Windows-specific part)
161  *
162  *    Revision 1.20  2001/10/22 15:33:56  david__schmidt
163  *    Special-cased OS/2 out of the Netscape-abort-on-404-in-js problem in
164  *    filters.c.  Added a FIXME in front of the offending code.  I'll gladly
165  *    put in a better/more robust fix for all parties if one is presented...
166  *    It seems that just returning 200 instead of 404 would pretty much fix
167  *    it for everyone, but I don't know all the history of the problem.
168  *
169  *    Revision 1.19  2001/10/14 22:02:57  jongfoster
170  *    New function string_append() which is like strsav(), but running
171  *    out of memory isn't automatically FATAL.
172  *
173  *    Revision 1.18  2001/09/20 13:33:43  steudten
174  *
175  *    change long to int as return value in hash_string(). Remember the wraparound
176  *    for int = long = sizeof(4) - thats maybe not what we want.
177  *
178  *    Revision 1.17  2001/09/13 20:51:29  jongfoster
179  *    Fixing potential problems with characters >=128 in simplematch()
180  *    This was also a compiler warning.
181  *
182  *    Revision 1.16  2001/09/10 10:56:59  oes
183  *    Silenced compiler warnings
184  *
185  *    Revision 1.15  2001/07/13 14:02:24  oes
186  *    Removed vim-settings
187  *
188  *    Revision 1.14  2001/06/29 21:45:41  oes
189  *    Indentation, CRLF->LF, Tab-> Space
190  *
191  *    Revision 1.13  2001/06/29 13:32:14  oes
192  *    Removed logentry from cancelled commit
193  *
194  *    Revision 1.12  2001/06/09 10:55:28  jongfoster
195  *    Changing BUFSIZ ==> BUFFER_SIZE
196  *
197  *    Revision 1.11  2001/06/07 23:09:19  jongfoster
198  *    Cosmetic indentation changes.
199  *
200  *    Revision 1.10  2001/06/07 14:51:38  joergs
201  *    make_path() no longer adds '/' if the dir already ends in '/'.
202  *
203  *    Revision 1.9  2001/06/07 14:43:17  swa
204  *    slight mistake in make_path, unix path style is /.
205  *
206  *    Revision 1.8  2001/06/05 22:32:01  jongfoster
207  *    New function make_path() to splice directory and file names together.
208  *
209  *    Revision 1.7  2001/06/03 19:12:30  oes
210  *    introduced bindup()
211  *
212  *    Revision 1.6  2001/06/01 18:14:49  jongfoster
213  *    Changing the calls to strerr() to check HAVE_STRERR (which is defined
214  *    in config.h if appropriate) rather than the NO_STRERR macro.
215  *
216  *    Revision 1.5  2001/06/01 10:31:51  oes
217  *    Added character class matching to trivimatch; renamed to simplematch
218  *
219  *    Revision 1.4  2001/05/31 17:32:31  oes
220  *
221  *     - Enhanced domain part globbing with infix and prefix asterisk
222  *       matching and optional unanchored operation
223  *
224  *    Revision 1.3  2001/05/29 23:10:09  oes
225  *
226  *
227  *     - Introduced chomp()
228  *     - Moved strsav() from showargs to miscutil
229  *
230  *    Revision 1.2  2001/05/29 09:50:24  jongfoster
231  *    Unified blocklist/imagelist/permissionslist.
232  *    File format is still under discussion, but the internal changes
233  *    are (mostly) done.
234  *
235  *    Also modified interceptor behaviour:
236  *    - We now intercept all URLs beginning with one of the following
237  *      prefixes (and *only* these prefixes):
238  *        * http://i.j.b/
239  *        * http://ijbswa.sf.net/config/
240  *        * http://ijbswa.sourceforge.net/config/
241  *    - New interceptors "home page" - go to http://i.j.b/ to see it.
242  *    - Internal changes so that intercepted and fast redirect pages
243  *      are not replaced with an image.
244  *    - Interceptors now have the option to send a binary page direct
245  *      to the client. (i.e. ijb-send-banner uses this)
246  *    - Implemented show-url-info interceptor.  (Which is why I needed
247  *      the above interceptors changes - a typical URL is
248  *      "http://i.j.b/show-url-info?url=www.somesite.com/banner.gif".
249  *      The previous mechanism would not have intercepted that, and
250  *      if it had been intercepted then it then it would have replaced
251  *      it with an image.)
252  *
253  *    Revision 1.1.1.1  2001/05/15 13:59:00  oes
254  *    Initial import of version 2.9.3 source tree
255  *
256  *
257  *********************************************************************/
258 \f
259
260 #include "config.h"
261
262 #include <stdio.h>
263 #include <sys/types.h>
264 #include <stdlib.h>
265 #if !defined(_WIN32) && !defined(__OS2__)
266 #include <unistd.h>
267 #endif /* #if !defined(_WIN32) && !defined(__OS2__) */
268 #include <string.h>
269 #include <ctype.h>
270 #include <assert.h>
271
272 #if !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV)
273 #include <time.h>
274 #endif /* !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV) */
275
276 #include "project.h"
277 #include "miscutil.h"
278 #include "errlog.h"
279 #include "jcc.h"
280
281 const char miscutil_h_rcs[] = MISCUTIL_H_VERSION;
282
283 /*********************************************************************
284  *
285  * Function    :  zalloc
286  *
287  * Description :  Malloc some memory and set it to '\0'.
288  *                The way calloc() ought to be -acjc
289  *
290  * Parameters  :
291  *          1  :  size = Size of memory chunk to return.
292  *
293  * Returns     :  Pointer to newly malloc'd memory chunk.
294  *
295  *********************************************************************/
296 void *zalloc(size_t size)
297 {
298    void * ret;
299
300    if ((ret = (void *)malloc(size)) != NULL)
301    {
302       memset(ret, 0, size);
303    }
304
305    return(ret);
306
307 }
308
309
310 #if defined(unix)
311 /*********************************************************************
312  *
313  * Function    :  write_pid_file 
314  *
315  * Description :  Writes a pid file with the pid of the main process 
316  *
317  * Parameters  :  None
318  *
319  * Returns     :  N/A 
320  *
321  *********************************************************************/
322 void write_pid_file(void)
323 {
324    FILE   *fp;
325    
326    /*
327     * If no --pidfile option was given,
328     * we can live without one.
329     */
330    if (pidfile == NULL) return;
331
332    if ((fp = fopen(pidfile, "w")) == NULL)
333    {
334       log_error(LOG_LEVEL_INFO, "can't open pidfile '%s': %E", pidfile);
335    }
336    else
337    {
338       fprintf(fp, "%u\n", (unsigned int) getpid());
339       fclose (fp);
340    }
341    return;
342
343 }
344 #endif /* def unix */
345
346
347 /*********************************************************************
348  *
349  * Function    :  hash_string
350  *
351  * Description :  Take a string and compute a (hopefuly) unique numeric
352  *                integer value.  This has several uses, but being able
353  *                to "switch" a string the one of my favorites.
354  *
355  * Parameters  :
356  *          1  :  s : string to be hashed.
357  *
358  * Returns     :  an unsigned long variable with the hashed value.
359  *
360  *********************************************************************/
361 unsigned int hash_string( const char* s )
362 {
363    unsigned int h = 0; 
364
365    for ( ; *s; ++s )
366    {
367       h = 5 * h + (unsigned int)*s;
368    }
369
370    return (h);
371
372 }
373
374
375 #ifdef __MINGW32__
376 /*********************************************************************
377  *
378  * Function    :  strdup
379  *
380  * Description :  For some reason (which is beyond me), gcc and WIN32
381  *                don't like strdup.  When a "free" is executed on a
382  *                strdup'd ptr, it can at times freez up!  So I just
383  *                replaced it and problem was solved.
384  *
385  * Parameters  :
386  *          1  :  s = string to duplicate
387  *
388  * Returns     :  Pointer to newly malloc'ed copy of the string.
389  *
390  *********************************************************************/
391 char *strdup( const char *s )
392 {
393    char * result = (char *)malloc( strlen(s)+1 );
394
395    if (result != NULL)
396    {
397       strcpy( result, s );
398    }
399
400    return( result );
401 }
402
403 #endif /* def __MINGW32__ */
404
405
406
407 /*********************************************************************
408  *
409  * Function    :  safe_strerror
410  *
411  * Description :  Variant of the library routine strerror() which will
412  *                work on systems without the library routine, and
413  *                which should never return NULL.
414  *
415  * Parameters  :
416  *          1  :  err = the `errno' of the last operation.
417  *
418  * Returns     :  An "English" string of the last `errno'.  Allocated
419  *                with strdup(), so caller frees.  May be NULL if the
420  *                system is out of memory.
421  *
422  *********************************************************************/
423 char *safe_strerror(int err)
424 {
425    char *s = NULL;
426    char buf[BUFFER_SIZE];
427
428
429 #ifdef HAVE_STRERROR
430    s = strerror(err);
431 #endif /* HAVE_STRERROR */
432
433    if (s == NULL)
434    {
435       sprintf(buf, "(errno = %d)", err);
436       s = buf;
437    }
438
439    return(strdup(s));
440
441 }
442
443
444 /*********************************************************************
445  *
446  * Function    :  strcmpic
447  *
448  * Description :  Case insensitive string comparison
449  *
450  * Parameters  :
451  *          1  :  s1 = string 1 to compare
452  *          2  :  s2 = string 2 to compare
453  *
454  * Returns     :  0 if s1==s2, Negative if s1<s2, Positive if s1>s2
455  *
456  *********************************************************************/
457 int strcmpic(const char *s1, const char *s2)
458 {
459    if (!s1) s1 = "";
460    if (!s2) s2 = "";
461
462    while (*s1 && *s2)
463    {
464       if ( ( *s1 != *s2 ) && ( ijb_tolower(*s1) != ijb_tolower(*s2) ) )
465       {
466          break;
467       }
468       s1++, s2++;
469    }
470    return(ijb_tolower(*s1) - ijb_tolower(*s2));
471
472 }
473
474
475 /*********************************************************************
476  *
477  * Function    :  strncmpic
478  *
479  * Description :  Case insensitive string comparison (upto n characters)
480  *
481  * Parameters  :
482  *          1  :  s1 = string 1 to compare
483  *          2  :  s2 = string 2 to compare
484  *          3  :  n = maximum characters to compare
485  *
486  * Returns     :  0 if s1==s2, Negative if s1<s2, Positive if s1>s2
487  *
488  *********************************************************************/
489 int strncmpic(const char *s1, const char *s2, size_t n)
490 {
491    if (n <= 0) return(0);
492    if (!s1) s1 = "";
493    if (!s2) s2 = "";
494    
495    while (*s1 && *s2)
496    {
497       if ( ( *s1 != *s2 ) && ( ijb_tolower(*s1) != ijb_tolower(*s2) ) )
498       {
499          break;
500       }
501
502       if (--n <= 0) break;
503
504       s1++, s2++;
505    }
506    return(ijb_tolower(*s1) - ijb_tolower(*s2));
507
508 }
509
510
511 /*********************************************************************
512  *
513  * Function    :  chomp
514  *
515  * Description :  In-situ-eliminate all leading and trailing whitespace
516  *                from a string.
517  *
518  * Parameters  :
519  *          1  :  s : string to be chomped.
520  *
521  * Returns     :  chomped string
522  *
523  *********************************************************************/
524 char *chomp(char *string)
525 {
526    char *p, *q, *r;
527
528    /* 
529     * strip trailing whitespace
530     */
531    p = string + strlen(string);
532    while (p > string && ijb_isspace(*(p-1)))
533    {
534       p--;
535    }
536    *p = '\0';
537
538    /* 
539     * find end of leading whitespace 
540     */
541    q = r = string;
542    while (*q && ijb_isspace(*q))
543    {
544       q++;
545    }
546
547    /*
548     * if there was any, move the rest forwards
549     */
550    if (q != string)
551    {
552       while (q <= p)
553       {
554          *r++ = *q++;
555       }
556    }
557
558    return(string);
559
560 }
561
562
563 /*********************************************************************
564  *
565  * Function    :  strsav
566  *
567  * Description :  Reallocate "old" and append text to it.  This makes
568  *                it easier to append to malloc'd strings.
569  *                Running out of memory is a FATAL error.
570  *
571  * Parameters  :
572  *          1  :  old = Old text that is to be extended.  Will be
573  *                free()d by this routine.  May be NULL.
574  *          2  :  text_to_append = Text to be appended to old.
575  *                May be NULL.
576  *
577  * Returns     :  Pointer to newly malloc'ed appended string.
578  *                If there is no text to append, return old.  Caller
579  *                must free().
580  *
581  *********************************************************************/
582 char *strsav(char *old, const char *text_to_append)
583 {
584    size_t old_len, new_len = 0;
585    char *p;
586
587    if ((text_to_append == NULL) || (*text_to_append == '\0'))
588    {
589       return(old);
590    }
591
592    if (NULL == old)
593    {
594       if ((p = strdup(text_to_append)) == NULL)
595       {
596          log_error(LOG_LEVEL_FATAL, "strdup() failed!");
597          /* Never get here - LOG_LEVEL_FATAL causes program exit */
598       }
599       return p;
600    }
601
602    old_len = strlen(old);
603    new_len = old_len + strlen(text_to_append) + 1;
604
605    if ((p = realloc(old, new_len)) == NULL)
606    {
607       log_error(LOG_LEVEL_FATAL, "realloc(%d) bytes failed!", new_len);
608       /* Never get here - LOG_LEVEL_FATAL causes program exit */
609    }
610
611    strcpy(p + old_len, text_to_append);
612    return(p);
613 }
614
615
616 /*********************************************************************
617  *
618  * Function    :  string_append
619  *
620  * Description :  Reallocate target_string and append text to it.  
621  *                This makes it easier to append to malloc'd strings.
622  *                This is similar to the (removed) strsav(), but
623  *                running out of memory isn't catastrophic.
624  *
625  *                Programming style:
626  *
627  *                The following style provides sufficient error
628  *                checking for this routine, with minimal clutter
629  *                in the source code.  It is recommended if you
630  *                have many calls to this function:
631  *
632  *                char * s = strdup(...); // don't check for error
633  *                string_append(&s, ...);  // don't check for error
634  *                string_append(&s, ...);  // don't check for error
635  *                string_append(&s, ...);  // don't check for error
636  *                if (NULL == s) { ... handle error ... }
637  *
638  *                OR, equivalently:
639  *
640  *                char * s = strdup(...); // don't check for error
641  *                string_append(&s, ...);  // don't check for error
642  *                string_append(&s, ...);  // don't check for error
643  *                if (string_append(&s, ...)) {... handle error ...}
644  *
645  * Parameters  :
646  *          1  :  target_string = Pointer to old text that is to be
647  *                extended.  *target_string will be free()d by this
648  *                routine.  target_string must be non-NULL.
649  *                If *target_string is NULL, this routine will
650  *                do nothing and return with an error - this allows
651  *                you to make many calls to this routine and only
652  *                check for errors after the last one.
653  *          2  :  text_to_append = Text to be appended to old.
654  *                Must not be NULL.
655  *
656  * Returns     :  JB_ERR_OK on success, and sets *target_string
657  *                   to newly malloc'ed appended string.  Caller
658  *                   must free(*target_string).
659  *                JB_ERR_MEMORY on out-of-memory.  (And free()s
660  *                   *target_string and sets it to NULL).
661  *                JB_ERR_MEMORY if *target_string is NULL.
662  *
663  *********************************************************************/
664 jb_err string_append(char **target_string, const char *text_to_append)
665 {
666    size_t old_len;
667    char *new_string;
668
669    assert(target_string);
670    assert(text_to_append);
671
672    if (*target_string == NULL)
673    {
674       return JB_ERR_MEMORY;
675    }
676
677    if (*text_to_append == '\0')
678    {
679       return JB_ERR_OK;
680    }
681
682    old_len = strlen(*target_string);
683
684    if (NULL == (new_string = realloc(*target_string,
685           strlen(text_to_append) + old_len + 1)))
686    {
687       free(*target_string);
688
689       *target_string = NULL;
690       return JB_ERR_MEMORY;
691    }
692
693    strcpy(new_string + old_len, text_to_append);
694
695    *target_string = new_string;
696    return JB_ERR_OK;
697 }
698
699
700 /*********************************************************************
701  *
702  * Function    :  string_join
703  *
704  * Description :  Join two strings together.  Frees BOTH the original
705  *                strings.  If either or both input strings are NULL,
706  *                fails as if it had run out of memory.
707  *
708  *                For comparison, string_append requires that the
709  *                second string is non-NULL, and doesn't free it.
710  *
711  *                Rationale: Too often, we want to do
712  *                string_append(s, html_encode(s2)).  That assert()s
713  *                if s2 is NULL or if html_encode() runs out of memory.
714  *                It also leaks memory.  Proper checking is cumbersome.
715  *                The solution: string_join(s, html_encode(s2)) is safe,
716  *                and will free the memory allocated by html_encode().
717  *
718  * Parameters  :
719  *          1  :  target_string = Pointer to old text that is to be
720  *                extended.  *target_string will be free()d by this
721  *                routine.  target_string must be non-NULL.
722  *          2  :  text_to_append = Text to be appended to old.
723  *
724  * Returns     :  JB_ERR_OK on success, and sets *target_string
725  *                   to newly malloc'ed appended string.  Caller
726  *                   must free(*target_string).
727  *                JB_ERR_MEMORY on out-of-memory, or if
728  *                   *target_string or text_to_append is NULL.  (In
729  *                   this case, frees *target_string and text_to_append,
730  *                   sets *target_string to NULL).
731  *
732  *********************************************************************/
733 jb_err string_join(char **target_string, char *text_to_append)
734 {
735    jb_err err;
736
737    assert(target_string);
738
739    if (text_to_append == NULL)
740    {
741       freez(*target_string);
742       return JB_ERR_MEMORY;
743    }
744
745    err = string_append(target_string, text_to_append);
746
747    free(text_to_append);
748
749    return err;
750 }
751
752
753 /*********************************************************************
754  *
755  * Function    :  string_toupper
756  *
757  * Description :  Produce a copy of string with all convertible
758  *                characters converted to uppercase.
759  *
760  * Parameters  :
761  *          1  :  string = string to convert
762  *
763  * Returns     :  Uppercase copy of string if possible, 
764  *                NULL on out-of-memory or if string was NULL.
765  *
766  *********************************************************************/
767 char *string_toupper(const char *string)
768 {
769    char *result, *p;
770    const char *q;
771
772    if (!string || ((result = (char *) zalloc(strlen(string) + 1)) == NULL))
773    {
774       return NULL;
775    }
776    
777    q = string;
778    p = result;
779
780    while (*q != '\0')
781    {
782       *p++ = toupper((int) *q++);
783    }
784
785    return result;
786
787 }
788
789
790 /*********************************************************************
791  *
792  * Function    :  simplematch
793  *
794  * Description :  String matching, with a (greedy) '*' wildcard that
795  *                stands for zero or more arbitrary characters and
796  *                character classes in [], which take both enumerations
797  *                and ranges.
798  *
799  * Parameters  :
800  *          1  :  pattern = pattern for matching
801  *          2  :  text    = text to be matched
802  *
803  * Returns     :  0 if match, else nonzero
804  *
805  *********************************************************************/
806 int simplematch(char *pattern, char *text)
807 {
808    unsigned char *pat = (unsigned char *) pattern;
809    unsigned char *txt = (unsigned char *) text;
810    unsigned char *fallback = pat; 
811    int wildcard = 0;
812   
813    unsigned char lastchar = 'a';
814    unsigned i;
815    unsigned char charmap[32];
816   
817    while (*txt)
818    {
819
820       /* EOF pattern but !EOF text? */
821       if (*pat == '\0')
822       {
823          if (wildcard)
824          {
825             pat = fallback;
826          }
827          else
828          {
829             return 1;
830          }
831       }
832
833       /* '*' in the pattern?  */
834       if (*pat == '*') 
835       {
836      
837          /* The pattern ends afterwards? Speed up the return. */
838          if (*++pat == '\0')
839          {
840             return 0;
841          }
842      
843          /* Else, set wildcard mode and remember position after '*' */
844          wildcard = 1;
845          fallback = pat;
846       }
847
848       /* Character range specification? */
849       if (*pat == '[')
850       {
851          memset(charmap, '\0', sizeof(charmap));
852
853          while (*++pat != ']')
854          {
855             if (!*pat)
856             { 
857                return 1;
858             }
859             else if (*pat == '-')
860             {
861                if ((*++pat == ']') || *pat == '\0')
862                {
863                   return(1);
864                }
865                for(i = lastchar; i <= *pat; i++)
866                {
867                   charmap[i / 8] |= (1 << (i % 8));
868                } 
869             }
870             else
871             {
872                charmap[*pat / 8] |= (1 << (*pat % 8));
873                lastchar = *pat;
874             }
875          }
876       } /* -END- if Character range specification */
877
878
879       /* 
880        * Char match, or char range match? 
881        */
882       if ( (*pat == *txt)
883       ||   (*pat == '?')
884       ||   ((*pat == ']') && (charmap[*txt / 8] & (1 << (*txt % 8)))) )
885       {
886          /* 
887           * Sucess: Go ahead
888           */
889          pat++;
890       }
891       else if (!wildcard)
892       {
893          /* 
894           * No match && no wildcard: No luck
895           */
896          return 1;
897       }
898       else if (pat != fallback)
899       {
900          /*
901           * Increment text pointer if in char range matching
902           */
903          if (*pat == ']')
904          {
905             txt++;
906          }
907          /*
908           * Wildcard mode && nonmatch beyond fallback: Rewind pattern
909           */
910          pat = fallback;
911          /*
912           * Restart matching from current text pointer
913           */
914          continue;
915       }
916       txt++;
917    }
918
919    /* Cut off extra '*'s */
920    if(*pat == '*')  pat++;
921
922    /* If this is the pattern's end, fine! */
923    return(*pat);
924
925 }
926
927
928 /*********************************************************************
929  *
930  * Function    :  bindup
931  *
932  * Description :  Duplicate the first n characters of a string that may
933  *                contain '\0' characters.
934  *
935  * Parameters  :
936  *          1  :  string = string to be duplicated
937  *          2  :  len = number of bytes to duplicate
938  *
939  * Returns     :  pointer to copy, or NULL if failiure
940  *
941  *********************************************************************/
942 char *bindup(const char *string, size_t len)
943 {
944    char *duplicate;
945
946    if (NULL == (duplicate = (char *)malloc(len)))
947    {
948       return NULL;
949    }
950    else
951    {
952      memcpy(duplicate, string, len);
953    }
954
955    return duplicate;
956
957 }
958
959
960 /*********************************************************************
961  *
962  * Function    :  make_path
963  *
964  * Description :  Takes a directory name and a file name, returns 
965  *                the complete path.  Handles windows/unix differences.
966  *                If the file name is already an absolute path, or if
967  *                the directory name is NULL or empty, it returns 
968  *                the filename. 
969  *
970  * Parameters  :
971  *          1  :  dir: Name of directory or NULL for none.
972  *          2  :  file: Name of file.  Should not be NULL or empty.
973  *
974  * Returns     :  "dir/file" (Or on windows, "dir\file").
975  *                It allocates the string on the heap.  Caller frees.
976  *                Returns NULL in error (i.e. NULL file or out of
977  *                memory) 
978  *
979  *********************************************************************/
980 char * make_path(const char * dir, const char * file)
981 {
982 #ifdef AMIGA
983    char path[512];
984
985    if(dir)
986    {
987       if(dir[0] == '.')
988       {
989          if(dir[1] == '/')
990          {
991             strncpy(path,dir+2,512);
992          }
993          else
994          {
995             strncpy(path,dir+1,512);
996          }
997       }
998       else
999       {
1000          strncpy(path,dir,512);
1001       }
1002       path[511]=0;
1003    } else {
1004       path[0]=0;
1005    }
1006    if(AddPart(path,file,512))
1007    {
1008       return strdup(path);
1009    } else {
1010       return NULL;
1011    }
1012 #else /* ndef AMIGA */
1013
1014    if ((file == NULL) || (*file == '\0'))
1015    {
1016       return NULL; /* Error */
1017    }
1018
1019    if ((dir == NULL) || (*dir == '\0') /* No directory specified */
1020 #if defined(_WIN32) || defined(__OS2__)
1021       || (*file == '\\') || (file[1] == ':') /* Absolute path (DOS) */
1022 #else /* ifndef _WIN32 || __OS2__ */
1023       || (*file == '/') /* Absolute path (U*ix) */
1024 #endif /* ifndef _WIN32 || __OS2__  */
1025       )
1026    {
1027       return strdup(file);
1028    }
1029    else
1030    {
1031       char * path;
1032
1033 #if defined(unix)
1034       if ( *dir != '/' && basedir && *basedir )
1035       {
1036          path = malloc( strlen( basedir ) + strlen(dir) + strlen(file) + 3);
1037          if (!path ) log_error(LOG_LEVEL_FATAL, "malloc failed!");
1038          strcpy(path, basedir);
1039          strcat(path, "/");
1040          strcat(path, dir);
1041       }
1042       else
1043       {
1044          path = malloc(strlen(dir) + strlen(file) + 2);
1045          if (!path ) log_error(LOG_LEVEL_FATAL, "malloc failed!");
1046          strcpy(path, dir);
1047       }
1048 #else
1049
1050       path = malloc(strlen(dir) + strlen(file) + 2);
1051       if (!path ) log_error(LOG_LEVEL_FATAL, "malloc failed!");
1052       strcpy(path, dir);
1053
1054 #endif /* defined unix */
1055
1056 #if defined(_WIN32) || defined(__OS2__)
1057       if(path[strlen(path)-1] != '\\')
1058       {
1059          strcat(path, "\\");
1060       }
1061 #else /* ifndef _WIN32 || __OS2__ */
1062       if(path[strlen(path)-1] != '/')
1063       {
1064          strcat(path, "/");
1065       }
1066 #endif /* ifndef _WIN32 || __OS2__ */
1067       strcat(path, file);
1068
1069       return path;
1070    }
1071 #endif /* ndef AMIGA */
1072 }
1073
1074
1075 /*********************************************************************
1076  *
1077  * Function    :  pick_from_range
1078  *
1079  * Description :  Pick a positive number out of a given range.
1080  *                Should only be used if randomness would be nice,
1081  *                but isn't really necessary.
1082  *
1083  * Parameters  :
1084  *          1  :  range: Highest possible number to pick.
1085  *
1086  * Returns     :  Picked number. 
1087  *
1088  *********************************************************************/
1089
1090 long int pick_from_range(long int range)
1091 {
1092    long int number;
1093 #ifdef HAVE_RANDOM
1094    number = random() % range + 1; 
1095 #elif defined(FEATURE_PTHREAD)
1096    pthread_mutex_lock(&rand_mutex);
1097    number = rand() % (long int)(range + 1);
1098    pthread_mutex_unlock(&rand_mutex);
1099 #else
1100 #ifdef _WIN32
1101    /*
1102     * On Windows and mingw32 srand() has to be called in every
1103     * rand()-using thread, but can cause crashes if it's not
1104     * mutex protected.
1105     *
1106     * Currently we don't have mutexes for mingw32, and for
1107     * our purpose this cludge is probably preferable to crashes.
1108     */
1109    log_error(LOG_LEVEL_INFO, "No thread-safe PRNG available? Using weak \'randomization\' factor.");
1110    number = (range + GetCurrentThreadId() % range) / 2;
1111 #else
1112    /*
1113     * XXX: Which platforms reach this and are there
1114     * better options than just using rand() and hoping
1115     * that it's safe?
1116     */
1117    log_error(LOG_LEVEL_INFO, "No thread-safe PRNG available? Header time randomization might cause "
1118       "crashes, predictable results or even combine these fine options.");
1119    number = rand() % (long int)(range + 1);
1120 #endif /* def _WIN32 */ 
1121
1122 #endif /* (def HAVE_RANDOM) */
1123
1124    return (number);
1125 }
1126
1127
1128 #if !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV)
1129 /*********************************************************************
1130  *
1131  * Function    :  timegm
1132  *
1133  * Description :  libc replacement function for the inverse of gmtime()
1134  *                Copyright (C) 2004 Free Software Foundation, Inc.
1135  *                Code copied from GnuPG with minor style changes.
1136  *
1137  * Parameters  :
1138  *          1  :  tm: Broken-down time struct.
1139  *
1140  * Returns     :  tm converted into time_t seconds. 
1141  *
1142  *********************************************************************/
1143
1144 time_t timegm(struct tm *tm)
1145 {
1146    time_t answer;
1147    char *zone;
1148
1149    zone=getenv("TZ");
1150    putenv("TZ=UTC");
1151    tzset();
1152    answer=mktime(tm);
1153    if(zone)
1154    {
1155       char *old_zone;
1156
1157       old_zone=malloc(3+strlen(zone)+1);
1158       if(old_zone)
1159       {
1160          strcpy(old_zone,"TZ=");
1161          strcat(old_zone,zone);
1162          putenv(old_zone);
1163       }
1164    }
1165    else
1166    {
1167 #ifdef HAVE_UNSETENV
1168       unsetenv("TZ");
1169 #else
1170       putenv("TZ");
1171 #endif
1172    }
1173    tzset();
1174    return answer;
1175 }
1176 #endif /* !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV) */
1177
1178
1179 /*
1180  * What follows is a portable snprintf routine, written by Mark Martinec.
1181  * See: http://www.ijs.si/software/snprintf/
1182  * Anyone who needs it can add a define for themselves... so far, only 
1183  * OS/2 (native) lacks snprintf.
1184
1185                                   snprintf.c
1186                    - a portable implementation of snprintf,
1187        including vsnprintf.c, asnprintf, vasnprintf, asprintf, vasprintf
1188                                        
1189    snprintf is a routine to convert numeric and string arguments to
1190    formatted strings. It is similar to sprintf(3) provided in a system's
1191    C library, yet it requires an additional argument - the buffer size -
1192    and it guarantees never to store anything beyond the given buffer,
1193    regardless of the format or arguments to be formatted. Some newer
1194    operating systems do provide snprintf in their C library, but many do
1195    not or do provide an inadequate (slow or idiosyncratic) version, which
1196    calls for a portable implementation of this routine.
1197
1198 Author
1199
1200    Mark Martinec <mark.martinec@ijs.si>, April 1999, June 2000
1201    Copyright © 1999, Mark Martinec
1202
1203  */
1204
1205 #ifdef __OS2__
1206
1207 #define PORTABLE_SNPRINTF_VERSION_MAJOR 2
1208 #define PORTABLE_SNPRINTF_VERSION_MINOR 2
1209
1210 #if defined(NEED_ASPRINTF) || defined(NEED_ASNPRINTF) || defined(NEED_VASPRINTF) || defined(NEED_VASNPRINTF)
1211 # if defined(NEED_SNPRINTF_ONLY)
1212 # undef NEED_SNPRINTF_ONLY
1213 # endif
1214 # if !defined(PREFER_PORTABLE_SNPRINTF)
1215 # define PREFER_PORTABLE_SNPRINTF
1216 # endif
1217 #endif
1218
1219 #if defined(SOLARIS_BUG_COMPATIBLE) && !defined(SOLARIS_COMPATIBLE)
1220 #define SOLARIS_COMPATIBLE
1221 #endif
1222
1223 #if defined(HPUX_BUG_COMPATIBLE) && !defined(HPUX_COMPATIBLE)
1224 #define HPUX_COMPATIBLE
1225 #endif
1226
1227 #if defined(DIGITAL_UNIX_BUG_COMPATIBLE) && !defined(DIGITAL_UNIX_COMPATIBLE)
1228 #define DIGITAL_UNIX_COMPATIBLE
1229 #endif
1230
1231 #if defined(PERL_BUG_COMPATIBLE) && !defined(PERL_COMPATIBLE)
1232 #define PERL_COMPATIBLE
1233 #endif
1234
1235 #if defined(LINUX_BUG_COMPATIBLE) && !defined(LINUX_COMPATIBLE)
1236 #define LINUX_COMPATIBLE
1237 #endif
1238
1239 #include <sys/types.h>
1240 #include <string.h>
1241 #include <stdlib.h>
1242 #include <stdio.h>
1243 #include <stdarg.h>
1244 #include <assert.h>
1245 #include <errno.h>
1246
1247 #ifdef isdigit
1248 #undef isdigit
1249 #endif
1250 #define isdigit(c) ((c) >= '0' && (c) <= '9')
1251
1252 /* For copying strings longer or equal to 'breakeven_point'
1253  * it is more efficient to call memcpy() than to do it inline.
1254  * The value depends mostly on the processor architecture,
1255  * but also on the compiler and its optimization capabilities.
1256  * The value is not critical, some small value greater than zero
1257  * will be just fine if you don't care to squeeze every drop
1258  * of performance out of the code.
1259  *
1260  * Small values favor memcpy, large values favor inline code.
1261  */
1262 #if defined(__alpha__) || defined(__alpha)
1263 #  define breakeven_point   2    /* AXP (DEC Alpha)     - gcc or cc or egcs */
1264 #endif
1265 #if defined(__i386__)  || defined(__i386)
1266 #  define breakeven_point  12    /* Intel Pentium/Linux - gcc 2.96 */
1267 #endif
1268 #if defined(__hppa)
1269 #  define breakeven_point  10    /* HP-PA               - gcc */
1270 #endif
1271 #if defined(__sparc__) || defined(__sparc)
1272 #  define breakeven_point  33    /* Sun Sparc 5         - gcc 2.8.1 */
1273 #endif
1274
1275 /* some other values of possible interest: */
1276 /* #define breakeven_point  8 */ /* VAX 4000          - vaxc */
1277 /* #define breakeven_point 19 */ /* VAX 4000          - gcc 2.7.0 */
1278
1279 #ifndef breakeven_point
1280 #  define breakeven_point   6    /* some reasonable one-size-fits-all value */
1281 #endif
1282
1283 #define fast_memcpy(d,s,n) \
1284   { register size_t nn = (size_t)(n); \
1285     if (nn >= breakeven_point) memcpy((d), (s), nn); \
1286     else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
1287       register char *dd; register const char *ss; \
1288       for (ss=(s), dd=(d); nn>0; nn--) *dd++ = *ss++; } }
1289
1290 #define fast_memset(d,c,n) \
1291   { register size_t nn = (size_t)(n); \
1292     if (nn >= breakeven_point) memset((d), (int)(c), nn); \
1293     else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
1294       register char *dd; register const int cc=(int)(c); \
1295       for (dd=(d); nn>0; nn--) *dd++ = cc; } }
1296
1297 /* prototypes */
1298
1299 #if defined(NEED_ASPRINTF)
1300 int asprintf   (char **ptr, const char *fmt, /*args*/ ...);
1301 #endif
1302 #if defined(NEED_VASPRINTF)
1303 int vasprintf  (char **ptr, const char *fmt, va_list ap);
1304 #endif
1305 #if defined(NEED_ASNPRINTF)
1306 int asnprintf  (char **ptr, size_t str_m, const char *fmt, /*args*/ ...);
1307 #endif
1308 #if defined(NEED_VASNPRINTF)
1309 int vasnprintf (char **ptr, size_t str_m, const char *fmt, va_list ap);
1310 #endif
1311
1312 #if defined(HAVE_SNPRINTF)
1313 /* declare our portable snprintf  routine under name portable_snprintf  */
1314 /* declare our portable vsnprintf routine under name portable_vsnprintf */
1315 #else
1316 /* declare our portable routines under names snprintf and vsnprintf */
1317 #define portable_snprintf snprintf
1318 #if !defined(NEED_SNPRINTF_ONLY)
1319 #define portable_vsnprintf vsnprintf
1320 #endif
1321 #endif
1322
1323 #if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
1324 int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...);
1325 #if !defined(NEED_SNPRINTF_ONLY)
1326 int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap);
1327 #endif
1328 #endif
1329
1330 /* declarations */
1331
1332 static char credits[] = "\n\
1333 @(#)snprintf.c, v2.2: Mark Martinec, <mark.martinec@ijs.si>\n\
1334 @(#)snprintf.c, v2.2: Copyright 1999, Mark Martinec. Frontier Artistic License applies.\n\
1335 @(#)snprintf.c, v2.2: http://www.ijs.si/software/snprintf/\n";
1336
1337 #if defined(NEED_ASPRINTF)
1338 int asprintf(char **ptr, const char *fmt, /*args*/ ...) {
1339   va_list ap;
1340   size_t str_m;
1341   int str_l;
1342
1343   *ptr = NULL;
1344   va_start(ap, fmt);                            /* measure the required size */
1345   str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap);
1346   va_end(ap);
1347   assert(str_l >= 0);        /* possible integer overflow if str_m > INT_MAX */
1348   *ptr = (char *) malloc(str_m = (size_t)str_l + 1);
1349   if (*ptr == NULL) { errno = ENOMEM; str_l = -1; }
1350   else {
1351     int str_l2;
1352     va_start(ap, fmt);
1353     str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap);
1354     va_end(ap);
1355     assert(str_l2 == str_l);
1356   }
1357   return str_l;
1358 }
1359 #endif
1360
1361 #if defined(NEED_VASPRINTF)
1362 int vasprintf(char **ptr, const char *fmt, va_list ap) {
1363   size_t str_m;
1364   int str_l;
1365
1366   *ptr = NULL;
1367   { va_list ap2;
1368     va_copy(ap2, ap);  /* don't consume the original ap, we'll need it again */
1369     str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap2);/*get required size*/
1370     va_end(ap2);
1371   }
1372   assert(str_l >= 0);        /* possible integer overflow if str_m > INT_MAX */
1373   *ptr = (char *) malloc(str_m = (size_t)str_l + 1);
1374   if (*ptr == NULL) { errno = ENOMEM; str_l = -1; }
1375   else {
1376     int str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap);
1377     assert(str_l2 == str_l);
1378   }
1379   return str_l;
1380 }
1381 #endif
1382
1383 #if defined(NEED_ASNPRINTF)
1384 int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...) {
1385   va_list ap;
1386   int str_l;
1387
1388   *ptr = NULL;
1389   va_start(ap, fmt);                            /* measure the required size */
1390   str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap);
1391   va_end(ap);
1392   assert(str_l >= 0);        /* possible integer overflow if str_m > INT_MAX */
1393   if ((size_t)str_l + 1 < str_m) str_m = (size_t)str_l + 1;      /* truncate */
1394   /* if str_m is 0, no buffer is allocated, just set *ptr to NULL */
1395   if (str_m == 0) {  /* not interested in resulting string, just return size */
1396   } else {
1397     *ptr = (char *) malloc(str_m);
1398     if (*ptr == NULL) { errno = ENOMEM; str_l = -1; }
1399     else {
1400       int str_l2;
1401       va_start(ap, fmt);
1402       str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap);
1403       va_end(ap);
1404       assert(str_l2 == str_l);
1405     }
1406   }
1407   return str_l;
1408 }
1409 #endif
1410
1411 #if defined(NEED_VASNPRINTF)
1412 int vasnprintf (char **ptr, size_t str_m, const char *fmt, va_list ap) {
1413   int str_l;
1414
1415   *ptr = NULL;
1416   { va_list ap2;
1417     va_copy(ap2, ap);  /* don't consume the original ap, we'll need it again */
1418     str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap2);/*get required size*/
1419     va_end(ap2);
1420   }
1421   assert(str_l >= 0);        /* possible integer overflow if str_m > INT_MAX */
1422   if ((size_t)str_l + 1 < str_m) str_m = (size_t)str_l + 1;      /* truncate */
1423   /* if str_m is 0, no buffer is allocated, just set *ptr to NULL */
1424   if (str_m == 0) {  /* not interested in resulting string, just return size */
1425   } else {
1426     *ptr = (char *) malloc(str_m);
1427     if (*ptr == NULL) { errno = ENOMEM; str_l = -1; }
1428     else {
1429       int str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap);
1430       assert(str_l2 == str_l);
1431     }
1432   }
1433   return str_l;
1434 }
1435 #endif
1436
1437 /*
1438  * If the system does have snprintf and the portable routine is not
1439  * specifically required, this module produces no code for snprintf/vsnprintf.
1440  */
1441 #if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
1442
1443 #if !defined(NEED_SNPRINTF_ONLY)
1444 int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...) {
1445   va_list ap;
1446   int str_l;
1447
1448   va_start(ap, fmt);
1449   str_l = portable_vsnprintf(str, str_m, fmt, ap);
1450   va_end(ap);
1451   return str_l;
1452 }
1453 #endif
1454
1455 #if defined(NEED_SNPRINTF_ONLY)
1456 int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...) {
1457 #else
1458 int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) {
1459 #endif
1460
1461 #if defined(NEED_SNPRINTF_ONLY)
1462   va_list ap;
1463 #endif
1464   size_t str_l = 0;
1465   const char *p = fmt;
1466
1467 /* In contrast with POSIX, the ISO C99 now says
1468  * that str can be NULL and str_m can be 0.
1469  * This is more useful than the old:  if (str_m < 1) return -1; */
1470
1471 #if defined(NEED_SNPRINTF_ONLY)
1472   va_start(ap, fmt);
1473 #endif
1474   if (!p) p = "";
1475   while (*p) {
1476     if (*p != '%') {
1477    /* if (str_l < str_m) str[str_l++] = *p++;    -- this would be sufficient */
1478    /* but the following code achieves better performance for cases
1479     * where format string is long and contains few conversions */
1480       const char *q = strchr(p+1,'%');
1481       size_t n = !q ? strlen(p) : (q-p);
1482       if (str_l < str_m) {
1483         size_t avail = str_m-str_l;
1484         fast_memcpy(str+str_l, p, (n>avail?avail:n));
1485       }
1486       p += n; str_l += n;
1487     } else {
1488       const char *starting_p;
1489       size_t min_field_width = 0, precision = 0;
1490       int zero_padding = 0, precision_specified = 0, justify_left = 0;
1491       int alternate_form = 0, force_sign = 0;
1492       int space_for_positive = 1; /* If both the ' ' and '+' flags appear,
1493                                      the ' ' flag should be ignored. */
1494       char length_modifier = '\0';            /* allowed values: \0, h, l, L */
1495       char tmp[32];/* temporary buffer for simple numeric->string conversion */
1496
1497       const char *str_arg;      /* string address in case of string argument */
1498       size_t str_arg_l;         /* natural field width of arg without padding
1499                                    and sign */
1500       unsigned char uchar_arg;
1501         /* unsigned char argument value - only defined for c conversion.
1502            N.B. standard explicitly states the char argument for
1503            the c conversion is unsigned */
1504
1505       size_t number_of_zeros_to_pad = 0;
1506         /* number of zeros to be inserted for numeric conversions
1507            as required by the precision or minimal field width */
1508
1509       size_t zero_padding_insertion_ind = 0;
1510         /* index into tmp where zero padding is to be inserted */
1511
1512       char fmt_spec = '\0';
1513         /* current conversion specifier character */
1514
1515       str_arg = credits;/* just to make compiler happy (defined but not used)*/
1516       str_arg = NULL;
1517       starting_p = p; p++;  /* skip '%' */
1518    /* parse flags */
1519       while (*p == '0' || *p == '-' || *p == '+' ||
1520              *p == ' ' || *p == '#' || *p == '\'') {
1521         switch (*p) {
1522         case '0': zero_padding = 1; break;
1523         case '-': justify_left = 1; break;
1524         case '+': force_sign = 1; space_for_positive = 0; break;
1525         case ' ': force_sign = 1;
1526      /* If both the ' ' and '+' flags appear, the ' ' flag should be ignored */
1527 #ifdef PERL_COMPATIBLE
1528      /* ... but in Perl the last of ' ' and '+' applies */
1529                   space_for_positive = 1;
1530 #endif
1531                   break;
1532         case '#': alternate_form = 1; break;
1533         case '\'': break;
1534         }
1535         p++;
1536       }
1537    /* If the '0' and '-' flags both appear, the '0' flag should be ignored. */
1538
1539    /* parse field width */
1540       if (*p == '*') {
1541         int j;
1542         p++; j = va_arg(ap, int);
1543         if (j >= 0) min_field_width = j;
1544         else { min_field_width = -j; justify_left = 1; }
1545       } else if (isdigit((int)(*p))) {
1546         /* size_t could be wider than unsigned int;
1547            make sure we treat argument like common implementations do */
1548         unsigned int uj = *p++ - '0';
1549         while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0');
1550         min_field_width = uj;
1551       }
1552    /* parse precision */
1553       if (*p == '.') {
1554         p++; precision_specified = 1;
1555         if (*p == '*') {
1556           int j = va_arg(ap, int);
1557           p++;
1558           if (j >= 0) precision = j;
1559           else {
1560             precision_specified = 0; precision = 0;
1561          /* NOTE:
1562           *   Solaris 2.6 man page claims that in this case the precision
1563           *   should be set to 0.  Digital Unix 4.0, HPUX 10 and BSD man page
1564           *   claim that this case should be treated as unspecified precision,
1565           *   which is what we do here.
1566           */
1567           }
1568         } else if (isdigit((int)(*p))) {
1569           /* size_t could be wider than unsigned int;
1570              make sure we treat argument like common implementations do */
1571           unsigned int uj = *p++ - '0';
1572           while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0');
1573           precision = uj;
1574         }
1575       }
1576    /* parse 'h', 'l' and 'll' length modifiers */
1577       if (*p == 'h' || *p == 'l') {
1578         length_modifier = *p; p++;
1579         if (length_modifier == 'l' && *p == 'l') {   /* double l = long long */
1580 #ifdef SNPRINTF_LONGLONG_SUPPORT
1581           length_modifier = '2';                  /* double l encoded as '2' */
1582 #else
1583           length_modifier = 'l';                 /* treat it as a single 'l' */
1584 #endif
1585           p++;
1586         }
1587       }
1588       fmt_spec = *p;
1589    /* common synonyms: */
1590       switch (fmt_spec) {
1591       case 'i': fmt_spec = 'd'; break;
1592       case 'D': fmt_spec = 'd'; length_modifier = 'l'; break;
1593       case 'U': fmt_spec = 'u'; length_modifier = 'l'; break;
1594       case 'O': fmt_spec = 'o'; length_modifier = 'l'; break;
1595       default: break;
1596       }
1597    /* get parameter value, do initial processing */
1598       switch (fmt_spec) {
1599       case '%': /* % behaves similar to 's' regarding flags and field widths */
1600       case 'c': /* c behaves similar to 's' regarding flags and field widths */
1601       case 's':
1602         length_modifier = '\0';          /* wint_t and wchar_t not supported */
1603      /* the result of zero padding flag with non-numeric conversion specifier*/
1604      /* is undefined. Solaris and HPUX 10 does zero padding in this case,    */
1605      /* Digital Unix and Linux does not. */
1606 #if !defined(SOLARIS_COMPATIBLE) && !defined(HPUX_COMPATIBLE)
1607         zero_padding = 0;    /* turn zero padding off for string conversions */
1608 #endif
1609         str_arg_l = 1;
1610         switch (fmt_spec) {
1611         case '%':
1612           str_arg = p; break;
1613         case 'c': {
1614           int j = va_arg(ap, int);
1615           uchar_arg = (unsigned char) j;   /* standard demands unsigned char */
1616           str_arg = (const char *) &uchar_arg;
1617           break;
1618         }
1619         case 's':
1620           str_arg = va_arg(ap, const char *);
1621           if (!str_arg) str_arg_l = 0;
1622        /* make sure not to address string beyond the specified precision !!! */
1623           else if (!precision_specified) str_arg_l = strlen(str_arg);
1624        /* truncate string if necessary as requested by precision */
1625           else if (precision == 0) str_arg_l = 0;
1626           else {
1627        /* memchr on HP does not like n > 2^31  !!! */
1628             const char *q = memchr(str_arg, '\0',
1629                              precision <= 0x7fffffff ? precision : 0x7fffffff);
1630             str_arg_l = !q ? precision : (q-str_arg);
1631           }
1632           break;
1633         default: break;
1634         }
1635         break;
1636       case 'd': case 'u': case 'o': case 'x': case 'X': case 'p': {
1637         /* NOTE: the u, o, x, X and p conversion specifiers imply
1638                  the value is unsigned;  d implies a signed value */
1639
1640         int arg_sign = 0;
1641           /* 0 if numeric argument is zero (or if pointer is NULL for 'p'),
1642             +1 if greater than zero (or nonzero for unsigned arguments),
1643             -1 if negative (unsigned argument is never negative) */
1644
1645         int int_arg = 0;  unsigned int uint_arg = 0;
1646           /* only defined for length modifier h, or for no length modifiers */
1647
1648         long int long_arg = 0;  unsigned long int ulong_arg = 0;
1649           /* only defined for length modifier l */
1650
1651         void *ptr_arg = NULL;
1652           /* pointer argument value -only defined for p conversion */
1653
1654 #ifdef SNPRINTF_LONGLONG_SUPPORT
1655         long long int long_long_arg = 0;
1656         unsigned long long int ulong_long_arg = 0;
1657           /* only defined for length modifier ll */
1658 #endif
1659         if (fmt_spec == 'p') {
1660         /* HPUX 10: An l, h, ll or L before any other conversion character
1661          *   (other than d, i, u, o, x, or X) is ignored.
1662          * Digital Unix:
1663          *   not specified, but seems to behave as HPUX does.
1664          * Solaris: If an h, l, or L appears before any other conversion
1665          *   specifier (other than d, i, u, o, x, or X), the behavior
1666          *   is undefined. (Actually %hp converts only 16-bits of address
1667          *   and %llp treats address as 64-bit data which is incompatible
1668          *   with (void *) argument on a 32-bit system).
1669          */
1670 #ifdef SOLARIS_COMPATIBLE
1671 #  ifdef SOLARIS_BUG_COMPATIBLE
1672           /* keep length modifiers even if it represents 'll' */
1673 #  else
1674           if (length_modifier == '2') length_modifier = '\0';
1675 #  endif
1676 #else
1677           length_modifier = '\0';
1678 #endif
1679           ptr_arg = va_arg(ap, void *);
1680           if (ptr_arg != NULL) arg_sign = 1;
1681         } else if (fmt_spec == 'd') {  /* signed */
1682           switch (length_modifier) {
1683           case '\0':
1684           case 'h':
1685          /* It is non-portable to specify a second argument of char or short
1686           * to va_arg, because arguments seen by the called function
1687           * are not char or short.  C converts char and short arguments
1688           * to int before passing them to a function.
1689           */
1690             int_arg = va_arg(ap, int);
1691             if      (int_arg > 0) arg_sign =  1;
1692             else if (int_arg < 0) arg_sign = -1;
1693             break;
1694           case 'l':
1695             long_arg = va_arg(ap, long int);
1696             if      (long_arg > 0) arg_sign =  1;
1697             else if (long_arg < 0) arg_sign = -1;
1698             break;
1699 #ifdef SNPRINTF_LONGLONG_SUPPORT
1700           case '2':
1701             long_long_arg = va_arg(ap, long long int);
1702             if      (long_long_arg > 0) arg_sign =  1;
1703             else if (long_long_arg < 0) arg_sign = -1;
1704             break;
1705 #endif
1706           }
1707         } else {  /* unsigned */
1708           switch (length_modifier) {
1709           case '\0':
1710           case 'h':
1711             uint_arg = va_arg(ap, unsigned int);
1712             if (uint_arg) arg_sign = 1;
1713             break;
1714           case 'l':
1715             ulong_arg = va_arg(ap, unsigned long int);
1716             if (ulong_arg) arg_sign = 1;
1717             break;
1718 #ifdef SNPRINTF_LONGLONG_SUPPORT
1719           case '2':
1720             ulong_long_arg = va_arg(ap, unsigned long long int);
1721             if (ulong_long_arg) arg_sign = 1;
1722             break;
1723 #endif
1724           }
1725         }
1726         str_arg = tmp; str_arg_l = 0;
1727      /* NOTE:
1728       *   For d, i, u, o, x, and X conversions, if precision is specified,
1729       *   the '0' flag should be ignored. This is so with Solaris 2.6,
1730       *   Digital UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl.
1731       */
1732 #ifndef PERL_COMPATIBLE
1733         if (precision_specified) zero_padding = 0;
1734 #endif
1735         if (fmt_spec == 'd') {
1736           if (force_sign && arg_sign >= 0)
1737             tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
1738          /* leave negative numbers for sprintf to handle,
1739             to avoid handling tricky cases like (short int)(-32768) */
1740 #ifdef LINUX_COMPATIBLE
1741         } else if (fmt_spec == 'p' && force_sign && arg_sign > 0) {
1742           tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
1743 #endif
1744         } else if (alternate_form) {
1745           if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X') )
1746             { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = fmt_spec; }
1747          /* alternate form should have no effect for p conversion, but ... */
1748 #ifdef HPUX_COMPATIBLE
1749           else if (fmt_spec == 'p'
1750          /* HPUX 10: for an alternate form of p conversion,
1751           *          a nonzero result is prefixed by 0x. */
1752 #ifndef HPUX_BUG_COMPATIBLE
1753          /* Actually it uses 0x prefix even for a zero value. */
1754                    && arg_sign != 0
1755 #endif
1756                   ) { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = 'x'; }
1757 #endif
1758         }
1759         zero_padding_insertion_ind = str_arg_l;
1760         if (!precision_specified) precision = 1;   /* default precision is 1 */
1761         if (precision == 0 && arg_sign == 0
1762 #if defined(HPUX_BUG_COMPATIBLE) || defined(LINUX_COMPATIBLE)
1763             && fmt_spec != 'p'
1764          /* HPUX 10 man page claims: With conversion character p the result of
1765           * converting a zero value with a precision of zero is a null string.
1766           * Actually HP returns all zeroes, and Linux returns "(nil)". */
1767 #endif
1768         ) {
1769          /* converted to null string */
1770          /* When zero value is formatted with an explicit precision 0,
1771             the resulting formatted string is empty (d, i, u, o, x, X, p).   */
1772         } else {
1773           char f[5]; int f_l = 0;
1774           f[f_l++] = '%';    /* construct a simple format string for sprintf */
1775           if (!length_modifier) { }
1776           else if (length_modifier=='2') { f[f_l++] = 'l'; f[f_l++] = 'l'; }
1777           else f[f_l++] = length_modifier;
1778           f[f_l++] = fmt_spec; f[f_l++] = '\0';
1779           if (fmt_spec == 'p') str_arg_l += sprintf(tmp+str_arg_l, f, ptr_arg);
1780           else if (fmt_spec == 'd') {  /* signed */
1781             switch (length_modifier) {
1782             case '\0':
1783             case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, int_arg);  break;
1784             case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, long_arg); break;
1785 #ifdef SNPRINTF_LONGLONG_SUPPORT
1786             case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,long_long_arg); break;
1787 #endif
1788             }
1789           } else {  /* unsigned */
1790             switch (length_modifier) {
1791             case '\0':
1792             case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, uint_arg);  break;
1793             case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, ulong_arg); break;
1794 #ifdef SNPRINTF_LONGLONG_SUPPORT
1795             case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,ulong_long_arg);break;
1796 #endif
1797             }
1798           }
1799          /* include the optional minus sign and possible "0x"
1800             in the region before the zero padding insertion point */
1801           if (zero_padding_insertion_ind < str_arg_l &&
1802               tmp[zero_padding_insertion_ind] == '-') {
1803             zero_padding_insertion_ind++;
1804           }
1805           if (zero_padding_insertion_ind+1 < str_arg_l &&
1806               tmp[zero_padding_insertion_ind]   == '0' &&
1807              (tmp[zero_padding_insertion_ind+1] == 'x' ||
1808               tmp[zero_padding_insertion_ind+1] == 'X') ) {
1809             zero_padding_insertion_ind += 2;
1810           }
1811         }
1812         { size_t num_of_digits = str_arg_l - zero_padding_insertion_ind;
1813           if (alternate_form && fmt_spec == 'o'
1814 #ifdef HPUX_COMPATIBLE                                  /* ("%#.o",0) -> ""  */
1815               && (str_arg_l > 0)
1816 #endif
1817 #ifdef DIGITAL_UNIX_BUG_COMPATIBLE                      /* ("%#o",0) -> "00" */
1818 #else
1819               /* unless zero is already the first character */
1820               && !(zero_padding_insertion_ind < str_arg_l
1821                    && tmp[zero_padding_insertion_ind] == '0')
1822 #endif
1823           ) {        /* assure leading zero for alternate-form octal numbers */
1824             if (!precision_specified || precision < num_of_digits+1) {
1825              /* precision is increased to force the first character to be zero,
1826                 except if a zero value is formatted with an explicit precision
1827                 of zero */
1828               precision = num_of_digits+1; precision_specified = 1;
1829             }
1830           }
1831        /* zero padding to specified precision? */
1832           if (num_of_digits < precision) 
1833             number_of_zeros_to_pad = precision - num_of_digits;
1834         }
1835      /* zero padding to specified minimal field width? */
1836         if (!justify_left && zero_padding) {
1837           int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
1838           if (n > 0) number_of_zeros_to_pad += n;
1839         }
1840         break;
1841       }
1842       default: /* unrecognized conversion specifier, keep format string as-is*/
1843         zero_padding = 0;  /* turn zero padding off for non-numeric convers. */
1844 #ifndef DIGITAL_UNIX_COMPATIBLE
1845         justify_left = 1; min_field_width = 0;                /* reset flags */
1846 #endif
1847 #if defined(PERL_COMPATIBLE) || defined(LINUX_COMPATIBLE)
1848      /* keep the entire format string unchanged */
1849         str_arg = starting_p; str_arg_l = p - starting_p;
1850      /* well, not exactly so for Linux, which does something inbetween,
1851       * and I don't feel an urge to imitate it: "%+++++hy" -> "%+y"  */
1852 #else
1853      /* discard the unrecognized conversion, just keep *
1854       * the unrecognized conversion character          */
1855         str_arg = p; str_arg_l = 0;
1856 #endif
1857         if (*p) str_arg_l++;  /* include invalid conversion specifier unchanged
1858                                  if not at end-of-string */
1859         break;
1860       }
1861       if (*p) p++;      /* step over the just processed conversion specifier */
1862    /* insert padding to the left as requested by min_field_width;
1863       this does not include the zero padding in case of numerical conversions*/
1864       if (!justify_left) {                /* left padding with blank or zero */
1865         int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
1866         if (n > 0) {
1867           if (str_l < str_m) {
1868             size_t avail = str_m-str_l;
1869             fast_memset(str+str_l, (zero_padding?'0':' '), (n>avail?avail:n));
1870           }
1871           str_l += n;
1872         }
1873       }
1874    /* zero padding as requested by the precision or by the minimal field width
1875     * for numeric conversions required? */
1876       if (number_of_zeros_to_pad <= 0) {
1877      /* will not copy first part of numeric right now, *
1878       * force it to be copied later in its entirety    */
1879         zero_padding_insertion_ind = 0;
1880       } else {
1881      /* insert first part of numerics (sign or '0x') before zero padding */
1882         int n = zero_padding_insertion_ind;
1883         if (n > 0) {
1884           if (str_l < str_m) {
1885             size_t avail = str_m-str_l;
1886             fast_memcpy(str+str_l, str_arg, (n>avail?avail:n));
1887           }
1888           str_l += n;
1889         }
1890      /* insert zero padding as requested by the precision or min field width */
1891         n = number_of_zeros_to_pad;
1892         if (n > 0) {
1893           if (str_l < str_m) {
1894             size_t avail = str_m-str_l;
1895             fast_memset(str+str_l, '0', (n>avail?avail:n));
1896           }
1897           str_l += n;
1898         }
1899       }
1900    /* insert formatted string
1901     * (or as-is conversion specifier for unknown conversions) */
1902       { int n = str_arg_l - zero_padding_insertion_ind;
1903         if (n > 0) {
1904           if (str_l < str_m) {
1905             size_t avail = str_m-str_l;
1906             fast_memcpy(str+str_l, str_arg+zero_padding_insertion_ind,
1907                         (n>avail?avail:n));
1908           }
1909           str_l += n;
1910         }
1911       }
1912    /* insert right padding */
1913       if (justify_left) {          /* right blank padding to the field width */
1914         int n = min_field_width - (str_arg_l+number_of_zeros_to_pad);
1915         if (n > 0) {
1916           if (str_l < str_m) {
1917             size_t avail = str_m-str_l;
1918             fast_memset(str+str_l, ' ', (n>avail?avail:n));
1919           }
1920           str_l += n;
1921         }
1922       }
1923     }
1924   }
1925 #if defined(NEED_SNPRINTF_ONLY)
1926   va_end(ap);
1927 #endif
1928   if (str_m > 0) { /* make sure the string is null-terminated
1929                       even at the expense of overwriting the last character
1930                       (shouldn't happen, but just in case) */
1931     str[str_l <= str_m-1 ? str_l : str_m-1] = '\0';
1932   }
1933   /* Return the number of characters formatted (excluding trailing null
1934    * character), that is, the number of characters that would have been
1935    * written to the buffer if it were large enough.
1936    *
1937    * The value of str_l should be returned, but str_l is of unsigned type
1938    * size_t, and snprintf is int, possibly leading to an undetected
1939    * integer overflow, resulting in a negative return value, which is illegal.
1940    * Both XSH5 and ISO C99 (at least the draft) are silent on this issue.
1941    * Should errno be set to EOVERFLOW and EOF returned in this case???
1942    */
1943   return (int) str_l;
1944 }
1945 #endif
1946 #endif /* __OS2__ */
1947 /*
1948   Local Variables:
1949   tab-width: 3
1950   end:
1951 */