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