diff options
-rw-r--r-- | NEWS | 7 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/gpg-error.def.in | 3 | ||||
-rw-r--r-- | src/gpg-error.h.in | 6 | ||||
-rw-r--r-- | src/gpg-error.vers | 3 | ||||
-rw-r--r-- | src/gpgrt-int.h | 11 | ||||
-rw-r--r-- | src/stringutils.c | 224 | ||||
-rw-r--r-- | src/sysutils.c | 39 | ||||
-rw-r--r-- | src/visibility.c | 27 | ||||
-rw-r--r-- | src/visibility.h | 4 | ||||
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/t-common.h | 29 | ||||
-rw-r--r-- | tests/t-stringutils.c | 282 |
14 files changed, 639 insertions, 3 deletions
@@ -1,6 +1,13 @@ Noteworthy changes in version 1.38 (unreleased) [C28/A28/R_] ----------------------------------------------- + * Interface changes relative to the 1.37 release: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + gpgrt_fnameconcat NEW. + gpgrt_absfnameconcat NEW. + + Release-info: https://dev.gnupg.org/T + Noteworthy changes in version 1.37 (2020-02-07) [C28/A28/R0] ----------------------------------------------- diff --git a/configure.ac b/configure.ac index a92143c..ceace2d 100644 --- a/configure.ac +++ b/configure.ac @@ -190,7 +190,7 @@ AM_GNU_GETTEXT([external]) # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS([stdlib.h locale.h stdint.h sys/select.h sys/time.h \ - signal.h poll.h]) + signal.h poll.h pwd.h]) AC_FUNC_STRERROR_R case "${host_os}" in @@ -213,7 +213,7 @@ AC_SUBST(INSTALLSHELLPATH) AC_FUNC_FORK AC_CHECK_FUNCS([flockfile vasprintf mmap rand strlwr stpcpy setenv stat \ - getrlimit ]) + getrlimit getpwnam getpwuid getpwnam_r getpwuid_r ]) # diff --git a/src/Makefile.am b/src/Makefile.am index e9c057f..336fe2a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -198,6 +198,7 @@ libgpg_error_la_SOURCES = gettext.h $(arch_sources) \ strsource.c strerror.c code-to-errno.c code-from-errno.c \ visibility.c visibility.h \ sysutils.c \ + stringutils.c \ syscall-clamp.c \ logging.c \ b64dec.c b64enc.c \ diff --git a/src/gpg-error.def.in b/src/gpg-error.def.in index 0a584c4..4e3b5d7 100644 --- a/src/gpg-error.def.in +++ b/src/gpg-error.def.in @@ -229,4 +229,7 @@ EXPORTS gpgrt_add_emergency_cleanup @174 gpgrt_abort @175 + gpgrt_fnameconcat @178 + gpgrt_absfnameconcat @179 + ;; end of file with public symbols for Windows. diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in index d118e90..470021d 100644 --- a/src/gpg-error.h.in +++ b/src/gpg-error.h.in @@ -1309,6 +1309,12 @@ void gpgrt_set_fixed_string_mapper (const char *(*f)(const char*)); * numbering scheme a LEVEL of 3 is suitable; see the manual. */ int gpgrt_cmp_version (const char *a, const char *b, int level); +/* Construct a filename from the NULL terminated list of parts. Tilde + * expansion is done for the first argument. The caller must release + * the result using gpgrt_free; on error ERRNO is set and NULL + * returned. The second function returns an absolute filename. */ +char *gpgrt_fnameconcat (const char *first, ...) GPGRT_ATTR_SENTINEL(0); +char *gpgrt_absfnameconcat (const char *first, ...) GPGRT_ATTR_SENTINEL(0); #ifdef __cplusplus diff --git a/src/gpg-error.vers b/src/gpg-error.vers index eef4cbc..594342b 100644 --- a/src/gpg-error.vers +++ b/src/gpg-error.vers @@ -199,6 +199,9 @@ GPG_ERROR_1.0 { gpgrt_add_emergency_cleanup; gpgrt_abort; + gpgrt_fnameconcat; + gpgrt_absfnameconcat; + local: *; }; diff --git a/src/gpgrt-int.h b/src/gpgrt-int.h index 718b62c..97f0533 100644 --- a/src/gpgrt-int.h +++ b/src/gpgrt-int.h @@ -787,6 +787,17 @@ gpg_err_code_t _gpgrt_chdir (const char *name); /* Return the current WD as a malloced string. */ char *_gpgrt_getcwd (void); +/* Return the home directory of user NAME. */ +char *_gpgrt_getpwdir (const char *name); + +/* Expand and concat file name parts. */ +char *_gpgrt_vfnameconcat (int want_abs, const char *first_part, + va_list arg_ptr); +char *_gpgrt_fnameconcat (const char *first_part, + ... ) GPGRT_ATTR_SENTINEL(0); +char *_gpgrt_absfnameconcat (const char *first_part, + ... ) GPGRT_ATTR_SENTINEL(0); + /* * Platform specific functions (Windows) diff --git a/src/stringutils.c b/src/stringutils.c new file mode 100644 index 0000000..d92398d --- /dev/null +++ b/src/stringutils.c @@ -0,0 +1,224 @@ +/* stringutils.c - String helper functions. + * Copyright (C) 1997, 2014 Werner Koch + * Copyright (C) 2020 g10 Code GmbH + * + * This file is part of libgpg-error. + * + * libgpg-error is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * libgpg-error is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include <config.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <stdarg.h> +#include <errno.h> +#ifdef HAVE_STAT +# include <sys/stat.h> +#endif +#include <sys/types.h> +#ifdef HAVE_PWD_H +# include <pwd.h> +#endif + +#include "gpgrt-int.h" + + +/* Helper for _gpgrt_fnameconcat. The additional flag WANT_ABS tells + * whether an absolute file name is requested. */ +char * +_gpgrt_vfnameconcat (int want_abs, const char *first_part, va_list arg_ptr) +{ + const char *argv[32]; + int argc; + size_t n; + int skip = 1; /* Characters to skip from FIRST_PART. */ + char *home_buffer = NULL; + char *name, *home, *p; + + /* Put all args into an array becuase we need to scan them twice. */ + n = strlen (first_part) + 1; + argc = 0; + while ((argv[argc] = va_arg (arg_ptr, const char *))) + { + n += strlen (argv[argc]) + 1; + if (argc >= DIM (argv)-1) + { + _gpg_err_set_errno (EINVAL); + return NULL; + } + argc++; + } + n++; + + home = NULL; + if (*first_part == '~') + { + if (first_part[1] == '/' || !first_part[1]) + { + /* This is the "~/" or "~" case. */ + home_buffer = _gpgrt_getenv ("HOME"); + if (!home_buffer) + home_buffer = _gpgrt_getpwdir (NULL); + home = home_buffer; + if (home && *home) + n += strlen (home); + } + else + { + /* This is the "~username/" or "~username" case. */ + char *user; + + user = _gpgrt_strdup (first_part+1); + if (!user) + return NULL; + + p = strchr (user, '/'); + if (p) + *p = 0; + skip = 1 + strlen (user); + + home = home_buffer = _gpgrt_getpwdir (user); + xfree (user); + if (home) + n += strlen (home); + else + skip = 1; + } + } + + name = xtrymalloc (n); + if (!name) + { + _gpgrt_free (home_buffer); + return NULL; + } + + if (home) + p = stpcpy (stpcpy (name, home), first_part + skip); + else + p = stpcpy (name, first_part); + + xfree (home_buffer); + home_buffer = NULL; + + for (argc=0; argv[argc]; argc++) + { + /* Avoid a leading double slash if the first part was "/". */ + if (!argc && name[0] == '/' && !name[1]) + p = stpcpy (p, argv[argc]); + else + p = stpcpy (stpcpy (p, "/"), argv[argc]); + } + + if (want_abs) + { +#ifdef HAVE_W32_SYSTEM + p = strchr (name, ':'); + if (p) + p++; + else + p = name; +#else + p = name; +#endif + if (*p != '/' +#ifdef HAVE_W32_SYSTEM + && *p != '\\' +#endif + ) + { + home = _gpgrt_getcwd (); + if (!home) + { + xfree (name); + return NULL; + } + + n = strlen (home) + 1 + strlen (name) + 1; + home_buffer = xtrymalloc (n); + if (!home_buffer) + { + xfree (home); + xfree (name); + return NULL; + } + + if (p == name) + p = home_buffer; + else /* Windows case. */ + { + memcpy (home_buffer, p, p - name + 1); + p = home_buffer + (p - name + 1); + } + + /* Avoid a leading double slash if the cwd is "/". */ + if (home[0] == '/' && !home[1]) + strcpy (stpcpy (p, "/"), name); + else + strcpy (stpcpy (stpcpy (p, home), "/"), name); + + xfree (home); + xfree (name); + name = home_buffer; + /* Let's do a simple compression to catch the common case of + * a trailing "/.". */ + n = strlen (name); + if (n > 2 && name[n-2] == '/' && name[n-1] == '.') + name[n-2] = 0; + } + } + +#ifdef HAVE_W32_SYSTEM + for (p=name; *p; p++) + if (*p == '\\') + *p = '/'; +#endif + return name; +} + + +/* Construct a filename from the NULL terminated list of parts. Tilde + * expansion is done for the first argument. The caller must release + * the result using gpgrt_free; on error ERRNO is set and NULL + * returned. */ +char * +_gpgrt_fnameconcat (const char *first_part, ... ) +{ + va_list arg_ptr; + char *result; + + va_start (arg_ptr, first_part); + result = _gpgrt_vfnameconcat (0, first_part, arg_ptr); + va_end (arg_ptr); + return result; +} + + +/* Construct a filename from the NULL terminated list of parts. Tilde + * expansion is done for the first argument. The caller must release + * the result using gpgrt_free; on error ERRNO is set and NULL + * returned. This version returns an absolute filename. */ +char * +_gpgrt_absfnameconcat (const char *first_part, ... ) +{ + va_list arg_ptr; + char *result; + + va_start (arg_ptr, first_part); + result = _gpgrt_vfnameconcat (1, first_part, arg_ptr); + va_end (arg_ptr); + return result; +} diff --git a/src/sysutils.c b/src/sysutils.c index bc31d92..6bdd76f 100644 --- a/src/sysutils.c +++ b/src/sysutils.c @@ -32,6 +32,9 @@ #endif #include <sys/types.h> #include <fcntl.h> +#ifdef HAVE_PWD_H +# include <pwd.h> +#endif #include "gpgrt-int.h" @@ -337,3 +340,39 @@ _gpgrt_getcwd (void) #endif } } + + +/* Get the standard home directory for user NAME. If NAME is NULL the + * directory for the current user is retruned. Caller must release + * the returned string. */ +char * +_gpgrt_getpwdir (const char *name) +{ + char *result = NULL; +#ifdef HAVE_PWD_H + struct passwd *pwd = NULL; + + if (name) + { +#ifdef HAVE_GETPWNAM + /* Fixme: We should use getpwnam_r if available. */ + pwd = getpwnam (name); +#endif + } + else + { +#ifdef HAVE_GETPWUID + /* Fixme: We should use getpwuid_r if available. */ + pwd = getpwuid (getuid()); +#endif + } + if (pwd) + { + result = _gpgrt_strdup (pwd->pw_dir); + } +#else /*!HAVE_PWD_H*/ + /* No support at all. */ + (void)name; +#endif /*HAVE_PWD_H*/ + return result; +} diff --git a/src/visibility.c b/src/visibility.c index d754032..5f88aad 100644 --- a/src/visibility.c +++ b/src/visibility.c @@ -1180,6 +1180,33 @@ gpgrt_cmp_version (const char *a, const char *b, int level) +/* String utilities. */ +char * +gpgrt_fnameconcat (const char *first, ... ) +{ + va_list arg_ptr; + char *result; + + va_start (arg_ptr, first); + result = _gpgrt_vfnameconcat (0, first, arg_ptr); + va_end (arg_ptr); + return result; +} + +char * +gpgrt_absfnameconcat (const char *first, ... ) +{ + va_list arg_ptr; + char *result; + + va_start (arg_ptr, first); + result = _gpgrt_vfnameconcat (1, first, arg_ptr); + va_end (arg_ptr); + return result; +} + + + /* For consistency reasons we use function wrappers also for Windows * specific function despite that they are technically not needed. */ #ifdef HAVE_W32_SYSTEM diff --git a/src/visibility.h b/src/visibility.h index 28038d0..192f733 100644 --- a/src/visibility.h +++ b/src/visibility.h @@ -216,6 +216,10 @@ MARK_VISIBLE (gpgrt_set_usage_outfnc); MARK_VISIBLE (gpgrt_cmp_version); +MARK_VISIBLE (gpgrt_fnameconcat); +MARK_VISIBLE (gpgrt_absfnameconcat); + + #undef MARK_VISIBLE #else /*!_GPGRT_INCL_BY_VISIBILITY_C*/ diff --git a/tests/Makefile.am b/tests/Makefile.am index ea02da1..39ca241 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -28,7 +28,7 @@ endif gpg_error_lib = ../src/libgpg-error.la TESTS = t-version t-strerror t-syserror t-lock t-printf t-poll t-b64 \ - t-argparse t-logging + t-argparse t-logging t-stringutils AM_CPPFLAGS = -I$(top_builddir)/src $(extra_includes) diff --git a/tests/t-common.h b/tests/t-common.h index e70e04d..db496e2 100644 --- a/tests/t-common.h +++ b/tests/t-common.h @@ -39,6 +39,33 @@ static void fail (const char *format, ...) GPGRT_ATTR_PRINTF(1,2); static void show (const char *format, ...) GPGRT_ATTR_PRINTF(1,2); +static void * +xmalloc (size_t n) +{ + char *p = gpgrt_malloc (n); + if (!p) + die ("out of core\n"); + return p; +} + +static char * +xstrdup (const char *s) +{ + char *p = gpgrt_strdup (s); + if (!p) + die ("out of core\n"); + return p; +} + +static void +xfree (void *p) +{ + if (p) + gpgrt_free (p); +} + + + static void die (const char *format, ...) { @@ -57,6 +84,8 @@ die (const char *format, ...) #ifdef HAVE_FLOCKFILE funlockfile (stderr); #endif + xfree (xstrdup ("")); /* To avoid compiler warnings. */ + xfree (xmalloc (16)); /* To avoid compiler warnings. */ exit (1); } diff --git a/tests/t-stringutils.c b/tests/t-stringutils.c new file mode 100644 index 0000000..01094bf --- /dev/null +++ b/tests/t-stringutils.c @@ -0,0 +1,282 @@ +/* t-stringutils.c - Check some string utilities + * Copyright (C) 2020 g10 Code GmbH + * + * This file is part of Libgpg-error. + * + * Libgpg-error is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgpg-error is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, see <https://www.gnu.org/licenses/>. + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <unistd.h> +#ifdef HAVE_STAT +# include <sys/stat.h> +#endif +#include <sys/types.h> +#ifdef HAVE_PWD_H +# include <pwd.h> +#endif +#include <errno.h> + +#define PGM "t-stringutils" +#include "t-common.h" + + +static const char * +my_strusage (int level) +{ + const char *p; + + switch (level) + { + case 9: p = "LGPL-2.1-or-later"; break; + case 11: p = PGM; break; + default: p = NULL; + } + return p; +} + + +const char * +mygethome (void) +{ + static char *home_buffer; + + if (!home_buffer) + { + char *home = getenv("HOME"); + + if(home) + home_buffer = xstrdup (home); +#if defined(HAVE_GETPWUID) && defined(HAVE_PWD_H) + else + { + struct passwd *pwd; + + pwd = getpwuid (getuid()); + if (pwd) + home_buffer = xstrdup (pwd->pw_dir); + } +#endif + } + return home_buffer; +} + + +static char * +mygetcwd (void) +{ + char *buffer; + size_t size = 100; + + for (;;) + { + buffer = xmalloc (size+1); + if (getcwd (buffer, size) == buffer) + return buffer; + xfree (buffer); + if (errno != ERANGE) + die ("error getting current cwd: %s\n", strerror (errno)); + size *= 2; + } +} + + +static void +check_fnameconcat (void) +{ + char *out; + const char *home = mygethome (); + size_t homelen = home? strlen (home):0; + + out = gpgrt_fnameconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", NULL); + if (out) + fail ("fnameconcat succeeded but should not at line %d\n", __LINE__); + else if (errno != EINVAL) + fail ("fnameconcat return wrong error at line %d\n", __LINE__); + xfree (out); + + out = gpgrt_fnameconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", NULL); + if (out) + fail ("fnameconcat succeeded but should not at line %d\n", __LINE__); + else if (errno != EINVAL) + fail ("fnameconcat return wrong error at line %d\n", __LINE__); + xfree (out); + + out = gpgrt_fnameconcat ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "1", "2", NULL); + if (!out || strcmp (out, + "1/2/3/4/5/6/7/8/9/10/" + "1/2/3/4/5/6/7/8/9/10/" + "1/2/3/4/5/6/7/8/9/10/" + "1/2")) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + xfree (out); + + out = gpgrt_fnameconcat ("foo", "~/bar", "baz/cde", NULL); + if (!out || strcmp (out, "foo/~/bar/baz/cde")) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + xfree (out); + + out = gpgrt_fnameconcat ("foo", "~/bar", "baz/cde/", NULL); + if (!out || strcmp (out, "foo/~/bar/baz/cde/")) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + xfree (out); + + out = gpgrt_fnameconcat ("/foo", "~/bar", "baz/cde/", NULL); + if (!out || strcmp (out, "/foo/~/bar/baz/cde/")) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + xfree (out); + + out = gpgrt_fnameconcat ("//foo", "~/bar", "baz/cde/", NULL); + if (!out || strcmp (out, "//foo/~/bar/baz/cde/")) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + xfree (out); + + out = gpgrt_fnameconcat ("", "~/bar", "baz/cde", NULL); + if (!out || strcmp (out, "/~/bar/baz/cde")) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + xfree (out); + + out = gpgrt_fnameconcat ("~/foo", "bar", NULL); + if (!out) + fail ("fnameconcat failed at line %d\n", __LINE__); + else if (home) + { + if (strlen (out) < homelen + 7) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + else if (strncmp (out, home, homelen)) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + else if (strcmp (out+homelen, "/foo/bar")) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + } + else + { + if (strcmp (out, "~/foo/bar")) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + } + xfree (out); + + out = gpgrt_fnameconcat ("~", "bar", NULL); + if (!out) + fail ("fnameconcat failed at line %d\n", __LINE__); + else if (home) + { + if (strlen (out) < homelen + 3) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + else if (strncmp (out, home, homelen)) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + else if (strcmp (out+homelen, "/bar")) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + } + else + { + if (strcmp (out, "~/bar")) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + } + xfree (out); +} + + +static void +check_absfnameconcat (void) +{ + char *out; + char *cwd = mygetcwd (); + size_t cwdlen = strlen (cwd); + + out = gpgrt_absfnameconcat ("foo", "bar", NULL); + if (!out) + fail ("fnameconcat failed at line %d\n", __LINE__); + else if (strlen (out) < cwdlen + 7) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + else if (strncmp (out, cwd, cwdlen)) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + else if (strcmp (out+cwdlen, "/foo/bar")) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + xfree (out); + + out = gpgrt_absfnameconcat ("./foo", NULL); + if (!out) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + else if (strlen (out) < cwdlen + 5) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + else if (strncmp (out, cwd, cwdlen)) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + else if (strcmp (out+cwdlen, "/./foo")) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + xfree (out); + + out = gpgrt_absfnameconcat (".", NULL); + if (!out) + fail ("fnameconcat failed at line %d\n", __LINE__); + else if (strlen (out) < cwdlen) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + else if (strncmp (out, cwd, cwdlen)) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + else if (strcmp (out+cwdlen, "")) + fail ("fnameconcat failed at line %d (out=%s)\n", __LINE__, out); + xfree (out); + + xfree (cwd); +} + + +int +main (int argc, char **argv) +{ + gpgrt_opt_t opts[] = { + ARGPARSE_x ('v', "verbose", NONE, 0, "Print more diagnostics"), + ARGPARSE_s_n('d', "debug", "Flyswatter"), + ARGPARSE_end() + }; + gpgrt_argparse_t pargs = { &argc, &argv, 0 }; + + gpgrt_set_strusage (my_strusage); + gpgrt_log_set_prefix (gpgrt_strusage (11), GPGRT_LOG_WITH_PREFIX); + + while (gpgrt_argparse (NULL, &pargs, opts)) + { + switch (pargs.r_opt) + { + case 'v': verbose++; break; + case 'd': debug++; break; + default : pargs.err = ARGPARSE_PRINT_ERROR; break; + } + } + gpgrt_argparse (NULL, &pargs, NULL); + + show ("testing string utilities\n"); + + check_fnameconcat (); + check_absfnameconcat (); + + show ("testing string utilities finished\n"); + return !!errorcount; +} |