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