Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F18826330
engine-g13.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
20 KB
Subscribers
None
engine-g13.c
View Options
/* engine-g13.c - G13 engine.
* Copyright (C) 2000 Werner Koch (dd9jn)
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2009 g10 Code GmbH
*
* This file is part of GPGME.
*
* GPGME is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* GPGME is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <https://gnu.org/licenses/>.
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#if HAVE_CONFIG_H
#include
<config.h>
#endif
#include
<stdlib.h>
#include
<string.h>
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#include
<assert.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_LOCALE_H
#include
<locale.h>
#endif
#include
<fcntl.h>
/* FIXME */
#include
<errno.h>
#include
"gpgme.h"
#include
"util.h"
#include
"ops.h"
#include
"wait.h"
#include
"priv-io.h"
#include
"sema.h"
#include
"assuan.h"
#include
"debug.h"
#include
"engine-backend.h"
typedef
struct
{
int
fd
;
/* FD we talk about. */
int
server_fd
;
/* Server FD for this connection. */
int
dir
;
/* Inbound/Outbound, maybe given implicit? */
void
*
data
;
/* Handler-specific data. */
void
*
tag
;
/* ID from the user for gpgme_remove_io_callback. */
char
server_fd_str
[
15
];
/* Same as SERVER_FD but as a string. We
need this because _gpgme_io_fd2str can't
be used on a closed descriptor. */
}
iocb_data_t
;
struct
engine_g13
{
assuan_context_t
assuan_ctx
;
int
lc_ctype_set
;
int
lc_messages_set
;
iocb_data_t
status_cb
;
struct
gpgme_io_cbs
io_cbs
;
/* User provided callbacks. */
struct
{
gpgme_assuan_data_cb_t
data_cb
;
void
*
data_cb_value
;
gpgme_assuan_inquire_cb_t
inq_cb
;
void
*
inq_cb_value
;
gpgme_assuan_status_cb_t
status_cb
;
void
*
status_cb_value
;
}
user
;
};
typedef
struct
engine_g13
*
engine_g13_t
;
static
void
g13_io_event
(
void
*
engine
,
gpgme_event_io_t
type
,
void
*
type_data
);
static
char
*
g13_get_version
(
const
char
*
file_name
)
{
return
_gpgme_get_program_version
(
file_name
?
file_name
:
_gpgme_get_default_g13_name
());
}
static
const
char
*
g13_get_req_version
(
void
)
{
return
"2.1.0"
;
}
static
void
close_notify_handler
(
int
fd
,
void
*
opaque
)
{
engine_g13_t
g13
=
opaque
;
assert
(
fd
!=
-1
);
if
(
g13
->
status_cb
.
fd
==
fd
)
{
if
(
g13
->
status_cb
.
tag
)
(
*
g13
->
io_cbs
.
remove
)
(
g13
->
status_cb
.
tag
);
g13
->
status_cb
.
fd
=
-1
;
g13
->
status_cb
.
tag
=
NULL
;
}
}
/* This is the default inquiry callback. We use it to handle the
Pinentry notifications. */
static
gpgme_error_t
default_inq_cb
(
engine_g13_t
g13
,
const
char
*
keyword
,
const
char
*
args
)
{
gpg_error_t
err
;
if
(
!
strcmp
(
keyword
,
"PINENTRY_LAUNCHED"
))
{
_gpgme_allow_set_foreground_window
((
pid_t
)
strtoul
(
args
,
NULL
,
10
));
}
if
(
g13
->
user
.
inq_cb
)
{
gpgme_data_t
data
=
NULL
;
err
=
g13
->
user
.
inq_cb
(
g13
->
user
.
inq_cb_value
,
keyword
,
args
,
&
data
);
if
(
!
err
&&
data
)
{
/* FIXME: Returning data is not yet implemented. However we
need to allow the caller to cleanup his data object.
Thus we run the callback in finish mode immediately. */
err
=
g13
->
user
.
inq_cb
(
g13
->
user
.
inq_cb_value
,
NULL
,
NULL
,
&
data
);
}
}
else
err
=
0
;
return
err
;
}
static
gpgme_error_t
g13_cancel
(
void
*
engine
)
{
engine_g13_t
g13
=
engine
;
if
(
!
g13
)
return
gpg_error
(
GPG_ERR_INV_VALUE
);
if
(
g13
->
status_cb
.
fd
!=
-1
)
_gpgme_io_close
(
g13
->
status_cb
.
fd
);
if
(
g13
->
assuan_ctx
)
{
assuan_release
(
g13
->
assuan_ctx
);
g13
->
assuan_ctx
=
NULL
;
}
return
0
;
}
static
gpgme_error_t
g13_cancel_op
(
void
*
engine
)
{
engine_g13_t
g13
=
engine
;
if
(
!
g13
)
return
gpg_error
(
GPG_ERR_INV_VALUE
);
if
(
g13
->
status_cb
.
fd
!=
-1
)
_gpgme_io_close
(
g13
->
status_cb
.
fd
);
return
0
;
}
static
void
g13_release
(
void
*
engine
)
{
engine_g13_t
g13
=
engine
;
if
(
!
g13
)
return
;
g13_cancel
(
engine
);
free
(
g13
);
}
static
gpgme_error_t
g13_new
(
void
**
engine
,
const
char
*
file_name
,
const
char
*
home_dir
,
const
char
*
version
)
{
gpgme_error_t
err
=
0
;
engine_g13_t
g13
;
const
char
*
pgmname
;
int
argc
;
const
char
*
argv
[
5
];
char
*
dft_display
=
NULL
;
char
dft_ttyname
[
64
];
char
*
env_tty
=
NULL
;
char
*
dft_ttytype
=
NULL
;
char
*
optstr
;
(
void
)
version
;
/* Not yet used. */
g13
=
calloc
(
1
,
sizeof
*
g13
);
if
(
!
g13
)
return
gpg_error_from_syserror
();
g13
->
status_cb
.
fd
=
-1
;
g13
->
status_cb
.
dir
=
1
;
g13
->
status_cb
.
tag
=
0
;
g13
->
status_cb
.
data
=
g13
;
pgmname
=
file_name
?
file_name
:
_gpgme_get_default_g13_name
();
argc
=
0
;
argv
[
argc
++
]
=
_gpgme_get_basename
(
pgmname
);
if
(
home_dir
)
{
argv
[
argc
++
]
=
"--homedir"
;
argv
[
argc
++
]
=
home_dir
;
}
argv
[
argc
++
]
=
"--server"
;
argv
[
argc
++
]
=
NULL
;
err
=
assuan_new_ext
(
&
g13
->
assuan_ctx
,
GPG_ERR_SOURCE_GPGME
,
&
_gpgme_assuan_malloc_hooks
,
_gpgme_assuan_log_cb
,
NULL
);
if
(
err
)
goto
leave
;
assuan_ctx_set_system_hooks
(
g13
->
assuan_ctx
,
&
_gpgme_assuan_system_hooks
);
#if USE_DESCRIPTOR_PASSING
err
=
assuan_pipe_connect
(
g13
->
assuan_ctx
,
pgmname
,
argv
,
NULL
,
NULL
,
NULL
,
ASSUAN_PIPE_CONNECT_FDPASSING
);
#else
err
=
assuan_pipe_connect
(
g13
->
assuan_ctx
,
pgmname
,
argv
,
NULL
,
NULL
,
NULL
,
0
);
#endif
if
(
err
)
goto
leave
;
err
=
_gpgme_getenv
(
"DISPLAY"
,
&
dft_display
);
if
(
err
)
goto
leave
;
if
(
dft_display
)
{
if
(
gpgrt_asprintf
(
&
optstr
,
"OPTION display=%s"
,
dft_display
)
<
0
)
{
free
(
dft_display
);
err
=
gpg_error_from_syserror
();
goto
leave
;
}
free
(
dft_display
);
err
=
assuan_transact
(
g13
->
assuan_ctx
,
optstr
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
gpgrt_free
(
optstr
);
if
(
err
)
goto
leave
;
}
err
=
_gpgme_getenv
(
"GPG_TTY"
,
&
env_tty
);
if
(
isatty
(
1
)
||
env_tty
||
err
)
{
int
rc
=
0
;
if
(
err
)
goto
leave
;
else
if
(
env_tty
)
{
snprintf
(
dft_ttyname
,
sizeof
(
dft_ttyname
),
"%s"
,
env_tty
);
free
(
env_tty
);
}
else
rc
=
ttyname_r
(
1
,
dft_ttyname
,
sizeof
(
dft_ttyname
));
/* Even though isatty() returns 1, ttyname_r() may fail in many
ways, e.g., when /dev/pts is not accessible under chroot. */
if
(
!
rc
)
{
if
(
gpgrt_asprintf
(
&
optstr
,
"OPTION ttyname=%s"
,
dft_ttyname
)
<
0
)
{
err
=
gpg_error_from_syserror
();
goto
leave
;
}
err
=
assuan_transact
(
g13
->
assuan_ctx
,
optstr
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
gpgrt_free
(
optstr
);
if
(
err
)
goto
leave
;
err
=
_gpgme_getenv
(
"TERM"
,
&
dft_ttytype
);
if
(
err
)
goto
leave
;
if
(
dft_ttytype
)
{
if
(
gpgrt_asprintf
(
&
optstr
,
"OPTION ttytype=%s"
,
dft_ttytype
)
<
0
)
{
free
(
dft_ttytype
);
err
=
gpg_error_from_syserror
();
goto
leave
;
}
free
(
dft_ttytype
);
err
=
assuan_transact
(
g13
->
assuan_ctx
,
optstr
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
gpgrt_free
(
optstr
);
if
(
err
)
goto
leave
;
}
}
}
#ifdef HAVE_W32_SYSTEM
/* Under Windows we need to use AllowSetForegroundWindow. Tell
g13 to tell us when it needs it. */
if
(
!
err
)
{
err
=
assuan_transact
(
g13
->
assuan_ctx
,
"OPTION allow-pinentry-notify"
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
if
(
gpg_err_code
(
err
)
==
GPG_ERR_UNKNOWN_OPTION
)
err
=
0
;
/* This is a new feature of g13. */
}
#endif
/*HAVE_W32_SYSTEM*/
leave
:
if
(
err
)
g13_release
(
g13
);
else
*
engine
=
g13
;
return
err
;
}
static
gpgme_error_t
g13_set_locale
(
void
*
engine
,
int
category
,
const
char
*
value
)
{
engine_g13_t
g13
=
engine
;
gpgme_error_t
err
;
char
*
optstr
;
const
char
*
catstr
;
/* FIXME: If value is NULL, we need to reset the option to default.
But we can't do this. So we error out here. G13 needs support
for this. */
if
(
0
)
;
#ifdef LC_CTYPE
else
if
(
category
==
LC_CTYPE
)
{
catstr
=
"lc-ctype"
;
if
(
!
value
&&
g13
->
lc_ctype_set
)
return
gpg_error
(
GPG_ERR_INV_VALUE
);
if
(
value
)
g13
->
lc_ctype_set
=
1
;
}
#endif
#ifdef LC_MESSAGES
else
if
(
category
==
LC_MESSAGES
)
{
catstr
=
"lc-messages"
;
if
(
!
value
&&
g13
->
lc_messages_set
)
return
gpg_error
(
GPG_ERR_INV_VALUE
);
if
(
value
)
g13
->
lc_messages_set
=
1
;
}
#endif
/* LC_MESSAGES */
else
return
gpg_error
(
GPG_ERR_INV_VALUE
);
/* FIXME: Reset value to default. */
if
(
!
value
)
return
0
;
if
(
gpgrt_asprintf
(
&
optstr
,
"OPTION %s=%s"
,
catstr
,
value
)
<
0
)
err
=
gpg_error_from_syserror
();
else
{
err
=
assuan_transact
(
g13
->
assuan_ctx
,
optstr
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
gpgrt_free
(
optstr
);
}
return
err
;
}
#if USE_DESCRIPTOR_PASSING
static
gpgme_error_t
g13_assuan_simple_command
(
assuan_context_t
ctx
,
const
char
*
cmd
,
engine_status_handler_t
status_fnc
,
void
*
status_fnc_value
)
{
gpg_error_t
err
;
char
*
line
;
size_t
linelen
;
(
void
)
status_fnc
;
(
void
)
status_fnc_value
;
err
=
assuan_write_line
(
ctx
,
cmd
);
if
(
err
)
return
err
;
do
{
err
=
assuan_read_line
(
ctx
,
&
line
,
&
linelen
);
if
(
err
)
return
err
;
if
(
*
line
==
'#'
||
!
linelen
)
continue
;
if
(
linelen
>=
2
&&
line
[
0
]
==
'O'
&&
line
[
1
]
==
'K'
&&
(
line
[
2
]
==
'\0'
||
line
[
2
]
==
' '
))
return
0
;
else
if
(
linelen
>=
4
&&
line
[
0
]
==
'E'
&&
line
[
1
]
==
'R'
&&
line
[
2
]
==
'R'
&&
line
[
3
]
==
' '
)
err
=
atoi
(
&
line
[
4
]);
else
if
(
linelen
>=
2
&&
line
[
0
]
==
'S'
&&
line
[
1
]
==
' '
)
{
char
*
rest
;
rest
=
strchr
(
line
+
2
,
' '
);
if
(
!
rest
)
rest
=
line
+
linelen
;
/* set to an empty string */
else
*
(
rest
++
)
=
0
;
/* Nothing to do with status lines. */
}
else
err
=
gpg_error
(
GPG_ERR_GENERAL
);
}
while
(
!
err
);
return
err
;
}
#endif
static
gpgme_error_t
status_handler
(
void
*
opaque
,
int
fd
)
{
struct
io_cb_data
*
data
=
(
struct
io_cb_data
*
)
opaque
;
engine_g13_t
g13
=
(
engine_g13_t
)
data
->
handler_value
;
gpgme_error_t
err
=
0
;
char
*
line
;
size_t
linelen
;
do
{
err
=
assuan_read_line
(
g13
->
assuan_ctx
,
&
line
,
&
linelen
);
if
(
err
)
{
/* Try our best to terminate the connection friendly. */
/* assuan_write_line (g13->assuan_ctx, "BYE"); */
TRACE
(
DEBUG_CTX
,
"gpgme:status_handler"
,
g13
,
"fd 0x%x: error reading assuan line: %s"
,
fd
,
gpg_strerror
(
err
));
}
else
if
(
linelen
>=
3
&&
line
[
0
]
==
'E'
&&
line
[
1
]
==
'R'
&&
line
[
2
]
==
'R'
&&
(
line
[
3
]
==
'\0'
||
line
[
3
]
==
' '
))
{
if
(
line
[
3
]
==
' '
)
err
=
atoi
(
&
line
[
4
]);
if
(
!
err
)
err
=
gpg_error
(
GPG_ERR_GENERAL
);
TRACE
(
DEBUG_CTX
,
"gpgme:status_handler"
,
g13
,
"fd 0x%x: ERR line: %s"
,
fd
,
err
?
gpg_strerror
(
err
)
:
"ok"
);
/* Command execution errors are not fatal, as we use
a session based protocol. */
data
->
op_err
=
err
;
/* The caller will do the rest (namely, call cancel_op,
which closes status_fd). */
return
0
;
}
else
if
(
linelen
>=
2
&&
line
[
0
]
==
'O'
&&
line
[
1
]
==
'K'
&&
(
line
[
2
]
==
'\0'
||
line
[
2
]
==
' '
))
{
TRACE
(
DEBUG_CTX
,
"gpgme:status_handler"
,
g13
,
"fd 0x%x: OK line"
,
fd
);
_gpgme_io_close
(
g13
->
status_cb
.
fd
);
return
0
;
}
else
if
(
linelen
>
2
&&
line
[
0
]
==
'D'
&&
line
[
1
]
==
' '
)
{
/* We are using the colon handler even for plain inline data
- strange name for that function but for historic reasons
we keep it. */
/* FIXME We can't use this for binary data because we
assume this is a string. For the current usage of colon
output it is correct. */
char
*
src
=
line
+
2
;
char
*
end
=
line
+
linelen
;
char
*
dst
=
src
;
linelen
=
0
;
while
(
src
<
end
)
{
if
(
*
src
==
'%'
&&
src
+
2
<
end
)
{
/* Handle escaped characters. */
++
src
;
*
dst
++
=
_gpgme_hextobyte
(
src
);
src
+=
2
;
}
else
*
dst
++
=
*
src
++
;
linelen
++
;
}
src
=
line
+
2
;
if
(
linelen
&&
g13
->
user
.
data_cb
)
err
=
g13
->
user
.
data_cb
(
g13
->
user
.
data_cb_value
,
src
,
linelen
);
else
err
=
0
;
TRACE
(
DEBUG_CTX
,
"gpgme:g13_status_handler"
,
g13
,
"fd 0x%x: D inlinedata; status from cb: %s"
,
fd
,
(
g13
->
user
.
data_cb
?
(
err
?
gpg_strerror
(
err
)
:
"ok"
)
:
"no callback"
));
}
else
if
(
linelen
>
2
&&
line
[
0
]
==
'S'
&&
line
[
1
]
==
' '
)
{
char
*
src
;
char
*
args
;
src
=
line
+
2
;
while
(
*
src
==
' '
)
src
++
;
args
=
strchr
(
line
+
2
,
' '
);
if
(
!
args
)
args
=
line
+
linelen
;
/* set to an empty string */
else
*
(
args
++
)
=
0
;
while
(
*
args
==
' '
)
args
++
;
if
(
g13
->
user
.
status_cb
)
err
=
g13
->
user
.
status_cb
(
g13
->
user
.
status_cb_value
,
src
,
args
);
else
err
=
0
;
TRACE
(
DEBUG_CTX
,
"gpgme:g13_status_handler"
,
g13
,
"fd 0x%x: S line (%s) - status from cb: %s"
,
fd
,
line
+
2
,
(
g13
->
user
.
status_cb
?
(
err
?
gpg_strerror
(
err
)
:
"ok"
)
:
"no callback"
));
}
else
if
(
linelen
>=
7
&&
line
[
0
]
==
'I'
&&
line
[
1
]
==
'N'
&&
line
[
2
]
==
'Q'
&&
line
[
3
]
==
'U'
&&
line
[
4
]
==
'I'
&&
line
[
5
]
==
'R'
&&
line
[
6
]
==
'E'
&&
(
line
[
7
]
==
'\0'
||
line
[
7
]
==
' '
))
{
char
*
src
;
char
*
args
;
for
(
src
=
line
+
7
;
*
src
==
' '
;
src
++
)
;
args
=
strchr
(
src
,
' '
);
if
(
!
args
)
args
=
line
+
linelen
;
/* Let it point to an empty string. */
else
*
(
args
++
)
=
0
;
while
(
*
args
==
' '
)
args
++
;
err
=
default_inq_cb
(
g13
,
src
,
args
);
if
(
!
err
)
{
/* Flush and send END. */
err
=
assuan_send_data
(
g13
->
assuan_ctx
,
NULL
,
0
);
}
else
if
(
gpg_err_code
(
err
)
==
GPG_ERR_ASS_CANCELED
)
{
/* Flush and send CANcel. */
err
=
assuan_send_data
(
g13
->
assuan_ctx
,
NULL
,
1
);
}
assuan_write_line
(
g13
->
assuan_ctx
,
"END"
);
}
}
while
(
!
err
&&
assuan_pending_line
(
g13
->
assuan_ctx
));
return
err
;
}
static
gpgme_error_t
add_io_cb
(
engine_g13_t
g13
,
iocb_data_t
*
iocbd
,
gpgme_io_cb_t
handler
)
{
gpgme_error_t
err
;
TRACE_BEG
(
DEBUG_ENGINE
,
"engine-g13:add_io_cb"
,
g13
,
"fd=%d, dir %d"
,
iocbd
->
fd
,
iocbd
->
dir
);
err
=
(
*
g13
->
io_cbs
.
add
)
(
g13
->
io_cbs
.
add_priv
,
iocbd
->
fd
,
iocbd
->
dir
,
handler
,
iocbd
->
data
,
&
iocbd
->
tag
);
if
(
err
)
return
TRACE_ERR
(
err
);
if
(
!
iocbd
->
dir
)
/* FIXME Kludge around poll() problem. */
err
=
_gpgme_io_set_nonblocking
(
iocbd
->
fd
);
return
TRACE_ERR
(
err
);
}
static
gpgme_error_t
start
(
engine_g13_t
g13
,
const
char
*
command
)
{
gpgme_error_t
err
;
assuan_fd_t
afdlist
[
5
];
int
fdlist
[
5
];
int
nfds
;
int
i
;
/* We need to know the fd used by assuan for reads. We do this by
using the assumption that the first returned fd from
assuan_get_active_fds() is always this one. */
nfds
=
assuan_get_active_fds
(
g13
->
assuan_ctx
,
0
/* read fds */
,
afdlist
,
DIM
(
afdlist
));
if
(
nfds
<
1
)
return
gpg_error
(
GPG_ERR_GENERAL
);
/* FIXME */
/* For now... */
for
(
i
=
0
;
i
<
nfds
;
i
++
)
fdlist
[
i
]
=
(
int
)
afdlist
[
i
];
/* We "duplicate" the file descriptor, so we can close it here (we
can't close fdlist[0], as that is closed by libassuan, and
closing it here might cause libassuan to close some unrelated FD
later). Alternatively, we could special case status_fd and
register/unregister it manually as needed, but this increases
code duplication and is more complicated as we can not use the
close notifications etc. A third alternative would be to let
Assuan know that we closed the FD, but that complicates the
Assuan interface. */
g13
->
status_cb
.
fd
=
_gpgme_io_dup
(
fdlist
[
0
]);
if
(
g13
->
status_cb
.
fd
<
0
)
return
gpg_error_from_syserror
();
if
(
_gpgme_io_set_close_notify
(
g13
->
status_cb
.
fd
,
close_notify_handler
,
g13
))
{
_gpgme_io_close
(
g13
->
status_cb
.
fd
);
g13
->
status_cb
.
fd
=
-1
;
return
gpg_error
(
GPG_ERR_GENERAL
);
}
err
=
add_io_cb
(
g13
,
&
g13
->
status_cb
,
status_handler
);
if
(
!
err
)
err
=
assuan_write_line
(
g13
->
assuan_ctx
,
command
);
if
(
!
err
)
g13_io_event
(
g13
,
GPGME_EVENT_START
,
NULL
);
return
err
;
}
#if USE_DESCRIPTOR_PASSING
static
gpgme_error_t
g13_reset
(
void
*
engine
)
{
engine_g13_t
g13
=
engine
;
/* We must send a reset because we need to reset the list of
signers. Note that RESET does not reset OPTION commands. */
return
g13_assuan_simple_command
(
g13
->
assuan_ctx
,
"RESET"
,
NULL
,
NULL
);
}
#endif
static
gpgme_error_t
g13_transact
(
void
*
engine
,
const
char
*
command
,
gpgme_assuan_data_cb_t
data_cb
,
void
*
data_cb_value
,
gpgme_assuan_inquire_cb_t
inq_cb
,
void
*
inq_cb_value
,
gpgme_assuan_status_cb_t
status_cb
,
void
*
status_cb_value
)
{
engine_g13_t
g13
=
engine
;
gpgme_error_t
err
;
if
(
!
g13
||
!
command
||
!*
command
)
return
gpg_error
(
GPG_ERR_INV_VALUE
);
g13
->
user
.
data_cb
=
data_cb
;
g13
->
user
.
data_cb_value
=
data_cb_value
;
g13
->
user
.
inq_cb
=
inq_cb
;
g13
->
user
.
inq_cb_value
=
inq_cb_value
;
g13
->
user
.
status_cb
=
status_cb
;
g13
->
user
.
status_cb_value
=
status_cb_value
;
err
=
start
(
g13
,
command
);
return
err
;
}
static
void
g13_set_io_cbs
(
void
*
engine
,
gpgme_io_cbs_t
io_cbs
)
{
engine_g13_t
g13
=
engine
;
g13
->
io_cbs
=
*
io_cbs
;
}
static
void
g13_io_event
(
void
*
engine
,
gpgme_event_io_t
type
,
void
*
type_data
)
{
engine_g13_t
g13
=
engine
;
TRACE
(
DEBUG_ENGINE
,
"gpgme:g13_io_event"
,
g13
,
"event %p, type %d, type_data %p"
,
g13
->
io_cbs
.
event
,
type
,
type_data
);
if
(
g13
->
io_cbs
.
event
)
(
*
g13
->
io_cbs
.
event
)
(
g13
->
io_cbs
.
event_priv
,
type
,
type_data
);
}
struct
engine_ops
_gpgme_engine_ops_g13
=
{
/* Static functions. */
_gpgme_get_default_g13_name
,
NULL
,
g13_get_version
,
g13_get_req_version
,
g13_new
,
/* Member functions. */
g13_release
,
#if USE_DESCRIPTOR_PASSING
g13_reset
,
#else
NULL
,
/* reset */
#endif
NULL
,
/* set_status_cb */
NULL
,
/* set_status_handler */
NULL
,
/* set_command_handler */
NULL
,
/* set_colon_line_handler */
g13_set_locale
,
NULL
,
/* set_protocol */
NULL
,
/* set_engine_flags */
NULL
,
/* decrypt */
NULL
,
/* delete */
NULL
,
/* edit */
NULL
,
/* encrypt */
NULL
,
/* encrypt_sign */
NULL
,
/* export */
NULL
,
/* export_ext */
NULL
,
/* genkey */
NULL
,
/* import */
NULL
,
/* keylist */
NULL
,
/* keylist_ext */
NULL
,
/* keylist_data */
NULL
,
/* keysign */
NULL
,
/* revsig */
NULL
,
/* tofu_policy */
NULL
,
/* sign */
NULL
,
/* verify */
NULL
,
/* getauditlog */
NULL
,
/* setexpire */
g13_transact
,
NULL
,
/* conf_load */
NULL
,
/* conf_save */
NULL
,
/* conf_dir */
NULL
,
/* query_swdb */
g13_set_io_cbs
,
g13_io_event
,
g13_cancel
,
g13_cancel_op
,
NULL
,
/* passwd */
NULL
,
/* set_pinentry_mode */
NULL
/* opspawn */
};
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Mon, Dec 23, 5:06 PM (6 h, 13 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
e9/55/4a924054e1cbf3bbe7225c19274f
Attached To
rM GPGME
Event Timeline
Log In to Comment