Cleaned up unused gpgsm and gpg options.
[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   (void)ctx;
917   (void)line;
918   log_info ("This command has not yet been implemented\n");
919 }
920
921
922 static void
923 do_open (char *line)
924 {
925   FILE *fp;
926   char *varname, *name, *mode, *p;
927   int fd;
928
929 #ifdef HAVE_W32_SYSTEM
930   if (server_pid == (pid_t)(-1))
931     {
932       log_error ("the pid of the server is unknown\n");
933       log_info ("use command \"/serverpid\" first\n");
934       return;
935     }
936 #endif
937
938   /* Get variable name. */
939   varname = line;
940   for (p=varname; *p && !spacep (p); p++)
941     ;
942   if (*p)
943     *p++ = 0;
944   while (spacep (p))
945     p++;
946
947   /* Get file name. */
948   name = p;
949   for (p=name; *p && !spacep (p); p++)
950     ;
951   if (*p)
952     *p++ = 0;
953   while (spacep (p))
954     p++;
955
956   /* Get mode.  */
957   mode = p;
958   if (!*mode)
959     mode = "r";
960   else
961     {
962       for (p=mode; *p && !spacep (p); p++)
963         ;
964       if (*p)
965         *p++ = 0;
966     }
967
968   /* Open and send. */
969   fp = fopen (name, mode);
970   if (!fp)
971     {
972       log_error ("can't open `%s' in \"%s\" mode: %s\n",
973                  name, mode, strerror (errno));
974       return;
975     }
976   fd = fileno (fp);
977   if (fd >= 0 && fd < DIM (open_fd_table))
978     {
979       open_fd_table[fd].inuse = 1;
980 #ifdef HAVE_W32_SYSTEM
981       {
982         HANDLE prochandle, handle, newhandle;
983
984         handle = (void*)_get_osfhandle (fd);
985      
986         prochandle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, server_pid);
987         if (!prochandle)
988           {
989             log_error ("failed to open the server process\n");
990             close (fd);
991             return;
992           }
993
994         if (!DuplicateHandle (GetCurrentProcess(), handle,
995                               prochandle, &newhandle, 0,
996                               TRUE, DUPLICATE_SAME_ACCESS ))
997           {
998             log_error ("failed to duplicate the handle\n");
999             close (fd);
1000             CloseHandle (prochandle);
1001             return;
1002           }
1003         CloseHandle (prochandle);
1004         open_fd_table[fd].handle = newhandle;
1005       }
1006       if (opt.verbose)
1007         log_info ("file `%s' opened in \"%s\" mode, fd=%d  (libc=%d)\n",
1008                    name, mode, (int)open_fd_table[fd].handle, fd);
1009       set_int_var (varname, (int)open_fd_table[fd].handle);
1010 #else  
1011       if (opt.verbose)
1012         log_info ("file `%s' opened in \"%s\" mode, fd=%d\n",
1013                    name, mode, fd);
1014       set_int_var (varname, fd);
1015 #endif
1016     }
1017   else
1018     {
1019       log_error ("can't put fd %d into table\n", fd);
1020       close (fd);
1021     }
1022 }
1023
1024
1025 static void
1026 do_close (char *line)
1027 {
1028   int fd = atoi (line);
1029
1030 #ifdef HAVE_W32_SYSTEM
1031   int i;
1032
1033   for (i=0; i < DIM (open_fd_table); i++)
1034     if ( open_fd_table[i].inuse && open_fd_table[i].handle == (void*)fd)
1035       break;
1036   if (i < DIM (open_fd_table))
1037     fd = i;
1038   else
1039     {
1040       log_error ("given fd (system handle) has not been opened\n");
1041       return;
1042     }
1043 #endif
1044
1045   if (fd < 0 || fd >= DIM (open_fd_table))
1046     {
1047       log_error ("invalid fd\n");
1048       return;
1049     }
1050
1051   if (!open_fd_table[fd].inuse)
1052     {
1053       log_error ("given fd has not been opened\n");
1054       return;
1055     }
1056 #ifdef HAVE_W32_SYSTEM
1057   CloseHandle (open_fd_table[fd].handle); /* Close duped handle.  */
1058 #endif
1059   close (fd);
1060   open_fd_table[fd].inuse = 0;
1061 }
1062
1063
1064 static void
1065 do_showopen (void)
1066 {
1067   int i;
1068
1069   for (i=0; i < DIM (open_fd_table); i++)
1070     if (open_fd_table[i].inuse)
1071       {
1072 #ifdef HAVE_W32_SYSTEM
1073         printf ("%-15d (libc=%d)\n", (int)open_fd_table[i].handle, i);
1074 #else
1075         printf ("%-15d\n", i);
1076 #endif
1077       }
1078 }
1079
1080
1081
1082 static int
1083 getinfo_pid_cb (void *opaque, const void *buffer, size_t length)
1084 {
1085   membuf_t *mb = opaque;
1086   put_membuf (mb, buffer, length);
1087   return 0;
1088 }
1089
1090 /* Get the pid of the server and store it locally.  */
1091 static void
1092 do_serverpid (assuan_context_t ctx)
1093 {
1094   int rc;
1095   membuf_t mb;
1096   char *buffer;
1097   
1098   init_membuf (&mb, 100);
1099   rc = assuan_transact (ctx, "GETINFO pid", getinfo_pid_cb, &mb,
1100                         NULL, NULL, NULL, NULL);
1101   put_membuf (&mb, "", 1);
1102   buffer = get_membuf (&mb, NULL);
1103   if (rc || !buffer)
1104     log_error ("command \"%s\" failed: %s\n", 
1105                "GETINFO pid", gpg_strerror (rc));
1106   else
1107     {
1108       server_pid = (pid_t)strtoul (buffer, NULL, 10);
1109       if (opt.verbose)
1110         log_info ("server's PID is %lu\n", (unsigned long)server_pid);
1111     }
1112   xfree (buffer);
1113 }
1114
1115
1116 /* gpg-connect-agent's entry point. */
1117 int
1118 main (int argc, char **argv)
1119 {
1120   ARGPARSE_ARGS pargs;
1121   int no_more_options = 0;
1122   assuan_context_t ctx;
1123   char *line, *p;
1124   char *tmpline;
1125   size_t linesize;
1126   int rc;
1127   int cmderr;
1128   const char *opt_run = NULL;
1129   FILE *script_fp = NULL;
1130   int use_tty, keep_line;
1131   struct {
1132     int collecting;
1133     loopline_t head;
1134     loopline_t *tail;
1135     loopline_t current;
1136     unsigned int nestlevel; 
1137     int oneshot;
1138     char *condition;
1139   } loopstack[20];
1140   int        loopidx;
1141   char **cmdline_commands = NULL;
1142
1143   gnupg_rl_initialize ();
1144   set_strusage (my_strusage);
1145   log_set_prefix ("gpg-connect-agent", 1);
1146
1147   /* Make sure that our subsystems are ready.  */
1148   init_common_subsystems ();
1149
1150   assuan_set_assuan_err_source (0);
1151
1152   i18n_init();
1153
1154   opt.homedir = default_homedir ();
1155   opt.connect_flags = 1; /* Use extended connect mode.  */
1156
1157   /* Parse the command line. */
1158   pargs.argc  = &argc;
1159   pargs.argv  = &argv;
1160   pargs.flags =  1;  /* Do not remove the args.  */
1161   while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts))
1162     {
1163       switch (pargs.r_opt)
1164         {
1165         case oQuiet:     opt.quiet = 1; break;
1166         case oVerbose:   opt.verbose++; break;
1167         case oNoVerbose: opt.verbose = 0; break;
1168         case oHomedir:   opt.homedir = pargs.r.ret_str; break;
1169         case oHex:       opt.hex = 1; break;
1170         case oDecode:    opt.decode = 1; break;
1171         case oRawSocket: opt.raw_socket = pargs.r.ret_str; break;
1172         case oExec:      opt.exec = 1; break;
1173         case oNoExtConnect: opt.connect_flags &= ~(1); break;
1174         case oRun:       opt_run = pargs.r.ret_str; break;
1175         case oSubst: 
1176           opt.enable_varsubst = 1;
1177           opt.trim_leading_spaces = 1;
1178           break;
1179
1180         default: pargs.err = 2; break;
1181         }
1182     }
1183
1184   if (log_get_errorcount (0))
1185     exit (2);
1186
1187   use_tty = (isatty ( fileno (stdin)) && isatty (fileno (stdout)));
1188
1189   if (opt.exec)
1190     {
1191       if (!argc)
1192         {
1193           log_error (_("option \"%s\" requires a program "
1194                        "and optional arguments\n"), "--exec" );
1195           exit (1);
1196         }
1197     }
1198   else if (argc)
1199     cmdline_commands = argv;
1200
1201   if (opt.exec && opt.raw_socket)
1202     log_info (_("option \"%s\" ignored due to \"%s\"\n"),
1203               "--raw-socket", "--exec");
1204
1205   if (opt_run && !(script_fp = fopen (opt_run, "r")))
1206     {
1207       log_error ("cannot open run file `%s': %s\n",
1208                  opt_run, strerror (errno));
1209       exit (1);
1210     }
1211
1212
1213   if (opt.exec)
1214     {
1215       int no_close[3];
1216
1217       no_close[0] = fileno (stderr);
1218       no_close[1] = log_get_fd ();
1219       no_close[2] = -1;
1220       rc = assuan_pipe_connect_ext (&ctx, *argv, (const char **)argv,
1221                                     no_close, NULL, NULL,
1222                                     opt.connect_flags);
1223       if (rc)
1224         {
1225           log_error ("assuan_pipe_connect_ext failed: %s\n",
1226                      gpg_strerror (rc));
1227           exit (1);
1228         }
1229
1230       if (opt.verbose)
1231         log_info ("server `%s' started\n", *argv);
1232
1233     }
1234   else if (opt.raw_socket)
1235     {
1236       rc = assuan_socket_connect_ext (&ctx, opt.raw_socket, 0,
1237                                       opt.connect_flags);
1238       if (rc)
1239         {
1240           log_error ("can't connect to socket `%s': %s\n",
1241                      opt.raw_socket, gpg_strerror (rc));
1242           exit (1);
1243         }
1244
1245       if (opt.verbose)
1246         log_info ("connection to socket `%s' established\n", opt.raw_socket);
1247     }
1248   else
1249     ctx = start_agent ();
1250
1251   /* See whether there is a line pending from the server (in case
1252      assuan did not run the initial handshaking).  */
1253   if (assuan_pending_line (ctx))
1254     {
1255       rc = read_and_print_response (ctx, &cmderr);
1256       if (rc)
1257         log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
1258     }
1259
1260  
1261   for (loopidx=0; loopidx < DIM (loopstack); loopidx++)
1262     loopstack[loopidx].collecting = 0;
1263   loopidx = -1;
1264   line = NULL;
1265   linesize = 0;
1266   keep_line = 1;
1267   for (;;)
1268     {
1269       int n;
1270       size_t maxlength = 2048;
1271
1272       assert (loopidx < (int)DIM (loopstack));
1273       if (loopidx >= 0 && loopstack[loopidx].current)
1274         {
1275           keep_line = 0;
1276           xfree (line);
1277           line = xstrdup (loopstack[loopidx].current->line);
1278           n = strlen (line);
1279           /* Never go beyond of the final /end.  */
1280           if (loopstack[loopidx].current->next)
1281             loopstack[loopidx].current = loopstack[loopidx].current->next;
1282           else if (!strncmp (line, "/end", 4) && (!line[4]||spacep(line+4)))
1283             ;
1284           else
1285             log_fatal ("/end command vanished\n");
1286         }
1287       else if (cmdline_commands && *cmdline_commands && !script_fp)
1288         {
1289           keep_line = 0;
1290           xfree (line);
1291           line = xstrdup (*cmdline_commands);
1292           cmdline_commands++;
1293           n = strlen (line);
1294           if (n >= maxlength)
1295             maxlength = 0;
1296         }
1297       else if (use_tty && !script_fp)
1298         {
1299           keep_line = 0;
1300           xfree (line);
1301           line = tty_get ("> ");
1302           n = strlen (line);
1303           if (n==1 && *line == CONTROL_D)
1304             n = 0;
1305           if (n >= maxlength)
1306             maxlength = 0;
1307         }
1308       else
1309         {
1310           if (!keep_line)
1311             {
1312               xfree (line);
1313               line = NULL;
1314               linesize = 0;
1315               keep_line = 1;
1316             }
1317           n = read_line (script_fp? script_fp:stdin, 
1318                          &line, &linesize, &maxlength);
1319         }
1320       if (n < 0)
1321         {
1322           log_error (_("error reading input: %s\n"), strerror (errno));
1323           if (script_fp)
1324             {
1325               fclose (script_fp);
1326               script_fp = NULL;
1327               log_error ("stopping script execution\n");
1328               continue;
1329             }
1330           exit (1);
1331         }
1332       if (!n)
1333         {
1334           /* EOF */
1335           if (script_fp)
1336             {
1337               fclose (script_fp);
1338               script_fp = NULL;
1339               if (opt.verbose)
1340                 log_info ("end of script\n");
1341               continue;
1342             }
1343           break; 
1344         }
1345       if (!maxlength)
1346         {
1347           log_error (_("line too long - skipped\n"));
1348           continue;
1349         }
1350       if (memchr (line, 0, n))
1351         log_info (_("line shortened due to embedded Nul character\n"));
1352       if (line[n-1] == '\n')
1353         line[n-1] = 0;
1354       
1355       if (opt.trim_leading_spaces)
1356         {
1357           const char *s = line;
1358           
1359           while (spacep (s))
1360             s++;
1361           if (s != line)
1362             {
1363               for (p=line; *s;)
1364                 *p++ = *s++;
1365               *p = 0;
1366               n = p - line;
1367             }
1368         }
1369
1370       if (loopidx+1 >= 0 && loopstack[loopidx+1].collecting)
1371         {
1372           loopline_t ll;
1373
1374           ll = xmalloc (sizeof *ll + strlen (line));
1375           ll->next = NULL;
1376           strcpy (ll->line, line);
1377           *loopstack[loopidx+1].tail = ll;
1378           loopstack[loopidx+1].tail = &ll->next;
1379
1380           if (!strncmp (line, "/end", 4) && (!line[4]||spacep(line+4)))
1381             loopstack[loopidx+1].nestlevel--;
1382           else if (!strncmp (line, "/while", 6) && (!line[6]||spacep(line+6)))
1383             loopstack[loopidx+1].nestlevel++;
1384           
1385           if (loopstack[loopidx+1].nestlevel)
1386             continue;
1387           /* We reached the corresponding /end.  */
1388           loopstack[loopidx+1].collecting = 0;
1389           loopidx++;
1390         }
1391
1392       if (*line == '/')
1393         {
1394           /* Handle control commands. */
1395           char *cmd = line+1;
1396
1397           for (p=cmd; *p && !spacep (p); p++)
1398             ;
1399           if (*p)
1400             *p++ = 0;
1401           while (spacep (p))
1402             p++;
1403           if (!strcmp (cmd, "let"))
1404             {
1405               assign_variable (p, 0);
1406             }
1407           else if (!strcmp (cmd, "slet"))
1408             {
1409               /* Deprecated - never used in a released version.  */
1410               assign_variable (p, 1);
1411             }
1412           else if (!strcmp (cmd, "showvar"))
1413             {
1414               show_variables ();
1415             }
1416           else if (!strcmp (cmd, "definq"))
1417             {
1418               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1419               if (tmpline)
1420                 {
1421                   add_definq (tmpline, 1, 0);
1422                   xfree (tmpline);
1423                 }
1424               else
1425                 add_definq (p, 1, 0);
1426             }
1427           else if (!strcmp (cmd, "definqfile"))
1428             {
1429               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1430               if (tmpline)
1431                 {
1432                   add_definq (tmpline, 0, 0);
1433                   xfree (tmpline);
1434                 }
1435               else
1436                 add_definq (p, 0, 0);
1437             }
1438           else if (!strcmp (cmd, "definqprog"))
1439             {
1440               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1441               if (tmpline)
1442                 {
1443                   add_definq (tmpline, 0, 1);
1444                   xfree (tmpline);
1445                 }
1446               else
1447                 add_definq (p, 0, 1);
1448             }
1449           else if (!strcmp (cmd, "datafile"))
1450             {
1451               const char *fname;
1452
1453               if (current_datasink)
1454                 {
1455                   if (current_datasink != stdout)
1456                     fclose (current_datasink);
1457                   current_datasink = NULL;
1458                 }
1459               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1460               fname = tmpline? tmpline : p;
1461               if (fname && !strcmp (fname, "-"))
1462                 current_datasink = stdout;
1463               else if (fname && *fname)
1464                 {
1465                   current_datasink = fopen (fname, "wb");
1466                   if (!current_datasink)
1467                     log_error ("can't open `%s': %s\n", 
1468                                fname, strerror (errno));
1469                 }
1470               xfree (tmpline);
1471             }
1472           else if (!strcmp (cmd, "showdef"))
1473             {
1474               show_definq ();
1475             }
1476           else if (!strcmp (cmd, "cleardef"))
1477             {
1478               clear_definq ();
1479             }
1480           else if (!strcmp (cmd, "echo"))
1481             {
1482               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1483               if (tmpline)
1484                 {
1485                   puts (tmpline);
1486                   xfree (tmpline);
1487                 }
1488               else
1489                 puts (p);
1490             }
1491           else if (!strcmp (cmd, "sendfd"))
1492             {
1493               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1494               if (tmpline)
1495                 {
1496                   do_sendfd (ctx, tmpline);
1497                   xfree (tmpline);
1498                 }
1499               else
1500                 do_sendfd (ctx, p);
1501               continue;
1502             }
1503           else if (!strcmp (cmd, "recvfd"))
1504             {
1505               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1506               if (tmpline)
1507                 {
1508                   do_recvfd (ctx, tmpline);
1509                   xfree (tmpline);
1510                 }
1511               else
1512                 do_recvfd (ctx, p);
1513               continue;
1514             }
1515           else if (!strcmp (cmd, "open"))
1516             {
1517               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1518               if (tmpline)
1519                 {
1520                   do_open (tmpline);
1521                   xfree (tmpline);
1522                 }
1523               else
1524                 do_open (p);
1525             }
1526           else if (!strcmp (cmd, "close"))
1527             {
1528               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1529               if (tmpline)
1530                 {
1531                   do_close (tmpline);
1532                   xfree (tmpline);
1533                 }
1534               else
1535                 do_close (p);
1536             }
1537           else if (!strcmp (cmd, "showopen"))
1538             {
1539               do_showopen ();
1540             }
1541           else if (!strcmp (cmd, "serverpid"))
1542             {
1543               do_serverpid (ctx);
1544             }
1545           else if (!strcmp (cmd, "hex"))
1546             opt.hex = 1;
1547           else if (!strcmp (cmd, "nohex"))
1548             opt.hex = 0;
1549           else if (!strcmp (cmd, "decode"))
1550             opt.decode = 1;
1551           else if (!strcmp (cmd, "nodecode"))
1552             opt.decode = 0;
1553           else if (!strcmp (cmd, "subst"))
1554             {
1555               opt.enable_varsubst = 1;
1556               opt.trim_leading_spaces = 1;
1557             }
1558           else if (!strcmp (cmd, "nosubst"))
1559             opt.enable_varsubst = 0;
1560           else if (!strcmp (cmd, "run"))
1561             {
1562               char *p2;
1563
1564               for (p2=p; *p2 && !spacep (p2); p2++)
1565                 ;
1566               if (*p2)
1567                 *p2++ = 0;
1568               while (spacep (p2))
1569                 p++;
1570               if (*p2)
1571                 {
1572                   log_error ("syntax error in run command\n");
1573                   if (script_fp)
1574                     {
1575                       fclose (script_fp);
1576                       script_fp = NULL;
1577                     }
1578                 }
1579               else if (script_fp)
1580                 {
1581                   log_error ("cannot nest run commands - stop\n");
1582                   fclose (script_fp);
1583                   script_fp = NULL;
1584                 }
1585               else if (!(script_fp = fopen (p, "r")))
1586                 {
1587                   log_error ("cannot open run file `%s': %s\n",
1588                              p, strerror (errno));
1589                 }
1590               else if (opt.verbose)
1591                 log_info ("running commands from `%s'\n", p);
1592             }
1593           else if (!strcmp (cmd, "while"))
1594             {
1595               if (loopidx+2 >= (int)DIM(loopstack))
1596                 {
1597                   log_error ("blocks are nested too deep\n");
1598                   /* We should better die or break all loop in this
1599                      case as recovering from this error won't be
1600                      easy.  */
1601                 }
1602               else
1603                 {
1604                   loopstack[loopidx+1].head = NULL;
1605                   loopstack[loopidx+1].tail = &loopstack[loopidx+1].head;
1606                   loopstack[loopidx+1].current = NULL;
1607                   loopstack[loopidx+1].nestlevel = 1;
1608                   loopstack[loopidx+1].oneshot = 0;
1609                   loopstack[loopidx+1].condition = xstrdup (p);
1610                   loopstack[loopidx+1].collecting = 1;
1611                 }
1612             }
1613           else if (!strcmp (cmd, "if"))
1614             {
1615               if (loopidx+2 >= (int)DIM(loopstack))
1616                 {
1617                   log_error ("blocks are nested too deep\n");
1618                 }
1619               else
1620                 {
1621                   /* Note that we need to evaluate the condition right
1622                      away and not just at the end of the block as we
1623                      do with a WHILE. */
1624                   loopstack[loopidx+1].head = NULL;
1625                   loopstack[loopidx+1].tail = &loopstack[loopidx+1].head;
1626                   loopstack[loopidx+1].current = NULL;
1627                   loopstack[loopidx+1].nestlevel = 1;
1628                   loopstack[loopidx+1].oneshot = 1;
1629                   loopstack[loopidx+1].condition = substitute_line_copy (p);
1630                   loopstack[loopidx+1].collecting = 1;
1631                 }
1632             }
1633           else if (!strcmp (cmd, "end"))
1634             {
1635               if (loopidx < 0)
1636                 log_error ("stray /end command encountered - ignored\n");
1637               else
1638                 {
1639                   char *tmpcond;
1640                   const char *value;
1641                   long condition;
1642
1643                   /* Evaluate the condition.  */
1644                   tmpcond = xstrdup (loopstack[loopidx].condition);
1645                   if (loopstack[loopidx].oneshot)
1646                     {
1647                       xfree (loopstack[loopidx].condition);
1648                       loopstack[loopidx].condition = xstrdup ("0");
1649                     }
1650                   tmpline = substitute_line (tmpcond);
1651                   value = tmpline? tmpline : tmpcond;
1652                   condition = strtol (value, NULL, 0);
1653                   xfree (tmpline);
1654                   xfree (tmpcond);
1655
1656                   if (condition)
1657                     {
1658                       /* Run loop.  */
1659                       loopstack[loopidx].current = loopstack[loopidx].head;
1660                     }
1661                   else
1662                     {
1663                       /* Cleanup.  */
1664                       while (loopstack[loopidx].head)
1665                         {
1666                           loopline_t tmp = loopstack[loopidx].head->next;
1667                           xfree (loopstack[loopidx].head);
1668                           loopstack[loopidx].head = tmp;
1669                         }
1670                       loopstack[loopidx].tail = NULL;
1671                       loopstack[loopidx].current = NULL;
1672                       loopstack[loopidx].nestlevel = 0;
1673                       loopstack[loopidx].collecting = 0;
1674                       loopstack[loopidx].oneshot = 0;
1675                       xfree (loopstack[loopidx].condition);
1676                       loopstack[loopidx].condition = NULL;
1677                       loopidx--;
1678                     }
1679                 }
1680             }
1681           else if (!strcmp (cmd, "bye"))
1682             {
1683               break;
1684             }
1685           else if (!strcmp (cmd, "sleep"))
1686             {
1687               gnupg_sleep (1);
1688             }
1689           else if (!strcmp (cmd, "help"))
1690             {
1691               puts (
1692 "Available commands:\n"
1693 "/echo ARGS             Echo ARGS.\n"
1694 "/let  NAME VALUE       Set variable NAME to VALUE.\n"
1695 "/showvar               Show all variables.\n"
1696 "/definq NAME VAR       Use content of VAR for inquiries with NAME.\n"
1697 "/definqfile NAME FILE  Use content of FILE for inquiries with NAME.\n"
1698 "/definqprog NAME PGM   Run PGM for inquiries with NAME.\n"
1699 "/datafile [NAME]       Write all D line content to file NAME.\n"
1700 "/showdef               Print all definitions.\n"
1701 "/cleardef              Delete all definitions.\n"
1702 "/sendfd FILE MODE      Open FILE and pass descriptor to server.\n"
1703 "/recvfd                Receive FD from server and print.\n"
1704 "/open VAR FILE MODE    Open FILE and assign the file descriptor to VAR.\n" 
1705 "/close FD              Close file with descriptor FD.\n"
1706 "/showopen              Show descriptors of all open files.\n"
1707 "/serverpid             Retrieve the pid of the server.\n"
1708 "/[no]hex               Enable hex dumping of received data lines.\n"
1709 "/[no]decode            Enable decoding of received data lines.\n"
1710 "/[no]subst             Enable variable substitution.\n"
1711 "/run FILE              Run commands from FILE.\n"
1712 "/if VAR                Begin conditional block controlled by VAR.\n"
1713 "/while VAR             Begin loop controlled by VAR.\n"
1714 "/end                   End loop or condition\n"
1715 "/bye                   Terminate gpg-connect-agent.\n"
1716 "/help                  Print this help.");
1717             }
1718           else
1719             log_error (_("unknown command `%s'\n"), cmd );
1720       
1721           continue;
1722         }
1723
1724       if (opt.verbose && script_fp)
1725         puts (line);
1726
1727       tmpline = opt.enable_varsubst? substitute_line (line) : NULL;
1728       if (tmpline)
1729         {
1730           rc = assuan_write_line (ctx, tmpline);
1731           xfree (tmpline);
1732         }
1733       else
1734         rc = assuan_write_line (ctx, line);
1735       if (rc)
1736         {
1737           log_info (_("sending line failed: %s\n"), gpg_strerror (rc) );
1738           break;
1739         }
1740       if (*line == '#' || !*line)
1741         continue; /* Don't expect a response for a comment line. */
1742
1743       rc = read_and_print_response (ctx, &cmderr);
1744       if (rc)
1745         log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
1746       if ((rc || cmderr) && script_fp)
1747         {
1748           log_error ("stopping script execution\n");
1749           fclose (script_fp);
1750           script_fp = NULL;
1751         }
1752           
1753
1754       /* FIXME: If the last command was BYE or the server died for
1755          some other reason, we won't notice until we get the next
1756          input command.  Probing the connection with a non-blocking
1757          read could help to notice termination or other problems
1758          early.  */
1759     }
1760
1761   if (opt.verbose)
1762     log_info ("closing connection to agent\n");
1763   
1764   return 0; 
1765 }
1766
1767
1768 /* Handle an Inquire from the server.  Return False if it could not be
1769    handled; in this case the caller shll complete the operation.  LINE
1770    is the complete line as received from the server.  This function
1771    may change the content of LINE. */
1772 static int
1773 handle_inquire (assuan_context_t ctx, char *line)
1774 {
1775   const char *name;
1776   definq_t d;
1777   FILE *fp = NULL;
1778   char buffer[1024];
1779   int rc, n;
1780
1781   /* Skip the command and trailing spaces. */
1782   for (; *line && !spacep (line); line++)
1783     ;
1784   while (spacep (line))
1785     line++;
1786   /* Get the name. */
1787   name = line;
1788   for (; *line && !spacep (line); line++)
1789     ;
1790   if (*line)
1791     *line++ = 0;
1792
1793   /* Now match it against our list.  The second loop is there to
1794      detect the match-all entry. */
1795   for (d=definq_list; d; d = d->next)
1796     if (d->name && !strcmp (d->name, name))
1797         break;
1798   if (!d)
1799     for (d=definq_list; d; d = d->next)
1800       if (!d->name)
1801         break;
1802   if (!d)
1803     {
1804       if (opt.verbose)
1805         log_info ("no handler for inquiry `%s' found\n", name);
1806       return 0;
1807     }
1808
1809   if (d->is_var)
1810     {
1811       char *tmpvalue = get_var_ext (d->file);
1812       rc = assuan_send_data (ctx, tmpvalue, strlen (tmpvalue));
1813       xfree (tmpvalue);
1814       if (rc)
1815         log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
1816     }
1817   else
1818     {
1819       if (d->is_prog)
1820         {
1821           fp = popen (d->file, "r");
1822           if (!fp)
1823             log_error ("error executing `%s': %s\n",
1824                        d->file, strerror (errno));
1825           else if (opt.verbose)
1826             log_error ("handling inquiry `%s' by running `%s'\n", 
1827                        name, d->file);
1828         }
1829       else
1830         {
1831           fp = fopen (d->file, "rb");
1832           if (!fp)
1833             log_error ("error opening `%s': %s\n", d->file, strerror (errno));
1834           else if (opt.verbose)
1835             log_error ("handling inquiry `%s' by returning content of `%s'\n",
1836                        name, d->file);
1837         }
1838       if (!fp)
1839         return 0;
1840
1841       while ( (n = fread (buffer, 1, sizeof buffer, fp)) )
1842         {
1843           rc = assuan_send_data (ctx, buffer, n);
1844           if (rc)
1845             {
1846               log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
1847               break;
1848             }
1849         }
1850       if (ferror (fp))
1851         log_error ("error reading from `%s': %s\n", d->file, strerror (errno));
1852     }
1853
1854   rc = assuan_send_data (ctx, NULL, 0);
1855   if (rc)
1856     log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
1857
1858   if (d->is_var)
1859     ;
1860   else if (d->is_prog)
1861     {
1862       if (pclose (fp))
1863         log_error ("error running `%s': %s\n", d->file, strerror (errno));
1864     }
1865   else
1866     fclose (fp);
1867   return 1;
1868 }
1869
1870
1871 /* Read all response lines from server and print them.  Returns 0 on
1872    success or an assuan error code.  Set R_GOTERR to true if the
1873    command did not returned OK.  */
1874 static int
1875 read_and_print_response (assuan_context_t ctx, int *r_goterr)
1876 {
1877   char *line;
1878   size_t linelen;
1879   assuan_error_t rc;
1880   int i, j;
1881   int need_lf = 0;
1882
1883   *r_goterr = 0;
1884   for (;;)
1885     {
1886       do 
1887         {
1888           rc = assuan_read_line (ctx, &line, &linelen);
1889           if (rc)
1890             return rc;
1891
1892           if (opt.verbose > 1 && *line == '#')
1893             {
1894               fwrite (line, linelen, 1, stdout);
1895               putchar ('\n');
1896             }
1897         }    
1898       while (*line == '#' || !linelen);
1899
1900       if (linelen >= 1
1901           && line[0] == 'D' && line[1] == ' ')
1902         {
1903           if (current_datasink)
1904             {
1905               const unsigned char *s;
1906               int c = 0;
1907
1908               for (j=2, s=(unsigned char*)line+2; j < linelen; j++, s++ )
1909                 {
1910                   if (*s == '%' && j+2 < linelen)
1911                     { 
1912                       s++; j++;
1913                       c = xtoi_2 ( s );
1914                       s++; j++;
1915                     }
1916                   else
1917                     c = *s;
1918                   putc (c, current_datasink);
1919                 }
1920             }
1921           else if (opt.hex)
1922             {
1923               for (i=2; i < linelen; )
1924                 {
1925                   int save_i = i;
1926
1927                   printf ("D[%04X] ", i-2);
1928                   for (j=0; j < 16 ; j++, i++)
1929                     {
1930                       if (j == 8)
1931                         putchar (' ');
1932                       if (i < linelen)
1933                         printf (" %02X", ((unsigned char*)line)[i]);
1934                       else
1935                         fputs ("   ", stdout);
1936                     }
1937                   fputs ("   ", stdout);
1938                   i= save_i;
1939                   for (j=0; j < 16; j++, i++)
1940                     {
1941                       unsigned int c = ((unsigned char*)line)[i];
1942                       if ( i >= linelen )
1943                         putchar (' ');
1944                       else if (isascii (c) && isprint (c) && !iscntrl (c))
1945                         putchar (c);
1946                       else
1947                         putchar ('.');
1948                     }
1949                   putchar ('\n');
1950                 }
1951             }
1952           else if (opt.decode)
1953             {
1954               const unsigned char *s;
1955               int need_d = 1;
1956               int c = 0;
1957
1958               for (j=2, s=(unsigned char*)line+2; j < linelen; j++, s++ )
1959                 {
1960                   if (need_d)
1961                     {
1962                       fputs ("D ", stdout);
1963                       need_d = 0;
1964                     }
1965                   if (*s == '%' && j+2 < linelen)
1966                     { 
1967                       s++; j++;
1968                       c = xtoi_2 ( s );
1969                       s++; j++;
1970                     }
1971                   else
1972                     c = *s;
1973                   if (c == '\n')
1974                     need_d = 1;
1975                   putchar (c);
1976                 }
1977               need_lf = (c != '\n');
1978             }
1979           else
1980             {
1981               fwrite (line, linelen, 1, stdout);
1982               putchar ('\n');
1983             }
1984         }
1985       else 
1986         {
1987           if (need_lf)
1988             {
1989               if (!current_datasink || current_datasink != stdout)
1990                 putchar ('\n');
1991               need_lf = 0;
1992             }
1993
1994           if (linelen >= 1
1995               && line[0] == 'S' 
1996               && (line[1] == '\0' || line[1] == ' '))
1997             {
1998               if (!current_datasink || current_datasink != stdout)
1999                 {
2000                   fwrite (line, linelen, 1, stdout);
2001                   putchar ('\n');
2002                 }
2003             }  
2004           else if (linelen >= 2
2005                    && line[0] == 'O' && line[1] == 'K'
2006                    && (line[2] == '\0' || line[2] == ' '))
2007             {
2008               if (!current_datasink || current_datasink != stdout)
2009                 {
2010                   fwrite (line, linelen, 1, stdout);
2011                   putchar ('\n');
2012                 }
2013               set_int_var ("?", 0);
2014               return 0;
2015             }
2016           else if (linelen >= 3
2017                    && line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
2018                    && (line[3] == '\0' || line[3] == ' '))
2019             {
2020               int errval;
2021
2022               errval = strtol (line+3, NULL, 10);
2023               if (!errval)
2024                 errval = -1;
2025               set_int_var ("?", errval);
2026               if (!current_datasink || current_datasink != stdout)
2027                 {
2028                   fwrite (line, linelen, 1, stdout);
2029                   putchar ('\n');
2030                 }
2031               *r_goterr = 1;
2032               return 0;
2033             }  
2034           else if (linelen >= 7
2035                    && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
2036                    && line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
2037                    && line[6] == 'E' 
2038                    && (line[7] == '\0' || line[7] == ' '))
2039             {
2040               if (!current_datasink || current_datasink != stdout)
2041                 {
2042                   fwrite (line, linelen, 1, stdout);
2043                   putchar ('\n');
2044                 }
2045               if (!handle_inquire (ctx, line))
2046                 assuan_write_line (ctx, "CANCEL");
2047             }
2048           else if (linelen >= 3
2049                    && line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
2050                    && (line[3] == '\0' || line[3] == ' '))
2051             {
2052               if (!current_datasink || current_datasink != stdout)
2053                 {
2054                   fwrite (line, linelen, 1, stdout);
2055                   putchar ('\n');
2056                 }
2057               /* Received from server, thus more responses are expected.  */
2058             }
2059           else
2060             return gpg_error (GPG_ERR_ASS_INV_RESPONSE);
2061         }
2062     }
2063 }
2064
2065
2066
2067
2068 /* Connect to the agent and send the standard options.  */
2069 static assuan_context_t
2070 start_agent (void)
2071 {
2072   int rc = 0;
2073   char *infostr, *p;
2074   assuan_context_t ctx;
2075
2076   infostr = getenv ("GPG_AGENT_INFO");
2077   if (!infostr || !*infostr)
2078     {
2079       char *sockname;
2080
2081       /* Check whether we can connect at the standard socket.  */
2082       sockname = make_filename (opt.homedir, "S.gpg-agent", NULL);
2083       rc = assuan_socket_connect (&ctx, sockname, 0);
2084       xfree (sockname);
2085     }
2086   else
2087     {
2088       int prot;
2089       int pid;
2090
2091       infostr = xstrdup (infostr);
2092       if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
2093         {
2094           log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
2095           xfree (infostr);
2096           exit (1);
2097         }
2098       *p++ = 0;
2099       pid = atoi (p);
2100       while (*p && *p != PATHSEP_C)
2101         p++;
2102       prot = *p? atoi (p+1) : 0;
2103       if (prot != 1)
2104         {
2105           log_error (_("gpg-agent protocol version %d is not supported\n"),
2106                      prot);
2107           xfree (infostr);
2108           exit (1);
2109         }
2110
2111       rc = assuan_socket_connect (&ctx, infostr, pid);
2112       xfree (infostr);
2113     }
2114
2115   if (rc)
2116     {
2117       log_error ("can't connect to the agent: %s\n", gpg_strerror (rc));
2118       exit (1);
2119     }
2120
2121   if (opt.verbose)
2122     log_info ("connection to agent established\n");
2123
2124   rc = assuan_transact (ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
2125   if (rc)
2126     {
2127       log_error (_("error sending %s command: %s\n"), "RESET", 
2128                  gpg_strerror (rc));
2129       exit (1);
2130     }
2131
2132   rc = send_pinentry_environment (ctx, GPG_ERR_SOURCE_DEFAULT,
2133                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2134   if (rc)
2135     {
2136       log_error (_("error sending standard options: %s\n"), gpg_strerror (rc));
2137       exit (1);
2138     }
2139
2140   return ctx;
2141 }