mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-02 22:46:30 +02:00
Assuan server mode is now basically usable
This commit is contained in:
parent
4fcb72b382
commit
7166bd6a5d
10 changed files with 426 additions and 59 deletions
|
@ -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)
|
||||
{
|
||||
char *p;
|
||||
const char *s;
|
||||
int shift, i;
|
||||
|
||||
if (*line == 'D' && line[1] == ' ') /* divert to special handler */
|
||||
return handle_data_line (ctx, line+2);
|
||||
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;
|
||||
|
||||
return set_error (ctx, Not_Implemented, NULL);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue