1 /* gpg-connect-agent.c - Tool to connect to the agent.
2 * Copyright (C) 2005 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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 2 of the License, or
9 * (at your option) any later version.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
31 #include "../common/util.h"
32 #include "../common/asshelp.h"
36 /* Constants to identify the commands and options. */
37 enum cmd_and_opt_values
50 /* The list of commands and options. */
51 static ARGPARSE_OPTS opts
[] =
53 { 301, NULL
, 0, N_("@\nOptions:\n ") },
55 { oVerbose
, "verbose", 0, N_("verbose") },
56 { oQuiet
, "quiet", 0, N_("quiet") },
57 { oHex
, "hex", 0, N_("print data out hex encoded") },
60 { oNoVerbose
, "no-verbose", 0, "@"},
61 { oHomedir
, "homedir", 2, "@" },
66 /* We keep all global options in the structure OPT. */
69 int verbose
; /* Verbosity level. */
70 int quiet
; /* Be extra quiet. */
71 const char *homedir
; /* Configuration directory name */
72 int hex
; /* Print data lines in hex format. */
76 /*-- local prototypes --*/
77 static int read_and_print_response (assuan_context_t ctx
);
78 static assuan_context_t
start_agent (void);
83 /* Print usage information and and provide strings for help. */
85 my_strusage( int level
)
91 case 11: p
= "gpg-connect-agent (GnuPG)";
93 case 13: p
= VERSION
; break;
94 case 17: p
= PRINTABLE_OS_NAME
; break;
95 case 19: p
= _("Please report bugs to <" PACKAGE_BUGREPORT
">.\n");
98 case 40: p
= _("Usage: gpg-connect-agent [options] (-h for help)");
101 p
= _("Syntax: gpg-connect-agent [options]\n"
102 "Connect to a running agent and send commands\n");
104 case 31: p
= "\nHome: "; break;
105 case 32: p
= opt
.homedir
; break;
106 case 33: p
= "\n"; break;
108 default: p
= NULL
; break;
114 /* Initialize the gettext system. */
118 #ifdef USE_SIMPLE_GETTEXT
119 set_gettext_file (PACKAGE_GT
);
122 setlocale (LC_ALL
, "" );
123 bindtextdomain (PACKAGE_GT
, LOCALEDIR
);
124 textdomain (PACKAGE_GT
);
130 /* gpg-connect-agent's entry point. */
132 main (int argc
, char **argv
)
136 int no_more_options
= 0;
137 assuan_context_t ctx
;
142 set_strusage (my_strusage
);
143 log_set_prefix ("gpg-connect-agent", 1);
147 opt
.homedir
= default_homedir ();
149 /* Parse the command line. */
152 pargs
.flags
= 1; /* Do not remove the args. */
153 while (!no_more_options
&& optfile_parse (NULL
, NULL
, NULL
, &pargs
, opts
))
157 case oQuiet
: opt
.quiet
= 1; break;
158 case oVerbose
: opt
.verbose
++; break;
159 case oNoVerbose
: opt
.verbose
= 0; break;
160 case oHomedir
: opt
.homedir
= pargs
.r
.ret_str
; break;
161 case oHex
: opt
.hex
= 1; break;
163 default: pargs
.err
= 2; break;
167 if (log_get_errorcount (0))
170 fname
= argc
? *argv
: NULL
;
172 ctx
= start_agent ();
181 n
= read_line (stdin
, &line
, &linesize
, &maxlength
);
184 log_error (_("error reading input: %s\n"), strerror (errno
));
191 log_error (_("line too long - skipped\n"));
194 if (memchr (line
, 0, n
))
195 log_info (_("line shortened due to embedded Nul character\n"));
196 if (line
[n
-1] == '\n')
198 rc
= assuan_write_line (ctx
, line
);
201 log_info (_("sending line failed: %s\n"), assuan_strerror (rc
) );
204 if (*line
== '#' || !*line
)
205 continue; /* Don't expect a response for a coment line. */
207 rc
= read_and_print_response (ctx
);
209 log_info (_("receiving line failed: %s\n"), assuan_strerror (rc
) );
213 log_info ("closing connection to agent\n");
219 /* Read all response lines from server and print them. Returns 0 on
220 success or an assuan error code. */
222 read_and_print_response (assuan_context_t ctx
)
233 rc
= assuan_read_line (ctx
, &line
, &linelen
);
237 while (*line
== '#' || !linelen
);
240 && line
[0] == 'D' && line
[1] == ' ')
244 for (i
=2; i
< linelen
; )
248 printf ("D[%04X] ", i
-2);
249 for (j
=0; j
< 16 ; j
++, i
++)
254 printf (" %02X", ((unsigned char*)line
)[i
]);
260 for (j
=0; j
< 16; j
++, i
++)
262 unsigned int c
= ((unsigned char*)line
)[i
];
265 else if (isascii (c
) && isprint (c
) && !iscntrl (c
))
275 fwrite (line
, linelen
, 1, stdout
);
279 else if (linelen
>= 1
281 && (line
[1] == '\0' || line
[1] == ' '))
283 fwrite (line
, linelen
, 1, stdout
);
286 else if (linelen
>= 2
287 && line
[0] == 'O' && line
[1] == 'K'
288 && (line
[2] == '\0' || line
[2] == ' '))
290 fwrite (line
, linelen
, 1, stdout
);
294 else if (linelen
>= 3
295 && line
[0] == 'E' && line
[1] == 'R' && line
[2] == 'R'
296 && (line
[3] == '\0' || line
[3] == ' '))
298 fwrite (line
, linelen
, 1, stdout
);
302 else if (linelen
>= 7
303 && line
[0] == 'I' && line
[1] == 'N' && line
[2] == 'Q'
304 && line
[3] == 'U' && line
[4] == 'I' && line
[5] == 'R'
306 && (line
[7] == '\0' || line
[7] == ' '))
308 fwrite (line
, linelen
, 1, stdout
);
312 else if (linelen
>= 3
313 && line
[0] == 'E' && line
[1] == 'N' && line
[2] == 'D'
314 && (line
[3] == '\0' || line
[3] == ' '))
316 fwrite (line
, linelen
, 1, stdout
);
318 /* Received from server, thus more responses are expected. */
321 return ASSUAN_Invalid_Response
;
328 /* Connect to teh agebnt and send the standard options. */
329 static assuan_context_t
334 assuan_context_t ctx
;
336 infostr
= getenv ("GPG_AGENT_INFO");
337 if (!infostr
|| !*infostr
)
341 /* Check whether we can connect at the standard socket. */
342 sockname
= make_filename (opt
.homedir
, "S.gpg-agent", NULL
);
343 rc
= assuan_socket_connect (&ctx
, sockname
, 0);
351 infostr
= xstrdup (infostr
);
352 if ( !(p
= strchr (infostr
, PATHSEP_C
)) || p
== infostr
)
354 log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
360 while (*p
&& *p
!= ':')
362 prot
= *p
? atoi (p
+1) : 0;
365 log_error (_("gpg-agent protocol version %d is not supported\n"),
371 rc
= assuan_socket_connect (&ctx
, infostr
, pid
);
377 log_error ("can't connect to the agent: %s\n", assuan_strerror (rc
));
382 log_info ("connection to agent established\n");
384 rc
= assuan_transact (ctx
, "RESET", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
387 log_error (_("error sending %s command: %s\n"), "RESET",
388 assuan_strerror (rc
));
392 rc
= send_pinentry_environment (ctx
, GPG_ERR_SOURCE_DEFAULT
,
393 NULL
, NULL
, NULL
, NULL
, NULL
);
396 log_error (_("error sending standard options: %s\n"), gpg_strerror (rc
));