Assuan server mode is now basically usable
[gnupg.git] / assuan / assuan-buffer.c
1 /* assuan-buffer.c - read and send data
2  *      Copyright (C) 2001 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <assert.h>
27
28 #include "assuan-defs.h"
29
30
31 static int
32 writen ( int fd, const char *buffer, size_t length )
33 {
34   while (length)
35     {
36       int nwritten = write (fd, buffer, length);
37       
38       if (nwritten < 0)
39         {
40           if (errno == EINTR)
41             continue;
42           return -1; /* write error */
43         }
44       length -= nwritten;
45       buffer += nwritten;
46     }
47   return 0;  /* okay */
48 }
49
50 /* read an entire line */
51 static int
52 readline (int fd, char *buf, size_t buflen, int *r_nread, int *eof)
53 {
54   size_t nleft = buflen;
55   char *p;
56
57   *eof = 0;
58   *r_nread = 0;
59   while (nleft > 0)
60     {
61       int n = read (fd, buf, nleft);
62       if (n < 0)
63         {
64           if (errno == EINTR)
65             continue;
66           return -1; /* read error */
67         }
68       else if (!n)
69         {
70           *eof = 1;
71           break; /* allow incomplete lines */
72         }
73       p = buf;
74       nleft -= n;
75       buf += n;
76       *r_nread += n;
77       
78       for (; n && *p != '\n'; n--, p++)
79         ;
80       if (n)
81         break;
82     }
83
84   return 0;
85 }
86
87
88 int
89 _assuan_read_line (ASSUAN_CONTEXT ctx)
90 {
91   char *line = ctx->inbound.line;
92   int n, nread;
93   int rc;
94   
95   if (ctx->inbound.eof)
96     return -1;
97
98   rc = readline (ctx->inbound.fd, line, LINELENGTH, &nread, &ctx->inbound.eof);
99   if (rc)
100     return ASSUAN_Read_Error;
101   if (!nread)
102     {
103       assert (ctx->inbound.eof);
104       return -1; 
105     }
106
107   for (n=nread-1; n>=0 ; n--)
108     {
109       if (line[n] == '\n')
110         {
111           if (n != nread-1)
112             {
113               fprintf (stderr, "DBG-assuan: %d bytes left over after read\n",
114                        nread-1 - n);
115               /* fixme: store them for the next read */
116             }
117           if (n && line[n-1] == '\r')
118             n--;
119           line[n] = 0;
120           ctx->inbound.linelen = n;
121           return 0;
122         }
123     }
124
125   *line = 0;
126   ctx->inbound.linelen = 0;
127   return ctx->inbound.eof? ASSUAN_Line_Not_Terminated : ASSUAN_Line_Too_Long;
128 }
129
130
131
132
133 int 
134 _assuan_write_line (ASSUAN_CONTEXT ctx, const char *line )
135 {
136   int rc;
137
138   /* fixme: we should do some kind of line buffering */
139   rc = writen (ctx->outbound.fd, line, strlen(line));
140   if (rc)
141     rc = ASSUAN_Write_Error;
142   if (!rc)
143     {
144       rc = writen (ctx->outbound.fd, "\n", 1);
145       if (rc)
146         rc = ASSUAN_Write_Error;
147     }
148
149   return rc;
150 }
151