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