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