1 /* asshelp.c - Helper functions for Assuan
2 * Copyright (C) 2002, 2004 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 3 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, see <http://www.gnu.org/licenses/>.
34 #include "errors.h" /* FIXME: This one conatisn only status code - rename it*/
39 send_one_option (assuan_context_t ctx
, gpg_err_source_t errsource
,
40 const char *name
, const char *value
)
45 if (!value
|| !*value
)
46 err
= 0; /* Avoid sending empty strings. */
47 else if (asprintf (&optstr
, "OPTION %s=%s", name
, value
) < 0)
48 err
= gpg_error_from_syserror ();
51 err
= assuan_transact (ctx
, optstr
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
59 /* Send the assuan commands pertaining to the pinenry environment. The
60 OPT_* arguments are optional and may be used to override the
61 defaults taken from the current locale. */
63 send_pinentry_environment (assuan_context_t ctx
,
64 gpg_err_source_t errsource
,
65 const char *opt_display
,
66 const char *opt_ttyname
,
67 const char *opt_ttytype
,
68 const char *opt_lc_ctype
,
69 const char *opt_lc_messages
)
72 char *dft_display
= NULL
;
73 char *dft_ttyname
= NULL
;
74 char *dft_ttytype
= NULL
;
78 /* Send the DISPLAY variable. */
79 dft_display
= getenv ("DISPLAY");
80 if (opt_display
|| dft_display
)
82 err
= send_one_option (ctx
, errsource
, "display",
83 opt_display
? opt_display
: dft_display
);
88 /* Send the name of the TTY. */
91 dft_ttyname
= getenv ("GPG_TTY");
92 if ((!dft_ttyname
|| !*dft_ttyname
) && ttyname (0))
93 dft_ttyname
= ttyname (0);
95 if (opt_ttyname
|| dft_ttyname
)
97 err
= send_one_option (ctx
, errsource
, "ttyname",
98 opt_ttyname
? opt_ttyname
: dft_ttyname
);
103 /* Send the type of the TTY. */
104 dft_ttytype
= getenv ("TERM");
105 if (opt_ttytype
|| (dft_ttyname
&& dft_ttytype
))
107 err
= send_one_option (ctx
, errsource
, "ttytype",
108 opt_ttyname
? opt_ttytype
: dft_ttytype
);
113 /* Send the value for LC_CTYPE. */
114 #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
115 old_lc
= setlocale (LC_CTYPE
, NULL
);
118 old_lc
= strdup (old_lc
);
120 return gpg_error_from_syserror ();
122 dft_lc
= setlocale (LC_CTYPE
, "");
124 if (opt_lc_ctype
|| (dft_ttyname
&& dft_lc
))
126 err
= send_one_option (ctx
, errsource
, "lc-ctype",
127 opt_lc_ctype
? opt_lc_ctype
: dft_lc
);
129 #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
132 setlocale (LC_CTYPE
, old_lc
);
139 /* Send the value for LC_MESSAGES. */
140 #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
141 old_lc
= setlocale (LC_MESSAGES
, NULL
);
144 old_lc
= strdup (old_lc
);
146 return gpg_error_from_syserror ();
148 dft_lc
= setlocale (LC_MESSAGES
, "");
150 if (opt_lc_messages
|| (dft_ttyname
&& dft_lc
))
152 err
= send_one_option (ctx
, errsource
, "lc-messages",
153 opt_lc_messages
? opt_lc_messages
: dft_lc
);
155 #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
158 setlocale (LC_MESSAGES
, old_lc
);
169 /* Try to connect to the agent via socket or fork it off and work by
170 pipes. Handle the server's initial greeting. Returns a new assuan
171 context at R_CTX or an error code. */
173 start_new_gpg_agent (assuan_context_t
*r_ctx
,
174 gpg_err_source_t errsource
,
176 const char *agent_program
,
177 const char *opt_display
,
178 const char *opt_ttyname
,
179 const char *opt_ttytype
,
180 const char *opt_lc_ctype
,
181 const char *opt_lc_messages
,
182 int verbose
, int debug
,
183 gpg_error_t (*status_cb
)(ctrl_t
, int, ...),
184 ctrl_t status_cb_arg
)
186 /* If we ever failed to connect via a socket we will force the use
187 of the pipe based server for the lifetime of the process. */
188 static int force_pipe_server
= 0;
192 assuan_context_t ctx
;
197 infostr
= force_pipe_server
? NULL
: getenv ("GPG_AGENT_INFO");
198 if (!infostr
|| !*infostr
)
202 /* First check whether we can connect at the standard
204 sockname
= make_filename (homedir
, "S.gpg-agent", NULL
);
205 rc
= assuan_socket_connect (&ctx
, sockname
, 0);
209 /* With no success start a new server. */
211 log_info (_("no running gpg-agent - starting one\n"));
214 status_cb (status_cb_arg
, STATUS_PROGRESS
,
215 "starting_agent ? 0 0", NULL
);
219 gpg_error_t tmperr
= gpg_error (gpg_err_code_from_errno (errno
));
220 log_error ("error flushing pending output: %s\n",
226 if (!agent_program
|| !*agent_program
)
227 agent_program
= gnupg_module_name (GNUPG_MODULE_NAME_AGENT
);
229 #ifdef HAVE_W32_SYSTEM
231 /* Under Windows we start the server in daemon mode. This
232 is because the default is to use the standard socket
233 and thus there is no need for the GPG_AGENT_INFO
234 envvar. This is possible as we don't have a real unix
235 domain socket but use a plain file and thus there is no
236 need to care about non-local file systems. */
239 argv
[0] = "--daemon";
240 argv
[1] = "--use-standard-socket";
243 rc
= gnupg_spawn_process_detached (agent_program
, argv
, NULL
);
245 log_debug ("failed to start agent `%s': %s\n",
246 agent_program
, gpg_strerror (rc
));
249 /* Give the agent some time to prepare itself. */
251 /* Now try again to connect the agent. */
252 rc
= assuan_socket_connect (&ctx
, sockname
, 0);
255 #else /*!HAVE_W32_SYSTEM*/
259 int no_close_list
[3];
262 if ( !(pgmname
= strrchr (agent_program
, '/')))
263 pgmname
= agent_program
;
268 argv
[1] = "--server";
272 if (log_get_fd () != -1)
273 no_close_list
[i
++] = log_get_fd ();
274 no_close_list
[i
++] = fileno (stderr
);
275 no_close_list
[i
] = -1;
277 /* Connect to the agent and perform initial handshaking. */
278 rc
= assuan_pipe_connect (&ctx
, agent_program
, argv
,
281 #endif /*!HAVE_W32_SYSTEM*/
290 infostr
= xstrdup (infostr
);
291 if ( !(p
= strchr (infostr
, PATHSEP_C
)) || p
== infostr
)
293 log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
295 force_pipe_server
= 1;
300 while (*p
&& *p
!= PATHSEP_C
)
302 prot
= *p
? atoi (p
+1) : 0;
305 log_error (_("gpg-agent protocol version %d is not supported\n"),
308 force_pipe_server
= 1;
312 rc
= assuan_socket_connect (&ctx
, infostr
, pid
);
314 if (gpg_err_code (rc
) == GPG_ERR_ASS_CONNECT_FAILED
)
316 log_info (_("can't connect to the agent - trying fall back\n"));
317 force_pipe_server
= 1;
324 log_error ("can't connect to the agent: %s\n", gpg_strerror (rc
));
325 return gpg_error (GPG_ERR_NO_AGENT
);
329 log_debug ("connection to agent established\n");
331 rc
= assuan_transact (ctx
, "RESET",
332 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
334 rc
= send_pinentry_environment (ctx
, errsource
,
335 opt_display
, opt_ttyname
, opt_ttytype
,
336 opt_lc_ctype
, opt_lc_messages
);
339 assuan_disconnect (ctx
);