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