1 /* helpfile.c - GnuPG's helpfile feature
2 * Copyright (C) 2007 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * This file is free software; you can redistribute it and/or modify
7 * it under the terms of either
9 * - the GNU Lesser General Public License as published by the Free
10 * Software Foundation; either version 3 of the License, or (at
11 * your option) any later version.
15 * - the GNU General Public License as published by the Free
16 * Software Foundation; either version 2 of the License, or (at
17 * your option) any later version.
19 * or both in parallel, as here.
21 * This file is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, see <https://www.gnu.org/licenses/>.
39 /* Try to find KEY in the file FNAME. */
41 findkey_fname (const char *key, const char *fname)
49 membuf_t mb = MEMBUF_ZERO;
51 fp = fopen (fname, "r");
56 err = gpg_error_from_syserror ();
57 log_error (_("can't open '%s': %s\n"), fname, gpg_strerror (err));
62 while (fgets (line, DIM(line)-1, fp))
66 if (!*line || line[strlen(line)-1] != '\n')
68 /* Eat until end of line. */
69 while ( (c=getc (fp)) != EOF && c != '\n')
71 err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG
72 : GPG_ERR_INCOMPLETE_LINE);
73 log_error (_("file '%s', line %d: %s\n"),
74 fname, lnr, gpg_strerror (err));
77 line[strlen(line)-1] = 0; /* Chop the LF. */
82 /* Allow for empty lines and spaces while not in an item. */
83 for (p=line; spacep (p); p++)
87 if (*line != '.' || spacep(line+1))
89 log_info (_("file '%s', line %d: %s\n"),
90 fname, lnr, _("ignoring garbage line"));
93 trim_trailing_spaces (line);
95 if (!strcmp (line+1, key))
97 /* Found. Start collecting. */
98 init_membuf (&mb, 1024);
103 /* If in an item only allow for comments in the first column
104 and provide ". " as an escape sequence to allow for
105 leading dots and hash marks in the actual text. */
114 trim_trailing_spaces (line);
116 if (is_membuf_ready (&mb))
117 break; /* Yep, found and collected the item. */
119 continue; /* Just an end of text dot. */
120 goto again; /* A new key line. */
126 if (is_membuf_ready (&mb))
128 put_membuf_str (&mb, p);
129 put_membuf (&mb, "\n", 1);
133 if ( !err && ferror (fp) )
135 err = gpg_error_from_syserror ();
136 log_error (_("error reading '%s', line %d: %s\n"),
137 fname, lnr, gpg_strerror (err));
141 if (is_membuf_ready (&mb))
143 /* We have collected something. */
146 xfree (get_membuf (&mb, NULL));
151 put_membuf (&mb, "", 1); /* Terminate string. */
152 return get_membuf (&mb, NULL);
160 /* Try the help files depending on the locale. */
162 findkey_locale (const char *key, const char *locname,
163 int only_current_locale, const char *dirname)
166 char *fname, *ext, *p;
169 fname = xtrymalloc (strlen (dirname) + 6 + strlen (locname) + 4 + 1);
172 ext = stpcpy (stpcpy (fname, dirname), "/help.");
173 /* Search with locale name and territory. ("help.LL_TT.txt") */
174 if (strchr (locname, '_'))
176 strcpy (stpcpy (ext, locname), ".txt");
177 result = findkey_fname (key, fname);
180 result = NULL; /* No territory. */
184 /* Search with just the locale name - if any. ("help.LL.txt") */
187 for (p=ext, s=locname; *s && *s != '_';)
190 result = findkey_fname (key, fname);
196 if (!result && (!only_current_locale || !*locname) )
198 /* Last try: Search in file without any locale info. ("help.txt") */
200 result = findkey_fname (key, fname);
208 /* Return a malloced help text as identified by KEY. The system takes
209 the string from an UTF-8 encoded file to be created by an
210 administrator or as distributed with GnuPG. On a GNU or Unix
211 system the entry is searched in these files:
213 /etc/gnupg/help.LL.txt
215 /usr/share/gnupg/help.LL.txt
216 /usr/share/gnupg/help.txt
218 Here LL denotes the two digit language code of the current locale.
219 If ONLY_CURRENT_LOCALE is set, the function won't fallback to the
220 english valiant ("help.txt") unless that locale has been requested.
222 The help file needs to be encoded in UTF-8, lines with a '#' in the
223 first column are comment lines and entirely ignored. Help keys are
224 identified by a key consisting of a single word with a single dot
225 as the first character. All key lines listed without any
226 intervening lines (except for comment lines) lead to the same help
227 text. Lines following the key lines make up the actual hep texts.
232 gnupg_get_help_string (const char *key, int only_current_locale)
234 static const char *locname;
241 const char *s = gnupg_messages_locale_name ();
242 buffer = xtrystrdup (s);
247 for (p = buffer; *p; p++)
248 if (*p == '.' || *p == '@' || *p == '/' /*(safeguard)*/)
253 *p = 0; /* Also cut at a underscore in the territory. */
262 result = findkey_locale (key, locname, only_current_locale,
263 gnupg_sysconfdir ());
265 result = findkey_locale (key, locname, only_current_locale,
269 trim_trailing_spaces (result);