mirror of
git://git.gnupg.org/gnupg.git
synced 2025-03-26 22:29:58 +01:00
Added code for data lines. For ease of implementation we need glibc
(custom streams).
This commit is contained in:
parent
0b17666145
commit
ff1ba2fdc7
@ -149,3 +149,99 @@ _assuan_write_line (ASSUAN_CONTEXT ctx, const char *line )
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Write out the data in buffer as datalines with line wrapping and
|
||||||
|
percent escaping. This fucntion is used for GNU's custom streams */
|
||||||
|
int
|
||||||
|
_assuan_cookie_write_data (void *cookie, const char *buffer, size_t size)
|
||||||
|
{
|
||||||
|
ASSUAN_CONTEXT ctx = cookie;
|
||||||
|
char *line;
|
||||||
|
size_t linelen;
|
||||||
|
|
||||||
|
if (ctx->outbound.data.error)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
line = ctx->outbound.data.line;
|
||||||
|
linelen = ctx->outbound.data.linelen;
|
||||||
|
line += linelen;
|
||||||
|
while (size)
|
||||||
|
{
|
||||||
|
/* insert data line header */
|
||||||
|
if (!linelen)
|
||||||
|
{
|
||||||
|
*line++ = 'D';
|
||||||
|
*line++ = ' ';
|
||||||
|
linelen += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy data, keep some space for the CRLF and to escape one character */
|
||||||
|
while (size && linelen < LINELENGTH-2-2)
|
||||||
|
{
|
||||||
|
if (*buffer == '%' || *buffer == '\r' || *buffer == '\n')
|
||||||
|
{
|
||||||
|
sprintf (line, "%%%02X", *(unsigned char*)buffer);
|
||||||
|
line += 3;
|
||||||
|
linelen += 3;
|
||||||
|
buffer++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*line++ = *buffer++;
|
||||||
|
linelen++;
|
||||||
|
}
|
||||||
|
size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linelen >= LINELENGTH-2-2)
|
||||||
|
{
|
||||||
|
*line++ = '\n';
|
||||||
|
linelen++;
|
||||||
|
if (writen (ctx->outbound.fd, ctx->outbound.data.line, linelen))
|
||||||
|
{
|
||||||
|
ctx->outbound.data.error = ASSUAN_Write_Error;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
line = ctx->outbound.data.line;
|
||||||
|
linelen = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->outbound.data.linelen = linelen;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Write out any buffered data
|
||||||
|
This fucntion is used for GNU's custom streams */
|
||||||
|
int
|
||||||
|
_assuan_cookie_write_flush (void *cookie)
|
||||||
|
{
|
||||||
|
ASSUAN_CONTEXT ctx = cookie;
|
||||||
|
char *line;
|
||||||
|
size_t linelen;
|
||||||
|
|
||||||
|
if (ctx->outbound.data.error)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
line = ctx->outbound.data.line;
|
||||||
|
linelen = ctx->outbound.data.linelen;
|
||||||
|
line += linelen;
|
||||||
|
if (linelen)
|
||||||
|
{
|
||||||
|
*line++ = '\n';
|
||||||
|
linelen++;
|
||||||
|
if (writen (ctx->outbound.fd, ctx->outbound.data.line, linelen))
|
||||||
|
{
|
||||||
|
ctx->outbound.data.error = ASSUAN_Write_Error;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ctx->outbound.data.linelen = 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,6 +49,12 @@ struct assuan_context_s {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
int fd;
|
int fd;
|
||||||
|
struct {
|
||||||
|
FILE *fp;
|
||||||
|
char line[LINELENGTH];
|
||||||
|
int linelen;
|
||||||
|
int error;
|
||||||
|
} data;
|
||||||
} outbound;
|
} outbound;
|
||||||
|
|
||||||
int pipe_mode; /* We are in pipe mode, i.e. we can handle just one
|
int pipe_mode; /* We are in pipe mode, i.e. we can handle just one
|
||||||
@ -74,6 +80,9 @@ int _assuan_register_std_commands (ASSUAN_CONTEXT ctx);
|
|||||||
/*-- assuan-buffer.c --*/
|
/*-- assuan-buffer.c --*/
|
||||||
int _assuan_write_line (ASSUAN_CONTEXT ctx, const char *line);
|
int _assuan_write_line (ASSUAN_CONTEXT ctx, const char *line);
|
||||||
int _assuan_read_line (ASSUAN_CONTEXT ctx);
|
int _assuan_read_line (ASSUAN_CONTEXT ctx);
|
||||||
|
int _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size);
|
||||||
|
int _assuan_cookie_write_flush (void *cookie);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -192,11 +192,11 @@ assuan_register_command (ASSUAN_CONTEXT ctx,
|
|||||||
if (!cmd_name)
|
if (!cmd_name)
|
||||||
return ASSUAN_Invalid_Value;
|
return ASSUAN_Invalid_Value;
|
||||||
|
|
||||||
fprintf (stderr, "DBG-assuan: registering %d as `%s'\n", cmd_id, cmd_name);
|
/* fprintf (stderr, "DBG-assuan: registering %d as `%s'\n", cmd_id, cmd_name); */
|
||||||
|
|
||||||
if (!ctx->cmdtbl)
|
if (!ctx->cmdtbl)
|
||||||
{
|
{
|
||||||
ctx->cmdtbl_size = 10;
|
ctx->cmdtbl_size = 50;
|
||||||
ctx->cmdtbl = xtrycalloc ( ctx->cmdtbl_size, sizeof *ctx->cmdtbl);
|
ctx->cmdtbl = xtrycalloc ( ctx->cmdtbl_size, sizeof *ctx->cmdtbl);
|
||||||
if (!ctx->cmdtbl)
|
if (!ctx->cmdtbl)
|
||||||
return ASSUAN_Out_Of_Core;
|
return ASSUAN_Out_Of_Core;
|
||||||
@ -206,13 +206,11 @@ assuan_register_command (ASSUAN_CONTEXT ctx,
|
|||||||
{
|
{
|
||||||
struct cmdtbl_s *x;
|
struct cmdtbl_s *x;
|
||||||
|
|
||||||
fprintf (stderr, "DBG-assuan: enlarging cmdtbl\n");
|
|
||||||
|
|
||||||
x = xtryrealloc ( ctx->cmdtbl, (ctx->cmdtbl_size+10) * sizeof *x);
|
x = xtryrealloc ( ctx->cmdtbl, (ctx->cmdtbl_size+10) * sizeof *x);
|
||||||
if (!x)
|
if (!x)
|
||||||
return ASSUAN_Out_Of_Core;
|
return ASSUAN_Out_Of_Core;
|
||||||
ctx->cmdtbl = x;
|
ctx->cmdtbl = x;
|
||||||
ctx->cmdtbl_size += 10;
|
ctx->cmdtbl_size += 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->cmdtbl[ctx->cmdtbl_used].name = cmd_name;
|
ctx->cmdtbl[ctx->cmdtbl_used].name = cmd_name;
|
||||||
@ -285,7 +283,7 @@ dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen)
|
|||||||
line += shift;
|
line += shift;
|
||||||
linelen -= shift;
|
linelen -= shift;
|
||||||
|
|
||||||
fprintf (stderr, "DBG-assuan: processing %s `%s'\n", s, line);
|
/* fprintf (stderr, "DBG-assuan: processing %s `%s'\n", s, line); */
|
||||||
return ctx->cmdtbl[i].handler (ctx, line);
|
return ctx->cmdtbl[i].handler (ctx, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,15 +314,28 @@ assuan_process (ASSUAN_CONTEXT ctx)
|
|||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
fprintf (stderr, "DBG-assuan: got %d bytes `%s'\n",
|
/* fprintf (stderr, "DBG-assuan: got %d bytes `%s'\n", */
|
||||||
ctx->inbound.linelen, ctx->inbound.line);
|
/* ctx->inbound.linelen, ctx->inbound.line); */
|
||||||
}
|
}
|
||||||
while ( *ctx->inbound.line == '#' || !ctx->inbound.linelen);
|
while ( *ctx->inbound.line == '#' || !ctx->inbound.linelen);
|
||||||
|
|
||||||
/* dispatch comamnd and return reply */
|
ctx->outbound.data.error = 0;
|
||||||
|
ctx->outbound.data.linelen = 0;
|
||||||
|
/* dispatch command and return reply */
|
||||||
rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen);
|
rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen);
|
||||||
|
/* check from data write errors */
|
||||||
|
if (ctx->outbound.data.fp)
|
||||||
|
{ /* Flush the data lines */
|
||||||
|
fclose (ctx->outbound.data.fp);
|
||||||
|
ctx->outbound.data.fp = NULL;
|
||||||
|
if (!rc && ctx->outbound.data.error)
|
||||||
|
rc = ctx->outbound.data.error;
|
||||||
|
}
|
||||||
|
/* Error handling */
|
||||||
if (!rc)
|
if (!rc)
|
||||||
rc = _assuan_write_line (ctx, "OK");
|
{
|
||||||
|
rc = _assuan_write_line (ctx, "OK");
|
||||||
|
}
|
||||||
else if (rc == -1)
|
else if (rc == -1)
|
||||||
{ /* No error checking because the peer may have already disconnect */
|
{ /* No error checking because the peer may have already disconnect */
|
||||||
_assuan_write_line (ctx, "OK Bye, bye - hope to meet you again");
|
_assuan_write_line (ctx, "OK Bye, bye - hope to meet you again");
|
||||||
@ -354,6 +365,33 @@ assuan_process (ASSUAN_CONTEXT ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return a FP to be used for data output. The FILE pointer is valid
|
||||||
|
until the end of a handler. So a close is not needed. Assuan does
|
||||||
|
all the buffering needed to insert the status line as well as the
|
||||||
|
required line wappping and quoting for data lines.
|
||||||
|
|
||||||
|
We use GNU's custom streams here. There should be an alternative
|
||||||
|
implementaion for systems w/o a glibc, a simple implementation
|
||||||
|
could use a child process */
|
||||||
|
FILE *
|
||||||
|
assuan_get_data_fp (ASSUAN_CONTEXT ctx)
|
||||||
|
{
|
||||||
|
cookie_io_functions_t cookie_fnc;
|
||||||
|
|
||||||
|
if (ctx->outbound.data.fp)
|
||||||
|
return ctx->outbound.data.fp;
|
||||||
|
|
||||||
|
cookie_fnc.read = NULL;
|
||||||
|
cookie_fnc.write = _assuan_cookie_write_data;
|
||||||
|
cookie_fnc.seek = NULL;
|
||||||
|
cookie_fnc.close = _assuan_cookie_write_flush;
|
||||||
|
|
||||||
|
ctx->outbound.data.fp = fopencookie (ctx, "wb", cookie_fnc);
|
||||||
|
ctx->outbound.data.error = 0;
|
||||||
|
return ctx->outbound.data.fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text)
|
assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text)
|
||||||
{
|
{
|
||||||
@ -391,8 +429,3 @@ assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text)
|
|||||||
xfree (helpbuf);
|
xfree (helpbuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,6 +80,7 @@ int assuan_register_command (ASSUAN_CONTEXT ctx,
|
|||||||
int cmd_id, const char *cmd_string,
|
int cmd_id, const char *cmd_string,
|
||||||
int (*handler)(ASSUAN_CONTEXT, char *));
|
int (*handler)(ASSUAN_CONTEXT, char *));
|
||||||
int assuan_process (ASSUAN_CONTEXT ctx);
|
int assuan_process (ASSUAN_CONTEXT ctx);
|
||||||
|
FILE *assuan_get_data_fp (ASSUAN_CONTEXT ctx);
|
||||||
void assuan_write_status (ASSUAN_CONTEXT ctx,
|
void assuan_write_status (ASSUAN_CONTEXT ctx,
|
||||||
const char *keyword, const char *text);
|
const char *keyword, const char *text);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user