~ubuntu-branches/ubuntu/oneiric/gnupg2/oneiric-updates

« back to all changes in this revision

Viewing changes to assuan/assuan-inquire.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
 
/* assuan-inquire.c - handle inquire stuff
2
 
 *      Copyright (C) 2001, 2002 Free Software Foundation, Inc.
3
 
 *
4
 
 * This file is part of Assuan.
5
 
 *
6
 
 * Assuan is free software; you can redistribute it and/or modify it
7
 
 * under the terms of the GNU Lesser General Public License as
8
 
 * published by the Free Software Foundation; either version 2.1 of
9
 
 * the License, or (at your option) any later version.
10
 
 *
11
 
 * Assuan is distributed in the hope that it will be useful, but
12
 
 * WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
 * Lesser General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU Lesser General Public
17
 
 * License along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 
19
 
 */
20
 
 
21
 
#include <config.h>
22
 
#include <stdlib.h>
23
 
#include <stdio.h>
24
 
#include <string.h>
25
 
 
26
 
#include "assuan-defs.h"
27
 
 
28
 
#define digitp(a) ((a) >= '0' && (a) <= '9')
29
 
#define xtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): \
30
 
                     *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
31
 
#define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
32
 
 
33
 
 
34
 
struct membuf {
35
 
  size_t len;
36
 
  size_t size;
37
 
  char *buf;
38
 
  int out_of_core;
39
 
  int too_large;
40
 
  size_t maxlen;
41
 
};
42
 
 
43
 
 
44
 
 
45
 
/* A simple implemnation of a dynamic buffer.  Use init_membuf() to
46
 
   create a buffer, put_membuf to append bytes and get_membuf to
47
 
   release and return the buffer.  Allocation errors are detected but
48
 
   only returned at the final get_membuf(), this helps not to clutter
49
 
   the code with out of core checks.  */
50
 
 
51
 
static void
52
 
init_membuf (struct membuf *mb, int initiallen, size_t maxlen)
53
 
{
54
 
  mb->len = 0;
55
 
  mb->size = initiallen;
56
 
  mb->out_of_core = 0;
57
 
  mb->too_large = 0;
58
 
  mb->maxlen = maxlen;
59
 
  /* we need to allocate one byte more for get_membuf */
60
 
  mb->buf = xtrymalloc (initiallen+1);
61
 
  if (!mb->buf)
62
 
      mb->out_of_core = 1;
63
 
}
64
 
 
65
 
static void
66
 
put_membuf (struct membuf *mb, const void *buf, size_t len)
67
 
{
68
 
  if (mb->out_of_core || mb->too_large)
69
 
    return;
70
 
 
71
 
  if (mb->maxlen && mb->len + len > mb->maxlen)
72
 
    {
73
 
      mb->too_large = 1;
74
 
      return;
75
 
    }
76
 
 
77
 
  if (mb->len + len >= mb->size)
78
 
    {
79
 
      char *p;
80
 
      
81
 
      mb->size += len + 1024;
82
 
      /* we need to allocate one byte more for get_membuf */
83
 
      p = xtryrealloc (mb->buf, mb->size+1);
84
 
      if (!p)
85
 
        {
86
 
          mb->out_of_core = 1;
87
 
          return;
88
 
        }
89
 
      mb->buf = p;
90
 
    }
91
 
  memcpy (mb->buf + mb->len, buf, len);
92
 
  mb->len += len;
93
 
}
94
 
 
95
 
static void *
96
 
get_membuf (struct membuf *mb, size_t *len)
97
 
{
98
 
  char *p;
99
 
 
100
 
  if (mb->out_of_core || mb->too_large)
101
 
    {
102
 
      xfree (mb->buf);
103
 
      mb->buf = NULL;
104
 
      return NULL;
105
 
    }
106
 
 
107
 
  mb->buf[mb->len] = 0; /* there is enough space for the hidden eos */
108
 
  p = mb->buf;
109
 
  *len = mb->len;
110
 
  mb->buf = NULL;
111
 
  mb->out_of_core = 1; /* don't allow a reuse */
112
 
  return p;
113
 
}
114
 
 
115
 
static void
116
 
free_membuf (struct membuf *mb)
117
 
{
118
 
  xfree (mb->buf);
119
 
  mb->buf = NULL;
120
 
}
121
 
 
122
 
 
123
 
