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