1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-06-14 18:31:03 +02:00

common: Improve helpfile.c to provide a generic template API.

* common/util.h (GET_TEMPLATE_CURRENT_LOCALE): New.
(GET_TEMPLATE_SUBST_ENVVARS): New.
(GET_TEMPLATE_CRLF): New.
* common/helpfile.c (findkey_fname): Add arg flags and terminate line
with CRLF if requested.
(findkey_locale): Replace arg only_current_locale by flags and add arg
domain.
(gnupg_get_help_string): Factor all code out to ...
(gnupg_get_template): new.  Add arg domain.  Handle SUBST flags.  Do
not trim tralins spaces with the CRLF flag.

* common/t-helpfile.c (main): Require domain name and add two options.
This commit is contained in:
Werner Koch 2025-05-28 15:19:19 +02:00
parent ef5fa47ee8
commit 8d837279bc
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
3 changed files with 83 additions and 31 deletions

View File

@ -1,5 +1,6 @@
/* helpfile.c - GnuPG's helpfile feature /* helpfile.c - GnuPG's helpfile feature
* Copyright (C) 2007 Free Software Foundation, Inc. * Copyright (C) 2007 Free Software Foundation, Inc.
* Copyright (C) 2011,2012, 2025 g10 Code GmbH
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -25,6 +26,7 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>. * along with this program; if not, see <https://www.gnu.org/licenses/>.
* SPDX-License-Identifier: (LGPL-3.0-or-later OR GPL-2.0-or-later)
*/ */
#include <config.h> #include <config.h>
@ -38,7 +40,7 @@
/* Try to find KEY in the file FNAME. */ /* Try to find KEY in the file FNAME. */
static char * static char *
findkey_fname (const char *key, const char *fname) findkey_fname (const char *key, const char *fname, unsigned int flags)
{ {
gpg_error_t err = 0; gpg_error_t err = 0;
estream_t fp; estream_t fp;
@ -126,7 +128,10 @@ findkey_fname (const char *key, const char *fname)
if (is_membuf_ready (&mb)) if (is_membuf_ready (&mb))
{ {
put_membuf_str (&mb, p); put_membuf_str (&mb, p);
put_membuf (&mb, "\n", 1); if ((flags & GET_TEMPLATE_CRLF))
put_membuf (&mb, "\r\n", 2);
else
put_membuf (&mb, "\n", 1);
} }
} }
@ -159,22 +164,23 @@ findkey_fname (const char *key, const char *fname)
/* Try the help files depending on the locale. */ /* Try the help files depending on the locale. */
static char * static char *
findkey_locale (const char *key, const char *locname, findkey_locale (const char *domain, const char *key, const char *locname,
int only_current_locale, const char *dirname) const char *dirname, unsigned int flags)
{ {
const char *s; const char *s;
char *fname, *ext, *p; char *fname, *ext, *p;
char *result; char *result;
fname = xtrymalloc (strlen (dirname) + 6 + strlen (locname) + 4 + 1); fname = xtrymalloc (strlen (dirname) + 2
+ strlen (domain) + strlen (locname) + 4 + 1);
if (!fname) if (!fname)
return NULL; return NULL;
ext = stpcpy (stpcpy (fname, dirname), "/help."); ext = stpcpy (stpcpy (stpcpy (stpcpy (fname, dirname), "/"), domain), ".");
/* Search with locale name and territory. ("help.LL_TT.txt") */ /* Search with locale name and territory. ("help.LL_TT.txt") */
if (strchr (locname, '_')) if (strchr (locname, '_'))
{ {
strcpy (stpcpy (ext, locname), ".txt"); strcpy (stpcpy (ext, locname), ".txt");
result = findkey_fname (key, fname); result = findkey_fname (key, fname, flags);
} }
else else
result = NULL; /* No territory. */ result = NULL; /* No territory. */
@ -187,17 +193,17 @@ findkey_locale (const char *key, const char *locname,
for (p=ext, s=locname; *s && *s != '_';) for (p=ext, s=locname; *s && *s != '_';)
*p++ = *s++; *p++ = *s++;
strcpy (p, ".txt"); strcpy (p, ".txt");
result = findkey_fname (key, fname); result = findkey_fname (key, fname, flags);
} }
else else
result = NULL; result = NULL;
} }
if (!result && (!only_current_locale || !*locname) ) if (!result && (!(flags & GET_TEMPLATE_CURRENT_LOCALE) || !*locname))
{ {
/* Last try: Search in file without any locale info. ("help.txt") */ /* Last try: Search in file without any locale info. ("help.txt") */
strcpy (ext, "txt"); strcpy (ext, "txt");
result = findkey_fname (key, fname); result = findkey_fname (key, fname, flags);
} }
xfree (fname); xfree (fname);
@ -205,31 +211,32 @@ findkey_locale (const char *key, const char *locname,
} }
/* Return a malloced help text as identified by KEY. The system takes /* Return a malloced text as identified by KEY. The system takes
the string from an UTF-8 encoded file to be created by an the string from an UTF-8 encoded file to be created by an
administrator or as distributed with GnuPG. On a GNU or Unix administrator or as distributed with GnuPG. On a GNU or Unix
system the entry is searched in these files: system the entry is searched in these files:
/etc/gnupg/help.LL.txt /etc/gnupg/<domain>.<LL>.txt
/etc/gnupg/help.txt /etc/gnupg/<domain>.txt
/usr/share/gnupg/help.LL.txt /usr/share/gnupg/<domain>.<LL>.txt
/usr/share/gnupg/help.txt /usr/share/gnupg/<domain>.txt
Here LL denotes the two digit language code of the current locale. The <domain> is either "help" or any other domain like "mail-tube".
If ONLY_CURRENT_LOCALE is set, the function won't fallback to the Here <LL> denotes the two digit language code of the current
english valiant ("help.txt") unless that locale has been requested. locale. If the flag bit GET_TEMPLATE_CURRENT_LOCALE is set, the
function won't fallback to the english valiant ("<domain>.txt")
unless that locale has been requested.
The help file needs to be encoded in UTF-8, lines with a '#' in the The template file needs to be encoded in UTF-8, lines with a '#' in the
first column are comment lines and entirely ignored. Help keys are first column are comment lines and entirely ignored. Help keys are
identified by a key consisting of a single word with a single dot identified by a key consisting of a single word with a single dot
as the first character. All key lines listed without any as the first character. All key lines listed without any
intervening lines (except for comment lines) lead to the same help intervening lines (except for comment lines) lead to the same help
text. Lines following the key lines make up the actual hep texts. text. Lines following the key lines make up the actual template texts.
*/ */
char * char *
gnupg_get_help_string (const char *key, int only_current_locale) gnupg_get_template (const char *domain, const char *key, unsigned int flags)
{ {
static const char *locname; static const char *locname;
char *result; char *result;
@ -250,7 +257,7 @@ gnupg_get_help_string (const char *key, int only_current_locale)
else if (*p == '_') else if (*p == '_')
{ {
if (count++) if (count++)
*p = 0; /* Also cut at a underscore in the territory. */ *p = 0; /* Also cut at an underscore in the territory. */
} }
locname = buffer; locname = buffer;
} }
@ -259,14 +266,32 @@ gnupg_get_help_string (const char *key, int only_current_locale)
if (!key || !*key) if (!key || !*key)
return NULL; return NULL;
result = findkey_locale (key, locname, only_current_locale, result = findkey_locale (domain, key, locname,
gnupg_sysconfdir ()); gnupg_sysconfdir (), flags);
if (!result) if (!result)
result = findkey_locale (key, locname, only_current_locale, result = findkey_locale (domain, key, locname,
gnupg_datadir ()); gnupg_datadir (), flags);
if (result) if (result && (flags & GET_TEMPLATE_SUBST_ENVVARS))
{
char *tmp = substitute_envvars (result);
if (tmp)
{
xfree (result);
result = tmp;
}
}
if (result && !(flags & GET_TEMPLATE_CRLF))
trim_trailing_spaces (result); trim_trailing_spaces (result);
return result; return result;
} }
char *
gnupg_get_help_string (const char *key, int only_current)
{
return gnupg_get_template ("help", key,
only_current? GET_TEMPLATE_CURRENT_LOCALE : 0);
}

