Add IF command and new variable functions to gpg-connect-agent.
authorWerner Koch <wk@gnupg.org>
Wed, 5 Mar 2008 10:08:10 +0000 (10:08 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 5 Mar 2008 10:08:10 +0000 (10:08 +0000)
doc/ChangeLog
doc/debugging.texi
doc/gpg.texi
doc/tools.texi
tools/ChangeLog
tools/gpg-connect-agent.c

index 72f9d33..ebc1c42 100644 (file)
@@ -2,6 +2,10 @@
 
        * tools.texi (Listing options): Document new types.
 
+2008-02-26  Werner Koch  <wk@g10code.com>
+
+       * gpg.texi (GPG Configuration Options): Mention rfc4398.
+
 2008-02-05  David Shaw  <dshaw@jabberwocky.com>
 
        * gpg.texi (GPG Esoteric Options): Tweak mention of Tempest font
index 242d601..1c9ec84 100644 (file)
@@ -16,7 +16,8 @@ solve the problem at hand.
 
 
 @menu
-* Debugging Tools::       Description of some useful tools
+* Debugging Tools::       Description of some useful tools.
+* Debugging Hints::       Various hints on debugging.
 * Common Problems::       Commonly seen problems.
 * Architecture Details::  How the whole thing works internally.
 @end menu
@@ -84,8 +85,26 @@ should not occur but sometimes things go wrong), run it using
 @samp{kbxutil --find-dups ~/.gnupg/pubring.kbx}
 
 
+@node Debugging Hints
+@section Various hints on debugging.
 
+@itemize @bullet
+
+@item How to find the IP address of a keyserver
+
+If a round robin URL of is used for a keyserver
+(e.g. subkeys.gnupg.org); it is not easy to see what server is actually
+used.  Using the keyserver debug option as in
 
+@smallexample
+ gpg --keyserver-options debug=1 -v --refresh-key 1E42B367
+@end smallexample
+
+is thus often helpful.  Note that the actual output depends on the
+backend and may change from release to release.
+
+
+@end itemize
 
 
 @node Common Problems
index 3fd33ed..4501632 100644 (file)
@@ -1311,8 +1311,7 @@ arguments, in the order they are to be tried:
 @table @asis
 
 @item cert
-locate a key using DNS CERT, as specified in 2538bis (currently in
-draft): http://www.josefsson.org/rfc2538bis/
+locate a key using DNS CERT, as specified in rfc4398.
 
 @item pka
 locate a key using DNS PKA.
index be4978f..b86972c 100644 (file)
@@ -1215,14 +1215,29 @@ Escape the @var{args} using percent style ecaping.  Tabs, formfeeds,
 linefeeds, carriage returns and colons are escaped. @code{percent+} also
 maps spaces to plus signs.
 
+@item errcode @var{arg}
+@itemx errsource @var{arg}
+@itemx errstring @var{arg}
+Assume @var{arg} is an integer and evaluate it using @code{strtol}.  Return
+the gpg-error error code, error source or a formatted string with the
+error code and error source.
+
+
 @item +
 @itemx -
-@item *
-@item /
-@item %
+@itemx *
+@itemx /
+@itemx %
 Evaluate all arguments as long integers using @code{strtol} and apply
 this operator.  A division by zero yields an empty string.
 
+@item !
+@itemx |
+@itemx &
+Evaluate all arguments as long integers using @code{strtol} and apply
+the logical oeprators NOT, OR or AND.  The NOT operator works on the
+last argument only.
+
 
 @end table
 
index 0f3ebd4..7d4e963 100644 (file)
@@ -1,3 +1,10 @@
+2008-03-05  Werner Koch  <wk@g10code.com>
+
+       * gpg-connect-agent.c (arithmetic_op): Add logical not, or and and.
+       (get_var_ext): Add functions errcode, errsource and errstring.
+       (read_and_print_response): Store server reply in $? variable.
+       (main): Implement IF command.
+
 2008-02-27  Marcus Brinkmann  <marcus@g10code.de>
 
        * gpgconf-comp.c (option_check_validity): For now, error out on
