aboutsummaryrefslogtreecommitdiffstats
path: root/src/assuan-handler.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2001-11-07 17:43:05 +0000
committerWerner Koch <[email protected]>2001-11-07 17:43:05 +0000
commitd5aea23fcaa3b05240242b8a8a192a0ea74bd9b8 (patch)
tree4bed195af93f9611e75c3cb12ef3bf077379a2b1 /src/assuan-handler.c
parentgpgsm does now build and a dummy server can be started. (diff)
downloadlibassuan-d5aea23fcaa3b05240242b8a8a192a0ea74bd9b8.tar.gz
libassuan-d5aea23fcaa3b05240242b8a8a192a0ea74bd9b8.zip
Assuan server mode is now basically usable
Diffstat (limited to '')
-rw-r--r--src/assuan-handler.c189
1 files changed, 147 insertions, 42 deletions
diff --git a/src/assuan-handler.c b/src/assuan-handler.c
index aeeb336..cebb786 100644
--- a/src/assuan-handler.c
+++ b/src/assuan-handler.c
@@ -31,7 +31,6 @@
static int
dummy_handler (ASSUAN_CONTEXT ctx, char *line)
{
- fprintf (stderr, "DBG-assuan: dummy handler called\n");
return set_error (ctx, Server_Fault, "no handler registered");
}
@@ -39,42 +38,36 @@ dummy_handler (ASSUAN_CONTEXT ctx, char *line)
static int
std_handler_nop (ASSUAN_CONTEXT ctx, char *line)
{
- fprintf (stderr, "DBG-assuan: processing a NOP `%s'\n", line);
return 0; /* okay */
}
static int
std_handler_cancel (ASSUAN_CONTEXT ctx, char *line)
{
- fprintf (stderr, "DBG-assuan: processing a CANCEL `%s'\n", line);
return set_error (ctx, Not_Implemented, NULL);
}
static int
std_handler_bye (ASSUAN_CONTEXT ctx, char *line)
{
- fprintf (stderr, "DBG-assuan: processing a BYE `%s'\n", line);
- return set_error (ctx, Not_Implemented, NULL);
+ return -1; /* pretty simple :-) */
}
static int
std_handler_auth (ASSUAN_CONTEXT ctx, char *line)
{
- fprintf (stderr, "DBG-assuan: processing a AUTH `%s'\n", line);
return set_error (ctx, Not_Implemented, NULL);
}
static int
std_handler_reset (ASSUAN_CONTEXT ctx, char *line)
{
- fprintf (stderr, "DBG-assuan: processing a RESET `%s'\n", line);
return set_error (ctx, Not_Implemented, NULL);
}
static int
std_handler_end (ASSUAN_CONTEXT ctx, char *line)
{
- fprintf (stderr, "DBG-assuan: processing a END `%s'\n", line);
return set_error (ctx, Not_Implemented, NULL);
}
@@ -104,8 +97,6 @@ std_handler_input (ASSUAN_CONTEXT ctx, char *line)
{
int rc, fd;
- fprintf (stderr, "DBG-assuan: processing a INPUT `%s'\n", line);
-
rc = parse_cmd_input_output (ctx, line, &fd);
if (rc)
return rc;
@@ -152,20 +143,6 @@ static struct {
};
-
-static const char *
-std_cmd_name (int cmd_id)
-{
- int i;
-
- for (i=0; std_cmd_table[i].name; i++)
- if (std_cmd_table[i].cmd_id == cmd_id)
- return std_cmd_table[i].name;
- return NULL;
-}
-
-
-
/**
* assuan_register_command:
* @ctx: the server context
@@ -175,8 +152,8 @@ std_cmd_name (int cmd_id)
*
* Register a handler to be used for a given command.
*
- * The @cmd_name must be %NULL for all @cmd_ids below
- * %ASSUAN_CMD_USER becuase predefined values are used.
+ * The @cmd_name must be %NULL or an empty string for all @cmd_ids
+ * below %ASSUAN_CMD_USER because predefined values are used.
*
* Return value:
**/
@@ -185,17 +162,63 @@ assuan_register_command (ASSUAN_CONTEXT ctx,
int cmd_id, const char *cmd_name,
int (*handler)(ASSUAN_CONTEXT, char *))
{
- if (cmd_name && cmd_id < ASSUAN_CMD_USER)
- return ASSUAN_Invalid_Value;
+ int i;
+
+ if (cmd_name && !*cmd_name)
+ cmd_name = NULL;
+
+ if (cmd_id < ASSUAN_CMD_USER)
+ {
+ if (cmd_name)
+ return ASSUAN_Invalid_Value; /* must be NULL for these values*/
+
+ for (i=0; std_cmd_table[i].name; i++)
+ {
+ if (std_cmd_table[i].cmd_id == cmd_id)
+ {
+ cmd_name = std_cmd_table[i].name;
+ if (!handler)
+ handler = std_cmd_table[i].handler;
+ break;
+ }
+ }
+ if (!std_cmd_table[i].name)
+ return ASSUAN_Invalid_Value; /* not a pre-registered one */
+ }
- if (!cmd_name)
- cmd_name = std_cmd_name (cmd_id);
+ if (!handler)
+ handler = dummy_handler;
if (!cmd_name)
- return ASSUAN_Invalid_Value;
-
+ return ASSUAN_Invalid_Value;
+
fprintf (stderr, "DBG-assuan: registering %d as `%s'\n", cmd_id, cmd_name);
+ if (!ctx->cmdtbl)
+ {
+ ctx->cmdtbl_size = 10;
+ ctx->cmdtbl = xtrycalloc ( ctx->cmdtbl_size, sizeof *ctx->cmdtbl);
+ if (!ctx->cmdtbl)
+ return ASSUAN_Out_Of_Core;
+ ctx->cmdtbl_used = 0;
+ }
+ else if (ctx->cmdtbl_used >= ctx->cmdtbl_size)
+ {
+ 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[ctx->cmdtbl_used].name = cmd_name;
+ ctx->cmdtbl[ctx->cmdtbl_used].cmd_id = cmd_id;
+ ctx->cmdtbl[ctx->cmdtbl_used].handler = handler;
+ ctx->cmdtbl_used++;
return 0;
}
@@ -209,8 +232,8 @@ _assuan_register_std_commands (ASSUAN_CONTEXT ctx)
{
if (std_cmd_table[i].always)
{
- rc = assuan_register_command (ctx, std_cmd_table[i].cmd_id, NULL,
- std_cmd_table[i].handler);
+ rc = assuan_register_command (ctx, std_cmd_table[i].cmd_id,
+ NULL, NULL);
if (rc)
return rc;
}
@@ -223,7 +246,7 @@ _assuan_register_std_commands (ASSUAN_CONTEXT ctx)
/* Process the special data lines. The "D " has already been removed
from the line. As all handlers this function may modify the line. */
static int
-handle_data_line (ASSUAN_CONTEXT ctx, char *line)
+handle_data_line (ASSUAN_CONTEXT ctx, char *line, int linelen)
{
return set_error (ctx, Not_Implemented, NULL);
}
@@ -233,20 +256,102 @@ handle_data_line (ASSUAN_CONTEXT ctx, char *line)
table, remove leading and white spaces from the arguments, all the
handler with the argument line and return the error */
static int
-dispatch_command (ASSUAN_CONTEXT ctx, char *line)
+dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen)
{
- if (*line == 'D' && line[1] == ' ') /* divert to special handler */
- return handle_data_line (ctx, line+2);
+ char *p;
+ const char *s;
+ int shift, i;
-
- return set_error (ctx, Not_Implemented, NULL);
+ if (*line == 'D' && line[1] == ' ') /* divert to special handler */
+ return handle_data_line (ctx, line+2, linelen-2);
+
+ for (p=line; *p && *p != ' ' && *p != '\t'; p++)
+ ;
+ if (p==line)
+ return set_error (ctx, Invalid_Command, "leading white-space");
+ if (*p)
+ { /* Skip over leading WS after the keyword */
+ *p++ = 0;
+ while ( *p == ' ' || *p == '\t')
+ p++;
+ }
+ shift = p - line;
+
+ for (i=0; (s=ctx->cmdtbl[i].name); i++)
+ if (!strcmp (line, s))
+ break;
+ if (!s)
+ return set_error (ctx, Unknown_Command, NULL);
+ line += shift;
+ linelen -= shift;
+
+ fprintf (stderr, "DBG-assuan: processing %s `%s'\n", s, line);
+ return ctx->cmdtbl[i].handler (ctx, line);
}
-
-
+/**
+ * assuan_process:
+ * @ctx: assuan context
+ *
+ * This fucntion is used to handle the assuan protocol after a
+ * connection has been established using assuan_accept(). This is the
+ * main protocol handler.
+ *
+ * Return value: 0 on success or an error code if the assuan operation
+ * failed. Note, that no error is returned for operational errors.
+ **/
+int
+assuan_process (ASSUAN_CONTEXT ctx)
+{
+ int rc;
+
+ do {
+ /* Read the line but skip comments */
+ do
+ {
+ rc = _assuan_read_line (ctx);
+ if (rc)
+ return rc;
+
+ 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 */
+ rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen);
+ if (!rc)
+ 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");
+ }
+ else
+ {
+ char errline[256];
+
+ if (rc < 100)
+ sprintf (errline, "ERR %d server fault (%.50s)",
+ ASSUAN_Server_Fault, assuan_strerror (rc));
+ else
+ {
+ const char *text = ctx->err_no == rc? ctx->err_str:NULL;
+
+ sprintf (errline, "ERR %d %.50s%s%.100s",
+ rc, assuan_strerror (rc), text? " - ":"", text?text:"");
+ }
+ rc = _assuan_write_line (ctx, errline);
+ }
+ } while (!rc);
+
+ if (rc == -1)
+ rc = 0;
+
+ return rc;
+}