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