1
/* assuan-buffer.c - read and send data
2
* Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4
* This file is part of Assuan.
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22
/* Please note that this is a stripped down and modified version of
23
the orginal Assuan code from libassuan. */
33
#ifdef HAVE_W32_SYSTEM
36
#include "assuan-defs.h"
39
void *memrchr(const void *s, int c, size_t n);
43
writen (assuan_context_t ctx, const char *buffer, size_t length)
47
ssize_t nwritten = ctx->io->writefnc (ctx, buffer, length);
53
return -1; /* write error */
61
/* Read an entire line. */
63
readaline (assuan_context_t ctx, char *buf, size_t buflen,
64
int *r_nread, int *r_eof)
66
size_t nleft = buflen;
73
ssize_t n = ctx->io->readfnc (ctx, buf, nleft);
79
return -1; /* read error */
84
break; /* allow incomplete lines */
91
p = memrchr (p, '\n', n);
93
break; /* at least one full line available - that's enough for now */
101
_assuan_read_line (assuan_context_t ctx)
103
char *line = ctx->inbound.line;
108
if (ctx->inbound.eof)
111
atticlen = ctx->inbound.attic.linelen;
114
memcpy (line, ctx->inbound.attic.line, atticlen);
115
ctx->inbound.attic.linelen = 0;
117
endp = memchr (line, '\n', atticlen);
119
/* Found another line in the attic. */
126
/* There is pending data but not a full line. */
128
assert (atticlen < LINELENGTH);
129
rc = readaline (ctx, line + atticlen,
130
LINELENGTH - atticlen, &nread, &ctx->inbound.eof);
134
/* No pending data. */
135
rc = readaline (ctx, line, LINELENGTH,
136
&nread, &ctx->inbound.eof);
140
fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [Error: %s]\n",
141
assuan_get_assuan_log_prefix (),
142
(unsigned int)getpid (), ctx, strerror (errno));
143
return ASSUAN_Read_Error;
147
assert (ctx->inbound.eof);
149
fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [EOF]\n",
150
assuan_get_assuan_log_prefix (),
151
(unsigned int)getpid (), ctx);
155
ctx->inbound.attic.pending = 0;
159
endp = memchr (line, '\n', nread);
163
int n = endp - line + 1;
165
/* LINE contains more than one line. We copy it to the attic
166
now as handlers are allowed to modify the passed
170
memcpy (ctx->inbound.attic.line, endp + 1, len);
171
ctx->inbound.attic.pending = memrchr (endp + 1, '\n', len) ? 1 : 0;
172
ctx->inbound.attic.linelen = len;
175
if (endp != line && endp[-1] == '\r')
179
ctx->inbound.linelen = endp - line;
182
fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- ",
183
assuan_get_assuan_log_prefix (),
184
(unsigned int)getpid (), ctx);
185
if (ctx->confidential)
186
fputs ("[Confidential data not shown]", ctx->log_fp);
188
_assuan_log_print_buffer (ctx->log_fp,
190
ctx->inbound.linelen);
191
putc ('\n', ctx->log_fp);
198
fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [Invalid line]\n",
199
assuan_get_assuan_log_prefix (),
200
(unsigned int)getpid (), ctx);
202
ctx->inbound.linelen = 0;
203
return ctx->inbound.eof ? ASSUAN_Line_Not_Terminated
204
: ASSUAN_Line_Too_Long;
209
/* Read the next line from the client or server and return a pointer
210
in *LINE to a buffer holding the line. LINELEN is the length of
211
*LINE. The buffer is valid until the next read operation on it.
212
The caller may modify the buffer. The buffer is invalid (i.e. must
213
not be used) if an error is returned.
215
Returns 0 on success or an assuan error code.
216
See also: assuan_pending_line().
219
assuan_read_line (assuan_context_t ctx, char **line, size_t *linelen)
224
return ASSUAN_Invalid_Value;
226
err = _assuan_read_line (ctx);
227
*line = ctx->inbound.line;
228
*linelen = ctx->inbound.linelen;
233
/* Return true if a full line is buffered (i.e. an entire line may be
234
read without any I/O). */
236
assuan_pending_line (assuan_context_t ctx)
238
return ctx && ctx->inbound.attic.pending;
243
_assuan_write_line (assuan_context_t ctx, const char *prefix,
244
const char *line, size_t len)
247
size_t prefixlen = prefix? strlen (prefix):0;
249
/* Make sure that the line is short enough. */
250
if (len + prefixlen + 2 > ASSUAN_LINELENGTH)
253
fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> "
254
"[supplied line too long -truncated]\n",
255
assuan_get_assuan_log_prefix (),
256
(unsigned int)getpid (), ctx);
259
if (len > ASSUAN_LINELENGTH - prefixlen - 2)
260
len = ASSUAN_LINELENGTH - prefixlen - 2 - 1;
263
/* Fixme: we should do some kind of line buffering. */
266
fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ",
267
assuan_get_assuan_log_prefix (),
268
(unsigned int)getpid (), ctx);
269
if (ctx->confidential)
270
fputs ("[Confidential data not shown]", ctx->log_fp);
272
_assuan_log_print_buffer (ctx->log_fp, line, len);
273
putc ('\n', ctx->log_fp);
278
rc = writen (ctx, prefix, prefixlen);
280
rc = ASSUAN_Write_Error;
284
rc = writen (ctx, line, len);
286
rc = ASSUAN_Write_Error;
289
rc = writen (ctx, "\n", 1);
291
rc = ASSUAN_Write_Error;
299
assuan_write_line (assuan_context_t ctx, const char *line)
305
return ASSUAN_Invalid_Value;
307
/* Make sure that we never take a LF from the user - this might
308
violate the protocol. */
309
s = strchr (line, '\n');
310
len = s? (s-line) : strlen (line);
312
if (ctx->log_fp && s)
313
fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> "
314
"[supplied line contained a LF -truncated]\n",
315
assuan_get_assuan_log_prefix (),
316
(unsigned int)getpid (), ctx);
318
return _assuan_write_line (ctx, NULL, line, len);
323
/* Write out the data in buffer as datalines with line wrapping and
324
percent escaping. This function is used for GNU's custom streams */
326
_assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
328
assuan_context_t ctx = cookie;
329
size_t size = orig_size;
333
if (ctx->outbound.data.error)
336
line = ctx->outbound.data.line;
337
linelen = ctx->outbound.data.linelen;
341
/* insert data line header */
349
/* copy data, keep some space for the CRLF and to escape one character */
350
while (size && linelen < LINELENGTH-2-2)
352
if (*buffer == '%' || *buffer == '\r' || *buffer == '\n')
354
sprintf (line, "%%%02X", *(unsigned char*)buffer);
367
if (linelen >= LINELENGTH-2-2)
371
fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ",
372
assuan_get_assuan_log_prefix (),
373
(unsigned int)getpid (), ctx);
375
if (ctx->confidential)
376
fputs ("[Confidential data not shown]", ctx->log_fp);
378
_assuan_log_print_buffer (ctx->log_fp,
379
ctx->outbound.data.line,
381
putc ('\n', ctx->log_fp);
385
if (writen (ctx, ctx->outbound.data.line, linelen))
387
ctx->outbound.data.error = ASSUAN_Write_Error;
390
line = ctx->outbound.data.line;
395
ctx->outbound.data.linelen = linelen;
396
return (int)orig_size;
400
/* Write out any buffered data
401
This function is used for GNU's custom streams */
403
_assuan_cookie_write_flush (void *cookie)
405
assuan_context_t ctx = cookie;
409
if (ctx->outbound.data.error)
412
line = ctx->outbound.data.line;
413
linelen = ctx->outbound.data.linelen;
419
fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ",
420
assuan_get_assuan_log_prefix (),
421
(unsigned int)getpid (), ctx);
422
if (ctx->confidential)
423
fputs ("[Confidential data not shown]", ctx->log_fp);
425
_assuan_log_print_buffer (ctx->log_fp,
426
ctx->outbound.data.line, linelen);
427
putc ('\n', ctx->log_fp);
431
if (writen (ctx, ctx->outbound.data.line, linelen))
433
ctx->outbound.data.error = ASSUAN_Write_Error;
436
ctx->outbound.data.linelen = 0;
444
* @ctx: An assuan context
445
* @buffer: Data to send or NULL to flush
446
* @length: length of the data to send/
448
* This function may be used by the server or the client to send data
449
* lines. The data will be escaped as required by the Assuan protocol
450
* and may get buffered until a line is full. To force sending the
451
* data out @buffer may be passed as NULL (in which case @length must
452
* also be 0); however when used by a client this flush operation does
453
* also send the terminating "END" command to terminate the reponse on
454
* a INQUIRE response. However, when assuan_transact() is used, this
455
* function takes care of sending END itself.
457
* Return value: 0 on success or an error code
461
assuan_send_data (assuan_context_t ctx, const void *buffer, size_t length)
464
return ASSUAN_Invalid_Value;
465
if (!buffer && length)
466
return ASSUAN_Invalid_Value;
469
{ /* flush what we have */
470
_assuan_cookie_write_flush (ctx);
471
if (ctx->outbound.data.error)
472
return ctx->outbound.data.error;
474
return assuan_write_line (ctx, "END");
478
_assuan_cookie_write_data (ctx, buffer, length);
479
if (ctx->outbound.data.error)
480
return ctx->outbound.data.error;