1
/* assuan-buffer.c - read and send data
2
* Copyright (C) 2001, 2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
28
#include "assuan-defs.h"
30
#ifdef HAVE_JNLIB_LOGGING
31
#include "../jnlib/logging.h"
38
#ifdef HAVE_JNLIB_LOGGING
39
return log_get_prefix (NULL);
47
writen ( int fd, const char *buffer, size_t length )
51
int nwritten = _assuan_write_wrapper?
52
_assuan_write_wrapper (fd, buffer, length):
53
write (fd, buffer, length);
59
return -1; /* write error */
67
/* read an entire line */
69
readline (int fd, char *buf, size_t buflen, int *r_nread, int *eof)
71
size_t nleft = buflen;
78
int n = _assuan_read_wrapper?
79
_assuan_read_wrapper (fd, buf, nleft):
80
read (fd, buf, nleft);
86
return -1; /* read error */
91
break; /* allow incomplete lines */
98
for (; n && *p != '\n'; n--, p++)
101
break; /* at least one full line available - that's enough for now */
109
_assuan_read_line (ASSUAN_CONTEXT ctx)
111
char *line = ctx->inbound.line;
112
int n, nread, atticlen;
115
if (ctx->inbound.eof)
118
atticlen = ctx->inbound.attic.linelen;
121
memcpy (line, ctx->inbound.attic.line, atticlen);
122
ctx->inbound.attic.linelen = 0;
123
for (n=0; n < atticlen && line[n] != '\n'; n++)
127
rc = 0; /* found another line in the attic */
132
{ /* read the rest */
133
assert (atticlen < LINELENGTH);
134
rc = readline (ctx->inbound.fd, line + atticlen,
135
LINELENGTH - atticlen, &nread, &ctx->inbound.eof);
139
rc = readline (ctx->inbound.fd, line, LINELENGTH,
140
&nread, &ctx->inbound.eof);
144
fprintf (ctx->log_fp, "%s[%p] <- [Error: %s]\n",
145
my_log_prefix (), ctx, strerror (errno));
146
return ASSUAN_Read_Error;
150
assert (ctx->inbound.eof);
152
fprintf (ctx->log_fp, "%s[%p] <- [EOF]\n", my_log_prefix (),ctx);
156
ctx->inbound.attic.pending = 0;
158
for (n=0; n < nread; n++)
168
/* we have to copy the rest because the handlers are
169
allowed to modify the passed buffer */
170
for (d=ctx->inbound.attic.line, s=line+n, i=nread-n; i; i--)
173
ctx->inbound.attic.pending = 1;
176
ctx->inbound.attic.linelen = nread-n;
179
if (n && line[n-1] == '\r')
182
ctx->inbound.linelen = n;
185
fprintf (ctx->log_fp, "%s[%p] <- ", my_log_prefix (), ctx);
186
if (ctx->confidential)
187
fputs ("[Confidential data not shown]", ctx->log_fp);
189
_assuan_log_print_buffer (ctx->log_fp,
191
ctx->inbound.linelen);
192
putc ('\n', ctx->log_fp);
199
fprintf (ctx->log_fp, "%s[%p] <- [Invalid line]\n", my_log_prefix (), ctx);
201
ctx->inbound.linelen = 0;
202
return ctx->inbound.eof? ASSUAN_Line_Not_Terminated : ASSUAN_Line_Too_Long;
206
/* Read the next line from the client or server and return a pointer
207
to a buffer with holding that line. linelen returns the length of
208
the line. This buffer is valid until another read operation is
209
done on this buffer. The caller is allowed to modify this buffer.
210
He should only use the buffer if the function returns without an
213
Returns: 0 on success or an assuan error code
214
See also: assuan_pending_line().
217
assuan_read_line (ASSUAN_CONTEXT ctx, char **line, size_t *linelen)
222
return ASSUAN_Invalid_Value;
224
err = _assuan_read_line (ctx);
225
*line = ctx->inbound.line;
226
*linelen = ctx->inbound.linelen;
231
/* Return true when a full line is pending for a read, without the need
234
assuan_pending_line (ASSUAN_CONTEXT ctx)
236
return ctx && ctx->inbound.attic.pending;
241
assuan_write_line (ASSUAN_CONTEXT ctx, const char *line )
248
return ASSUAN_Invalid_Value;
250
/* Make sure that we never take a LF from the user - this might
251
violate the protocol. */
252
s = strchr (line, '\n');
253
len = s? (s-line) : strlen (line);
255
/* fixme: we should do some kind of line buffering. */
258
fprintf (ctx->log_fp, "%s[%p] -> ", my_log_prefix (), ctx);
260
fputs ("[supplied line contained a LF]", ctx->log_fp);
261
if (ctx->confidential)
262
fputs ("[Confidential data not shown]", ctx->log_fp);
264
_assuan_log_print_buffer (ctx->log_fp, line, len);
265
putc ('\n', ctx->log_fp);
268
rc = writen (ctx->outbound.fd, line, len);
270
rc = ASSUAN_Write_Error;
273
rc = writen (ctx->outbound.fd, "\n", 1);
275
rc = ASSUAN_Write_Error;
283
/* Write out the data in buffer as datalines with line wrapping and
284
percent escaping. This fucntion is used for GNU's custom streams */
286
_assuan_cookie_write_data (void *cookie, const char *buffer, size_t size)
288
ASSUAN_CONTEXT ctx = cookie;
292
if (ctx->outbound.data.error)
295
line = ctx->outbound.data.line;
296
linelen = ctx->outbound.data.linelen;
300
/* insert data line header */
308
/* copy data, keep some space for the CRLF and to escape one character */
309
while (size && linelen < LINELENGTH-2-2)
311
if (*buffer == '%' || *buffer == '\r' || *buffer == '\n')
313
sprintf (line, "%%%02X", *(unsigned char*)buffer);
326
if (linelen >= LINELENGTH-2-2)
330
fprintf (ctx->log_fp, "%s[%p] -> ", my_log_prefix (), ctx);
331
if (ctx->confidential)
332
fputs ("[Confidential data not shown]", ctx->log_fp);
334
_assuan_log_print_buffer (ctx->log_fp,
335
ctx->outbound.data.line,
337
putc ('\n', ctx->log_fp);
341
if (writen (ctx->outbound.fd, ctx->outbound.data.line, linelen))
343
ctx->outbound.data.error = ASSUAN_Write_Error;
346
line = ctx->outbound.data.line;
351
ctx->outbound.data.linelen = linelen;
356
/* Write out any buffered data
357
This fucntion is used for GNU's custom streams */
359
_assuan_cookie_write_flush (void *cookie)
361
ASSUAN_CONTEXT ctx = cookie;
365
if (ctx->outbound.data.error)
368
line = ctx->outbound.data.line;
369
linelen = ctx->outbound.data.linelen;
375
fprintf (ctx->log_fp, "%s[%p] -> ", my_log_prefix (), ctx);
376
if (ctx->confidential)
377
fputs ("[Confidential data not shown]", ctx->log_fp);
379
_assuan_log_print_buffer (ctx->log_fp,
380
ctx->outbound.data.line,
382
putc ('\n', ctx->log_fp);
386
if (writen (ctx->outbound.fd, ctx->outbound.data.line, linelen))
388
ctx->outbound.data.error = ASSUAN_Write_Error;
391
ctx->outbound.data.linelen = 0;
399
* @ctx: An assuan context
400
* @buffer: Data to send or NULL to flush
401
* @length: length of the data to send/
403
* This function may be used by the server or the client to send data
404
* lines. The data will be escaped as required by the Assuan protocol
405
* and may get buffered until a line is full. To force sending the
406
* data out @buffer may be passed as NULL (in which case @length must
407
* also be 0); however when used by a client this flush operation does
408
* also send the terminating "END" command to terminate the reponse on
409
* a INQUIRE response. However, when assuan_transact() is used, this
410
* function takes care of sending END itself.
412
* Return value: 0 on success or an error code
416
assuan_send_data (ASSUAN_CONTEXT ctx, const void *buffer, size_t length)
419
return ASSUAN_Invalid_Value;
420
if (!buffer && length)
421
return ASSUAN_Invalid_Value;
424
{ /* flush what we have */
425
_assuan_cookie_write_flush (ctx);
426
if (ctx->outbound.data.error)
427
return ctx->outbound.data.error;
429
return assuan_write_line (ctx, "END");
433
_assuan_cookie_write_data (ctx, buffer, length);
434
if (ctx->outbound.data.error)
435
return ctx->outbound.data.error;