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