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