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