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