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