c76f0e219baf0cb64b666c3e4efd2ee9cc40b287
[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
1138   gnupg_rl_initialize ();
1139   set_strusage (my_strusage);
1140   log_set_prefix ("gpg-connect-agent", 1);
1141
1142   /* Make sure that our subsystems are ready.  */
1143   init_common_subsystems ();
1144
1145   assuan_set_assuan_err_source (0);
1146
1147   i18n_init();
1148
1149   opt.homedir = default_homedir ();
1150   opt.connect_flags = 1; /* Use extended connect mode.  */
1151
1152   /* Parse the command line. */
1153   pargs.argc  = &argc;
1154   pargs.argv  = &argv;
1155   pargs.flags =  1;  /* Do not remove the args.  */
1156   while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts))
1157     {
1158       switch (pargs.r_opt)
1159         {
1160         case oQuiet:     opt.quiet = 1; break;
1161         case oVerbose:   opt.verbose++; break;
1162         case oNoVerbose: opt.verbose = 0; break;
1163         case oHomedir:   opt.homedir = pargs.r.ret_str; break;
1164         case oHex:       opt.hex = 1; break;
1165         case oDecode:    opt.decode = 1; break;
1166         case oRawSocket: opt.raw_socket = pargs.r.ret_str; break;
1167         case oExec:      opt.exec = 1; break;
1168         case oNoExtConnect: opt.connect_flags &= ~(1); break;
1169         case oRun:       opt_run = pargs.r.ret_str; break;
1170         case oSubst: 
1171           opt.enable_varsubst = 1;
1172           opt.trim_leading_spaces = 1;
1173           break;
1174
1175         default: pargs.err = 2; break;
1176         }
1177     }
1178
1179   if (log_get_errorcount (0))
1180     exit (2);
1181
1182   use_tty = (isatty ( fileno (stdin)) && isatty (fileno (stdout)));
1183
1184   if (opt.exec)
1185     {
1186       if (!argc)
1187         {
1188           log_error (_("option \"%s\" requires a program "
1189                        "and optional arguments\n"), "--exec" );
1190           exit (1);
1191         }
1192     }
1193   else if (argc)
1194     usage (1);
1195
1196   if (opt.exec && opt.raw_socket)
1197     log_info (_("option \"%s\" ignored due to \"%s\"\n"),
1198               "--raw-socket", "--exec");
1199
1200   if (opt_run && !(script_fp = fopen (opt_run, "r")))
1201     {
1202       log_error ("cannot open run file `%s': %s\n",
1203                  opt_run, strerror (errno));
1204       exit (1);
1205     }
1206
1207
1208   if (opt.exec)
1209     {
1210       int no_close[3];
1211
1212       no_close[0] = fileno (stderr);
1213       no_close[1] = log_get_fd ();
1214       no_close[2] = -1;
1215       rc = assuan_pipe_connect_ext (&ctx, *argv, (const char **)argv,
1216                                     no_close, NULL, NULL,
1217                                     opt.connect_flags);
1218       if (rc)
1219         {
1220           log_error ("assuan_pipe_connect_ext failed: %s\n",
1221                      gpg_strerror (rc));
1222           exit (1);
1223         }
1224
1225       if (opt.verbose)
1226         log_info ("server `%s' started\n", *argv);
1227
1228     }
1229   else if (opt.raw_socket)
1230     {
1231       rc = assuan_socket_connect_ext (&ctx, opt.raw_socket, 0,
1232                                       opt.connect_flags);
1233       if (rc)
1234         {
1235           log_error ("can't connect to socket `%s': %s\n",
1236                      opt.raw_socket, gpg_strerror (rc));
1237           exit (1);
1238         }
1239
1240       if (opt.verbose)
1241         log_info ("connection to socket `%s' established\n", opt.raw_socket);
1242     }
1243   else
1244     ctx = start_agent ();
1245
1246   /* See whether there is a line pending from the server (in case
1247      assuan did not run the initial handshaking).  */
1248   if (assuan_pending_line (ctx))
1249     {
1250       rc = read_and_print_response (ctx, &cmderr);
1251       if (rc)
1252         log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
1253     }
1254
1255  
1256   for (loopidx=0; loopidx < DIM (loopstack); loopidx++)
1257     loopstack[loopidx].collecting = 0;
1258   loopidx = -1;
1259   line = NULL;
1260   linesize = 0;
1261   keep_line = 1;
1262   for (;;)
1263     {
1264       int n;
1265       size_t maxlength = 2048;
1266
1267       assert (loopidx < (int)DIM (loopstack));
1268       if (loopidx >= 0 && loopstack[loopidx].current)
1269         {
1270           keep_line = 0;
1271           xfree (line);
1272           line = xstrdup (loopstack[loopidx].current->line);
1273           n = strlen (line);
1274           /* Never go beyond of the final /end.  */
1275           if (loopstack[loopidx].current->next)
1276             loopstack[loopidx].current = loopstack[loopidx].current->next;
1277           else if (!strncmp (line, "/end", 4) && (!line[4]||spacep(line+4)))
1278             ;
1279           else
1280             log_fatal ("/end command vanished\n");
1281         }
1282       else if (use_tty && !script_fp)
1283         {
1284           keep_line = 0;
1285           xfree (line);
1286           line = tty_get ("> ");
1287           n = strlen (line);
1288           if (n==1 && *line == CONTROL_D)
1289             n = 0;
1290           if (n >= maxlength)
1291             maxlength = 0;
1292         }
1293       else
1294         {
1295           if (!keep_line)
1296             {
1297               xfree (line);
1298               line = NULL;
1299               linesize = 0;
1300               keep_line = 1;
1301             }
1302           n = read_line (script_fp? script_fp:stdin, 
1303                          &line, &linesize, &maxlength);
1304         }
1305       if (n < 0)
1306         {
1307           log_error (_("error reading input: %s\n"), strerror (errno));
1308           if (script_fp)
1309             {
1310               fclose (script_fp);
1311               script_fp = NULL;
1312               log_error ("stopping script execution\n");
1313               continue;
1314             }
1315           exit (1);
1316         }
1317       if (!n)
1318         {
1319           /* EOF */
1320           if (script_fp)
1321             {
1322               fclose (script_fp);
1323               script_fp = NULL;
1324               if (opt.verbose)
1325                 log_info ("end of script\n");
1326               continue;
1327             }
1328           break; 
1329         }
1330       if (!maxlength)
1331         {
1332           log_error (_("line too long - skipped\n"));
1333           continue;
1334         }
1335       if (memchr (line, 0, n))
1336         log_info (_("line shortened due to embedded Nul character\n"));
1337       if (line[n-1] == '\n')
1338         line[n-1] = 0;
1339       
1340       if (opt.trim_leading_spaces)
1341         {
1342           const char *s = line;
1343           
1344           while (spacep (s))
1345             s++;
1346           if (s != line)
1347             {
1348               for (p=line; *s;)
1349                 *p++ = *s++;
1350               *p = 0;
1351               n = p - line;
1352             }
1353         }
1354
1355       if (loopidx+1 >= 0 && loopstack[loopidx+1].collecting)
1356         {
1357           loopline_t ll;
1358
1359           ll = xmalloc (sizeof *ll + strlen (line));
1360           ll->next = NULL;
1361           strcpy (ll->line, line);
1362           *loopstack[loopidx+1].tail = ll;
1363           loopstack[loopidx+1].tail = &ll->next;
1364
1365           if (!strncmp (line, "/end", 4) && (!line[4]||spacep(line+4)))
1366             loopstack[loopidx+1].nestlevel--;
1367           else if (!strncmp (line, "/while", 6) && (!line[6]||spacep(line+6)))
1368             loopstack[loopidx+1].nestlevel++;
1369           
1370           if (loopstack[loopidx+1].nestlevel)
1371             continue;
1372           /* We reached the corresponding /end.  */
1373           loopstack[loopidx+1].collecting = 0;
1374           loopidx++;
1375         }
1376
1377       if (*line == '/')
1378         {
1379           /* Handle control commands. */
1380           char *cmd = line+1;
1381
1382           for (p=cmd; *p && !spacep (p); p++)
1383             ;
1384           if (*p)
1385             *p++ = 0;
1386           while (spacep (p))
1387             p++;
1388           if (!strcmp (cmd, "let"))
1389             {
1390               assign_variable (p, 0);
1391             }
1392           else if (!strcmp (cmd, "slet"))
1393             {
1394               /* Deprecated - never used in a released version.  */
1395               assign_variable (p, 1);
1396             }
1397           else if (!strcmp (cmd, "showvar"))
1398             {
1399               show_variables ();
1400             }
1401           else if (!strcmp (cmd, "definq"))
1402             {
1403               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1404               if (tmpline)
1405                 {
1406                   add_definq (tmpline, 1, 0);
1407                   xfree (tmpline);
1408                 }
1409               else
1410                 add_definq (p, 1, 0);
1411             }
1412           else if (!strcmp (cmd, "definqfile"))
1413             {
1414               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1415               if (tmpline)
1416                 {
1417                   add_definq (tmpline, 0, 0);
1418                   xfree (tmpline);
1419                 }
1420               else
1421                 add_definq (p, 0, 0);
1422             }
1423           else if (!strcmp (cmd, "definqprog"))
1424             {
1425               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1426               if (tmpline)
1427                 {
1428                   add_definq (tmpline, 0, 1);
1429                   xfree (tmpline);
1430                 }
1431               else
1432                 add_definq (p, 0, 1);
1433             }
1434           else if (!strcmp (cmd, "showdef"))
1435             {
1436               show_definq ();
1437             }
1438           else if (!strcmp (cmd, "cleardef"))
1439             {
1440               clear_definq ();
1441             }
1442           else if (!strcmp (cmd, "echo"))
1443             {
1444               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1445               if (tmpline)
1446                 {
1447                   puts (tmpline);
1448                   xfree (tmpline);
1449                 }
1450               else
1451                 puts (p);
1452             }
1453           else if (!strcmp (cmd, "sendfd"))
1454             {
1455               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1456               if (tmpline)
1457                 {
1458                   do_sendfd (ctx, tmpline);
1459                   xfree (tmpline);
1460                 }
1461               else
1462                 do_sendfd (ctx, p);
1463               continue;
1464             }
1465           else if (!strcmp (cmd, "recvfd"))
1466             {
1467               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1468               if (tmpline)
1469                 {
1470                   do_recvfd (ctx, tmpline);
1471                   xfree (tmpline);
1472                 }
1473               else
1474                 do_recvfd (ctx, p);
1475               continue;
1476             }
1477           else if (!strcmp (cmd, "open"))
1478             {
1479               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1480               if (tmpline)
1481                 {
1482                   do_open (tmpline);
1483                   xfree (tmpline);
1484                 }
1485               else
1486                 do_open (p);
1487             }
1488           else if (!strcmp (cmd, "close"))
1489             {
1490               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
1491               if (tmpline)
1492                 {
1493                   do_close (tmpline);
1494                   xfree (tmpline);
1495                 }
1496               else
1497                 do_close (p);
1498             }
1499           else if (!strcmp (cmd, "showopen"))
1500             {
1501               do_showopen ();
1502             }
1503           else if (!strcmp (cmd, "serverpid"))
1504             {
1505               do_serverpid (ctx);
1506             }
1507           else if (!strcmp (cmd, "hex"))
1508             opt.hex = 1;
1509           else if (!strcmp (cmd, "nohex"))
1510             opt.hex = 0;
1511           else if (!strcmp (cmd, "decode"))
1512             opt.decode = 1;
1513           else if (!strcmp (cmd, "nodecode"))
1514             opt.decode = 0;
1515           else if (!strcmp (cmd, "subst"))
1516             {
1517               opt.enable_varsubst = 1;
1518               opt.trim_leading_spaces = 1;
1519             }
1520           else if (!strcmp (cmd, "nosubst"))
1521             opt.enable_varsubst = 0;
1522           else if (!strcmp (cmd, "run"))
1523             {
1524               char *p2;
1525
1526               for (p2=p; *p2 && !spacep (p2); p2++)
1527                 ;
1528               if (*p2)
1529                 *p2++ = 0;
1530               while (spacep (p2))
1531                 p++;
1532               if (*p2)
1533                 {
1534                   log_error ("syntax error in run command\n");
1535                   if (script_fp)
1536                     {
1537                       fclose (script_fp);
1538                       script_fp = NULL;
1539                     }
1540                 }
1541               else if (script_fp)
1542                 {
1543                   log_error ("cannot nest run commands - stop\n");
1544                   fclose (script_fp);
1545                   script_fp = NULL;
1546                 }
1547               else if (!(script_fp = fopen (p, "r")))
1548                 {
1549                   log_error ("cannot open run file `%s': %s\n",
1550                              p, strerror (errno));
1551                 }
1552               else if (opt.verbose)
1553                 log_info ("running commands from `%s'\n", p);
1554             }
1555           else if (!strcmp (cmd, "while"))
1556             {
1557               if (loopidx+2 >= (int)DIM(loopstack))
1558                 {
1559                   log_error ("blocks are nested too deep\n");
1560                   /* We should better die or break all loop in this
1561                      case as recovering from this error won't be
1562                      easy.  */
1563                 }
1564               else
1565                 {
1566                   loopstack[loopidx+1].head = NULL;
1567                   loopstack[loopidx+1].tail = &loopstack[loopidx+1].head;
1568                   loopstack[loopidx+1].current = NULL;
1569                   loopstack[loopidx+1].nestlevel = 1;
1570                   loopstack[loopidx+1].oneshot = 0;
1571                   loopstack[loopidx+1].condition = xstrdup (p);
1572                   loopstack[loopidx+1].collecting = 1;
1573                 }
1574             }
1575           else if (!strcmp (cmd, "if"))
1576             {
1577               if (loopidx+2 >= (int)DIM(loopstack))
1578                 {
1579                   log_error ("blocks are nested too deep\n");
1580                 }
1581               else
1582                 {
1583                   /* Note that we need to evaluate the condition right
1584                      away and not just at the end of the block as we
1585                      do with a WHILE. */
1586                   loopstack[loopidx+1].head = NULL;
1587                   loopstack[loopidx+1].tail = &loopstack[loopidx+1].head;
1588                   loopstack[loopidx+1].current = NULL;
1589                   loopstack[loopidx+1].nestlevel = 1;
1590                   loopstack[loopidx+1].oneshot = 1;
1591                   loopstack[loopidx+1].condition = substitute_line_copy (p);
1592                   loopstack[loopidx+1].collecting = 1;
1593                 }
1594             }
1595           else if (!strcmp (cmd, "end"))
1596             {
1597               if (loopidx < 0)
1598                 log_error ("stray /end command encountered - ignored\n");
1599               else
1600                 {
1601                   char *tmpcond;
1602                   const char *value;
1603                   long condition;
1604
1605                   /* Evaluate the condition.  */
1606                   tmpcond = xstrdup (loopstack[loopidx].condition);
1607                   if (loopstack[loopidx].oneshot)
1608                     {
1609                       xfree (loopstack[loopidx].condition);
1610                       loopstack[loopidx].condition = xstrdup ("0");
1611                     }
1612                   tmpline = substitute_line (tmpcond);
1613                   value = tmpline? tmpline : tmpcond;
1614                   condition = strtol (value, NULL, 0);
1615                   xfree (tmpline);
1616                   xfree (tmpcond);
1617
1618                   if (condition)
1619                     {
1620                       /* Run loop.  */
1621                       loopstack[loopidx].current = loopstack[loopidx].head;
1622                     }
1623                   else
1624                     {
1625                       /* Cleanup.  */
1626                       while (loopstack[loopidx].head)
1627                         {
1628                           loopline_t tmp = loopstack[loopidx].head->next;
1629                           xfree (loopstack[loopidx].head);
1630                           loopstack[loopidx].head = tmp;
1631                         }
1632                       loopstack[loopidx].tail = NULL;
1633                       loopstack[loopidx].current = NULL;
1634                       loopstack[loopidx].nestlevel = 0;
1635                       loopstack[loopidx].collecting = 0;
1636                       loopstack[loopidx].oneshot = 0;
1637                       xfree (loopstack[loopidx].condition);
1638                       loopstack[loopidx].condition = NULL;
1639                       loopidx--;
1640                     }
1641                 }
1642             }
1643           else if (!strcmp (cmd, "bye"))
1644             {
1645               break;
1646             }
1647           else if (!strcmp (cmd, "sleep"))
1648             {
1649               gnupg_sleep (1);
1650             }
1651           else if (!strcmp (cmd, "help"))
1652             {
1653               puts (
1654 "Available commands:\n"
1655 "/echo ARGS             Echo ARGS.\n"
1656 "/let  NAME VALUE       Set variable NAME to VALUE.\n"
1657 "/showvar               Show all variables.\n"
1658 "/definq NAME VAR       Use content of VAR for inquiries with NAME.\n"
1659 "/definqfile NAME FILE  Use content of FILE for inquiries with NAME.\n"
1660 "/definqprog NAME PGM   Run PGM for inquiries with NAME.\n"
1661 "/showdef               Print all definitions.\n"
1662 "/cleardef              Delete all definitions.\n"
1663 "/sendfd FILE MODE      Open FILE and pass descriptor to server.\n"
1664 "/recvfd                Receive FD from server and print.\n"
1665 "/open VAR FILE MODE    Open FILE and assign the file descriptor to VAR.\n" 
1666 "/close FD              Close file with descriptor FD.\n"
1667 "/showopen              Show descriptors of all open files.\n"
1668 "/serverpid             Retrieve the pid of the server.\n"
1669 "/[no]hex               Enable hex dumping of received data lines.\n"
1670 "/[no]decode            Enable decoding of received data lines.\n"
1671 "/[no]subst             Enable varibale substitution.\n"
1672 "/run FILE              Run commands from FILE.\n"
1673 "/if VAR                Begin conditional block controlled by VAR.\n"
1674 "/while VAR             Begin loop controlled by VAR.\n"
1675 "/end                   End loop or condition\n"
1676 "/bye                   Terminate gpg-connect-agent.\n"
1677 "/help                  Print this help.");
1678             }
1679           else
1680             log_error (_("unknown command `%s'\n"), cmd );
1681       
1682           continue;
1683         }
1684
1685       if (opt.verbose && script_fp)
1686         puts (line);
1687
1688       tmpline = opt.enable_varsubst? substitute_line (line) : NULL;
1689       if (tmpline)
1690         {
1691           rc = assuan_write_line (ctx, tmpline);
1692           xfree (tmpline);
1693         }
1694       else
1695         rc = assuan_write_line (ctx, line);
1696       if (rc)
1697         {
1698           log_info (_("sending line failed: %s\n"), gpg_strerror (rc) );
1699           break;
1700         }
1701       if (*line == '#' || !*line)
1702         continue; /* Don't expect a response for a comment line. */
1703
1704       rc = read_and_print_response (ctx, &cmderr);
1705       if (rc)
1706         log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
1707       if ((rc || cmderr) && script_fp)
1708         {
1709           log_error ("stopping script execution\n");
1710           fclose (script_fp);
1711           script_fp = NULL;
1712         }
1713           
1714
1715       /* FIXME: If the last command was BYE or the server died for
1716          some other reason, we won't notice until we get the next
1717          input command.  Probing the connection with a non-blocking
1718          read could help to notice termination or other problems
1719          early.  */
1720     }
1721
1722   if (opt.verbose)
1723     log_info ("closing connection to agent\n");
1724   
1725   return 0; 
1726 }
1727
1728
1729 /* Handle an Inquire from the server.  Return False if it could not be
1730    handled; in this case the caller shll complete the operation.  LINE
1731    is the complete line as received from the server.  This function
1732    may change the content of LINE. */
1733 static int
1734 handle_inquire (assuan_context_t ctx, char *line)
1735 {
1736   const char *name;
1737   definq_t d;
1738   FILE *fp = NULL;
1739   char buffer[1024];
1740   int rc, n;
1741
1742   /* Skip the command and trailing spaces. */
1743   for (; *line && !spacep (line); line++)
1744     ;
1745   while (spacep (line))
1746     line++;
1747   /* Get the name. */
1748   name = line;
1749   for (; *line && !spacep (line); line++)
1750     ;
1751   if (*line)
1752     *line++ = 0;
1753
1754   /* Now match it against our list.  The second loop is there to
1755      detect the match-all entry. */
1756   for (d=definq_list; d; d = d->next)
1757     if (d->name && !strcmp (d->name, name))
1758         break;
1759   if (!d)
1760     for (d=definq_list; d; d = d->next)
1761       if (!d->name)
1762         break;
1763   if (!d)
1764     {
1765       if (opt.verbose)
1766         log_info ("no handler for inquiry `%s' found\n", name);
1767       return 0;
1768     }
1769
1770   if (d->is_var)
1771     {
1772       char *tmpvalue = get_var_ext (d->file);
1773       rc = assuan_send_data (ctx, tmpvalue, strlen (tmpvalue));
1774       xfree (tmpvalue);
1775       if (rc)
1776         log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
1777     }
1778   else
1779     {
1780       if (d->is_prog)
1781         {
1782           fp = popen (d->file, "r");
1783           if (!fp)
1784             log_error ("error executing `%s': %s\n",
1785                        d->file, strerror (errno));
1786           else if (opt.verbose)
1787             log_error ("handling inquiry `%s' by running `%s'\n", 
1788                        name, d->file);
1789         }
1790       else
1791         {
1792           fp = fopen (d->file, "rb");
1793           if (!fp)
1794             log_error ("error opening `%s': %s\n", d->file, strerror (errno));
1795           else if (opt.verbose)
1796             log_error ("handling inquiry `%s' by returning content of `%s'\n",
1797                        name, d->file);
1798         }
1799       if (!fp)
1800         return 0;
1801
1802       while ( (n = fread (buffer, 1, sizeof buffer, fp)) )
1803         {
1804           rc = assuan_send_data (ctx, buffer, n);
1805           if (rc)
1806             {
1807               log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
1808               break;
1809             }
1810         }
1811       if (ferror (fp))
1812         log_error ("error reading from `%s': %s\n", d->file, strerror (errno));
1813     }
1814
1815   rc = assuan_send_data (ctx, NULL, 0);
1816   if (rc)
1817     log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
1818
1819   if (d->is_var)
1820     ;
1821   else if (d->is_prog)
1822     {
1823       if (pclose (fp))
1824         log_error ("error running `%s': %s\n", d->file, strerror (errno));
1825     }
1826   else
1827     fclose (fp);
1828   return 1;
1829 }
1830
1831
1832 /* Read all response lines from server and print them.  Returns 0 on
1833    success or an assuan error code.  Set R_GOTERR to true if the
1834    command did not returned OK.  */
1835 static int
1836 read_and_print_response (assuan_context_t ctx, int *r_goterr)
1837 {
1838   char *line;
1839   size_t linelen;
1840   assuan_error_t rc;
1841   int i, j;
1842   int need_lf = 0;
1843
1844   *r_goterr = 0;
1845   for (;;)
1846     {
1847       do 
1848         {
1849           rc = assuan_read_line (ctx, &line, &linelen);
1850           if (rc)
1851             return rc;
1852
1853           if (opt.verbose > 1 && *line == '#')
1854             {
1855               fwrite (line, linelen, 1, stdout);
1856               putchar ('\n');
1857             }
1858         }    
1859       while (*line == '#' || !linelen);
1860
1861       if (linelen >= 1
1862           && line[0] == 'D' && line[1] == ' ')
1863         {
1864           if (opt.hex)
1865             {
1866               for (i=2; i < linelen; )
1867                 {
1868                   int save_i = i;
1869
1870                   printf ("D[%04X] ", i-2);
1871                   for (j=0; j < 16 ; j++, i++)
1872                     {
1873                       if (j == 8)
1874                         putchar (' ');
1875                       if (i < linelen)
1876                         printf (" %02X", ((unsigned char*)line)[i]);
1877                       else
1878                         fputs ("   ", stdout);
1879                     }
1880                   fputs ("   ", stdout);
1881                   i= save_i;
1882                   for (j=0; j < 16; j++, i++)
1883                     {
1884                       unsigned int c = ((unsigned char*)line)[i];
1885                       if ( i >= linelen )
1886                         putchar (' ');
1887                       else if (isascii (c) && isprint (c) && !iscntrl (c))
1888                         putchar (c);
1889                       else
1890                         putchar ('.');
1891                     }
1892                   putchar ('\n');
1893                 }
1894             }
1895           else if (opt.decode)
1896             {
1897               const unsigned char *s;
1898               int need_d = 1;
1899               int c = 0;
1900
1901               for (j=2, s=(unsigned char*)line+2; j < linelen; j++, s++ )
1902                 {
1903                   if (need_d)
1904                     {
1905                       fputs ("D ", stdout);
1906                       need_d = 0;
1907                     }
1908                   if (*s == '%' && j+2 < linelen)
1909                     { 
1910                       s++; j++;
1911                       c = xtoi_2 ( s );
1912                       s++; j++;
1913                     }
1914                   else
1915                     c = *s;
1916                   if (c == '\n')
1917                     need_d = 1;
1918                   putchar (c);
1919                 }
1920               need_lf = (c != '\n');
1921             }
1922           else
1923             {
1924               fwrite (line, linelen, 1, stdout);
1925               putchar ('\n');
1926             }
1927         }
1928       else 
1929         {
1930           if (need_lf)
1931             {
1932               putchar ('\n');
1933               need_lf = 0;
1934             }
1935
1936           if (linelen >= 1
1937               && line[0] == 'S' 
1938               && (line[1] == '\0' || line[1] == ' '))
1939             {
1940               fwrite (line, linelen, 1, stdout);
1941               putchar ('\n');
1942             }  
1943           else if (linelen >= 2
1944                    && line[0] == 'O' && line[1] == 'K'
1945                    && (line[2] == '\0' || line[2] == ' '))
1946             {
1947               fwrite (line, linelen, 1, stdout);
1948               putchar ('\n');
1949               set_int_var ("?", 0);
1950               return 0;
1951             }
1952           else if (linelen >= 3
1953                    && line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
1954                    && (line[3] == '\0' || line[3] == ' '))
1955             {
1956               int errval;
1957
1958               errval = strtol (line+3, NULL, 10);
1959               if (!errval)
1960                 errval = -1;
1961               set_int_var ("?", errval);
1962               fwrite (line, linelen, 1, stdout);
1963               putchar ('\n');
1964               *r_goterr = 1;
1965               return 0;
1966             }  
1967           else if (linelen >= 7
1968                    && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
1969                    && line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
1970                    && line[6] == 'E' 
1971                    && (line[7] == '\0' || line[7] == ' '))
1972             {
1973               fwrite (line, linelen, 1, stdout);
1974               putchar ('\n');
1975               if (!handle_inquire (ctx, line))
1976                 assuan_write_line (ctx, "CANCEL");
1977             }
1978           else if (linelen >= 3
1979                    && line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
1980                    && (line[3] == '\0' || line[3] == ' '))
1981             {
1982               fwrite (line, linelen, 1, stdout);
1983               putchar ('\n');
1984               /* Received from server, thus more responses are expected.  */
1985             }
1986           else
1987             return gpg_error (GPG_ERR_ASS_INV_RESPONSE);
1988         }
1989     }
1990 }
1991
1992
1993
1994
1995 /* Connect to the agent and send the standard options.  */
1996 static assuan_context_t
1997 start_agent (void)
1998 {
1999   int rc = 0;
2000   char *infostr, *p;
2001   assuan_context_t ctx;
2002
2003   infostr = getenv ("GPG_AGENT_INFO");
2004   if (!infostr || !*infostr)
2005     {
2006       char *sockname;
2007
2008       /* Check whether we can connect at the standard socket.  */
2009       sockname = make_filename (opt.homedir, "S.gpg-agent", NULL);
2010       rc = assuan_socket_connect (&ctx, sockname, 0);
2011       xfree (sockname);
2012     }
2013   else
2014     {
2015       int prot;
2016       int pid;
2017
2018       infostr = xstrdup (infostr);
2019       if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
2020         {
2021           log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
2022           xfree (infostr);
2023           exit (1);
2024         }
2025       *p++ = 0;
2026       pid = atoi (p);
2027       while (*p && *p != PATHSEP_C)
2028         p++;
2029       prot = *p? atoi (p+1) : 0;
2030       if (prot != 1)
2031         {
2032           log_error (_("gpg-agent protocol version %d is not supported\n"),
2033                      prot);
2034           xfree (infostr);
2035           exit (1);
2036         }
2037
2038       rc = assuan_socket_connect (&ctx, infostr, pid);
2039       xfree (infostr);
2040     }
2041
2042   if (rc)
2043     {
2044       log_error ("can't connect to the agent: %s\n", gpg_strerror (rc));
2045       exit (1);
2046     }
2047
2048   if (opt.verbose)
2049     log_info ("connection to agent established\n");
2050
2051   rc = assuan_transact (ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
2052   if (rc)
2053     {
2054       log_error (_("error sending %s command: %s\n"), "RESET", 
2055                  gpg_strerror (rc));
2056       exit (1);
2057     }
2058
2059   rc = send_pinentry_environment (ctx, GPG_ERR_SOURCE_DEFAULT,
2060                                   NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2061   if (rc)
2062     {
2063       log_error (_("error sending standard options: %s\n"), gpg_strerror (rc));
2064       exit (1);
2065     }
2066
2067   return ctx;
2068 }