View File

@ -39,6 +39,7 @@ int
main (int argc, char **argv) main (int argc, char **argv)
{ {
char *result; char *result;
unsigned int flags = 0;
if (argc) if (argc)
{ argc--; argv++; } { argc--; argv++; }
@ -48,17 +49,35 @@ main (int argc, char **argv)
verbose = 1; verbose = 1;
argc--; argv++; argc--; argv++;
} }
if (argc && !strcmp (argv[0], "--env"))
{
flags |= GET_TEMPLATE_SUBST_ENVVARS;
argc--; argv++;
}
if (argc && !strcmp (argv[0], "--crlf"))
{
flags |= GET_TEMPLATE_CRLF;
argc--; argv++;
}
if (argc != 2)
{
fprintf (stderr, "Usage: t-helpfile [--env] [--crlf] domain key\n");
exit (2);
}
result = gnupg_get_help_string (argc? argv[0]:NULL, 0);
result = gnupg_get_template (argv[0], argv[1], flags);
if (!result) if (!result)
{ {
fprintf (stderr, fprintf (stderr,
"Error: nothing found for '%s'\n", argc?argv[0]:"(null)"); "Error: nothing found for '%s' in domain '%s'\n",
argv[1], argv[0]);
errcount++; errcount++;
} }
else else
{ {
printf ("key '%s' result='%s'\n", argc?argv[0]:"(null)", result); printf ("domain '%s' key '%s' result='%s'\n",
argv[0], argv[1], result);
xfree (result); xfree (result);
} }

View File

@ -296,6 +296,14 @@ void gnupg_set_builddir (const char *newdir);
void gnupg_rl_initialize (void); void gnupg_rl_initialize (void);
/*-- helpfile.c --*/ /*-- helpfile.c --*/
/* Bit flags for gnupg_get_template. */
#define GET_TEMPLATE_CURRENT_LOCALE 1 /* Use only the current locale. */
#define GET_TEMPLATE_SUBST_ENVVARS 2 /* Substitute environment variables. */
#define GET_TEMPLATE_CRLF 4 /* Use CR+LF. */
char *gnupg_get_template (const char *domain, const char *key,
unsigned int flags);
char *gnupg_get_help_string (const char *key, int only_current_locale); char *gnupg_get_help_string (const char *key, int only_current_locale);
/*-- localename.c --*/ /*-- localename.c --*/