* assuan.h: Added Invalid Option error code.
authorWerner Koch <wk@gnupg.org>
Sun, 20 Jan 2002 16:49:34 +0000 (16:49 +0000)
committerWerner Koch <wk@gnupg.org>
Sun, 20 Jan 2002 16:49:34 +0000 (16:49 +0000)
* assuan-handler.c (std_handler_option): New.
(std_cmd_tbl): Add OPTION as standard command.
(assuan_register_option_handler): New.
(dispatch_command): Use case insensitive matching as a fallback.
(my_strcasecmp): New.

assuan/ChangeLog
assuan/assuan-defs.h
assuan/assuan-handler.c
assuan/assuan.h

index 3c3fdcd..d12acee 100644 (file)
@@ -1,3 +1,13 @@
+2002-01-20  Werner Koch  <wk@gnupg.org>
+
+       * assuan.h: Added Invalid Option error code.
+
+       * assuan-handler.c (std_handler_option): New.
+       (std_cmd_tbl): Add OPTION as standard command.
+       (assuan_register_option_handler): New.
+       (dispatch_command): Use case insensitive matching as a fallback.
+       (my_strcasecmp): New.
+
 2002-01-19  Werner Koch  <wk@gnupg.org>
 
        * assuan-buffer.c (_assuan_read_line): Add output logging.
index d19e6b9..c14b409 100644 (file)
@@ -87,6 +87,7 @@ struct assuan_context_s {
   void (*bye_notify_fnc)(ASSUAN_CONTEXT);
   void (*reset_notify_fnc)(ASSUAN_CONTEXT);
   void (*cancel_notify_fnc)(ASSUAN_CONTEXT);
+  int  (*option_handler_fnc)(ASSUAN_CONTEXT,const char*, const char*);
   void (*input_notify_fnc)(ASSUAN_CONTEXT, const char *);
   void (*output_notify_fnc)(ASSUAN_CONTEXT, const char *);
 
index db9749e..1c8aded 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "assuan-defs.h"
 
+#define spacep(p)  (*(p) == ' ' || *(p) == '\t')
 #define digitp(a) ((a) >= '0' && (a) <= '9')
 
 
@@ -48,6 +49,53 @@ std_handler_cancel (ASSUAN_CONTEXT ctx, char *line)
     ctx->cancel_notify_fnc (ctx);
   return set_error (ctx, Not_Implemented, NULL); 
 }
+
+static int
+std_handler_option (ASSUAN_CONTEXT ctx, char *line)
+{
+  char *key, *value, *p;
+
+  for (key=line; spacep (key); key++)
+    ;
+  if (!*key)
+    return set_error (ctx, Syntax_Error, "argument required");
+  if (*key == '=')
+    return set_error (ctx, Syntax_Error, "no option name given");
+  for (value=key; *value && !spacep (value) && *value != '='; value++)
+    ;
+  if (*value)
+    {
+      if (spacep (value))
+        *value++ = 0; /* terminate key */
+      for (; spacep (value); value++)
+        ;
+      if (*value == '=')
+        {
+          *value++ = 0; /* terminate key */
+          for (; spacep (value); value++)
+            ;
+          if (!*value)
+            return set_error (ctx, Syntax_Error, "option argument expected");
+        }
+      if (*value)
+        {
+          for (p = value + strlen(value) - 1; p > value && spacep (p); p--)
+            ;
+          if (p > value)
+            *++p = 0; /* strip trailing spaces */
+        }
+    }
+
+  if (*key == '-' && key[1] == '-' && key[2])
+    key += 2; /* the double dashes are optional */
+  if (*key == '-')
+    return set_error (ctx, Syntax_Error,
+                      "option should not begin with one dash");
+
+  if (ctx->option_handler_fnc)
+    return ctx->option_handler_fnc (ctx, key, value);
+  return 0;
+}
   
 static int
 std_handler_bye (ASSUAN_CONTEXT ctx, char *line)
