aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2025-04-07 14:27:06 +0000
committerWerner Koch <[email protected]>2025-04-07 14:27:06 +0000
commit9864dd4d66342cca340f8ebe57f46b2fa274bac0 (patch)
treeace2874c1629a27b876e301adfbb80f8611b37c3
parentAdd a section mode to the name-value functions. (diff)
downloadlibgpg-error-9864dd4d66342cca340f8ebe57f46b2fa274bac0.tar.gz
libgpg-error-9864dd4d66342cca340f8ebe57f46b2fa274bac0.zip
argparse: Make getreg meta command work on Unix.
* src/argparse.c (_gpgrt_argparse_internal_s): Add fields no_registry and registry. (initialize): Init them. (emulated_registry_lookup): New. (handle_meta_getenv): Use it. * tests/etc/t-argparse.conf: Add a getreg meta command. * tests/t-argparse.c (opt): Add a disable-akr command. * tests/etc/Registry: New.
-rw-r--r--NEWS2
-rw-r--r--src/argparse.c100
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/etc/Registry8
-rw-r--r--tests/etc/t-argparse.conf5
-rw-r--r--tests/t-argparse.c9
6 files changed, 116 insertions, 10 deletions
diff --git a/NEWS b/NEWS
index 58de99e..fb46926 100644
--- a/NEWS
+++ b/NEWS
@@ -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 );