Always use the non-blocking portion of libssh2. This changes libpwmd
[libpwmd.git] / assuan / assuan-client.c
blob51d24b6f431395bb9982ca781247464a8bf27914
1 /* assuan-client.c - client functions
2 * Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
4 * This file is part of Assuan.
6 * Assuan is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
11 * Assuan is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <errno.h>
24 #include <unistd.h>
25 #include <assert.h>
27 #include "assuan-defs.h"
29 #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
30 *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
31 #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
34 assuan_error_t
35 _assuan_read_from_server (assuan_context_t ctx, int *okay, int *off)
37 char *line;
38 int linelen;
39 assuan_error_t rc;
41 *okay = 0;
42 *off = 0;
43 do
47 rc = _assuan_read_line (ctx);
49 while (!ctx->in_inquire && _assuan_error_is_eagain (rc));
50 if (rc)
51 return rc;
52 line = ctx->inbound.line;
53 linelen = ctx->inbound.linelen;
55 while (*line == '#' || !linelen);
57 if (linelen >= 1
58 && line[0] == 'D' && line[1] == ' ')
60 *okay = 2; /* data line */
61 *off = 2;
63 else if (linelen >= 1
64 && line[0] == 'S'
65 && (line[1] == '\0' || line[1] == ' '))
67 *okay = 4;
68 *off = 1;
69 while (line[*off] == ' ')
70 ++*off;
72 else if (linelen >= 2
73 && line[0] == 'O' && line[1] == 'K'
74 && (line[2] == '\0' || line[2] == ' '))
76 *okay = 1;
77 *off = 2;
78 while (line[*off] == ' ')
79 ++*off;
81 else if (linelen >= 3
82 && line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
83 && (line[3] == '\0' || line[3] == ' '))
85 *okay = 0;
86 *off = 3;
87 while (line[*off] == ' ')
88 ++*off;
90 else if (linelen >= 7
91 && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
92 && line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
93 && line[6] == 'E'
94 && (line[7] == '\0' || line[7] == ' '))
96 *okay = 3;
97 *off = 7;
98 ctx->in_inquire = 1;
99 while (line[*off] == ' ')
100 ++*off;
102 else if (linelen >= 3
103 && line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
104 && (line[3] == '\0' || line[3] == ' '))
106 *okay = 5; /* end line */
107 *off = 3;
109 else
110 rc = _assuan_error (ASSUAN_Invalid_Response);
111 return rc;
117 * assuan_transact:
118 * @ctx: The Assuan context
119 * @command: Command line to be send to the server
120 * @data_cb: Callback function for data lines
121 * @data_cb_arg: first argument passed to @data_cb
122 * @inquire_cb: Callback function for a inquire response
123 * @inquire_cb_arg: first argument passed to @inquire_cb
124 * @status_cb: Callback function for a status response
125 * @status_cb_arg: first argument passed to @status_cb
127 * FIXME: Write documentation
129 * Return value: 0 on success or error code. The error code may be
130 * the one one returned by the server in error lines or from the
131 * callback functions. Take care: When a callback returns an error
132 * this function returns immediately with an error and thus the caller
133 * will altter return an Assuan error (write erro in most cases).
135 assuan_error_t
136 assuan_transact (assuan_context_t ctx,
137 const char *command,
138 int (*data_cb)(void *, const void *, size_t),
139 void *data_cb_arg,
140 int (*inquire_cb)(void*, const char *),
141 void *inquire_cb_arg,
142 int (*status_cb)(void*, const char *),
143 void *status_cb_arg)
145 assuan_error_t rc;
146 int okay, off;
147 char *line;
148 int linelen;
150 ctx->in_inquire = 0;
151 rc = assuan_write_line (ctx, command);
152 if (rc)
153 return rc;
155 if (*command == '#' || !*command)
156 return 0; /* Don't expect a response for a comment line. */
158 again:
159 rc = _assuan_read_from_server (ctx, &okay, &off);
160 if (rc)
161 return rc; /* error reading from server */
163 line = ctx->inbound.line + off;
164 linelen = ctx->inbound.linelen - off;
166 if (!okay)
168 rc = atoi (line);
169 if (rc > 0 && rc < 100)
170 rc = _assuan_error (ASSUAN_Server_Fault);
171 else if (rc > 0 && rc <= 405)
172 rc = _assuan_error (rc);
174 else if (okay == 2)
176 if (!data_cb)
177 rc = _assuan_error (ASSUAN_No_Data_Callback);
178 else
180 char *s, *d;
182 for (s=d=line; linelen; linelen--)
184 if (*s == '%' && linelen > 2)
185 { /* handle escaping */
186 s++;
187 *d++ = xtoi_2 (s);
188 s += 2;
189 linelen -= 2;
191 else
192 *d++ = *s++;
194 *d = 0; /* add a hidden string terminator */
195 rc = data_cb (data_cb_arg, line, d - line);
196 if (!rc)
197 goto again;
200 else if (okay == 3)
202 if (!inquire_cb)
204 assuan_write_line (ctx, "END"); /* get out of inquire mode */
205 _assuan_read_from_server (ctx, &okay, &off); /* dummy read */
206 rc = _assuan_error (ASSUAN_No_Inquire_Callback);
208 else
210 rc = inquire_cb (inquire_cb_arg, line);
211 ctx->in_inquire = 0;
212 if (!rc)
213 rc = assuan_send_data (ctx, NULL, 0); /* flush and send END */
214 if (!rc)
215 goto again;
218 else if (okay == 4)
220 if (status_cb)
221 rc = status_cb (status_cb_arg, line);
222 if (!rc)
223 goto again;
225 else if (okay == 5)
227 if (!data_cb)
228 rc = _assuan_error (ASSUAN_No_Data_Callback);
229 else
231 rc = data_cb (data_cb_arg, NULL, 0);
232 if (!rc)
233 goto again;
237 return rc;