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