index 57eed64..c76f0e2 100644 (file)
@@ -1,5 +1,5 @@
 /* gpg-connect-agent.c - Tool to connect to the agent.
- *     Copyright (C) 2005, 2007 Free Software Foundation, Inc.
+ *     Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -416,6 +416,9 @@ arithmetic_op (int operator, const char *operands)
   result = strtol (operands, NULL, 0);
   while (*operands && !spacep (operands) )
     operands++;
+  if (operator == '!')
+    result = !result;
+
   while (*operands)
     {
       while ( spacep (operands) )
@@ -440,6 +443,9 @@ arithmetic_op (int operator, const char *operands)
             return NULL;
           result %= value;
           break;
+        case '!': result = !value; break;
+        case '|': result = result || value; break;
+        case '&': result = result && value; break;
         default:
           log_error ("unknown arithmetic operator `%c'\n", operator);
           return NULL;
@@ -452,7 +458,7 @@ arithmetic_op (int operator, const char *operands)
 
 
 /* Extended version of get_var.  This returns a malloced string and
-   understand the fucntion syntax: "func args". 
+   understand the function syntax: "func args". 
 
    Defined functions are
    
@@ -486,6 +492,16 @@ arithmetic_op (int operator, const char *operands)
            linefeeds and carriage returns are also escaped.
            "percent+" also maps spaces to plus characters.
 
+     errcode ARG
+           Assuming ARG is an integer, return the gpg-error code.
+
+     errsource ARG
+           Assuming ARG is an integer, return the gpg-error source.
+
+     errstring ARG
+           Assuming ARG is an integer return a formatted fpf error string.
+
+
    Example: get_var_ext ("get sysconfdir") -> "/etc/gnupg"
     
   */
@@ -497,6 +513,7 @@ get_var_ext (const char *name)
   char *result;
   char *p;
   char *free_me = NULL;
+  int intvalue;
 
   if (recursion_count > 50)
     {
@@ -538,11 +555,7 @@ get_var_ext (const char *name)
       else if (!strcmp (s, "datadir"))
         result = xstrdup (gnupg_datadir ());
       else if (!strcmp (s, "serverpid"))
-        {
-          char numbuf[30];
-          snprintf (numbuf, sizeof numbuf, "%d", (int)server_pid);
-          result = xstrdup (numbuf);
-        }
+        result = xasprintf ("%d", (int)server_pid);
       else
         {
           log_error ("invalid argument `%s' for variable function `get'\n", s);
@@ -579,7 +592,26 @@ get_var_ext (const char *name)
         if (*p == ' ')
           *p = '+';
     }
-  else if ( (s - name) == 1 && strchr ("+-*/%", *name))
+  else if ( (s - name) == 7 && !strncmp (name, "errcode", 7))
+    {
+      s++;
+      intvalue = (int)strtol (s, NULL, 0);
+      result = xasprintf ("%d", gpg_err_code (intvalue));
+    }
+  else if ( (s - name) == 9 && !strncmp (name, "errsource", 9))
+    {
+      s++;
+      intvalue = (int)strtol (s, NULL, 0);
+      result = xasprintf ("%d", gpg_err_source (intvalue));
+    }
+  else if ( (s - name) == 9 && !strncmp (name, "errstring", 9))
+    {
+      s++;
+      intvalue = (int)strtol (s, NULL, 0);
+      result = xasprintf ("%s <%s>", 
+                          gpg_strerror (intvalue), gpg_strsource (intvalue));
+    }
+  else if ( (s - name) == 1 && strchr ("+-*/%!|&", *name))
     {
       result = arithmetic_op (*name, s+1);
     }
@@ -1098,6 +1130,7 @@ main (int argc, char **argv)
     loopline_t *tail;
     loopline_t current;
     unsigned int nestlevel; 
+    int oneshot;
     char *condition;
   } loopstack[20];
   int        loopidx;
