aboutsummaryrefslogtreecommitdiffstats
path: root/assuan/assuan-inquire.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--assuan/assuan-inquire.c158
1 files changed, 152 insertions, 6 deletions
diff --git a/assuan/assuan-inquire.c b/assuan/assuan-inquire.c
index d8c52d09..58b9f029 100644
--- a/assuan/assuan-inquire.c
+++ b/assuan/assuan-inquire.c
@@ -1,5 +1,5 @@
/* assuan-inquire.c - handle inquire stuff
- * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
*
* This file is part of Assuan.
*
@@ -14,9 +14,7 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
@@ -44,7 +42,7 @@ struct membuf
-/* A simple implemnation of a dynamic buffer. Use init_membuf() to
+/* A simple implementation of a dynamic buffer. Use init_membuf() to
create a buffer, put_membuf to append bytes and get_membuf to
release and return the buffer. Allocation errors are detected but
only returned at the final get_membuf(), this helps not to clutter
@@ -171,7 +169,9 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
{
do
{
- rc = _assuan_read_line (ctx);
+ do
+ rc = _assuan_read_line (ctx);
+ while (_assuan_error_is_eagain (rc));
if (rc)
goto leave;
line = (unsigned char *) ctx->inbound.line;
@@ -234,8 +234,154 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,
return rc;
}
+
+void
+_assuan_inquire_release (assuan_context_t ctx)
+{
+ if (ctx->in_inquire)
+ {
+ if (ctx->inquire_membuf)
+ {
+ free_membuf (ctx->inquire_membuf);
+ free (ctx->inquire_membuf);
+ }
+ ctx->in_inquire = 0;
+ }
+}
+
+
+int
+_assuan_inquire_ext_cb (assuan_context_t ctx)
+{
+ int rc;
+ unsigned char *line;
+ int linelen;
+ struct membuf *mb;
+ unsigned char *p;
+
+ line = (unsigned char *) ctx->inbound.line;
+ linelen = ctx->inbound.linelen;
+ mb = ctx->inquire_membuf;
+
+ if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N')
+ {
+ rc = _assuan_error (ASSUAN_Canceled);
+ goto leave;
+ }
+ if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
+ && (!line[3] || line[3] == ' '))
+ {
+ rc = 0;
+ goto leave;
+ }
+
+ if (line[0] != 'D' || line[1] != ' ' || mb == NULL)
+ {
+ rc = _assuan_error (ASSUAN_Unexpected_Command);
+ goto leave;
+ }
+
+ if (linelen < 3)
+ return 0;
+ line += 2;
+ linelen -= 2;
+
+ p = line;
+ while (linelen)
+ {
+ for (;linelen && *p != '%'; linelen--, p++)
+ ;
+ put_membuf (mb, line, p-line);
+ if (linelen > 2)
+ { /* handle escaping */
+ unsigned char tmp[1];
+ p++;
+ *tmp = xtoi_2 (p);
+ p += 2;
+ linelen -= 3;
+ put_membuf (mb, tmp, 1);
+ }
+ line = p;
+ }
+ if (mb->too_large)
+ {
+ rc = _assuan_error (ASSUAN_Too_Much_Data);
+ goto leave;
+ }
+
+ return 0;
+
+ leave:
+ {
+ size_t buf_len = 0;
+ unsigned char *buf = NULL;
+
+ if (mb)
+ {
+ buf = get_membuf (mb, &buf_len);
+ if (!buf)
+ rc = _assuan_error (ASSUAN_Out_Of_Core);
+ free_membuf (mb);
+ free (mb);
+ ctx->inquire_membuf = NULL;
+ }
+ ctx->in_inquire = 0;
+ rc = (ctx->inquire_cb) (ctx->inquire_cb_data, rc, buf, buf_len);
+ }
+ return rc;
+}
+
+/**
+ * assuan_inquire_ext:
+ * @ctx: An assuan context
+ * @keyword: The keyword used for the inquire
+ * @maxlen: If not 0, the size limit of the inquired data.
+ * @cb: A callback handler which is invoked after the operation completed.
+ * @cb_data: A user-provided value passed to the callback handler.
+ *
+ * A Server may use this to Send an inquire. r_buffer, r_length and
+ * maxlen may all be NULL/0 to indicate that no real data is expected.
+ * When this function returns,
+ *
+ * Return value: 0 on success or an ASSUAN error code
+ **/
+assuan_error_t
+assuan_inquire_ext (assuan_context_t ctx, const char *keyword, size_t maxlen,
+ int (*cb) (void *cb_data, int rc, unsigned char *buf,
+ size_t len),
+ void *cb_data)
+{
+ assuan_error_t rc;
+ struct membuf *mb = NULL;
+ char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INQUIRE ")+CR,LF) */
+ if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf)))
+ return _assuan_error (ASSUAN_Invalid_Value);
+ if (!ctx->is_server)
+ return _assuan_error (ASSUAN_Not_A_Server);
+ if (ctx->in_inquire)
+ return _assuan_error (ASSUAN_Nested_Commands);
+ mb = malloc (sizeof (struct membuf));
+ if (!mb)
+ return _assuan_error (ASSUAN_Out_Of_Core);
+ init_membuf (mb, maxlen ? maxlen : 1024, maxlen);
+ strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword);
+ rc = assuan_write_line (ctx, cmdbuf);
+ if (rc)
+ {
+ free_membuf (mb);
+ free (mb);
+ return rc;
+ }
+ ctx->in_inquire = 1;
+
+ /* Set up the continuation. */
+ ctx->inquire_cb = cb;
+ ctx->inquire_cb_data = cb_data;
+ ctx->inquire_membuf = mb;
+ return 0;
+}