Fix for latest libgpg-error.
[gnupg.git] / common / stringhelp.c
1 /* stringhelp.c -  standard string helper functions
2  * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005,
3  *               2006, 2007, 2008, 2009  Free Software Foundation, Inc.
4  *
5  * This file is part of JNLIB.
6  *
7  * JNLIB is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 3 of
10  * the License, or (at your option) any later version.
11  *
12  * JNLIB is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdarg.h>
25 #include <ctype.h>
26 #include <errno.h>
27 #ifdef HAVE_PWD_H
28 # include <pwd.h>
29 #endif
30 #include <unistd.h>
31 #include <sys/types.h>
32 #ifdef HAVE_W32_SYSTEM
33 # include <windows.h>
34 #endif
35
36 #include "libjnlib-config.h"
37 #include "utf8conv.h"
38 #include "stringhelp.h"
39
40
41 #define tohex_lower(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'a'))
42
43 /* Sometimes we want to avoid mixing slashes and backslashes on W32
44    and prefer backslashes.  There is usual no problem with mixing
45    them, however a very few W32 API calls can't grok plain slashes.
46    Printing filenames with mixed slashes also looks a bit strange.
47    This function has no effext on POSIX. */
48 static inline char *
49 change_slashes (char *name)
50 {
51 #ifdef HAVE_DRIVE_LETTERS
52   char *p;
53
54   if (strchr (name, '\\'))
55     {
56       for (p=name; *p; p++)
57         if (*p == '/')
58           *p = '\\';
59     }
60 #endif /*HAVE_DRIVE_LETTERS*/
61   return name;
62 }
63
64
65 /*
66  * Look for the substring SUB in buffer and return a pointer to that
67  * substring in BUFFER or NULL if not found.
68  * Comparison is case-insensitive.
69  */
70 const char *
71 memistr (const void *buffer, size_t buflen, const char *sub)
72 {
73   const unsigned char *buf = buffer;
74   const unsigned char *t = (const unsigned char *)buffer;
75   const unsigned char *s = (const unsigned char *)sub;
76   size_t n = buflen;
77
78   for ( ; n ; t++, n-- )
79     {
80       if ( toupper (*t) == toupper (*s) )
81         {
82           for ( buf=t++, buflen = n--, s++;
83                 n && toupper (*t) == toupper (*s); t++, s++, n-- )
84             ;
85           if (!*s)
86             return (const char*)buf;
87           t = buf;
88           s = (const unsigned char *)sub ;
89           n = buflen;
90         }
91     }
92   return NULL;
93 }
94
95 const char *
96 ascii_memistr ( const void *buffer, size_t buflen, const char *sub )
97 {
98   const unsigned char *buf = buffer;
99   const unsigned char *t = (const unsigned char *)buf;
100   const unsigned char *s = (const unsigned char *)sub;
101   size_t n = buflen;
102
103   for ( ; n ; t++, n-- )
104     {
105       if (ascii_toupper (*t) == ascii_toupper (*s) )
106         {
107           for ( buf=t++, buflen = n--, s++;
108                 n && ascii_toupper (*t) == ascii_toupper (*s); t++, s++, n-- )
109             ;
110           if (!*s)
111             return (const char*)buf;
112           t = (const unsigned char *)buf;
113           s = (const unsigned char *)sub ;
114           n = buflen;
115         }
116     }
117   return NULL;
118 }
119
120 /* This function is similar to strncpy().  However it won't copy more
121    than N - 1 characters and makes sure that a '\0' is appended. With
122    N given as 0, nothing will happen.  With DEST given as NULL, memory
123    will be allocated using jnlib_xmalloc (i.e. if it runs out of core
124    the function terminates).  Returns DES or a pointer to the
125    allocated memory.
126  */
127 char *
128 mem2str( char *dest , const void *src , size_t n )
129 {
130     char *d;
131     const char *s;
132
133     if( n ) {
134         if( !dest )
135             dest = jnlib_xmalloc( n ) ;
136         d = dest;
137         s = src ;
138         for(n--; n && *s; n-- )
139             *d++ = *s++;
140         *d = '\0' ;
141     }
142
143     return dest ;
144 }
145
146
147 /****************
148  * remove leading and trailing white spaces
149  */
150 char *
151 trim_spaces( char *str )
152 {
153     char *string, *p, *mark;
154
155     string = str;
156     /* find first non space character */
157     for( p=string; *p && isspace( *(byte*)p ) ; p++ )
158         ;
159     /* move characters */
160     for( (mark = NULL); (*string = *p); string++, p++ )
161         if( isspace( *(byte*)p ) ) {
162             if( !mark )
163                 mark = string ;
164         }
165         else
166             mark = NULL ;
167     if( mark )
168         *mark = '\0' ;  /* remove trailing spaces */
169
170     return str ;
171 }
172
173 /****************
174  * remove trailing white spaces
175  */
176 char *
177 trim_trailing_spaces( char *string )
178 {
179     char *p, *mark;
180
181     for( mark = NULL, p = string; *p; p++ ) {
182         if( isspace( *(byte*)p ) ) {
183             if( !mark )
184                 mark = p;
185         }
186         else
187             mark = NULL;
188     }
189     if( mark )
190         *mark = '\0' ;
191
192     return string ;
193 }
194
195
196 unsigned
197 trim_trailing_chars( byte *line, unsigned len, const char *trimchars )
198 {
199     byte *p, *mark;
200     unsigned n;
201
202     for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
203         if( strchr(trimchars, *p ) ) {
204             if( !mark )
205                 mark = p;
206         }
207         else
208             mark = NULL;
209     }
210
211     if( mark ) {
212         *mark = 0;
213         return mark - line;
214     }
215     return len;
216 }
217
218 /****************
219  * remove trailing white spaces and return the length of the buffer
220  */
221 unsigned
222 trim_trailing_ws( byte *line, unsigned len )
223 {
224     return trim_trailing_chars( line, len, " \t\r\n" );
225 }
226
227 size_t
228 length_sans_trailing_chars (const unsigned char *line, size_t len,
229                             const char *trimchars )
230 {
231   const unsigned char *p, *mark;
232   size_t n;
233   
234   for( mark=NULL, p=line, n=0; n < len; n++, p++ )
235     {
236       if (strchr (trimchars, *p ))
237         {
238           if( !mark )
239             mark = p;
240         }
241       else
242         mark = NULL;
243     }
244   
245   if (mark) 
246     return mark - line;
247   return len;
248 }
249
250 /*
251  *  Return the length of line ignoring trailing white-space.
252  */
253 size_t
254 length_sans_trailing_ws (const unsigned char *line, size_t len)
255 {
256   return length_sans_trailing_chars (line, len, " \t\r\n");
257 }
258
259
260
261 /*
262  * Extract from a given path the filename component.  This function
263  * terminates the process on memory shortage.
264  */
265 char *
266 make_basename(const char *filepath, const char *inputpath)
267 {
268 #ifdef __riscos__
269     return riscos_make_basename(filepath, inputpath);
270 #else
271     char *p;
272
273     (void)inputpath; /* Only required for riscos.  */
274
275     if ( !(p=strrchr(filepath, '/')) )
276 #ifdef HAVE_DRIVE_LETTERS
277         if ( !(p=strrchr(filepath, '\\')) )
278             if ( !(p=strrchr(filepath, ':')) )
279 #endif
280               {
281                 return jnlib_xstrdup(filepath);
282               }
283
284     return jnlib_xstrdup(p+1);
285 #endif
286 }
287
288
289
290 /*
291  * Extract from a given filename the path prepended to it.  If there
292  * isn't a path prepended to the filename, a dot is returned ('.').
293  * This function terminates the process on memory shortage.
294  */
295 char *
296 make_dirname(const char *filepath)
297 {
298     char *dirname;
299     int  dirname_length;
300     char *p;
301
302     if ( !(p=strrchr(filepath, '/')) )
303 #ifdef HAVE_DRIVE_LETTERS
304         if ( !(p=strrchr(filepath, '\\')) )
305             if ( !(p=strrchr(filepath, ':')) )
306 #endif
307               {
308                 return jnlib_xstrdup(".");
309               }
310
311     dirname_length = p-filepath;
312     dirname = jnlib_xmalloc(dirname_length+1);
313     strncpy(dirname, filepath, dirname_length);
314     dirname[dirname_length] = 0;
315
316     return dirname;
317 }
318
319
320 \f
321 static char *
322 get_pwdir (int xmode, const char *name)
323 {
324   char *result = NULL;
325 #ifdef HAVE_PWD_H
326   struct passwd *pwd = NULL;
327
328   if (name)
329     {
330 #ifdef HAVE_GETPWNAM
331       /* Fixme: We should use getpwnam_r if available.  */
332       pwd = getpwnam (name);
333 #endif
334     }
335   else
336     {
337 #ifdef HAVE_GETPWUID
338       /* Fixme: We should use getpwuid_r if available.  */
339       pwd = getpwuid (getuid());
340 #endif
341     }
342   if (pwd)
343     {
344       if (xmode)
345         result = jnlib_xstrdup (pwd->pw_dir);
346       else
347         result = jnlib_strdup (pwd->pw_dir);
348     }
349 #else /*!HAVE_PWD_H*/
350   /* No support at all.  */
351   (void)xmode;
352   (void)name;
353 #endif /*HAVE_PWD_H*/
354   return result;
355 }
356
357 static char *
358 do_make_filename (int xmode, const char *first_part, va_list arg_ptr)
359 {
360   const char *argv[32];
361   int argc;
362   size_t n; 
363   int skip = 1;
364   char *home_buffer = NULL;
365   char *name, *home, *p;                           
366        
367   n = strlen (first_part) + 1;                     
368   argc = 0;
369   while ( (argv[argc] = va_arg (arg_ptr, const char *)) )   
370     {
371       n += strlen (argv[argc]) + 1;                        
372       if (argc >= DIM (argv)-1)
373         {
374           if (xmode)
375             BUG ();
376           jnlib_set_errno (EINVAL);
377           return NULL;
378         }
379       argc++; 
380     }
381   n++;
382   
383   home = NULL;                                     
384   if (*first_part == '~')
385     {
386       if (first_part[1] == '/' || !first_part[1])
387         {
388           /* This is the "~/" or "~" case.  */
389           home = getenv("HOME");
390           if (!home)
391             home = home_buffer = get_pwdir (xmode, NULL);
392           if (home && *home)
393             n += strlen (home);                            
394         }
395       else
396         {
397           /* This is the "~username/" or "~username" case.  */
398           char *user;
399     
400           if (xmode)
401             user = jnlib_xstrdup (first_part+1);
402           else
403             {
404               user = jnlib_strdup (first_part+1);
405               if (!user)
406                 return NULL;
407             }
408           p = strchr (user, '/');
409           if (p)
410             *p = 0;
411           skip = 1 + strlen (user);
412           
413           home = home_buffer = get_pwdir (xmode, user);
414           jnlib_free (user);
415           if (home)
416             n += strlen (home);
417           else
418             skip = 1;
419         }
420     }
421
422   if (xmode)
423     name = jnlib_xmalloc (n);
424   else
425     {
426       name = jnlib_malloc (n);
427       if (!name)
428         {
429           jnlib_free (home_buffer);
430           return NULL;
431         }
432     }
433   
434   if (home)
435     p = stpcpy (stpcpy (name, home), first_part + skip);
436   else
437     p = stpcpy (name, first_part);
438
439   jnlib_free (home_buffer);
440
441   for (argc=0; argv[argc]; argc++)
442     p = stpcpy (stpcpy (p, "/"), argv[argc]);
443
444   return change_slashes (name);
445 }
446
447 /* Construct a filename from the NULL terminated list of parts.  Tilde
448    expansion is done for the first argument.  This function terminates
449    the process on memory shortage. */
450 char *
451 make_filename (const char *first_part, ... )
452 {
453   va_list arg_ptr;
454   char *result;
455
456   va_start (arg_ptr, first_part);
457   result = do_make_filename (1, first_part, arg_ptr);
458   va_end (arg_ptr);
459   return result;
460 }
461
462 /* Construct a filename from the NULL terminated list of parts.  Tilde
463    expansion is done for the first argument.  This function may return
464    NULL on error. */
465 char *
466 make_filename_try (const char *first_part, ... )
467 {
468   va_list arg_ptr;
469   char *result;
470
471   va_start (arg_ptr, first_part);
472   result = do_make_filename (0, first_part, arg_ptr);
473   va_end (arg_ptr);
474   return result;
475 }
476
477
478 \f
479 /* Compare whether the filenames are identical.  This is a
480    special version of strcmp() taking the semantics of filenames in
481    account.  Note that this function works only on the supplied names
482    without considereing any context like the current directory.  See
483    also same_file_p(). */
484 int
485 compare_filenames (const char *a, const char *b)
486 {
487 #ifdef HAVE_DRIVE_LETTERS
488   for ( ; *a && *b; a++, b++ ) 
489     {
490       if (*a != *b 
491           && (toupper (*(const unsigned char*)a)
492               != toupper (*(const unsigned char*)b) )
493           && !((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/')))
494         break;
495     }
496   if ((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/'))
497     return 0;
498   else
499     return (toupper (*(const unsigned char*)a) 
500             - toupper (*(const unsigned char*)b));
501 #else
502     return strcmp(a,b);
503 #endif
504 }
505
506
507 /* Convert 2 hex characters at S to a byte value.  Return this value
508    or -1 if there is an error. */
509 int
510 hextobyte (const char *s)
511 {
512   int c;
513
514   if ( *s >= '0' && *s <= '9' )
515     c = 16 * (*s - '0');
516   else if ( *s >= 'A' && *s <= 'F' )
517     c = 16 * (10 + *s - 'A');
518   else if ( *s >= 'a' && *s <= 'f' )
519     c = 16 * (10 + *s - 'a');
520   else
521     return -1;
522   s++;
523   if ( *s >= '0' && *s <= '9' )
524     c += *s - '0';
525   else if ( *s >= 'A' && *s <= 'F' )
526     c += 10 + *s - 'A';
527   else if ( *s >= 'a' && *s <= 'f' )
528     c += 10 + *s - 'a';
529   else
530     return -1;
531   return c;
532 }
533
534
535 /* Print a BUFFER to stream FP while replacing all control characters
536    and the characters DELIM and DELIM2 with standard C escape
537    sequences.  Returns the number of characters printed. */
538 size_t 
539 print_sanitized_buffer2 (FILE *fp, const void *buffer, size_t length,
540                          int delim, int delim2)
541 {
542   const unsigned char *p = buffer;
543   size_t count = 0;
544
545   for (; length; length--, p++, count++)
546     {
547       if (*p < 0x20 
548           || *p == 0x7f
549           || *p == delim 
550           || *p == delim2
551           || ((delim || delim2) && *p=='\\'))
552         {
553           putc ('\\', fp);
554           count++;
555           if (*p == '\n')
556             {
557               putc ('n', fp);
558               count++;
559             }
560           else if (*p == '\r')
561             {
562               putc ('r', fp);
563               count++;
564             }
565           else if (*p == '\f')
566             {
567               putc ('f', fp);
568               count++;
569             }
570           else if (*p == '\v')
571             {
572               putc ('v', fp);
573               count++;
574             }
575           else if (*p == '\b')
576             {
577               putc ('b', fp);
578               count++;
579             }
580           else if (!*p)
581             {
582               putc('0', fp);
583               count++;
584             }
585           else
586             {
587               fprintf (fp, "x%02x", *p);
588               count += 3;
589             }
590         }
591       else
592         {
593           putc (*p, fp);
594           count++;
595         }
596     }
597
598   return count;
599 }
600
601 /* Same as print_sanitized_buffer2 but with just one delimiter. */
602 size_t 
603 print_sanitized_buffer (FILE *fp, const void *buffer, size_t length,
604                         int delim)
605 {
606   return print_sanitized_buffer2 (fp, buffer, length, delim, 0);
607 }
608
609
610 size_t 
611 print_sanitized_utf8_buffer (FILE *fp, const void *buffer,
612                              size_t length, int delim)
613 {
614   const char *p = buffer;
615   size_t i;
616
617   /* We can handle plain ascii simpler, so check for it first. */
618   for (i=0; i < length; i++ ) 
619     {
620       if ( (p[i] & 0x80) )
621         break;
622     }
623   if (i < length)
624     {
625         char *buf = utf8_to_native (p, length, delim);
626         /*(utf8 conversion already does the control character quoting)*/
627         i = strlen (buf);
628         fputs (buf, fp);
629         jnlib_free (buf);
630         return i;
631     }
632   else
633     return print_sanitized_buffer (fp, p, length, delim);
634 }
635
636
637 size_t 
638 print_sanitized_string2 (FILE *fp, const char *string, int delim, int delim2)
639 {
640   return string? print_sanitized_buffer2 (fp, string, strlen (string),
641                                           delim, delim2):0;
642 }
643
644 size_t 
645 print_sanitized_string (FILE *fp, const char *string, int delim)
646 {
647   return string? print_sanitized_buffer (fp, string, strlen (string), delim):0;
648 }
649
650 size_t 
651 print_sanitized_utf8_string (FILE *fp, const char *string, int delim)
652 {
653   return string? print_sanitized_utf8_buffer (fp,
654                                               string, strlen (string),
655                                               delim) : 0;
656 }
657
658 /* Create a string from the buffer P_ARG of length N which is suitable
659    for printing.  Caller must release the created string using xfree.
660    This function terminates the process on memory shortage.  */
661 char *
662 sanitize_buffer (const void *p_arg, size_t n, int delim)
663 {
664   const unsigned char *p = p_arg;
665   size_t save_n, buflen;
666   const unsigned char *save_p;
667   char *buffer, *d;
668
669   /* First count length. */
670   for (save_n = n, save_p = p, buflen=1 ; n; n--, p++ ) 
671     {
672       if ( *p < 0x20 || *p == 0x7f || *p == delim  || (delim && *p=='\\'))
673         {
674           if ( *p=='\n' || *p=='\r' || *p=='\f'
675                || *p=='\v' || *p=='\b' || !*p )
676             buflen += 2;
677           else
678             buflen += 5;
679         }
680       else
681         buflen++;
682     }
683   p = save_p;
684   n = save_n;
685   /* And now make the string */
686   d = buffer = jnlib_xmalloc( buflen );
687   for ( ; n; n--, p++ )
688     {
689       if (*p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\')) {
690         *d++ = '\\';
691         if( *p == '\n' )
692           *d++ = 'n';
693         else if( *p == '\r' )
694           *d++ = 'r';
695         else if( *p == '\f' )
696           *d++ = 'f';
697         else if( *p == '\v' )
698           *d++ = 'v';
699         else if( *p == '\b' )
700           *d++ = 'b';
701         else if( !*p )
702           *d++ = '0';
703         else {
704           sprintf(d, "x%02x", *p );
705           d += 3;
706         }
707       }
708       else
709         *d++ = *p;
710     }
711   *d = 0;
712   return buffer;
713 }
714
715
716 /* Given a string containing an UTF-8 encoded text, return the number
717    of characters in this string.  It differs from strlen in that it
718    only counts complete UTF-8 characters.  Note, that this function
719    does not take combined characters into account.  */
720 size_t
721 utf8_charcount (const char *s)
722 {
723   size_t n;
724
725   for (n=0; *s; s++)
726     if ( (*s&0xc0) != 0x80 ) /* Exclude continuation bytes: 10xxxxxx */
727       n++;
728
729   return n;
730 }
731
732
733 /****************************************************
734  **********  W32 specific functions  ****************
735  ****************************************************/
736
737 #ifdef HAVE_W32_SYSTEM
738 const char *
739 w32_strerror (int ec)
740 {
741   static char strerr[256];
742   
743   if (ec == -1)
744     ec = (int)GetLastError ();
745 #ifdef HAVE_W32CE_SYSTEM
746   /* There is only a wchar_t FormatMessage.  It does not make much
747      sense to play the conversion game; we print only the code.  */
748   snprintf (strerr, sizeof strerr, "ec=%d", (int)GetLastError ());
749 #else
750   FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec,
751                  MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
752                  strerr, DIM (strerr)-1, NULL);
753 #endif
754   return strerr;    
755 }
756 #endif /*HAVE_W32_SYSTEM*/
757
758
759 /****************************************************
760  ******** Locale insensitive ctype functions ********
761  ****************************************************/
762 /* FIXME: replace them by a table lookup and macros */
763 int
764 ascii_isupper (int c)
765 {
766     return c >= 'A' && c <= 'Z';
767 }
768
769 int
770 ascii_islower (int c)
771 {
772     return c >= 'a' && c <= 'z';
773 }
774
775 int 
776 ascii_toupper (int c)
777 {
778     if (c >= 'a' && c <= 'z')
779         c &= ~0x20;
780     return c;
781 }
782
783 int 
784 ascii_tolower (int c)
785 {
786     if (c >= 'A' && c <= 'Z')
787         c |= 0x20;
788     return c;
789 }
790
791
792 int
793 ascii_strcasecmp( const char *a, const char *b )
794 {
795     if (a == b)
796         return 0;
797
798     for (; *a && *b; a++, b++) {
799         if (*a != *b && ascii_toupper(*a) != ascii_toupper(*b))
800             break;
801     }
802     return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
803 }
804
805 int 
806 ascii_strncasecmp (const char *a, const char *b, size_t n)
807 {
808   const unsigned char *p1 = (const unsigned char *)a;
809   const unsigned char *p2 = (const unsigned char *)b;
810   unsigned char c1, c2;
811
812   if (p1 == p2 || !n )
813     return 0;
814
815   do
816     {
817       c1 = ascii_tolower (*p1);
818       c2 = ascii_tolower (*p2);
819
820       if ( !--n || c1 == '\0')
821         break;
822
823       ++p1;
824       ++p2;
825     }
826   while (c1 == c2);
827   
828   return c1 - c2;
829 }
830
831
832 int
833 ascii_memcasecmp (const void *a_arg, const void *b_arg, size_t n )
834 {
835   const char *a = a_arg;
836   const char *b = b_arg;
837
838   if (a == b)
839     return 0;
840   for ( ; n; n--, a++, b++ )
841     {
842       if( *a != *b  && ascii_toupper (*a) != ascii_toupper (*b) )
843         return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
844     }
845   return 0;
846 }
847
848 int
849 ascii_strcmp( const char *a, const char *b )
850 {
851     if (a == b)
852         return 0;
853
854     for (; *a && *b; a++, b++) {
855         if (*a != *b )
856             break;
857     }
858     return *a == *b? 0 : (*(signed char *)a - *(signed char *)b);
859 }
860
861
862 void *
863 ascii_memcasemem (const void *haystack, size_t nhaystack,
864                   const void *needle, size_t nneedle)
865 {
866
867   if (!nneedle)
868     return (void*)haystack; /* finding an empty needle is really easy */
869   if (nneedle <= nhaystack)
870     {
871       const char *a = haystack;
872       const char *b = a + nhaystack - nneedle;
873       
874       for (; a <= b; a++)
875         {
876           if ( !ascii_memcasecmp (a, needle, nneedle) )
877             return (void *)a;
878         }
879     }
880   return NULL;
881 }
882
883 /*********************************************
884  ********** missing string functions *********
885  *********************************************/
886
887 #ifndef HAVE_STPCPY
888 char *
889 stpcpy(char *a,const char *b)
890 {
891     while( *b )
892         *a++ = *b++;
893     *a = 0;
894
895     return (char*)a;
896 }
897 #endif
898
899 #ifndef HAVE_STRSEP
900 /* Code taken from glibc-2.2.1/sysdeps/generic/strsep.c. */
901 char *
902 strsep (char **stringp, const char *delim)
903 {
904   char *begin, *end;
905
906   begin = *stringp;
907   if (begin == NULL)
908     return NULL;
909
910   /* A frequent case is when the delimiter string contains only one
911      character.  Here we don't need to call the expensive `strpbrk'
912      function and instead work using `strchr'.  */
913   if (delim[0] == '\0' || delim[1] == '\0')
914     {
915       char ch = delim[0];
916
917       if (ch == '\0')
918         end = NULL;
919       else
920         {
921           if (*begin == ch)
922             end = begin;
923           else if (*begin == '\0')
924             end = NULL;
925           else
926             end = strchr (begin + 1, ch);
927         }
928     }
929   else
930     /* Find the end of the token.  */
931     end = strpbrk (begin, delim);
932
933   if (end)
934     {
935       /* Terminate the token and set *STRINGP past NUL character.  */
936       *end++ = '\0';
937       *stringp = end;
938     }
939   else
940     /* No more delimiters; this is the last token.  */
941     *stringp = NULL;
942
943   return begin;
944 }
945 #endif /*HAVE_STRSEP*/
946
947
948 #ifndef HAVE_STRLWR
949 char *
950 strlwr(char *s)
951 {
952     char *p;
953     for(p=s; *p; p++ )
954         *p = tolower(*p);
955     return s;
956 }
957 #endif
958
959
960 #ifndef HAVE_STRCASECMP
961 int
962 strcasecmp( const char *a, const char *b )
963 {
964     for( ; *a && *b; a++, b++ ) {
965         if( *a != *b && toupper(*a) != toupper(*b) )
966             break;
967     }
968     return *(const byte*)a - *(const byte*)b;
969 }
970 #endif
971
972
973 /****************
974  * mingw32/cpd has a memicmp()
975  */
976 #ifndef HAVE_MEMICMP
977 int
978 memicmp( const char *a, const char *b, size_t n )
979 {
980     for( ; n; n--, a++, b++ )
981         if( *a != *b  && toupper(*(const byte*)a) != toupper(*(const byte*)b) )
982             return *(const byte *)a - *(const byte*)b;
983     return 0;
984 }
985 #endif
986
987
988 #ifndef HAVE_MEMRCHR
989 void *
990 memrchr (const void *buffer, int c, size_t n)
991 {
992   const unsigned char *p = buffer;
993
994   for (p += n; n ; n--)
995     if (*--p == c)
996       return (void *)p;
997   return NULL;
998 }
999 #endif /*HAVE_MEMRCHR*/
1000
1001 \f
1002 /* Percent-escape the string STR by replacing colons with '%3a'.  If
1003    EXTRA is not NULL all characters in EXTRA are also escaped.  */
1004 static char *
1005 do_percent_escape (const char *str, const char *extra, int die)
1006 {
1007   int i, j;
1008   char *ptr;
1009
1010   if (!str)
1011     return NULL;
1012
1013   for (i=j=0; str[i]; i++)
1014     if (str[i] == ':' || str[i] == '%' || (extra && strchr (extra, str[i])))
1015       j++;
1016   if (die)
1017     ptr = jnlib_xmalloc (i + 2 * j + 1);
1018   else
1019     {
1020       ptr = jnlib_malloc (i + 2 * j + 1);
1021       if (!ptr)
1022         return NULL;
1023     }
1024   i = 0;
1025   while (*str)
1026     {
1027       if (*str == ':')
1028         {
1029           ptr[i++] = '%';
1030           ptr[i++] = '3';
1031           ptr[i++] = 'a';
1032         }
1033       else if (*str == '%')
1034         {
1035           ptr[i++] = '%';
1036           ptr[i++] = '2';
1037           ptr[i++] = '5';
1038         }
1039       else if (extra && strchr (extra, *str))
1040         {
1041           ptr[i++] = '%';
1042           ptr[i++] = tohex_lower ((*str>>4)&15);
1043           ptr[i++] = tohex_lower (*str&15);
1044         }
1045       else
1046         ptr[i++] = *str;
1047       str++;
1048     }
1049   ptr[i] = '\0';
1050
1051   return ptr;
1052 }
1053
1054 /* Percent-escape the string STR by replacing colons with '%3a'.  If
1055    EXTRA is not NULL all characters in EXTRA are also escaped.  This
1056    function terminates the process on memory shortage.  */
1057 char *
1058 percent_escape (const char *str, const char *extra)
1059 {
1060   return do_percent_escape (str, extra, 1);
1061 }
1062
1063 /* Same as percent_escape but return NULL instead of exiting on memory
1064    error. */
1065 char *
1066 try_percent_escape (const char *str, const char *extra)
1067 {
1068   return do_percent_escape (str, extra, 0);
1069 }
1070
1071
1072
1073 static char *
1074 do_strconcat (const char *s1, va_list arg_ptr)
1075 {
1076   const char *argv[48];
1077   size_t argc;
1078   size_t needed;
1079   char *buffer, *p;
1080
1081   argc = 0;
1082   argv[argc++] = s1;
1083   needed = strlen (s1);
1084   while (((argv[argc] = va_arg (arg_ptr, const char *))))
1085     {
1086       needed += strlen (argv[argc]);
1087       if (argc >= DIM (argv)-1)
1088         {
1089           jnlib_set_errno (EINVAL);
1090           return NULL;
1091         }
1092       argc++;
1093     }
1094   needed++;
1095   buffer = jnlib_malloc (needed);
1096   if (buffer)
1097     {
1098       for (p = buffer, argc=0; argv[argc]; argc++)
1099         p = stpcpy (p, argv[argc]);
1100     }
1101   return buffer;
1102 }
1103
1104
1105 /* Concatenate the string S1 with all the following strings up to a
1106    NULL.  Returns a malloced buffer with the new string or NULL on a
1107    malloc error or if too many arguments are given.  */
1108 char *
1109 strconcat (const char *s1, ...)
1110 {
1111   va_list arg_ptr;
1112   char *result;
1113
1114   if (!s1)
1115     result = jnlib_strdup ("");
1116   else
1117     {
1118       va_start (arg_ptr, s1);
1119       result = do_strconcat (s1, arg_ptr);
1120       va_end (arg_ptr);
1121     }
1122   return result;
1123 }
1124
1125 /* Same as strconcat but terminate the process with an error message
1126    if something goes wrong.  */
1127 char *
1128 xstrconcat (const char *s1, ...)
1129 {
1130   va_list arg_ptr;
1131   char *result;
1132
1133   if (!s1)
1134     result = jnlib_xstrdup ("");
1135   else
1136     {
1137       va_start (arg_ptr, s1);
1138       result = do_strconcat (s1, arg_ptr);
1139       va_end (arg_ptr);
1140     }
1141   if (!result)
1142     {
1143       if (errno == EINVAL)
1144         fputs ("\nfatal: too many args for xstrconcat\n", stderr);
1145       else
1146         fputs ("\nfatal: out of memory\n", stderr);
1147       exit (2);
1148     }
1149   return result;
1150 }
1151