From e751bcdd04f7ff05f7b63c9e9214699486084869 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 5 Mar 2008 10:08:10 +0000 Subject: [PATCH] Add IF command and new variable functions to gpg-connect-agent. --- doc/ChangeLog | 4 ++ doc/debugging.texi | 21 +++++++++- doc/gpg.texi | 3 +- doc/tools.texi | 21 ++++++++-- tools/ChangeLog | 7 ++++ tools/gpg-connect-agent.c | 88 ++++++++++++++++++++++++++++++++++----- 6 files changed, 128 insertions(+), 16 deletions(-) diff --git a/doc/ChangeLog b/doc/ChangeLog index 72f9d33c5..ebc1c4248 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -2,6 +2,10 @@ * tools.texi (Listing options): Document new types. +2008-02-26 Werner Koch + + * gpg.texi (GPG Configuration Options): Mention rfc4398. + 2008-02-05 David Shaw * gpg.texi (GPG Esoteric Options): Tweak mention of Tempest font diff --git a/doc/debugging.texi b/doc/debugging.texi index 242d601cb..1c9ec8413 100644 --- a/doc/debugging.texi +++ b/doc/debugging.texi @@ -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 diff --git a/doc/gpg.texi b/doc/gpg.texi index 3fd33ed16..4501632f2 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -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. diff --git a/doc/tools.texi b/doc/tools.texi index be4978f41..b86972cac 100644 --- a/doc/tools.texi +++ b/doc/tools.texi @@ -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 diff --git a/tools/ChangeLog b/tools/ChangeLog index 0f3ebd4be..7d4e96390 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,10 @@ +2008-03-05 Werner Koch + + * 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 * gpgconf-comp.c (option_check_validity): For now, error out on diff --git a/tools/gpg-connect-agent.c b/tools/gpg-connect-agent.c index 57eed64f0..c76f0e219 100644 --- a/tools/gpg-connect-agent.c +++ b/tools/gpg-connect-agent.c @@ -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;