gpg_error_t
_assuan_write_line (assuan_context_t ctx, const char *prefix,
                    const char *line, size_t len)
{
  gpg_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)
    {
      _assuan_log_control_channel (ctx, 1,
                                   "supplied line too long - truncated",
                                   NULL, 0, NULL, 0);
      if (prefixlen > 5)
        prefixlen = 5;
      if (len > ASSUAN_LINELENGTH - prefixlen - 2)
        len = ASSUAN_LINELENGTH - prefixlen - 2 - 1;
    }

  monitor_result = 0;
  if (ctx->io_monitor)
    monitor_result = ctx->io_monitor (ctx, ctx->io_monitor_data, 1, line, len);

  /* Fixme: we should do some kind of line buffering.  */
  if (!(monitor_result & ASSUAN_IO_MONITOR_NOLOG))
    _assuan_log_control_channel (ctx, 1, NULL,
                                 prefixlen? prefix:NULL, prefixlen,
                                 line, len);

  if (prefixlen && !(monitor_result & ASSUAN_IO_MONITOR_IGNORE))
    {
      rc = writen (ctx, prefix, prefixlen);
      if (rc)
	rc = _assuan_error (ctx, gpg_err_code_from_syserror ());
    }
  if (!rc && !(monitor_result & ASSUAN_IO_MONITOR_IGNORE))
    {
      rc = writen (ctx, line, len);
      if (rc)
	rc = _assuan_error (ctx, gpg_err_code_from_syserror ());
      if (!rc)
        {
          rc = writen (ctx, "\n", 1);
          if (rc)
	    rc = _assuan_error (ctx, gpg_err_code_from_syserror ());
        }
    }
  return rc;
}
Exemple #2
0
/* Function returns an Assuan error. */
assuan_error_t
_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 _assuan_error(-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 = readline(ctx, line + atticlen,
                          LINELENGTH - atticlen, &nread, &ctx->inbound.eof);
        }
    }
    else
        /* No pending data.  */
        rc = readline(ctx, line, LINELENGTH,
                      &nread, &ctx->inbound.eof);
    if(rc)
    {
        if(ctx->log_fp)
            fprintf(ctx->log_fp, "%s[%u.%d] DBG: <- [Error: %s]\n",
                    assuan_get_assuan_log_prefix(),
                    (unsigned int)getpid(), ctx->inbound.fd,
                    strerror(errno));
        return _assuan_error(ASSUAN_Read_Error);
    }
    if(!nread)
    {
        assert(ctx->inbound.eof);
        if(ctx->log_fp)
            fprintf(ctx->log_fp, "%s[%u.%d] DBG: <- [EOF]\n",
                    assuan_get_assuan_log_prefix(),
                    (unsigned int)getpid(), ctx->inbound.fd);
        return _assuan_error(-1);
    }

    ctx->inbound.attic.pending = 0;
    nread += atticlen;

    if(! endp)
        endp = memchr(line, '\n', nread);

    if(endp)
    {
        unsigned monitor_result;
        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;

        monitor_result = (ctx->io_monitor
                          ? ctx->io_monitor(ctx, 0,
                                            ctx->inbound.line,
                                            ctx->inbound.linelen)
                          : 0);
        if((monitor_result & 2))
            ctx->inbound.linelen = 0;

        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->inbound.line,
                                         ctx->inbound.linelen);
            putc('\n', ctx->log_fp);
        }
        return 0;
    }
    else
    {
        if(ctx->log_fp)
            fprintf(ctx->log_fp, "%s[%u.%d] DBG: <- [Invalid line]\n",
                    assuan_get_assuan_log_prefix(),
                    (unsigned int)getpid(), ctx->inbound.fd);
        *line = 0;
        ctx->inbound.linelen = 0;
        return _assuan_error(ctx->inbound.eof
                             ? ASSUAN_Line_Not_Terminated
                             : ASSUAN_Line_Too_Long);
    }
}
/* Read a line with buffering of partial lines.  Function returns an
   Assuan error.  */
gpg_error_t
_assuan_read_line (assuan_context_t ctx)
{
  gpg_error_t rc = 0;
  char *line = ctx->inbound.line;
  int nread, atticlen;
  char *endp = 0;

  if (ctx->inbound.eof)
    return _assuan_error (ctx, GPG_ERR_EOF);

  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.  */
	  nread = atticlen;
	  atticlen = 0;
	}
      else
        {
	  /* There is pending data but not a full line.  */
          assert (atticlen < LINELENGTH);
          rc = readline (ctx, line + atticlen,
			 LINELENGTH - atticlen, &nread, &ctx->inbound.eof);
        }
    }
  else
    /* No pending data.  */
    rc = readline (ctx, line, LINELENGTH,
                   &nread, &ctx->inbound.eof);
  if (rc)
    {
      int saved_errno = errno;
      char buf[100];

      snprintf (buf, sizeof buf, "error: %s", strerror (errno));
      _assuan_log_control_channel (ctx, 0, buf, NULL, 0, NULL, 0);

      if (saved_errno == EAGAIN)
        {
          /* We have to save a partial line.  Due to readline's
	     behaviour, we know that this is not a complete line yet
	     (no newline).  So we don't set PENDING to true.  */
          memcpy (ctx->inbound.attic.line, line, atticlen + nread);
          ctx->inbound.attic.pending = 0;
          ctx->inbound.attic.linelen = atticlen + nread;
        }

      gpg_err_set_errno (saved_errno);
      return _assuan_error (ctx, gpg_err_code_from_syserror ());
    }
  if (!nread)
    {
      assert (ctx->inbound.eof);
      _assuan_log_control_channel (ctx, 0, "eof", NULL, 0, NULL, 0);
      return _assuan_error (ctx, GPG_ERR_EOF);
    }

  ctx->inbound.attic.pending = 0;
  nread += atticlen;

  if (! endp)
    endp = memchr (line, '\n', nread);

  if (endp)
    {
      unsigned monitor_result;
      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;

      monitor_result = 0;
      if (ctx->io_monitor)
	monitor_result = ctx->io_monitor (ctx, ctx->io_monitor_data, 0,
					  ctx->inbound.line,
					  ctx->inbound.linelen);
      if (monitor_result & ASSUAN_IO_MONITOR_IGNORE)
        ctx->inbound.linelen = 0;

      if ( !(monitor_result & ASSUAN_IO_MONITOR_NOLOG))
        _assuan_log_control_channel (ctx, 0, NULL,
                                     ctx->inbound.line, ctx->inbound.linelen,
                                     NULL, 0);
      return 0;
    }
  else
    {
      _assuan_log_control_channel (ctx, 0, "invalid line",
                                   NULL, 0, NULL, 0);
      *line = 0;
      ctx->inbound.linelen = 0;
      return _assuan_error (ctx, ctx->inbound.eof
			    ? GPG_ERR_ASS_INCOMPLETE_LINE
			    : GPG_ERR_ASS_LINE_TOO_LONG);
    }
}
Exemple #4
0
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;
}