mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Lock scdaemon to CCID if once found.
This solves a problem where ccid was used, the card unplugged and then scdaemon tries to find a new (plugged in) reader and thus will eventually try PC/SC over and over again. Also added an explicit --kill command to gpgconf.
This commit is contained in:
parent
90dcc0c3ad
commit
7c03c8cc65
@ -61,7 +61,7 @@ watchgnupg --force ~/.gnupg/S.log
|
||||
|
||||
@noindent
|
||||
This starts it on the current terminal for listening on the socket
|
||||
@file{~/.gnupg/S.log}.
|
||||
@file{~/.gnupg/S.log}.
|
||||
|
||||
@mansect options
|
||||
@noindent
|
||||
@ -69,7 +69,7 @@ This starts it on the current terminal for listening on the socket
|
||||
|
||||
@table @gnupgtabopt
|
||||
|
||||
@item --force
|
||||
@item --force
|
||||
@opindex force
|
||||
Delete an already existing socket file.
|
||||
|
||||
@ -129,9 +129,9 @@ name for remote debugging.
|
||||
|
||||
@mansect see also
|
||||
@ifset isman
|
||||
@command{gpg}(1),
|
||||
@command{gpgsm}(1),
|
||||
@command{gpg-agent}(1),
|
||||
@command{gpg}(1),
|
||||
@command{gpgsm}(1),
|
||||
@command{gpg-agent}(1),
|
||||
@command{scdaemon}(1)
|
||||
@end ifset
|
||||
@include see-also-note.texi
|
||||
@ -150,7 +150,7 @@ name for remote debugging.
|
||||
@node addgnupghome
|
||||
@section Create .gnupg home directories.
|
||||
@ifset manverb
|
||||
.B addgnupghome
|
||||
.B addgnupghome
|
||||
\- Create .gnupg home directories
|
||||
@end ifset
|
||||
|
||||
@ -197,7 +197,7 @@ addgnupghome account1 account2 ... accountn
|
||||
.br
|
||||
.B gpgconf
|
||||
.RI [ options ]
|
||||
.B \-\-list-options
|
||||
.B \-\-list-options
|
||||
.I component
|
||||
.br
|
||||
.B gpgconf
|
||||
@ -301,10 +301,17 @@ is given, check that file instead.
|
||||
|
||||
@item --reload [@var{component}]
|
||||
@opindex reload
|
||||
Reload all or the given component. This is basically the sam as sending
|
||||
Reload all or the given component. This is basically the same as sending
|
||||
a SIGHUP to the component. Components which don't support reloading are
|
||||
ignored.
|
||||
|
||||
@item --kill [@var{component}]
|
||||
@opindex kill
|
||||
Kill the given component. Components which support killing are
|
||||
gpg-agent and scdaemon. Components which don't support reloading are
|
||||
ignored. Note that as of now reload and kill have the same effect for
|
||||
scdaemon.
|
||||
|
||||
@end table
|
||||
|
||||
|
||||
@ -570,7 +577,7 @@ configuration file. It is @emph{percent-escaped}.
|
||||
|
||||
@item line
|
||||
If an error occurred in the configuration file, this field has the line
|
||||
number of the failing statement in the configuration file.
|
||||
number of the failing statement in the configuration file.
|
||||
It is an @emph{unsigned number}.
|
||||
|
||||
@item error
|
||||
@ -867,7 +874,7 @@ effect.
|
||||
@subsection Listing global options
|
||||
|
||||
Sometimes it is useful for applications to look at the global options
|
||||
file @file{gpgconf.conf}.
|
||||
file @file{gpgconf.conf}.
|
||||
The colon separated listing format is record oriented and uses the first
|
||||
field to identify the record type:
|
||||
|
||||
@ -936,9 +943,9 @@ no feature to change the global option file through @command{gpgconf}.
|
||||
|
||||
@mansect see also
|
||||
@ifset isman
|
||||
@command{gpg}(1),
|
||||
@command{gpgsm}(1),
|
||||
@command{gpg-agent}(1),
|
||||
@command{gpg}(1),
|
||||
@command{gpgsm}(1),
|
||||
@command{gpg-agent}(1),
|
||||
@command{scdaemon}(1),
|
||||
@command{dirmngr}(1)
|
||||
@end ifset
|
||||
@ -989,7 +996,7 @@ applygnupgdefaults
|
||||
@ifset manverb
|
||||
.B gpgsm-gencert.sh
|
||||
\- Generate an X.509 certificate request
|
||||
@end ifset
|
||||
@end ifset
|
||||
|
||||
@mansect synopsis
|
||||
@ifset manverb
|
||||
@ -1008,8 +1015,8 @@ which will be printed to stdout.
|
||||
|
||||
@mansect see also
|
||||
@ifset isman
|
||||
@command{gpgsm}(1),
|
||||
@command{gpg-agent}(1),
|
||||
@command{gpgsm}(1),
|
||||
@command{gpg-agent}(1),
|
||||
@command{scdaemon}(1)
|
||||
@end ifset
|
||||
@include see-also-note.texi
|
||||
@ -1096,7 +1103,7 @@ The following additional options may be used:
|
||||
@item -v
|
||||
@itemx --verbose
|
||||
@opindex verbose
|
||||
Output additional information while running.
|
||||
Output additional information while running.
|
||||
|
||||
@item -P @var{string}
|
||||
@itemx --passphrase @var{string}
|
||||
@ -1108,9 +1115,9 @@ for other users.
|
||||
|
||||
@mansect see also
|
||||
@ifset isman
|
||||
@command{gpg}(1),
|
||||
@command{gpgsm}(1),
|
||||
@command{gpg-agent}(1),
|
||||
@command{gpg}(1),
|
||||
@command{gpgsm}(1),
|
||||
@command{gpg-agent}(1),
|
||||
@command{scdaemon}(1)
|
||||
@end ifset
|
||||
@include see-also-note.texi
|
||||
@ -1169,7 +1176,7 @@ The following options may be used:
|
||||
@item -v
|
||||
@itemx --verbose
|
||||
@opindex verbose
|
||||
Output additional information while running.
|
||||
Output additional information while running.
|
||||
|
||||
@item -q
|
||||
@item --quiet
|
||||
@ -1186,7 +1193,7 @@ Specify the agent program to be started if none is running.
|
||||
|
||||
@item -S
|
||||
@itemx --raw-socket @var{name}
|
||||
@opindex S
|
||||
@opindex S
|
||||
@opindex raw-socket
|
||||
Connect to socket @var{name} assuming this is an Assuan style server.
|
||||
Do not run any special initializations or environment checks. This may
|
||||
@ -1209,7 +1216,7 @@ connects to the assuan server in extended mode to allow descriptor
|
||||
passing. This option makes it use the old mode.
|
||||
|
||||
@item --run @var{file}
|
||||
@opindex run
|
||||
@opindex run
|
||||
Run the commands from @var{file} at startup and then continue with the
|
||||
regular input method. Note, that commands given on the command line are
|
||||
executed after this file.
|
||||
@ -1251,7 +1258,7 @@ Variables are referenced by prefixing the name with a dollar sign and
|
||||
optionally include the name in curly braces. The rules for a valid name
|
||||
are identically to those of the standard bourne shell. This is not yet
|
||||
enforced but may be in the future. When used with curly braces no
|
||||
leading or trailing white space is allowed.
|
||||
leading or trailing white space is allowed.
|
||||
|
||||
If a variable is not found, it is searched in the environment and if
|
||||
found copied to the table of variables.
|
||||
@ -1264,7 +1271,7 @@ following functions are available:
|
||||
@item get
|
||||
Return a value described by the argument. Available arguments are:
|
||||
|
||||
@table @code
|
||||
@table @code
|
||||
@item cwd
|
||||
The current working directory.
|
||||
@item homedir
|
||||
@ -1431,7 +1438,7 @@ Print a list of available control commands.
|
||||
|
||||
@ifset isman
|
||||
@mansect see also
|
||||
@command{gpg-agent}(1),
|
||||
@command{gpg-agent}(1),
|
||||
@command{scdaemon}(1)
|
||||
@include see-also-note.texi
|
||||
@end ifset
|
||||
@ -1452,8 +1459,8 @@ Print a list of available control commands.
|
||||
@mansect synopsis
|
||||
@ifset manverb
|
||||
.B dirmngr-client
|
||||
.RI [ options ]
|
||||
.RI [ certfile | pattern ]
|
||||
.RI [ options ]
|
||||
.RI [ certfile | pattern ]
|
||||
@end ifset
|
||||
|
||||
@mansect description
|
||||
@ -1478,7 +1485,7 @@ dirmngr-client <@var{acert}
|
||||
@end example
|
||||
|
||||
Where @var{acert} is one DER encoded (binary) X.509 certificates to be
|
||||
tested.
|
||||
tested.
|
||||
@ifclear isman
|
||||
The return value of this command is
|
||||
@end ifclear
|
||||
@ -1489,7 +1496,7 @@ The return value of this command is
|
||||
@end ifset
|
||||
@table @code
|
||||
|
||||
@item 0
|
||||
@item 0
|
||||
The certificate under question is valid; i.e. there is a valid CRL
|
||||
available and it is not listed tehre or teh OCSP request returned that
|
||||
that certificate is valid.
|
||||
@ -1673,7 +1680,7 @@ configured with @samp{--enable-symcryptrun} at build time.
|
||||
@command{symcryptrun} is invoked this way:
|
||||
|
||||
@example
|
||||
symcryptrun --class CLASS --program PROGRAM --keyfile KEYFILE
|
||||
symcryptrun --class CLASS --program PROGRAM --keyfile KEYFILE
|
||||
[--decrypt | --encrypt] [inputfile]
|
||||
@end example
|
||||
@mancont
|
||||
@ -1685,12 +1692,12 @@ For decryption vice versa.
|
||||
@var{CLASS} describes the calling conventions of the external tool.
|
||||
Currently it must be given as @samp{confucius}. @var{PROGRAM} is
|
||||
the full filename of that external tool.
|
||||
|
||||
|
||||
For the class @samp{confucius} the option @option{--keyfile} is
|
||||
required; @var{keyfile} is the name of a file containing the secret key,
|
||||
which may be protected by a passphrase. For detailed calling
|
||||
conventions, see the source code.
|
||||
|
||||
|
||||
@noindent
|
||||
Note, that @command{gpg-agent} must be running before starting
|
||||
@command{symcryptrun}.
|
||||
@ -1702,7 +1709,7 @@ The following additional options may be used:
|
||||
@item -v
|
||||
@itemx --verbose
|
||||
@opindex verbose
|
||||
Output additional information while running.
|
||||
Output additional information while running.
|
||||
|
||||
@item -q
|
||||
@item --quiet
|
||||
@ -1724,22 +1731,22 @@ information to STDERR.
|
||||
The possible exit status codes of @command{symcryptrun} are:
|
||||
|
||||
@table @code
|
||||
@item 0
|
||||
@item 0
|
||||
Success.
|
||||
@item 1
|
||||
@item 1
|
||||
Some error occured.
|
||||
@item 2
|
||||
@item 2
|
||||
No valid passphrase was provided.
|
||||
@item 3
|
||||
@item 3
|
||||
The operation was canceled by the user.
|
||||
|
||||
@end table
|
||||
|
||||
@mansect see also
|
||||
@ifset isman
|
||||
@command{gpg}(1),
|
||||
@command{gpgsm}(1),
|
||||
@command{gpg-agent}(1),
|
||||
@command{gpg}(1),
|
||||
@command{gpgsm}(1),
|
||||
@command{gpg-agent}(1),
|
||||
@end ifset
|
||||
@include see-also-note.texi
|
||||
|
||||
@ -1747,8 +1754,8 @@ The possible exit status codes of @command{symcryptrun} are:
|
||||
@c
|
||||
@c GPG-ZIP
|
||||
@c
|
||||
@c The original manpage on which this section is based was written
|
||||
@c by Colin Tuckley <colin@tuckley.org> and Daniel Leidert
|
||||
@c The original manpage on which this section is based was written
|
||||
@c by Colin Tuckley <colin@tuckley.org> and Daniel Leidert
|
||||
@c <daniel.leidert@wgdd.de> for the Debian distribution (but may be used by
|
||||
@c others).
|
||||
@manpage gpg-zip.1
|
||||
@ -1880,8 +1887,7 @@ gpg-zip --list-archive test1
|
||||
|
||||
@mansect see also
|
||||
@ifset isman
|
||||
@command{gpg}(1),
|
||||
@command{tar}(1),
|
||||
@command{gpg}(1),
|
||||
@command{tar}(1),
|
||||
@end ifset
|
||||
@include see-also-note.texi
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
2011-02-23 Werner Koch <wk@g10code.com>
|
||||
|
||||
* apdu.c (apdu_open_reader): Lock in to CCID if used once.
|
||||
|
||||
2011-01-25 NIIBE Yutaka <gniibe@fsij.org>,
|
||||
Grant Olson <kgo@grant-olson.net> (wk)
|
||||
|
||||
|
18
scd/apdu.c
18
scd/apdu.c
@ -1,5 +1,6 @@
|
||||
/* apdu.c - ISO 7816 APDU functions and low level I/O
|
||||
* Copyright (C) 2003, 2004, 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2003, 2004, 2008, 2009, 2010,
|
||||
* 2011 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -2355,12 +2356,25 @@ apdu_open_reader (const char *portstr, int *r_no_service)
|
||||
#ifdef HAVE_LIBUSB
|
||||
if (!opt.disable_ccid)
|
||||
{
|
||||
static int once_available;
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
slot = open_ccid_reader (portstr);
|
||||
if (slot != -1)
|
||||
return slot; /* got one */
|
||||
{
|
||||
once_available = 1;
|
||||
return slot; /* got one */
|
||||
}
|
||||
|
||||
/* If we ever loaded successfully loaded a CCID reader we never
|
||||
want to fallback to another driver. This solves a problem
|
||||
where ccid was used, the card unplugged and then scdaemon
|
||||
tries to find a new reader and will eventually try PC/SC over
|
||||
and over again. To reset this flag "gpgconf --kill scdaemon"
|
||||
can be used. */
|
||||
if (once_available)
|
||||
return -1;
|
||||
|
||||
/* If a CCID reader specification has been given, the user does
|
||||
not want a fallback to other drivers. */
|
||||
|
@ -1,3 +1,9 @@
|
||||
2011-02-23 Werner Koch <wk@g10code.com>
|
||||
|
||||
* gpgconf.c: Add command --kill.
|
||||
* gpgconf-comp.c (gc_component_kill): New.
|
||||
(gpg_agent_runtime_change, scdaemon_runtime_change): Add kill flag.
|
||||
|
||||
2011-02-03 Werner Koch <wk@g10code.com>
|
||||
|
||||
* watchgnupg.c (print_version): Update copyright year.
|
||||
@ -1247,7 +1253,7 @@
|
||||
|
||||
|
||||
Copyright 2003, 2004, 2005, 2006, 2007, 2008,
|
||||
2009, 2010 Free Software Foundation, Inc.
|
||||
2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
|
||||
This file is free software; as a special exception the author gives
|
||||
unlimited permission to copy and/or distribute it, with or without
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* gpgconf-comp.c - Configuration utility for GnuPG.
|
||||
* Copyright (C) 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2004, 2007, 2008, 2009, 2010,
|
||||
* 2011 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -104,8 +105,8 @@ gc_error (int status, int errnum, const char *fmt, ...)
|
||||
|
||||
|
||||
/* Forward declaration. */
|
||||
static void gpg_agent_runtime_change (void);
|
||||
static void scdaemon_runtime_change (void);
|
||||
static void gpg_agent_runtime_change (int killflag);
|
||||
static void scdaemon_runtime_change (int killflag);
|
||||
|
||||
/* Backend configuration. Backends are used to decide how the default
|
||||
and current value of an option can be determined, and how the
|
||||
@ -163,8 +164,9 @@ static struct
|
||||
available. */
|
||||
char module_name;
|
||||
|
||||
/* The runtime change callback. */
|
||||
void (*runtime_change) (void);
|
||||
/* The runtime change callback. If KILLFLAG is true the component
|
||||
is killed and not just reloaded. */
|
||||
void (*runtime_change) (int killflag);
|
||||
|
||||
/* The option name for the configuration filename of this backend.
|
||||
This must be an absolute filename. It can be an option from a
|
||||
@ -182,13 +184,13 @@ static struct
|
||||
NULL, "gpgconf-gpg.conf" },
|
||||
{ "GPGSM", "gpgsm", GNUPG_MODULE_NAME_GPGSM,
|
||||
NULL, "gpgconf-gpgsm.conf" },
|
||||
{ "GPG Agent", "gpg-agent", GNUPG_MODULE_NAME_AGENT,
|
||||
{ "GPG Agent", "gpg-agent", GNUPG_MODULE_NAME_AGENT,
|
||||
gpg_agent_runtime_change, "gpgconf-gpg-agent.conf" },
|
||||
{ "SCDaemon", "scdaemon", GNUPG_MODULE_NAME_SCDAEMON,
|
||||
scdaemon_runtime_change, "gpgconf-scdaemon.conf" },
|
||||
{ "DirMngr", "dirmngr", GNUPG_MODULE_NAME_DIRMNGR,
|
||||
NULL, "gpgconf-dirmngr.conf" },
|
||||
{ "DirMngr LDAP Server List", NULL, 0,
|
||||
{ "DirMngr LDAP Server List", NULL, 0,
|
||||
NULL, "ldapserverlist-file", "LDAP Server" },
|
||||
{ "Pinentry", "pinentry", GNUPG_MODULE_NAME_PINENTRY,
|
||||
NULL, "gpgconf-pinentry.conf" },
|
||||
@ -405,17 +407,17 @@ struct gc_option
|
||||
/* A gettext domain in which the following description can be found.
|
||||
If this is NULL, then DESC is not translated. Valid for groups
|
||||
and options.
|
||||
|
||||
|
||||
Note that we try to keep the description of groups within the
|
||||
gnupg domain.
|
||||
|
||||
gnupg domain.
|
||||
|
||||
IMPORTANT: If you add a new domain please make sure to add a code
|
||||
set switching call to the function my_dgettext further below. */
|
||||
const char *desc_domain;
|
||||
|
||||
/* A gettext description for this group or option. If it starts
|
||||
with a '|', then the string up to the next '|' describes the
|
||||
argument, and the description follows the second '|'.
|
||||
argument, and the description follows the second '|'.
|
||||
|
||||
In general enclosing these description in N_() is not required
|
||||
because the description should be identical to the one in the
|
||||
@ -516,7 +518,7 @@ static gc_option_t gc_options_gpg_agent[] =
|
||||
GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
|
||||
"gnupg", N_("Options controlling the security") },
|
||||
{ "default-cache-ttl", GC_OPT_FLAG_RUNTIME,
|
||||
GC_LEVEL_BASIC, "gnupg",
|
||||
GC_LEVEL_BASIC, "gnupg",
|
||||
"|N|expire cached PINs after N seconds",
|
||||
GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
|
||||
{ "default-cache-ttl-ssh", GC_OPT_FLAG_RUNTIME,
|
||||
@ -528,7 +530,7 @@ static gc_option_t gc_options_gpg_agent[] =
|
||||
N_("|N|set maximum PIN cache lifetime to N seconds"),
|
||||
GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
|
||||
{ "max-cache-ttl-ssh", GC_OPT_FLAG_RUNTIME,
|
||||
GC_LEVEL_EXPERT, "gnupg",
|
||||
GC_LEVEL_EXPERT, "gnupg",
|
||||
N_("|N|set maximum SSH key lifetime to N seconds"),
|
||||
GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
|
||||
{ "ignore-cache-for-signing", GC_OPT_FLAG_RUNTIME,
|
||||
@ -544,16 +546,16 @@ static gc_option_t gc_options_gpg_agent[] =
|
||||
{ "Passphrase policy",
|
||||
GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
|
||||
"gnupg", N_("Options enforcing a passphrase policy") },
|
||||
{ "enforce-passphrase-constraints", GC_OPT_FLAG_RUNTIME,
|
||||
GC_LEVEL_EXPERT, "gnupg",
|
||||
{ "enforce-passphrase-constraints", GC_OPT_FLAG_RUNTIME,
|
||||
GC_LEVEL_EXPERT, "gnupg",
|
||||
N_("do not allow to bypass the passphrase policy"),
|
||||
GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
|
||||
{ "min-passphrase-len", GC_OPT_FLAG_RUNTIME,
|
||||
GC_LEVEL_ADVANCED, "gnupg",
|
||||
GC_LEVEL_ADVANCED, "gnupg",
|
||||
N_("|N|set minimal required length for new passphrases to N"),
|
||||
GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
|
||||
{ "min-passphrase-nonalpha", GC_OPT_FLAG_RUNTIME,
|
||||
GC_LEVEL_EXPERT, "gnupg",
|
||||
GC_LEVEL_EXPERT, "gnupg",
|
||||
N_("|N|require at least N non-alpha characters for a new passphrase"),
|
||||
GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
|
||||
{ "check-passphrase-pattern", GC_OPT_FLAG_RUNTIME,
|
||||
@ -561,11 +563,11 @@ static gc_option_t gc_options_gpg_agent[] =
|
||||
"gnupg", N_("|FILE|check new passphrases against pattern in FILE"),
|
||||
GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT },
|
||||
{ "max-passphrase-days", GC_OPT_FLAG_RUNTIME,
|
||||
GC_LEVEL_EXPERT, "gnupg",
|
||||
GC_LEVEL_EXPERT, "gnupg",
|
||||
N_("|N|expire the passphrase after N days"),
|
||||
GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
|
||||
{ "enable-passphrase-history", GC_OPT_FLAG_RUNTIME,
|
||||
GC_LEVEL_EXPERT, "gnupg",
|
||||
{ "enable-passphrase-history", GC_OPT_FLAG_RUNTIME,
|
||||
GC_LEVEL_EXPERT, "gnupg",
|
||||
N_("do not allow the reuse of old passphrases"),
|
||||
GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
|
||||
|
||||
@ -686,7 +688,7 @@ static gc_option_t gc_options_gpg[] =
|
||||
(GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_NO_CHANGE), GC_LEVEL_INVISIBLE,
|
||||
NULL, NULL,
|
||||
GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
|
||||
|
||||
|
||||
|
||||
{ "Debug",
|
||||
GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
|
||||
@ -849,7 +851,7 @@ static gc_option_t gc_options_dirmngr[] =
|
||||
{ "csh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
|
||||
"dirmngr", "csh-style command output",
|
||||
GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
|
||||
|
||||
|
||||
{ "Configuration",
|
||||
GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
|
||||
"gnupg", N_("Options controlling the configuration") },
|
||||
@ -1047,17 +1049,17 @@ struct error_line_s
|
||||
|
||||
/* Engine specific support. */
|
||||
static void
|
||||
gpg_agent_runtime_change (void)
|
||||
gpg_agent_runtime_change (int killflag)
|
||||
{
|
||||
gpg_error_t err;
|
||||
const char *pgmname;
|
||||
const char *argv[2];
|
||||
pid_t pid;
|
||||
|
||||
|
||||
pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT);
|
||||
argv[0] = "reloadagent";
|
||||
argv[0] = killflag? "KILLAGENT" : "RELOADAGENT";
|
||||
argv[1] = NULL;
|
||||
|
||||
|
||||
err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
|
||||
if (!err)
|
||||
err = gnupg_wait_process (pgmname, pid, 1, NULL);
|
||||
@ -1069,13 +1071,15 @@ gpg_agent_runtime_change (void)
|
||||
|
||||
|
||||
static void
|
||||
scdaemon_runtime_change (void)
|
||||
scdaemon_runtime_change (int killflag)
|
||||
{
|
||||
gpg_error_t err;
|
||||
const char *pgmname;
|
||||
const char *argv[6];
|
||||
pid_t pid;
|
||||
|
||||
|
||||
(void)killflag; /* For scdaemon kill and reload are synonyms. */
|
||||
|
||||
/* We use "GETINFO app_running" to see whether the agent is already
|
||||
running and kill it only in this case. This avoids an explicit
|
||||
starting of the agent in case it is not yet running. There is
|
||||
@ -1088,7 +1092,7 @@ scdaemon_runtime_change (void)
|
||||
argv[3] = "scd killscd";
|
||||
argv[4] = "/end";
|
||||
argv[5] = NULL;
|
||||
|
||||
|
||||
err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
|
||||
if (!err)
|
||||
err = gnupg_wait_process (pgmname, pid, 1, NULL);
|
||||
@ -1099,6 +1103,35 @@ scdaemon_runtime_change (void)
|
||||
}
|
||||
|
||||
|
||||
/* Unconditionally restart COMPONENT. */
|
||||
void
|
||||
gc_component_kill (int component)
|
||||
{
|
||||
int runtime[GC_BACKEND_NR];
|
||||
gc_option_t *option;
|
||||
gc_backend_t backend;
|
||||
|
||||
/* Set a flag for the backends to be reloaded. */
|
||||
for (backend = 0; backend < GC_BACKEND_NR; backend++)
|
||||
runtime[backend] = 0;
|
||||
|
||||
if (component >= 0)
|
||||
{
|
||||
assert (component < GC_COMPONENT_NR);
|
||||
option = gc_component[component].options;
|
||||
for (; option && option->name; option++)
|
||||
runtime[option->backend] = 1;
|
||||
}
|
||||
|
||||
/* Do the restart for the selected backends. */
|
||||
for (backend = 0; backend < GC_BACKEND_NR; backend++)
|
||||
{
|
||||
if (runtime[backend] && gc_backend[backend].runtime_change)
|
||||
(*gc_backend[backend].runtime_change) (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Unconditionally reload COMPONENT or all components if COMPONENT is -1. */
|
||||
void
|
||||
gc_component_reload (int component)
|
||||
@ -1110,7 +1143,7 @@ gc_component_reload (int component)
|
||||
/* Set a flag for the backends to be reloaded. */
|
||||
for (backend = 0; backend < GC_BACKEND_NR; backend++)
|
||||
runtime[backend] = 0;
|
||||
|
||||
|
||||
if (component == -1)
|
||||
{
|
||||
for (component = 0; component < GC_COMPONENT_NR; component++)
|
||||
@ -1129,10 +1162,10 @@ gc_component_reload (int component)
|
||||
}
|
||||
|
||||
/* Do the reload for all selected backends. */
|
||||
for (backend = 0; backend < GC_BACKEND_NR; backend++)
|
||||
for (backend = 0; backend < GC_BACKEND_NR; backend++)
|
||||
{
|
||||
if (runtime[backend] && gc_backend[backend].runtime_change)
|
||||
(*gc_backend[backend].runtime_change) ();
|
||||
(*gc_backend[backend].runtime_change) (0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1152,7 +1185,7 @@ my_dgettext (const char *domain, const char *msgid)
|
||||
{
|
||||
static int switched_codeset;
|
||||
char *text;
|
||||
|
||||
|
||||
if (!switched_codeset)
|
||||
{
|
||||
switched_codeset = 1;
|
||||
@ -1172,7 +1205,7 @@ my_dgettext (const char *domain, const char *msgid)
|
||||
{
|
||||
static int switched_codeset;
|
||||
char *text;
|
||||
|
||||
|
||||
if (!switched_codeset)
|
||||
{
|
||||
switched_codeset = 1;
|
||||
@ -1180,7 +1213,7 @@ my_dgettext (const char *domain, const char *msgid)
|
||||
|
||||
bindtextdomain ("dirmngr", LOCALEDIR);
|
||||
bind_textdomain_codeset ("dirmngr", "utf-8");
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* Note: This is a hack to actually use the gnupg2 domain as
|
||||
@ -1225,7 +1258,7 @@ gc_percent_escape (const char *src)
|
||||
*(dst++) = '%';
|
||||
*(dst++) = '2';
|
||||
*(dst++) = '5';
|
||||
}
|
||||
}
|
||||
else if (*src == ':')
|
||||
{
|
||||
/* The colon is used as field separator. */
|
||||
@ -1281,7 +1314,7 @@ percent_deescape (const char *src)
|
||||
|
||||
*(dst++) = (char) val;
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
*(dst++) = *(src++);
|
||||
}
|
||||
@ -1374,7 +1407,7 @@ collect_error_output (estream_t fp, const char *tag)
|
||||
buffer[pos - (c == '\n')] = 0;
|
||||
if (cont_line)
|
||||
; /*Ignore continuations of previous line. */
|
||||
else if (!strncmp (buffer, tag, taglen) && buffer[taglen] == ':')
|
||||
else if (!strncmp (buffer, tag, taglen) && buffer[taglen] == ':')
|
||||
{
|
||||
/* "gpgsm: foo:4: bla" */
|
||||
/* Yep, we are interested in this line. */
|
||||
@ -1424,7 +1457,7 @@ collect_error_output (estream_t fp, const char *tag)
|
||||
cont_line = (c != '\n');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* We ignore error lines not terminated by a LF. */
|
||||
return errlines;
|
||||
}
|
||||
@ -1483,16 +1516,16 @@ gc_component_check_options (int component, estream_t out, const char *conf_file)
|
||||
else
|
||||
argv[i++] = "--gpgconf-test";
|
||||
argv[i++] = NULL;
|
||||
|
||||
|
||||
result = 0;
|
||||
errlines = NULL;
|
||||
err = gnupg_spawn_process (pgmname, argv, GPG_ERR_SOURCE_DEFAULT, NULL, 0,
|
||||
NULL, NULL, &errfp, &pid);
|
||||
if (err)
|
||||
result |= 1; /* Program could not be run. */
|
||||
else
|
||||
else
|
||||
{
|
||||
errlines = collect_error_output (errfp,
|
||||
errlines = collect_error_output (errfp,
|
||||
gc_component[component].name);
|
||||
if (gnupg_wait_process (pgmname, pid, 1, &exitcode))
|
||||
{
|
||||
@ -1504,12 +1537,12 @@ gc_component_check_options (int component, estream_t out, const char *conf_file)
|
||||
gnupg_release_process (pid);
|
||||
es_fclose (errfp);
|
||||
}
|
||||
|
||||
|
||||
/* If the program could not be run, we can't tell whether
|
||||
the config file is good. */
|
||||
if (result & 1)
|
||||
result |= 2;
|
||||
|
||||
result |= 2;
|
||||
|
||||
if (out)
|
||||
{
|
||||
const char *desc;
|
||||
@ -1617,7 +1650,7 @@ list_one_option (const gc_option_t *option, estream_t out)
|
||||
if (opt.verbose)
|
||||
{
|
||||
es_putc (' ', out);
|
||||
|
||||
|
||||
if (!option->flags)
|
||||
es_fprintf (out, "none");
|
||||
else
|
||||
@ -1649,7 +1682,7 @@ list_one_option (const gc_option_t *option, estream_t out)
|
||||
|
||||
/* The description field. */
|
||||
es_fprintf (out, ":%s", desc ? gc_percent_escape (desc) : "");
|
||||
|
||||
|
||||
/* The type field. */
|
||||
es_fprintf (out, ":%u", option->arg_type);
|
||||
if (opt.verbose)
|
||||
@ -1690,7 +1723,7 @@ list_one_option (const gc_option_t *option, estream_t out)
|
||||
/* List all options of the component COMPONENT. */
|
||||
void
|
||||
gc_component_list_options (int component, estream_t out)
|
||||
{
|
||||
{
|
||||
const gc_option_t *option = gc_component[component].options;
|
||||
|
||||
while (option && option->name)
|
||||
@ -1713,7 +1746,7 @@ gc_component_list_options (int component, estream_t out)
|
||||
different active options, and because it is hard to
|
||||
maintain manually, we calculate it here. The value in
|
||||
the global static table is ignored. */
|
||||
|
||||
|
||||
while (group_option->name)
|
||||
{
|
||||
if (group_option->flags & GC_OPT_FLAG_GROUP)
|
||||
@ -1788,7 +1821,7 @@ get_config_filename (gc_component_t component, gc_backend_t backend)
|
||||
#if HAVE_W32CE_SYSTEM
|
||||
if (!(filename[0] == '/' || filename[0] == '\\'))
|
||||
#elif defined(HAVE_DOSISH_SYSTEM)
|
||||
if (!(filename[0]
|
||||
if (!(filename[0]
|
||||
&& filename[1] == ':'
|
||||
&& (filename[2] == '/' || filename[2] == '\\')))
|
||||
#else
|
||||
@ -1819,8 +1852,8 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
|
||||
estream_t config;
|
||||
char *config_filename;
|
||||
|
||||
pgmname = (gc_backend[backend].module_name
|
||||
? gnupg_module_name (gc_backend[backend].module_name)
|
||||
pgmname = (gc_backend[backend].module_name
|
||||
? gnupg_module_name (gc_backend[backend].module_name)
|
||||
: gc_backend[backend].program );
|
||||
argv[0] = "--gpgconf-list";
|
||||
argv[1] = NULL;
|
||||
@ -1839,7 +1872,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
|
||||
char *linep;
|
||||
unsigned long flags = 0;
|
||||
char *default_value = NULL;
|
||||
|
||||
|
||||
/* Strip newline and carriage return, if present. */
|
||||
while (length > 0
|
||||
&& (line[length - 1] == '\n' || line[length - 1] == '\r'))
|
||||
@ -1848,7 +1881,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
|
||||
linep = strchr (line, ':');
|
||||
if (linep)
|
||||
*(linep++) = '\0';
|
||||
|
||||
|
||||
/* Extract additional flags. Default to none. */
|
||||
if (linep)
|
||||
{
|
||||
@ -1928,7 +1961,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
|
||||
char *name;
|
||||
char *value;
|
||||
gc_option_t *option;
|
||||
|
||||
|
||||
name = line;
|
||||
while (*name == ' ' || *name == '\t')
|
||||
name++;
|
||||
@ -2015,7 +2048,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
|
||||
|
||||
|
||||
/* Retrieve the options for the component COMPONENT from backend
|
||||
BACKEND, which we already know is of type file list. */
|
||||
BACKEND, which we already know is of type file list. */
|
||||
static void
|
||||
retrieve_options_from_file (gc_component_t component, gc_backend_t backend)
|
||||
{
|
||||
@ -2115,7 +2148,7 @@ gc_component_retrieve_options (int component)
|
||||
component = 0;
|
||||
assert (component < GC_COMPONENT_NR);
|
||||
}
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
option = gc_component[component].options;
|
||||
@ -2125,16 +2158,16 @@ gc_component_retrieve_options (int component)
|
||||
if (!(option->flags & GC_OPT_FLAG_GROUP))
|
||||
{
|
||||
backend = option->backend;
|
||||
|
||||
|
||||
if (backend_seen[backend])
|
||||
{
|
||||
option++;
|
||||
continue;
|
||||
}
|
||||
backend_seen[backend] = 1;
|
||||
|
||||
|
||||
assert (backend != GC_BACKEND_ANY);
|
||||
|
||||
|
||||
if (gc_backend[backend].program)
|
||||
retrieve_options_from_program (component, backend);
|
||||
else
|
||||
@ -2161,7 +2194,7 @@ option_check_validity (gc_option_t *option, unsigned long flags,
|
||||
if (!option->active)
|
||||
gc_error (1, 0, "option %s not supported by backend %s",
|
||||
option->name, gc_backend[option->backend].name);
|
||||
|
||||
|
||||
if (option->new_flags || option->new_value)
|
||||
gc_error (1, 0, "option %s already changed", option->name);
|
||||
|
||||
@ -2816,10 +2849,10 @@ change_options_program (gc_component_t component, gc_backend_t backend,
|
||||
== GC_ARG_TYPE_STRING)
|
||||
{
|
||||
char *end;
|
||||
|
||||
|
||||
assert (*arg == '"');
|
||||
arg++;
|
||||
|
||||
|
||||
end = strchr (arg, ',');
|
||||
if (end)
|
||||
*end = '\0';
|
||||
@ -3000,16 +3033,16 @@ gc_component_change_options (int component, estream_t in, estream_t out)
|
||||
char *linep;
|
||||
unsigned long flags = 0;
|
||||
char *new_value = "";
|
||||
|
||||
|
||||
/* Strip newline and carriage return, if present. */
|
||||
while (length > 0
|
||||
&& (line[length - 1] == '\n' || line[length - 1] == '\r'))
|
||||
line[--length] = '\0';
|
||||
|
||||
|
||||
linep = strchr (line, ':');
|
||||
if (linep)
|
||||
*(linep++) = '\0';
|
||||
|
||||
|
||||
/* Extract additional flags. Default to none. */
|
||||
if (linep)
|
||||
{
|
||||
@ -3019,20 +3052,20 @@ gc_component_change_options (int component, estream_t in, estream_t out)
|
||||
end = strchr (linep, ':');
|
||||
if (end)
|
||||
*(end++) = '\0';
|
||||
|
||||
|
||||
gpg_err_set_errno (0);
|
||||
flags = strtoul (linep, &tail, 0);
|
||||
if (errno)
|
||||
gc_error (1, errno, "malformed flags in option %s", line);
|
||||
if (!(*tail == '\0' || *tail == ':' || *tail == ' '))
|
||||
gc_error (1, 0, "garbage after flags in option %s", line);
|
||||
|
||||
|
||||
linep = end;
|
||||
}
|
||||
|
||||
/* Don't allow setting of the no change flag. */
|
||||
flags &= ~GC_OPT_FLAG_NO_CHANGE;
|
||||
|
||||
|
||||
/* Extract default value, if present. Default to empty if not. */
|
||||
if (linep)
|
||||
{
|
||||
@ -3043,18 +3076,18 @@ gc_component_change_options (int component, estream_t in, estream_t out)
|
||||
new_value = linep;
|
||||
linep = end;
|
||||
}
|
||||
|
||||
|
||||
option = find_option (component, line, GC_BACKEND_ANY);
|
||||
if (!option)
|
||||
gc_error (1, 0, "unknown option %s", line);
|
||||
|
||||
|
||||
if ((option->flags & GC_OPT_FLAG_NO_CHANGE))
|
||||
{
|
||||
gc_error (0, 0, "ignoring new value for option %s",
|
||||
option->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
change_one_value (option, runtime, flags, new_value);
|
||||
}
|
||||
}
|
||||
@ -3100,10 +3133,10 @@ gc_component_change_options (int component, estream_t in, estream_t out)
|
||||
&src_filename[option->backend],
|
||||
&dest_filename[option->backend],
|
||||
&orig_filename[option->backend]);
|
||||
|
||||
|
||||
if (err)
|
||||
break;
|
||||
|
||||
|
||||
option++;
|
||||
}
|
||||
|
||||
@ -3192,14 +3225,14 @@ gc_component_change_options (int component, estream_t in, estream_t out)
|
||||
|
||||
/* If it all worked, notify the daemons of the changes. */
|
||||
if (opt.runtime)
|
||||
for (backend = 0; backend < GC_BACKEND_NR; backend++)
|
||||
for (backend = 0; backend < GC_BACKEND_NR; backend++)
|
||||
{
|
||||
if (runtime[backend] && gc_backend[backend].runtime_change)
|
||||
(*gc_backend[backend].runtime_change) ();
|
||||
(*gc_backend[backend].runtime_change) (0);
|
||||
}
|
||||
|
||||
/* Move the per-process backup file into its place. */
|
||||
for (backend = 0; backend < GC_BACKEND_NR; backend++)
|
||||
for (backend = 0; backend < GC_BACKEND_NR; backend++)
|
||||
if (orig_filename[backend])
|
||||
{
|
||||
char *backup_filename;
|
||||
@ -3236,7 +3269,7 @@ key_matches_user_or_group (char *user)
|
||||
*group++ = 0;
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
/* Under Windows we don't support groups. */
|
||||
/* Under Windows we don't support groups. */
|
||||
if (group && *group)
|
||||
gc_error (0, 0, _("Note that group specifications are ignored\n"));
|
||||
#ifndef HAVE_W32CE_SYSTEM
|
||||
@ -3384,7 +3417,7 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
|
||||
gc_option_t *option_info = NULL;
|
||||
char *p;
|
||||
int is_continuation;
|
||||
|
||||
|
||||
lineno++;
|
||||
key = line;
|
||||
while (*key == ' ' || *key == '\t')
|
||||
@ -3549,26 +3582,26 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
|
||||
*group++ = 0;
|
||||
if ((p = strchr (group, ':')))
|
||||
*p = 0; /* We better strip any extra stuff. */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
es_fprintf (listfp, "k:%s:", gc_percent_escape (key));
|
||||
es_fprintf (listfp, "%s\n", group? gc_percent_escape (group):"");
|
||||
}
|
||||
|
||||
/* All other lines are rule records. */
|
||||
es_fprintf (listfp, "r:::%s:%s:%s:",
|
||||
gc_component[component_id].name,
|
||||
gc_component[component_id].name,
|
||||
option_info->name? option_info->name : "",
|
||||
flags? flags : "");
|
||||
if (value != empty)
|
||||
es_fprintf (listfp, "\"%s", gc_percent_escape (value));
|
||||
|
||||
|
||||
es_putc ('\n', listfp);
|
||||
}
|
||||
|
||||
/* Check whether the key matches but do this only if we are not
|
||||
running in syntax check mode. */
|
||||
if ( update
|
||||
if ( update
|
||||
&& !result && !listfp
|
||||
&& (got_match || (key && key_matches_user_or_group (key))) )
|
||||
{
|
||||
@ -3632,9 +3665,9 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
|
||||
|
||||
if (opt.runtime)
|
||||
{
|
||||
for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++)
|
||||
for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++)
|
||||
if (runtime[backend_id] && gc_backend[backend_id].runtime_change)
|
||||
(*gc_backend[backend_id].runtime_change) ();
|
||||
(*gc_backend[backend_id].runtime_change) (0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* gpgconf.c - Configuration utility for GnuPG
|
||||
* Copyright (C) 2003, 2007, 2009 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2003, 2007, 2009, 2011 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -49,6 +49,7 @@ enum cmd_and_opt_values
|
||||
aListConfig,
|
||||
aCheckConfig,
|
||||
aListDirs,
|
||||
aKill,
|
||||
aReload
|
||||
};
|
||||
|
||||
@ -57,7 +58,7 @@ enum cmd_and_opt_values
|
||||
static ARGPARSE_OPTS opts[] =
|
||||
{
|
||||
{ 300, NULL, 0, N_("@Commands:\n ") },
|
||||
|
||||
|
||||
{ aListComponents, "list-components", 256, N_("list all components") },
|
||||
{ aCheckPrograms, "check-programs", 256, N_("check all programs") },
|
||||
{ aListOptions, "list-options", 256, N_("|COMPONENT|list options") },
|
||||
@ -72,9 +73,10 @@ static ARGPARSE_OPTS opts[] =
|
||||
{ aCheckConfig, "check-config", 256,
|
||||
N_("check global configuration file") },
|
||||
{ aReload, "reload", 256, N_("reload all or a given component")},
|
||||
{ aKill, "kill", 256, N_("kill a given component")},
|
||||
|
||||
{ 301, NULL, 0, N_("@\nOptions:\n ") },
|
||||
|
||||
|
||||
{ oOutput, "output", 2, N_("use as output file") },
|
||||
{ oVerbose, "verbose", 0, N_("verbose") },
|
||||
{ oQuiet, "quiet", 0, N_("quiet") },
|
||||
@ -180,6 +182,7 @@ main (int argc, char **argv)
|
||||
case aListConfig:
|
||||
case aCheckConfig:
|
||||
case aReload:
|
||||
case aKill:
|
||||
cmd = pargs.r_opt;
|
||||
break;
|
||||
|
||||
@ -189,9 +192,9 @@ main (int argc, char **argv)
|
||||
|
||||
if (log_get_errorcount (0))
|
||||
exit (2);
|
||||
|
||||
|
||||
fname = argc ? *argv : NULL;
|
||||
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case aListComponents:
|
||||
@ -240,6 +243,34 @@ main (int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
|
||||
case aKill:
|
||||
if (!fname)
|
||||
{
|
||||
es_fputs (_("usage: gpgconf [options] "), es_stderr);
|
||||
es_putc ('\n', es_stderr);
|
||||
es_fputs (_("Need one component argument"), es_stderr);
|
||||
es_putc ('\n', es_stderr);
|
||||
exit (2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Kill a given component. */
|
||||
int idx;
|
||||
|
||||
idx = gc_component_find (fname);
|
||||
if (idx < 0)
|
||||
{
|
||||
es_fputs (_("Component not found"), es_stderr);
|
||||
es_putc ('\n', es_stderr);
|
||||
exit (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
gc_component_kill (idx);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case aReload:
|
||||
if (!fname)
|
||||
{
|
||||
@ -288,7 +319,7 @@ main (int argc, char **argv)
|
||||
if (gc_process_gpgconf_conf (NULL, 1, 1, NULL))
|
||||
exit (1);
|
||||
break;
|
||||
|
||||
|
||||
case aListDirs:
|
||||
/* Show the system configuration directories for gpgconf. */
|
||||
get_outfp (&outfp);
|
||||
@ -342,6 +373,5 @@ main (int argc, char **argv)
|
||||
if (es_fclose (outfp))
|
||||
gc_error (1, errno, "error closing `%s'", opt.outfile);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,9 @@ char *gc_percent_escape (const char *src);
|
||||
|
||||
void gc_error (int status, int errnum, const char *fmt, ...);
|
||||
|
||||
/* Kill given component. */
|
||||
void gc_component_kill (int component);
|
||||
|
||||
/* Reload given component. */
|
||||
void gc_component_reload (int component);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user