@@ -1523,7 +1556,7 @@ main (int argc, char **argv)
             {
               if (loopidx+2 >= (int)DIM(loopstack))
                 {
-                  log_error ("loops are nested too deep\n");
+                  log_error ("blocks are nested too deep\n");
                   /* We should better die or break all loop in this
                      case as recovering from this error won't be
                      easy.  */
@@ -1534,10 +1567,31 @@ main (int argc, char **argv)
                   loopstack[loopidx+1].tail = &loopstack[loopidx+1].head;
                   loopstack[loopidx+1].current = NULL;
                   loopstack[loopidx+1].nestlevel = 1;
+                  loopstack[loopidx+1].oneshot = 0;
                   loopstack[loopidx+1].condition = xstrdup (p);
                   loopstack[loopidx+1].collecting = 1;
                 }
             }
+          else if (!strcmp (cmd, "if"))
+            {
+              if (loopidx+2 >= (int)DIM(loopstack))
+                {
+                  log_error ("blocks are nested too deep\n");
+                }
+              else
+                {
+                  /* Note that we need to evaluate the condition right
+                     away and not just at the end of the block as we
+                     do with a WHILE. */
+                  loopstack[loopidx+1].head = NULL;
+                  loopstack[loopidx+1].tail = &loopstack[loopidx+1].head;
+                  loopstack[loopidx+1].current = NULL;
+                  loopstack[loopidx+1].nestlevel = 1;
+                  loopstack[loopidx+1].oneshot = 1;
+                  loopstack[loopidx+1].condition = substitute_line_copy (p);
+                  loopstack[loopidx+1].collecting = 1;
+                }
+            }
           else if (!strcmp (cmd, "end"))
             {
               if (loopidx < 0)
@@ -1550,6 +1604,11 @@ main (int argc, char **argv)
 
                   /* Evaluate the condition.  */
                   tmpcond = xstrdup (loopstack[loopidx].condition);
+                  if (loopstack[loopidx].oneshot)
+                    {
+                      xfree (loopstack[loopidx].condition);
+                      loopstack[loopidx].condition = xstrdup ("0");
+                    }
                   tmpline = substitute_line (tmpcond);
                   value = tmpline? tmpline : tmpcond;
                   condition = strtol (value, NULL, 0);
@@ -1574,6 +1633,7 @@ main (int argc, char **argv)
                       loopstack[loopidx].current = NULL;
                       loopstack[loopidx].nestlevel = 0;
                       loopstack[loopidx].collecting = 0;
+                      loopstack[loopidx].oneshot = 0;
                       xfree (loopstack[loopidx].condition);
                       loopstack[loopidx].condition = NULL;
                       loopidx--;
@@ -1610,8 +1670,9 @@ main (int argc, char **argv)
 "/[no]decode            Enable decoding of received data lines.\n"
 "/[no]subst             Enable varibale substitution.\n"
 "/run FILE              Run commands from FILE.\n"
+"/if VAR                Begin conditional block controlled by VAR.\n"
 "/while VAR             Begin loop controlled by VAR.\n"
-"/end                   End loop.\n"
+"/end                   End loop or condition\n"
 "/bye                   Terminate gpg-connect-agent.\n"
 "/help                  Print this help.");
             }
@@ -1885,12 +1946,19 @@ read_and_print_response (assuan_context_t ctx, int *r_goterr)
             {
               fwrite (line, linelen, 1, stdout);
               putchar ('\n');
+              set_int_var ("?", 0);
               return 0;
             }
           else if (linelen >= 3
                    && line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
                    && (line[3] == '\0' || line[3] == ' '))
             {
+              int errval;
+
+              errval = strtol (line+3, NULL, 10);
+              if (!errval)
+                errval = -1;
+              set_int_var ("?", errval);
               fwrite (line, linelen, 1, stdout);
               putchar ('\n');
               *r_goterr = 1;