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