diff options
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | src/argparse.c | 100 | ||||
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/etc/Registry | 8 | ||||
-rw-r--r-- | tests/etc/t-argparse.conf | 5 | ||||
-rw-r--r-- | tests/t-argparse.c | 9 |
6 files changed, 116 insertions, 10 deletions
@@ -10,6 +10,8 @@ Noteworthy changes in version 1.52 (unreleased) [C38/A38/R_] * New API for name value files. + * Add a Windows Registry emulation for Unix. + * Interface changes relative to the 1.51 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gpgrt_w32_reg_query_string NEW (Windows only). diff --git a/src/argparse.c b/src/argparse.c index cb1527d..41fd833 100644 --- a/src/argparse.c +++ b/src/argparse.c @@ -1,7 +1,7 @@ /* argparse.c - Argument Parser for option handling * Copyright (C) 1997-2001, 2006-2008, 2013-2017 Werner Koch * Copyright (C) 1998-2001, 2006-2008, 2012 Free Software Foundation, Inc. - * Copyright (C) 2015-2021 g10 Code GmbH + * Copyright (C) 2015-2021, 2025 g10 Code GmbH * * This file is part of Libgpg-error. * @@ -126,6 +126,7 @@ struct _gpgrt_argparse_internal_s unsigned int user_wildcard:1; /* A [user *] has been seen. */ unsigned int user_any_active:1; /* Any user section was active. */ unsigned int user_active:1; /* User section active. */ + unsigned int no_registry:1; /* Registry not availabale. */ unsigned int expand:1; /* Expand vars in option values. */ unsigned int explicit_cmd_mode:1;/* Command mode set via config. */ unsigned int cmd_mode:1; /* Command mode according to config. */ @@ -146,6 +147,9 @@ struct _gpgrt_argparse_internal_s char *confname; opttable_t *opts; /* Malloced option table. */ unsigned int nopts; /* Number of items in OPTS. */ +#ifndef HAVE_W32_SYSTEM + gpgrt_nvc_t registry; /* Registry emulation. */ +#endif }; @@ -264,6 +268,7 @@ deinitialize (gpgrt_argparse_t *arg) xfree (v); v = vn; } + _gpgrt_nvc_release (arg->internal->registry); xfree (arg->internal->username); xfree (arg->internal->explicit_conffile); xfree (arg->internal->opts); @@ -323,6 +328,7 @@ initialize (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, estream_t fp) arg->internal->user_wildcard = 0; arg->internal->user_any_active = 0; arg->internal->user_active = 0; + arg->internal->no_registry = 0; arg->internal->if_cond = 0; arg->internal->vartbl = NULL; arg->internal->username = NULL; @@ -340,6 +346,9 @@ initialize (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, estream_t fp) arg->internal->iio_list = NULL; arg->internal->conffp = NULL; arg->internal->confname = NULL; +#ifndef HAVE_W32_SYSTEM + arg->internal->registry = NULL; +#endif /* Clear the copy of the option list. */ /* Clear the error indicator. */ @@ -1225,6 +1234,82 @@ handle_meta_let (gpgrt_argparse_t *arg, unsigned int alternate, char *args) } +#ifndef HAVE_W32_SYSTEM +/* On Unix we emulate the Windows Regregisyr using a name-value + * formatted file "Registry" in the system config directory. If an + * inetnal error is found _ERR is set to an argparse error and NULL + * returned. */ +static char * +emulated_registry_lookup (gpgrt_argparse_t *arg, const char *name, int *r_err) +{ + const char *s; + gpgrt_nve_t e; + + *r_err = 0; + + if (!arg->internal->in_sysconf) + return NULL; /* Lookup in the user conf directory is not supported. */ + if (arg->internal->no_registry) + return NULL; /* Registry file does not exist. */ + + /* Read and parse the resgistry if not yet done. */ + if (!arg->internal->registry) + { + gpg_error_t err; + int lnr; + char *fname; + estream_t fp; + char *p; + + if (!arg->internal->confname || !arg->internal->confname) + return NULL; /* No system conf file known. */ + + fname = xtrymalloc (strlen (arg->internal->confname) + 8 + 2 ); + if (!fname) + { + *r_err = ARGPARSE_OUT_OF_CORE; + return NULL; + } + strcpy (fname, arg->internal->confname); + p = strrchr (fname, '/'); + strcpy (p? p : fname, "/Registry"); + fp = _gpgrt_fopen (fname, "r"); + if (!fp) + { + arg->internal->no_registry = 1; + return NULL; + } + if (arg->internal->verbose) + _gpgrt_log_info ("Note: Using Registry emulation file '%s'\n", fname); + + err = _gpgrt_nvc_parse (&arg->internal->registry, &lnr, fp, + GPGRT_NVC_SECTION); + _gpgrt_fclose (fp); + if (err) + { + _gpgrt_log_info ("%s:%d: error parsing Registry emulation file: %s\n", + fname, lnr, _gpg_strerror (err)); + *r_err = ARGPARSE_READ_ERROR; + arg->internal->no_registry = 1; + xfree (fname); + return NULL; + } + xfree (fname); + } + + e = _gpgrt_nvc_lookup (arg->internal->registry, name); + if (!e && *name != '/') + { + /* Strip any HKLM or HKCU prefix and try again. */ + name = strchr (name, '/'); + if (name) + e = _gpgrt_nvc_lookup (arg->internal->registry, name); + } + s = e? _gpgrt_nve_value (e) : NULL; + return s? xtrystrdup (s) : NULL; +} +#endif /* Unix*/ + /* Implementation of the "getenv" and, if ALTERNATE is set, the * "getreg" command. ARG is the context. ARGS is a non-empty string * with the name of the variable and of the envvar/registry-entry. @@ -1234,12 +1319,10 @@ static int handle_meta_getenv (gpgrt_argparse_t *arg, unsigned int alternate, char *args) { char *name = args; - char *varname; + char *varname, *p; const char *s; int rc; -#ifdef HAVE_W32_SYSTEM char *helpbuf = NULL; -#endif for (varname = name; *varname && !(isascii (*varname) && isspace (*varname)); @@ -1262,7 +1345,12 @@ handle_meta_getenv (gpgrt_argparse_t *arg, unsigned int alternate, char *args) #ifdef HAVE_W32_SYSTEM s = helpbuf = _gpgrt_w32_reg_get_string (varname); #else - s = ""; + for (p=varname; *p; p++) + if (*p == '\\') + *p = '/'; + s = helpbuf = emulated_registry_lookup (arg, varname, &rc); + if (!s && rc) + return rc; #endif } else @@ -1270,9 +1358,7 @@ handle_meta_getenv (gpgrt_argparse_t *arg, unsigned int alternate, char *args) /* Set/clear the variable but do not substitute. */ rc = set_variable (arg, name, s, 0); -#ifdef HAVE_W32_SYSTEM xfree (helpbuf); -#endif return rc; } diff --git a/tests/Makefile.am b/tests/Makefile.am index abe57b3..4ebb9d7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -19,7 +19,7 @@ ## Process this file with automake to produce Makefile.in -EXTRA_DIST = t-argparse.conf etc/t-argparse.conf +EXTRA_DIST = t-argparse.conf etc/t-argparse.conf etc/Registry gpg_error_lib = ../src/libgpg-error.la diff --git a/tests/etc/Registry b/tests/etc/Registry new file mode 100644 index 0000000..fe5598e --- /dev/null +++ b/tests/etc/Registry @@ -0,0 +1,8 @@ +# A test Registry emulation file for t-argparse + +[HKCU\Software\GNU\GnuPG] +DisableAKR: fact +SomeKey: Value-one + +[ \fhghfkhkfh ] +DisableAKR: yes diff --git a/tests/etc/t-argparse.conf b/tests/etc/t-argparse.conf index 92c373d..d8afc9c 100644 --- a/tests/etc/t-argparse.conf +++ b/tests/etc/t-argparse.conf @@ -69,6 +69,11 @@ output # Default key for user john my-option 42 +[expand] +[getreg foo HKCU\Software\GNU\GnuPG:DisableAKR] +disable-akr $foo +[-expand] + # Options applied only for user joy end here. [user *] [-info All the following options are applied only if the] diff --git a/tests/t-argparse.c b/tests/t-argparse.c index 6085066..666e17d 100644 --- a/tests/t-argparse.c +++ b/tests/t-argparse.c @@ -40,6 +40,7 @@ static struct { int echo; int a_long_one; char *street; + char *disable_akr; } opt; @@ -85,6 +86,7 @@ main (int argc, char **argv) ARGPARSE_s_n(500, "a-long-option", 0 ), ARGPARSE_conffile(501, "options", "|FILE|read options from FILE"), ARGPARSE_noconffile(502, "no-options", "Ignore conf files"), + ARGPARSE_s_s(503, "disable-akr", "@" ), ARGPARSE_verbatim("This epilog consists\nof only 2 lines\n"), ARGPARSE_end() }; @@ -93,8 +95,8 @@ main (int argc, char **argv) | ARGPARSE_FLAG_ONEDASH | ARGPARSE_FLAG_SYS | ARGPARSE_FLAG_USER - /* | ARGPARSE_FLAG_VERBOSE */ - /* | ARGPARSE_FLAG_WITHATTR */ + | ARGPARSE_FLAG_VERBOSE + | ARGPARSE_FLAG_WITHATTR ) }; int i; const char *srcdir; @@ -146,6 +148,7 @@ main (int argc, char **argv) case 'M': opt.myopt = 0; break; case 's': opt.street = pargs.r.ret_str; break; case 500: opt.a_long_one++; break; + case 503: opt.disable_akr = pargs.r.ret_str; break; case 601: case 602: @@ -176,6 +179,8 @@ main (int argc, char **argv) printf (" myopt=%d\n", opt.myopt ); if (opt.a_long_one) printf (" a-long-one=%d\n", opt.a_long_one ); + if (opt.disable_akr) + printf (" disable-akr=%s\n", opt.disable_akr); if (opt.echo) printf (" echo=%d\n", opt.echo ); |