/**
124
 
 * assuan_inquire:
125
 
 * @ctx: An assuan context
126
 
 * @keyword: The keyword used for the inquire
127
 
 * @r_buffer: Returns an allocated buffer
128
 
 * @r_length: Returns the length of this buffer
129
 
 * @maxlen: If not 0, the size limit of the inquired data.
130
 
 * 
131
 
 * A Server may use this to Send an inquire.  r_buffer, r_length and
132
 
 * maxlen may all be NULL/0 to indicate that no real data is expected.
133
 
 * 
134
 
 * Return value: 0 on success or an ASSUAN error code
135
 
 **/
136
 
AssuanError
137
 
assuan_inquire (ASSUAN_CONTEXT ctx, const char *keyword,
138
 
                char **r_buffer, size_t *r_length, size_t maxlen)
139
 
{
140
 
  AssuanError rc;
141
 
  struct membuf mb;
142
 
  char cmdbuf[100];
143
 
  unsigned char *line, *p;
144
 
  int linelen;
145
 
  int nodataexpected;
146
 
 
147
 
  if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf)))
148
 
    return ASSUAN_Invalid_Value;
149
 
  nodataexpected = !r_buffer && !r_length && !maxlen;
150
 
  if (!nodataexpected && (!r_buffer || !r_length))
151
 
    return ASSUAN_Invalid_Value;
152
 
  if (!ctx->is_server)
153
 
    return ASSUAN_Not_A_Server;
154
 
  if (ctx->in_inquire)
155
 
    return ASSUAN_Nested_Commands;
156
 
  
157
 
  ctx->in_inquire = 1;
158
 
  if (nodataexpected)
159
 
    memset (&mb, 0, sizeof mb); /* avoid compiler warnings */
160
 
  else
161
 
    init_membuf (&mb, maxlen? maxlen:1024, maxlen);
162
 
 
163
 
  strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword);
164
 
  rc = assuan_write_line (ctx, cmdbuf);
165
 
  if (rc)
166
 
    goto leave;
167
 
 
168
 
  for (;;)
169
 
    {
170
 
      do 
171
 
        {
172
 
          rc = _assuan_read_line (ctx);
173
 
          if (rc)
174
 
            goto leave;
175
 
          line = ctx->inbound.line;
176
 
          linelen = ctx->inbound.linelen;
177
 
        }    
178
 
      while (*line == '#' || !linelen);
179
 
      if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
180
 
          && (!line[3] || line[3] == ' '))
181
 
        break; /* END command received*/
182
 
      if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N')
183
 
        {
184
 
          rc = ASSUAN_Canceled;
185
 
          goto leave;
186
 
        }
187
 
      if (line[0] != 'D' || line[1] != ' ' || nodataexpected)
188
 
        {
189
 
          rc = ASSUAN_Unexpected_Command;
190
 
          goto leave;
191
 
        }
192
 
      if (linelen < 3)
193
 
        continue;
194
 
      line += 2;
195
 
      linelen -= 2;
196
 
 
197
 
      p = line;
198
 
      while (linelen)
199
 
        {
200
 
          for (;linelen && *p != '%'; linelen--, p++)
201
 
            ;
202
 
          put_membuf (&mb, line, p-line);
203
 
          if (linelen > 2)
204
 
            { /* handle escaping */
205
 
              unsigned char tmp[1];
206
 
              p++;
207
 
              *tmp = xtoi_2 (p);
208
 
              p += 2;
209
 
              linelen -= 3;
210
 
              put_membuf (&mb, tmp, 1);
211
 
            }
212
 
          line = p;
213
 
        }
214
 
      if (mb.too_large)
215
 
        {
216
 
          rc = ASSUAN_Too_Much_Data;
217
 
          goto leave;
218
 
        }
219
 
    }
220
 
 
221
 
  if (!nodataexpected)
222
 
    {
223
 
      *r_buffer = get_membuf (&mb, r_length);
224
 
      if (!*r_buffer)
225
 
        rc = ASSUAN_Out_Of_Core;
226
 
    }
227
 
 
228
 
 leave:
229
 
  if (!nodataexpected)
230
 
    free_membuf (&mb);
231
 
  ctx->in_inquire = 0;
232
 
  return rc;
233
 
}
234
 
 
235
 
 
236
 
 
237
 
 
238
 
 
239