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
30 #include "../common/util.h"
31 #include "../common/asshelp.h"
35 /* Constants to identify the commands and options. */
36 enum cmd_and_opt_values
48 /* The list of commands and options. */
49 static ARGPARSE_OPTS opts[] =
51 { 301, NULL, 0, N_("@\nOptions:\n ") },
53 { oVerbose, "verbose", 0, N_("verbose") },
54 { oQuiet, "quiet", 0, N_("quiet") },
57 { oNoVerbose, "no-verbose", 0, "@"},
58 { oHomedir, "homedir", 2, "@" },
63 /* We keep all global options in the structure OPT. */
66 int verbose; /* Verbosity level. */
67 int quiet; /* Be extra quiet. */
68 const char *homedir; /* Configuration directory name */
73 /*-- local prototypes --*/
74 static int read_and_print_response (assuan_context_t ctx);
75 static assuan_context_t start_agent (void);
80 /* Print usage information and and provide strings for help. */
82 my_strusage( int level )
88 case 11: p = "gpg-connect-agent (GnuPG)";
90 case 13: p = VERSION; break;
91 case 17: p = PRINTABLE_OS_NAME; break;
92 case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
95 case 40: p = _("Usage: gpg-connect-agent [options] (-h for help)");
98 p = _("Syntax: gpg-connect-agent [options]\n"
99 "Connect to a running agent and send commands\n");
101 case 31: p = "\nHome: "; break;
102 case 32: p = opt.homedir; break;
103 case 33: p = "\n"; break;
105 default: p = NULL; break;
111 /* Initialize the gettext system. */
115 #ifdef USE_SIMPLE_GETTEXT
116 set_gettext_file (PACKAGE_GT);
119 setlocale (LC_ALL, "" );
120 bindtextdomain (PACKAGE_GT, LOCALEDIR);
121 textdomain (PACKAGE_GT);
127 /* gpg-connect-agent's entry point. */
129 main (int argc, char **argv)
133 int no_more_options = 0;
134 assuan_context_t ctx;
139 set_strusage (my_strusage);
140 log_set_prefix ("gpg-connect-agent", 1);
144 opt.homedir = default_homedir ();
146 /* Parse the command line. */
149 pargs.flags = 1; /* Do not remove the args. */
150 while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts))
154 case oQuiet: opt.quiet = 1; break;
155 case oVerbose: opt.verbose++; break;
156 case oNoVerbose: opt.verbose = 0; break;
157 case oHomedir: opt.homedir = pargs.r.ret_str; break;
159 default: pargs.err = 2; break;
163 if (log_get_errorcount (0))
166 fname = argc ? *argv : NULL;
168 ctx = start_agent ();
177 n = read_line (stdin, &line, &linesize, &maxlength);
180 log_error (_("error reading input: %s\n"), strerror (errno));
187 log_error (_("line too long - skipped\n"));
190 if (memchr (line, 0, n))
191 log_info (_("line shortened due to embedded Nul character\n"));
192 if (line[n-1] == '\n')
194 rc = assuan_write_line (ctx, line);
197 log_info (_("sending line failed: %s\n"), assuan_strerror (rc) );
200 if (*line == '#' || !*line)
201 continue; /* Don't expect a response for a coment line. */
203 rc = read_and_print_response (ctx);
205 log_info (_("receiving line failed: %s\n"), assuan_strerror (rc) );
209 log_info ("closing connection to agent\n");
215 /* Read all response lines from server and print them. Returns 0 on
216 success or an assuan error code. */
218 read_and_print_response (assuan_context_t ctx)
228 rc = assuan_read_line (ctx, &line, &linelen);
232 while (*line == '#' || !linelen);
235 && line[0] == 'D' && line[1] == ' ')
237 fwrite (line, linelen, 1, stdout);
240 else if (linelen >= 1
242 && (line[1] == '\0' || line[1] == ' '))
244 fwrite (line, linelen, 1, stdout);
247 else if (linelen >= 2
248 && line[0] == 'O' && line[1] == 'K'
249 && (line[2] == '\0' || line[2] == ' '))
251 fwrite (line, linelen, 1, stdout);
255 else if (linelen >= 3
256 && line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
257 && (line[3] == '\0' || line[3] == ' '))
259 fwrite (line, linelen, 1, stdout);
263 else if (linelen >= 7
264 && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
265 && line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
267 && (line[7] == '\0' || line[7] == ' '))
269 fwrite (line, linelen, 1, stdout);
273 else if (linelen >= 3
274 && line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
275 && (line[3] == '\0' || line[3] == ' '))
277 fwrite (line, linelen, 1, stdout);
279 /* Received from server, thus more responses are expected. */
282 return ASSUAN_Invalid_Response;
289 /* Connect to teh agebnt and send the standard options. */
290 static assuan_context_t
295 assuan_context_t ctx;
297 infostr = getenv ("GPG_AGENT_INFO");
298 if (!infostr || !*infostr)
302 /* Check whether we can connect at the standard socket. */
303 sockname = make_filename (opt.homedir, "S.gpg-agent", NULL);
304 rc = assuan_socket_connect (&ctx, sockname, 0);
312 infostr = xstrdup (infostr);
313 if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
315 log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
321 while (*p && *p != ':')
323 prot = *p? atoi (p+1) : 0;
326 log_error (_("gpg-agent protocol version %d is not supported\n"),
332 rc = assuan_socket_connect (&ctx, infostr, pid);
338 log_error ("can't connect to the agent: %s\n", assuan_strerror (rc));
343 log_info ("connection to agent established\n");
345 rc = assuan_transact (ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
348 log_error (_("error sending %s command: %s\n"), "RESET",
349 assuan_strerror (rc));
353 rc = send_pinentry_environment (ctx, GPG_ERR_SOURCE_DEFAULT,
354 NULL, NULL, NULL, NULL, NULL);
357 log_error (_("error sending standard options: %s\n"), gpg_strerror (rc));