Call libssh2_channel_close() before freeing it.
[libpwmd.git] / assuan / assuan-client.c
blob15f4f1cda1b38c57804feb8922022f3aefacb72d
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 (_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 while (line[*off] == ' ')
99 ++*off;
101 else if (linelen >= 3
102 && line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
103 && (line[3] == '\0' || line[3] == ' '))
105 *okay = 5; /* end line */
106 *off = 3;
108 else
109 rc = _assuan_error (ASSUAN_Invalid_Response);
110 return rc;
116 * assuan_transact:
117 * @ctx: The Assuan context
118 * @command: Command line to be send to the server
119 * @data_cb: Callback function for data lines
120 * @data_cb_arg: first argument passed to @data_cb
121 * @inquire_cb: Callback function for a inquire response
122 * @inquire_cb_arg: first argument passed to @inquire_cb
123 * @status_cb: Callback function for a status response
124 * @status_cb_arg: first argument passed to @status_cb
126 * FIXME: Write documentation
128 * Return value: 0 on success or error code. The error code may be
129 * the one one returned by the server in error lines or from the
130 * callback functions. Take care: When a callback returns an error
131 * this function returns immediately with an error and thus the caller
132 * will altter return an Assuan error (write erro in most cases).
134 assuan_error_t
135 assuan_transact (assuan_context_t ctx,
136 const char *command,
137 int (*data_cb)(void *, const void *, size_t),
138 void *data_cb_arg,
139 int (*inquire_cb)(void*, const char *),
140 void *inquire_cb_arg,
141 int (*status_cb)(void*, const char *),
142 void *status_cb_arg)
144 assuan_error_t rc;
145 int okay, off;
146 char *line;
147 int linelen;
149 rc = assuan_write_line (ctx, command);
150 if (rc)
151 return rc;
153 if (*command == '#' || !*command)
154 return 0; /* Don't expect a response for a comment line. */
156 again:
157 rc = _assuan_read_from_server (ctx, &okay, &off);
158 if (rc)
159 return rc; /* error reading from server */
161 line = ctx->inbound.line + off;
162 linelen = ctx->inbound.linelen - off;
164 if (!okay)
166 rc = atoi (line);
167 if (rc > 0 && rc < 100)
168 rc = _assuan_error (ASSUAN_Server_Fault);
169 else if (rc > 0 && rc <= 405)
170 rc = _assuan_error (rc);
172 else if (okay == 2)
174 if (!data_cb)
175 rc = _assuan_error (ASSUAN_No_Data_Callback);
176 else
178 char *s, *d;
180 for (s=d=line; linelen; linelen--)
182 if (*s == '%' && linelen > 2)
183 { /* handle escaping */
184 s++;
185 *d++ = xtoi_2 (s);
186 s += 2;
187 linelen -= 2;
189 else
190 *d++ = *s++;
192 *d = 0; /* add a hidden string terminator */
193 rc = data_cb (data_cb_arg, line, d - line);
194 if (!rc)
195 goto again;
198 else if (okay == 3)
200 if (!inquire_cb)
202 assuan_write_line (ctx, "END"); /* get out of inquire mode */
203 _assuan_read_from_server (ctx, &okay, &off); /* dummy read */
204 rc = _assuan_error (ASSUAN_No_Inquire_Callback);
206 else
208 rc = inquire_cb (inquire_cb_arg, line);
209 if (!rc)
210 rc = assuan_send_data (ctx, NULL, 0); /* flush and send END */
211 if (!rc)
212 goto again;
215 else if (okay == 4)
217 if (status_cb)
218 rc = status_cb (status_cb_arg, line);
219 if (!rc)
220 goto again;
222 else if (okay == 5)
224 if (!data_cb)
225 rc = _assuan_error (ASSUAN_No_Data_Callback);
226 else
228 rc = data_cb (data_cb_arg, NULL, 0);
229 if (!rc)
230 goto again;
234 return rc;