~ubuntu-branches/ubuntu/karmic/gnupg2/karmic-security

« back to all changes in this revision

Viewing changes to common/helpfile.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-10-04 10:25:53 UTC
  • mfrom: (5.1.15 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081004102553-fv62pp8dsitxli47
Tags: 2.0.9-3.1
* Non-maintainer upload.
* agent/gpg-agent.c: Deinit the threading library before exec'ing
  the command to run in --daemon mode. And because that still doesn't
  restore the sigprocmask, do that manually. Closes: #499569

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* helpfile.c - GnuPG's helpfile feature
 
2
 *      Copyright (C) 2007 Free Software Foundation, Inc.
 
3
 *
 
4
 * This file is part of GnuPG.
 
5
 *
 
6
 * GnuPG is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 3 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * GnuPG is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
#include <config.h>
 
21
#include <stdlib.h>
 
22
 
 
23
 
 
24
#include "util.h"
 
25
#include "i18n.h"
 
26
#include "membuf.h"
 
27
 
 
28
 
 
29
/* Try to find KEY in the file FNAME.  */
 
30
static char *
 
31
findkey_fname (const char *key, const char *fname)
 
32
{
 
33
  gpg_error_t err = 0;
 
34
  FILE *fp;
 
35
  int lnr = 0;
 
36
  int c;
 
37
  char *p, line[256];
 
38
  int in_item = 0;
 
39
  membuf_t mb = MEMBUF_ZERO;
 
40
 
 
41
  fp = fopen (fname, "r");
 
42
  if (!fp)
 
43
    {
 
44
      if (errno != ENOENT)
 
45
        {
 
46
          err = gpg_error_from_syserror ();
 
47
          log_error (_("can't open `%s': %s\n"), fname, gpg_strerror (err));
 
48
        }
 
49
      return NULL;
 
50
    }
 
51
 
 
52
  while (fgets (line, DIM(line)-1, fp))
 
53
    {
 
54
      lnr++;
 
55
      
 
56
      if (!*line || line[strlen(line)-1] != '\n')
 
57
        {
 
58
          /* Eat until end of line. */
 
59
          while ( (c=getc (fp)) != EOF && c != '\n')
 
60
            ;
 
61
          err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG
 
62
                           : GPG_ERR_INCOMPLETE_LINE);
 
63
          log_error (_("file `%s', line %d: %s\n"),
 
64
                     fname, lnr, gpg_strerror (err));
 
65
        }
 
66
      else
 
67
        line[strlen(line)-1] = 0; /* Chop the LF. */
 
68
      
 
69
    again:
 
70
      if (!in_item)
 
71
        {
 
72
          /* Allow for empty lines and spaces while not in an item. */
 
73
          for (p=line; spacep (p); p++)
 
74
            ;
 
75
          if (!*p || *p == '#')
 
76
            continue;
 
77
          if (*line != '.' || spacep(line+1))
 
78
            {
 
79
              log_info (_("file `%s', line %d: %s\n"),
 
80
                        fname, lnr, _("ignoring garbage line"));
 
81
              continue;
 
82
            }
 
83
          trim_trailing_spaces (line);
 
84
          in_item = 1;
 
85
          if (!strcmp (line+1, key))
 
86
            {
 
87
              /* Found.  Start collecting.  */
 
88
              init_membuf (&mb, 1024);
 
89
            }
 
90
          continue;
 
91
        }
 
92
 
 
93
      /* If in an item only allow for comments in the first column
 
94
         and provide ". " as an escape sequence to allow for
 
95
         leading dots and hash marks in the actual text.  */
 
96
      if (*line == '#')
 
97
        continue;
 
98
      if (*line == '.')
 
99
        { 
 
100
          if (spacep(line+1))
 
101
            p = line + 2;
 
102
          else
 
103
            {
 
104
              trim_trailing_spaces (line);
 
105
              in_item = 0;
 
106
              if (is_membuf_ready (&mb))
 
107
                break;        /* Yep, found and collected the item.  */
 
108
              if (!line[1])
 
109
                continue;     /* Just an end of text dot. */
 
110
              goto again;     /* A new key line.  */
 
111
            }
 
112
        }
 
113
      else
 
114
        p = line;
 
115
 
 
116
      if (is_membuf_ready (&mb))
 
117
        {
 
118
          put_membuf_str (&mb, p);
 
119
          put_membuf (&mb, "\n", 1);
 
120
        }
 
121
 
 
122
    }
 
123
  if ( !err && ferror (fp) )
 
124
    {
 
125
      err = gpg_error_from_syserror ();
 
126
      log_error (_("error reading `%s', line %d: %s\n"),
 
127
                 fname, lnr, gpg_strerror (err));
 
128
    }
 
129
  
 
130
  fclose (fp);
 
131
  if (is_membuf_ready (&mb))
 
132
    {
 
133
      /* We have collected something.  */
 
134
      if (err)
 
135
        {
 
136
          xfree (get_membuf (&mb, NULL));
 
137
          return NULL;
 
138
        }
 
139
      else
 
140
        {
 
141
          put_membuf (&mb, "", 1);  /* Terminate string.  */
 
142
          return get_membuf (&mb, NULL);
 
143
        }
 
144
    }
 
145
  else
 
146
    return NULL;
 
147
}
 
