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