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