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