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