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