Added code for data lines. For ease of implementation we need glibc
authorWerner Koch <wk@gnupg.org>
Mon, 19 Nov 2001 16:15:43 +0000 (16:15 +0000)
committerWerner Koch <wk@gnupg.org>
Mon, 19 Nov 2001 16:15:43 +0000 (16:15 +0000)
(custom streams).

assuan/assuan-buffer.c
assuan/assuan-defs.h
assuan/assuan-handler.c
assuan/assuan.h

index 73786b6..912272f 100644 (file)
@@ -149,3 +149,99 @@ _assuan_write_line (ASSUAN_CONTEXT ctx, const char *line )
   return rc;
 }
 
+
+\f
+/* 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;
+}
+
+
+
+
index 96e8a4a..8723fd3 100644 (file)
@@ -49,6 +49,12 @@ struct assuan_context_s {
 
   struct {
     int fd;
+    struct {
+      FILE *fp;
+      char line[LINELENGTH];
+      int linelen; 
+      int error;
+    } data; 
   } outbound;
 
   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 --*/
 int _assuan_write_line (ASSUAN_CONTEXT ctx, const char *line);
 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);
+
 
 
 
index 90f170a..472206b 100644 (file)
@@ -192,11 +192,11 @@ assuan_register_command (ASSUAN_CONTEXT ctx,
   if (!cmd_name)
     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)
     {
-      ctx->cmdtbl_size = 10;
+      ctx->cmdtbl_size = 50;
       ctx->cmdtbl = xtrycalloc ( ctx->cmdtbl_size, sizeof *ctx->cmdtbl);
       if (!ctx->cmdtbl)
         return ASSUAN_Out_Of_Core;
@@ -206,13 +206,11 @@ assuan_register_command (ASSUAN_CONTEXT ctx,
     {
       struct cmdtbl_s *x;
 
-      fprintf (stderr, "DBG-assuan: enlarging cmdtbl\n");
-      
       x = xtryrealloc ( ctx->cmdtbl, (ctx->cmdtbl_size+10) * sizeof *x);
       if (!x)
         return ASSUAN_Out_Of_Core;
       ctx->cmdtbl = x;
-      ctx->cmdtbl_size += 10;
+      ctx->cmdtbl_size += 50;
     }
 
   ctx->cmdtbl[ctx->cmdtbl_used].name = cmd_name;
@@ -285,7 +283,7 @@ dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen)
   line += 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);
 }
 
@@ -316,15 +314,28 @@ assuan_process (ASSUAN_CONTEXT ctx)
         if (rc)
           return rc;
       
-        fprintf (stderr, "DBG-assuan: got %d bytes `%s'\n",
-                 ctx->inbound.linelen, ctx->inbound.line);
+/*          fprintf (stderr, "DBG-assuan: got %d bytes `%s'\n", */
+/*                   ctx->inbound.linelen, ctx->inbound.line); */
       }
     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);
+    /* 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)
-      rc = _assuan_write_line (ctx, "OK");
+      {
+        rc = _assuan_write_line (ctx, "OK");
+      }
     else if (rc == -1)
       { /* No error checking because the peer may have already disconnect */ 
         _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
 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);
     }
 }
-
-
-
-
-
index 02a8fda..e6b33c7 100644 (file)
@@ -80,6 +80,7 @@ int assuan_register_command (ASSUAN_CONTEXT ctx,
                              int cmd_id, const char *cmd_string,
                              int (*handler)(ASSUAN_CONTEXT, char *));
 int assuan_process (ASSUAN_CONTEXT ctx);
+FILE *assuan_get_data_fp (ASSUAN_CONTEXT ctx);
 void assuan_write_status (ASSUAN_CONTEXT ctx,
                           const char *keyword, const char *text);