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