LCOV - code coverage report
Current view: top level - tools - gpg-connect-agent.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 158 1038 15.2 %
Date: 2015-11-05 17:10:59 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 = opt.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           1 : set_var (const char *name, const char *value)
     363             : {
     364             :   variable_t var;
     365             : 
     366           1 :   for (var = variable_table; var; var = var->next)
     367           0 :     if (!strcmp (var->name, name))
     368           0 :       break;
     369           1 :   if (!var)
     370             :     {
     371           1 :       var = xmalloc (sizeof *var + strlen (name));
     372           1 :       var->value = NULL;
     373           1 :       strcpy (var->name, name);
     374           1 :       var->next = variable_table;
     375           1 :       variable_table = var;
     376             :     }
     377           1 :   xfree (var->value);
     378           1 :   var->value = value? xstrdup (value) : NULL;
     379           1 :   return var->value;
     380             : }
     381             : 
     382             : 
     383             : static void
     384           1 : set_int_var (const char *name, int value)
     385             : {
     386             :   char numbuf[35];
     387             : 
     388           1 :   snprintf (numbuf, sizeof numbuf, "%d", value);
     389           1 :   set_var (name, numbuf);
     390           1 : }
     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 = make_filename (opt.homedir, NULL);
     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           1 : help_cmd_p (const char *line)
    1132             : {
    1133           1 :   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           2 :   return (!ascii_strncasecmp (line, "HELP", 4)
    1141           1 :           && (spacep (line+4) || !line[4]));
    1142             : }
    1143             : 
    1144             : 
    1145             : /* gpg-connect-agent's entry point. */
    1146             : int
    1147           2 : main (int argc, char **argv)
    1148             : {
    1149             :   ARGPARSE_ARGS pargs;
    1150           2 :   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           2 :   const char *opt_run = NULL;
    1158           2 :   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           2 :   char **cmdline_commands = NULL;
    1171             : 
    1172           2 :   early_system_init ();
    1173           2 :   gnupg_rl_initialize ();
    1174           2 :   set_strusage (my_strusage);
    1175           2 :   log_set_prefix ("gpg-connect-agent", 1);
    1176             : 
    1177             :   /* Make sure that our subsystems are ready.  */
    1178           2 :   i18n_init();
    1179           2 :   init_common_subsystems (&argc, &argv);
    1180             : 
    1181           2 :   assuan_set_gpg_err_source (0);
    1182             : 
    1183             : 
    1184           2 :   opt.homedir = default_homedir ();
    1185           2 :   opt.autostart = 1;
    1186           2 :   opt.connect_flags = 1;
    1187             : 
    1188             :   /* Parse the command line. */
    1189           2 :   pargs.argc  = &argc;
    1190           2 :   pargs.argv  = &argv;
    1191           2 :   pargs.flags =  1;  /* Do not remove the args.  */
    1192           6 :   while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts))
    1193             :     {
    1194           2 :       switch (pargs.r_opt)
    1195             :         {
    1196           0 :         case oQuiet:     opt.quiet = 1; break;
    1197           1 :         case oVerbose:   opt.verbose++; break;
    1198           0 :         case oNoVerbose: opt.verbose = 0; break;
    1199           0 :         case oHomedir:   opt.homedir = pargs.r.ret_str; break;
    1200           1 :         case oAgentProgram: opt.agent_program = pargs.r.ret_str;  break;
    1201           0 :         case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str;  break;
    1202           0 :         case oNoAutostart:    opt.autostart = 0; break;
    1203           0 :         case oHex:       opt.hex = 1; break;
    1204           0 :         case oDecode:    opt.decode = 1; break;
    1205           0 :         case oDirmngr:   opt.use_dirmngr = 1; break;
    1206           0 :         case oUIServer:  opt.use_uiserver = 1; break;
    1207           0 :         case oRawSocket: opt.raw_socket = pargs.r.ret_str; break;
    1208           0 :         case oTcpSocket: opt.tcp_socket = pargs.r.ret_str; break;
    1209           0 :         case oExec:      opt.exec = 1; break;
    1210           0 :         case oNoExtConnect: opt.connect_flags &= ~(1); break;
    1211           0 :         case oRun:       opt_run = pargs.r.ret_str; break;
    1212             :         case oSubst:
    1213           0 :           opt.enable_varsubst = 1;
    1214           0 :           opt.trim_leading_spaces = 1;
    1215           0 :           break;
    1216             : 
    1217           0 :         default: pargs.err = 2; break;
    1218             :         }
    1219             :     }
    1220             : 
    1221           2 :   if (log_get_errorcount (0))
    1222           0 :     exit (2);
    1223             : 
    1224             :   /* --uiserver is a shortcut for a specific raw socket.  This comes
    1225             :        in particular handy on Windows. */
    1226           2 :   if (opt.use_uiserver)
    1227             :     {
    1228           0 :       opt.raw_socket = make_absfilename (opt.homedir, "S.uiserver", NULL);
    1229             :     }
    1230             : 
    1231             :   /* Print a warning if an argument looks like an option.  */
    1232           2 :   if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
    1233             :     {
    1234             :       int i;
    1235             : 
    1236           5 :       for (i=0; i < argc; i++)
    1237           3 :         if (argv[i][0] == '-' && argv[i][1] == '-')
    1238           0 :           log_info (_("Note: '%s' is not considered an option\n"), argv[i]);
    1239             :     }
    1240             : 
    1241             : 
    1242           2 :   use_tty = (gnupg_isatty (fileno (stdin)) && gnupg_isatty (fileno (stdout)));
    1243             : 
    1244           2 :   if (opt.exec)
    1245             :     {
    1246           0 :       if (!argc)
    1247             :         {
    1248           0 :           log_error (_("option \"%s\" requires a program "
    1249             :                        "and optional arguments\n"), "--exec" );
    1250           0 :           exit (1);
    1251             :         }
    1252             :     }
    1253           2 :   else if (argc)
    1254           2 :     cmdline_commands = argv;
    1255             : 
    1256           2 :   if (opt.exec && opt.raw_socket)
    1257             :     {
    1258           0 :       opt.raw_socket = NULL;
    1259           0 :       log_info (_("option \"%s\" ignored due to \"%s\"\n"),
    1260             :                 "--raw-socket", "--exec");
    1261             :     }
    1262           2 :   if (opt.exec && opt.tcp_socket)
    1263             :     {
    1264           0 :       opt.tcp_socket = NULL;
    1265           0 :       log_info (_("option \"%s\" ignored due to \"%s\"\n"),
    1266             :                 "--tcp-socket", "--exec");
    1267             :     }
    1268           2 :   if (opt.tcp_socket && opt.raw_socket)
    1269             :     {
    1270           0 :       opt.tcp_socket = NULL;
    1271           0 :       log_info (_("option \"%s\" ignored due to \"%s\"\n"),
    1272             :                 "--tcp-socket", "--raw-socket");
    1273             :     }
    1274             : 
    1275           2 :   if (opt_run && !(script_fp = fopen (opt_run, "r")))
    1276             :     {
    1277           0 :       log_error ("cannot open run file '%s': %s\n",
    1278           0 :                  opt_run, strerror (errno));
    1279           0 :       exit (1);
    1280             :     }
    1281             : 
    1282             : 
    1283           2 :   if (opt.exec)
    1284             :     {
    1285             :       assuan_fd_t no_close[3];
    1286             : 
    1287           0 :       no_close[0] = assuan_fd_from_posix_fd (es_fileno (es_stderr));
    1288           0 :       no_close[1] = assuan_fd_from_posix_fd (log_get_fd ());
    1289           0 :       no_close[2] = ASSUAN_INVALID_FD;
    1290             : 
    1291           0 :       rc = assuan_new (&ctx);
    1292           0 :       if (rc)
    1293             :         {
    1294           0 :           log_error ("assuan_new failed: %s\n", gpg_strerror (rc));
    1295           0 :           exit (1);
    1296             :         }
    1297             : 
    1298           0 :       rc = assuan_pipe_connect
    1299             :         (ctx, *argv, (const char **)argv, no_close, NULL, NULL,
    1300           0 :          (opt.connect_flags & 1) ? ASSUAN_PIPE_CONNECT_FDPASSING : 0);
    1301           0 :       if (rc)
    1302             :         {
    1303           0 :           log_error ("assuan_pipe_connect_ext failed: %s\n",
    1304             :                      gpg_strerror (rc));
    1305           0 :           exit (1);
    1306             :         }
    1307             : 
    1308           0 :       if (opt.verbose)
    1309           0 :         log_info ("server '%s' started\n", *argv);
    1310             : 
    1311             :     }
    1312           2 :   else if (opt.raw_socket)
    1313             :     {
    1314           0 :       rc = assuan_new (&ctx);
    1315           0 :       if (rc)
    1316             :         {
    1317           0 :           log_error ("assuan_new failed: %s\n", gpg_strerror (rc));
    1318           0 :           exit (1);
    1319             :         }
    1320             : 
    1321           0 :       rc = assuan_socket_connect
    1322             :         (ctx, opt.raw_socket, 0,
    1323           0 :          (opt.connect_flags & 1) ? ASSUAN_SOCKET_CONNECT_FDPASSING : 0);
    1324           0 :       if (rc)
    1325             :         {
    1326           0 :           log_error ("can't connect to socket '%s': %s\n",
    1327             :                      opt.raw_socket, gpg_strerror (rc));
    1328           0 :           exit (1);
    1329             :         }
    1330             : 
    1331           0 :       if (opt.verbose)
    1332           0 :         log_info ("connection to socket '%s' established\n", opt.raw_socket);
    1333             :     }
    1334           2 :   else if (opt.tcp_socket)
    1335             :     {
    1336             :       char *url;
    1337             : 
    1338           0 :       url = xstrconcat ("assuan://", opt.tcp_socket, NULL);
    1339             : 
    1340           0 :       rc = assuan_new (&ctx);
    1341           0 :       if (rc)
    1342             :         {
    1343           0 :           log_error ("assuan_new failed: %s\n", gpg_strerror (rc));
    1344           0 :           exit (1);
    1345             :         }
    1346             : 
    1347           0 :       rc = assuan_socket_connect (ctx, opt.tcp_socket, 0, 0);
    1348           0 :       if (rc)
    1349             :         {
    1350           0 :           log_error ("can't connect to server '%s': %s\n",
    1351             :                      opt.tcp_socket, gpg_strerror (rc));
    1352           0 :           exit (1);
    1353             :         }
    1354             : 
    1355           0 :       if (opt.verbose)
    1356           0 :         log_info ("connection to socket '%s' established\n", url);
    1357             : 
    1358           0 :       xfree (url);
    1359             :     }
    1360             :   else
    1361           2 :     ctx = start_agent ();
    1362             : 
    1363             :   /* See whether there is a line pending from the server (in case
    1364             :      assuan did not run the initial handshaking).  */
    1365           2 :   if (assuan_pending_line (ctx))
    1366             :     {
    1367           0 :       rc = read_and_print_response (ctx, 0, &cmderr);
    1368           0 :       if (rc)
    1369           0 :         log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
    1370             :     }
    1371             : 
    1372             : 
    1373          42 :   for (loopidx=0; loopidx < DIM (loopstack); loopidx++)
    1374          40 :     loopstack[loopidx].collecting = 0;
    1375           2 :   loopidx = -1;
    1376           2 :   line = NULL;
    1377           2 :   linesize = 0;
    1378           2 :   keep_line = 1;
    1379             :   for (;;)
    1380             :     {
    1381             :       int n;
    1382           3 :       size_t maxlength = 2048;
    1383             : 
    1384           3 :       assert (loopidx < (int)DIM (loopstack));
    1385           3 :       if (loopidx >= 0 && loopstack[loopidx].current)
    1386             :         {
    1387           0 :           keep_line = 0;
    1388           0 :           xfree (line);
    1389           0 :           line = xstrdup (loopstack[loopidx].current->line);
    1390           0 :           n = strlen (line);
    1391             :           /* Never go beyond of the final /end.  */
    1392           0 :           if (loopstack[loopidx].current->next)
    1393           0 :             loopstack[loopidx].current = loopstack[loopidx].current->next;
    1394           0 :           else if (!strncmp (line, "/end", 4) && (!line[4]||spacep(line+4)))
    1395             :             ;
    1396             :           else
    1397           0 :             log_fatal ("/end command vanished\n");
    1398             :         }
    1399           3 :       else if (cmdline_commands && *cmdline_commands && !script_fp)
    1400             :         {
    1401           3 :           keep_line = 0;
    1402           3 :           xfree (line);
    1403           3 :           line = xstrdup (*cmdline_commands);
    1404           3 :           cmdline_commands++;
    1405           3 :           n = strlen (line);
    1406           6 :           if (n >= maxlength)
    1407           0 :             maxlength = 0;
    1408             :         }
    1409           0 :       else if (use_tty && !script_fp)
    1410             :         {
    1411           0 :           keep_line = 0;
    1412           0 :           xfree (line);
    1413           0 :           line = tty_get ("> ");
    1414           0 :           n = strlen (line);
    1415           0 :           if (n==1 && *line == CONTROL_D)
    1416           0 :             n = 0;
    1417           0 :           if (n >= maxlength)
    1418           0 :             maxlength = 0;
    1419             :         }
    1420             :       else
    1421             :         {
    1422           0 :           if (!keep_line)
    1423             :             {
    1424           0 :               xfree (line);
    1425           0 :               line = NULL;
    1426           0 :               linesize = 0;
    1427           0 :               keep_line = 1;
    1428             :             }
    1429           0 :           n = read_line (script_fp? script_fp:stdin,
    1430             :                          &line, &linesize, &maxlength);
    1431             :         }
    1432           3 :       if (n < 0)
    1433             :         {
    1434           0 :           log_error (_("error reading input: %s\n"), strerror (errno));
    1435           0 :           if (script_fp)
    1436             :             {
    1437           0 :               fclose (script_fp);
    1438           0 :               script_fp = NULL;
    1439           0 :               log_error ("stopping script execution\n");
    1440           0 :               continue;
    1441             :             }
    1442           0 :           exit (1);
    1443             :         }
    1444           3 :       if (!n)
    1445             :         {
    1446             :           /* EOF */
    1447           0 :           if (script_fp)
    1448             :             {
    1449           0 :               fclose (script_fp);
    1450           0 :               script_fp = NULL;
    1451           0 :               if (opt.verbose)
    1452           0 :                 log_info ("end of script\n");
    1453           0 :               continue;
    1454             :             }
    1455           2 :           break;
    1456             :         }
    1457           3 :       if (!maxlength)
    1458             :         {
    1459           0 :           log_error (_("line too long - skipped\n"));
    1460           0 :           continue;
    1461             :         }
    1462           3 :       if (memchr (line, 0, n))
    1463           0 :         log_info (_("line shortened due to embedded Nul character\n"));
    1464           3 :       if (line[n-1] == '\n')
    1465           0 :         line[n-1] = 0;
    1466             : 
    1467           3 :       if (opt.trim_leading_spaces)
    1468             :         {
    1469           0 :           const char *s = line;
    1470             : 
    1471           0 :           while (spacep (s))
    1472           0 :             s++;
    1473           0 :           if (s != line)
    1474             :             {
    1475           0 :               for (p=line; *s;)
    1476           0 :                 *p++ = *s++;
    1477           0 :               *p = 0;
    1478           0 :               n = p - line;
    1479             :             }
    1480             :         }
    1481             : 
    1482           3 :       if (loopidx+1 >= 0 && loopstack[loopidx+1].collecting)
    1483             :         {
    1484             :           loopline_t ll;
    1485             : 
    1486           0 :           ll = xmalloc (sizeof *ll + strlen (line));
    1487           0 :           ll->next = NULL;
    1488           0 :           strcpy (ll->line, line);
    1489           0 :           *loopstack[loopidx+1].tail = ll;
    1490           0 :           loopstack[loopidx+1].tail = &ll->next;
    1491             : 
    1492           0 :           if (!strncmp (line, "/end", 4) && (!line[4]||spacep(line+4)))
    1493           0 :             loopstack[loopidx+1].nestlevel--;
    1494           0 :           else if (!strncmp (line, "/while", 6) && (!line[6]||spacep(line+6)))
    1495           0 :             loopstack[loopidx+1].nestlevel++;
    1496             : 
    1497           0 :           if (loopstack[loopidx+1].nestlevel)
    1498           0 :             continue;
    1499             :           /* We reached the corresponding /end.  */
    1500           0 :           loopstack[loopidx+1].collecting = 0;
    1501           0 :           loopidx++;
    1502             :         }
    1503             : 
    1504           3 :       if (*line == '/')
    1505             :         {
    1506             :           /* Handle control commands. */
    1507           2 :           char *cmd = line+1;
    1508             : 
    1509           2 :           for (p=cmd; *p && !spacep (p); p++)
    1510             :             ;
    1511           2 :           if (*p)
    1512           0 :             *p++ = 0;
    1513           4 :           while (spacep (p))
    1514           0 :             p++;
    1515           2 :           if (!strcmp (cmd, "let"))
    1516             :             {
    1517           0 :               assign_variable (p, 0);
    1518             :             }
    1519           2 :           else if (!strcmp (cmd, "slet"))
    1520             :             {
    1521             :               /* Deprecated - never used in a released version.  */
    1522           0 :               assign_variable (p, 1);
    1523             :             }
    1524           2 :           else if (!strcmp (cmd, "showvar"))
    1525             :             {
    1526           0 :               show_variables ();
    1527             :             }
    1528           2 :           else if (!strcmp (cmd, "definq"))
    1529             :             {
    1530           0 :               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
    1531           0 :               if (tmpline)
    1532             :                 {
    1533           0 :                   add_definq (tmpline, 1, 0);
    1534           0 :                   xfree (tmpline);
    1535             :                 }
    1536             :               else
    1537           0 :                 add_definq (p, 1, 0);
    1538             :             }
    1539           2 :           else if (!strcmp (cmd, "definqfile"))
    1540             :             {
    1541           0 :               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
    1542           0 :               if (tmpline)
    1543             :                 {
    1544           0 :                   add_definq (tmpline, 0, 0);
    1545           0 :                   xfree (tmpline);
    1546             :                 }
    1547             :               else
    1548           0 :                 add_definq (p, 0, 0);
    1549             :             }
    1550           2 :           else if (!strcmp (cmd, "definqprog"))
    1551             :             {
    1552           0 :               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
    1553           0 :               if (tmpline)
    1554             :                 {
    1555           0 :                   add_definq (tmpline, 0, 1);
    1556           0 :                   xfree (tmpline);
    1557             :                 }
    1558             :               else
    1559           0 :                 add_definq (p, 0, 1);
    1560             :             }
    1561           2 :           else if (!strcmp (cmd, "datafile"))
    1562             :             {
    1563             :               const char *fname;
    1564             : 
    1565           0 :               if (current_datasink)
    1566             :                 {
    1567           0 :                   if (current_datasink != stdout)
    1568           0 :                     fclose (current_datasink);
    1569           0 :                   current_datasink = NULL;
    1570             :                 }
    1571           0 :               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
    1572           0 :               fname = tmpline? tmpline : p;
    1573           0 :               if (fname && !strcmp (fname, "-"))
    1574           0 :                 current_datasink = stdout;
    1575           0 :               else if (fname && *fname)
    1576             :                 {
    1577           0 :                   current_datasink = fopen (fname, "wb");
    1578           0 :                   if (!current_datasink)
    1579           0 :                     log_error ("can't open '%s': %s\n",
    1580           0 :                                fname, strerror (errno));
    1581             :                 }
    1582           0 :               xfree (tmpline);
    1583             :             }
    1584           2 :           else if (!strcmp (cmd, "showdef"))
    1585             :             {
    1586           0 :               show_definq ();
    1587             :             }
    1588           2 :           else if (!strcmp (cmd, "cleardef"))
    1589             :             {
    1590           0 :               clear_definq ();
    1591             :             }
    1592           2 :           else if (!strcmp (cmd, "echo"))
    1593             :             {
    1594           0 :               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
    1595           0 :               if (tmpline)
    1596             :                 {
    1597           0 :                   puts (tmpline);
    1598           0 :                   xfree (tmpline);
    1599             :                 }
    1600             :               else
    1601           0 :                 puts (p);
    1602             :             }
    1603           2 :           else if (!strcmp (cmd, "sendfd"))
    1604             :             {
    1605           0 :               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
    1606           0 :               if (tmpline)
    1607             :                 {
    1608           0 :                   do_sendfd (ctx, tmpline);
    1609           0 :                   xfree (tmpline);
    1610             :                 }
    1611             :               else
    1612           0 :                 do_sendfd (ctx, p);
    1613           0 :               continue;
    1614             :             }
    1615           2 :           else if (!strcmp (cmd, "recvfd"))
    1616             :             {
    1617           0 :               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
    1618           0 :               if (tmpline)
    1619             :                 {
    1620           0 :                   do_recvfd (ctx, tmpline);
    1621           0 :                   xfree (tmpline);
    1622             :                 }
    1623             :               else
    1624           0 :                 do_recvfd (ctx, p);
    1625           0 :               continue;
    1626             :             }
    1627           2 :           else if (!strcmp (cmd, "open"))
    1628             :             {
    1629           0 :               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
    1630           0 :               if (tmpline)
    1631             :                 {
    1632           0 :                   do_open (tmpline);
    1633           0 :                   xfree (tmpline);
    1634             :                 }
    1635             :               else
    1636           0 :                 do_open (p);
    1637             :             }
    1638           2 :           else if (!strcmp (cmd, "close"))
    1639             :             {
    1640           0 :               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
    1641           0 :               if (tmpline)
    1642             :                 {
    1643           0 :                   do_close (tmpline);
    1644           0 :                   xfree (tmpline);
    1645             :                 }
    1646             :               else
    1647           0 :                 do_close (p);
    1648             :             }
    1649           2 :           else if (!strcmp (cmd, "showopen"))
    1650             :             {
    1651           0 :               do_showopen ();
    1652             :             }
    1653           2 :           else if (!strcmp (cmd, "serverpid"))
    1654             :             {
    1655           0 :               do_serverpid (ctx);
    1656             :             }
    1657           2 :           else if (!strcmp (cmd, "hex"))
    1658           0 :             opt.hex = 1;
    1659           2 :           else if (!strcmp (cmd, "nohex"))
    1660           0 :             opt.hex = 0;
    1661           2 :           else if (!strcmp (cmd, "decode"))
    1662           0 :             opt.decode = 1;
    1663           2 :           else if (!strcmp (cmd, "nodecode"))
    1664           0 :             opt.decode = 0;
    1665           2 :           else if (!strcmp (cmd, "subst"))
    1666             :             {
    1667           0 :               opt.enable_varsubst = 1;
    1668           0 :               opt.trim_leading_spaces = 1;
    1669             :             }
    1670           2 :           else if (!strcmp (cmd, "nosubst"))
    1671           0 :             opt.enable_varsubst = 0;
    1672           2 :           else if (!strcmp (cmd, "run"))
    1673             :             {
    1674             :               char *p2;
    1675             : 
    1676           0 :               for (p2=p; *p2 && !spacep (p2); p2++)
    1677             :                 ;
    1678           0 :               if (*p2)
    1679           0 :                 *p2++ = 0;
    1680           0 :               while (spacep (p2))
    1681           0 :                 p++;
    1682           0 :               if (*p2)
    1683             :                 {
    1684           0 :                   log_error ("syntax error in run command\n");
    1685           0 :                   if (script_fp)
    1686             :                     {
    1687           0 :                       fclose (script_fp);
    1688           0 :                       script_fp = NULL;
    1689             :                     }
    1690             :                 }
    1691           0 :               else if (script_fp)
    1692             :                 {
    1693           0 :                   log_error ("cannot nest run commands - stop\n");
    1694           0 :                   fclose (script_fp);
    1695           0 :                   script_fp = NULL;
    1696             :                 }
    1697           0 :               else if (!(script_fp = fopen (p, "r")))
    1698             :                 {
    1699           0 :                   log_error ("cannot open run file '%s': %s\n",
    1700           0 :                              p, strerror (errno));
    1701             :                 }
    1702           0 :               else if (opt.verbose)
    1703           0 :                 log_info ("running commands from '%s'\n", p);
    1704             :             }
    1705           2 :           else if (!strcmp (cmd, "while"))
    1706             :             {
    1707           0 :               if (loopidx+2 >= (int)DIM(loopstack))
    1708             :                 {
    1709           0 :                   log_error ("blocks are nested too deep\n");
    1710             :                   /* We should better die or break all loop in this
    1711             :                      case as recovering from this error won't be
    1712             :                      easy.  */
    1713             :                 }
    1714             :               else
    1715             :                 {
    1716           0 :                   loopstack[loopidx+1].head = NULL;
    1717           0 :                   loopstack[loopidx+1].tail = &loopstack[loopidx+1].head;
    1718           0 :                   loopstack[loopidx+1].current = NULL;
    1719           0 :                   loopstack[loopidx+1].nestlevel = 1;
    1720           0 :                   loopstack[loopidx+1].oneshot = 0;
    1721           0 :                   loopstack[loopidx+1].condition = xstrdup (p);
    1722           0 :                   loopstack[loopidx+1].collecting = 1;
    1723             :                 }
    1724             :             }
    1725           2 :           else if (!strcmp (cmd, "if"))
    1726             :             {
    1727           0 :               if (loopidx+2 >= (int)DIM(loopstack))
    1728             :                 {
    1729           0 :                   log_error ("blocks are nested too deep\n");
    1730             :                 }
    1731             :               else
    1732             :                 {
    1733             :                   /* Note that we need to evaluate the condition right
    1734             :                      away and not just at the end of the block as we
    1735             :                      do with a WHILE. */
    1736           0 :                   loopstack[loopidx+1].head = NULL;
    1737           0 :                   loopstack[loopidx+1].tail = &loopstack[loopidx+1].head;
    1738           0 :                   loopstack[loopidx+1].current = NULL;
    1739           0 :                   loopstack[loopidx+1].nestlevel = 1;
    1740           0 :                   loopstack[loopidx+1].oneshot = 1;
    1741           0 :                   loopstack[loopidx+1].condition = substitute_line_copy (p);
    1742           0 :                   loopstack[loopidx+1].collecting = 1;
    1743             :                 }
    1744             :             }
    1745           2 :           else if (!strcmp (cmd, "end"))
    1746             :             {
    1747           0 :               if (loopidx < 0)
    1748           0 :                 log_error ("stray /end command encountered - ignored\n");
    1749             :               else
    1750             :                 {
    1751             :                   char *tmpcond;
    1752             :                   const char *value;
    1753             :                   long condition;
    1754             : 
    1755             :                   /* Evaluate the condition.  */
    1756           0 :                   tmpcond = xstrdup (loopstack[loopidx].condition);
    1757           0 :                   if (loopstack[loopidx].oneshot)
    1758             :                     {
    1759           0 :                       xfree (loopstack[loopidx].condition);
    1760           0 :                       loopstack[loopidx].condition = xstrdup ("0");
    1761             :                     }
    1762           0 :                   tmpline = substitute_line (tmpcond);
    1763           0 :                   value = tmpline? tmpline : tmpcond;
    1764             :                   /* "true" or "yes" are commonly used to mean TRUE;
    1765             :                      all other strings will evaluate to FALSE due to
    1766             :                      the strtoul.  */
    1767           0 :                   if (!ascii_strcasecmp (value, "true")
    1768           0 :                       || !ascii_strcasecmp (value, "yes"))
    1769           0 :                     condition = 1;
    1770             :                   else
    1771           0 :                     condition = strtol (value, NULL, 0);
    1772           0 :                   xfree (tmpline);
    1773           0 :                   xfree (tmpcond);
    1774             : 
    1775           0 :                   if (condition)
    1776             :                     {
    1777             :                       /* Run loop.  */
    1778           0 :                       loopstack[loopidx].current = loopstack[loopidx].head;
    1779             :                     }
    1780             :                   else
    1781             :                     {
    1782             :                       /* Cleanup.  */
    1783           0 :                       while (loopstack[loopidx].head)
    1784             :                         {
    1785           0 :                           loopline_t tmp = loopstack[loopidx].head->next;
    1786           0 :                           xfree (loopstack[loopidx].head);
    1787           0 :                           loopstack[loopidx].head = tmp;
    1788             :                         }
    1789           0 :                       loopstack[loopidx].tail = NULL;
    1790           0 :                       loopstack[loopidx].current = NULL;
    1791           0 :                       loopstack[loopidx].nestlevel = 0;
    1792           0 :                       loopstack[loopidx].collecting = 0;
    1793           0 :                       loopstack[loopidx].oneshot = 0;
    1794           0 :                       xfree (loopstack[loopidx].condition);
    1795           0 :                       loopstack[loopidx].condition = NULL;
    1796           0 :                       loopidx--;
    1797             :                     }
    1798             :                 }
    1799             :             }
    1800           2 :           else if (!strcmp (cmd, "bye"))
    1801             :             {
    1802           2 :               break;
    1803             :             }
    1804           0 :           else if (!strcmp (cmd, "sleep"))
    1805             :             {
    1806           0 :               gnupg_sleep (1);
    1807             :             }
    1808           0 :           else if (!strcmp (cmd, "help"))
    1809             :             {
    1810           0 :               puts (
    1811             : "Available commands:\n"
    1812             : "/echo ARGS             Echo ARGS.\n"
    1813             : "/let  NAME VALUE       Set variable NAME to VALUE.\n"
    1814             : "/showvar               Show all variables.\n"
    1815             : "/definq NAME VAR       Use content of VAR for inquiries with NAME.\n"
    1816             : "/definqfile NAME FILE  Use content of FILE for inquiries with NAME.\n"
    1817             : "/definqprog NAME PGM   Run PGM for inquiries with NAME.\n"
    1818             : "/datafile [NAME]       Write all D line content to file NAME.\n"
    1819             : "/showdef               Print all definitions.\n"
    1820             : "/cleardef              Delete all definitions.\n"
    1821             : "/sendfd FILE MODE      Open FILE and pass descriptor to server.\n"
    1822             : "/recvfd                Receive FD from server and print.\n"
    1823             : "/open VAR FILE MODE    Open FILE and assign the file descriptor to VAR.\n"
    1824             : "/close FD              Close file with descriptor FD.\n"
    1825             : "/showopen              Show descriptors of all open files.\n"
    1826             : "/serverpid             Retrieve the pid of the server.\n"
    1827             : "/[no]hex               Enable hex dumping of received data lines.\n"
    1828             : "/[no]decode            Enable decoding of received data lines.\n"
    1829             : "/[no]subst             Enable variable substitution.\n"
    1830             : "/run FILE              Run commands from FILE.\n"
    1831             : "/if VAR                Begin conditional block controlled by VAR.\n"
    1832             : "/while VAR             Begin loop controlled by VAR.\n"
    1833             : "/end                   End loop or condition\n"
    1834             : "/bye                   Terminate gpg-connect-agent.\n"
    1835             : "/help                  Print this help.");
    1836             :             }
    1837             :           else
    1838           0 :             log_error (_("unknown command '%s'\n"), cmd );
    1839             : 
    1840           0 :           continue;
    1841             :         }
    1842             : 
    1843           1 :       if (opt.verbose && script_fp)
    1844           0 :         puts (line);
    1845             : 
    1846           1 :       tmpline = opt.enable_varsubst? substitute_line (line) : NULL;
    1847           1 :       if (tmpline)
    1848             :         {
    1849           0 :           rc = assuan_write_line (ctx, tmpline);
    1850           0 :           xfree (tmpline);
    1851             :         }
    1852             :       else
    1853           1 :         rc = assuan_write_line (ctx, line);
    1854           1 :       if (rc)
    1855             :         {
    1856           0 :           log_info (_("sending line failed: %s\n"), gpg_strerror (rc) );
    1857           0 :           break;
    1858             :         }
    1859           1 :       if (*line == '#' || !*line)
    1860           0 :         continue; /* Don't expect a response for a comment line. */
    1861             : 
    1862           1 :       rc = read_and_print_response (ctx, help_cmd_p (line), &cmderr);
    1863           1 :       if (rc)
    1864           0 :         log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
    1865           1 :       if ((rc || cmderr) && script_fp)
    1866             :         {
    1867           0 :           log_error ("stopping script execution\n");
    1868           0 :           fclose (script_fp);
    1869           0 :           script_fp = NULL;
    1870             :         }
    1871             : 
    1872             : 
    1873             :       /* FIXME: If the last command was BYE or the server died for
    1874             :          some other reason, we won't notice until we get the next
    1875             :          input command.  Probing the connection with a non-blocking
    1876             :          read could help to notice termination or other problems
    1877             :          early.  */
    1878           1 :     }
    1879             : 
    1880           2 :   if (opt.verbose)
    1881           1 :     log_info ("closing connection to agent\n");
    1882             : 
    1883           2 :   return 0;
    1884             : }
    1885             : 
    1886             : 
    1887             : /* Handle an Inquire from the server.  Return False if it could not be
    1888             :    handled; in this case the caller shll complete the operation.  LINE
    1889             :    is the complete line as received from the server.  This function
    1890             :    may change the content of LINE. */
    1891             : static int
    1892           0 : handle_inquire (assuan_context_t ctx, char *line)
    1893             : {
    1894             :   const char *name;
    1895             :   definq_t d;
    1896           0 :   FILE *fp = NULL;
    1897             :   char buffer[1024];
    1898             :   int rc, n;
    1899             : 
    1900             :   /* Skip the command and trailing spaces. */
    1901           0 :   for (; *line && !spacep (line); line++)
    1902             :     ;
    1903           0 :   while (spacep (line))
    1904           0 :     line++;
    1905             :   /* Get the name. */
    1906           0 :   name = line;
    1907           0 :   for (; *line && !spacep (line); line++)
    1908             :     ;
    1909           0 :   if (*line)
    1910           0 :     *line++ = 0;
    1911             : 
    1912             :   /* Now match it against our list.  The second loop is there to
    1913             :      detect the match-all entry. */
    1914           0 :   for (d=definq_list; d; d = d->next)
    1915           0 :     if (d->name && !strcmp (d->name, name))
    1916           0 :         break;
    1917           0 :   if (!d)
    1918           0 :     for (d=definq_list; d; d = d->next)
    1919           0 :       if (!d->name)
    1920           0 :         break;
    1921           0 :   if (!d)
    1922             :     {
    1923           0 :       if (opt.verbose)
    1924           0 :         log_info ("no handler for inquiry '%s' found\n", name);
    1925           0 :       return 0;
    1926             :     }
    1927             : 
    1928           0 :   if (d->is_var)
    1929             :     {
    1930           0 :       char *tmpvalue = get_var_ext (d->file);
    1931           0 :       if (tmpvalue)
    1932           0 :         rc = assuan_send_data (ctx, tmpvalue, strlen (tmpvalue));
    1933             :       else
    1934           0 :         rc = assuan_send_data (ctx, "", 0);
    1935           0 :       xfree (tmpvalue);
    1936           0 :       if (rc)
    1937           0 :         log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
    1938             :     }
    1939             :   else
    1940             :     {
    1941           0 :       if (d->is_prog)
    1942             :         {
    1943             : #ifdef HAVE_W32CE_SYSTEM
    1944             :           fp = NULL;
    1945             : #else
    1946           0 :           fp = popen (d->file, "r");
    1947             : #endif
    1948           0 :           if (!fp)
    1949           0 :             log_error ("error executing '%s': %s\n",
    1950           0 :                        d->file, strerror (errno));
    1951           0 :           else if (opt.verbose)
    1952           0 :             log_error ("handling inquiry '%s' by running '%s'\n",
    1953           0 :                        name, d->file);
    1954             :         }
    1955             :       else
    1956             :         {
    1957           0 :           fp = fopen (d->file, "rb");
    1958           0 :           if (!fp)
    1959           0 :             log_error ("error opening '%s': %s\n", d->file, strerror (errno));
    1960           0 :           else if (opt.verbose)
    1961           0 :             log_error ("handling inquiry '%s' by returning content of '%s'\n",
    1962           0 :                        name, d->file);
    1963             :         }
    1964           0 :       if (!fp)
    1965           0 :         return 0;
    1966             : 
    1967           0 :       while ( (n = fread (buffer, 1, sizeof buffer, fp)) )
    1968             :         {
    1969           0 :           rc = assuan_send_data (ctx, buffer, n);
    1970           0 :           if (rc)
    1971             :             {
    1972           0 :               log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
    1973           0 :               break;
    1974             :             }
    1975             :         }
    1976           0 :       if (ferror (fp))
    1977           0 :         log_error ("error reading from '%s': %s\n", d->file, strerror (errno));
    1978             :     }
    1979             : 
    1980           0 :   rc = assuan_send_data (ctx, NULL, 0);
    1981           0 :   if (rc)
    1982           0 :     log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
    1983             : 
    1984           0 :   if (d->is_var)
    1985             :     ;
    1986           0 :   else if (d->is_prog)
    1987             :     {
    1988             : #ifndef HAVE_W32CE_SYSTEM
    1989           0 :       if (pclose (fp))
    1990           0 :         log_error ("error running '%s': %s\n", d->file, strerror (errno));
    1991             : #endif
    1992             :     }
    1993             :   else
    1994           0 :     fclose (fp);
    1995           0 :   return 1;
    1996             : }
    1997             : 
    1998             : 
    1999             : /* Read all response lines from server and print them.  Returns 0 on
    2000             :    success or an assuan error code.  If WITHHASH istrue, comment lines
    2001             :    are printed.  Sets R_GOTERR to true if the command did not returned
    2002             :    OK.  */
    2003             : static int
    2004           1 : read_and_print_response (assuan_context_t ctx, int withhash, int *r_goterr)
    2005             : {
    2006             :   char *line;
    2007             :   size_t linelen;
    2008             :   gpg_error_t rc;
    2009             :   int i, j;
    2010           1 :   int need_lf = 0;
    2011             : 
    2012           1 :   *r_goterr = 0;
    2013             :   for (;;)
    2014             :     {
    2015             :       do
    2016             :         {
    2017           1 :           rc = assuan_read_line (ctx, &line, &linelen);
    2018           1 :           if (rc)
    2019           0 :             return rc;
    2020             : 
    2021           1 :           if ((withhash || opt.verbose > 1) && *line == '#')
    2022             :             {
    2023           0 :               fwrite (line, linelen, 1, stdout);
    2024           0 :               putchar ('\n');
    2025             :             }
    2026             :         }
    2027           1 :       while (*line == '#' || !linelen);
    2028             : 
    2029           1 :       if (linelen >= 1
    2030           1 :           && line[0] == 'D' && line[1] == ' ')
    2031             :         {
    2032           0 :           if (current_datasink)
    2033             :             {
    2034             :               const unsigned char *s;
    2035           0 :               int c = 0;
    2036             : 
    2037           0 :               for (j=2, s=(unsigned char*)line+2; j < linelen; j++, s++ )
    2038             :                 {
    2039           0 :                   if (*s == '%' && j+2 < linelen)
    2040             :                     {
    2041           0 :                       s++; j++;
    2042           0 :                       c = xtoi_2 ( s );
    2043           0 :                       s++; j++;
    2044             :                     }
    2045             :                   else
    2046           0 :                     c = *s;
    2047           0 :                   putc (c, current_datasink);
    2048             :                 }
    2049             :             }
    2050           0 :           else if (opt.hex)
    2051             :             {
    2052           0 :               for (i=2; i < linelen; )
    2053             :                 {
    2054           0 :                   int save_i = i;
    2055             : 
    2056           0 :                   printf ("D[%04X] ", i-2);
    2057           0 :                   for (j=0; j < 16 ; j++, i++)
    2058             :                     {
    2059           0 :                       if (j == 8)
    2060           0 :                         putchar (' ');
    2061           0 :                       if (i < linelen)
    2062           0 :                         printf (" %02X", ((unsigned char*)line)[i]);
    2063             :                       else
    2064           0 :                         fputs ("   ", stdout);
    2065             :                     }
    2066           0 :                   fputs ("   ", stdout);
    2067           0 :                   i= save_i;
    2068           0 :                   for (j=0; j < 16; j++, i++)
    2069             :                     {
    2070           0 :                       unsigned int c = ((unsigned char*)line)[i];
    2071           0 :                       if ( i >= linelen )
    2072           0 :                         putchar (' ');
    2073           0 :                       else if (isascii (c) && isprint (c) && !iscntrl (c))
    2074           0 :                         putchar (c);
    2075             :                       else
    2076           0 :                         putchar ('.');
    2077             :                     }
    2078           0 :                   putchar ('\n');
    2079             :                 }
    2080             :             }
    2081           0 :           else if (opt.decode)
    2082             :             {
    2083             :               const unsigned char *s;
    2084           0 :               int need_d = 1;
    2085           0 :               int c = 0;
    2086             : 
    2087           0 :               for (j=2, s=(unsigned char*)line+2; j < linelen; j++, s++ )
    2088             :                 {
    2089           0 :                   if (need_d)
    2090             :                     {
    2091           0 :                       fputs ("D ", stdout);
    2092           0 :                       need_d = 0;
    2093             :                     }
    2094           0 :                   if (*s == '%' && j+2 < linelen)
    2095             :                     {
    2096           0 :                       s++; j++;
    2097           0 :                       c = xtoi_2 ( s );
    2098           0 :                       s++; j++;
    2099             :                     }
    2100             :                   else
    2101           0 :                     c = *s;
    2102           0 :                   if (c == '\n')
    2103           0 :                     need_d = 1;
    2104           0 :                   putchar (c);
    2105             :                 }
    2106           0 :               need_lf = (c != '\n');
    2107             :             }
    2108             :           else
    2109             :             {
    2110           0 :               fwrite (line, linelen, 1, stdout);
    2111           0 :               putchar ('\n');
    2112             :             }
    2113             :         }
    2114             :       else
    2115             :         {
    2116           1 :           if (need_lf)
    2117             :             {
    2118           0 :               if (!current_datasink || current_datasink != stdout)
    2119           0 :                 putchar ('\n');
    2120           0 :               need_lf = 0;
    2121             :             }
    2122             : 
    2123           1 :           if (linelen >= 1
    2124           1 :               && line[0] == 'S'
    2125           0 :               && (line[1] == '\0' || line[1] == ' '))
    2126             :             {
    2127           0 :               if (!current_datasink || current_datasink != stdout)
    2128             :                 {
    2129           0 :                   fwrite (line, linelen, 1, stdout);
    2130           0 :                   putchar ('\n');
    2131             :                 }
    2132             :             }
    2133           1 :           else if (linelen >= 2
    2134           1 :                    && line[0] == 'O' && line[1] == 'K'
    2135           1 :                    && (line[2] == '\0' || line[2] == ' '))
    2136             :             {
    2137           1 :               if (!current_datasink || current_datasink != stdout)
    2138             :                 {
    2139           1 :                   fwrite (line, linelen, 1, stdout);
    2140           1 :                   putchar ('\n');
    2141             :                 }
    2142           1 :               set_int_var ("?", 0);
    2143           1 :               return 0;
    2144             :             }
    2145           0 :           else if (linelen >= 3
    2146           0 :                    && line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
    2147           0 :                    && (line[3] == '\0' || line[3] == ' '))
    2148             :             {
    2149             :               int errval;
    2150             : 
    2151           0 :               errval = strtol (line+3, NULL, 10);
    2152           0 :               if (!errval)
    2153           0 :                 errval = -1;
    2154           0 :               set_int_var ("?", errval);
    2155           0 :               if (!current_datasink || current_datasink != stdout)
    2156             :                 {
    2157           0 :                   fwrite (line, linelen, 1, stdout);
    2158           0 :                   putchar ('\n');
    2159             :                 }
    2160           0 :               *r_goterr = 1;
    2161           0 :               return 0;
    2162             :             }
    2163           0 :           else if (linelen >= 7
    2164           0 :                    && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
    2165           0 :                    && line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
    2166           0 :                    && line[6] == 'E'
    2167           0 :                    && (line[7] == '\0' || line[7] == ' '))
    2168             :             {
    2169           0 :               if (!current_datasink || current_datasink != stdout)
    2170             :                 {
    2171           0 :                   fwrite (line, linelen, 1, stdout);
    2172           0 :                   putchar ('\n');
    2173             :                 }
    2174           0 :               if (!handle_inquire (ctx, line))
    2175           0 :                 assuan_write_line (ctx, "CANCEL");
    2176             :             }
    2177           0 :           else if (linelen >= 3
    2178           0 :                    && line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
    2179           0 :                    && (line[3] == '\0' || line[3] == ' '))
    2180             :             {
    2181           0 :               if (!current_datasink || current_datasink != stdout)
    2182             :                 {
    2183           0 :                   fwrite (line, linelen, 1, stdout);
    2184           0 :                   putchar ('\n');
    2185             :                 }
    2186             :               /* Received from server, thus more responses are expected.  */
    2187             :             }
    2188             :           else
    2189           0 :             return gpg_error (GPG_ERR_ASS_INV_RESPONSE);
    2190             :         }
    2191           0 :     }
    2192             : }
    2193             : 
    2194             : 
    2195             : 
    2196             : 
    2197             : /* Connect to the agent and send the standard options.  */
    2198             : static assuan_context_t
    2199           2 : start_agent (void)
    2200             : {
    2201             :   gpg_error_t err;
    2202             :   assuan_context_t ctx;
    2203             :   session_env_t session_env;
    2204             : 
    2205           2 :   session_env = session_env_new ();
    2206           2 :   if (!session_env)
    2207           0 :     log_fatal ("error allocating session environment block: %s\n",
    2208           0 :                strerror (errno));
    2209           2 :   if (opt.use_dirmngr)
    2210           0 :     err = start_new_dirmngr (&ctx,
    2211             :                              GPG_ERR_SOURCE_DEFAULT,
    2212             :                              opt.homedir,
    2213             :                              opt.dirmngr_program,
    2214             :                              opt.autostart,
    2215           0 :                              !opt.quiet, 0,
    2216             :                              NULL, NULL);
    2217             :   else
    2218           2 :     err = start_new_gpg_agent (&ctx,
    2219             :                                GPG_ERR_SOURCE_DEFAULT,
    2220             :                                opt.homedir,
    2221             :                                opt.agent_program,
    2222             :                                NULL, NULL,
    2223             :                                session_env,
    2224             :                                opt.autostart,
    2225           2 :                                !opt.quiet, 0,
    2226             :                                NULL, NULL);
    2227             : 
    2228           2 :   session_env_release (session_env);
    2229           2 :   if (err)
    2230             :     {
    2231           0 :       if (!opt.autostart
    2232           0 :           && (gpg_err_code (err)
    2233             :               == opt.use_dirmngr? GPG_ERR_NO_DIRMNGR : GPG_ERR_NO_AGENT))
    2234             :         {
    2235             :           /* In the no-autostart case we don't make gpg-connect-agent
    2236             :              fail on a missing server.  */
    2237           0 :           log_info (opt.use_dirmngr?
    2238             :                     _("no dirmngr running in this session\n"):
    2239             :                     _("no gpg-agent running in this session\n"));
    2240           0 :           exit (0);
    2241             :         }
    2242             :       else
    2243             :         {
    2244           0 :           log_error (_("error sending standard options: %s\n"),
    2245             :                      gpg_strerror (err));
    2246           0 :           exit (1);
    2247             :         }
    2248             :     }
    2249             : 
    2250           2 :   return ctx;
    2251             : }

Generated by: LCOV version 1.11