Extended gpg-connect-agent.
[gnupg.git] / tools / gpg-connect-agent.c
1 /* gpg-connect-agent.c - Tool to connect to the agent.
2  *      Copyright (C) 2005, 2007 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
29 #include "i18n.h"
30 #include "../common/util.h"
31 #include "../common/asshelp.h"
32 #include "../common/sysutils.h"
33 #include "../common/membuf.h"
34
35 /* Constants to identify the commands and options. */
36 enum cmd_and_opt_values
37   {
38     aNull = 0,
39     oQuiet      = 'q',
40     oVerbose    = 'v',
41     oRawSocket  = 'S',
42     oExec       = 'E',
43
44     oNoVerbose  = 500,
45     oHomedir,
46     oHex,
47     oDecode,
48     oNoExtConnect
49
50   };
51
52
53 /* The list of commands and options. */
54 static ARGPARSE_OPTS opts[] =
55   {
56     { 301, NULL, 0, N_("@\nOptions:\n ") },
57     
58     { oVerbose, "verbose",  0, N_("verbose") },
59     { oQuiet, "quiet",      0, N_("quiet") },
60     { oHex,   "hex",        0, N_("print data out hex encoded") },
61     { oDecode,"decode",     0, N_("decode received data lines") },
62     { oRawSocket, "raw-socket", 2, N_("|NAME|connect to Assuan socket NAME")},
63     { oExec, "exec", 0, N_("run the Assuan server given on the command line")},
64     { oNoExtConnect, "no-ext-connect",
65                             0, N_("do not use extended connect mode")},
66
67     /* hidden options */
68     { oNoVerbose, "no-verbose",  0, "@"},
69     { oHomedir, "homedir", 2, "@" },   
70     {0}
71   };
72
73
74 /* We keep all global options in the structure OPT.  */
75 struct
76 {
77   int verbose;          /* Verbosity level.  */
78   int quiet;            /* Be extra quiet.  */
79   const char *homedir;  /* Configuration directory name */
80   int hex;              /* Print data lines in hex format. */
81   int decode;           /* Decode received data lines.  */
82   const char *raw_socket; /* Name of socket to connect in raw mode. */
83   int exec;             /* Run the pgm given on the command line. */
84   unsigned int connect_flags;    /* Flags used for connecting. */
85   int enable_varsubst;  /* Set if variable substitution is enabled.  */
86 } opt;
87
88
89
90 /* Definitions for /definq commands and a global linked list with all
91    the definitions. */
92 struct definq_s
93 {
94   struct definq_s *next;
95   char *name;     /* Name of inquiry or NULL for any name. */
96   int is_prog;     /* True if this is a program to run. */
97   char file[1];   /* Name of file or program. */
98 };
99 typedef struct definq_s *definq_t;
100
101 static definq_t definq_list;
102 static definq_t *definq_list_tail = &definq_list;
103
104
105 /* Variable definitions and glovbal table.  */
106 struct variable_s
107 {
108   struct variable_s *next;
109   char *value;  /* Malloced value - always a string.  */
110   char name[1]; /* Name of the variable.  */
111 };
112 typedef struct variable_s *variable_t;
113
114 static variable_t variable_table;
115
116 /* This is used to store the pid of the server.  */
117 static pid_t server_pid = (pid_t)(-1);
118
119
120 /* A list of open file descriptors. */
121 static struct
122 {
123   int inuse;
124 #ifdef HAVE_W32_SYSTEM
125   HANDLE handle;
126 #endif
127 } open_fd_table[256];
128
129
130 /*-- local prototypes --*/
131 static int read_and_print_response (assuan_context_t ctx);
132 static assuan_context_t start_agent (void);
133
134
135
136 \f
137 /* Print usage information and and provide strings for help. */
138 static const char *
139 my_strusage( int level )
140 {
141   const char *p;
142
143   switch (level)
144     {
145     case 11: p = "gpg-connect-agent (GnuPG)";
146       break;
147     case 13: p = VERSION; break;
148     case 17: p = PRINTABLE_OS_NAME; break;
149     case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
150       break;
151     case 1:
152     case 40: p = _("Usage: gpg-connect-agent [options] (-h for help)");
153       break;
154     case 41:
155       p = _("Syntax: gpg-connect-agent [options]\n"
156             "Connect to a running agent and send commands\n");
157       break;
158     case 31: p = "\nHome: "; break;
159     case 32: p = opt.homedir; break;
160     case 33: p = "\n"; break;
161
162     default: p = NULL; break;
163     }
164   return p;
165 }
166
167 \f
168 static void
169 set_var (const char *name, const char *value)
170 {
171   variable_t var;
172
173   for (var = variable_table; var; var = var->next)
174     if (!strcmp (var->name, name))
175       break;
176   if (!var)
177     {
178       var = xmalloc (sizeof *var + strlen (name));
179       var->value = NULL;
180       strcpy (var->name, name);
181       var->next = variable_table;
182       variable_table = var;
183     }
184   xfree (var->value);
185   var->value = value? xstrdup (value) : NULL;
186 }    
187
188
189 static void
190 set_int_var (const char *name, int value)
191 {
192   char numbuf[35];
193
194   snprintf (numbuf, sizeof numbuf, "%d", value);
195   set_var (name, numbuf);
196 }
197
198 /* Return the value of a variable.  That value is valid until a
199    variable of the name is changed.  Return NULL if not found.  */
200 static const char *
201 get_var (const char *name)
202 {
203   variable_t var;
204
205   for (var = variable_table; var; var = var->next)
206     if (!strcmp (var->name, name))
207       break;
208   if (!var || !var->value)
209     return NULL;
210   return var->value;
211 }
212
213
214
215 /* Substitute variables in LINE and return a new allocated buffer if
216    required.  The function might modify LINE if the expanded version
217    fits into it.  */
218 static char *
219 substitute_line (char *buffer)
220 {
221   char *line = buffer;
222   char *p, *pend;
223   const char *value;
224   size_t valuelen, n;
225   char *result = NULL;
226
227   while (*line)
228     {
229       p = strchr (line, '$');
230       if (!p)
231         return result; /* No more variables.  */
232       
233       if (p[1] == '$') /* Escaped dollar sign. */
234         {
235           memmove (p, p+1, strlen (p+1)+1);
236           line = p + 1;
237           continue;
238         }
239       for (pend=p+1; *pend && !spacep (pend) && *pend != '$' ; pend++)
240         ;
241       if (*pend)
242         {
243           int save = *pend;
244           *pend = 0;
245           value = get_var (p+1);
246           *pend = save;
247         }
248       else
249         value = get_var (p+1);
250       if (!value)
251         value = "";
252       valuelen = strlen (value);
253       if (valuelen <= pend - p)
254         {
255           memcpy (p, value, valuelen);
256           p += valuelen;
257           n = pend - p;
258           if (n)
259             memmove (p, p+n, strlen (p+n)+1);
260           line = p;
261         }
262       else
263         {
264           char *src = result? result : buffer;
265           char *dst;
266
267           dst = xmalloc (strlen (src) + valuelen + 1);
268           n = p - src;
269           memcpy (dst, src, n);
270           memcpy (dst + n, value, valuelen);
271           n += valuelen;
272           strcpy (dst + n, pend);
273           line = dst + n;
274           free (result);
275           result = dst;
276         }
277     }
278   return result;
279 }
280
281
282
283 static void
284 assign_variable (char *line)
285 {
286   char *name, *p, *tmp;
287
288   /* Get the  name. */
289   name = line;
290   for (p=name; *p && !spacep (p); p++)
291     ;
292   if (*p)
293     *p++ = 0;
294   while (spacep (p))
295     p++;
296
297   if (!*p)
298     set_var (name, NULL); /* Remove variable.  */ 
299   else 
300     {
301       tmp = opt.enable_varsubst? substitute_line (p) : NULL;
302       if (tmp)
303         {
304           set_var (name, tmp);
305           xfree (tmp);
306         }
307       else
308         set_var (name, p);
309     }
310 }
311
312
313 static void
314 show_variables (void)
315 {
316   variable_t var;
317
318   for (var = variable_table; var; var = var->next)
319     if (var->value)
320       printf ("%-20s %s\n", var->name, var->value);
321 }
322
323
324 /* Store an inquire response pattern.  Note, that this function may
325    change the content of LINE.  We assume that leading white spaces
326    are already removed. */
327 static void
328 add_definq (char *line, int is_prog)
329 {
330   definq_t d;
331   char *name, *p;
332
333   /* Get name. */
334   name = line;
335   for (p=name; *p && !spacep (p); p++)
336     ;
337   if (*p)
338     *p++ = 0;
339   while (spacep (p))
340     p++;
341
342   d = xmalloc (sizeof *d + strlen (p) );
343   strcpy (d->file, p);
344   d->is_prog = is_prog;
345   if ( !strcmp (name, "*"))
346     d->name = NULL;
347   else
348     d->name = xstrdup (name);
349
350   d->next = NULL;
351   *definq_list_tail = d;
352   definq_list_tail = &d->next;
353 }
354
355
356 /* Show all inquiry defintions. */
357 static void
358 show_definq (void)
359 {
360   definq_t d;
361
362   for (d=definq_list; d; d = d->next)
363     if (d->name)
364       printf ("%-20s %c %s\n", d->name, d->is_prog? 'p':'f', d->file);
365   for (d=definq_list; d; d = d->next)
366     if (!d->name)
367       printf ("%-20s %c %s\n", "*", d->is_prog? 'p':'f', d->file);
368 }
369
370
371 /* Clear all inquiry definitions. */
372 static void
373 clear_definq (void)
374 {
375   while (definq_list)
376     { 
377       definq_t tmp = definq_list->next;
378       xfree (definq_list->name);
379       xfree (definq_list);
380       definq_list = tmp;
381     }
382   definq_list_tail = &definq_list;
383 }      
384
385
386 static void
387 do_sendfd (assuan_context_t ctx, char *line)
388 {
389   FILE *fp;
390   char *name, *mode, *p;
391   int rc, fd;
392
393   /* Get file name. */
394   name = line;
395   for (p=name; *p && !spacep (p); p++)
396     ;
397   if (*p)
398     *p++ = 0;
399   while (spacep (p))
400     p++;
401
402   /* Get mode.  */
403   mode = p;
404   if (!*mode)
405     mode = "r";
406   else
407     {
408       for (p=mode; *p && !spacep (p); p++)
409         ;
410       if (*p)
411         *p++ = 0;
412     }
413
414   /* Open and send. */
415   fp = fopen (name, mode);
416   if (!fp)
417     {
418       log_error ("can't open `%s' in \"%s\" mode: %s\n",
419                  name, mode, strerror (errno));
420       return;
421     }
422   fd = fileno (fp);
423
424   if (opt.verbose)
425     log_error ("file `%s' opened in \"%s\" mode, fd=%d\n",
426                name, mode, fd);
427
428   rc = assuan_sendfd (ctx, INT2FD (fd) );
429   if (rc)
430     log_error ("sending descriptor %d failed: %s\n", fd, gpg_strerror (rc));
431   fclose (fp);
432 }
433
434
435 static void
436 do_recvfd (assuan_context_t ctx, char *line)
437 {
438   log_info ("This command has not yet been implemented\n");
439 }
440
441
442 static void
443 do_open (char *line)
444 {
445   FILE *fp;
446   char *varname, *name, *mode, *p;
447   int fd;
448
449 #ifdef HAVE_W32_SYSTEM
450   if (server_pid == (pid_t)(-1))
451     {
452       log_error ("the pid of the server is unknown\n");
453       log_info ("use command \"/serverpid\" first\n");
454       return;
455     }
456 #endif
457
458   /* Get variable name. */
459   varname = line;
460   for (p=varname; *p && !spacep (p); p++)
461     ;
462   if (*p)
463     *p++ = 0;
464   while (spacep (p))
465     p++;
466
467   /* Get file name. */
468   name = p;
469   for (p=name; *p && !spacep (p); p++)
470     ;
471   if (*p)
472     *p++ = 0;
473   while (spacep (p))
474     p++;
475
476   /* Get mode.  */
477   mode = p;
478   if (!*mode)
479     mode = "r";
480   else
481     {
482       for (p=mode; *p && !spacep (p); p++)
483         ;
484       if (*p)
485         *p++ = 0;
486     }
487
488   /* Open and send. */
489   fp = fopen (name, mode);
490   if (!fp)
491     {
492       log_error ("can't open `%s' in \"%s\" mode: %s\n",
493                  name, mode, strerror (errno));
494       return;
495     }
496   fd = fileno (fp);
497   if (fd >= 0 && fd < DIM (open_fd_table))
498     {
499       open_fd_table[fd].inuse = 1;
500 #ifdef HAVE_W32_SYSTEM
501       {
502         HANDLE prochandle, handle, newhandle;
503
504         handle = (void*)_get_osfhandle (fd);
505      
506         prochandle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, server_pid);
507         if (!prochandle)
508           {
509             log_error ("failed to open the server process\n");
510             close (fd);
511             return;
512           }
513
514         if (!DuplicateHandle (GetCurrentProcess(), handle,
515                               prochandle, &newhandle, 0,
516                               TRUE, DUPLICATE_SAME_ACCESS ))
517           {
518             log_error ("failed to duplicate the handle\n");
519             close (fd);
520             CloseHandle (prochandle);
521             return;
522           }
523         CloseHandle (prochandle);
524         open_fd_table[fd].handle = newhandle;
525       }
526       if (opt.verbose)
527         log_info ("file `%s' opened in \"%s\" mode, fd=%d  (libc=%d)\n",
528                    name, mode, (int)open_fd_table[fd].handle, fd);
529       set_int_var (varname, (int)open_fd_table[fd].handle);
530 #else  
531       if (opt.verbose)
532         log_info ("file `%s' opened in \"%s\" mode, fd=%d\n",
533                    name, mode, fd);
534       set_int_var (varname, fd);
535 #endif
536     }
537   else
538     {
539       log_error ("can't put fd %d into table\n", fd);
540       close (fd);
541     }
542 }
543
544
545 static void
546 do_close (char *line)
547 {
548   int fd = atoi (line);
549
550 #ifdef HAVE_W32_SYSTEM
551   int i;
552
553   for (i=0; i < DIM (open_fd_table); i++)
554     if ( open_fd_table[i].inuse && open_fd_table[i].handle == (void*)fd)
555       break;
556   if (i < DIM (open_fd_table))
557     fd = i;
558   else
559     {
560       log_error ("given fd (system handle) has not been opened\n");
561       return;
562     }
563 #endif
564
565   if (fd < 0 || fd >= DIM (open_fd_table))
566     {
567       log_error ("invalid fd\n");
568       return;
569     }
570
571   if (!open_fd_table[fd].inuse)
572     {
573       log_error ("given fd has not been opened\n");
574       return;
575     }
576 #ifdef HAVE_W32_SYSTEM
577   CloseHandle (open_fd_table[fd].handle); /* Close duped handle.  */
578 #endif
579   close (fd);
580   open_fd_table[fd].inuse = 0;
581 }
582
583
584 static void
585 do_showopen (void)
586 {
587   int i;
588
589   for (i=0; i < DIM (open_fd_table); i++)
590     if (open_fd_table[i].inuse)
591       {
592 #ifdef HAVE_W32_SYSTEM
593         printf ("%-15d (libc=%d)\n", (int)open_fd_table[i].handle, i);
594 #else
595         printf ("%-15d\n", i);
596 #endif
597       }
598 }
599
600
601
602 static int
603 getinfo_pin_cb (void *opaque, const void *buffer, size_t length)
604 {
605   membuf_t *mb = opaque;
606   put_membuf (mb, buffer, length);
607   return 0;
608 }
609
610 /* Get the pid of the server and store it locally.  */
611 static void
612 do_serverpid (assuan_context_t ctx)
613 {
614   int rc;
615   membuf_t mb;
616   char *buffer;
617   
618   init_membuf (&mb, 100);
619   rc = assuan_transact (ctx, "GETINFO pid", getinfo_pin_cb, &mb,
620                         NULL, NULL, NULL, NULL);
621   put_membuf (&mb, "", 1);
622   buffer = get_membuf (&mb, NULL);
623   if (rc || !buffer)
624     log_error ("command \"%s\" failed: %s\n", 
625                "GETINFO pid", gpg_strerror (rc));
626   else
627     {
628       server_pid = (pid_t)strtoul (buffer, NULL, 10);
629       if (opt.verbose)
630         log_info ("server's PID is %lu\n", (unsigned long)server_pid);
631     }
632   xfree (buffer);
633 }
634
635
636 /* gpg-connect-agent's entry point. */
637 int
638 main (int argc, char **argv)
639 {
640   ARGPARSE_ARGS pargs;
641   int no_more_options = 0;
642   assuan_context_t ctx;
643   char *line, *p;
644   char *tmpline;
645   size_t linesize;
646   int rc;
647
648   set_strusage (my_strusage);
649   log_set_prefix ("gpg-connect-agent", 1);
650
651   /* Make sure that our subsystems are ready.  */
652   init_common_subsystems ();
653
654   assuan_set_assuan_err_source (0);
655
656   i18n_init();
657
658   opt.homedir = default_homedir ();
659   opt.connect_flags = 1; /* Use extended connect mode.  */
660
661   /* Parse the command line. */
662   pargs.argc  = &argc;
663   pargs.argv  = &argv;
664   pargs.flags =  1;  /* Do not remove the args.  */
665   while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts))
666     {
667       switch (pargs.r_opt)
668         {
669         case oQuiet:     opt.quiet = 1; break;
670         case oVerbose:   opt.verbose++; break;
671         case oNoVerbose: opt.verbose = 0; break;
672         case oHomedir:   opt.homedir = pargs.r.ret_str; break;
673         case oHex:       opt.hex = 1; break;
674         case oDecode:    opt.decode = 1; break;
675         case oRawSocket: opt.raw_socket = pargs.r.ret_str; break;
676         case oExec:      opt.exec = 1; break;
677         case oNoExtConnect: opt.connect_flags &= ~(1); break;
678
679         default: pargs.err = 2; break;
680         }
681     }
682
683   if (log_get_errorcount (0))
684     exit (2);
685
686   if (opt.exec)
687     {
688       if (!argc)
689         {
690           log_error (_("option \"%s\" requires a program "
691                        "and optional arguments\n"), "--exec" );
692           exit (1);
693         }
694     }
695   else if (argc)
696     usage (1);
697
698   if (opt.exec && opt.raw_socket)
699     log_info (_("option \"%s\" ignored due to \"%s\"\n"),
700               "--raw-socket", "--exec");
701
702   if (opt.exec)
703     {
704       int no_close[3];
705
706       no_close[0] = fileno (stderr);
707       no_close[1] = log_get_fd ();
708       no_close[2] = -1;
709       rc = assuan_pipe_connect_ext (&ctx, *argv, (const char **)argv,
710                                     no_close, NULL, NULL,
711                                     opt.connect_flags);
712       if (rc)
713         {
714           log_error ("assuan_pipe_connect_ext failed: %s\n",
715                      gpg_strerror (rc));
716           exit (1);
717         }
718
719       if (opt.verbose)
720         log_info ("server `%s' started\n", *argv);
721
722     }
723   else if (opt.raw_socket)
724     {
725       rc = assuan_socket_connect_ext (&ctx, opt.raw_socket, 0,
726                                       opt.connect_flags);
727       if (rc)
728         {
729           log_error ("can't connect to socket `%s': %s\n",
730                      opt.raw_socket, gpg_strerror (rc));
731           exit (1);
732         }
733
734       if (opt.verbose)
735         log_info ("connection to socket `%s' established\n", opt.raw_socket);
736     }
737   else
738     ctx = start_agent ();
739
740   /* See whether there is a line pending from the server (in case
741      assuan did not run the initial handshaking).  */
742   if (assuan_pending_line (ctx))
743     {
744       rc = read_and_print_response (ctx);
745       if (rc)
746         log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
747     }
748
749   line = NULL;
750   linesize = 0;
751   for (;;)
752     {
753       int n;
754       size_t maxlength;
755
756       maxlength = 2048;
757       n = read_line (stdin, &line, &linesize, &maxlength);
758       if (n < 0)
759         {
760           log_error (_("error reading input: %s\n"), strerror (errno));
761           exit (1);
762         }
763       if (!n)
764         break; /* EOF */
765       if (!maxlength)
766         {
767           log_error (_("line too long - skipped\n"));
768           continue;
769         }
770       if (memchr (line, 0, n))
771         log_info (_("line shortened due to embedded Nul character\n"));
772       if (line[n-1] == '\n')
773         line[n-1] = 0;
774       if (*line == '/')
775         {
776           /* Handle control commands. */
777           char *cmd = line+1;
778
779           for (p=cmd; *p && !spacep (p); p++)
780             ;
781           if (*p)
782             *p++ = 0;
783           while (spacep (p))
784             p++;
785           if (!strcmp (cmd, "let"))
786             {
787               assign_variable (p);
788             }
789           else if (!strcmp (cmd, "showvar"))
790             {
791               show_variables ();
792             }
793           else if (!strcmp (cmd, "definqfile"))
794             {
795               add_definq (p, 0);
796             }
797           else if (!strcmp (cmd, "definqprog"))
798             {
799               add_definq (p, 1);
800             }
801           else if (!strcmp (cmd, "showdef"))
802             {
803               show_definq ();
804             }
805           else if (!strcmp (cmd, "cleardef"))
806             {
807               clear_definq ();
808             }
809           else if (!strcmp (cmd, "echo"))
810             {
811               tmpline = opt.enable_varsubst? substitute_line (p) : NULL;
812               if (tmpline)
813                 {
814                   puts (tmpline);
815                   xfree (tmpline);
816                 }
817               else
818                 puts (p);
819             }
820           else if (!strcmp (cmd, "sendfd"))
821             {
822               do_sendfd (ctx, p);
823               continue;
824             }
825           else if (!strcmp (cmd, "recvfd"))
826             {
827               do_recvfd (ctx, p);
828               continue;
829             }
830           else if (!strcmp (cmd, "open"))
831             {
832               do_open (p);
833             }
834           else if (!strcmp (cmd, "close"))
835             {
836               do_close (p);
837             }
838           else if (!strcmp (cmd, "showopen"))
839             {
840               do_showopen ();
841             }
842           else if (!strcmp (cmd, "serverpid"))
843             {
844               do_serverpid (ctx);
845             }
846           else if (!strcmp (cmd, "hex"))
847             opt.hex = 1;
848           else if (!strcmp (cmd, "nohex"))
849             opt.hex = 0;
850           else if (!strcmp (cmd, "decode"))
851             opt.decode = 1;
852           else if (!strcmp (cmd, "nodecode"))
853             opt.decode = 0;
854           else if (!strcmp (cmd, "subst"))
855             opt.enable_varsubst = 1;
856           else if (!strcmp (cmd, "nosubst"))
857             opt.enable_varsubst = 0;
858           else if (!strcmp (cmd, "help"))
859             {
860               puts (
861 "Available commands:\n"
862 "/echo ARGS             Echo ARGS.\n"
863 "/let  NAME VALUE       Set variable NAME to VALUE.\n"
864 "/showvar               Show all variables.\n"
865 "/definqfile NAME FILE\n"
866 "    Use content of FILE for inquiries with NAME.\n"
867 "    NAME may be \"*\" to match any inquiry.\n"
868 "/definqprog NAME PGM\n"
869 "    Run PGM for inquiries matching NAME and pass the\n"
870 "    entire line to it as arguments.\n"
871 "/showdef               Print all definitions.\n"
872 "/cleardef              Delete all definitions.\n"
873 "/sendfd FILE MODE      Open FILE and pass descriptor to server.\n"
874 "/recvfd                Receive FD from server and print.\n"
875 "/open VAR FILE MODE    Open FILE and assign the descrptor to VAR.\n" 
876 "/close FD              Close file with descriptor FD.\n"
877 "/showopen              Show descriptors of all open files.\n"
878 "/serverpid             Retrieve the pid of the server.\n"
879 "/[no]hex               Enable hex dumping of received data lines.\n"
880 "/[no]decode            Enable decoding of received data lines.\n"
881 "/[no]subst             Enable varibale substitution.\n"
882 "/help                  Print this help.");
883             }
884           else
885             log_error (_("unknown command `%s'\n"), cmd );
886       
887           continue;
888         }
889
890       tmpline = opt.enable_varsubst? substitute_line (line) : NULL;
891       if (tmpline)
892         {
893           rc = assuan_write_line (ctx, tmpline);
894           xfree (tmpline);
895         }
896       else
897         rc = assuan_write_line (ctx, line);
898       if (rc)
899         {
900           log_info (_("sending line failed: %s\n"), gpg_strerror (rc) );
901           break;
902         }
903       if (*line == '#' || !*line)
904         continue; /* Don't expect a response for a comment line. */
905
906       rc = read_and_print_response (ctx);
907       if (rc)
908         log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) );
909
910       /* FIXME: If the last command was BYE or the server died for
911          some other reason, we won't notice until we get the next
912          input command.  Probing the connection with a non-blocking
913          read could help to notice termination or other problems
914          early.  */
915     }
916
917   if (opt.verbose)
918     log_info ("closing connection to agent\n");
919   
920   return 0; 
921 }
922
923
924 /* Handle an Inquire from the server.  Return False if it could not be
925    handled; in this case the caller shll complete the operation.  LINE
926    is the complete line as received from the server.  This function
927    may change the content of LINE. */
928 static int
929 handle_inquire (assuan_context_t ctx, char *line)
930 {
931   const char *name;
932   definq_t d;
933   FILE *fp;
934   char buffer[1024];
935   int rc, n;
936
937   /* Skip the command and trailing spaces. */
938   for (; *line && !spacep (line); line++)
939     ;
940   while (spacep (line))
941     line++;
942   /* Get the name. */
943   name = line;
944   for (; *line && !spacep (line); line++)
945     ;
946   if (*line)
947     *line++ = 0;
948
949   /* Now match it against our list. he second loop is todetect the
950      match all entry. **/
951   for (d=definq_list; d; d = d->next)
952     if (d->name && !strcmp (d->name, name))
953         break;
954   if (!d)
955     for (d=definq_list; d; d = d->next)
956       if (!d->name)
957         break;
958   if (!d)
959     {
960       if (opt.verbose)
961         log_info ("no handler for inquiry `%s' found\n", name);
962       return 0;
963     }
964
965   if (d->is_prog)
966     {
967       fp = popen (d->file, "r");
968       if (!fp)
969         log_error ("error executing `%s': %s\n", d->file, strerror (errno));
970       else if (opt.verbose)
971         log_error ("handling inquiry `%s' by running `%s'\n", name, d->file);
972     }
973   else
974     {
975       fp = fopen (d->file, "rb");
976       if (!fp)
977         log_error ("error opening `%s': %s\n", d->file, strerror (errno));
978       else if (opt.verbose)
979         log_error ("handling inquiry `%s' by returning content of `%s'\n",
980                    name, d->file);
981     }
982   if (!fp)
983     return 0;
984
985   while ( (n = fread (buffer, 1, sizeof buffer, fp)) )
986     {
987       rc = assuan_send_data (ctx, buffer, n);
988       if (rc)
989         {
990           log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
991           break;
992         }
993     }
994   if (ferror (fp))
995     log_error ("error reading from `%s': %s\n", d->file, strerror (errno));
996
997   rc = assuan_send_data (ctx, NULL, 0);
998   if (rc)
999     log_error ("sending data back failed: %s\n", gpg_strerror (rc) );
1000
1001   if (d->is_prog)
1002     {
1003       if (pclose (fp))
1004         log_error ("error running `%s': %s\n", d->file, strerror (errno));
1005     }
1006   else
1007     fclose (fp);
1008   return 1;
1009 }
1010
1011
1012 /* Read all response lines from server and print them.  Returns 0 on
1013    success or an assuan error code. */
1014 static int
1015 read_and_print_response (assuan_context_t ctx)
1016 {
1017   char *line;
1018   size_t linelen;
1019   assuan_error_t rc;
1020   int i, j;
1021   int need_lf = 0;
1022
1023   for (;;)
1024     {
1025       do 
1026         {
1027           rc = assuan_read_line (ctx, &line, &linelen);
1028           if (rc)
1029             return rc;
1030
1031           if (opt.verbose > 1 && *line == '#')
1032             {
1033               fwrite (line, linelen, 1, stdout);
1034               putchar ('\n');
1035             }
1036         }    
1037       while (*line == '#' || !linelen);
1038
1039       if (linelen >= 1
1040           && line[0] == 'D' && line[1] == ' ')
1041         {
1042           if (opt.hex)
1043             {
1044               for (i=2; i < linelen; )
1045                 {
1046                   int save_i = i;
1047
1048                   printf ("D[%04X] ", i-2);
1049                   for (j=0; j < 16 ; j++, i++)
1050                     {
1051                       if (j == 8)
1052                         putchar (' ');
1053                       if (i < linelen)
1054                         printf (" %02X", ((unsigned char*)line)[i]);
1055                       else
1056                         fputs ("   ", stdout);
1057                     }
1058                   fputs ("   ", stdout);
1059                   i= save_i;
1060                   for (j=0; j < 16; j++, i++)
1061                     {
1062                       unsigned int c = ((unsigned char*)line)[i];
1063                       if ( i >= linelen )
1064                         putchar (' ');
1065                       else if (isascii (c) && isprint (c) && !iscntrl (c))
1066                         putchar (c);
1067                       else
1068                         putchar ('.');
1069                     }
1070                   putchar ('\n');
1071                 }
1072             }
1073           else if (opt.decode)
1074             {
1075               const unsigned char *s;
1076               int need_d = 1;
1077               int c = 0;
1078
1079               for (j=2, s=(unsigned char*)line+2; j < linelen; j++, s++ )
1080                 {
1081                   if (need_d)
1082                     {
1083                       fputs ("D ", stdout);
1084                       need_d = 0;
1085                     }
1086                   if (*s == '%' && j+2 < linelen)
1087                     { 
1088                       s++; j++;
1089                       c = xtoi_2 ( s );
1090                       s++; j++;
1091                     }
1092                   else
1093                     c = *s;
1094                   if (c == '\n')
1095                     need_d = 1;
1096                   putchar (c);
1097                 }
1098               need_lf = (c != '\n');
1099             }
1100           else
1101             {
1102               fwrite (line, linelen, 1, stdout);
1103               putchar ('\n');
1104             }
1105         }
1106       else 
1107         {
1108           if (need_lf)
1109             {
1110               putchar ('\n');
1111               need_lf = 0;
1112             }
1113
1114           if (linelen >= 1
1115               && line[0] == 'S' 
1116               && (line[1] == '\0' || line[1] == ' '))
1117             {
1118               fwrite (line, linelen, 1, stdout);
1119               putchar ('\n');
1120             }  
1121           else if (linelen >= 2
1122                    && line[0] == 'O' && line[1] == 'K'
1123                    && (line[2] == '\0' || line[2] == ' '))
1124             {
1125               fwrite (line, linelen, 1, stdout);
1126               putchar ('\n');
1127               return 0;
1128             }
1129           else if (linelen >= 3
1130                    && line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
1131                    && (line[3] == '\0' || line[3] == ' '))
1132             {
1133               fwrite (line, linelen, 1, stdout);
1134               putchar ('\n');
1135               return 0;
1136             }  
1137           else if (linelen >= 7
1138                    && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
1139                    && line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
1140                    && line[6] == 'E' 
1141                    && (line[7] == '\0' || line[7] == ' '))
1142             {
1143               fwrite (line, linelen, 1, stdout);
1144               putchar ('\n');
1145               if (!handle_inquire (ctx, line))
1146                 assuan_write_line (ctx, "CANCEL");
1147             }
1148           else if (linelen >= 3
1149                    && line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
1150                    && (line[3] == '\0' || line[3] == ' '))
1151             {
1152               fwrite (line, linelen, 1, stdout);
1153               putchar ('\n');
1154               /* Received from server, thus more responses are expected.  */
1155             }
1156           else
1157             return gpg_error (GPG_ERR_ASS_INV_RESPONSE);
1158         }
1159     }
1160 }
1161
1162
1163
1164
1165 /* Connect to the agent and send the standard options.  */
1166 static assuan_context_t
1167 start_agent (void)
1168 {
1169   int rc = 0;
1170   char *infostr, *p;
1171   assuan_context_t ctx;
1172
1173   infostr = getenv ("GPG_AGENT_INFO");
1174   if (!infostr || !*infostr)
1175     {
1176       char *sockname;
1177
1178       /* Check whether we can connect at the standard socket.  */
1179       sockname = make_filename (opt.homedir, "S.gpg-agent", NULL);
1180       rc = assuan_socket_connect (&ctx, sockname, 0);
1181       xfree (sockname);
1182     }
1183   else
1184     {
1185       int prot;
1186       int pid;
1187
1188       infostr = xstrdup (infostr);
1189       if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
1190         {
1191           log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
1192           xfree (infostr);
1193           exit (1);
1194         }
1195       *p++ = 0;
1196       pid = atoi (p);
1197       while (*p && *p != PATHSEP_C)
1198         p++;
1199       prot = *p? atoi (p+1) : 0;
1200       if (prot != 1)
1201         {
1202           log_error (_("gpg-agent protocol version %d is not supported\n"),
1203                      prot);
1204           xfree (infostr);
1205           exit (1);
1206         }
1207
1208       rc = assuan_socket_connect (&ctx, infostr, pid);
1209       xfree (infostr);
1210     }
1211
1212   if (rc)
1213     {
1214       log_error ("can't connect to the agent: %s\n", gpg_strerror (rc));
1215       exit (1);
1216     }
1217
1218   if (opt.verbose)
1219     log_info ("connection to agent established\n");
1220
1221   rc = assuan_transact (ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
1222   if (rc)
1223     {
1224       log_error (_("error sending %s command: %s\n"), "RESET", 
1225                  gpg_strerror (rc));
1226       exit (1);
1227     }
1228
1229   rc = send_pinentry_environment (ctx, GPG_ERR_SOURCE_DEFAULT,
1230                                   NULL, NULL, NULL, NULL, NULL);
1231   if (rc)
1232     {
1233       log_error (_("error sending standard options: %s\n"), gpg_strerror (rc));
1234       exit (1);
1235     }
1236
1237   return ctx;
1238 }