assuan_error_t _assuan_write_line (assuan_context_t ctx, const char *prefix, const char *line, size_t len) { int rc = 0; size_t prefixlen = prefix? strlen (prefix):0; /* Make sure that the line is short enough. */ if (len + prefixlen + 2 > ASSUAN_LINELENGTH) { if (ctx->log_fp) fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> " "[supplied line too long -truncated]\n", assuan_get_assuan_log_prefix (), (unsigned int)getpid (), (void *)ctx); if (prefixlen > 5) prefixlen = 5; if (len > ASSUAN_LINELENGTH - prefixlen - 2) len = ASSUAN_LINELENGTH - prefixlen - 2 - 1; } /* Fixme: we should do some kind of line buffering. */ if (ctx->log_fp) { fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ", assuan_get_assuan_log_prefix (), (unsigned int)getpid (), (void *)ctx); if (ctx->confidential) fputs ("[Confidential data not shown]", ctx->log_fp); else _assuan_log_print_buffer (ctx->log_fp, line, len); putc ('\n', ctx->log_fp); } if (prefixlen) { rc = writen (ctx, prefix, prefixlen); if (rc) rc = ASSUAN_Write_Error; } if (!rc) { rc = writen (ctx, line, len); if (rc) rc = ASSUAN_Write_Error; if (!rc) { rc = writen (ctx, "\n", 1); if (rc) rc = ASSUAN_Write_Error; } } return rc; }
/* Write out any buffered data This function is used for GNU's custom streams */ int _assuan_cookie_write_flush(void *cookie) { assuan_context_t ctx = cookie; char *line; size_t linelen; unsigned int monitor_result; if(ctx->outbound.data.error) return 0; line = ctx->outbound.data.line; linelen = ctx->outbound.data.linelen; line += linelen; monitor_result = (ctx->io_monitor ? ctx->io_monitor(ctx, 1, ctx->outbound.data.line, linelen) : 0); if(linelen) { if(ctx->log_fp && !(monitor_result & 1)) { fprintf(ctx->log_fp, "%s[%u.%d] DBG: -> ", assuan_get_assuan_log_prefix(), (unsigned int)getpid(), ctx->inbound.fd); if(ctx->confidential) fputs("[Confidential data not shown]", ctx->log_fp); else _assuan_log_print_buffer(ctx->log_fp, ctx->outbound.data.line, linelen); putc('\n', ctx->log_fp); } *line++ = '\n'; linelen++; if(!(monitor_result & 2) && writen(ctx, ctx->outbound.data.line, linelen)) { ctx->outbound.data.error = _assuan_error(ASSUAN_Write_Error); return 0; } ctx->outbound.data.linelen = 0; } return 0; }
/* Write out any buffered data This function is used for GNU's custom streams */ int _assuan_cookie_write_flush (void *cookie) { assuan_context_t 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) { if (ctx->log_fp) { fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ", assuan_get_assuan_log_prefix (), (unsigned int)getpid (), (void *)ctx); if (ctx->confidential) fputs ("[Confidential data not shown]", ctx->log_fp); else _assuan_log_print_buffer (ctx->log_fp, ctx->outbound.data.line, linelen); putc ('\n', ctx->log_fp); } *line++ = '\n'; linelen++; if (writen (ctx, ctx->outbound.data.line, linelen)) { ctx->outbound.data.error = ASSUAN_Write_Error; return 0; } ctx->outbound.data.linelen = 0; } return 0; }
int _assuan_read_line (assuan_context_t ctx) { char *line = ctx->inbound.line; int nread, atticlen; int rc; char *endp = 0; if (ctx->inbound.eof) return -1; atticlen = ctx->inbound.attic.linelen; if (atticlen) { memcpy (line, ctx->inbound.attic.line, atticlen); ctx->inbound.attic.linelen = 0; endp = memchr (line, '\n', atticlen); if (endp) /* Found another line in the attic. */ { rc = 0; nread = atticlen; atticlen = 0; } else /* There is pending data but not a full line. */ { assert (atticlen < LINELENGTH); rc = readaline (ctx, line + atticlen, LINELENGTH - atticlen, &nread, &ctx->inbound.eof); } } else /* No pending data. */ rc = readaline (ctx, line, LINELENGTH, &nread, &ctx->inbound.eof); if (rc) { if (ctx->log_fp) fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [Error: %s]\n", assuan_get_assuan_log_prefix (), (unsigned int)getpid (), (void *)ctx, strerror (errno)); return ASSUAN_Read_Error; } if (!nread) { assert (ctx->inbound.eof); if (ctx->log_fp) fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [EOF]\n", assuan_get_assuan_log_prefix (), (unsigned int)getpid (), (void *)ctx); return -1; } ctx->inbound.attic.pending = 0; nread += atticlen; if (! endp) endp = memchr (line, '\n', nread); if (endp) { int n = endp - line + 1; if (n < nread) /* LINE contains more than one line. We copy it to the attic now as handlers are allowed to modify the passed buffer. */ { int len = nread - n; memcpy (ctx->inbound.attic.line, endp + 1, len); ctx->inbound.attic.pending = memrchr (endp + 1, '\n', len) ? 1 : 0; ctx->inbound.attic.linelen = len; } if (endp != line && endp[-1] == '\r') endp --; *endp = 0; ctx->inbound.linelen = endp - line; if (ctx->log_fp) { fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- ", assuan_get_assuan_log_prefix (), (unsigned int)getpid (), (void *)ctx); if (ctx->confidential) fputs ("[Confidential data not shown]", ctx->log_fp); else _assuan_log_print_buffer (ctx->log_fp, ctx->inbound.line, ctx->inbound.linelen); putc ('\n', ctx->log_fp); } return 0; } else { if (ctx->log_fp) fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [Invalid line]\n", assuan_get_assuan_log_prefix (), (unsigned int)getpid (), (void *)ctx); *line = 0; ctx->inbound.linelen = 0; return ctx->inbound.eof ? ASSUAN_Line_Not_Terminated : ASSUAN_Line_Too_Long; } }
/* Write out the data in buffer as datalines with line wrapping and percent escaping. This function is used for GNU's custom streams */ int _assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size) { assuan_context_t ctx = cookie; size_t size = orig_size; 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) { if (ctx->log_fp) { fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ", assuan_get_assuan_log_prefix (), (unsigned int)getpid (), (void *)ctx); if (ctx->confidential) fputs ("[Confidential data not shown]", ctx->log_fp); else _assuan_log_print_buffer (ctx->log_fp, ctx->outbound.data.line, linelen); putc ('\n', ctx->log_fp); } *line++ = '\n'; linelen++; if (writen (ctx, 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 (int)orig_size; }
assuan_error_t _assuan_write_line(assuan_context_t ctx, const char *prefix, const char *line, size_t len) { assuan_error_t rc = 0; size_t prefixlen = prefix ? strlen(prefix) : 0; unsigned int monitor_result; /* Make sure that the line is short enough. */ if(len + prefixlen + 2 > ASSUAN_LINELENGTH) { if(ctx->log_fp) fprintf(ctx->log_fp, "%s[%u.%d] DBG: -> " "[supplied line too long -truncated]\n", assuan_get_assuan_log_prefix(), (unsigned int)getpid(), ctx->inbound.fd); if(prefixlen > 5) prefixlen = 5; if(len > ASSUAN_LINELENGTH - prefixlen - 2) len = ASSUAN_LINELENGTH - prefixlen - 2 - 1; } monitor_result = (ctx->io_monitor ? ctx->io_monitor(ctx, 1, line, len) : 0); /* Fixme: we should do some kind of line buffering. */ if(ctx->log_fp && !(monitor_result & 1)) { fprintf(ctx->log_fp, "%s[%u.%d] DBG: -> ", assuan_get_assuan_log_prefix(), (unsigned int)getpid(), ctx->inbound.fd); if(ctx->confidential) fputs("[Confidential data not shown]", ctx->log_fp); else { if(prefixlen) _assuan_log_print_buffer(ctx->log_fp, prefix, prefixlen); _assuan_log_print_buffer(ctx->log_fp, line, len); } putc('\n', ctx->log_fp); } if(prefixlen && !(monitor_result & 2)) { rc = writen(ctx, prefix, prefixlen); if(rc) rc = _assuan_error(ASSUAN_Write_Error); } if(!rc && !(monitor_result & 2)) { rc = writen(ctx, line, len); if(rc) rc = _assuan_error(ASSUAN_Write_Error); if(!rc) { rc = writen(ctx, "\n", 1); if(rc) rc = _assuan_error(ASSUAN_Write_Error); } } return rc; }