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