diff options
author | Werner Koch <wk@gnupg.org> | 2020-02-22 11:31:32 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2020-02-22 11:31:32 +0100 |
commit | b79b2a7fb3ad3ada45d17e8632f1ee4212ce0764 (patch) | |
tree | 161abb391bd7293c427ca894cf4ac92f7f665ccf /src | |
parent | ac663bceb02e99d4a52a1e4d65064f0deac184c1 (diff) | |
download | libgpg-error-b79b2a7fb3ad3ada45d17e8632f1ee4212ce0764.tar.gz |
core: Extend the way a config file can be specified,
* src/argparse.c (PATHSEP_C, DIRSEP_C): New.
(is_absfname, is_twopartfname): New.
(_gpgrt_argparser): Allow for a two-part config name.
Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/argparse.c | 96 |
1 files changed, 88 insertions, 8 deletions
diff --git a/src/argparse.c b/src/argparse.c index 970499f..837d153 100644 --- a/src/argparse.c +++ b/src/argparse.c @@ -36,6 +36,14 @@ #include "gpgrt-int.h" +#ifdef HAVE_W32_SYSTEM +# define PATHSEP_C ';' +# define DIRSEP_C '\\' +#else +# define PATHSEP_C ':' +# define DIRSEP_C '/' +#endif + /* The malloced configuration directories or NULL. */ static struct @@ -895,6 +903,47 @@ any_opt_conffile (gpgrt_opt_t *opts) } +/* Return true if FNAME is an absoluete filename. */ +static int +is_absfname (const char *fname) +{ + const char *s; + +#ifdef HAVE_W32_SYSTEM + s = strchr (fname, ':'); + if (s) + s++; + else + s = fname; +#else + s = fname; +#endif + + return (*s == '/' +#ifdef HAVE_W32_SYSTEM + || *s == DIRSEP_C +#endif + ); +} + + +/* If FNAME specifies two files of the form + * NAME1:/NAME2 (Unix) + * or + * NAME1;[x:]/NAME2 (Windows) + * return a pointer to the delimiter or NULL if there is none. + */ +static const char * +is_twopartfname (const char *fname) +{ + const char *s; + + if ((s = strchr (fname, PATHSEP_C)) && is_absfname (s+1) && s != fname) + return s; + return NULL; +} + + /* The full arg parser which handles option files and command line * arguments. The behaviour depends on the combinations of CONFNAME * and the ARGPARSE_FLAG_xxx values: @@ -912,8 +961,11 @@ any_opt_conffile (gpgrt_opt_t *opts) * ARGPARSE_TYPE_NONE is used no user configuration files are * processed and from the system configuration files only those which * are immutable are processed. The string values for CONFNAME shall - * not include a directory part, because that is taken from the values - * set by gpgrt_set_confdir. + * not include a directory part because that is taken from the values + * set by gpgrt_set_confdir. However, if CONFNAME is a twopart + * filename delimited by a colon (semicolon on Windows) with the + * second part being an absolute filename, the first part is used for + * the SYS file and the the entire second part for the USER file. */ int _gpgrt_argparser (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, @@ -998,9 +1050,29 @@ _gpgrt_argparser (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, goto next_state; case STATE_open_sys: - xfree (arg->internal->confname); - arg->internal->confname = _gpgrt_fnameconcat - (confdir.sys? confdir.sys : "/etc", confname, NULL); + { + /* If it is a two part name take the first part. */ + const char *s; + char *tmpname = NULL; + + if ((s = is_twopartfname (confname))) + { + tmpname = xtrymalloc (s - confname + 1); + if (!tmpname) + return (arg->r_opt = ARGPARSE_OUT_OF_CORE); + memcpy (tmpname, confname, s-confname); + tmpname[s-confname] = 0; + s = tmpname; + } + else + s = confname; + xfree (arg->internal->confname); + arg->internal->confname = _gpgrt_fnameconcat + (confdir.sys? confdir.sys : "/etc", s, NULL); + _gpgrt_free (tmpname); + if (!arg->internal->confname) + return (arg->r_opt = ARGPARSE_OUT_OF_CORE); + } arg->lineno = 0; arg->internal->idx = 0; arg->internal->stopped = 0; @@ -1062,10 +1134,18 @@ _gpgrt_argparser (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, } else { - /* Use the standard configure file. */ + /* Use the standard configure file. If it is a two part + * name take the second part. */ + const char *s; + xfree (arg->internal->confname); - arg->internal->confname = _gpgrt_fnameconcat - (confdir.user? confdir.user : "/FIXME", confname, NULL); + if ((s = is_twopartfname (confname))) + arg->internal->confname = _gpgrt_fnameconcat (s + 1, NULL); + else + arg->internal->confname = _gpgrt_fnameconcat + (confdir.user? confdir.user : "~/.config", confname, NULL); + if (!arg->internal->confname) + return (arg->r_opt = ARGPARSE_OUT_OF_CORE); } arg->lineno = 0; arg->internal->idx = 0; |