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