148
 
 
149
 
 
150
/* Try the help files depending on the locale.  */
 
151
static char *
 
152
findkey_locale (const char *key, const char *locname,
 
153
                int only_current_locale, const char *dirname)
 
154
{
 
155
  const char *s;
 
156
  char *fname, *ext, *p;
 
157
  char *result;
 
158
 
 
159
  fname = xtrymalloc (strlen (dirname) + 6 + strlen (locname) + 4 + 1);
 
160
  if (!fname)
 
161
    return NULL;
 
162
  ext = stpcpy (stpcpy (fname, dirname), "/help.");
 
163
  /* Search with locale name and territory.  ("help.LL_TT.txt") */
 
164
  if (strchr (locname, '_'))
 
165
    {
 
166
      strcpy (stpcpy (ext, locname), ".txt");
 
167
      result = findkey_fname (key, fname);
 
168
    }
 
169
  else
 
170
    result = NULL;  /* No territory.  */
 
171
 
 
172
  if (!result)
 
173
    {
 
174
      /* Search with just the locale name - if any. ("help.LL.txt") */
 
175
      if (*locname)
 
176
        {
 
177
          for (p=ext, s=locname; *s && *s != '_';)
 
178
            *p++ = *s++;
 
179
          strcpy (p, ".txt");
 
180
          result = findkey_fname (key, fname);
 
181
        }
 
182
      else
 
183
        result = NULL;
 
184
    }
 
185
  
 
186
  if (!result && (!only_current_locale || !*locname) )
 
187
    {
 
188
      /* Last try: Search in file without any locale info.  ("help.txt") */
 
189
      strcpy (ext, "txt");
 
190
      result = findkey_fname (key, fname);
 
191
    }
 
192
 
 
193
  xfree (fname);
 
194
  return result;
 
195
}
 
196
 
 
197
 
 
198
/* Return a malloced help text as identified by KEY.  The system takes
 
199
   the string from an UTF-8 encoded file to be created by an
 
200
   administrator or as distributed with GnuPG.  On a GNU or Unix
 
201
   system the entry is searched in these files:
 
202
 
 
203
     /etc/gnupg/help.LL.txt
 
204
     /etc/gnupg/help.txt
 
205
     /usr/share/gnupg/help.LL.txt
 
206
     /usr/share/gnupg/help.txt
 
207
     
 
208
   Here LL denotes the two digit language code of the current locale.
 
209
   If ONLY_CURRENT_LOCALE is set, the fucntion won;t fallback to the
 
210
   english valiant ("help.txt") unless that locale has been requested.
 
211
   
 
212
   The help file needs to be encoded in UTF-8, lines with a '#' in the
 
213
   first column are comment lines and entirely ignored.  Help keys are
 
214
   identified by a key consisting of a single word with a single dot
 
215
   as the first character.  All key lines listed without any
 
216
   intervening lines (except for comment lines) lead to the same help
 
217
   text.  Lines following the key lines make up the actual hep texts.
 
218
   
 
219
*/
 
220
 
 
221
char *
 
222
gnupg_get_help_string (const char *key, int only_current_locale)
 
223
{
 
224
  static const char *locname;
 
225
  char *result;
 
226
 
 
227
  if (!locname)
 
228
    {
 
229
      char *buffer, *p;
 
230
      int count = 0;
 
231
      const char *s = gnupg_messages_locale_name ();
 
232
      buffer = xtrystrdup (s);
 
233
      if (!buffer)
 
234
        locname = "";
 
235
      else
 
236
        {
 
237
          for (p = buffer; *p; p++)
 
238
            if (*p == '.' || *p == '@' || *p == '/' /*(safeguard)*/)
 
239
              *p = 0;
 
240
            else if (*p == '_')
 
241
              {
 
242
                if (count++)
 
243
                  *p = 0;  /* Also cut at a underscore in the territory.  */
 
244
              }
 
245
          locname = buffer;
 
246
        }
 
247
    }
 
248
 
 
249
  if (!key || !*key)
 
250
    return NULL;
 
251
 
 
252
  result = findkey_locale (key, locname, only_current_locale, 
 
253
                           gnupg_sysconfdir ());
 
254
  if (!result)
 
255
    result = findkey_locale (key, locname, only_current_locale,
 
256
                             gnupg_datadir ());
 
257
 
 
258
  if (result)
 
259
    trim_trailing_spaces (result);
 
260
 
 
261
  return result;
 
262
}