agent/
[gnupg.git] / jnlib / stringhelp.c
blob3173ebc154a3f3211b1845fe2b8658cc5b7b8852
1 /* stringhelp.c - standard string helper functions
2 * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005,
3 * 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
5 * This file is part of JNLIB.
7 * JNLIB is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 3 of
10 * the License, or (at your option) any later version.
12 * JNLIB is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <config.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdarg.h>
25 #include <ctype.h>
26 #include <errno.h>
27 #ifdef HAVE_PWD_H
28 # include <pwd.h>
29 #endif
30 #include <unistd.h>
31 #include <sys/types.h>
32 #ifdef HAVE_W32_SYSTEM
33 # include <windows.h>
34 #endif
36 #include "libjnlib-config.h"
37 #include "utf8conv.h"
38 #include "stringhelp.h"
41 #define tohex_lower(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'a'))
43 /* Sometimes we want to avoid mixing slashes and backslashes on W32
44 and prefer backslashes. There is usual no problem with mixing
45 them, however a very few W32 API calls can't grok plain slashes.
46 Printing filenames with mixed slashes also looks a bit strange.
47 This function has no effext on POSIX. */
48 static inline char *
49 change_slashes (char *name)
51 #ifdef HAVE_DRIVE_LETTERS
52 char *p;
54 if (strchr (name, '\\'))
56 for (p=name; *p; p++)
57 if (*p == '/')
58 *p = '\\';
60 #endif /*HAVE_DRIVE_LETTERS*/
61 return name;
66 * Look for the substring SUB in buffer and return a pointer to that
67 * substring in BUFFER or NULL if not found.
68 * Comparison is case-insensitive.
70 const char *
71 memistr (const void *buffer, size_t buflen, const char *sub)
73 const unsigned char *buf = buffer;
74 const unsigned char *t = (const unsigned char *)buffer;
75 const unsigned char *s = (const unsigned char *)sub;
76 size_t n = buflen;
78 for ( ; n ; t++, n-- )
80 if ( toupper (*t) == toupper (*s) )
82 for ( buf=t++, buflen = n--, s++;
83 n && toupper (*t) == toupper (*s); t++, s++, n-- )
85 if (!*s)
86 return (const char*)buf;
87 t = buf;
88 s = (const unsigned char *)sub ;
89 n = buflen;
92 return NULL;
95 const char *
96 ascii_memistr ( const void *buffer, size_t buflen, const char *sub )
98 const unsigned char *buf = buffer;
99 const unsigned char *t = (const unsigned char *)buf;
100 const unsigned char *s = (const unsigned char *)sub;
101 size_t n = buflen;
103 for ( ; n ; t++, n-- )
105 if (ascii_toupper (*t) == ascii_toupper (*s) )
107 for ( buf=t++, buflen = n--, s++;
108 n && ascii_toupper (*t) == ascii_toupper (*s); t++, s++, n-- )
110 if (!*s)
111 return (const char*)buf;
112 t = (const unsigned char *)buf;
113 s = (const unsigned char *)sub ;
114 n = buflen;
117 return NULL;
120 /* This function is similar to strncpy(). However it won't copy more
121 than N - 1 characters and makes sure that a '\0' is appended. With
122 N given as 0, nothing will happen. With DEST given as NULL, memory
123 will be allocated using jnlib_xmalloc (i.e. if it runs out of core
124 the function terminates). Returns DES or a pointer to the
125 allocated memory.
127 char *
128 mem2str( char *dest , const void *src , size_t n )
130 char *d;
131 const char *s;
133 if( n ) {
134 if( !dest )
135 dest = jnlib_xmalloc( n ) ;
136 d = dest;
137 s = src ;
138 for(n--; n && *s; n-- )
139 *d++ = *s++;
140 *d = '\0' ;
143 return dest ;
147 /****************
148 * remove leading and trailing white spaces
150 char *
151 trim_spaces( char *str )
153 char *string, *p, *mark;
155 string = str;
156 /* find first non space character */
157 for( p=string; *p && isspace( *(byte*)p ) ; p++ )
159 /* move characters */
160 for( (mark = NULL); (*string = *p); string++, p++ )
161 if( isspace( *(byte*)p ) ) {
162 if( !mark )
163 mark = string ;
165 else
166 mark = NULL ;
167 if( mark )
168 *mark = '\0' ; /* remove trailing spaces */
170 return str ;
173 /****************
174 * remove trailing white spaces
176 char *
177 trim_trailing_spaces( char *string )
179 char *p, *mark;
181 for( mark = NULL, p = string; *p; p++ ) {
182 if( isspace( *(byte*)p ) ) {
183 if( !mark )
184 mark = p;
186 else
187 mark = NULL;
189 if( mark )
190 *mark = '\0' ;
192 return string ;
196 unsigned
197 trim_trailing_chars( byte *line, unsigned len, const char *trimchars )
199 byte *p, *mark;
200 unsigned n;
202 for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
203 if( strchr(trimchars, *p ) ) {
204 if( !mark )
205 mark = p;
207 else
208 mark = NULL;
211 if( mark ) {
212 *mark = 0;
213 return mark - line;
215 return len;
218 /****************
219 * remove trailing white spaces and return the length of the buffer
221 unsigned
222 trim_trailing_ws( byte *line, unsigned len )
224 return trim_trailing_chars( line, len, " \t\r\n" );
227 size_t
228 length_sans_trailing_chars (const unsigned char *line, size_t len,
229 const char *trimchars )
231 const unsigned char *p, *mark;
232 size_t n;
234 for( mark=NULL, p=line, n=0; n < len; n++, p++ )
236 if (strchr (trimchars, *p ))
238 if( !mark )
239 mark = p;
241 else
242 mark = NULL;
245 if (mark)
246 return mark - line;
247 return len;
251 * Return the length of line ignoring trailing white-space.
253 size_t
254 length_sans_trailing_ws (const unsigned char *line, size_t len)
256 return length_sans_trailing_chars (line, len, " \t\r\n");
262 * Extract from a given path the filename component. This function
263 * terminates the process on memory shortage.
265 char *
266 make_basename(const char *filepath, const char *inputpath)
268 #ifdef __riscos__
269 return riscos_make_basename(filepath, inputpath);
270 #else
271 char *p;
273 (void)inputpath; /* Only required for riscos. */
275 if ( !(p=strrchr(filepath, '/')) )
276 #ifdef HAVE_DRIVE_LETTERS
277 if ( !(p=strrchr(filepath, '\\')) )
278 if ( !(p=strrchr(filepath, ':')) )
279 #endif
281 return jnlib_xstrdup(filepath);
284 return jnlib_xstrdup(p+1);
285 #endif
291 * Extract from a given filename the path prepended to it. If there
292 * isn't a path prepended to the filename, a dot is returned ('.').
293 * This function terminates the process on memory shortage.
295 char *
296 make_dirname(const char *filepath)
298 char *dirname;
299 int dirname_length;
300 char *p;
302 if ( !(p=strrchr(filepath, '/')) )
303 #ifdef HAVE_DRIVE_LETTERS
304 if ( !(p=strrchr(filepath, '\\')) )
305 if ( !(p=strrchr(filepath, ':')) )
306 #endif
308 return jnlib_xstrdup(".");
311 dirname_length = p-filepath;
312 dirname = jnlib_xmalloc(dirname_length+1);
313 strncpy(dirname, filepath, dirname_length);
314 dirname[dirname_length] = 0;
316 return dirname;
321 static char *
322 get_pwdir (int xmode, const char *name)
324 char *result = NULL;
325 #ifdef HAVE_PWD_H
326 struct passwd *pwd = NULL;
328 if (name)
330 #ifdef HAVE_GETPWNAM
331 /* Fixme: We should use getpwnam_r if available. */
332 pwd = getpwnam (name);
333 #endif
335 else
337 #ifdef HAVE_GETPWUID
338 /* Fixme: We should use getpwuid_r if available. */
339 pwd = getpwuid (getuid());
340 #endif
342 if (pwd)
344 if (xmode)
345 result = jnlib_xstrdup (pwd->pw_dir);
346 else
347 result = jnlib_strdup (pwd->pw_dir);
349 #endif /*HAVE_PWD_H*/
350 return result;
353 static char *
354 do_make_filename (int xmode, const char *first_part, va_list arg_ptr)
356 const char *argv[32];
357 int argc;
358 size_t n;
359 int skip = 1;
360 char *home_buffer = NULL;
361 char *name, *home, *p;
363 n = strlen (first_part) + 1;
364 argc = 0;
365 while ( (argv[argc] = va_arg (arg_ptr, const char *)) )
367 n += strlen (argv[argc]) + 1;
368 if (argc >= DIM (argv)-1)
370 if (xmode)
371 BUG ();
372 errno = EINVAL;
373 return NULL;
375 argc++;
377 n++;
379 home = NULL;
380 if (*first_part == '~')
382 if (first_part[1] == '/' || !first_part[1])
384 /* This is the "~/" or "~" case. */
385 home = getenv("HOME");
386 if (!home)
387 home = home_buffer = get_pwdir (xmode, NULL);
388 if (home && *home)
389 n += strlen (home);
391 else
393 /* This is the "~username/" or "~username" case. */
394 char *user;
396 if (xmode)
397 user = jnlib_xstrdup (first_part+1);
398 else
400 user = jnlib_strdup (first_part+1);
401 if (!user)
402 return NULL;
404 p = strchr (user, '/');
405 if (p)
406 *p = 0;
407 skip = 1 + strlen (user);
409 home = home_buffer = get_pwdir (xmode, user);
410 jnlib_free (user);
411 if (home)
412 n += strlen (home);
413 else
414 skip = 1;
418 if (xmode)
419 name = jnlib_xmalloc (n);
420 else
422 name = jnlib_malloc (n);
423 if (!name)
425 jnlib_free (home_buffer);
426 return NULL;
430 if (home)
431 p = stpcpy (stpcpy (name, home), first_part + skip);
432 else
433 p = stpcpy (name, first_part);
435 jnlib_free (home_buffer);
437 for (argc=0; argv[argc]; argc++)
438 p = stpcpy (stpcpy (p, "/"), argv[argc]);
440 return change_slashes (name);
443 /* Construct a filename from the NULL terminated list of parts. Tilde
444 expansion is done for the first argument. This function terminates
445 the process on memory shortage. */
446 char *
447 make_filename (const char *first_part, ... )
449 va_list arg_ptr;
450 char *result;
452 va_start (arg_ptr, first_part);
453 result = do_make_filename (1, first_part, arg_ptr);
454 va_end (arg_ptr);
455 return result;
458 /* Construct a filename from the NULL terminated list of parts. Tilde
459 expansion is done for the first argument. This function may return
460 NULL on error. */
461 char *
462 make_filename_try (const char *first_part, ... )
464 va_list arg_ptr;
465 char *result;
467 va_start (arg_ptr, first_part);
468 result = do_make_filename (0, first_part, arg_ptr);
469 va_end (arg_ptr);
470 return result;
475 /* Compare whether the filenames are identical. This is a
476 special version of strcmp() taking the semantics of filenames in
477 account. Note that this function works only on the supplied names
478 without considereing any context like the current directory. See
479 also same_file_p(). */
481 compare_filenames (const char *a, const char *b)
483 #ifdef HAVE_DRIVE_LETTERS
484 for ( ; *a && *b; a++, b++ )
486 if (*a != *b
487 && (toupper (*(const unsigned char*)a)
488 != toupper (*(const unsigned char*)b) )
489 && !((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/')))
490 break;
492 if ((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/'))
493 return 0;
494 else
495 return (toupper (*(const unsigned char*)a)
496 - toupper (*(const unsigned char*)b));
497 #else
498 return strcmp(a,b);
499 #endif
503 /* Convert 2 hex characters at S to a byte value. Return this value
504 or -1 if there is an error. */
506 hextobyte (const char *s)
508 int c;
510 if ( *s >= '0' && *s <= '9' )
511 c = 16 * (*s - '0');
512 else if ( *s >= 'A' && *s <= 'F' )
513 c = 16 * (10 + *s - 'A');
514 else if ( *s >= 'a' && *s <= 'f' )
515 c = 16 * (10 + *s - 'a');
516 else
517 return -1;
518 s++;
519 if ( *s >= '0' && *s <= '9' )
520 c += *s - '0';
521 else if ( *s >= 'A' && *s <= 'F' )
522 c += 10 + *s - 'A';
523 else if ( *s >= 'a' && *s <= 'f' )
524 c += 10 + *s - 'a';
525 else
526 return -1;
527 return c;
531 /* Print a BUFFER to stream FP while replacing all control characters
532 and the characters DELIM and DELIM2 with standard C escape
533 sequences. Returns the number of characters printed. */
534 size_t
535 print_sanitized_buffer2 (FILE *fp, const void *buffer, size_t length,
536 int delim, int delim2)
538 const unsigned char *p = buffer;
539 size_t count = 0;
541 for (; length; length--, p++, count++)
543 if (*p < 0x20
544 || *p == 0x7f
545 || *p == delim
546 || *p == delim2
547 || ((delim || delim2) && *p=='\\'))
549 putc ('\\', fp);
550 count++;
551 if (*p == '\n')
553 putc ('n', fp);
554 count++;
556 else if (*p == '\r')
558 putc ('r', fp);
559 count++;
561 else if (*p == '\f')
563 putc ('f', fp);
564 count++;
566 else if (*p == '\v')
568 putc ('v', fp);
569 count++;
571 else if (*p == '\b')
573 putc ('b', fp);
574 count++;
576 else if (!*p)
578 putc('0', fp);
579 count++;
581 else
583 fprintf (fp, "x%02x", *p);
584 count += 3;
587 else
589 putc (*p, fp);
590 count++;
594 return count;
597 /* Same as print_sanitized_buffer2 but with just one delimiter. */
598 size_t
599 print_sanitized_buffer (FILE *fp, const void *buffer, size_t length,
600 int delim)
602 return print_sanitized_buffer2 (fp, buffer, length, delim, 0);
606 size_t
607 print_sanitized_utf8_buffer (FILE *fp, const void *buffer,
608 size_t length, int delim)
610 const char *p = buffer;
611 size_t i;
613 /* We can handle plain ascii simpler, so check for it first. */
614 for (i=0; i < length; i++ )
616 if ( (p[i] & 0x80) )
617 break;
619 if (i < length)
621 char *buf = utf8_to_native (p, length, delim);
622 /*(utf8 conversion already does the control character quoting)*/
623 i = strlen (buf);
624 fputs (buf, fp);
625 jnlib_free (buf);
626 return i;
628 else
629 return print_sanitized_buffer (fp, p, length, delim);
633 size_t
634 print_sanitized_string2 (FILE *fp, const char *string, int delim, int delim2)
636 return string? print_sanitized_buffer2 (fp, string, strlen (string),
637 delim, delim2):0;
640 size_t
641 print_sanitized_string (FILE *fp, const char *string, int delim)
643 return string? print_sanitized_buffer (fp, string, strlen (string), delim):0;
646 size_t
647 print_sanitized_utf8_string (FILE *fp, const char *string, int delim)
649 return string? print_sanitized_utf8_buffer (fp,
650 string, strlen (string),
651 delim) : 0;
654 /* Create a string from the buffer P_ARG of length N which is suitable
655 for printing. Caller must release the created string using xfree.
656 This function terminates the process on memory shortage. */
657 char *
658 sanitize_buffer (const void *p_arg, size_t n, int delim)
660 const unsigned char *p = p_arg;
661 size_t save_n, buflen;
662 const unsigned char *save_p;
663 char *buffer, *d;
665 /* First count length. */
666 for (save_n = n, save_p = p, buflen=1 ; n; n--, p++ )
668 if ( *p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\'))
670 if ( *p=='\n' || *p=='\r' || *p=='\f'
671 || *p=='\v' || *p=='\b' || !*p )
672 buflen += 2;
673 else
674 buflen += 5;
676 else
677 buflen++;
679 p = save_p;
680 n = save_n;
681 /* And now make the string */
682 d = buffer = jnlib_xmalloc( buflen );
683 for ( ; n; n--, p++ )
685 if (*p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\')) {
686 *d++ = '\\';
687 if( *p == '\n' )
688 *d++ = 'n';
689 else if( *p == '\r' )
690 *d++ = 'r';
691 else if( *p == '\f' )
692 *d++ = 'f';
693 else if( *p == '\v' )
694 *d++ = 'v';
695 else if( *p == '\b' )
696 *d++ = 'b';
697 else if( !*p )
698 *d++ = '0';
699 else {
700 sprintf(d, "x%02x", *p );
701 d += 3;
704 else
705 *d++ = *p;
707 *d = 0;
708 return buffer;
712 /* Given a string containing an UTF-8 encoded text, return the number
713 of characters in this string. It differs from strlen in that it
714 only counts complete UTF-8 characters. Note, that this function
715 does not take combined characters into account. */
716 size_t
717 utf8_charcount (const char *s)
719 size_t n;
721 for (n=0; *s; s++)
722 if ( (*s&0xc0) != 0x80 ) /* Exclude continuation bytes: 10xxxxxx */
723 n++;
725 return n;
729 /****************************************************
730 ********** W32 specific functions ****************
731 ****************************************************/
733 #ifdef HAVE_W32_SYSTEM
734 const char *
735 w32_strerror (int ec)
737 static char strerr[256];
739 if (ec == -1)
740 ec = (int)GetLastError ();
741 FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec,
742 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
743 strerr, DIM (strerr)-1, NULL);
744 return strerr;
746 #endif /*HAVE_W32_SYSTEM*/
749 /****************************************************
750 ******** Locale insensitive ctype functions ********
751 ****************************************************/
752 /* FIXME: replace them by a table lookup and macros */
754 ascii_isupper (int c)
756 return c >= 'A' && c <= 'Z';
760 ascii_islower (int c)
762 return c >= 'a' && c <= 'z';
765 int
766 ascii_toupper (int c)
768 if (c >= 'a' && c <= 'z')
769 c &= ~0x20;
770 return c;
773 int
774 ascii_tolower (int c)
776 if (c >= 'A' && c <= 'Z')
777 c |= 0x20;
778 return c;
783 ascii_strcasecmp( const char *a, const char *b )
785 if (a == b)
786 return 0;
788 for (; *a && *b; a++, b++) {
789 if (*a != *b && ascii_toupper(*a) != ascii_toupper(*b))
790 break;
792 return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
795 int
796 ascii_strncasecmp (const char *a, const char *b, size_t n)
798 const unsigned char *p1 = (const unsigned char *)a;
799 const unsigned char *p2 = (const unsigned char *)b;
800 unsigned char c1, c2;
802 if (p1 == p2 || !n )
803 return 0;
807 c1 = ascii_tolower (*p1);
808 c2 = ascii_tolower (*p2);
810 if ( !--n || c1 == '\0')
811 break;
813 ++p1;
814 ++p2;
816 while (c1 == c2);
818 return c1 - c2;
823 ascii_memcasecmp (const void *a_arg, const void *b_arg, size_t n )
825 const char *a = a_arg;
826 const char *b = b_arg;
828 if (a == b)
829 return 0;
830 for ( ; n; n--, a++, b++ )
832 if( *a != *b && ascii_toupper (*a) != ascii_toupper (*b) )
833 return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
835 return 0;
839 ascii_strcmp( const char *a, const char *b )
841 if (a == b)
842 return 0;
844 for (; *a && *b; a++, b++) {
845 if (*a != *b )
846 break;
848 return *a == *b? 0 : (*(signed char *)a - *(signed char *)b);
852 void *
853 ascii_memcasemem (const void *haystack, size_t nhaystack,
854 const void *needle, size_t nneedle)
857 if (!nneedle)
858 return (void*)haystack; /* finding an empty needle is really easy */
859 if (nneedle <= nhaystack)
861 const char *a = haystack;
862 const char *b = a + nhaystack - nneedle;
864 for (; a <= b; a++)
866 if ( !ascii_memcasecmp (a, needle, nneedle) )
867 return (void *)a;
870 return NULL;
873 /*********************************************
874 ********** missing string functions *********
875 *********************************************/
877 #ifndef HAVE_STPCPY
878 char *
879 stpcpy(char *a,const char *b)
881 while( *b )
882 *a++ = *b++;
883 *a = 0;
885 return (char*)a;
887 #endif
889 #ifndef HAVE_STRSEP
890 /* Code taken from glibc-2.2.1/sysdeps/generic/strsep.c. */
891 char *
892 strsep (char **stringp, const char *delim)
894 char *begin, *end;
896 begin = *stringp;
897 if (begin == NULL)
898 return NULL;
900 /* A frequent case is when the delimiter string contains only one
901 character. Here we don't need to call the expensive `strpbrk'
902 function and instead work using `strchr'. */
903 if (delim[0] == '\0' || delim[1] == '\0')
905 char ch = delim[0];
907 if (ch == '\0')
908 end = NULL;
909 else
911 if (*begin == ch)
912 end = begin;
913 else if (*begin == '\0')
914 end = NULL;
915 else
916 end = strchr (begin + 1, ch);
919 else
920 /* Find the end of the token. */
921 end = strpbrk (begin, delim);
923 if (end)
925 /* Terminate the token and set *STRINGP past NUL character. */
926 *end++ = '\0';
927 *stringp = end;
929 else
930 /* No more delimiters; this is the last token. */
931 *stringp = NULL;
933 return begin;
935 #endif /*HAVE_STRSEP*/
938 #ifndef HAVE_STRLWR
939 char *
940 strlwr(char *s)
942 char *p;
943 for(p=s; *p; p++ )
944 *p = tolower(*p);
945 return s;
947 #endif
950 #ifndef HAVE_STRCASECMP
952 strcasecmp( const char *a, const char *b )
954 for( ; *a && *b; a++, b++ ) {
955 if( *a != *b && toupper(*a) != toupper(*b) )
956 break;
958 return *(const byte*)a - *(const byte*)b;
960 #endif
963 /****************
964 * mingw32/cpd has a memicmp()
966 #ifndef HAVE_MEMICMP
968 memicmp( const char *a, const char *b, size_t n )
970 for( ; n; n--, a++, b++ )
971 if( *a != *b && toupper(*(const byte*)a) != toupper(*(const byte*)b) )
972 return *(const byte *)a - *(const byte*)b;
973 return 0;
975 #endif
978 #ifndef HAVE_MEMRCHR
979 void *
980 memrchr (const void *buffer, int c, size_t n)
982 const unsigned char *p = buffer;
984 for (p += n; n ; n--)
985 if (*--p == c)
986 return (void *)p;
987 return NULL;
989 #endif /*HAVE_MEMRCHR*/
992 /* Percent-escape the string STR by replacing colons with '%3a'. If
993 EXTRA is not NULL all characters in EXTRA are also escaped. */
994 static char *
995 do_percent_escape (const char *str, const char *extra, int die)
997 int i, j;
998 char *ptr;
1000 if (!str)
1001 return NULL;
1003 for (i=j=0; str[i]; i++)
1004 if (str[i] == ':' || str[i] == '%' || (extra && strchr (extra, str[i])))
1005 j++;
1006 if (die)
1007 ptr = jnlib_xmalloc (i + 2 * j + 1);
1008 else
1010 ptr = jnlib_malloc (i + 2 * j + 1);
1011 if (!ptr)
1012 return NULL;
1014 i = 0;
1015 while (*str)
1017 if (*str == ':')
1019 ptr[i++] = '%';
1020 ptr[i++] = '3';
1021 ptr[i++] = 'a';
1023 else if (*str == '%')
1025 ptr[i++] = '%';
1026 ptr[i++] = '2';
1027 ptr[i++] = '5';
1029 else if (extra && strchr (extra, *str))
1031 ptr[i++] = '%';
1032 ptr[i++] = tohex_lower ((*str>>4)&15);
1033 ptr[i++] = tohex_lower (*str&15);
1035 else
1036 ptr[i++] = *str;
1037 str++;
1039 ptr[i] = '\0';
1041 return ptr;
1044 /* Percent-escape the string STR by replacing colons with '%3a'. If
1045 EXTRA is not NULL all characters in EXTRA are also escaped. This
1046 function terminates the process on memory shortage. */
1047 char *
1048 percent_escape (const char *str, const char *extra)
1050 return do_percent_escape (str, extra, 1);
1053 /* Same as percent_escape but return NULL instead of exiting on memory
1054 error. */
1055 char *
1056 try_percent_escape (const char *str, const char *extra)
1058 return do_percent_escape (str, extra, 0);
1063 static char *
1064 do_strconcat (const char *s1, va_list arg_ptr)
1066 const char *argv[48];
1067 size_t argc;
1068 size_t needed;
1069 char *buffer, *p;
1071 argc = 0;
1072 argv[argc++] = s1;
1073 needed = strlen (s1);
1074 while (((argv[argc] = va_arg (arg_ptr, const char *))))
1076 needed += strlen (argv[argc]);
1077 if (argc >= DIM (argv)-1)
1079 errno = EINVAL;
1080 return NULL;
1082 argc++;
1084 needed++;
1085 buffer = jnlib_malloc (needed);
1086 if (buffer)
1088 for (p = buffer, argc=0; argv[argc]; argc++)
1089 p = stpcpy (p, argv[argc]);
1091 return buffer;
1095 /* Concatenate the string S1 with all the following strings up to a
1096 NULL. Returns a malloced buffer with the new string or NULL on a
1097 malloc error or if too many arguments are given. */
1098 char *
1099 strconcat (const char *s1, ...)
1101 va_list arg_ptr;
1102 char *result;
1104 if (!s1)
1105 result = jnlib_strdup ("");
1106 else
1108 va_start (arg_ptr, s1);
1109 result = do_strconcat (s1, arg_ptr);
1110 va_end (arg_ptr);
1112 return result;
1115 /* Same as strconcat but terminate the process with an error message
1116 if something goes wrong. */
1117 char *
1118 xstrconcat (const char *s1, ...)
1120 va_list arg_ptr;
1121 char *result;
1123 if (!s1)
1124 result = jnlib_xstrdup ("");
1125 else
1127 va_start (arg_ptr, s1);
1128 result = do_strconcat (s1, arg_ptr);
1129 va_end (arg_ptr);
1131 if (!result)
1133 if (errno == EINVAL)
1134 fputs ("\nfatal: too many args for xstrconcat\n", stderr);
1135 else
1136 fputs ("\nfatal: out of memory\n", stderr);
1137 exit (2);
1139 return result;