@@ -147,6 +195,7 @@ static struct {
 } std_cmd_table[] = {
   { "NOP",    ASSUAN_CMD_NOP,    std_handler_nop, 1 },
   { "CANCEL", ASSUAN_CMD_CANCEL, std_handler_cancel, 1 },
+  { "OPTION", ASSUAN_CMD_OPTION, std_handler_option, 1 },
   { "BYE",    ASSUAN_CMD_BYE,    std_handler_bye, 1 },
   { "AUTH",   ASSUAN_CMD_AUTH,   std_handler_auth, 1 },
   { "RESET",  ASSUAN_CMD_RESET,  std_handler_reset, 1 },
@@ -154,6 +203,7 @@ static struct {
 
   { "INPUT",  ASSUAN_CMD_INPUT,  std_handler_input },
   { "OUTPUT", ASSUAN_CMD_OUTPUT, std_handler_output },
+  { "OPTION", ASSUAN_CMD_OPTION, std_handler_option, 1 },
   { NULL }
 };
 
@@ -263,6 +313,17 @@ assuan_register_cancel_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
 }
 
 int
+assuan_register_option_handler (ASSUAN_CONTEXT ctx,
+                               int (*fnc)(ASSUAN_CONTEXT,
+                                          const char*, const char*))
+{
+  if (!ctx)
+    return ASSUAN_Invalid_Value;
+  ctx->option_handler_fnc = fnc;
+  return 0;
+}
+
+int
 assuan_register_input_notify (ASSUAN_CONTEXT ctx,
                               void (*fnc)(ASSUAN_CONTEXT, const char *))
 {
@@ -312,6 +373,20 @@ handle_data_line (ASSUAN_CONTEXT ctx, char *line, int linelen)
   return set_error (ctx, Not_Implemented, NULL);
 }
 
+/* like ascii_strcasecmp but assume that B is already uppercase */
+static int
+my_strcasecmp (const char *a, const char *b)
+{
+    if (a == b)
+        return 0;
+
+    for (; *a && *b; a++, b++)
+      {
+       if (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) != *b)
+           break;
+      }
+    return *a == *b? 0 : (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) - *b);
+}
 
 /* Parse the line, break out the command, find it in the command
    table, remove leading and white spaces from the arguments, all the
@@ -339,8 +414,18 @@ dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen)
   shift = p - line;
 
   for (i=0; (s=ctx->cmdtbl[i].name); i++)
-    if (!strcmp (line, s))
-      break;
+    {
+      if (!strcmp (line, s))
+        break;
+    }
+  if (!s)
+    { /* and try case insensitive */
+      for (i=0; (s=ctx->cmdtbl[i].name); i++)
+        {
+          if (!my_strcasecmp (line, s))
+            break;
+        }
+    }
   if (!s)
     return set_error (ctx, Unknown_Command, NULL);
   line += shift;
index 3382283..31d6fbd 100644 (file)
@@ -72,6 +72,7 @@ typedef enum {
   ASSUAN_Too_Much_Data = 119,
   ASSUAN_Inquire_Unknown = 120,
   ASSUAN_Inquire_Error = 121,
+  ASSUAN_Invalid_Option = 122,
 
   ASSUAN_Bad_Certificate = 201,
   ASSUAN_Bad_Certificate_Path = 202,
@@ -97,6 +98,7 @@ typedef enum {
   ASSUAN_CMD_BYE,
   ASSUAN_CMD_AUTH,
   ASSUAN_CMD_RESET,
+  ASSUAN_CMD_OPTION,
   ASSUAN_CMD_DATA,
   ASSUAN_CMD_END,
   ASSUAN_CMD_INPUT,
@@ -124,6 +126,11 @@ int assuan_register_input_notify (ASSUAN_CONTEXT ctx,
                                   void (*fnc)(ASSUAN_CONTEXT, const char *));
 int assuan_register_output_notify (ASSUAN_CONTEXT ctx,
                                   void (*fnc)(ASSUAN_CONTEXT, const char *));
+
+int assuan_register_option_handler (ASSUAN_CONTEXT ctx,
+                                    int (*fnc)(ASSUAN_CONTEXT,
+                                               const char*, const char*));
+
 int assuan_process (ASSUAN_CONTEXT ctx);
 int assuan_process_next (ASSUAN_CONTEXT ctx);
 int assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what,