LCOV - code coverage report
Current view: top level - tools - gpg-connect-agent.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 163 1039 15.7 %
Date: 2016-09-12 12:29:17 Functions: 6 27 22.2 %

          Line data    Source code
       1             : /* gpg-connect-agent.c - Tool to connect to the agent.
       2             :  * Copyright (C) 2005, 2007, 2008, 2010 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2014 Werner Koch
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * GnuPG is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * GnuPG is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : 
      23             : #include <stdio.h>
      24             : #include <stdlib.h>
      25             : #include <string.h>
      26             : #include <errno.h>
      27             : #include <ctype.h>
      28             : #include <assuan.h>
      29             : #include <unistd.h>
      30             : #include <assert.h>
      31             : 
      32             : #include "i18n.h"
      33             : #include "../common/util.h"
      34             : #include "../common/asshelp.h"
      35             : #include "../common/sysutils.h"
      36             : #include "../common/membuf.h"
      37             : #include "../common/ttyio.h"
      38             : #ifdef HAVE_W32_SYSTEM
      39             : #  include "../common/exechelp.h"
      40             : #endif
      41             : #include "../common/init.h"
      42             : 
      43             : 
      44             : #define CONTROL_D ('D' - 'A' + 1)
      45             : #define octdigitp(p) (*(p) >= '0' && *(p) <= '7')
      46             : 
      47             : /* Constants to identify the commands and options. */
      48             : enum cmd_and_opt_values
      49             :   {
      50             :     aNull = 0,
      51             :     oQuiet      = 'q',
      52             :     oVerbose    = 'v',
      53             :     oRawSocket  = 'S',
      54             :     oTcpSocket  = 'T',
      55             :     oExec       = 'E',
      56             :     oRun        = 'r',
      57             :     oSubst      = 's',
      58             : 
      59             :     oNoVerbose  = 500,
      60             :     oHomedir,
      61             :     oAgentProgram,
      62             :     oDirmngrProgram,
      63             :     oHex,
      64             :     oDecode,
      65             :     oNoExtConnect,
      66             :     oDirmngr,
      67             :     oUIServer,
      68             :     oNoAutostart,
      69             : 
      70             :   };
      71             : 
      72             : 
      73             : /* The list of commands and options. */
      74             : static ARGPARSE_OPTS opts[] = {
      75             :   ARGPARSE_group (301, N_("@\nOptions:\n ")),
      76             : 
      77             :   ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
      78             :   ARGPARSE_s_n (oQuiet, "quiet",     N_("quiet")),
      79             :   ARGPARSE_s_n (oHex,   "hex",       N_("print data out hex encoded")),
      80             :   ARGPARSE_s_n (oDecode,"decode",    N_("decode received data lines")),
      81             :   ARGPARSE_s_n (oDirmngr,"dirmngr",  N_("connect to the dirmngr")),
      82             :   ARGPARSE_s_n (oUIServer, "uiserver", "@"),
      83             :   ARGPARSE_s_s (oRawSocket, "raw-socket",
      84             :                 N_("|NAME|connect to Assuan socket NAME")),
      85             :   ARGPARSE_s_s (oTcpSocket, "tcp-socket",
      86             :                 N_("|ADDR|connect to Assuan server at ADDR")),
      87             :   ARGPARSE_s_n (oExec, "exec",
      88             :                 N_("run the Assuan server given on the command line")),
      89             :   ARGPARSE_s_n (oNoExtConnect, "no-ext-connect",
      90             :                 N_("do not use extended connect mode")),
      91             :   ARGPARSE_s_s (oRun,  "run",
      92             :                 N_("|FILE|run commands from FILE on startup")),
      93             :   ARGPARSE_s_n (oSubst, "subst",     N_("run /subst on startup")),
      94             : 
      95             :   ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"),
      96             :   ARGPARSE_s_n (oNoVerbose, "no-verbose", "@"),
      97             :   ARGPARSE_s_s (oHomedir, "homedir", "@" ),
      98             :   ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
      99             :   ARGPARSE_s_s (oDirmngrProgram, "dirmngr-program", "@"),
     100             : 
     101             :   ARGPARSE_end ()
     102             : };
     103             : 
     104             : 
     105             : /* We keep all global options in the structure OPT.  */
     106             : struct
     107             : {
     108             :   int verbose;          /* Verbosity level.  */
     109             :   int quiet;            /* Be extra quiet.  */
     110             :   int autostart;        /* Start the server if not running.  */
     111             :   const char *homedir;  /* Configuration directory name */
     112             :   const char *agent_program;  /* Value of --agent-program.  */
     113             :   const char *dirmngr_program;  /* Value of --dirmngr-program.  */
     114             :   int hex;              /* Print data lines in hex format. */
     115             :   int decode;           /* Decode received data lines.  */
     116             :   int use_dirmngr;      /* Use the dirmngr and not gpg-agent.  */
     117             :   int use_uiserver;     /* Use the standard UI server.  */
     118             :   const char *raw_socket; /* Name of socket to connect in raw mode. */
     119             :   const char *tcp_socket; /* Name of server to connect in tcp mode. */
     120             :   int exec;             /* Run the pgm given on the command line. */
     121             :   unsigned int connect_flags;    /* Flags used for connecting. */
     122             :   int enable_varsubst;  /* Set if variable substitution is enabled.  */
     123             :   int trim_leading_spaces;
     124             : } opt;
     125             : 
     126             : 
     127             : 
     128             : /* Definitions for /definq commands and a global linked list with all
     129             :    the definitions. */
     130             : struct definq_s
     131             : {
     132             :   struct definq_s *next;
     133             :   char *name;     /* Name of inquiry or NULL for any name. */
     134             :   int is_var;     /* True if FILE is a variable name. */
     135             :   int is_prog;    /* True if FILE is a program to run. */
     136             :   char file[1];   /* Name of file or program. */
     137             : };
     138             : typedef struct definq_s *definq_t;
     139             : 
     140             : static definq_t definq_list;
     141             : static definq_t *definq_list_tail = &definq_list;
     142             : 
     143             : 
     144             : /* Variable definitions and glovbal table.  */
     145             : struct variable_s
     146             : {
     147             :   struct variable_s *next;
     148             :   char *value;  /* Malloced value - always a string.  */
     149             :   char name[1]; /* Name of the variable.  */
     150             : };
     151             : typedef struct variable_s *variable_t;
     152             : 
     153             : static variable_t variable_table;
     154             : 
     155             : 
     156             : /* To implement loops we store entire lines in a linked list.  */
     157             : struct loopline_s
     158             : {
     159             :   struct loopline_s *next;
     160             :   char line[1];
     161             : };
     162             : typedef struct loopline_s *loopline_t;
     163             : 
     164             : 
     165             : /* This is used to store the pid of the server.  */
     166             : static pid_t server_pid = (pid_t)(-1);
     167             : 
     168             : /* The current datasink file or NULL.  */
     169             : static FILE *current_datasink;
     170             : 
     171             : /* A list of open file descriptors. */
     172             : static struct
     173             : {
     174             :   int inuse;
     175             : #ifdef HAVE_W32_SYSTEM
     176             :   HANDLE handle;
     177             : #endif
     178             : } open_fd_table[256];
     179             : 
     180             : 
     181             : /*-- local prototypes --*/
     182             : static char *substitute_line_copy (const char *buffer);
     183             : static int read_and_print_response (assuan_context_t ctx, int withhash,
     184             :                                     int *r_goterr);
     185             : static assuan_context_t start_agent (void);
     186             : 
     187             : 
     188             : 
     189             : 
     190             : /* Print usage information and and provide strings for help. */
     191             : static const char *
     192           0 : my_strusage( int level )
     193             : {
     194             :   const char *p;
     195             : 
     196           0 :   switch (level)
     197             :     {
     198           0 :     case 11: p = "@GPG@-connect-agent (@GNUPG@)";
     199           0 :       break;
     200           0 :     case 13: p = VERSION; break;
     201           0 :     case 17: p = PRINTABLE_OS_NAME; break;
     202           0 :     case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
     203             : 
     204             :     case 1:
     205           0 :     case 40: p = _("Usage: @GPG@-connect-agent [options] (-h for help)");
     206           0 :       break;
     207             :     case 41:
     208           0 :       p = _("Syntax: @GPG@-connect-agent [options]\n"
     209             :             "Connect to a running agent and send commands\n");
     210           0 :       break;
     211           0 :     case 31: p = "\nHome: "; break;
     212           0 :     case 32: p = gnupg_homedir (); break;
     213           0 :     case 33: p = "\n"; break;
     214             : 
     215           0 :     default: p = NULL; break;
     216             :     }
     217           0 :   return p;
     218             : }
     219             : 
     220             : 
     221             : /* Unescape STRING and returned the malloced result.  The surrounding
     222             :    quotes must already be removed from STRING.  */
     223             : static char *
     224           0 : unescape_string (const char *string)
     225             : {
     226             :   const unsigned char *s;
     227             :   int esc;
     228             :   size_t n;
     229             :   char *buffer;
     230             :   unsigned char *d;
     231             : 
     232           0 :   n = 0;
     233           0 :   for (s = (const unsigned char*)string, esc=0; *s; s++)
     234             :     {
     235           0 :       if (esc)
     236             :         {
     237           0 :           switch (*s)
     238             :             {
     239             :             case 'b':
     240             :             case 't':
     241             :             case 'v':
     242             :             case 'n':
     243             :             case 'f':
     244             :             case 'r':
     245             :             case '"':
     246             :             case '\'':
     247           0 :             case '\\': n++; break;
     248             :             case 'x':
     249           0 :               if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2))
     250           0 :                 n++;
     251           0 :               break;
     252             : 
     253             :             default:
     254           0 :               if (s[1] && s[2]
     255           0 :                   && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
     256           0 :                 n++;
     257           0 :               break;
     258             :             }
     259           0 :           esc = 0;
     260             :         }
     261           0 :       else if (*s == '\\')
     262           0 :         esc = 1;
     263             :       else
     264           0 :         n++;
     265             :     }
     266             : 
     267           0 :   buffer = xmalloc (n+1);
     268           0 :   d = (unsigned char*)buffer;
     269           0 :   for (s = (const unsigned char*)string, esc=0; *s; s++)
     270             :     {
     271           0 :       if (esc)
     272             :         {
     273           0 :           switch (*s)
     274             :             {
     275           0 :             case 'b':  *d++ = '\b'; break;
     276           0 :             case 't':  *d++ = '\t'; break;
     277           0 :             case 'v':  *d++ = '\v'; break;
     278           0 :             case 'n':  *d++ = '\n'; break;
     279           0 :             case 'f':  *d++ = '\f'; break;
     280           0 :             case 'r':  *d++ = '\r'; break;
     281           0 :             case '"':  *d++ = '\"'; break;
     282           0 :             case '\'': *d++ = '\''; break;
     283           0 :             case '\\': *d++ = '\\'; break;
     284             :             case 'x':
     285           0 :               if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2))
     286             :                 {
     287           0 :                   s++;
     288           0 :                   *d++ = xtoi_2 (s);
     289           0 :                   s++;
     290             :                 }
     291           0 :               break;
     292             : 
     293             :             default:
     294           0 :               if (s[1] && s[2]
     295           0 :                   && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
     296             :                 {
     297           0 :                   *d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2);
     298           0 :                   s += 2;
     299             :                 }
     300           0 :               break;
     301             :             }
     302           0 :           esc = 0;
     303             :         }
     304           0 :       else if (*s == '\\')
     305           0 :         esc = 1;
     306             :       else
     307           0 :         *d++ = *s;
     308             :     }
     309           0 :   *d = 0;
     310           0 :   return buffer;
     311             : }
     312             : 
     313             : 
     314             : /* Do the percent unescaping and return a newly malloced string.
     315             :    If WITH_PLUS is set '+' characters will be changed to space. */
     316             : static char *
     317           0 : unpercent_string (const char *string, int with_plus)
     318             : {
     319             :   const unsigned char *s;
     320             :   unsigned char *buffer, *p;
     321             :   size_t n;
     322             : 
     323           0 :   n = 0;
     324           0 :   for (s=(const unsigned char *)string; *s; s++)
     325             :     {
     326           0 :       if (*s == '%' && s[1] && s[2])
     327             :         {
     328           0 :           s++;
     329           0 :           n++;
     330           0 :           s++;
     331             :         }
     332           0 :       else if (with_plus && *s == '+')
     333           0 :         n++;
     334             :       else
     335           0 :         n++;
     336             :     }
     337             : 
     338           0 :   buffer = xmalloc (n+1);
     339           0 :   p = buffer;
     340           0 :   for (s=(const unsigned char *)string; *s; s++)
     341             :     {
     342           0 :       if (*s == '%' && s[1] && s[2])
     343             :         {
     344           0 :           s++;
     345           0 :           *p++ = xtoi_2 (s);
     346           0 :           s++;
     347             :         }
     348           0 :       else if (with_plus && *s == '+')
     349           0 :         *p++ = ' ';
     350             :       else
     351           0 :         *p++ = *s;
     352             :     }
     353           0 :   *p = 0;
     354           0 :   return (char*)buffer;
     355             : }
     356             : 
     357             : 
     358             : 
     359             : 
     360             : 
     361             : static const char *
     362          43 : set_var (const char *name, const char *value)
     363             : {
     364             :   variable_t var;
     365             : 
     366          43 :   for (var = variable_table; var; var = var->next)
     367           0 :     if (!strcmp (var->name, name))
     368           0 :       break;
     369          43 :   if (!var)
     370             :     {
     371          43 :       var = xmalloc (sizeof *var + strlen (name));
     372          43 :       var->value = NULL;
     373          43 :       strcpy (var->name, name);
     374          43 :       var->next = variable_table;
     375          43 :       variable_table = var;
     376             :     }
     377          43 :   xfree (var->value);
     378          43 :   var->value = value? xstrdup (value) : NULL;
     379          43 :   return var->value;
     380             : }
     381             : 
     382             : 
     383             : static void
     384          43 : set_int_var (const char *name, int value)
     385             : {
     386             :   char numbuf[35];
     387             : 
     388          43 :   snprintf (numbuf, sizeof numbuf, "%d", value);
     389          43 :   set_var (name, numbuf);
     390          43 : }
     391             : 
     392             : 
     393             : /* Return the value of a variable.  That value is valid until a
     394             :    variable of the name is changed.  Return NULL if not found.  Note
     395             :    that envvars are copied to our variable list at the first access
     396             :    and not at oprogram start.  */
     397             : static const char *
     398           0 : get_var (const char *name)
     399             : {
     400             :   variable_t var;
     401             :   const char *s;
     402             : 
     403           0 :   if (!*name)
     404           0 :     return "";
     405           0 :   for (var = variable_table; var; var = var->next)
     406           0 :     if (!strcmp (var->name, name))
     407           0 :       break;
     408           0 :   if (!var && (s = getenv (name)))
     409           0 :     return set_var (name, s);
     410           0 :   if (!var || !var->value)
     411           0 :     return NULL;
     412           0 :   return var->value;
     413             : }
     414             : 
     415             : 
     416             : /* Perform some simple arithmentic operations.  Caller must release
     417             :    the return value.  On error the return value is NULL.  */
     418             : static char *
     419           0 : arithmetic_op (int operator, const char *operands)
     420             : {
     421             :   long result, value;
     422             :   char numbuf[35];
     423             : 
     424           0 :   while ( spacep (operands) )
     425           0 :     operands++;
     426           0 :   if (!*operands)
     427           0 :     return NULL;
     428           0 :   result = strtol (operands, NULL, 0);
     429           0 :   while (*operands && !spacep (operands) )
     430           0 :     operands++;
     431           0 :   if (operator == '!')
     432           0 :     result = !result;
     433             : 
     434           0 :   while (*operands)
     435             :     {
     436           0 :       while ( spacep (operands) )
     437           0 :         operands++;
     438           0 :       if (!*operands)
     439           0 :         break;
     440           0 :       value = strtol (operands, NULL, 0);
     441           0 :       while (*operands && !spacep (operands) )
     442           0 :         operands++;
     443           0 :       switch (operator)
     444             :         {
     445           0 :         case '+': result += value; break;
     446           0 :         case '-': result -= value; break;
     447           0 :         case '*': result *= value; break;
     448             :         case '/':
     449           0 :           if (!value)
     450           0 :             return NULL;
     451           0 :           result /= value;
     452           0 :           break;
     453             :         case '%':
     454           0 :           if (!value)
     455           0 :             return NULL;
     456           0 :           result %= value;
     457           0 :           break;
     458           0 :         case '!': result = !value; break;
     459           0 :         case '|': result = result || value; break;
     460           0 :         case '&': result = result && value; break;
     461             :         default:
     462           0 :           log_error ("unknown arithmetic operator '%c'\n", operator);
     463           0 :           return NULL;
     464             :         }
     465             :     }
     466           0 :   snprintf (numbuf, sizeof numbuf, "%ld", result);
     467           0 :   return xstrdup (numbuf);
     468             : }
     469             : 
     470             : 
     471             : 
     472             : /* Extended version of get_var.  This returns a malloced string and
     473             :    understand the function syntax: "func args".
     474             : 
     475             :    Defined functions are
     476             : 
     477             :      get - Return a value described by the next argument:
     478             :            cwd        - The current working directory.
     479             :            homedir    - The gnupg homedir.
     480             :            sysconfdir - GnuPG's system configuration directory.
     481             :            bindir     - GnuPG's binary directory.
     482             :            libdir     - GnuPG's library directory.
     483             :            libexecdir - GnuPG's library directory for executable files.
     484             :            datadir    - GnuPG's data directory.
     485             :            serverpid  - The PID of the current server.
     486             : 
     487             :      unescape ARGS
     488             :            Remove C-style escapes from string.  Note that "\0" and
     489             :            "\x00" terminate the string implictly.  Use "\x7d" to
     490             :            represent the closing brace.  The args start right after
     491             :            the first space after the function name.
     492             : 
     493             :      unpercent ARGS
     494             :      unpercent+ ARGS
     495             :            Remove percent style ecaping from string.  Note that "%00
     496             :            terminates the string implicitly.  Use "%7d" to represetn
     497             :            the closing brace.  The args start right after the first
     498             :            space after the function name.  "unpercent+" also maps '+'
     499             :            to space.
     500             : 
     501             :      percent ARGS
     502             :      percent+ ARGS
     503             :            Escape the args using the percent style.  Tabs, formfeeds,
     504             :            linefeeds, carriage return, and the plus sign are also
     505             :            escaped.  "percent+" also maps spaces to plus characters.
     506             : 
     507             :      errcode ARG
     508             :            Assuming ARG is an integer, return the gpg-error code.
     509             : 
     510             :      errsource ARG
     511             :            Assuming ARG is an integer, return the gpg-error source.
     512             : 
     513             :      errstring ARG
     514             :            Assuming ARG is an integer return a formatted fpf error string.
     515             : 
     516             : 
     517             :    Example: get_var_ext ("get sysconfdir") -> "/etc/gnupg"
     518             : 
     519             :   */
     520             : static char *
     521           0 : get_var_ext (const char *name)
     522             : {
     523             :   static int recursion_count;
     524             :   const char *s;
     525             :   char *result;
     526             :   char *p;
     527           0 :   char *free_me = NULL;
     528             :   int intvalue;
     529             : 
     530           0 :   if (recursion_count > 50)
     531             :     {
     532           0 :       log_error ("variables nested too deeply\n");
     533           0 :       return NULL;
     534             :     }
     535             : 
     536           0 :   recursion_count++;
     537           0 :   free_me = opt.enable_varsubst? substitute_line_copy (name) : NULL;
     538           0 :   if (free_me)
     539           0 :     name = free_me;
     540           0 :   for (s=name; *s && !spacep (s); s++)
     541             :     ;
     542           0 :   if (!*s)
     543             :     {
     544           0 :       s = get_var (name);
     545           0 :       result = s? xstrdup (s): NULL;
     546             :     }
     547           0 :   else if ( (s - name) == 3 && !strncmp (name, "get", 3))
     548             :     {
     549           0 :       while ( spacep (s) )
     550           0 :         s++;
     551           0 :       if (!strcmp (s, "cwd"))
     552             :         {
     553           0 :           result = gnupg_getcwd ();
     554           0 :           if (!result)
     555           0 :             log_error ("getcwd failed: %s\n", strerror (errno));
     556             :         }
     557           0 :       else if (!strcmp (s, "homedir"))
     558           0 :         result = xstrdup (gnupg_homedir ());
     559           0 :       else if (!strcmp (s, "sysconfdir"))
     560           0 :         result = xstrdup (gnupg_sysconfdir ());
     561           0 :       else if (!strcmp (s, "bindir"))
     562           0 :         result = xstrdup (gnupg_bindir ());
     563           0 :       else if (!strcmp (s, "libdir"))
     564           0 :         result = xstrdup (gnupg_libdir ());
     565           0 :       else if (!strcmp (s, "libexecdir"))
     566           0 :         result = xstrdup (gnupg_libexecdir ());
     567           0 :       else if (!strcmp (s, "datadir"))
     568           0 :         result = xstrdup (gnupg_datadir ());
     569           0 :       else if (!strcmp (s, "serverpid"))
     570           0 :         result = xasprintf ("%d", (int)server_pid);
     571             :       else
     572             :         {
     573           0 :           log_error ("invalid argument '%s' for variable function 'get'\n", s);
     574           0 :           log_info  ("valid are: cwd, "
     575             :                      "{home,bin,lib,libexec,data}dir, serverpid\n");
     576           0 :           result = NULL;
     577             :         }
     578             :     }
     579           0 :   else if ( (s - name) == 8 && !strncmp (name, "unescape", 8))
     580             :     {
     581           0 :       s++;
     582           0 :       result = unescape_string (s);
     583             :     }
     584           0 :   else if ( (s - name) == 9 && !strncmp (name, "unpercent", 9))
     585             :     {
     586           0 :       s++;
     587           0 :       result = unpercent_string (s, 0);
     588             :     }
     589           0 :   else if ( (s - name) == 10 && !strncmp (name, "unpercent+", 10))
     590             :     {
     591           0 :       s++;
     592           0 :       result = unpercent_string (s, 1);
     593             :     }
     594           0 :   else if ( (s - name) == 7 && !strncmp (name, "percent", 7))
     595             :     {
     596           0 :       s++;
     597           0 :       result = percent_escape (s, "+\t\r\n\f\v");
     598             :     }
     599           0 :   else if ( (s - name) == 8 && !strncmp (name, "percent+", 8))
     600             :     {
     601           0 :       s++;
     602           0 :       result = percent_escape (s, "+\t\r\n\f\v");
     603           0 :       for (p=result; *p; p++)
     604           0 :         if (*p == ' ')
     605           0 :           *p = '+';
     606             :     }
     607           0 :   else if ( (s - name) == 7 && !strncmp (name, "errcode", 7))
     608             :     {
     609           0 :       s++;
     610           0 :       intvalue = (int)strtol (s, NULL, 0);
     611           0 :       result = xasprintf ("%d", gpg_err_code (intvalue));
     612             :     }
     613           0 :   else if ( (s - name) == 9 && !strncmp (name, "errsource", 9))
     614             :     {
     615           0 :       s++;
     616           0 :       intvalue = (int)strtol (s, NULL, 0);
     617           0 :       result = xasprintf ("%d", gpg_err_source (intvalue));
     618             :     }
     619           0 :   else if ( (s - name) == 9 && !strncmp (name, "errstring", 9))
     620             :     {
     621           0 :       s++;
     622           0 :       intvalue = (int)strtol (s, NULL, 0);
     623           0 :       result = xasprintf ("%s <%s>",
     624             :                           gpg_strerror (intvalue), gpg_strsource (intvalue));
     625             :     }
     626           0 :   else if ( (s - name) == 1 && strchr ("+-*/%!|&", *name))
     627             :     {
     628           0 :       result = arithmetic_op (*name, s+1);
     629             :     }
     630             :   else
     631             :     {
     632           0 :       log_error ("unknown variable function '%.*s'\n", (int)(s-name), name);
     633           0 :       result = NULL;
     634             :     }
     635             : 
     636           0 :   xfree (free_me);
     637           0 :   recursion_count--;
     638           0 :   return result;
     639             : }
     640             : 
     641             : 
     642             : /* Substitute variables in LINE and return a new allocated buffer if
     643             :    required.  The function might modify LINE if the expanded version
     644             :    fits into it.  */
     645             : static char *
     646           0 : substitute_line (char *buffer)
     647             : {
     648           0 :   char *line = buffer;
     649             :   char *p, *pend;
     650             :   const char *value;
     651             :   size_t valuelen, n;
     652           0 :   char *result = NULL;
     653           0 :   char *freeme = NULL;
     654             : 
     655           0 :   while (*line)
     656             :     {
     657           0 :       p = strchr (line, '$');
     658           0 :       if (!p)
     659           0 :         return result; /* No more variables.  */
     660             : 
     661           0 :       if (p[1] == '$') /* Escaped dollar sign. */
     662             :         {
     663           0 :           memmove (p, p+1, strlen (p+1)+1);
     664           0 :           line = p + 1;
     665           0 :           continue;
     666             :         }
     667           0 :       if (p[1] == '{')
     668             :         {
     669           0 :           int count = 0;
     670             : 
     671           0 :           for (pend=p+2; *pend; pend++)
     672             :             {
     673           0 :               if (*pend == '{')
     674           0 :                 count++;
     675           0 :               else if (*pend == '}')
     676             :                 {
     677           0 :                   if (--count < 0)
     678           0 :                     break;
     679             :                 }
     680             :             }
     681           0 :           if (!*pend)
     682           0 :             return result; /* Unclosed - don't substitute.  */
     683             :         }
     684             :       else
     685             :         {
     686           0 :           for (pend=p+1; *pend && !spacep (pend) && *pend != '$' ; pend++)
     687             :             ;
     688             :         }
     689           0 :       if (p[1] == '{' && *pend == '}')
     690           0 :         {
     691           0 :           int save = *pend;
     692           0 :           *pend = 0;
     693           0 :           freeme = get_var_ext (p+2);
     694           0 :           value = freeme;
     695           0 :           *pend++ = save;
     696             :         }
     697           0 :       else if (*pend)
     698             :         {
     699           0 :           int save = *pend;
     700           0 :           *pend = 0;
     701           0 :           value = get_var (p+1);
     702           0 :           *pend = save;
     703             :         }
     704             :       else
     705           0 :         value = get_var (p+1);
     706           0 :       if (!value)
     707           0 :         value = "";
     708           0 :       valuelen = strlen (value);
     709           0 :       if (valuelen <= pend - p)
     710             :         {
     711           0 :           memcpy (p, value, valuelen);
     712           0 :           p += valuelen;
     713           0 :           n = pend - p;
     714           0 :           if (n)
     715           0 :             memmove (p, p+n, strlen (p+n)+1);
     716           0 :           line = p;
     717             :         }
     718             :       else
     719             :         {
     720           0 :           char *src = result? result : buffer;
     721             :           char *dst;
     722             : 
     723           0 :           dst = xmalloc (strlen (src) + valuelen + 1);
     724           0 :           n = p - src;
     725           0 :           memcpy (dst, src, n);
     726           0 :           memcpy (dst + n, value, valuelen);
     727           0 :           n += valuelen;
     728           0 :           strcpy (dst + n, pend);
     729           0 :           line = dst + n;
     730           0 :           xfree (result);
     731           0 :           result = dst;
     732             :         }
     733           0 :       xfree (freeme);
     734           0 :       freeme = NULL;
     735             :     }
     736           0 :   return result;
     737             : }
     738             : 
     739             : /* Same as substitute_line but do not modify BUFFER.  */
     740             : static char *
     741           0 : substitute_line_copy (const char *buffer)
     742             : {
     743             :   char *result, *p;
     744             : 
     745           0 :   p = xstrdup (buffer?buffer:"");
     746           0 :   result = substitute_line (p);
     747           0 :   if (!result)
     748           0 :     result = p;
     749             :   else
     750           0 :     xfree (p);
     751           0 :   return result;
     752             : }
     753             : 
     754             : 
     755             : static void
     756           0 : assign_variable (char *line, int syslet)
     757             : {
     758             :   char *name, *p, *tmp, *free_me, *buffer;
     759             : 
     760             :   /* Get the  name. */
     761           0 :   name = line;
     762           0 :   for (p=name; *p && !spacep (p); p++)
     763             :     ;
     764           0 :   if (*p)
     765           0 :     *p++ = 0;
     766           0 :   while (spacep (p))
     767           0 :     p++;
     768             : 
     769           0 :   if (!*p)
     770           0 :     set_var (name, NULL); /* Remove variable.  */
     771           0 :   else if (syslet)
     772             :     {
     773           0 :       free_me = opt.enable_varsubst? substitute_line_copy (p) : NULL;
     774           0 :       if (free_me)
     775           0 :         p = free_me;
     776           0 :       buffer = xmalloc (4 + strlen (p) + 1);
     777           0 :       strcpy (stpcpy (buffer, "get "), p);
     778           0 :       tmp = get_var_ext (buffer);
     779           0 :       xfree (buffer);
     780           0 :       set_var (name, tmp);
     781           0 :       xfree (tmp);
     782           0 :       xfree (free_me);
     783             :     }
     784             :   else
     785             :     {
     786           0 :       tmp = opt.enable_varsubst? substitute_line_copy (p) : NULL;
     787           0 :       if (tmp)
     788             :         {
     789           0 :           set_var (name, tmp);
     790           0 :           xfree (tmp);
     791             :         }
     792             :       else
     793           0 :         set_var (name, p);
     794             :     }
     795           0 : }
     796             : 
     797             : 
     798             : static void
     799           0 : show_variables (void)
     800             : {
     801             :   variable_t var;
     802             : 
     803           0 :   for (var = variable_table; var; var = var->next)
     804           0 :     if (var->value)
     805           0 :       printf ("%-20s %s\n", var->name, var->value);
     806           0 : }
     807             : 
     808             : 
     809             : /* Store an inquire response pattern.  Note, that this function may
     810             :    change the content of LINE.  We assume that leading white spaces
     811             :    are already removed. */
     812             : static void
     813           0 : add_definq (char *line, int is_var, int is_prog)
     814             : {
     815             :   definq_t d;
     816             :   char *name, *p;
     817             : 
     818             :   /* Get name. */
     819           0 :   name = line;
     820           0 :   for (p=name; *p && !spacep (p); p++)
     821             :     ;
     822           0 :   if (*p)
     823           0 :     *p++ = 0;
     824           0 :   while (spacep (p))
     825           0 :     p++;
     826             : 
     827           0 :   d = xmalloc (sizeof *d + strlen (p) );
     828           0 :   strcpy (d->file, p);
     829           0 :   d->is_var  = is_var;
     830           0 :   d->is_prog = is_prog;
     831           0 :   if ( !strcmp (name, "*"))
     832           0 :     d->name = NULL;
     833             :   else
     834           0 :     d->name = xstrdup (name);
     835             : 
     836           0 :   d->next = NULL;
     837           0 :   *definq_list_tail = d;
     838           0 :   definq_list_tail = &d->next;
     839           0 : }
     840             : 
     841             : 
     842             : /* Show all inquiry defintions. */
     843             : static void
     844           0 : show_definq (void)
     845             : {
     846             :   definq_t d;
     847             : 
     848           0 :   for (d=definq_list; d; d = d->next)
     849           0 :     if (d->name)
     850           0 :       printf ("%-20s %c %s\n",
     851           0 :               d->name, d->is_var? 'v' : d->is_prog? 'p':'f', d->file);
     852           0 :   for (d=definq_list; d; d = d->next)
     853           0 :     if (!d->name)
     854           0 :       printf ("%-20s %c %s\n", "*",
     855           0 :               d->is_var? 'v': d->is_prog? 'p':'f', d->file);
     856           0 : }
     857             : 
     858             : 
     859             : /* Clear all inquiry definitions. */
     860             : static void
     861           0 : clear_definq (void)
     862             : {
     863           0 :   while (definq_list)
     864             :     {
     865           0 :       definq_t tmp = definq_list->next;
     866           0 :       xfree (definq_list->name);
     867           0 :       xfree (definq_list);
     868           0 :       definq_list = tmp;
     869             :     }
     870           0 :   definq_list_tail = &definq_list;
     871           0 : }
     872             : 
     873             : 
     874             : static void
     875           0 : do_sendfd (assuan_context_t ctx, char *line)
     876             : {
     877             :   FILE *fp;
     878             :   char *name, *mode, *p;
     879             :   int rc, fd;
     880             : 
     881             :   /* Get file name. */
     882           0 :   name = line;
     883           0 :   for (p=name; *p && !spacep (p); p++)
     884             :     ;
     885           0 :   if (*p)
     886           0 :     *p++ = 0;
     887           0 :   while (spacep (p))
     888           0 :     p++;
     889             : 
     890             :   /* Get mode.  */
     891           0 :   mode = p;
     892           0 :   if (!*mode)
     893           0 :     mode = "r";
     894             :   else
     895             :     {
     896           0 :       for (p=mode; *p && !spacep (p); p++)
     897             :         ;
     898           0 :       if (*p)
     899           0 :         *p++ = 0;
     900             :     }
     901             : 
     902             :   /* Open and send. */
     903           0 :   fp = fopen (name, mode);
     904           0 :   if (!fp)
     905             :     {
     906           0 :       log_error ("can't open '%s' in \"%s\" mode: %s\n",
     907           0 :                  name, mode, strerror (errno));
     908           0 :       return;
     909             :     }
     910           0 :   fd = fileno (fp);
     911             : 
     912           0 :   if (opt.verbose)
     913           0 :     log_error ("file '%s' opened in \"%s\" mode, fd=%d\n",
     914             :                name, mode, fd);
     915             : 
     916           0 :   rc = assuan_sendfd (ctx, INT2FD (fd) );
     917           0 :   if (rc)
     918           0 :     log_error ("sending descriptor %d failed: %s\n", fd, gpg_strerror (rc));
     919           0 :   fclose (fp);
     920             : }
     921             : 
     922             : 
     923             : static void
     924           0 : do_recvfd (assuan_context_t ctx, char *line)
     925             : {
     926             :   (void)ctx;
     927             :   (void)line;
     928           0 :   log_info ("This command has not yet been implemented\n");
     929           0 : }
     930             : 
     931             : 
     932             : static void
     933           0 : do_open (char *line)
     934             : {
     935             :   FILE *fp;
     936             :   char *varname, *name, *mode, *p;
     937             :   int fd;
     938             : 
     939             : #ifdef HAVE_W32_SYSTEM
     940             :   if (server_pid == (pid_t)(-1))
     941             :     {
     942             :       log_error ("the pid of the server is unknown\n");
     943             :       log_info ("use command \"/serverpid\" first\n");
     944             :       return;
     945             :     }
     946             : #endif
     947             : 
     948             :   /* Get variable name. */
     949           0 :   varname = line;
     950           0 :   for (p=varname; *p && !spacep (p); p++)
     951             :     ;
     952           0 :   if (*p)
     953           0 :     *p++ = 0;
     954           0 :   while (spacep (p))
     955           0 :     p++;
     956             : 
     957             :   /* Get file name. */
     958           0 :   name = p;
     959           0 :   for (p=name; *p && !spacep (p); p++)
     960             :     ;
     961           0 :   if (*p)
     962           0 :     *p++ = 0;
     963           0 :   while (spacep (p))
     964           0 :     p++;
     965             : 
     966             :   /* Get mode.  */
     967           0 :   mode = p;
     968           0 :   if (!*mode)
     969           0 :     mode = "r";
     970             :   else
     971             :     {
     972           0 :       for (p=mode; *p && !spacep (p); p++)
     973             :         ;
     974           0 :       if (*p)
     975           0 :         *p++ = 0;
     976             :     }
     977             : 
     978             :   /* Open and send. */
     979           0 :   fp = fopen (name, mode);
     980           0 :   if (!fp)
     981             :     {
     982           0 :       log_error ("can't open '%s' in \"%s\" mode: %s\n",
     983           0 :                  name, mode, strerror (errno));
     984           0 :       return;
     985             :     }
     986           0 :   fd = fileno (fp);
     987           0 :   if (fd >= 0 && fd < DIM (open_fd_table))
     988             :     {
     989           0 :       open_fd_table[fd].inuse = 1;
     990             : #ifdef HAVE_W32CE_SYSTEM
     991             : # warning fixme: implement our pipe emulation.
     992             : #endif
     993             : #if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
     994             :       {
     995             :         HANDLE prochandle, handle, newhandle;
     996             : 
     997             :         handle = (void*)_get_osfhandle (fd);
     998             : 
     999             :         prochandle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, server_pid);
    1000             :         if (!prochandle)
    1001             :           {
    1002             :             log_error ("failed to open the server process\n");
    1003             :             close (fd);
    1004             :             return;
    1005             :           }
    1006             : 
    1007             :         if (!DuplicateHandle (GetCurrentProcess(), handle,
    1008             :                               prochandle, &newhandle, 0,
    1009             :                               TRUE, DUPLICATE_SAME_ACCESS ))
    1010             :           {
    1011             :             log_error ("failed to duplicate the handle\n");
    1012             :             close (fd);
    1013             :             CloseHandle (prochandle);
    1014             :             return;
    1015             :           }
    1016             :         CloseHandle (prochandle);
    1017             :         open_fd_table[fd].handle = newhandle;
    1018             :       }
    1019             :       if (opt.verbose)
    1020             :         log_info ("file '%s' opened in \"%s\" mode, fd=%d  (libc=%d)\n",
    1021             :                    name, mode, (int)open_fd_table[fd].handle, fd);
    1022             :       set_int_var (varname, (int)open_fd_table[fd].handle);
    1023             : #else
    1024           0 :       if (opt.verbose)
    1025           0 :         log_info ("file '%s' opened in \"%s\" mode, fd=%d\n",
    1026             :                    name, mode, fd);
    1027           0 :       set_int_var (varname, fd);
    1028             : #endif
    1029             :     }
    1030             :   else
    1031             :     {
    1032           0 :       log_error ("can't put fd %d into table\n", fd);
    1033           0 :       close (fd);
    1034             :     }
    1035             : }
    1036             : 
    1037             : 
    1038             : static void
    1039           0 : do_close (char *line)
    1040             : {
    1041           0 :   int fd = atoi (line);
    1042             : 
    1043             : #ifdef HAVE_W32_SYSTEM
    1044             :   int i;
    1045             : 
    1046             :   for (i=0; i < DIM (open_fd_table); i++)
    1047             :     if ( open_fd_table[i].inuse && open_fd_table[i].handle == (void*)fd)
    1048             :       break;
    1049             :   if (i < DIM (open_fd_table))
    1050             :     fd = i;
    1051             :   else
    1052             :     {
    1053             :       log_error ("given fd (system handle) has not been opened\n");
    1054             :       return;
    1055             :     }
    1056             : #endif
    1057             : 
    1058           0 :   if (fd < 0 || fd >= DIM (open_fd_table))
    1059             :     {
    1060           0 :       log_error ("invalid fd\n");
    1061           0 :       return;
    1062             :     }
    1063             : 
    1064           0 :   if (!open_fd_table[fd].inuse)
    1065             :     {
    1066           0 :       log_error ("given fd has not been opened\n");
    1067           0 :       return;
    1068             :     }
    1069             : #ifdef HAVE_W32_SYSTEM
    1070             :   CloseHandle (open_fd_table[fd].handle); /* Close duped handle.  */
    1071             : #endif
    1072           0 :   close (fd);
    1073           0 :   open_fd_table[fd].inuse = 0;
    1074             : }
    1075             : 
    1076             : 
    1077             : static void
    1078           0 : do_showopen (void)
    1079             : {
    1080             :   int i;
    1081             : 
    1082           0 :   for (i=0; i < DIM (open_fd_table); i++)
    1083           0 :     if (open_fd_table[i].inuse)
    1084             :       {
    1085             : #ifdef HAVE_W32_SYSTEM
    1086             :         printf ("%-15d (libc=%d)\n", (int)open_fd_table[i].handle, i);
    1087             : #else
    1088           0 :         printf ("%-15d\n", i);
    1089             : #endif
    1090             :       }
    1091           0 : }
    1092             : 
    1093             : 
    1094             : 
    1095             : static gpg_error_t
    1096           0 : getinfo_pid_cb (void *opaque, const void *buffer, size_t length)
    1097             : {
    1098           0 :   membuf_t *mb = opaque;
    1099           0 :   put_membuf (mb, buffer, length);
    1100           0 :   return 0;
    1101             : }
    1102             : 
    1103             : /* Get the pid of the server and store it locally.  */
    1104             : static void
    1105           0 : do_serverpid (assuan_context_t ctx)
    1106             : {
    1107             :   int rc;
    1108             :   membuf_t mb;
    1109             :   char *buffer;
    1110             : 
    1111           0 :   init_membuf (&mb, 100);
    1112           0 :   rc = assuan_transact (ctx, "GETINFO pid", getinfo_pid_cb, &mb,
    1113             :                         NULL, NULL, NULL, NULL);
    1114           0 :   put_membuf (&mb, "", 1);
    1115           0 :   buffer = get_membuf (&mb, NULL);
    1116           0 :   if (rc || !buffer)
    1117           0 :     log_error ("command \"%s\" failed: %s\n",
    1118             :                "GETINFO pid", gpg_strerror (rc));
    1119             :   else
    1120             :     {
    1121           0 :       server_pid = (pid_t)strtoul (buffer, NULL, 10);
    1122           0 :       if (opt.verbose)
    1123           0 :         log_info ("server's PID is %lu\n", (unsigned long)server_pid);
    1124             :     }
    1125           0 :   xfree (buffer);
    1126           0 : }
    1127             : 
    1128             : 
    1129             : /* Return true if the command is either "HELP" or "SCD HELP".  */
    1130             : static int
    1131          43 : help_cmd_p (const char *line)
    1132             : {
    1133          43 :   if (!ascii_strncasecmp (line, "SCD", 3)
    1134           0 :       && (spacep (line+3) || !line[3]))
    1135             :     {
    1136           0 :       for (line += 3; spacep (line); line++)
    1137             :         ;
    1138             :     }
    1139             : 
    1140          86 :   return (!ascii_strncasecmp (line, "HELP", 4)
    1141          43 :           && (spacep (line+4) || !line[4]));
    1142             : }
    1143             : 
    1144             : 
    1145             : /* gpg-connect-agent's entry point. */
    1146             : int
    1147          84 : main (int argc, char **argv)
    1148             : {
    1149             :   ARGPARSE_ARGS pargs;
    1150          84 :   int no_more_options = 0;
    1151             :   assuan_context_t ctx;
    1152             :   char *line, *p;
    1153             :   char *tmpline;
    1154             :   size_t linesize;
    1155             :   int rc;
    1156             :   int cmderr;
    1157          84 :   const char *opt_run = NULL;
    1158          84 :   FILE *script_fp = NULL;
    1159             :   int use_tty, keep_line;
    1160             :   struct {
    1161             :     int collecting;
    1162             :     loopline_t head;
    1163             :     loopline_t *tail;
    1164             :     loopline_t current;
    1165             :     unsigned int nestlevel;
    1166             :     int oneshot;
    1167             :     char *condition;
    1168             :   } loopstack[20];
    1169             :   int        loopidx;
    1170          84 :   char **cmdline_commands = NULL;
    1171             : 
    1172          84 :   early_system_init ();
    1173          84 :   gnupg_rl_initialize ();
    1174          84 :   set_strusage (my_strusage);
    1175          84 :   log_set_prefix ("gpg-connect-agent", GPGRT_LOG_WITH_PREFIX);
    1176             : 
    1177             :   /* Make sure that our subsystems are ready.  */
    1178          84 :   i18n_init();
    1179          84 :   init_common_subsystems (&argc, &argv);
    1180             : 
    1181          84 :   assuan_set_gpg_err_source (0);
    1182             : 
    1183             : 
    1184          84 :   opt.autostart = 1;
    1185          84 :   opt.connect_flags = 1;
    1186             : 
    1187             :   /* Parse the command line. */
    1188          84 :   pargs.argc  = &argc;
    1189          84 :   pargs.argv  = &argv;
    1190          84 :   pargs.flags =  1;  /* Do not remove the args.  */
    1191         292 :   while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts))
    1192             :     {
    1193         124 :       switch (pargs.r_opt)
    1194             :         {
    1195           0 :         case oQuiet:     opt.quiet = 1; break;
    1196          83 :         case oVerbose:   opt.verbose++; break;
    1197           0 :         case oNoVerbose: opt.verbose = 0; break;
    1198           0 :         case oHomedir:   gnupg_set_homedir (pargs.r.ret_str); break;
    1199          41 :         case oAgentProgram: opt.agent_program = pargs.r.ret_str;  break;
    1200           0 :         case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str;  break;
    1201           0 :         case oNoAutostart:    opt.autostart = 0; break;
    1202           0 :         case oHex:       opt.hex = 1; break;
    1203           0 :         case oDecode:    opt.decode = 1; break;
    1204           0 :         case oDirmngr:   opt.use_dirmngr = 1; break;
    1205           0 :         case oUIServer:  opt.use_uiserver = 1; break;
    1206           0 :         case oRawSocket: opt.raw_socket = pargs.r.ret_str; break;
    1207           0 :         case oTcpSocket: opt.tcp_socket = pargs.r.ret_str; break;
    1208           0 :         case oExec:      opt.exec = 1; break;
    1209           0 :         case oNoExtConnect: opt.connect_flags &= ~(1); break;
    1210           0 :         case oRun:       opt_run = pargs.r.ret_str; break;
    1211             :         case oSubst:
    1212           0 :           opt.enable_varsubst = 1;
    1213           0 :           opt.trim_leading_spaces = 1;
    1214           0 :           break;
    1215             : 
    1216           0 :         default: pargs.err = 2; break;
    1217             :         }
    1218             :     }
    1219             : 
    1220          84 :   if (log_get_errorcount (0))
    1221           0 :     exit (2);
    1222             : 
    1223             :   /* --uiserver is a shortcut for a specific raw socket.  This comes
    1224             :        in particular handy on Windows. */
    1225          84 :   if (opt.use_uiserver)
    1226             :     {
    1227           0 :       opt.raw_socket = make_absfilename (gnupg_homedir (), "S.uiserver", NULL);
    1228             :     }
    1229             : 
    1230             :   /* Print a warning if an argument looks like an option.  */
    1231          84 :   if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
    1232             :     {
    1233             :       int i;
    1234             : 
    1235         209 :       for (i=0; i < argc; i++)
    1236         125 :         if (argv[i][0] == '-' && argv[i][1] == '-')
    1237           0 :           log_info (_("Note: '%s' is not considered an option\n"), argv[i]);
    1238             :     }
    1239             : 
    1240             : 
    1241          84 :   use_tty = (gnupg_isatty (fileno (stdin)) && gnupg_isatty (fileno (stdout)));
    1242             : 
    1243          84 :   if (opt.exec)
    1244             :     {
    1245           0 :       if (!argc)
    1246             :         {
    1247           0 :           log_error (_("option \"%s\" requires a program "
    1248             :                        "and optional arguments\n"), "--exec" );
    1249           0 :           exit (1);
    1250             :         }
    1251             :     }
    1252          84 :   else if (argc)
    1253          83 :     cmdline_commands = argv;
    1254             : 
    1255          84 :   if (opt.exec && opt.raw_socket)
    1256             :     {
    1257           0 :       opt.raw_socket = NULL;
    1258           0 :       log_info (_("option \"%s\" ignored due to \"%s\"\n"),
    1259             :                 "--raw-socket", "--exec");
    1260             :     }
    1261          84 :   if (opt.exec && opt.tcp_socket)
    1262             :     {
    1263           0 :       opt.tcp_socket = NULL;
    1264           0 :       log_info (_("option \"%s\" ignored due to \"%s\"\n"),
    1265             :                 "--tcp-socket", "--exec");
    1266             :     }
    1267          84 :   if (opt.tcp_socket && opt.raw_socket)
    1268             :     {
    1269           0 :       opt.tcp_socket = NULL;
    1270           0 :       log_info (_("option \"%s\" ignored due to \"%s\"\n"),
    1271             :                 "--tcp-socket", "--raw-socket");
    1272             :     }
    1273             : 
    1274          84 :   if (opt_run && !(script_fp = fopen (opt_run, "r")))
    1275             :     {
    1276           0 :       log_error ("cannot open run file '%s': %s\n",
    1277           0 :                  opt_run, strerror (errno));
    1278           0 :       exit (1);
    1279             :     }
    1280             : 
    1281             : 
    1282          84 :   if (opt.exec)
    1283             :     {
    1284             :       assuan_fd_t no_close[3];
    1285             : 
    1286           0 :       no_close[0] = assuan_fd_from_posix_fd (es_fileno (es_stderr));
    1287           0 :       no_close[1] = assuan_fd_from_posix_fd (log_get_fd ());
    1288           0 :       no_close[2] = ASSUAN_INVALID_FD;
    1289             : 
    1290           0 :       rc = assuan_new (&ctx);
    1291           0 :       if (rc)
    1292             :         {
    1293           0 :           log_error ("assuan_new failed: %s\n", gpg_strerror (rc));
    1294           0 :           exit (1);
    1295             :         }
    1296             : 
    1297           0 :       rc = assuan_pipe_connect
    1298             :         (ctx, *argv, (const char **)argv, no_close, NULL, NULL,
    1299           0 :          (opt.connect_flags & 1) ? ASSUAN_PIPE_CONNECT_FDPASSING : 0);
    1300           0 :       if (rc)
    1301             :         {
    1302           0 :           log_error ("assuan_pipe_connect_ext failed: %s\n",
    1303             :                      gpg_strerror (rc));
    1304           0 :           exit (1);
    1305             :         }
    1306             : 
    1307           0 :       if (opt.verbose)
    1308           0 :         log_info ("server '%s' started\n", *argv);
    1309             : 
    1310             :     }
    1311          84 :   else if (opt.raw_socket)
    1312             :     {
    1313           0 :       rc = assuan_new (&ctx);
    1314           0 :       if (rc)
    1315             :         {
    1316           0 :           log_error ("assuan_new failed: %s\n", gpg_strerror (rc));
    1317           0 :           exit (1);
    1318             :         }
    1319             : 
    1320           0 :       rc = assuan_socket_connect
    1321             :         (ctx, opt.raw_socket, 0,
    1322           0 :          (opt.connect_flags & 1) ? ASSUAN_SOCKET_CONNECT_FDPASSING : 0);
    1323           0 :       if (rc)
    1324             :         {
    1325           0 :           log_error ("can't connect to socket '%s': %s\n",
    1326             :                      opt.raw_socket, gpg_strerror (rc));
    1327           0 :           exit (1);
    1328             :         }
    1329             : 
    1330           0 :       if (opt.verbose)
    1331           0 :         log_info ("connection to socket '%s' established\n", opt.raw_socket);
    1332             :     }
    1333          84 :   else if (opt.tcp_socket)
    1334             :     {
    1335             :       char *url;
    1336             : 
    1337           0 :       url = xstrconcat ("assuan://", opt.tcp_socket, NULL);
    1338             : 
    1339           0 :       rc = assuan_new (&ctx);
    1340           0 :       if (rc)
    1341             :         {
    1342           0 :           log_error ("assuan_new failed: %s\n", gpg_strerror (rc));
    1343           0 :           exit (1);
    1344             :         }
    1345             : 
    1346           0 :       rc = assuan_socket_connect (ctx, opt.tcp_socket, 0, 0);
    1347           0 :       if (rc)
    1348             :         {
    1349           0 :           log_error ("can't connect to server '%s': %s\n",
    1350             :                      opt.tcp_socket, gpg_strerror (rc));
    1351           0 :           exit (1);
    1352             :         }
    1353             : 
    1354           0 :       if (opt.verbose)
    1355           0 :         log_info ("connection to socket '%s' established\n", url);
    1356             : 
    1357           0 :       xfree (url);
    1358             :     }
    1359             :   else
    1360          84 :     ctx = start_agent ();
    1361             : 
    1362             :   /* See whether there is a line pending from the server (in case
    1363             :      assuan did not run the initial handshaking).  */
    1364          84 :   if (assuan_pending_line (ctx))
    1365             :     {
    1366           0 :       rc = read_and_print_response (ctx, 0, &cmderr);
    1367           0 :       if (rc)
    1368           0 :         log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
    1369             :     }
    1370             : 
    1371             : 
    1372        1764 :   for (loopidx=0; loopidx < DIM (loopstack); loopidx++)
    1373        1680 :     loopstack[loopidx].collecting = 0;
    1374          84 :   loopidx = -1;
    1375          84 :   line = NULL;
    1376          84 :   linesize = 0;
    1377          84 :   keep_line = 1;
    1378             :   for (;;)
    1379             :     {
    1380             :       int n;
    1381         127 :       size_t maxlength = 2048;
    1382             : 
    1383         127 :       assert (loopidx < (int)DIM (loopstack));
    1384         127 :       if (loopidx >= 0 && loopstack[loopidx].current)
    1385             :         {
    1386           0 :           keep_line = 0;
    1387           0 :           xfree (line);
    1388           0 :           line = xstrdup (loopstack[loopidx].current->line);
    1389           0 :           n = strlen (line);
    1390             :           /* Never go beyond of the final /end.  */
    1391           0 :           if (loopstack[loopidx].current->next)
    1392           0 :             loopstack[loopidx].current = loopstack[loopidx].current->next;
    1393           0 :           else if (!strncmp (line, "/end", 4) && (!line[4]||spacep(line+4)))
    1394             :             ;
    1395             :           else
    1396           0 :             log_fatal ("/end command vanished\n");
    1397             :         }
    1398         127 :       else if (cmdline_commands && *cmdline_commands && !script_fp)
    1399             :         {
    1400         125 :           keep_line = 0;
    1401         125 :           xfree (line);
    1402         125 :           line = xstrdup (*cmdline_commands);
    1403         125 :           cmdline_commands++;
    1404         125 :           n = strlen (line);
    1405         250 :           if (n >= maxlength)
    1406           0 :             maxlength = 0;
    1407             :         }
    1408           2 :       else if (use_tty && !script_fp)
    1409             :         {
    1410           0 :           keep_line = 0;
    1411           0 :           xfree (line);
    1412           0 :           line = tty_get ("> ");
    1413           0 :           n = strlen (line);
    1414           0 :           if (n==1 && *line == CONTROL_D)
    1415           0 :             n = 0;
    1416           0 :           if (n >= maxlength)
    1417           0 :             maxlength = 0;
    1418             :         }
    1419             :       else
    1420             :         {
    1421           2 :           if (!keep_line)
    1422             :             {
    1423           0 :               xfree (line);
    1424           0 :               line = NULL;
    1425           0 :               linesize = 0;
    1426           0 :               keep_line = 1;
    1427             :             }
    1428           2 :           n = read_line (script_fp? script_fp:stdin,
    1429             :                          &line, &linesize, &maxlength);
    1430             :         }
    1431         127 :       if (n < 0)
    1432             :         {
    1433           0 :           log_error (_("error reading input: %s\n"), strerror (errno));
    1434           0 :           if (script_fp)
    1435             :             {
    1436           0 :               fclose (script_fp);
    1437           0 :               script_fp = NULL;
    1438           0 :               log_error ("stopping script execution\n");
    1439           0 :               continue;
    1440             :             }
    1441           0 :           exit (1);
    1442             :         }
    1443         127 :       if (!n)
    1444             :         {
    1445             :           /* EOF */
    1446           1 :           if (script_fp)
    1447             :             {
    1448           0 :               fclose (script_fp);
    1449           0 :               script_fp = NULL;
    1450           0 :               if (opt.verbose)
    1451           0 :                 log_info ("end of script\n");
    1452           0 :               continue;
    1453             :             }
    1454          85 :           break;
    1455             :         }
    1456         126 :       if (!maxlength)
    1457             :         {
    1458           0 :           log_error (_("line too long - skipped\n"));
    1459           0 :           continue;
    1460             :         }
    1461         126 :       if (memchr (line, 0, n))
    1462           0 :         log_info (_("line shortened due to embedded Nul character\n"));
    1463         126 :       if (line[n-1] == '\n')
    1464           0 :         line[n-1] = 0;
    1465             : 
    1466         126 :       if (opt.trim_leading_spaces)
    1467             :         {
    1468           0 :           const char *s = line;
    1469             : 
    1470           0 :           while (spacep (s))
    1471           0 :             s++;
    1472           0 :           if (s != line)
    1473             :             {
    1474           0 :               for (p=line; *s;)
    1475           0 :                 *p++ = *s++;
    1476           0 :               *p = 0;
    1477           0 :               n = p - line;
    1478             :             }
    1479             :         }
    1480             : 
    1481         126 :       if (loopidx+1 >= 0 && loopstack[loopidx+1].collecting)
    1482             :         {
    1483             :           loopline_t ll;
    1484             : 
    1485           0 :           ll = xmalloc (sizeof *ll + strlen (line));
    1486           0 :           ll->next = NULL;
    1487           0 :           strcpy (ll->line, line);
    1488           0 :           *loopstack[loopidx+1].tail = ll;
    1489           0 :           loopstack[loopidx+1].tail = &ll->next;
    1490             : 
    1491           0 :           if (!strncmp (line, "/end", 4) && (!line[4]||spacep(line+4)))
    1492           0 :             loopstack[loopidx+1].nestlevel--;
    1493           0 :           else if (!strncmp (line, "/while", 6) && (!line[6]||spacep(line+6)))
    1494           0 :             loopstack[loopidx+1].nestlevel++;
    1495             : 
    1496           0 :           if (loopstack[loopidx+1].nestlevel)
    1497           0 :             continue;
    1498             :           /* We reached the corresponding /end.  */
    1499           0 :           loopstack[loopidx+1].collecting = 0;
    1500           0 :           loopidx++;
    1501             :         }
    1502             : 
    1503         126 :       if (*line == '/')
    1504             :         {
    1505             :           /* Handle control commands. */
    1506          83 :           char *cmd = line+1;
    1507             : 
    1508          83 :           for (p=cmd; *p && !spacep (p); p++)
    1509             :             ;
    1510          83 :           if (*p)
    1511           0 :             *p++ = 0;
    1512         166 :           while (spacep (p))
    1513           0 :             p++;
    1514          83 :           if (!strcmp (cmd, "let"))
    1515             :             {
    1516           0 :               assign_variable (p, 0);
    1517             :             }
    1518          83 :           else if (!strcmp (cmd, "slet"))
    1519             :             {
    1520             :               /* Deprecated - never used in a released version.  */
    1521           0 :               assign_variable (p, 1);
    1522             :             }
    1523          83 :           else if (!strcmp (cmd, "showvar"))
    1524             :             {
    1525           0 :               show_variables ();
    1526             :             }
    1527          83 :           else if (!strcmp (cmd, "definq"))
    1528             :             {
    1529           0 :               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
    1530           0 :               if (tmpline)
    1531             :                 {
    1532           0 :                   add_definq (tmpline, 1, 0);
    1533           0 :                   xfree (tmpline);
    1534             :                 }
    1535             :               else
    1536           0 :                 add_definq (p, 1, 0);
    1537             :             }
    1538          83 :           else if (!strcmp (cmd, "definqfile"))
    1539             :             {
    1540           0 :               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
    1541           0 :               if (tmpline)
    1542             :                 {
    1543           0 :                   add_definq (tmpline, 0, 0);
    1544           0 :                   xfree (tmpline);
    1545             :                 }
    1546             :               else
    1547           0 :                 add_definq (p, 0, 0);
    1548             :             }
    1549          83 :           else if (!strcmp (cmd, "definqprog"))
    1550             :             {
    1551           0 :               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
    1552           0 :               if (tmpline)
    1553             :                 {
    1554           0 :                   add_definq (tmpline, 0, 1);
    1555           0 :                   xfree (tmpline);
    1556             :                 }
    1557             :               else
    1558           0 :                 add_definq (p, 0, 1);
    1559             :             }
    1560          83 :           else if (!strcmp (cmd, "datafile"))
    1561             :             {
    1562             :               const char *fname;
    1563             : 
    1564           0 :               if (current_datasink)
    1565             :                 {
    1566           0 :                   if (current_datasink != stdout)
    1567           0 :                     fclose (current_datasink);
    1568           0 :                   current_datasink = NULL;
    1569             :                 }
    1570           0 :               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
    1571           0 :               fname = tmpline? tmpline : p;
    1572           0 :               if (fname && !strcmp (fname, "-"))
    1573           0 :                 current_datasink = stdout;
    1574           0 :               else if (fname && *fname)
    1575             :                 {
    1576           0 :                   current_datasink = fopen (fname, "wb");
    1577           0 :                   if (!current_datasink)
    1578           0 :                     log_error ("can't open '%s': %s\n",
    1579           0 :                                fname, strerror (errno));
    1580             :                 }
    1581           0 :               xfree (tmpline);
    1582             :             }
    1583          83 :           else if (!strcmp (cmd, "showdef"))
    1584             :             {
    1585           0 :               show_definq ();
    1586             :             }
    1587          83 :           else if (!strcmp (cmd, "cleardef"))
    1588             :             {
    1589           0 :               clear_definq ();
    1590             :             }
    1591          83 :           else if (!strcmp (cmd, "echo"))
    1592             :             {
    1593           0 :               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
    1594           0 :               if (tmpline)
    1595             :                 {
    1596           0 :                   puts (tmpline);
    1597           0 :                   xfree (tmpline);
    1598             :                 }
    1599             :               else
    1600           0 :                 puts (p);
    1601             :             }
    1602          83 :           else if (!strcmp (cmd, "sendfd"))
    1603             :             {
    1604           0 :               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
    1605           0 :               if (tmpline)
    1606             :                 {
    1607           0 :                   do_sendfd (ctx, tmpline);
    1608           0 :                   xfree (tmpline);
    1609             :                 }
    1610             :               else
    1611           0 :                 do_sendfd (ctx, p);
    1612           0 :               continue;
    1613             :             }
    1614          83 :           else if (!strcmp (cmd, "recvfd"))
    1615             :             {
    1616           0 :               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
    1617           0 :               if (tmpline)
    1618             :                 {
    1619           0 :                   do_recvfd (ctx, tmpline);
    1620           0 :                   xfree (tmpline);
    1621             :                 }
    1622             :               else
    1623           0 :                 do_recvfd (ctx, p);
    1624           0 :               continue;
    1625             :             }
    1626          83 :           else if (!strcmp (cmd, "open"))
    1627             :             {
    1628           0 :               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
    1629           0 :               if (tmpline)
    1630             :                 {
    1631           0 :                   do_open (tmpline);
    1632           0 :                   xfree (tmpline);
    1633             :                 }
    1634             :               else
    1635           0 :                 do_open (p);
    1636             :             }
    1637          83 :           else if (!strcmp (cmd, "close"))
    1638             :             {
    1639           0 :               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
    1640           0 :               if (tmpline)
    1641             :                 {
    1642           0 :                   do_close (tmpline);
    1643           0 :                   xfree (tmpline);
    1644             :                 }
    1645             :               else
    1646           0 :                 do_close (p);
    1647             :             }
    1648          83 :           else if (!strcmp (cmd, "showopen"))
    1649             :             {
    1650           0 :               do_showopen ();
    1651             :             }
    1652          83 :           else if (!strcmp (cmd, "serverpid"))
    1653             :             {
    1654           0 :               do_serverpid (ctx);
    1655             :             }
    1656          83 :           else if (!strcmp (cmd, "hex"))
    1657           0 :             opt.hex = 1;
    1658          83 :           else if (!strcmp (cmd, "nohex"))
    1659           0 :             opt.hex = 0;
    1660          83 :           else if (!strcmp (cmd, "decode"))
    1661           0 :             opt.decode = 1;
    1662          83 :           else if (!strcmp (cmd, "nodecode"))
    1663           0 :             opt.decode = 0;
    1664          83 :           else if (!strcmp (cmd, "subst"))
    1665             :             {
    1666           0 :               opt.enable_varsubst = 1;
    1667           0 :               opt.trim_leading_spaces = 1;
    1668             :             }
    1669          83 :           else if (!strcmp (cmd, "nosubst"))
    1670           0 :             opt.enable_varsubst = 0;
    1671          83 :           else if (!strcmp (cmd, "run"))
    1672             :             {
    1673             :               char *p2;
    1674             : 
    1675           0 :               for (p2=p; *p2 && !spacep (p2); p2++)
    1676             :                 ;
    1677           0 :               if (*p2)
    1678           0 :                 *p2++ = 0;
    1679           0 :               while (spacep (p2))
    1680           0 :                 p++;
    1681           0 :               if (*p2)
    1682             :                 {
    1683           0 :                   log_error ("syntax error in run command\n");
    1684           0 :                   if (script_fp)
    1685             :                     {
    1686           0 :                       fclose (script_fp);
    1687           0 :                       script_fp = NULL;
    1688             :                     }
    1689             :                 }
    1690           0 :               else if (script_fp)
    1691             :                 {
    1692           0 :                   log_error ("cannot nest run commands - stop\n");
    1693           0 :                   fclose (script_fp);
    1694           0 :                   script_fp = NULL;
    1695             :                 }
    1696           0 :               else if (!(script_fp = fopen (p, "r")))
    1697             :                 {
    1698           0 :                   log_error ("cannot open run file '%s': %s\n",
    1699           0 :                              p, strerror (errno));
    1700             :                 }
    1701           0 :               else if (opt.verbose)
    1702           0 :                 log_info ("running commands from '%s'\n", p);
    1703             :             }
    1704          83 :           else if (!strcmp (cmd, "while"))
    1705             :             {
    1706           0 :               if (loopidx+2 >= (int)DIM(loopstack))
    1707             :                 {
    1708           0 :                   log_error ("blocks are nested too deep\n");
    1709             :                   /* We should better die or break all loop in this
    1710             :                      case as recovering from this error won't be
    1711             :                      easy.  */
    1712             :                 }
    1713             :               else
    1714             :                 {
    1715           0 :                   loopstack[loopidx+1].head = NULL;
    1716           0 :                   loopstack[loopidx+1].tail = &loopstack[loopidx+1].head;
    1717           0 :                   loopstack[loopidx+1].current = NULL;
    1718           0 :                   loopstack[loopidx+1].nestlevel = 1;
    1719           0 :                   loopstack[loopidx+1].oneshot = 0;
    1720           0 :                   loopstack[loopidx+1].condition = xstrdup (p);
    1721           0 :                   loopstack[loopidx+1].collecting = 1;
    1722             :                 }
    1723             :             }
    1724          83 :           else if (!strcmp (cmd, "if"))
    1725             :             {
    1726           0 :               if (loopidx+2 >= (int)DIM(loopstack))
    1727             :                 {
    1728           0 :                   log_error ("blocks are nested too deep\n");
    1729             :                 }
    1730             :               else
    1731             :                 {
    1732             :                   /* Note that we need to evaluate the condition right
    1733             :                      away and not just at the end of the block as we
    1734             :                      do with a WHILE. */
    1735           0 :                   loopstack[loopidx+1].head = NULL;
    1736           0 :                   loopstack[loopidx+1].tail = &loopstack[loopidx+1].head;
    1737           0 :                   loopstack[loopidx+1].current = NULL;
    1738           0 :                   loopstack[loopidx+1].nestlevel = 1;
    1739           0 :                   loopstack[loopidx+1].oneshot = 1;
    1740           0 :                   loopstack[loopidx+1].condition = substitute_line_copy (p);
    1741           0 :                   loopstack[loopidx+1].collecting = 1;
    1742             :                 }
    1743             :             }
    1744          83 :           else if (!strcmp (cmd, "end"))
    1745             :             {
    1746           0 :               if (loopidx < 0)
    1747           0 :                 log_error ("stray /end command encountered - ignored\n");
    1748             :               else
    1749             :                 {
    1750             :                   char *tmpcond;
    1751             :                   const char *value;
    1752             :                   long condition;
    1753             : 
    1754             :                   /* Evaluate the condition.  */
    1755           0 :                   tmpcond = xstrdup (loopstack[loopidx].condition);
    1756           0 :                   if (loopstack[loopidx].oneshot)
    1757             :                     {
    1758           0 :                       xfree (loopstack[loopidx].condition);
    1759           0 :                       loopstack[loopidx].condition = xstrdup ("0");
    1760             :                     }
    1761           0 :                   tmpline = substitute_line (tmpcond);
    1762           0 :                   value = tmpline? tmpline : tmpcond;
    1763             :                   /* "true" or "yes" are commonly used to mean TRUE;
    1764             :                      all other strings will evaluate to FALSE due to
    1765             :                      the strtoul.  */
    1766           0 :                   if (!ascii_strcasecmp (value, "true")
    1767           0 :                       || !ascii_strcasecmp (value, "yes"))
    1768           0 :                     condition = 1;
    1769             :                   else
    1770           0 :                     condition = strtol (value, NULL, 0);
    1771           0 :                   xfree (tmpline);
    1772           0 :                   xfree (tmpcond);
    1773             : 
    1774           0 :                   if (condition)
    1775             :                     {
    1776             :                       /* Run loop.  */
    1777           0 :                       loopstack[loopidx].current = loopstack[loopidx].head;
    1778             :                     }
    1779             :                   else
    1780             :                     {
    1781             :                       /* Cleanup.  */
    1782           0 :                       while (loopstack[loopidx].head)
    1783             :                         {
    1784           0 :                           loopline_t tmp = loopstack[loopidx].head->next;
    1785           0 :                           xfree (loopstack[loopidx].head);
    1786           0 :                           loopstack[loopidx].head = tmp;
    1787             :                         }
    1788           0 :                       loopstack[loopidx].tail = NULL;
    1789           0 :                       loopstack[loopidx].current = NULL;
    1790           0 :                       loopstack[loopidx].nestlevel = 0;
    1791           0 :                       loopstack[loopidx].collecting = 0;
    1792           0 :                       loopstack[loopidx].oneshot = 0;
    1793           0 :                       xfree (loopstack[loopidx].condition);
    1794           0 :                       loopstack[loopidx].condition = NULL;
    1795           0 :                       loopidx--;
    1796             :                     }
    1797             :                 }
    1798             :             }
    1799          83 :           else if (!strcmp (cmd, "bye"))
    1800             :             {
    1801          83 :               break;
    1802             :             }
    1803           0 :           else if (!strcmp (cmd, "sleep"))
    1804             :             {
    1805           0 :               gnupg_sleep (1);
    1806             :             }
    1807           0 :           else if (!strcmp (cmd, "help"))
    1808             :             {
    1809           0 :               puts (
    1810             : "Available commands:\n"
    1811             : "/echo ARGS             Echo ARGS.\n"
    1812             : "/let  NAME VALUE       Set variable NAME to VALUE.\n"
    1813             : "/showvar               Show all variables.\n"
    1814             : "/definq NAME VAR       Use content of VAR for inquiries with NAME.\n"
    1815             : "/definqfile NAME FILE  Use content of FILE for inquiries with NAME.\n"
    1816             : "/definqprog NAME PGM   Run PGM for inquiries with NAME.\n"
    1817             : "/datafile [NAME]       Write all D line content to file NAME.\n"
    1818             : "/showdef               Print all definitions.\n"
    1819             : "/cleardef              Delete all definitions.\n"
    1820             : "/sendfd FILE MODE      Open FILE and pass descriptor to server.\n"
    1821             : "/recvfd                Receive FD from server and print.\n"
    1822             : "/open VAR FILE MODE    Open FILE and assign the file descriptor to VAR.\n"
    1823             : "/close FD              Close file with descriptor FD.\n"
    1824             : "/showopen              Show descriptors of all open files.\n"
    1825             : "/serverpid             Retrieve the pid of the server.\n"
    1826             : "/[no]hex               Enable hex dumping of received data lines.\n"
    1827             : "/[no]decode            Enable decoding of received data lines.\n"
    1828             : "/[no]subst             Enable variable substitution.\n"
    1829             : "/run FILE              Run commands from FILE.\n"
    1830             : "/if VAR                Begin conditional block controlled by VAR.\n"
    1831             : "/while VAR             Begin loop controlled by VAR.\n"
    1832             : "/end                   End loop or condition\n"
    1833             : "/bye                   Terminate gpg-connect-agent.\n"
    1834             : "/help                  Print this help.");
    1835             :             }
    1836             :           else
    1837           0 :             log_error (_("unknown command '%s'\n"), cmd );
    1838             : 
    1839           0 :           continue;
    1840             :         }
    1841             : 
    1842          43 :       if (opt.verbose && script_fp)
    1843           0 :         puts (line);
    1844             : 
    1845          43 :       tmpline = opt.enable_varsubst? substitute_line (line) : NULL;
    1846          43 :       if (tmpline)
    1847             :         {
    1848           0 :           rc = assuan_write_line (ctx, tmpline);
    1849           0 :           xfree (tmpline);
    1850             :         }
    1851             :       else
    1852          43 :         rc = assuan_write_line (ctx, line);
    1853          43 :       if (rc)
    1854             :         {
    1855           0 :           log_info (_("sending line failed: %s\n"), gpg_strerror (rc) );
    1856           0 :           break;
    1857             :         }
    1858          43 :       if (*line == '#' || !*line)
    1859           0 :         continue; /* Don't expect a response for a comment line. */
    1860             : 
    1861          43 :       rc = read_and_print_response (ctx, help_cmd_p (line), &cmderr);
    1862          43 :       if (rc)
    1863           0 :         log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
    1864          43 :       if ((rc || cmderr) && script_fp)
    1865             :         {
    1866           0 :           log_error ("stopping script execution\n");
    1867           0 :           fclose (script_fp);
    1868           0 :           script_fp = NULL;
    1869             :         }
    1870             : 
    1871             : 
    1872             :       /* FIXME: If the last command was BYE or the server died for
    1873             :          some other reason, we won't notice until we get the next
    1874             :          input command.  Probing the connection with a non-blocking
    1875             :          read could help to notice termination or other problems
    1876             :          early.  */
    1877          43 :     }
    1878             : 
    1879          84 :   if (opt.verbose)
    1880          83 :     log_info ("closing connection to agent\n");
    1881             : 
    1882             :   /* XXX: We would like to release the context here, but libassuan
    1883             :      nicely says good bye to the server, which results in a SIGPIPE if
    1884             :      the server died.  Unfortunately, libassuan does not ignore
    1885             :      SIGPIPE when used with UNIX sockets, hence we simply leak the
    1886             :      context here.  */
    1887             :   if (0)
    1888             :     assuan_release (ctx);
    1889             :   else
    1890          84 :     gpgrt_annotate_leaked_object (ctx);
    1891          84 :   xfree (line);
    1892          84 :   return 0;
    1893             : }
    1894             : 
    1895             : 
    1896             : /* Handle an Inquire from the server.  Return False if it could not be
    1897             :    handled; in this case the caller shll complete the operation.  LINE
    1898             :    is the complete line as received from the server.  This function
    1899             :    may change the content of LINE. */
    1900             : static int
    1901           0 : handle_inquire (assuan_context_t ctx, char *line)
    1902             : {
    1903             :   const char *name;
    1904             :   definq_t d;
    1905           0 :   FILE *fp = NULL;
    1906             :   char buffer[1024];
    1907             :   int rc, n;
    1908             : 
    1909             :   /* Skip the command and trailing spaces. */
    1910           0 :   for (; *line && !spacep (line); line++)
    1911             :     ;
    1912           0 :   while (spacep (line))
    1913           0 :     line++;
    1914             :   /* Get the name. */
    1915           0 :   name = line;
    1916           0 :   for (; *line && !spacep (line); line++)
    1917             :     ;
    1918           0 :   if (*line)
    1919           0 :     *line++ = 0;
    1920             : 
    1921             :   /* Now match it against our list.  The second loop is there to
    1922             :      detect the match-all entry. */
    1923           0 :   for (d=definq_list; d; d = d->next)
    1924           0 :     if (d->name && !strcmp (d->name, name))
    1925           0 :         break;
    1926           0 :   if (!d)
    1927           0 :     for (d=definq_list; d; d = d->next)
    1928           0 :       if (!d->name)
    1929           0 :         break;
    1930           0 :   if (!d)
    1931             :     {
    1932           0 :       if (opt.verbose)
    1933           0 :         log_info ("no handler for inquiry '%s' found\n", name);
    1934           0 :       return 0;
    1935             :     }
    1936             : 
    1937           0 :   if (d->is_var)
    1938             :     {
    1939           0 :       char *tmpvalue = get_var_ext (d->file);
    1940           0 :       if (tmpvalue)
    1941           0 :         rc = assuan_send_data (ctx, tmpvalue, strlen (tmpvalue));
    1942             :       else
    1943           0 :         rc = assuan_send_data (ctx, "", 0);
    1944           0 :       xfree (tmpvalue);
    1945           0 :       if (rc)
    1946           0 :         log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
    1947             :     }
    1948             :   else
    1949             :     {
    1950           0 :       if (d->is_prog)
    1951             :         {
    1952             : #ifdef HAVE_W32CE_SYSTEM
    1953             :           fp = NULL;
    1954             : #else
    1955           0 :           fp = popen (d->file, "r");
    1956             : #endif
    1957           0 :           if (!fp)
    1958           0 :             log_error ("error executing '%s': %s\n",
    1959           0 :                        d->file, strerror (errno));
    1960           0 :           else if (opt.verbose)
    1961           0 :             log_error ("handling inquiry '%s' by running '%s'\n",
    1962           0 :                        name, d->file);
    1963             :         }
    1964             :       else
    1965             :         {
    1966           0 :           fp = fopen (d->file, "rb");
    1967           0 :           if (!fp)
    1968           0 :             log_error ("error opening '%s': %s\n", d->file, strerror (errno));
    1969           0 :           else if (opt.verbose)
    1970           0 :             log_error ("handling inquiry '%s' by returning content of '%s'\n",
    1971           0 :                        name, d->file);
    1972             :         }
    1973           0 :       if (!fp)
    1974           0 :         return 0;
    1975             : 
    1976           0 :       while ( (n = fread (buffer, 1, sizeof buffer, fp)) )
    1977             :         {
    1978           0 :           rc = assuan_send_data (ctx, buffer, n);
    1979           0 :           if (rc)
    1980             :             {
    1981           0 :               log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
    1982           0 :               break;
    1983             :             }
    1984             :         }
    1985           0 :       if (ferror (fp))
    1986           0 :         log_error ("error reading from '%s': %s\n", d->file, strerror (errno));
    1987             :     }
    1988             : 
    1989           0 :   rc = assuan_send_data (ctx, NULL, 0);
    1990           0 :   if (rc)
    1991           0 :     log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
    1992             : 
    1993           0 :   if (d->is_var)
    1994             :     ;
    1995           0 :   else if (d->is_prog)
    1996             :     {
    1997             : #ifndef HAVE_W32CE_SYSTEM
    1998           0 :       if (pclose (fp))
    1999           0 :         log_error ("error running '%s': %s\n", d->file, strerror (errno));
    2000             : #endif
    2001             :     }
    2002             :   else
    2003           0 :     fclose (fp);
    2004           0 :   return 1;
    2005             : }
    2006             : 
    2007             : 
    2008             : /* Read all response lines from server and print them.  Returns 0 on
    2009             :    success or an assuan error code.  If WITHHASH istrue, comment lines
    2010             :    are printed.  Sets R_GOTERR to true if the command did not returned
    2011             :    OK.  */
    2012             : static int
    2013          43 : read_and_print_response (assuan_context_t ctx, int withhash, int *r_goterr)
    2014             : {
    2015             :   char *line;
    2016             :   size_t linelen;
    2017             :   gpg_error_t rc;
    2018             :   int i, j;
    2019          43 :   int need_lf = 0;
    2020             : 
    2021          43 :   *r_goterr = 0;
    2022             :   for (;;)
    2023             :     {
    2024             :       do
    2025             :         {
    2026          43 :           rc = assuan_read_line (ctx, &line, &linelen);
    2027          43 :           if (rc)
    2028           0 :             return rc;
    2029             : 
    2030          43 :           if ((withhash || opt.verbose > 1) && *line == '#')
    2031             :             {
    2032           0 :               fwrite (line, linelen, 1, stdout);
    2033           0 :               putchar ('\n');
    2034             :             }
    2035             :         }
    2036          43 :       while (*line == '#' || !linelen);
    2037             : 
    2038          43 :       if (linelen >= 1
    2039          43 :           && line[0] == 'D' && line[1] == ' ')
    2040             :         {
    2041           0 :           if (current_datasink)
    2042             :             {
    2043             :               const unsigned char *s;
    2044           0 :               int c = 0;
    2045             : 
    2046           0 :               for (j=2, s=(unsigned char*)line+2; j < linelen; j++, s++ )
    2047             :                 {
    2048           0 :                   if (*s == '%' && j+2 < linelen)
    2049             :                     {
    2050           0 :                       s++; j++;
    2051           0 :                       c = xtoi_2 ( s );
    2052           0 :                       s++; j++;
    2053             :                     }
    2054             :                   else
    2055           0 :                     c = *s;
    2056           0 :                   putc (c, current_datasink);
    2057             :                 }
    2058             :             }
    2059           0 :           else if (opt.hex)
    2060             :             {
    2061           0 :               for (i=2; i < linelen; )
    2062             :                 {
    2063           0 :                   int save_i = i;
    2064             : 
    2065           0 :                   printf ("D[%04X] ", i-2);
    2066           0 :                   for (j=0; j < 16 ; j++, i++)
    2067             :                     {
    2068           0 :                       if (j == 8)
    2069           0 :                         putchar (' ');
    2070           0 :                       if (i < linelen)
    2071           0 :                         printf (" %02X", ((unsigned char*)line)[i]);
    2072             :                       else
    2073           0 :                         fputs ("   ", stdout);
    2074             :                     }
    2075           0 :                   fputs ("   ", stdout);
    2076           0 :                   i= save_i;
    2077           0 :                   for (j=0; j < 16; j++, i++)
    2078             :                     {
    2079           0 :                       unsigned int c = ((unsigned char*)line)[i];
    2080           0 :                       if ( i >= linelen )
    2081           0 :                         putchar (' ');
    2082           0 :                       else if (isascii (c) && isprint (c) && !iscntrl (c))
    2083           0 :                         putchar (c);
    2084             :                       else
    2085           0 :                         putchar ('.');
    2086             :                     }
    2087           0 :                   putchar ('\n');
    2088             :                 }
    2089             :             }
    2090           0 :           else if (opt.decode)
    2091             :             {
    2092             :               const unsigned char *s;
    2093           0 :               int need_d = 1;
    2094           0 :               int c = 0;
    2095             : 
    2096           0 :               for (j=2, s=(unsigned char*)line+2; j < linelen; j++, s++ )
    2097             :                 {
    2098           0 :                   if (need_d)
    2099             :                     {
    2100           0 :                       fputs ("D ", stdout);
    2101           0 :                       need_d = 0;
    2102             :                     }
    2103           0 :                   if (*s == '%' && j+2 < linelen)
    2104             :                     {
    2105           0 :                       s++; j++;
    2106           0 :                       c = xtoi_2 ( s );
    2107           0 :                       s++; j++;
    2108             :                     }
    2109             :                   else
    2110           0 :                     c = *s;
    2111           0 :                   if (c == '\n')
    2112           0 :                     need_d = 1;
    2113           0 :                   putchar (c);
    2114             :                 }
    2115           0 :               need_lf = (c != '\n');
    2116             :             }
    2117             :           else
    2118             :             {
    2119           0 :               fwrite (line, linelen, 1, stdout);
    2120           0 :               putchar ('\n');
    2121             :             }
    2122             :         }
    2123             :       else
    2124             :         {
    2125          43 :           if (need_lf)
    2126             :             {
    2127           0 :               if (!current_datasink || current_datasink != stdout)
    2128           0 :                 putchar ('\n');
    2129           0 :               need_lf = 0;
    2130             :             }
    2131             : 
    2132          43 :           if (linelen >= 1
    2133          43 :               && line[0] == 'S'
    2134           0 :               && (line[1] == '\0' || line[1] == ' '))
    2135             :             {
    2136           0 :               if (!current_datasink || current_datasink != stdout)
    2137             :                 {
    2138           0 :                   fwrite (line, linelen, 1, stdout);
    2139           0 :                   putchar ('\n');
    2140             :                 }
    2141             :             }
    2142          43 :           else if (linelen >= 2
    2143          43 :                    && line[0] == 'O' && line[1] == 'K'
    2144          43 :                    && (line[2] == '\0' || line[2] == ' '))
    2145             :             {
    2146          43 :               if (!current_datasink || current_datasink != stdout)
    2147             :                 {
    2148          43 :                   fwrite (line, linelen, 1, stdout);
    2149          43 :                   putchar ('\n');
    2150             :                 }
    2151          43 :               set_int_var ("?", 0);
    2152          43 :               return 0;
    2153             :             }
    2154           0 :           else if (linelen >= 3
    2155           0 :                    && line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
    2156           0 :                    && (line[3] == '\0' || line[3] == ' '))
    2157             :             {
    2158             :               int errval;
    2159             : 
    2160           0 :               errval = strtol (line+3, NULL, 10);
    2161           0 :               if (!errval)
    2162           0 :                 errval = -1;
    2163           0 :               set_int_var ("?", errval);
    2164           0 :               if (!current_datasink || current_datasink != stdout)
    2165             :                 {
    2166           0 :                   fwrite (line, linelen, 1, stdout);
    2167           0 :                   putchar ('\n');
    2168             :                 }
    2169           0 :               *r_goterr = 1;
    2170           0 :               return 0;
    2171             :             }
    2172           0 :           else if (linelen >= 7
    2173           0 :                    && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
    2174           0 :                    && line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
    2175           0 :                    && line[6] == 'E'
    2176           0 :                    && (line[7] == '\0' || line[7] == ' '))
    2177             :             {
    2178           0 :               if (!current_datasink || current_datasink != stdout)
    2179             :                 {
    2180           0 :                   fwrite (line, linelen, 1, stdout);
    2181           0 :                   putchar ('\n');
    2182             :                 }
    2183           0 :               if (!handle_inquire (ctx, line))
    2184           0 :                 assuan_write_line (ctx, "CANCEL");
    2185             :             }
    2186           0 :           else if (linelen >= 3
    2187           0 :                    && line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
    2188           0 :                    && (line[3] == '\0' || line[3] == ' '))
    2189             :             {
    2190           0 :               if (!current_datasink || current_datasink != stdout)
    2191             :                 {
    2192           0 :                   fwrite (line, linelen, 1, stdout);
    2193           0 :                   putchar ('\n');
    2194             :                 }
    2195             :               /* Received from server, thus more responses are expected.  */
    2196             :             }
    2197             :           else
    2198           0 :             return gpg_error (GPG_ERR_ASS_INV_RESPONSE);
    2199             :         }
    2200           0 :     }
    2201             : }
    2202             : 
    2203             : 
    2204             : 
    2205             : 
    2206             : /* Connect to the agent and send the standard options.  */
    2207             : static assuan_context_t
    2208          84 : start_agent (void)
    2209             : {
    2210             :   gpg_error_t err;
    2211             :   assuan_context_t ctx;
    2212             :   session_env_t session_env;
    2213             : 
    2214          84 :   session_env = session_env_new ();
    2215          84 :   if (!session_env)
    2216           0 :     log_fatal ("error allocating session environment block: %s\n",
    2217           0 :                strerror (errno));
    2218          84 :   if (opt.use_dirmngr)
    2219           0 :     err = start_new_dirmngr (&ctx,
    2220             :                              GPG_ERR_SOURCE_DEFAULT,
    2221             :                              opt.dirmngr_program,
    2222             :                              opt.autostart,
    2223           0 :                              !opt.quiet, 0,
    2224             :                              NULL, NULL);
    2225             :   else
    2226          84 :     err = start_new_gpg_agent (&ctx,
    2227             :                                GPG_ERR_SOURCE_DEFAULT,
    2228             :                                opt.agent_program,
    2229             :                                NULL, NULL,
    2230             :                                session_env,
    2231             :                                opt.autostart,
    2232          84 :                                !opt.quiet, 0,
    2233             :                                NULL, NULL);
    2234             : 
    2235          84 :   session_env_release (session_env);
    2236          84 :   if (err)
    2237             :     {
    2238           0 :       if (!opt.autostart
    2239           0 :           && (gpg_err_code (err)
    2240             :               == opt.use_dirmngr? GPG_ERR_NO_DIRMNGR : GPG_ERR_NO_AGENT))
    2241             :         {
    2242             :           /* In the no-autostart case we don't make gpg-connect-agent
    2243             :              fail on a missing server.  */
    2244           0 :           log_info (opt.use_dirmngr?
    2245             :                     _("no dirmngr running in this session\n"):
    2246             :                     _("no gpg-agent running in this session\n"));
    2247           0 :           exit (0);
    2248             :         }
    2249             :       else
    2250             :         {
    2251           0 :           log_error (_("error sending standard options: %s\n"),
    2252             :                      gpg_strerror (err));
    2253           0 :           exit (1);
    2254             :         }
    2255             :     }
    2256             : 
    2257          84 :   return ctx;
    2258             : }

Generated by: LCOV version 1.11