Line data Source code
1 : /* asshelp.c - Helper functions for Assuan
2 : * Copyright (C) 2002, 2004, 2007, 2009, 2010 Free Software Foundation, Inc.
3 : *
4 : * This file is part of GnuPG.
5 : *
6 : * This file is free software; you can redistribute it and/or modify
7 : * it under the terms of either
8 : *
9 : * - the GNU Lesser General Public License as published by the Free
10 : * Software Foundation; either version 3 of the License, or (at
11 : * your option) any later version.
12 : *
13 : * or
14 : *
15 : * - the GNU General Public License as published by the Free
16 : * Software Foundation; either version 2 of the License, or (at
17 : * your option) any later version.
18 : *
19 : * or both in parallel, as here.
20 : *
21 : * This file is distributed in the hope that it will be useful,
22 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 : * GNU General Public License for more details.
25 : *
26 : * You should have received a copy of the GNU General Public License
27 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
28 : */
29 :
30 : #include <config.h>
31 : #include <stdio.h>
32 : #include <stdlib.h>
33 : #include <string.h>
34 : #include <unistd.h>
35 : #include <errno.h>
36 : #ifdef HAVE_LOCALE_H
37 : #include <locale.h>
38 : #endif
39 :
40 : #include "i18n.h"
41 : #include "util.h"
42 : #include "exechelp.h"
43 : #include "sysutils.h"
44 : #include "status.h"
45 : #include "asshelp.h"
46 :
47 : /* The type we use for lock_agent_spawning. */
48 : #ifdef HAVE_W32_SYSTEM
49 : # define lock_spawn_t HANDLE
50 : #else
51 : # define lock_spawn_t dotlock_t
52 : #endif
53 :
54 : /* The time we wait until the agent or the dirmngr are ready for
55 : operation after we started them before giving up. */
56 : #ifdef HAVE_W32CE_SYSTEM
57 : # define SECS_TO_WAIT_FOR_AGENT 30
58 : # define SECS_TO_WAIT_FOR_DIRMNGR 30
59 : #else
60 : # define SECS_TO_WAIT_FOR_AGENT 5
61 : # define SECS_TO_WAIT_FOR_DIRMNGR 5
62 : #endif
63 :
64 : /* A bitfield that specifies the assuan categories to log. This is
65 : identical to the default log handler of libassuan. We need to do
66 : it ourselves because we use a custom log handler and want to use
67 : the same assuan variables to select the categories to log. */
68 : static int log_cats;
69 : #define TEST_LOG_CAT(x) (!! (log_cats & (1 << (x - 1))))
70 :
71 :
72 : static int
73 37077 : my_libassuan_log_handler (assuan_context_t ctx, void *hook,
74 : unsigned int cat, const char *msg)
75 : {
76 : unsigned int dbgval;
77 :
78 : (void)ctx;
79 :
80 37077 : if (! TEST_LOG_CAT (cat))
81 7734 : return 0;
82 :
83 29343 : dbgval = hook? *(unsigned int*)hook : 0;
84 29343 : if (!(dbgval & 1024))
85 29343 : return 0; /* Assuan debugging is not enabled. */
86 :
87 0 : if (msg)
88 0 : log_string (GPGRT_LOG_DEBUG, msg);
89 :
90 0 : return 1;
91 : }
92 :
93 :
94 : /* Setup libassuan to use our own logging functions. Should be used
95 : early at startup. */
96 : void
97 1305 : setup_libassuan_logging (unsigned int *debug_var_address)
98 : {
99 : char *flagstr;
100 :
101 1305 : flagstr = getenv ("ASSUAN_DEBUG");
102 1305 : if (flagstr)
103 0 : log_cats = atoi (flagstr);
104 : else /* Default to log the control channel. */
105 1305 : log_cats = (1 << (ASSUAN_LOG_CONTROL - 1));
106 1305 : assuan_set_log_cb (my_libassuan_log_handler, debug_var_address);
107 1305 : }
108 :
109 : /* Change the Libassuan log categories to those given by NEWCATS.
110 : NEWCATS is 0 the default category of ASSUAN_LOG_CONTROL is
111 : selected. Note, that setup_libassuan_logging overrides the values
112 : given here. */
113 : void
114 0 : set_libassuan_log_cats (unsigned int newcats)
115 : {
116 0 : if (newcats)
117 0 : log_cats = newcats;
118 : else /* Default to log the control channel. */
119 0 : log_cats = (1 << (ASSUAN_LOG_CONTROL - 1));
120 0 : }
121 :
122 :
123 :
124 : static gpg_error_t
125 2145 : send_one_option (assuan_context_t ctx, gpg_err_source_t errsource,
126 : const char *name, const char *value, int use_putenv)
127 : {
128 : gpg_error_t err;
129 : char *optstr;
130 :
131 : (void)errsource;
132 :
133 2145 : if (!value || !*value)
134 0 : err = 0; /* Avoid sending empty strings. */
135 2145 : else if (asprintf (&optstr, "OPTION %s%s=%s",
136 : use_putenv? "putenv=":"", name, value) < 0)
137 0 : err = gpg_error_from_syserror ();
138 : else
139 : {
140 2145 : err = assuan_transact (ctx, optstr, NULL, NULL, NULL, NULL, NULL, NULL);
141 2145 : xfree (optstr);
142 : }
143 :
144 2145 : return err;
145 : }
146 :
147 :
148 : /* Send the assuan commands pertaining to the pinentry environment. The
149 : OPT_* arguments are optional and may be used to override the
150 : defaults taken from the current locale. */
151 : gpg_error_t
152 393 : send_pinentry_environment (assuan_context_t ctx,
153 : gpg_err_source_t errsource,
154 : const char *opt_lc_ctype,
155 : const char *opt_lc_messages,
156 : session_env_t session_env)
157 :
158 : {
159 393 : gpg_error_t err = 0;
160 : #if defined(HAVE_SETLOCALE)
161 393 : char *old_lc = NULL;
162 : #endif
163 393 : char *dft_lc = NULL;
164 : const char *dft_ttyname;
165 : int iterator;
166 : const char *name, *assname, *value;
167 : int is_default;
168 :
169 393 : iterator = 0;
170 4716 : while ((name = session_env_list_stdenvnames (&iterator, &assname)))
171 : {
172 3930 : value = session_env_getenv_or_default (session_env, name, NULL);
173 3930 : if (!value)
174 2395 : continue;
175 :
176 1535 : if (assname)
177 1142 : err = send_one_option (ctx, errsource, assname, value, 0);
178 : else
179 : {
180 393 : err = send_one_option (ctx, errsource, name, value, 1);
181 393 : if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
182 0 : err = 0; /* Server too old; can't pass the new envvars. */
183 : }
184 1535 : if (err)
185 0 : return err;
186 : }
187 :
188 :
189 393 : dft_ttyname = session_env_getenv_or_default (session_env, "GPG_TTY",
190 : &is_default);
191 393 : if (dft_ttyname && !is_default)
192 0 : dft_ttyname = NULL; /* We need the default value. */
193 :
194 : /* Send the value for LC_CTYPE. */
195 : #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
196 393 : old_lc = setlocale (LC_CTYPE, NULL);
197 393 : if (old_lc)
198 : {
199 393 : old_lc = xtrystrdup (old_lc);
200 393 : if (!old_lc)
201 0 : return gpg_error_from_syserror ();
202 : }
203 393 : dft_lc = setlocale (LC_CTYPE, "");
204 : #endif
205 393 : if (opt_lc_ctype || (dft_ttyname && dft_lc))
206 : {
207 305 : err = send_one_option (ctx, errsource, "lc-ctype",
208 : opt_lc_ctype ? opt_lc_ctype : dft_lc, 0);
209 : }
210 : #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
211 393 : if (old_lc)
212 : {
213 393 : setlocale (LC_CTYPE, old_lc);
214 393 : xfree (old_lc);
215 : }
216 : #endif
217 393 : if (err)
218 0 : return err;
219 :
220 : /* Send the value for LC_MESSAGES. */
221 : #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
222 393 : old_lc = setlocale (LC_MESSAGES, NULL);
223 393 : if (old_lc)
224 : {
225 393 : old_lc = xtrystrdup (old_lc);
226 393 : if (!old_lc)
227 0 : return gpg_error_from_syserror ();
228 : }
229 393 : dft_lc = setlocale (LC_MESSAGES, "");
230 : #endif
231 393 : if (opt_lc_messages || (dft_ttyname && dft_lc))
232 : {
233 305 : err = send_one_option (ctx, errsource, "lc-messages",
234 : opt_lc_messages ? opt_lc_messages : dft_lc, 0);
235 : }
236 : #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
237 393 : if (old_lc)
238 : {
239 393 : setlocale (LC_MESSAGES, old_lc);
240 393 : xfree (old_lc);
241 : }
242 : #endif
243 393 : if (err)
244 0 : return err;
245 :
246 393 : return 0;
247 : }
248 :
249 :
250 : /* Lock a spawning process. The caller needs to provide the address
251 : of a variable to store the lock information and the name or the
252 : process. */
253 : static gpg_error_t
254 1 : lock_spawning (lock_spawn_t *lock, const char *homedir, const char *name,
255 : int verbose)
256 : {
257 : #ifdef HAVE_W32_SYSTEM
258 : int waitrc;
259 : int timeout = (!strcmp (name, "agent")
260 : ? SECS_TO_WAIT_FOR_AGENT
261 : : SECS_TO_WAIT_FOR_DIRMNGR);
262 :
263 : (void)homedir; /* Not required. */
264 :
265 : *lock = CreateMutexW
266 : (NULL, FALSE,
267 : !strcmp (name, "agent")? L"spawn_"GNUPG_NAME"_agent_sentinel":
268 : !strcmp (name, "dirmngr")? L"spawn_"GNUPG_NAME"_dirmngr_sentinel":
269 : /* */ L"spawn_"GNUPG_NAME"_unknown_sentinel");
270 : if (!*lock)
271 : {
272 : log_error ("failed to create the spawn_%s mutex: %s\n",
273 : name, w32_strerror (-1));
274 : return gpg_error (GPG_ERR_GENERAL);
275 : }
276 :
277 : retry:
278 : waitrc = WaitForSingleObject (*lock, 1000);
279 : if (waitrc == WAIT_OBJECT_0)
280 : return 0;
281 :
282 : if (waitrc == WAIT_TIMEOUT && timeout)
283 : {
284 : timeout--;
285 : if (verbose)
286 : log_info ("another process is trying to start the %s ... (%ds)\n",
287 : name, timeout);
288 : goto retry;
289 : }
290 : if (waitrc == WAIT_TIMEOUT)
291 : log_info ("error waiting for the spawn_%s mutex: timeout\n", name);
292 : else
293 : log_info ("error waiting for the spawn_%s mutex: (code=%d) %s\n",
294 : name, waitrc, w32_strerror (-1));
295 : return gpg_error (GPG_ERR_GENERAL);
296 : #else /*!HAVE_W32_SYSTEM*/
297 : char *fname;
298 :
299 : (void)verbose;
300 :
301 1 : *lock = NULL;
302 :
303 1 : fname = make_absfilename_try
304 : (homedir,
305 1 : !strcmp (name, "agent")? "gnupg_spawn_agent_sentinel":
306 0 : !strcmp (name, "dirmngr")? "gnupg_spawn_dirmngr_sentinel":
307 : /* */ "gnupg_spawn_unknown_sentinel",
308 : NULL);
309 1 : if (!fname)
310 0 : return gpg_error_from_syserror ();
311 :
312 1 : *lock = dotlock_create (fname, 0);
313 1 : xfree (fname);
314 1 : if (!*lock)
315 0 : return gpg_error_from_syserror ();
316 :
317 : /* FIXME: We should use a timeout of 5000 here - however
318 : make_dotlock does not yet support values other than -1 and 0. */
319 1 : if (dotlock_take (*lock, -1))
320 0 : return gpg_error_from_syserror ();
321 :
322 1 : return 0;
323 : #endif /*!HAVE_W32_SYSTEM*/
324 : }
325 :
326 :
327 : /* Unlock the spawning process. */
328 : static void
329 1 : unlock_spawning (lock_spawn_t *lock, const char *name)
330 : {
331 1 : if (*lock)
332 : {
333 : #ifdef HAVE_W32_SYSTEM
334 : if (!ReleaseMutex (*lock))
335 : log_error ("failed to release the spawn_%s mutex: %s\n",
336 : name, w32_strerror (-1));
337 : CloseHandle (*lock);
338 : #else /*!HAVE_W32_SYSTEM*/
339 : (void)name;
340 1 : dotlock_destroy (*lock);
341 : #endif /*!HAVE_W32_SYSTEM*/
342 1 : *lock = NULL;
343 : }
344 1 : }
345 :
346 : /* Try to connect to the agent via socket or start it if it is not
347 : running and AUTOSTART is set. Handle the server's initial
348 : greeting. Returns a new assuan context at R_CTX or an error
349 : code. */
350 : gpg_error_t
351 393 : start_new_gpg_agent (assuan_context_t *r_ctx,
352 : gpg_err_source_t errsource,
353 : const char *homedir,
354 : const char *agent_program,
355 : const char *opt_lc_ctype,
356 : const char *opt_lc_messages,
357 : session_env_t session_env,
358 : int autostart, int verbose, int debug,
359 : gpg_error_t (*status_cb)(ctrl_t, int, ...),
360 : ctrl_t status_cb_arg)
361 : {
362 : gpg_error_t err;
363 : assuan_context_t ctx;
364 393 : int did_success_msg = 0;
365 : char *sockname;
366 : const char *argv[6];
367 :
368 393 : *r_ctx = NULL;
369 :
370 393 : err = assuan_new (&ctx);
371 393 : if (err)
372 : {
373 0 : log_error ("error allocating assuan context: %s\n", gpg_strerror (err));
374 0 : return err;
375 : }
376 :
377 393 : sockname = make_absfilename (homedir, GPG_AGENT_SOCK_NAME, NULL);
378 393 : err = assuan_socket_connect (ctx, sockname, 0, 0);
379 393 : if (err && autostart)
380 : {
381 : char *abs_homedir;
382 : lock_spawn_t lock;
383 1 : char *program = NULL;
384 1 : const char *program_arg = NULL;
385 : char *p;
386 : const char *s;
387 : int i;
388 :
389 : /* With no success start a new server. */
390 1 : if (!agent_program || !*agent_program)
391 0 : agent_program = gnupg_module_name (GNUPG_MODULE_NAME_AGENT);
392 1 : else if ((s=strchr (agent_program, '|')) && s[1] == '-' && s[2]=='-')
393 : {
394 : /* Hack to insert an additional option on the command line. */
395 1 : program = xtrystrdup (agent_program);
396 1 : if (!program)
397 : {
398 0 : gpg_error_t tmperr = gpg_err_make (errsource,
399 : gpg_err_code_from_syserror ());
400 0 : xfree (sockname);
401 0 : assuan_release (ctx);
402 0 : return tmperr;
403 : }
404 1 : p = strchr (program, '|');
405 1 : *p++ = 0;
406 1 : program_arg = p;
407 : }
408 :
409 1 : if (verbose)
410 1 : log_info (_("no running gpg-agent - starting '%s'\n"),
411 : agent_program);
412 :
413 1 : if (status_cb)
414 0 : status_cb (status_cb_arg, STATUS_PROGRESS,
415 : "starting_agent ? 0 0", NULL);
416 :
417 : /* We better pass an absolute home directory to the agent just
418 : in case gpg-agent does not convert the passed name to an
419 : absolute one (which it should do). */
420 1 : abs_homedir = make_absfilename_try (homedir, NULL);
421 1 : if (!abs_homedir)
422 : {
423 0 : gpg_error_t tmperr = gpg_err_make (errsource,
424 : gpg_err_code_from_syserror ());
425 0 : log_error ("error building filename: %s\n",gpg_strerror (tmperr));
426 0 : xfree (sockname);
427 0 : assuan_release (ctx);
428 0 : xfree (program);
429 0 : return tmperr;
430 : }
431 :
432 1 : if (fflush (NULL))
433 : {
434 0 : gpg_error_t tmperr = gpg_err_make (errsource,
435 : gpg_err_code_from_syserror ());
436 0 : log_error ("error flushing pending output: %s\n",
437 0 : strerror (errno));
438 0 : xfree (sockname);
439 0 : assuan_release (ctx);
440 0 : xfree (abs_homedir);
441 0 : xfree (program);
442 0 : return tmperr;
443 : }
444 :
445 : /* If the agent has been configured for use with a standard
446 : socket, an environment variable is not required and thus
447 : we we can savely start the agent here. */
448 1 : i = 0;
449 1 : argv[i++] = "--homedir";
450 1 : argv[i++] = abs_homedir;
451 1 : argv[i++] = "--use-standard-socket";
452 1 : if (program_arg)
453 1 : argv[i++] = program_arg;
454 1 : argv[i++] = "--daemon";
455 1 : argv[i++] = NULL;
456 :
457 1 : if (!(err = lock_spawning (&lock, homedir, "agent", verbose))
458 1 : && assuan_socket_connect (ctx, sockname, 0, 0))
459 : {
460 1 : err = gnupg_spawn_process_detached (program? program : agent_program,
461 : argv, NULL);
462 1 : if (err)
463 0 : log_error ("failed to start agent '%s': %s\n",
464 : agent_program, gpg_strerror (err));
465 : else
466 : {
467 1 : for (i=0; i < SECS_TO_WAIT_FOR_AGENT; i++)
468 : {
469 1 : if (verbose)
470 1 : log_info (_("waiting for the agent to come up ... (%ds)\n"),
471 : SECS_TO_WAIT_FOR_AGENT - i);
472 1 : gnupg_sleep (1);
473 1 : err = assuan_socket_connect (ctx, sockname, 0, 0);
474 1 : if (!err)
475 : {
476 1 : if (verbose)
477 : {
478 1 : log_info (_("connection to agent established\n"));
479 1 : did_success_msg = 1;
480 : }
481 1 : break;
482 : }
483 : }
484 : }
485 : }
486 :
487 1 : unlock_spawning (&lock, "agent");
488 1 : xfree (abs_homedir);
489 1 : xfree (program);
490 : }
491 393 : xfree (sockname);
492 393 : if (err)
493 : {
494 0 : if (autostart || gpg_err_code (err) != GPG_ERR_ASS_CONNECT_FAILED)
495 0 : log_error ("can't connect to the agent: %s\n", gpg_strerror (err));
496 0 : assuan_release (ctx);
497 0 : return gpg_err_make (errsource, GPG_ERR_NO_AGENT);
498 : }
499 :
500 393 : if (debug && !did_success_msg)
501 0 : log_debug (_("connection to agent established\n"));
502 :
503 393 : err = assuan_transact (ctx, "RESET",
504 : NULL, NULL, NULL, NULL, NULL, NULL);
505 393 : if (!err)
506 : {
507 393 : err = send_pinentry_environment (ctx, errsource,
508 : opt_lc_ctype, opt_lc_messages,
509 : session_env);
510 393 : if (gpg_err_code (err) == GPG_ERR_FORBIDDEN
511 0 : && gpg_err_source (err) == GPG_ERR_SOURCE_GPGAGENT)
512 : {
513 : /* Check whether we are in restricted mode. */
514 0 : if (!assuan_transact (ctx, "GETINFO restricted",
515 : NULL, NULL, NULL, NULL, NULL, NULL))
516 : {
517 0 : if (verbose)
518 0 : log_info (_("connection to agent is in restricted mode\n"));
519 0 : err = 0;
520 : }
521 : }
522 : }
523 393 : if (err)
524 : {
525 0 : assuan_release (ctx);
526 0 : return err;
527 : }
528 :
529 393 : *r_ctx = ctx;
530 393 : return 0;
531 : }
532 :
533 :
534 : /* Try to connect to the dirmngr via a socket. On platforms
535 : supporting it, start it up if needed and if AUTOSTART is true.
536 : Returns a new assuan context at R_CTX or an error code. */
537 : gpg_error_t
538 0 : start_new_dirmngr (assuan_context_t *r_ctx,
539 : gpg_err_source_t errsource,
540 : const char *homedir,
541 : const char *dirmngr_program,
542 : int autostart,
543 : int verbose, int debug,
544 : gpg_error_t (*status_cb)(ctrl_t, int, ...),
545 : ctrl_t status_cb_arg)
546 : {
547 : gpg_error_t err;
548 : assuan_context_t ctx;
549 : const char *sockname;
550 0 : int did_success_msg = 0;
551 :
552 0 : *r_ctx = NULL;
553 :
554 0 : err = assuan_new (&ctx);
555 0 : if (err)
556 : {
557 0 : log_error ("error allocating assuan context: %s\n", gpg_strerror (err));
558 0 : return err;
559 : }
560 :
561 0 : sockname = dirmngr_user_socket_name ();
562 0 : if (sockname)
563 : {
564 : /* First try the local socket name and only if that fails try
565 : the system socket. */
566 0 : err = assuan_socket_connect (ctx, sockname, 0, 0);
567 0 : if (err)
568 0 : sockname = dirmngr_sys_socket_name ();
569 : }
570 : else
571 0 : sockname = dirmngr_sys_socket_name ();
572 :
573 0 : err = assuan_socket_connect (ctx, sockname, 0, 0);
574 :
575 : #ifdef USE_DIRMNGR_AUTO_START
576 0 : if (err && autostart)
577 : {
578 : lock_spawn_t lock;
579 : const char *argv[4];
580 0 : int try_system_daemon = 0;
581 : char *abs_homedir;
582 :
583 : /* No connection: Try start a new Dirmngr. On Windows this will
584 : fail because the Dirmngr is expected to be a system service.
585 : However on WinCE we don't distinguish users and thus we can
586 : start it. */
587 :
588 : /* We prefer to start it as a user daemon. */
589 0 : sockname = dirmngr_user_socket_name ();
590 0 : if (!sockname)
591 : {
592 0 : sockname = dirmngr_sys_socket_name ();
593 0 : try_system_daemon = 1;
594 : }
595 :
596 0 : if (!dirmngr_program || !*dirmngr_program)
597 0 : dirmngr_program = gnupg_module_name (GNUPG_MODULE_NAME_DIRMNGR);
598 :
599 0 : if (verbose)
600 0 : log_info (_("no running Dirmngr - starting '%s'\n"),
601 : dirmngr_program);
602 :
603 0 : if (status_cb)
604 0 : status_cb (status_cb_arg, STATUS_PROGRESS,
605 : "starting_dirmngr ? 0 0", NULL);
606 :
607 0 : abs_homedir = make_absfilename (homedir, NULL);
608 0 : if (!abs_homedir)
609 : {
610 0 : gpg_error_t tmperr = gpg_err_make (errsource,
611 : gpg_err_code_from_syserror ());
612 0 : log_error ("error building filename: %s\n",gpg_strerror (tmperr));
613 0 : assuan_release (ctx);
614 0 : return tmperr;
615 : }
616 :
617 0 : if (fflush (NULL))
618 : {
619 0 : gpg_error_t tmperr = gpg_err_make (errsource,
620 : gpg_err_code_from_syserror ());
621 0 : log_error ("error flushing pending output: %s\n",
622 0 : strerror (errno));
623 0 : assuan_release (ctx);
624 0 : return tmperr;
625 : }
626 :
627 0 : argv[0] = "--daemon";
628 0 : if (try_system_daemon)
629 0 : argv[1] = NULL;
630 : else
631 : { /* Try starting as user daemon - dirmngr does this if the
632 : home directory is given on the command line. */
633 0 : argv[1] = "--homedir";
634 0 : argv[2] = abs_homedir;
635 0 : argv[3] = NULL;
636 : }
637 :
638 : /* On the use of HOMEDIR for locking: Under Windows HOMEDIR is
639 : not used thus it does not matter. Under Unix we should
640 : TRY_SYSTEM_DAEMON should never be true because
641 : dirmngr_user_socket_name() won't return NULL. */
642 :
643 0 : if (!(err = lock_spawning (&lock, homedir, "dirmngr", verbose))
644 0 : && assuan_socket_connect (ctx, sockname, 0, 0))
645 : {
646 0 : err = gnupg_spawn_process_detached (dirmngr_program, argv, NULL);
647 0 : if (err)
648 0 : log_error ("failed to start the dirmngr '%s': %s\n",
649 : dirmngr_program, gpg_strerror (err));
650 : else
651 : {
652 : int i;
653 :
654 0 : for (i=0; i < SECS_TO_WAIT_FOR_DIRMNGR; i++)
655 : {
656 0 : if (verbose)
657 0 : log_info (_("waiting for the dirmngr "
658 : "to come up ... (%ds)\n"),
659 : SECS_TO_WAIT_FOR_DIRMNGR - i);
660 0 : gnupg_sleep (1);
661 0 : err = assuan_socket_connect (ctx, sockname, 0, 0);
662 0 : if (!err)
663 : {
664 0 : if (verbose)
665 : {
666 0 : log_info (_("connection to the dirmngr"
667 : " established\n"));
668 0 : did_success_msg = 1;
669 : }
670 0 : break;
671 : }
672 : }
673 : }
674 : }
675 :
676 0 : unlock_spawning (&lock, "dirmngr");
677 0 : xfree (abs_homedir);
678 : }
679 : #else
680 : (void)homedir;
681 : (void)dirmngr_program;
682 : (void)verbose;
683 : (void)status_cb;
684 : (void)status_cb_arg;
685 : #endif /*USE_DIRMNGR_AUTO_START*/
686 :
687 0 : if (err)
688 : {
689 0 : if (autostart || gpg_err_code (err) != GPG_ERR_ASS_CONNECT_FAILED)
690 0 : log_error ("connecting dirmngr at '%s' failed: %s\n",
691 : sockname, gpg_strerror (err));
692 0 : assuan_release (ctx);
693 0 : return gpg_err_make (errsource, GPG_ERR_NO_DIRMNGR);
694 : }
695 :
696 0 : if (debug && !did_success_msg)
697 0 : log_debug (_("connection to the dirmngr established\n"));
698 :
699 0 : *r_ctx = ctx;
700 0 : return 0;
701 : }
|