Minor fixes.
[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 <" PACKAGE_BUGREPORT ">.\n");
181       break;
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 /* Unescale 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 int
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_assuan_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       rc = assuan_pipe_connect_ext (&ctx, *argv, (const char **)argv,
1228                                     no_close, NULL, NULL,
1229                                     opt.connect_flags);
1230       if (rc)
1231         {
1232           log_error ("assuan_pipe_connect_ext failed: %s\n",
1233                      gpg_strerror (rc));
1234           exit (1);
1235         }
1236
1237       if (opt.verbose)
1238         log_info ("server `%s' started\n", *argv);
1239
1240     }
1241   else if (opt.raw_socket)
1242     {
1243       rc = assuan_socket_connect_ext (&ctx, opt.raw_socket, 0,
1244                                       opt.connect_flags);
1245       if (rc)
1246         {
1247           log_error ("can't connect to socket `%s': %s\n",
1248                      opt.raw_socket, gpg_strerror (rc));
1249           exit (1);
1250         }
1251
1252       if (opt.verbose)
1253         log_info ("connection to socket `%s' established\n", opt.raw_socket);
1254     }
1255   else
1256     ctx = start_agent ();
1257
1258   /* See whether there is a line pending from the server (in case
1259      assuan did not run the initial handshaking).  */
1260   if (assuan_pending_line (ctx))
1261     {
1262       rc = read_and_print_response (ctx, &cmderr);
1263       if (rc)
1264         log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
1265     }
1266
1267  
1268   for (loopidx=0; loopidx < DIM (loopstack); loopidx++)
1269     loopstack[loopidx].collecting = 0;
1270   loopidx = -1;
1271   line = NULL;
1272   linesize = 0;
1273   keep_line = 1;
1274   for (;;)
1275     {
1276       int n;
1277       size_t maxlength = 2048;
1278
1279       assert (loopidx < (int)DIM (loopstack));
1280       if (loopidx >= 0 && loopstack[loopidx].current)
1281         {
1282           keep_line = 0;
1283           xfree (line);
1284           line = xstrdup (loopstack[loopidx].current->line);
1285           n = strlen (line);
1286           /* Never go beyond of the final /end.  */
1287           if (loopstack[loopidx].current->next)
1288             loopstack[loopidx].current = loopstack[loopidx].current->next;
1289           else if (!strncmp (line, "/end", 4) && (!line[4]||spacep(line+4)))
1290             ;
1291           else
1292             log_fatal ("/end command vanished\n");
1293         }
1294       else if (cmdline_commands && *cmdline_commands && !script_fp)
1295         {
1296           keep_line = 0;
1297           xfree (line);
1298           line = xstrdup (*cmdline_commands);
1299           cmdline_commands++;
1300           n = strlen (line);
1301           if (n >= maxlength)
1302             maxlength = 0;
1303         }
1304       else if (use_tty && !script_fp)
1305         {
1306           keep_line = 0;
1307           xfree (line);
1308           line = tty_get ("> ");
1309           n = strlen (line);
1310           if (n==1 && *line == CONTROL_D)
1311             n = 0;
1312           if (n >= maxlength)
1313             maxlength = 0;
1314         }
1315       else
1316         {
1317           if (!keep_line)
1318             {
1319               xfree (line);
1320               line = NULL;
1321               linesize = 0;
1322               keep_line = 1;
1323             }
1324           n = read_line (script_fp? script_fp:stdin, 
1325                          &line, &linesize, &maxlength);
1326         }
1327       if (n < 0)
1328         {
1329           log_error (_("error reading input: %s\n"), strerror (errno));
1330           if (script_fp)
1331             {
1332               fclose (script_fp);
1333               script_fp = NULL;
1334               log_error ("stopping script execution\n");
1335               continue;
1336             }
1337           exit (1);
1338         }
1339       if (!n)
1340         {
1341           /* EOF */
1342           if (script_fp)
1343             {
1344               fclose (script_fp);
1345               script_fp = NULL;
1346               if (opt.verbose)
1347                 log_info ("end of script\n");
1348               continue;
1349             }
1350           break; 
1351         }
1352       if (!maxlength)
1353         {
1354           log_error (_("line too long - skipped\n"));
1355           continue;
1356         }
1357       if (memchr (line, 0, n))
1358         log_info (_("line shortened due to embedded Nul character\n"));
1359       if (line[n-1] == '\n')
1360         line[n-1] = 0;
1361       
1362       if (opt.trim_leading_spaces)
1363         {
1364           const char *s = line;
1365           
1366           while (spacep (s))
1367             s++;
1368           if (s != line)
1369             {
1370               for (p=line; *s;)
1371                 *p++ = *s++;
1372               *p = 0;
1373               n = p - line;
1374             }
1375         }
1376
1377       if (loopidx+1 >= 0 && loopstack[loopidx+1].collecting)
1378         {
1379           loopline_t ll;
1380
1381           ll = xmalloc (sizeof *ll + strlen (line));
1382           ll->next = NULL;
1383           strcpy (ll->line, line);
1384           *loopstack[loopidx+1].tail = ll;
1385           loopstack[loopidx+1].tail = &ll->next;
1386
1387           if (!strncmp (line, "/end", 4) && (!line[4]||spacep(line+4)))
1388             loopstack[loopidx+1].nestlevel--;
1389           else if (!strncmp (line, "/while", 6) && (!line[6]||spacep(line+6)))
1390             loopstack[loopidx+1].nestlevel++;
1391           
1392           if (loopstack[loopidx+1].nestlevel)
1393             continue;
1394           /* We reached the corresponding /end.  */
1395           loopstack[loopidx+1].collecting = 0;
1396           loopidx++;
1397         }
1398
1399       if (*line == '/')
1400         {
1401           /* Handle control commands. */
1402           char *cmd = line+1;
1403
1404           for (p=cmd; *p && !spacep (p); p++)
1405             ;
1406           if (*p)
1407             *p++ = 0;
1408           while (spacep (p))
1409             p++;
1410           if (!strcmp (cmd, "let"))
1411             {
1412               assign_variable (p, 0);
1413             }
1414           else if (!strcmp (cmd, "slet"))
1415             {
1416               /* Deprecated - never used in a released version.  */
1417               assign_variable (p, 1);
1418             }
1419           else if (!strcmp (cmd, "showvar"))
1420             {
1421               show_variables ();
1422             }
1423           else if (!strcmp (cmd, "definq"))
1424             {
1425               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1426               if (tmpline)
1427                 {
1428                   add_definq (tmpline, 1, 0);
1429                   xfree (tmpline);
1430                 }
1431               else
1432                 add_definq (p, 1, 0);
1433             }
1434           else if (!strcmp (cmd, "definqfile"))
1435             {
1436               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1437               if (tmpline)
1438                 {
1439                   add_definq (tmpline, 0, 0);
1440                   xfree (tmpline);
1441                 }
1442               else
1443                 add_definq (p, 0, 0);
1444             }
1445           else if (!strcmp (cmd, "definqprog"))
1446             {
1447               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1448               if (tmpline)
1449                 {
1450                   add_definq (tmpline, 0, 1);
1451                   xfree (tmpline);
1452                 }
1453               else
1454                 add_definq (p, 0, 1);
1455             }
1456           else if (!strcmp (cmd, "datafile"))
1457             {
1458               const char *fname;
1459
1460               if (current_datasink)
1461                 {
1462                   if (current_datasink != stdout)
1463                     fclose (current_datasink);
1464                   current_datasink = NULL;
1465                 }
1466               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1467               fname = tmpline? tmpline : p;
1468               if (fname && !strcmp (fname, "-"))
1469                 current_datasink = stdout;
1470               else if (fname && *fname)
1471                 {
1472                   current_datasink = fopen (fname, "wb");
1473                   if (!current_datasink)
1474                     log_error ("can't open `%s': %s\n", 
1475                                fname, strerror (errno));
1476                 }
1477               xfree (tmpline);
1478             }
1479           else if (!strcmp (cmd, "showdef"))
1480             {
1481               show_definq ();
1482             }
1483           else if (!strcmp (cmd, "cleardef"))
1484             {
1485               clear_definq ();
1486             }
1487           else if (!strcmp (cmd, "echo"))
1488             {
1489               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1490               if (tmpline)
1491                 {
1492                   puts (tmpline);
1493                   xfree (tmpline);
1494                 }
1495               else
1496                 puts (p);
1497             }
1498           else if (!strcmp (cmd, "sendfd"))
1499             {
1500               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1501               if (tmpline)
1502                 {
1503                   do_sendfd (ctx, tmpline);
1504                   xfree (tmpline);
1505                 }
1506               else
1507                 do_sendfd (ctx, p);
1508               continue;
1509             }
1510           else if (!strcmp (cmd, "recvfd"))
1511             {
1512               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1513               if (tmpline)
1514                 {
1515                   do_recvfd (ctx, tmpline);
1516                   xfree (tmpline);
1517                 }
1518               else
1519                 do_recvfd (ctx, p);
1520               continue;
1521             }
1522           else if (!strcmp (cmd, "open"))
1523             {
1524               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1525               if (tmpline)
1526                 {
1527                   do_open (tmpline);
1528                   xfree (tmpline);
1529                 }
1530               else
1531                 do_open (p);
1532             }
1533           else if (!strcmp (cmd, "close"))
1534             {
1535               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1536               if (tmpline)
1537                 {
1538                   do_close (tmpline);
1539                   xfree (tmpline);
1540                 }
1541               else
1542                 do_close (p);
1543             }
1544           else if (!strcmp (cmd, "showopen"))
1545             {
1546               do_showopen ();
1547             }
1548           else if (!strcmp (cmd, "serverpid"))
1549             {
1550               do_serverpid (ctx);
1551             }
1552           else if (!strcmp (cmd, "hex"))
1553             opt.hex = 1;
1554           else if (!strcmp (cmd, "nohex"))
1555             opt.hex = 0;
1556           else if (!strcmp (cmd, "decode"))
1557             opt.decode = 1;
1558           else if (!strcmp (cmd, "nodecode"))
1559             opt.decode = 0;
1560           else if (!strcmp (cmd, "subst"))
1561             {
1562               opt.enable_varsubst = 1;
1563               opt.trim_leading_spaces = 1;
1564             }
1565           else if (!strcmp (cmd, "nosubst"))
1566             opt.enable_varsubst = 0;
1567           else if (!strcmp (cmd, "run"))
1568             {
1569               char *p2;
1570
1571               for (p2=p; *p2 && !spacep (p2); p2++)
1572                 ;
1573               if (*p2)
1574                 *p2++ = 0;
1575               while (spacep (p2))
1576                 p++;
1577               if (*p2)
1578                 {
1579                   log_error ("syntax error in run command\n");
1580                   if (script_fp)
1581                     {
1582                       fclose (script_fp);
1583                       script_fp = NULL;
1584                     }
1585                 }
1586               else if (script_fp)
1587                 {
1588                   log_error ("cannot nest run commands - stop\n");
1589                   fclose (script_fp);
1590                   script_fp = NULL;
1591                 }
1592               else if (!(script_fp = fopen (p, "r")))
1593                 {
1594                   log_error ("cannot open run file `%s': %s\n",
1595                              p, strerror (errno));
1596                 }
1597               else if (opt.verbose)
1598                 log_info ("running commands from `%s'\n", p);
1599             }
1600           else if (!strcmp (cmd, "while"))
1601             {
1602               if (loopidx+2 >= (int)DIM(loopstack))
1603                 {
1604                   log_error ("blocks are nested too deep\n");
1605                   /* We should better die or break all loop in this
1606                      case as recovering from this error won't be
1607                      easy.  */
1608                 }
1609               else
1610                 {
1611                   loopstack[loopidx+1].head = NULL;
1612                   loopstack[loopidx+1].tail = &loopstack[loopidx+1].head;
1613                   loopstack[loopidx+1].current = NULL;
1614                   loopstack[loopidx+1].nestlevel = 1;
1615                   loopstack[loopidx+1].oneshot = 0;
1616                   loopstack[loopidx+1].condition = xstrdup (p);
1617                   loopstack[loopidx+1].collecting = 1;
1618                 }
1619             }
1620           else if (!strcmp (cmd, "if"))
1621             {
1622               if (loopidx+2 >= (int)DIM(loopstack))
1623                 {
1624                   log_error ("blocks are nested too deep\n");
1625                 }
1626               else
1627                 {
1628                   /* Note that we need to evaluate the condition right
1629                      away and not just at the end of the block as we
1630                      do with a WHILE. */
1631                   loopstack[loopidx+1].head = NULL;
1632                   loopstack[loopidx+1].tail = &loopstack[loopidx+1].head;
1633                   loopstack[loopidx+1].current = NULL;
1634                   loopstack[loopidx+1].nestlevel = 1;
1635                   loopstack[loopidx+1].oneshot = 1;
1636                   loopstack[loopidx+1].condition = substitute_line_copy (p);
1637                   loopstack[loopidx+1].collecting = 1;
1638                 }
1639             }
1640           else if (!strcmp (cmd, "end"))
1641             {
1642               if (loopidx < 0)
1643                 log_error ("stray /end command encountered - ignored\n");
1644               else
1645                 {
1646                   char *tmpcond;
1647                   const char *value;
1648                   long condition;
1649
1650                   /* Evaluate the condition.  */
1651                   tmpcond = xstrdup (loopstack[loopidx].condition);
1652                   if (loopstack[loopidx].oneshot)
1653                     {
1654                       xfree (loopstack[loopidx].condition);
1655                       loopstack[loopidx].condition = xstrdup ("0");
1656                     }
1657                   tmpline = substitute_line (tmpcond);
1658                   value = tmpline? tmpline : tmpcond;
1659                   condition = strtol (value, NULL, 0);
1660                   xfree (tmpline);
1661                   xfree (tmpcond);
1662
1663                   if (condition)
1664                     {
1665                       /* Run loop.  */
1666                       loopstack[loopidx].current = loopstack[loopidx].head;
1667                     }
1668                   else
1669                     {
1670                       /* Cleanup.  */
1671                       while (loopstack[loopidx].head)
1672                         {
1673                           loopline_t tmp = loopstack[loopidx].head->next;
1674                           xfree (loopstack[loopidx].head);
1675                           loopstack[loopidx].head = tmp;
1676                         }
1677                       loopstack[loopidx].tail = NULL;
1678                       loopstack[loopidx].current = NULL;
1679                       loopstack[loopidx].nestlevel = 0;
1680                       loopstack[loopidx].collecting = 0;
1681                       loopstack[loopidx].oneshot = 0;
1682                       xfree (loopstack[loopidx].condition);
1683                       loopstack[loopidx].condition = NULL;
1684                       loopidx--;
1685                     }
1686                 }
1687             }
1688           else if (!strcmp (cmd, "bye"))
1689             {
1690               break;
1691             }
1692           else if (!strcmp (cmd, "sleep"))
1693             {
1694               gnupg_sleep (1);
1695             }
1696           else if (!strcmp (cmd, "help"))
1697             {
1698               puts (
1699 "Available commands:\n"
1700 "/echo ARGS             Echo ARGS.\n"
1701 "/let  NAME VALUE       Set variable NAME to VALUE.\n"
1702 "/showvar               Show all variables.\n"
1703 "/definq NAME VAR       Use content of VAR for inquiries with NAME.\n"
1704 "/definqfile NAME FILE  Use content of FILE for inquiries with NAME.\n"
1705 "/definqprog NAME PGM   Run PGM for inquiries with NAME.\n"
1706 "/datafile [NAME]       Write all D line content to file NAME.\n"
1707 "/showdef               Print all definitions.\n"
1708 "/cleardef              Delete all definitions.\n"
1709 "/sendfd FILE MODE      Open FILE and pass descriptor to server.\n"
1710 "/recvfd                Receive FD from server and print.\n"
1711 "/open VAR FILE MODE    Open FILE and assign the file descriptor to VAR.\n" 
1712 "/close FD              Close file with descriptor FD.\n"
1713 "/showopen              Show descriptors of all open files.\n"
1714 "/serverpid             Retrieve the pid of the server.\n"
1715 "/[no]hex               Enable hex dumping of received data lines.\n"
1716 "/[no]decode            Enable decoding of received data lines.\n"
1717 "/[no]subst             Enable variable substitution.\n"
1718 "/run FILE              Run commands from FILE.\n"
1719 "/if VAR                Begin conditional block controlled by VAR.\n"
1720 "/while VAR             Begin loop controlled by VAR.\n"
1721 "/end                   End loop or condition\n"
1722 "/bye                   Terminate gpg-connect-agent.\n"
1723 "/help                  Print this help.");
1724             }
1725           else
1726             log_error (_("unknown command `%s'\n"), cmd );
1727       
1728           continue;
1729         }
1730
1731       if (opt.verbose && script_fp)
1732         puts (line);
1733
1734       tmpline = opt.enable_varsubst? substitute_line (line) : NULL;
1735       if (tmpline)
1736         {
1737           rc = assuan_write_line (ctx, tmpline);
1738           xfree (tmpline);
1739         }
1740       else
1741         rc = assuan_write_line (ctx, line);
1742       if (rc)
1743         {
1744           log_info (_("sending line failed: %s\n"), gpg_strerror (rc) );
1745           break;
1746         }
1747       if (*line == '#' || !*line)
1748         continue; /* Don't expect a response for a comment line. */
1749
1750       rc = read_and_print_response (ctx, &cmderr);
1751       if (rc)
1752         log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
1753       if ((rc || cmderr) && script_fp)
1754         {
1755           log_error ("stopping script execution\n");
1756           fclose (script_fp);
1757           script_fp = NULL;
1758         }
1759           
1760
1761       /* FIXME: If the last command was BYE or the server died for
1762          some other reason, we won't notice until we get the next
1763          input command.  Probing the connection with a non-blocking
1764          read could help to notice termination or other problems
1765          early.  */
1766     }
1767
1768   if (opt.verbose)
1769     log_info ("closing connection to agent\n");
1770   
1771   return 0; 
1772 }
1773
1774
1775 /* Handle an Inquire from the server.  Return False if it could not be
1776    handled; in this case the caller shll complete the operation.  LINE
1777    is the complete line as received from the server.  This function
1778    may change the content of LINE. */
1779 static int
1780 handle_inquire (assuan_context_t ctx, char *line)
1781 {
1782   const char *name;
1783   definq_t d;
1784   FILE *fp = NULL;
1785   char buffer[1024];
1786   int rc, n;
1787
1788   /* Skip the command and trailing spaces. */
1789   for (; *line && !spacep (line); line++)
1790     ;
1791   while (spacep (line))
1792     line++;
1793   /* Get the name. */
1794   name = line;
1795   for (; *line && !spacep (line); line++)
1796     ;
1797   if (*line)
1798     *line++ = 0;
1799
1800   /* Now match it against our list.  The second loop is there to
1801      detect the match-all entry. */
1802   for (d=definq_list; d; d = d->next)
1803     if (d->name && !strcmp (d->name, name))
1804         break;
1805   if (!d)
1806     for (d=definq_list; d; d = d->next)
1807       if (!d->name)
1808         break;
1809   if (!d)
1810     {
1811       if (opt.verbose)
1812         log_info ("no handler for inquiry `%s' found\n", name);
1813       return 0;
1814     }
1815
1816   if (d->is_var)
1817     {
1818       char *tmpvalue = get_var_ext (d->file);
1819       rc = assuan_send_data (ctx, tmpvalue, strlen (tmpvalue));
1820       xfree (tmpvalue);
1821       if (rc)
1822         log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
1823     }
1824   else
1825     {
1826       if (d->is_prog)
1827         {
1828           fp = popen (d->file, "r");
1829           if (!fp)
1830             log_error ("error executing `%s': %s\n",
1831                        d->file, strerror (errno));
1832           else if (opt.verbose)
1833             log_error ("handling inquiry `%s' by running `%s'\n", 
1834                        name, d->file);
1835         }
1836       else
1837         {
1838           fp = fopen (d->file, "rb");
1839           if (!fp)
1840             log_error ("error opening `%s': %s\n", d->file, strerror (errno));
1841           else if (opt.verbose)
1842             log_error ("handling inquiry `%s' by returning content of `%s'\n",
1843                        name, d->file);
1844         }
1845       if (!fp)
1846         return 0;
1847
1848       while ( (n = fread (buffer, 1, sizeof buffer, fp)) )
1849         {
1850           rc = assuan_send_data (ctx, buffer, n);
1851           if (rc)
1852             {
1853               log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
1854               break;
1855             }
1856         }
1857       if (ferror (fp))
1858         log_error ("error reading from `%s': %s\n", d->file, strerror (errno));
1859     }
1860
1861   rc = assuan_send_data (ctx, NULL, 0);
1862   if (rc)
1863     log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
1864
1865   if (d->is_var)
1866     ;
1867   else if (d->is_prog)
1868     {
1869       if (pclose (fp))
1870         log_error ("error running `%s': %s\n", d->file, strerror (errno));
1871     }
1872   else
1873     fclose (fp);
1874   return 1;
1875 }
1876
1877
1878 /* Read all response lines from server and print them.  Returns 0 on
1879    success or an assuan error code.  Set R_GOTERR to true if the
1880    command did not returned OK.  */
1881 static int
1882 read_and_print_response (assuan_context_t ctx, int *r_goterr)
1883 {
1884   char *line;
1885   size_t linelen;
1886   assuan_error_t rc;
1887   int i, j;
1888   int need_lf = 0;
1889
1890   *r_goterr = 0;
1891   for (;;)
1892     {
1893       do 
1894         {
1895           rc = assuan_read_line (ctx, &line, &linelen);
1896           if (rc)
1897             return rc;
1898
1899           if (opt.verbose > 1 && *line == '#')
1900             {
1901               fwrite (line, linelen, 1, stdout);
1902               putchar ('\n');
1903             }
1904         }    
1905       while (*line == '#' || !linelen);
1906
1907       if (linelen >= 1
1908           && line[0] == 'D' && line[1] == ' ')
1909         {
1910           if (current_datasink)
1911             {
1912               const unsigned char *s;
1913               int c = 0;
1914
1915               for (j=2, s=(unsigned char*)line+2; j < linelen; j++, s++ )
1916                 {
1917                   if (*s == '%' && j+2 < linelen)
1918                     { 
1919                       s++; j++;
1920                       c = xtoi_2 ( s );
1921                       s++; j++;
1922                     }
1923                   else
1924                     c = *s;
1925                   putc (c, current_datasink);
1926                 }
1927             }
1928           else if (opt.hex)
1929             {
1930               for (i=2; i < linelen; )
1931                 {
1932                   int save_i = i;
1933
1934                   printf ("D[%04X] ", i-2);
1935                   for (j=0; j < 16 ; j++, i++)
1936                     {
1937                       if (j == 8)
1938                         putchar (' ');
1939                       if (i < linelen)
1940                         printf (" %02X", ((unsigned char*)line)[i]);
1941                       else
1942                         fputs ("   ", stdout);
1943                     }
1944                   fputs ("   ", stdout);
1945                   i= save_i;
1946                   for (j=0; j < 16; j++, i++)
1947                     {
1948                       unsigned int c = ((unsigned char*)line)[i];
1949                       if ( i >= linelen )
1950                         putchar (' ');
1951                       else if (isascii (c) && isprint (c) && !iscntrl (c))
1952                         putchar (c);
1953                       else
1954                         putchar ('.');
1955                     }
1956                   putchar ('\n');
1957                 }
1958             }
1959           else if (opt.decode)
1960             {
1961               const unsigned char *s;
1962               int need_d = 1;
1963               int c = 0;
1964
1965               for (j=2, s=(unsigned char*)line+2; j < linelen; j++, s++ )
1966                 {
1967                   if (need_d)
1968                     {
1969                       fputs ("D ", stdout);
1970                       need_d = 0;
1971                     }
1972                   if (*s == '%' && j+2 < linelen)
1973                     { 
1974                       s++; j++;
1975                       c = xtoi_2 ( s );
1976                       s++; j++;
1977                     }
1978                   else
1979                     c = *s;
1980                   if (c == '\n')
1981                     need_d = 1;
1982                   putchar (c);
1983                 }
1984               need_lf = (c != '\n');
1985             }
1986           else
1987             {
1988               fwrite (line, linelen, 1, stdout);
1989               putchar ('\n');
1990             }
1991         }
1992       else 
1993         {
1994           if (need_lf)
1995             {
1996               if (!current_datasink || current_datasink != stdout)
1997                 putchar ('\n');
1998               need_lf = 0;
1999             }
2000
2001           if (linelen >= 1
2002               && line[0] == 'S' 
2003               && (line[1] == '\0' || line[1] == ' '))
2004             {
2005               if (!current_datasink || current_datasink != stdout)
2006                 {
2007                   fwrite (line, linelen, 1, stdout);
2008                   putchar ('\n');
2009                 }
2010             }  
2011           else if (linelen >= 2
2012                    && line[0] == 'O' && line[1] == 'K'
2013                    && (line[2] == '\0' || line[2] == ' '))
2014             {
2015               if (!current_datasink || current_datasink != stdout)
2016                 {
2017                   fwrite (line, linelen, 1, stdout);
2018                   putchar ('\n');
2019                 }
2020               set_int_var ("?", 0);
2021               return 0;
2022             }
2023           else if (linelen >= 3
2024                    && line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
2025                    && (line[3] == '\0' || line[3] == ' '))
2026             {
2027               int errval;
2028
2029               errval = strtol (line+3, NULL, 10);
2030               if (!errval)
2031                 errval = -1;
2032               set_int_var ("?", errval);
2033               if (!current_datasink || current_datasink != stdout)
2034                 {
2035                   fwrite (line, linelen, 1, stdout);
2036                   putchar ('\n');
2037                 }
2038               *r_goterr = 1;
2039               return 0;
2040             }  
2041           else if (linelen >= 7
2042                    && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
2043                    && line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
2044                    && line[6] == 'E' 
2045                    && (line[7] == '\0' || line[7] == ' '))
2046             {
2047               if (!current_datasink || current_datasink != stdout)
2048                 {
2049                   fwrite (line, linelen, 1, stdout);
2050                   putchar ('\n');
2051                 }
2052               if (!handle_inquire (ctx, line))
2053                 assuan_write_line (ctx, "CANCEL");
2054             }
2055           else if (linelen >= 3
2056                    && line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
2057                    && (line[3] == '\0' || line[3] == ' '))
2058             {
2059               if (!current_datasink || current_datasink != stdout)
2060                 {
2061                   fwrite (line, linelen, 1, stdout);
2062                   putchar ('\n');
2063                 }
2064               /* Received from server, thus more responses are expected.  */
2065             }
2066           else
2067             return gpg_error (GPG_ERR_ASS_INV_RESPONSE);
2068         }
2069     }
2070 }
2071
2072
2073
2074
2075 /* Connect to the agent and send the standard options.  */
2076 static assuan_context_t
2077 start_agent (void)
2078 {
2079   int rc = 0;
2080   char *infostr, *p;
2081   assuan_context_t ctx;
2082
2083   infostr = getenv ("GPG_AGENT_INFO");
2084   if (!infostr || !*infostr)
2085     {
2086       char *sockname;
2087
2088       /* Check whether we can connect at the standard socket.  */
2089       sockname = make_filename (opt.homedir, "S.gpg-agent", NULL);
2090       rc = assuan_socket_connect (&ctx, sockname, 0);
2091
2092 #ifdef HAVE_W32_SYSTEM
2093       /* If we failed to connect under Windows, we fire up the agent.  */
2094       if (gpg_err_code (rc) == GPG_ERR_ASS_CONNECT_FAILED)
2095         {
2096           const char *agent_program;
2097           const char *argv[3];
2098           int save_rc = rc;
2099           
2100           if (opt.verbose)
2101             log_info (_("no running gpg-agent - starting one\n"));
2102           agent_program = gnupg_module_name (GNUPG_MODULE_NAME_AGENT);
2103           
2104           argv[0] = "--daemon";
2105           argv[1] = "--use-standard-socket"; 
2106           argv[2] = NULL;  
2107
2108           rc = gnupg_spawn_process_detached (agent_program, argv, NULL);
2109           if (rc)
2110             log_debug ("failed to start agent `%s': %s\n",
2111                        agent_program, gpg_strerror (rc));
2112           else
2113             {
2114               /* Give the agent some time to prepare itself. */
2115               gnupg_sleep (3);
2116               /* Now try again to connect the agent.  */
2117               rc = assuan_socket_connect (&ctx, sockname, 0);
2118             }
2119           if (rc)
2120             rc = save_rc;
2121         }
2122 #endif /*HAVE_W32_SYSTEM*/
2123       xfree (sockname);
2124     }
2125   else
2126     {
2127       int prot;
2128       int pid;
2129
2130       infostr = xstrdup (infostr);
2131       if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
2132         {
2133           log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
2134           xfree (infostr);
2135           exit (1);
2136         }
2137       *p++ = 0;
2138       pid = atoi (p);
2139       while (*p && *p != PATHSEP_C)
2140         p++;
2141       prot = *p? atoi (p+1) : 0;
2142       if (prot != 1)
2143         {
2144           log_error (_("gpg-agent protocol version %d is not supported\n"),
2145                      prot);
2146           xfree (infostr);
2147           exit (1);
2148         }
2149
2150       rc = assuan_socket_connect (&ctx, infostr, pid);
2151       xfree (infostr);
2152     }
2153
2154   if (rc)
2155     {
2156       log_error ("can't connect to the agent: %s\n", gpg_strerror (rc));
2157       exit (1);
2158     }
2159
2160   if (opt.verbose)
2161     log_info ("connection to agent established\n");
2162
2163   rc = assuan_transact (ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
2164   if (rc)
2165     {
2166       log_error (_("error sending %s command: %s\n"), "RESET", 
2167                  gpg_strerror (rc));
2168       exit (1);
2169     }
2170
2171   rc = send_pinentry_environment (ctx, GPG_ERR_SOURCE_DEFAULT,
2172                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2173   if (rc)
2174     {
2175       log_error (_("error sending standard options: %s\n"), gpg_strerror (rc));
2176       exit (1);
2177     }
2178
2179   return ctx;
2180 }