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