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