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