49
50
#define LOCK_TIMEOUT (1*60)
52
static assuan_context_t entry_ctx = NULL;
52
/* The assuan context of the current pinentry. */
53
static assuan_context_t entry_ctx;
55
/* The control variable of the connection owning the current pinentry.
56
This is only valid if ENTRY_CTX is not NULL. Note, that we care
57
only about the value of the pointer and that it should never be
59
static ctrl_t entry_owner;
61
/* A mutex used to serialize access to the pinentry. */
54
62
static pth_mutex_t entry_lock;
57
/* data to be passed to our callbacks */
64
/* The thread ID of the popup working thread. */
65
static pth_t popup_tid;
67
/* A flag used in communication between the popup working thread and
69
static int popup_finished;
73
/* Data to be passed to our callbacks, */
61
78
unsigned char *buffer;
102
119
log_info ("agent_query_dump_state: entry_lock=");
103
120
dump_mutex_state (&entry_lock);
104
121
log_printf ("\n");
105
log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld\n",
106
entry_ctx, (long)assuan_get_pid (entry_ctx));
122
log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%p\n",
123
entry_ctx, (long)assuan_get_pid (entry_ctx), popup_tid);
126
/* Called to make sure that a popup window owned by the current
127
connection gets closed. */
129
agent_reset_query (ctrl_t ctrl)
131
if (entry_ctx && popup_tid && entry_owner == ctrl)
133
agent_popup_message_stop (ctrl);
588
/* The thread running the popup message. */
590
popup_message_thread (void *arg)
592
assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL);
598
/* Pop up a message window similar to the confirm one but keep it open
599
until agent_popup_message_stop has been called. It is crucial for
600
the caller to make sure that the stop function gets called as soon
601
as the message is not anymore required becuase the message is
602
system modal and all other attempts to use the pinentry will fail
603
(after a timeout). */
605
agent_popup_message_start (ctrl_t ctrl, const char *desc,
606
const char *ok_btn, const char *cancel_btn)
609
char line[ASSUAN_LINELENGTH];
612
rc = start_pinentry (ctrl);
617
snprintf (line, DIM(line)-1, "SETDESC %s", desc);
619
snprintf (line, DIM(line)-1, "RESET");
620
line[DIM(line)-1] = 0;
621
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
623
return unlock_pinentry (map_assuan_err (rc));
627
snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
628
line[DIM(line)-1] = 0;
629
rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
631
return unlock_pinentry (map_assuan_err (rc));
635
snprintf (line, DIM(line)-1, "SETCANCEL %s", cancel_btn);
636
line[DIM(line)-1] = 0;
637
rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
639
return unlock_pinentry (map_assuan_err (rc));
642
tattr = pth_attr_new();
643
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
644
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
645
pth_attr_set (tattr, PTH_ATTR_NAME, "popup-message");
648
popup_tid = pth_spawn (tattr, popup_message_thread, NULL);
651
rc = gpg_error_from_errno (errno);
652
log_error ("error spawning popup message handler: %s\n",
654
pth_attr_destroy (tattr);
655
return unlock_pinentry (rc);
657
pth_attr_destroy (tattr);
662
/* Close a popup window. */
664
agent_popup_message_stop (ctrl_t ctrl)
669
if (!popup_tid || !entry_ctx)
671
log_debug ("agent_popup_message_stop called with no active popup\n");
675
pid = assuan_get_pid (entry_ctx);
676
if (pid == (pid_t)(-1))
677
; /* No pid available can't send a kill. */
678
else if (popup_finished)
679
; /* Already finished and ready for joining. */
680
else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
681
{ /* The daemon already died. No need to send a kill. However
682
because we already waited for the process, we need to tell
683
assuan that it should not wait again (done by
686
assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
691
/* Now wait for the thread to terminate. */
692
rc = pth_join (popup_tid, NULL);
694
log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
699
/* Now we can close the connection. */