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