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