common: Add functions make_absfilename and make_absfilename_try.
[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 = name;
501 #else
502       p = name;
503 #endif
504       if (*p != '/'
505 #ifdef HAVE_DRIVE_LETTERS
506           && *p != '\\'
507 #endif
508           )
509         {
510           home = gnupg_getcwd ();
511           if (!home)
512             {
513               if (xmode)
514                 {
515                   fprintf (stderr, "\nfatal: getcwd failed: %s\n",
516                            strerror (errno));
517                   exit(2);
518                 }
519               jnlib_free (name);
520               return NULL;
521             }
522           n = strlen (home) + 1 + strlen (name) + 1;
523           if (xmode)
524             home_buffer = jnlib_xmalloc (n);
525           else
526             {
527               home_buffer = jnlib_malloc (n);
528               if (!home_buffer)
529                 {
530                   jnlib_free (name);
531                   return NULL;
532                 }
533             }
534           if (p == name)
535             p = home_buffer;
536           else /* Windows case.  */
537             {
538               memcpy (home_buffer, p, p - name + 1);
539               p = home_buffer + (p - name + 1);
540             }
541           strcpy (stpcpy (stpcpy (p, home), "/"), name);
542           jnlib_free (name);
543           name = home_buffer;
544           /* Let's do a simple compression to catch the most common
545              case of using "." for gpg's --homedir option.  */
546           n = strlen (name);
547           if (n > 2 && name[n-2] == '/' && name[n-1] == '.')
548             name[n-2] = 0;
549         }
550     }
551   return change_slashes (name);
552 }
553
554 /* Construct a filename from the NULL terminated list of parts.  Tilde
555    expansion is done for the first argument.  This function terminates
556    the process on memory shortage. */
557 char *
558 make_filename (const char *first_part, ... )
559 {
560   va_list arg_ptr;
561   char *result;
562
563   va_start (arg_ptr, first_part);
564   result = do_make_filename (1, first_part, arg_ptr);
565   va_end (arg_ptr);
566   return result;
567 }
568
569 /* Construct a filename from the NULL terminated list of parts.  Tilde
570    expansion is done for the first argument.  This function may return
571    NULL on error. */
572 char *
573 make_filename_try (const char *first_part, ... )
574 {
575   va_list arg_ptr;
576   char *result;
577
578   va_start (arg_ptr, first_part);
579   result = do_make_filename (0, first_part, arg_ptr);
580   va_end (arg_ptr);
581   return result;
582 }
583
584 /* Construct an absolute filename from the NULL terminated list of
585    parts.  Tilde expansion is done for the first argument.  This
586    function terminates the process on memory shortage. */
587 char *
588 make_absfilename (const char *first_part, ... )
589 {
590   va_list arg_ptr;
591   char *result;
592
593   va_start (arg_ptr, first_part);
594   result = do_make_filename (3, first_part, arg_ptr);
595   va_end (arg_ptr);
596   return result;
597 }
598
599 /* Construct an absolute filename from the NULL terminated list of
600    parts.  Tilde expansion is done for the first argument.  This
601    function may return NULL on error. */
602 char *
603 make_absfilename_try (const char *first_part, ... )
604 {
605   va_list arg_ptr;
606   char *result;
607
608   va_start (arg_ptr, first_part);
609   result = do_make_filename (2, first_part, arg_ptr);
610   va_end (arg_ptr);
611   return result;
612 }
613
614
615 \f
616 /* Compare whether the filenames are identical.  This is a
617    special version of strcmp() taking the semantics of filenames in
618    account.  Note that this function works only on the supplied names
619    without considering any context like the current directory.  See
620    also same_file_p(). */
621 int
622 compare_filenames (const char *a, const char *b)
623 {
624 #ifdef HAVE_DOSISH_SYSTEM
625   for ( ; *a && *b; a++, b++ )
626     {
627       if (*a != *b
628           && (toupper (*(const unsigned char*)a)
629               != toupper (*(const unsigned char*)b) )
630           && !((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/')))
631         break;
632     }
633   if ((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/'))
634     return 0;
635   else
636     return (toupper (*(const unsigned char*)a)
637             - toupper (*(const unsigned char*)b));
638 #else
639     return strcmp(a,b);
640 #endif
641 }
642
643
644 /* Convert 2 hex characters at S to a byte value.  Return this value
645    or -1 if there is an error. */
646 int
647 hextobyte (const char *s)
648 {
649   int c;
650
651   if ( *s >= '0' && *s <= '9' )
652     c = 16 * (*s - '0');
653   else if ( *s >= 'A' && *s <= 'F' )
654     c = 16 * (10 + *s - 'A');
655   else if ( *s >= 'a' && *s <= 'f' )
656     c = 16 * (10 + *s - 'a');
657   else
658     return -1;
659   s++;
660   if ( *s >= '0' && *s <= '9' )
661     c += *s - '0';
662   else if ( *s >= 'A' && *s <= 'F' )
663     c += 10 + *s - 'A';
664   else if ( *s >= 'a' && *s <= 'f' )
665     c += 10 + *s - 'a';
666   else
667     return -1;
668   return c;
669 }
670
671
672 /* Print a BUFFER to stream FP while replacing all control characters
673    and the characters DELIM and DELIM2 with standard C escape
674    sequences.  Returns the number of characters printed. */
675 size_t
676 print_sanitized_buffer2 (FILE *fp, const void *buffer, size_t length,
677                          int delim, int delim2)
678 {
679   const unsigned char *p = buffer;
680   size_t count = 0;
681
682   for (; length; length--, p++, count++)
683     {
684       if (*p < 0x20
685           || *p == 0x7f
686           || *p == delim
687           || *p == delim2
688           || ((delim || delim2) && *p=='\\'))
689         {
690           putc ('\\', fp);
691           count++;
692           if (*p == '\n')
693             {
694               putc ('n', fp);
695               count++;
696             }
697           else if (*p == '\r')
698             {
699               putc ('r', fp);
700               count++;
701             }
702           else if (*p == '\f')
703             {
704               putc ('f', fp);
705               count++;
706             }
707           else if (*p == '\v')
708             {
709               putc ('v', fp);
710               count++;
711             }
712           else if (*p == '\b')
713             {
714               putc ('b', fp);
715               count++;
716             }
717           else if (!*p)
718             {
719               putc('0', fp);
720               count++;
721             }
722           else
723             {
724               fprintf (fp, "x%02x", *p);
725               count += 3;
726             }
727         }
728       else
729         {
730           putc (*p, fp);
731           count++;
732         }
733     }
734
735   return count;
736 }
737
738 /* Same as print_sanitized_buffer2 but with just one delimiter. */
739 size_t
740 print_sanitized_buffer (FILE *fp, const void *buffer, size_t length,
741                         int delim)
742 {
743   return print_sanitized_buffer2 (fp, buffer, length, delim, 0);
744 }
745
746
747 size_t
748 print_sanitized_utf8_buffer (FILE *fp, const void *buffer,
749                              size_t length, int delim)
750 {
751   const char *p = buffer;
752   size_t i;
753
754   /* We can handle plain ascii simpler, so check for it first. */
755   for (i=0; i < length; i++ )
756     {
757       if ( (p[i] & 0x80) )
758         break;
759     }
760   if (i < length)
761     {
762         char *buf = utf8_to_native (p, length, delim);
763         /*(utf8 conversion already does the control character quoting)*/
764         i = strlen (buf);
765         fputs (buf, fp);
766         jnlib_free (buf);
767         return i;
768     }
769   else
770     return print_sanitized_buffer (fp, p, length, delim);
771 }
772
773
774 size_t
775 print_sanitized_string2 (FILE *fp, const char *string, int delim, int delim2)
776 {
777   return string? print_sanitized_buffer2 (fp, string, strlen (string),
778                                           delim, delim2):0;
779 }
780
781 size_t
782 print_sanitized_string (FILE *fp, const char *string, int delim)
783 {
784   return string? print_sanitized_buffer (fp, string, strlen (string), delim):0;
785 }
786
787 size_t
788 print_sanitized_utf8_string (FILE *fp, const char *string, int delim)
789 {
790   return string? print_sanitized_utf8_buffer (fp,
791                                               string, strlen (string),
792                                               delim) : 0;
793 }
794
795 /* Create a string from the buffer P_ARG of length N which is suitable
796    for printing.  Caller must release the created string using xfree.
797    This function terminates the process on memory shortage.  */
798 char *
799 sanitize_buffer (const void *p_arg, size_t n, int delim)
800 {
801   const unsigned char *p = p_arg;
802   size_t save_n, buflen;
803   const unsigned char *save_p;
804   char *buffer, *d;
805
806   /* First count length. */
807   for (save_n = n, save_p = p, buflen=1 ; n; n--, p++ )
808     {
809       if ( *p < 0x20 || *p == 0x7f || *p == delim  || (delim && *p=='\\'))
810         {
811           if ( *p=='\n' || *p=='\r' || *p=='\f'
812                || *p=='\v' || *p=='\b' || !*p )
813             buflen += 2;
814           else
815             buflen += 5;
816         }
817       else
818         buflen++;
819     }
820   p = save_p;
821   n = save_n;
822   /* And now make the string */
823   d = buffer = jnlib_xmalloc( buflen );
824   for ( ; n; n--, p++ )
825     {
826       if (*p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\')) {
827         *d++ = '\\';
828         if( *p == '\n' )
829           *d++ = 'n';
830         else if( *p == '\r' )
831           *d++ = 'r';
832         else if( *p == '\f' )
833           *d++ = 'f';
834         else if( *p == '\v' )
835           *d++ = 'v';
836         else if( *p == '\b' )
837           *d++ = 'b';
838         else if( !*p )
839           *d++ = '0';
840         else {
841           sprintf(d, "x%02x", *p );
842           d += 3;
843         }
844       }
845       else
846         *d++ = *p;
847     }
848   *d = 0;
849   return buffer;
850 }
851
852
853 /* Given a string containing an UTF-8 encoded text, return the number
854    of characters in this string.  It differs from strlen in that it
855    only counts complete UTF-8 characters.  Note, that this function
856    does not take combined characters into account.  */
857 size_t
858 utf8_charcount (const char *s)
859 {
860   size_t n;
861
862   for (n=0; *s; s++)
863     if ( (*s&0xc0) != 0x80 ) /* Exclude continuation bytes: 10xxxxxx */
864       n++;
865
866   return n;
867 }
868
869
870 /****************************************************
871  **********  W32 specific functions  ****************
872  ****************************************************/
873
874 #ifdef HAVE_W32_SYSTEM
875 const char *
876 w32_strerror (int ec)
877 {
878   static char strerr[256];
879
880   if (ec == -1)
881     ec = (int)GetLastError ();
882 #ifdef HAVE_W32CE_SYSTEM
883   /* There is only a wchar_t FormatMessage.  It does not make much
884      sense to play the conversion game; we print only the code.  */
885   snprintf (strerr, sizeof strerr, "ec=%d", (int)GetLastError ());
886 #else
887   FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec,
888                  MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
889                  strerr, DIM (strerr)-1, NULL);
890 #endif
891   return strerr;
892 }
893 #endif /*HAVE_W32_SYSTEM*/
894
895
896 /****************************************************
897  ******** Locale insensitive ctype functions ********
898  ****************************************************/
899 /* FIXME: replace them by a table lookup and macros */
900 int
901 ascii_isupper (int c)
902 {
903     return c >= 'A' && c <= 'Z';
904 }
905
906 int
907 ascii_islower (int c)
908 {
909     return c >= 'a' && c <= 'z';
910 }
911
912 int
913 ascii_toupper (int c)
914 {
915     if (c >= 'a' && c <= 'z')
916         c &= ~0x20;
917     return c;
918 }
919
920 int
921 ascii_tolower (int c)
922 {
923     if (c >= 'A' && c <= 'Z')
924         c |= 0x20;
925     return c;
926 }
927
928
929 int
930 ascii_strcasecmp( const char *a, const char *b )
931 {
932     if (a == b)
933         return 0;
934
935     for (; *a && *b; a++, b++) {
936         if (*a != *b && ascii_toupper(*a) != ascii_toupper(*b))
937             break;
938     }
939     return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
940 }
941
942 int
943 ascii_strncasecmp (const char *a, const char *b, size_t n)
944 {
945   const unsigned char *p1 = (const unsigned char *)a;
946   const unsigned char *p2 = (const unsigned char *)b;
947   unsigned char c1, c2;
948
949   if (p1 == p2 || !n )
950     return 0;
951
952   do
953     {
954       c1 = ascii_tolower (*p1);
955       c2 = ascii_tolower (*p2);
956
957       if ( !--n || c1 == '\0')
958         break;
959
960       ++p1;
961       ++p2;
962     }
963   while (c1 == c2);
964
965   return c1 - c2;
966 }
967
968
969 int
970 ascii_memcasecmp (const void *a_arg, const void *b_arg, size_t n )
971 {
972   const char *a = a_arg;
973   const char *b = b_arg;
974
975   if (a == b)
976     return 0;
977   for ( ; n; n--, a++, b++ )
978     {
979       if( *a != *b  && ascii_toupper (*a) != ascii_toupper (*b) )
980         return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
981     }
982   return 0;
983 }
984
985 int
986 ascii_strcmp( const char *a, const char *b )
987 {
988     if (a == b)
989         return 0;
990
991     for (; *a && *b; a++, b++) {
992         if (*a != *b )
993             break;
994     }
995     return *a == *b? 0 : (*(signed char *)a - *(signed char *)b);
996 }
997
998
999 void *
1000 ascii_memcasemem (const void *haystack, size_t nhaystack,
1001                   const void *needle, size_t nneedle)
1002 {
1003
1004   if (!nneedle)
1005     return (void*)haystack; /* finding an empty needle is really easy */
1006   if (nneedle <= nhaystack)
1007     {
1008       const char *a = haystack;
1009       const char *b = a + nhaystack - nneedle;
1010
1011       for (; a <= b; a++)
1012         {
1013           if ( !ascii_memcasecmp (a, needle, nneedle) )
1014             return (void *)a;
1015         }
1016     }
1017   return NULL;
1018 }
1019
1020 /*********************************************
1021  ********** missing string functions *********
1022  *********************************************/
1023
1024 #ifndef HAVE_STPCPY
1025 char *
1026 stpcpy(char *a,const char *b)
1027 {
1028     while( *b )
1029         *a++ = *b++;
1030     *a = 0;
1031
1032     return (char*)a;
1033 }
1034 #endif
1035
1036 #ifndef HAVE_STRSEP
1037 /* Code taken from glibc-2.2.1/sysdeps/generic/strsep.c. */
1038 char *
1039 strsep (char **stringp, const char *delim)
1040 {
1041   char *begin, *end;
1042
1043   begin = *stringp;
1044   if (begin == NULL)
1045     return NULL;
1046
1047   /* A frequent case is when the delimiter string contains only one
1048      character.  Here we don't need to call the expensive 'strpbrk'
1049      function and instead work using 'strchr'.  */
1050   if (delim[0] == '\0' || delim[1] == '\0')
1051     {
1052       char ch = delim[0];
1053
1054       if (ch == '\0')
1055         end = NULL;
1056       else
1057         {
1058           if (*begin == ch)
1059             end = begin;
1060           else if (*begin == '\0')
1061             end = NULL;
1062           else
1063             end = strchr (begin + 1, ch);
1064         }
1065     }
1066   else
1067     /* Find the end of the token.  */
1068     end = strpbrk (begin, delim);
1069
1070   if (end)
1071     {
1072       /* Terminate the token and set *STRINGP past NUL character.  */
1073       *end++ = '\0';
1074       *stringp = end;
1075     }
1076   else
1077     /* No more delimiters; this is the last token.  */
1078     *stringp = NULL;
1079
1080   return begin;
1081 }
1082 #endif /*HAVE_STRSEP*/
1083
1084
1085 #ifndef HAVE_STRLWR
1086 char *
1087 strlwr(char *s)
1088 {
1089     char *p;
1090     for(p=s; *p; p++ )
1091         *p = tolower(*p);
1092     return s;
1093 }
1094 #endif
1095
1096
1097 #ifndef HAVE_STRCASECMP
1098 int
1099 strcasecmp( const char *a, const char *b )
1100 {
1101     for( ; *a && *b; a++, b++ ) {
1102         if( *a != *b && toupper(*a) != toupper(*b) )
1103             break;
1104     }
1105     return *(const byte*)a - *(const byte*)b;
1106 }
1107 #endif
1108
1109
1110 /****************
1111  * mingw32/cpd has a memicmp()
1112  */
1113 #ifndef HAVE_MEMICMP
1114 int
1115 memicmp( const char *a, const char *b, size_t n )
1116 {
1117     for( ; n; n--, a++, b++ )
1118         if( *a != *b  && toupper(*(const byte*)a) != toupper(*(const byte*)b) )
1119             return *(const byte *)a - *(const byte*)b;
1120     return 0;
1121 }
1122 #endif
1123
1124
1125 #ifndef HAVE_MEMRCHR
1126 void *
1127 memrchr (const void *buffer, int c, size_t n)
1128 {
1129   const unsigned char *p = buffer;
1130
1131   for (p += n; n ; n--)
1132     if (*--p == c)
1133       return (void *)p;
1134   return NULL;
1135 }
1136 #endif /*HAVE_MEMRCHR*/
1137
1138 \f
1139 /* Percent-escape the string STR by replacing colons with '%3a'.  If
1140    EXTRA is not NULL all characters in EXTRA are also escaped.  */
1141 static char *
1142 do_percent_escape (const char *str, const char *extra, int die)
1143 {
1144   int i, j;
1145   char *ptr;
1146
1147   if (!str)
1148     return NULL;
1149
1150   for (i=j=0; str[i]; i++)
1151     if (str[i] == ':' || str[i] == '%' || (extra && strchr (extra, str[i])))
1152       j++;
1153   if (die)
1154     ptr = jnlib_xmalloc (i + 2 * j + 1);
1155   else
1156     {
1157       ptr = jnlib_malloc (i + 2 * j + 1);
1158       if (!ptr)
1159         return NULL;
1160     }
1161   i = 0;
1162   while (*str)
1163     {
1164       if (*str == ':')
1165         {
1166           ptr[i++] = '%';
1167           ptr[i++] = '3';
1168           ptr[i++] = 'a';
1169         }
1170       else if (*str == '%')
1171         {
1172           ptr[i++] = '%';
1173           ptr[i++] = '2';
1174           ptr[i++] = '5';
1175         }
1176       else if (extra && strchr (extra, *str))
1177         {
1178           ptr[i++] = '%';
1179           ptr[i++] = tohex_lower ((*str>>4)&15);
1180           ptr[i++] = tohex_lower (*str&15);
1181         }
1182       else
1183         ptr[i++] = *str;
1184       str++;
1185     }
1186   ptr[i] = '\0';
1187
1188   return ptr;
1189 }
1190
1191 /* Percent-escape the string STR by replacing colons with '%3a'.  If
1192    EXTRA is not NULL all characters in EXTRA are also escaped.  This
1193    function terminates the process on memory shortage.  */
1194 char *
1195 percent_escape (const char *str, const char *extra)
1196 {
1197   return do_percent_escape (str, extra, 1);
1198 }
1199
1200 /* Same as percent_escape but return NULL instead of exiting on memory
1201    error. */
1202 char *
1203 try_percent_escape (const char *str, const char *extra)
1204 {
1205   return do_percent_escape (str, extra, 0);
1206 }
1207
1208
1209
1210 static char *
1211 do_strconcat (const char *s1, va_list arg_ptr)
1212 {
1213   const char *argv[48];
1214   size_t argc;
1215   size_t needed;
1216   char *buffer, *p;
1217
1218   argc = 0;
1219   argv[argc++] = s1;
1220   needed = strlen (s1);
1221   while (((argv[argc] = va_arg (arg_ptr, const char *))))
1222     {
1223       needed += strlen (argv[argc]);
1224       if (argc >= DIM (argv)-1)
1225         {
1226           jnlib_set_errno (EINVAL);
1227           return NULL;
1228         }
1229       argc++;
1230     }
1231   needed++;
1232   buffer = jnlib_malloc (needed);
1233   if (buffer)
1234     {
1235       for (p = buffer, argc=0; argv[argc]; argc++)
1236         p = stpcpy (p, argv[argc]);
1237     }
1238   return buffer;
1239 }
1240
1241
1242 /* Concatenate the string S1 with all the following strings up to a
1243    NULL.  Returns a malloced buffer with the new string or NULL on a
1244    malloc error or if too many arguments are given.  */
1245 char *
1246 strconcat (const char *s1, ...)
1247 {
1248   va_list arg_ptr;
1249   char *result;
1250
1251   if (!s1)
1252     result = jnlib_strdup ("");
1253   else
1254     {
1255       va_start (arg_ptr, s1);
1256       result = do_strconcat (s1, arg_ptr);
1257       va_end (arg_ptr);
1258     }
1259   return result;
1260 }
1261
1262 /* Same as strconcat but terminate the process with an error message
1263    if something goes wrong.  */
1264 char *
1265 xstrconcat (const char *s1, ...)
1266 {
1267   va_list arg_ptr;
1268   char *result;
1269
1270   if (!s1)
1271     result = jnlib_xstrdup ("");
1272   else
1273     {
1274       va_start (arg_ptr, s1);
1275       result = do_strconcat (s1, arg_ptr);
1276       va_end (arg_ptr);
1277     }
1278   if (!result)
1279     {
1280       if (errno == EINVAL)
1281         fputs ("\nfatal: too many args for xstrconcat\n", stderr);
1282       else
1283         fputs ("\nfatal: out of memory\n", stderr);
1284       exit (2);
1285     }
1286   return result;
1287 }