diff options
author | Werner Koch <[email protected]> | 2001-11-07 17:43:05 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2001-11-07 17:43:05 +0000 |
commit | d5aea23fcaa3b05240242b8a8a192a0ea74bd9b8 (patch) | |
tree | 4bed195af93f9611e75c3cb12ef3bf077379a2b1 /src/assuan-handler.c | |
parent | gpgsm does now build and a dummy server can be started. (diff) | |
download | libassuan-d5aea23fcaa3b05240242b8a8a192a0ea74bd9b8.tar.gz libassuan-d5aea23fcaa3b05240242b8a8a192a0ea74bd9b8.zip |
Assuan server mode is now basically usable
Diffstat (limited to '')
-rw-r--r-- | src/assuan-handler.c | 189 |
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; +} |