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