aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/ChangeLog252
-rw-r--r--tools/Makefile.am39
-rw-r--r--tools/Manifest6
-rw-r--r--tools/README.gpgconf422
-rwxr-xr-xtools/addgnupghome122
-rwxr-xr-xtools/der-to-pem27
-rw-r--r--tools/gpgconf-comp.c2434
-rw-r--r--tools/gpgconf.c206
-rw-r--r--tools/gpgconf.h58
-rw-r--r--tools/gpgparsemail.c705
-rw-r--r--tools/no-libgcrypt.c105
-rw-r--r--tools/rfc822parse.c1235
-rw-r--r--tools/rfc822parse.h79
-rw-r--r--tools/watchgnupg.c389
14 files changed, 0 insertions, 6079 deletions
diff --git a/tools/ChangeLog b/tools/ChangeLog
deleted file mode 100644
index a81a2d301..000000000
--- a/tools/ChangeLog
+++ /dev/null
@@ -1,252 +0,0 @@
-2004-06-14 Werner Koch <[email protected]>
-
- * no-libgcrypt.c (gcry_realloc, gcry_xmalloc, gcry_xcalloc): New.
-
- * gpgconf-comp.c (retrieve_options_from_program)
- (retrieve_options_from_file, change_options_file)
- (change_options_program, gc_component_change_options): Replaced
- getline by read_line and test for allocation failure.
-
-2004-05-21 Marcus Brinkmann <[email protected]>
-
- * gpgconf-comp.c (gc_options_dirmngr): Remove CRL group, put its
- only option "max-replies" into LDAP group.
- (gc_component): Change description of dirmngr to "Directory
- Manager".
-
- * gpgconf-comp.c (gc_component_change_options): Move the
- per-process backup file into a standard location.
-
-2004-05-03 Werner Koch <[email protected]>
-
- * gpgconf-comp.c: Add --allow-mark-trusted for the gpg-agent.
-
-2004-04-30 Werner Koch <[email protected]>
-
- * gpgconf-comp.c: Added more runtime flags for the gpg-agent
- backend.
-
-2004-04-29 Marcus Brinkmann <[email protected]>
-
- * gpgconf-comp.c (change_options_program): Turn on utf8-strings in
- the gpgconf specific part of the config file for the GnuPG
- backend.
-
-2004-04-28 Werner Koch <[email protected]>
-
- * gpgconf-comp.c: Add --ocsp-signer for the dirmngr backend.
-
-2004-04-20 Marcus Brinkmann <[email protected]>
-
- * gpgconf-comp.c (gc_options_gpg_agent): Change type of
- ignore-cache-for-signing option to GC_ARG_TYPE_NONE.
-
-2004-04-07 Werner Koch <[email protected]>
-
- * gpgconf-comp.c (my_dgettext): Switch the codeset once to utf-8.
- Allow building with out NLS.
-
-2004-03-23 Marcus Brinkmann <[email protected]>
-
- * gpgconf-comp.c (gc_options_dirmngr): Set GC_OPT_FLAG_ARG_OPT for
- "LDAP Server".
- (change_options_file): Remove assertion that tests that this flag
- is not present. Handle an empty string in OPTION->new_value.
-
- * gpgconf.c (main): Remove obsolete warning.
-
-2004-03-23 Werner Koch <[email protected]>
-
- * gpgconf-comp.c (gc_options_gpg): New.
- (gc_component_t, gc_component): Add GC_BACKEND_GPG.
- (gc_options_dirmngr): Add allow-ocsp.
-
-2004-03-23 Marcus Brinkmann <[email protected]>
-
- * gpgconf-comp.c (gc_flag): Add missing flags.
-
- * gpgconf-comp.c: Include <signal.h>.
- (gc_backend): Add new member runtime_change.
- (gpg_agent_runtime_change): New function.
- (gc_component_change_options): New variable runtime. Initialize
- it. If an option is changed that has the GC_OPT_FLAG_RUNTIME bit
- set, also set the corresponding runtime variable. Finally, call
- the runtime_change callback of the backend if needed.
-
-2004-03-16 Werner Koch <[email protected]>
-
- * gpgconf-comp.c (gc_options_gpg_agent): Implemented.
- (gc_options_gpgsm, gc_options_scdaemon): Implemented.
- (gc_backend_t): Add GC_BACKEND_SCDAEMON.
-
-2004-03-12 Marcus Brinkmann <[email protected]>
-
- * gpgconf-comp.c (gc_component_change_options): Set the filenames
- of the option's backend, not of the component.
- Also use GC_BACKEND_NR, not GC_COMPONENT_NR.
-
-2004-03-09 Werner Koch <[email protected]>
-
- * gpgconf-comp.c [_riscos_]: Removed special code for RISC OS; we
- don't want to clutter our code with system dependent stuff.
-
-2004-03-08 Marcus Brinkmann <[email protected]>
-
- * gpgconf-comp.c (retrieve_options_from_file): Quote each string
- in the list, not only the first.
-
-2004-02-26 Marcus Brinkmann <[email protected]>
-
- * gpgconf-comp.c (gc_component_list_options): Do not print empty
- groups.
-
- * gpgconf-comp.c (option_check_validity): Check if option is
- active.
- (change_options_file): Implement.
-
- * gpgconf-comp.c (retrieve_options_from_program): Remove broken
- string handling.
-
- * gpgconf-comp.c (change_options_program): Support all types of
- options, including list types.
-
- * README.gpgconf: Fix description of arguments.
- * gpgconf-comp.c (option_check_validity): Rewritten to properly
- support optional arguments in lists.
-
- * README.gpgconf: Add info about optional arg and arg type 0.
- * gpgconf-comp.c (gc_component_change_options): Parse list of
- arg type 0 options.
- (option_check_validity): Add new argument NEW_VALUE_NR. Perform
- rigorous validity checks.
- (change_options_program): Disable an option also if we have a new
- value for it.
-
-2004-02-25 Marcus Brinkmann <[email protected]>
-
- * gpgconf-comp.c (gc_component_list_options): Correct output for
- lists of arg type none.
- (struct gc_option): Add new member new_flags.
- (option_check_validity): Check OPTION->new_flags beside
- OPTION->new_value. Add new argument FLAGS.
- (gc_component_change_options): Support default flag correctly.
- (change_options_program): Likewise.
-
-2004-02-24 Marcus Brinkmann <[email protected]>
-
- * README.gpgconf: Revert last change. Add new flags "default",
- "default desc" and "no arg desc". Add new field ARGDEF. Add new
- field FLAG to backend interface.
- * gpgconf-comp.c (struct gc_option): Make flags of type unsigned
- long.
- (gc_component_list_options): Adjust type for flags.
- Add default argument field.
- (retrieve_options_from_program): Use "1" as value for non-option
- arguments, not "Y".
- (gc_component_change_options): Read in flags from input.
-
-2004-02-23 Marcus Brinkmann <[email protected]>
-
- * README.gpgconf: Change meaning of type 0 options value if it is
- the empty string or "0".
-
- * gpgconf.h (struct): Add member runtime.
- * gpgconf.c: Add new option oRuntime.
- (main): Same here.
-
- * gpgconf-comp.c (hextobyte): New function.
- (percent_deescape): New function.
- (get_config_pathname): Percent deescape pathname if taken from
- option (default) value. Use default value only if it exists and
- is not empty. Use empty string otherwise. Don't include leading
- quote in pathname.
- (change_options_program): Percent deescape string before writing
- it out.
-
- * gpgconf-comp.c (gc_component_list_options): Do not skip groups
- on output.
-
-2004-02-18 Werner Koch <[email protected]>
-
- * gpgconf-comp.c: Added empty components for gpgsm and scdaemon.
-
-2004-02-12 Werner Koch <[email protected]>
-
- * watchgnupg.c (main): Implement option "--".
- (print_version): New.
-
- * Makefile.am: Include cmacros.am for common flags.
-
-2004-02-03 Werner Koch <[email protected]>
-
- * addgnupghome: Try to use getent, so that it also works for NIS
- setups.
-
-2004-01-31 Marcus Brinkmann <[email protected]>
-
- * gpgconf-comp.c: Some bug fixes, parse only defaults from the
- program, and read the current values from the configuration file
- directly.
-
-2004-01-30 Marcus Brinkmann <[email protected]>
-
- * gpgconf-comp.c (gc_error): New function, use it instead of
- error() throughout.
-
- * gpgconf-comp.c: Use xmalloc, libcommon's asctimestamp and
- gnupg_get_time, fix error() invocation and use getline()
- consistently.
-
-2004-01-30 Werner Koch <[email protected]>
-
- * addgnupghome: Also set the group of copied files.
-
-2004-01-30 Werner Koch <[email protected]>
-
- * Makefile.am (sbin_SCRIPTS): New, to install addgnupghome.
- (EXTRA_DIST): Added rfc822parse.c rfc822parse.h gpgparsemail.c
- which might be useful for debugging.
-
-2004-01-29 Werner Koch <[email protected]>
-
- * addgnupghome: New.
-
-2004-01-29 Marcus Brinkmann <[email protected]>
-
- * gpgconf-list.c: File removed.
- * README.gpgconf: New file.
- * gpgconf-comp.c: New file.
- * Makefile.am (gpgconf_SOURCES): Remove gpgconf-list.c, add
- gpgconf-comp.c.
-
-2004-01-16 Werner Koch <[email protected]>
-
- * watchgnupg.c (main): Need to use FD_ISSET for the client
- descriptors too; aiiih. Set the listening socket to non-blocking.
-
-2004-01-10 Werner Koch <[email protected]>
-
- * Makefile.am: Use GPG_ERROR_CFLAGS
-
-2004-01-05 Werner Koch <[email protected]>
-
- * Manifest: New.
- * gpgconf.c, gpgconf.h, gpgconf-list.c: New. A skeleton for now.
- * no-libgcrypt.c: New.
- * Makefile.am: Add above.
-
-2003-12-23 Werner Koch <[email protected]>
-
- * Makefile.am: New.
- * watchgnupg.c: New.
-
-
- Copyright 2003, 2004 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
- modifications, as long as this notice is preserved.
-
- This file is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/tools/Makefile.am b/tools/Makefile.am
deleted file mode 100644
index 71a77356f..000000000
--- a/tools/Makefile.am
+++ /dev/null
@@ -1,39 +0,0 @@
-# Makefile.am - Tools directory
-# Copyright (C) 2003 Free Software Foundation, Inc.
-#
-# This file is part of GnuPG.
-#
-# GnuPG is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# GnuPG 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 General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-
-EXTRA_DIST = Manifest watchgnupg.c \
- rfc822parse.c rfc822parse.h gpgparsemail.c \
- addgnupghome
-
-AM_CPPFLAGS = -I$(top_srcdir)/intl -I$(top_srcdir)/common
-include $(top_srcdir)/am/cmacros.am
-
-# Note, that we require GPG_ERROR_CFLAGS only because some share header files
-# require that file. It is not actually used in gpgconf.
-AM_CFLAGS = @GPG_ERROR_CFLAGS@
-
-sbin_SCRIPTS = addgnupghome
-
-bin_PROGRAMS = gpgconf watchgnupg
-
-gpgconf_SOURCES = gpgconf.c gpgconf.h gpgconf-comp.c no-libgcrypt.c
-
-gpgconf_LDADD = ../jnlib/libjnlib.a ../common/libcommon.a @INTLLIBS@
-
-watchgnupg_SOURCES = watchgnupg.c
diff --git a/tools/Manifest b/tools/Manifest
deleted file mode 100644
index 96423352d..000000000
--- a/tools/Manifest
+++ /dev/null
@@ -1,6 +0,0 @@
-Makefile.am
-watchgnupg.c
-gpgconf.c
-gpgconf.h
-gpgconf-list.c
-$names$
diff --git a/tools/README.gpgconf b/tools/README.gpgconf
deleted file mode 100644
index c0d3c7c61..000000000
--- a/tools/README.gpgconf
+++ /dev/null
@@ -1,422 +0,0 @@
-============
- GPG Conf
-============
-
-CONCEPT
-=======
-
-gpgconf provides access to the configuration of one or more components
-of the GnuPG system. These components correspond more or less to the
-programs that exist in the GnuPG framework, like GnuPG, GPGSM,
-DirMngr, etc. But this is not a strict one-to-one relationship. Not
-all configuration options are available through GPGConf. GPGConf
-provides a generic and abstract method to access the most important
-configuration options that can feasibly be controlled via such a
-mechanism.
-
-GPGConf can be used to gather and change the options available in each
-component, and can also provide their default values. GPGConf will
-give detailed type information that can be used to restrict the user's
-input without making an attempt to commit the changes.
-
-GPGConf provides the backend of a configuration editor. The
-configuration editor would usually be a graphical user interface
-program, that allows to display the current options, their default
-values, and allows the user to make changes to the options. These
-changes can then be made active with GPGConf again. Such a program
-that uses GPGConf in this way will be called 'GUI' throughout this
-document.
-
-
-Format Conventions
-==================
-
-Some lines in the output of GPGConf contain a list of colon-separated
-fields. The following conventions apply:
-
-The GUI program is required to strip off trailing newline and/or carriage
-return characters from the output.
-
-GPGConf will never leave out fields. If a certain version documents a
-certain field, this field will always be present in all GPGConf
-versions from that time on.
-
-Future versions of GPGConf might append fields to the list. New
-fields will always be separated from the previously last field by a
-colon separator. The GUI should be prepared to parse the last field
-it knows about up until a colon or end of line.
-
-Not all fields are defined under all conditions. You are required to
-ignore the content of undefined fields.
-
-Some fields contain strings that are not escaped in any way. Such
-fields are described to be used "verbatim". These fields will never
-contain a colon character (for obvious reasons). No de-escaping or
-other formatting is required to use the field content. This is for
-easy parsing of the output, when it is known that the content can
-never contain any special characters.
-
-Some fields contain strings that are described to be
-"percent-escaped". Such strings need to be de-escaped before their
-content can be presented to the user. A percent-escaped string is
-de-escaped by replacing all occurences of %XY by the byte that has the
-hexadecimal value XY. X and Y are from the set { '0'..'9', 'a'..'f' }.
-
-Some fields contain strings that are described to be "localised". Such
-strings are translated to the active language and formatted in the
-active character set.
-
-Some fields contain an unsigned number. This number will always fit
-into a 32-bit unsigned integer variable. The number may be followed
-by a space, followed by a human readable description of that value.
-You should ignore everything in the field that follows the number.
-
-Some fields contain a signed number. This number will always fit into
-a 32-bit signed integer variable. The number may be followed by a
-space, followed by a human readable description of that value. You
-should ignore everything in the field that follows the number.
-
-Some fields contain an option argument. The format of an option
-argument depends on the type of the option and on some flags:
-
-The simplest case is that the option does not take an argument at all
-(TYPE is 0). Then the option argument is an unsigned number that
-specifies how often the option occurs. If the LIST flag is not set,
-then the only valid number is 1. Options that don't take an argument
-never have the "default" or "optional arg" flag set.
-
-If the option takes a number argument (ALT-TYPE is 2 or 3), and it can
-only occur once (LIST flag is not set), then the option argument is
-either empty (only allowed if the argument is optional), or it is a
-number. A number is a string that begins with an optional minus
-character, followed by one or more digits. The number must fit into
-an integer variable (unsigned or signed, depending on ALT-TYPE).
-
-If the option takes a number argument and it can occur more than once,
-then the option argument is either empty, or it is a comma-separated
-list of numbers as described above.
-
-If the option takes a string argument (ALT-TYPE is 1), and it can only
-occur once (LIST flag is not set) then the option argument is either
-empty (only allowed if the argument is optional), or it starts with a
-double quote character (") followed by a percent-escaped string that
-is the argument value. Note that there is only a leading double quote
-character, no trailing one. The double quote character is only needed
-to be able to differentiate between no value and the empty string as
-value.
-
-If the option takes a number argument and it can occur more than once,
-then the option argument is either empty, or it is a comma-separated
-list of string arguments as described above.
-
-FIXME: Document the active language and active character set. Allow
-to change it via the command line?
-
-
-Components
-==========
-
-A component is a set of configuration options that semantically belong
-together. Furthermore, several changes to a component can be made in
-an atomic way with a single operation. The GUI could for example
-provide a menu with one entry for each component, or a window with one
-tabulator sheet per component.
-
-The following interface is provided to list the available components:
-
-Command --list-components
--------------------------
-
-Outputs a list of all components available, one per line. The format
-of each line is:
-
-NAME:DESCRIPTION
-
-NAME
-
-This field contains a name tag of the component. The name tag is used
-to specify the component in all communication with GPGConf. The name
-tag is to be used verbatim. It is not in any escaped format.
-
-DESCRIPTION
-
-The string in this field contains a human-readable description of the
-component. It can be displayed to the user of the GUI for
-informational purposes. It is percent-escaped and localized.
-
-Example:
-$ gpgconf --list-components
-gpg-agent:GPG Agent
-dirmngr:CRL Manager
-
-
-OPTIONS
-=======
-
-Every component contains one or more options. Options may belong to a
-group. The following command lists all options and the groups they
-belong to:
-
-Command --list-options COMPONENT
---------------------------------
-
-Lists all options (and the groups they belong to) in the component
-COMPONENT. COMPONENT is the string in the field NAME in the
-output of the --list-components command.
-
-There is one line for each option and each group. First come all
-options that are not in any group. Then comes a line describing a
-group. Then come all options that belong into each group. Then comes
-the next group and so on.
-
-The format of each line is:
-
-NAME:FLAGS:LEVEL:DESCRIPTION:TYPE:ALT-TYPE:ARGNAME:DEFAULT:ARGDEF:VALUE
-
-NAME
-
-This field contains a name tag for the group or option. The name tag
-is used to specify the group or option in all communication with
-GPGConf. The name tag is to be used verbatim. It is not in any
-escaped format.
-
-FLAGS
-
-The flags field contains an unsigned number. Its value is the
-OR-wise combination of the following flag values:
-
- 1 group If this flag is set, this is a line describing
- a group and not an option.
- O 2 optional arg If this flag is set, the argument is optional.
- This is never set for arg type 0 (none) options.
- O 4 list If this flag is set, the option can be given
- multiple times.
- O 8 runtime If this flag is set, the option can be changed
- at runtime.
- O 16 default If this flag is set, a default value is available.
- O 32 default desc If this flag is set, a (runtime) default is available.
- This and the 'default' flag are mutually exclusive.
- O 64 no arg desc If this flag is set, and the 'optional arg' flag
- is set, then the option has a special meaning if no
- argument is given.
-
-Flags marked with a 'O' are only defined for options (ie, if the GROUP
-flag is not set).
-
-LEVEL
-
-This field is defined for options and for groups. It contains an
-unsigned number that specifies the expert level under which this group
-or option should be displayed. The following expert levels are
-defined for options (they have analogous meaning for groups):
-
- 0 basic This option should always be offered to the user.
- 1 advanced This option may be offered to advanced users.
- 2 expert This option should only be offered to expert users.
- 3 invisible This option should normally never be displayed,
- not even to expert users.
- 4 internal This option is for internal use only. Ignore it.
-
-The level of a group will always be the lowest level of all options it
-contains.
-
-DESCRIPTION
-
-This field is defined for options and groups. The string in this
-field contains a human-readable description of the option or group.
-It can be displayed to the user of the GUI for informational purposes.
-It is percent-escaped and localized.
-
-TYPE
-
-This field is only defined for options. It contains an unsigned
-number that specifies the type of the option's argument, if any.
-The following types are defined:
-
- Basic types
- 0 none No argument allowed.
- 1 string An unformatted string.
- 2 int32 A signed integer number.
- 3 uint32 An unsigned integer number.
-
- Complex types
- 32 pathname A string that describes the pathname of a file.
- The file does not necessarily need to exist.
- 33 ldap server A string that describes an LDAP server in the format
- HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN.
-
-More types will be added in the future. Please see the ALT-TYPE field
-for information on how to cope with unknown types.
-
-ALT-TYPE
-
-This field is identical to TYPE, except that only the types 0 to 31
-are allowed. The GUI is expected to present the user the option in
-the format specified by TYPE. But if the argument type TYPE is not
-supported by the GUI, it can still display the option in the more
-generic basic type ALT-TYPE. The GUI must support all the defined
-basic types to be able to display all options. More basic types may
-be added in future versions. If the GUI encounters a basic type it
-doesn't support, it should report an error and abort the operation.
-
-ARGNAME
-
-This field is only defined for options with an argument type TYPE that
-is not 0. In this case it may contain a percent-escaped and localised
-string that gives a short name for the argument. The field may also
-be empty, though, in which case a short name is not known.
-
-DEFAULT
-
-This field is defined only for options. Its format is that of an
-option argument (see section Format Conventions for details). If the
-default value is empty, then no default is known. Otherwise, the
-value specifies the default value for this option. Note that this
-field is also meaningful if the option itself does not take a real
-argument.
-
-ARGDEF
-
-This field is defined only for options for which the "optional arg"
-flag is set. If the "no arg desc" flag is not set, its format is that
-of an option argument (see section Format Conventions for details).
-If the default value is empty, then no default is known. Otherwise,
-the value specifies the default value for this option. If the "no arg
-desc" flag is set, the field is either empty or contains a description
-of the effect of this option if no argument is given. Note that this
-field is also meaningful if the option itself does not take a real
-argument.
-
-VALUE
-
-This field is defined only for options. Its format is that of an
-option argument. If it is empty, then the option is not explicitely
-set in the current configuration, and the default applies (if any).
-Otherwise, it contains the current value of the option. Note that
-this field is also meaningful if the option itself does not take a
-real argument.
-
-
-CHANGING OPTIONS
-================
-
-To change the options for a component, you must provide them in the
-following format:
-
-NAME:FLAGS:NEW-VALUE
-
-NAME
-
-This is the name of the option to change.
-
-FLAGS
-
-The flags field contains an unsigned number. Its value is the
-OR-wise combination of the following flag values:
-
- 16 default If this flag is set, the option is deleted and the
- default value is used instead (if applicable).
-
-NEW-VALUE
-
-The new value for the option. This field is only defined if the
-"default" flag is not set. The format is that of an option argument.
-If it is empty (or the field is omitted), the default argument is used
-(only allowed if the argument is optional for this option).
-Otherwise, the option will be set to the specified value.
-
-
-Example:
-To set the option force, which is of basic type 0 (none).
-$ echo 'force:0:1' | gpgconf --change-options dirmngr
-To delete the option force:
-$ echo 'force:16:' | gpgconf --change-options dirmngr
-
-
-Option --runtime
-----------------
-
-If this option is set, the changes will take effect at run-time, as
-far as this is possible. Otherwise, they will take effect at the next
-start of the respective backend programs.
-
-
-BACKENDS
-========
-
-Backends should support the following commands:
-
-Command --gpgconf-list
-----------------------
-
-List the location of the configuration file, and all default values of
-all options. The location of the configuration file must be an
-absolute pathname.
-
-The format of each line is:
-
-NAME:FLAGS:DEFAULT:ARGDEF
-
-NAME
-
-This field contains a name tag for the group or option. The name tag
-is used to specify the group or option in all communication with
-GPGConf. The name tag is to be used verbatim. It is not in any
-escaped format.
-
-FLAGS
-
-The flags field contains an unsigned number. Its value is the
-OR-wise combination of the following flag values:
-
- 16 default If this flag is set, a default value is available.
- 32 default desc If this flag is set, a (runtime) default is available.
- This and the "default" flag are mutually exclusive.
- 64 no arg desc If this flag is set, and the "optional arg" flag
- is set, then the option has a special meaning if no
- argument is given.
-
-DEFAULT
-
-This field is defined only for options. Its format is that of an
-option argument (see section Format Conventions for details). If the
-default value is empty, then no default is known. Otherwise, the
-value specifies the default value for this option. Note that this
-field is also meaningful if the option itself does not take a real
-argument.
-
-ARGDEF
-
-This field is defined only for options for which the "optional arg"
-flag is set. If the "no arg desc" flag is not set, its format is that
-of an option argument (see section Format Conventions for details).
-If the default value is empty, then no default is known. Otherwise,
-the value specifies the default value for this option. If the "no arg
-desc" flag is set, the field is either empty or contains a description
-of the effect of this option if no argument is given. Note that this
-field is also meaningful if the option itself does not take a real
-argument.
-
-
-Example:
-$ dirmngr --gpgconf-list
-gpgconf-config-file:/mnt/marcus/.gnupg/dirmngr.conf
-ldapservers-file:/mnt/marcus/.gnupg/dirmngr_ldapservers.conf
-add-servers:0
-max-replies:10
-
-
-TODO
-----
-
-* Extend the backend interface to include gettext domain and
-description, if available, to avoid repeating this information in
-gpgconf.
-
-* Left out string arguments (optional) are written out exactly as
-empty string arguments. Should we do quoting?
-
-* More string argument trouble: Special characters like newlines etc
-cause trouble. Again, should we do quoting?
-
-
diff --git a/tools/addgnupghome b/tools/addgnupghome
deleted file mode 100755
index 37a427bf2..000000000
--- a/tools/addgnupghome
+++ /dev/null
@@ -1,122 +0,0 @@
-# !/bin/sh -*- sh -*-
-# Add a new .gnupg home directory for a list of users
-#
-# Copyright 2004 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
-# modifications, as long as this notice is preserved.
-#
-# This file is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-PGM=addgnupghome
-any_error=0
-
-
-error () {
- echo "$PGM: $*" >&2
- any_error=1
-}
-
-info () {
- echo "$PGM: $*" >&2
-}
-
-# Do it for one user
-one_user () {
- user="$1"
- home=$(${cat_passwd} | awk -F: -v n="$user" '$1 == n {print $6}')
- if [ -z "$home" ]; then
- if ${cat_passwd} | awk -F: -v n="$user" '$1 == n {exit 1}'; then
- error "no such user \`$user'"
- else
- error "no home directory for user \`$user'"
- fi
- return
- fi
- if [ ! -d "$home" ]; then
- error "home directory \`$home' of user \`$user' does not exist"
- return
- fi
- if [ -d "$home/.gnupg" ]; then
- info "skipping user \`$user': \`.gnupg' already exists"
- return
- fi
- info "creating home directory \`$home/.gnupg' for \`$user'"
- if ! mkdir "$home/.gnupg" ; then
- error "error creating \`$home/.gnupg'"
- return
- fi
-
- if ! chown $user "$home/.gnupg" ; then
- error "error changing ownership of \`$home/.gnupg'"
- return
- fi
-
- group=$(id -g "$user")
- [ -z "$group" ] && group="0"
-
- if [ "$group" -gt 0 ]; then
- if ! chgrp $group "$home/.gnupg" ; then
- error "error changing group of \`$home/.gnupg'"
- return
- fi
- fi
-
- if ! cd "$home/.gnupg" ; then
- error "error cd-ing to \`$home/.gnupg'"
- return
- fi
- for f in $filelist; do
- if [ -d /etc/skel/.gnupg/$f ]; then
- mkdir $f
- else
- cp /etc/skel/.gnupg/$f $f
- fi
- if ! chown $user $f ; then
- error "error changing ownership of \`$f'"
- return
- fi
- if [ "$group" -gt 0 ]; then
- if ! chgrp $group "$f" ; then
- error "error changing group of \`$f'"
- return
- fi
- fi
- done
-
-}
-
-if [ -z "$1" ]; then
- echo "usage: $PGM userids"
- exit 1
-fi
-
-# Check whether we can use getent
-if getent --help </dev/null >/dev/null 2>&1 ; then
- cat_passwd='getent passwd'
-else
- cat_passwd='cat /etc/passwd'
- info "please note that only users from /etc/passwd are checked"
-fi
-
-if [ ! -d /etc/skel/.gnupg ]; then
- error "skeleton directory \`/etc/skel/.gnupg' does not exist"
- exit 1
-fi
-cd "/etc/skel/.gnupg" || (error "error cd-ing to \`/etc/skel/.gnupg'"; exit 1)
-filelist=$(find . \( -type f -or -type d \) -not -name '*~' -not -name . -print)
-
-
-if ! umask 0077 ; then
- error "error setting umask"
- exit 1
-fi
-
-for name in $*; do
- one_user $name
-done
-
-exit $any_error
diff --git a/tools/der-to-pem b/tools/der-to-pem
deleted file mode 100755
index 183996654..000000000
--- a/tools/der-to-pem
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh
-# Convert A BER or DER encoding to PEM format.
-#
-# Copyright 20032 Free Software Foundation, Inc.
-#
-# This program is Free Software; as a special exception the author gives
-# unlimited permission to copy and/or distribute it, with or without
-# modifications, as long as this notice is preserved.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-PGM="der-to-pem"
-if [ $# == 0 ]; then
- input=""
-elif [ $# == 1 ]; then
- input="$1"
-else
- echo "usage: $PGM [<inputfile>]" >&2
- exit 1
-fi
-
-echo "-----BEGIN CERTIFICATE-----"
-mimencode $input
-echo "-----END CERTIFICATE-----"
-
diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c
deleted file mode 100644
index cc0751d0c..000000000
--- a/tools/gpgconf-comp.c
+++ /dev/null
@@ -1,2434 +0,0 @@
-/* gpgconf-comp.c - Configuration utility for GnuPG.
- Copyright (C) 2004 Free Software Foundation, Inc.
-
- This file is part of GnuPG.
-
- GnuPG is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- GnuPG 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
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GnuPG; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-/* FIXME use gettext.h */
-#include <libintl.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <assert.h>
-#include <errno.h>
-#include <time.h>
-#include <stdarg.h>
-#include <signal.h>
-
-/* For log_logv(), asctimestamp(), gnupg_get_time (). */
-#define JNLIB_NEED_LOG_LOGV
-#include "util.h"
-
-#include "gpgconf.h"
-
-
-/* TODO:
- Components: Add more components and their options.
- Robustness: Do more validation. Call programs to do validation for us.
- Don't use popen, as this will not tell us if the program had a
- non-zero exit code.
- Add options to change backend binary path.
- Extract binary path for some backends from gpgsm/gpg config.
-*/
-
-
-#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ))
-void gc_error (int status, int errnum, const char *fmt, ...) \
- __attribute__ ((format (printf, 3, 4)));
-#endif
-
-/* Output a diagnostic message. If ERRNUM is not 0, then the output
- is followed by a colon, a white space, and the error string for the
- error number ERRNUM. In any case the output is finished by a
- newline. The message is prepended by the program name, a colon,
- and a whitespace. The output may be further formatted or
- redirected by the jnlib logging facility. */
-void
-gc_error (int status, int errnum, const char *fmt, ...)
-{
- va_list arg_ptr;
-
- va_start (arg_ptr, fmt);
- log_logv (JNLIB_LOG_ERROR, fmt, arg_ptr);
- va_end (arg_ptr);
-
- if (errnum)
- log_printf (": %s\n", strerror (errnum));
- else
- log_printf ("\n");
-
- if (status)
- {
- log_printf (NULL);
- log_printf ("fatal error (exit status %i)\n", status);
- exit (status);
- }
-}
-
-
-/* Forward declaration. */
-void gpg_agent_runtime_change (void);
-
-/* Backend configuration. Backends are used to decide how the default
- and current value of an option can be determined, and how the
- option can be changed. To every option in every component belongs
- exactly one backend that controls and determines the option. Some
- backends are programs from the GPG system. Others might be
- implemented by GPGConf itself. If you change this enum, don't
- forget to update GC_BACKEND below. */
-typedef enum
- {
- /* Any backend, used for find_option (). */
- GC_BACKEND_ANY,
-
- /* The Gnu Privacy Guard. */
- GC_BACKEND_GPG,
-
- /* The Gnu Privacy Guard for S/MIME. */
- GC_BACKEND_GPGSM,
-
- /* The GPG Agent. */
- GC_BACKEND_GPG_AGENT,
-
- /* The GnuPG SCDaemon. */
- GC_BACKEND_SCDAEMON,
-
- /* The Aegypten directory manager. */
- GC_BACKEND_DIRMNGR,
-
- /* The LDAP server list file for the Aegypten director manager. */
- GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST,
-
- /* The number of the above entries. */
- GC_BACKEND_NR
- } gc_backend_t;
-
-
-/* To be able to implement generic algorithms for the various
- backends, we collect all information about them in this struct. */
-static struct
-{
- /* The name of the backend. */
- const char *name;
-
- /* The name of the program that acts as the backend. Some backends
- don't have an associated program, but are implemented directly by
- GPGConf. In this case, PROGRAM is NULL. */
- char *program;
-
- /* The runtime change callback. */
- void (*runtime_change) (void);
-
- /* The option name for the configuration filename of this backend.
- This must be an absolute pathname. It can be an option from a
- different backend (but then ordering of the options might
- matter). */
- const char *option_config_filename;
-
- /* If this is a file backend rather than a program backend, then
- this is the name of the option associated with the file. */
- const char *option_name;
-} gc_backend[GC_BACKEND_NR] =
- {
- { NULL }, /* GC_BACKEND_ANY dummy entry. */
- { "GnuPG", "gpg", NULL, "gpgconf-gpg.conf" },
- { "GPGSM", "gpgsm", NULL, "gpgconf-gpgsm.conf" },
- { "GPG Agent", "gpg-agent", gpg_agent_runtime_change,
- "gpgconf-gpg-agent.conf" },
- { "SCDaemon", "scdaemon", NULL, "gpgconf-scdaemon.conf" },
- { "DirMngr", "dirmngr", NULL, "gpgconf-dirmngr.conf" },
- { "DirMngr LDAP Server List", NULL, NULL, "ldapserverlist-file",
- "LDAP Server" },
- };
-
-
-/* Option configuration. */
-
-/* An option might take an argument, or not. Argument types can be
- basic or complex. Basic types are generic and easy to validate.
- Complex types provide more specific information about the intended
- use, but can be difficult to validate. If you add to this enum,
- don't forget to update GC_ARG_TYPE below. YOU MUST NOT CHANGE THE
- NUMBERS OF THE EXISTING ENTRIES, AS THEY ARE PART OF THE EXTERNAL
- INTERFACE. */
-typedef enum
- {
- /* Basic argument types. */
-
- /* No argument. */
- GC_ARG_TYPE_NONE = 0,
-
- /* A String argument. */
- GC_ARG_TYPE_STRING = 1,
-
- /* A signed integer argument. */
- GC_ARG_TYPE_INT32 = 2,
-
- /* An unsigned integer argument. */
- GC_ARG_TYPE_UINT32 = 3,
-
- /* ADD NEW BASIC TYPE ENTRIES HERE. */
-
- /* Complex argument types. */
-
- /* A complete pathname. */
- GC_ARG_TYPE_PATHNAME = 32,
-
- /* An LDAP server in the format
- HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN. */
- GC_ARG_TYPE_LDAP_SERVER = 33,
-
- /* A 40 character fingerprint. */
- GC_ARG_TYPE_KEY_FPR = 34,
-
- /* ADD NEW COMPLEX TYPE ENTRIES HERE. */
-
- /* The number of the above entries. */
- GC_ARG_TYPE_NR
- } gc_arg_type_t;
-
-
-/* For every argument, we record some information about it in the
- following struct. */
-static struct
-{
- /* For every argument type exists a basic argument type that can be
- used as a fallback for input and validation purposes. */
- gc_arg_type_t fallback;
-
- /* Human-readable name of the type. */
- const char *name;
-} gc_arg_type[GC_ARG_TYPE_NR] =
- {
- /* The basic argument types have their own types as fallback. */
- { GC_ARG_TYPE_NONE, "none" },
- { GC_ARG_TYPE_STRING, "string" },
- { GC_ARG_TYPE_INT32, "int32" },
- { GC_ARG_TYPE_UINT32, "uint32" },
-
- /* Reserved basic type entries for future extension. */
- { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
- { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
- { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
- { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
- { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
- { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
- { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
- { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
- { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
- { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
- { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
- { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
- { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
- { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
-
- /* The complex argument types have a basic type as fallback. */
- { GC_ARG_TYPE_STRING, "pathname" },
- { GC_ARG_TYPE_STRING, "ldap server" },
- { GC_ARG_TYPE_STRING, "key fpr" },
- };
-
-
-/* Every option has an associated expert level, than can be used to
- hide advanced and expert options from beginners. If you add to
- this list, don't forget to update GC_LEVEL below. YOU MUST NOT
- CHANGE THE NUMBERS OF THE EXISTING ENTRIES, AS THEY ARE PART OF THE
- EXTERNAL INTERFACE. */
-typedef enum
- {
- /* The basic options should always be displayed. */
- GC_LEVEL_BASIC,
-
- /* The advanced options may be hidden from beginners. */
- GC_LEVEL_ADVANCED,
-
- /* The expert options should only be displayed to experts. */
- GC_LEVEL_EXPERT,
-
- /* The invisible options should normally never be displayed. */
- GC_LEVEL_INVISIBLE,
-
- /* The internal options are never exported, they mark options that
- are recorded for internal use only. */
- GC_LEVEL_INTERNAL,
-
- /* ADD NEW ENTRIES HERE. */
-
- /* The number of the above entries. */
- GC_LEVEL_NR
- } gc_expert_level_t;
-
-/* A description for each expert level. */
-static struct
-{
- const char *name;
-} gc_level[] =
- {
- { "basic" },
- { "advanced" },
- { "expert" },
- { "invisible" },
- { "internal" }
- };
-
-
-/* Option flags. YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING
- FLAGS, AS THEY ARE PART OF THE EXTERNAL INTERFACE. */
-#define GC_OPT_FLAG_NONE 0UL
-/* Some entries in the option list are not options, but mark the
- beginning of a new group of options. These entries have the GROUP
- flag set. */
-#define GC_OPT_FLAG_GROUP (1UL << 0)
-/* The ARG_OPT flag for an option indicates that the argument is
- optional. This is never set for GC_ARG_TYPE_NONE options. */
-#define GC_OPT_FLAG_ARG_OPT (1UL << 1)
-/* The LIST flag for an option indicates that the option can occur
- several times. A comma separated list of arguments is used as the
- argument value. */
-#define GC_OPT_FLAG_LIST (1UL << 2)
-/* The RUNTIME flag for an option indicates that the option can be
- changed at runtime. */
-#define GC_OPT_FLAG_RUNTIME (1UL << 3)
-
-/* The following flags are incorporated from the backend. */
-/* The DEFAULT flag for an option indicates that the option has a
- default value. */
-#define GC_OPT_FLAG_DEFAULT (1UL << 4)
-/* The DEF_DESC flag for an option indicates that the option has a
- default, which is described by the value of the default field. */
-#define GC_OPT_FLAG_DEF_DESC (1UL << 5)
-/* The NO_ARG_DESC flag for an option indicates that the argument has
- a default, which is described by the value of the ARGDEF field. */
-#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6)
-
-/* A human-readable description for each flag. */
-static struct
-{
- const char *name;
-} gc_flag[] =
- {
- { "group" },
- { "optional arg" },
- { "list" },
- { "runtime" },
- { "default" },
- { "default desc" },
- { "no arg desc" }
- };
-
-
-/* To each option, or group marker, the information in the GC_OPTION
- struct is provided. If you change this, don't forget to update the
- option list of each component. */
-struct gc_option
-{
- /* If this is NULL, then this is a terminator in an array of unknown
- length. Otherwise, if this entry is a group marker (see FLAGS),
- then this is the name of the group described by this entry.
- Otherwise it is the name of the option described by this
- entry. The name must not contain a colon. */
- const char *name;
-
- /* The option flags. If the GROUP flag is set, then this entry is a
- group marker, not an option, and only the fields LEVEL,
- DESC_DOMAIN and DESC are valid. In all other cases, this entry
- describes a new option and all fields are valid. */
- unsigned long flags;
-
- /* The expert level. This field is valid for options and groups. A
- group has the expert level of the lowest-level option in the
- group. */
- gc_expert_level_t level;
-
- /* 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. */
- 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 '|'. */
- const char *desc;
-
- /* The following fields are only valid for options. */
-
- /* The type of the option argument. */
- gc_arg_type_t arg_type;
-
- /* The backend that implements this option. */
- gc_backend_t backend;
-
- /* The following fields are set to NULL at startup (because all
- option's are declared as static variables). They are at the end
- of the list so that they can be omitted from the option
- declarations. */
-
- /* This is true if the option is supported by this version of the
- backend. */
- int active;
-
- /* The default value for this option. This is NULL if the option is
- not present in the backend, the empty string if no default is
- available, and otherwise a quoted string. */
- char *default_value;
-
- /* The default argument is only valid if the "optional arg" flag is
- set, and specifies the default argument (value) that is used if
- the argument is omitted. */
- char *default_arg;
-
- /* The current value of this option. */
- char *value;
-
- /* The new flags for this option. The only defined flag is actually
- GC_OPT_FLAG_DEFAULT, and it means that the option should be
- deleted. In this case, NEW_VALUE is NULL. */
- unsigned long new_flags;
-
- /* The new value of this option. */
- char *new_value;
-};
-typedef struct gc_option gc_option_t;
-
-/* Use this macro to terminate an option list. */
-#define GC_OPTION_NULL { NULL }
-
-
-/* The options of the GC_COMPONENT_GPG_AGENT component. */
-static gc_option_t gc_options_gpg_agent[] =
- {
- /* The configuration file to which we write the changes. */
- { "gpgconf-gpg-agent.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
- NULL, NULL, GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPG_AGENT },
-
- { "Monitor",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- NULL, "Options controlling the diagnostic output" },
- { "verbose", GC_OPT_FLAG_LIST|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
- "gnupg", "verbose",
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
- { "quiet", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
- "gnupg", "be somewhat more quiet",
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
- { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
-
- { "Configuration",
- GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
- NULL, "Options controlling the configuration" },
- { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
- "gnupg", "|FILE|read options from FILE",
- GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPG_AGENT },
-
- { "Debug",
- GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
- "gnupg", "Options useful for debugging" },
- { "debug-level", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
- "gnupg", "|LEVEL|set the debugging level to LEVEL",
- GC_ARG_TYPE_STRING, GC_BACKEND_GPG_AGENT },
- { "log-file", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
- "gnupg", "|FILE|write logs to FILE",
- GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPG_AGENT },
- { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
-
- { "Security",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- NULL, "Options controlling the security" },
- { "default-cache-ttl", GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
- "gnupg", "|N|expire cached PINs after N seconds",
- GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
- { "ignore-cache-for-signing", GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
- "gnupg", "do not use the PIN cache when signing",
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
- { "allow-mark-trusted", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
- "gnupg", "allow clients to mark keys as \"trusted\"",
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
- { "no-grab", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT,
- "gnupg", "do not grab keyboard and mouse",
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
-
-
- GC_OPTION_NULL
- };
-
-
-/* The options of the GC_COMPONENT_SCDAEMON component. */
-static gc_option_t gc_options_scdaemon[] =
- {
- /* The configuration file to which we write the changes. */
- { "gpgconf-scdaemon.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
- NULL, NULL, GC_ARG_TYPE_PATHNAME, GC_BACKEND_SCDAEMON },
-
- { "Monitor",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- NULL, "Options controlling the diagnostic output" },
- { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
- "gnupg", "verbose",
- GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
- { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", "be somewhat more quiet",
- GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
- { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
-
- { "Configuration",
- GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
- NULL, "Options controlling the configuration" },
- { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
- "gnupg", "|FILE|read options from FILE",
- GC_ARG_TYPE_PATHNAME, GC_BACKEND_SCDAEMON },
- { "reader-port", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", "|N|connect to reader at port N",
- GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
- { "ctapi-driver", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "gnupg", "|NAME|use NAME as ct-API driver",
- GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
- { "pcsc-driver", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "gnupg", "|NAME|use NAME as PC/SC driver",
- GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
- { "disable-opensc", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
- "gnupg", "do not use the OpenSC layer",
- GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
- { "disable-ccid", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
- "gnupg", "do not use the internal CCID driver",
- GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
-
-
- { "Debug",
- GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
- "gnupg", "Options useful for debugging" },
- { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED,
- "gnupg", "|LEVEL|set the debugging level to LEVEL",
- GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
- { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "gnupg", "|FILE|write logs to FILE",
- GC_ARG_TYPE_PATHNAME, GC_BACKEND_SCDAEMON },
-
- { "Security",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- NULL, "Options controlling the security" },
- { "allow-admin", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", "allow the use of admin card commands",
- GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
-
-
- GC_OPTION_NULL
- };
-
-
-/* The options of the GC_COMPONENT_GPG component. */
-static gc_option_t gc_options_gpg[] =
- {
- /* The configuration file to which we write the changes. */
- { "gpgconf-gpg.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
- NULL, NULL, GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPG },
-
- { "Monitor",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- NULL, "Options controlling the diagnostic output" },
- { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
- "gnupg", "verbose",
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
- { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", "be somewhat more quiet",
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
- { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
-
- { "Configuration",
- GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
- NULL, "Options controlling the configuration" },
- { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
- "gnupg", "|FILE|read options from FILE",
- GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPG },
-
- { "Debug",
- GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
- "gnupg", "Options useful for debugging" },
- { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED,
- "gnupg", "|LEVEL|set the debugging level to LEVEL",
- GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
- { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "gnupg", "|FILE|write logs to FILE",
- GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPG },
-/* { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, */
-/* NULL, NULL, */
-/* GC_ARG_TYPE_UINT32, GC_BACKEND_GPG }, */
-
- { "Keyserver",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- NULL, "Configuration for Keyservers" },
- { "keyserver", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", "|URL|use keyserver at URL",
- GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
-
-
- GC_OPTION_NULL
- };
-
-
-
-/* The options of the GC_COMPONENT_GPGSM component. */
-static gc_option_t gc_options_gpgsm[] =
- {
- /* The configuration file to which we write the changes. */
- { "gpgconf-gpgsm.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
- NULL, NULL, GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPGSM },
-
- { "Monitor",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- NULL, "Options controlling the diagnostic output" },
- { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
- "gnupg", "verbose",
- GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
- { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", "be somewhat more quiet",
- GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
- { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
-
- { "Configuration",
- GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
- NULL, "Options controlling the configuration" },
- { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
- "gnupg", "|FILE|read options from FILE",
- GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPGSM },
-
- { "Debug",
- GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
- "gnupg", "Options useful for debugging" },
- { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED,
- "gnupg", "|LEVEL|set the debugging level to LEVEL",
- GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
- { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "gnupg", "|FILE|write logs to FILE",
- GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPGSM },
- { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_GPGSM },
-
- { "Security",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- NULL, "Options controlling the security" },
- { "disable-crl-checks", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", "never consult a CRL",
- GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
- { "enable-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "gnupg", "check validity using OCSP",
- GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
- { "include-certs", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
- "gnupg", "|N|number of certificates to include",
- GC_ARG_TYPE_INT32, GC_BACKEND_GPGSM },
- { "disable-policy-checks", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "gnupg", "do not check certificate policies",
- GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
- { "auto-issuer-key-retrieve", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "gnupg", "fetch missing issuer certificates",
- GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
-
- GC_OPTION_NULL
- };
-
-
-/* The options of the GC_COMPONENT_DIRMNGR component. */
-static gc_option_t gc_options_dirmngr[] =
- {
- /* The configuration file to which we write the changes. */
- { "gpgconf-dirmngr.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
- NULL, NULL, GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR },
-
- { "Monitor",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- NULL, "Options controlling the diagnostic output" },
- { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
- "dirmngr", "verbose",
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "dirmngr", "be somewhat more quiet",
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
-
- { "Format",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- NULL, "Options controlling the format of the output" },
- { "sh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "dirmngr", "sh-style command output",
- GC_ARG_TYPE_NONE, GC_BACKEND_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,
- NULL, "Options controlling the configuration" },
- { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
- "dirmngr", "|FILE|read options from FILE",
- GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR },
-
- { "Debug",
- GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
- "dirmngr", "Options useful for debugging" },
- { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED,
- "dirmngr", "|LEVEL|set the debugging level to LEVEL",
- GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
- { "no-detach", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "dirmngr", "do not detach from the console",
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "dirmngr", "|FILE|write logs to FILE",
- GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR },
- { "debug-wait", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
- { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
- NULL, NULL,
- GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
-
- { "Enforcement",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- NULL, "Options controlling the interactivity and enforcement" },
- { "batch", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "dirmngr", "run without asking a user",
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "force", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "dirmngr", "force loading of outdated CRLs",
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
-
- { "LDAP",
- GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
- NULL, "Configuration of LDAP servers to use" },
- { "add-servers", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "dirmngr", "add new servers discovered in CRL distribution points"
- " to serverlist", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "ldaptimeout", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "dirmngr", "|N|set LDAP timeout to N seconds",
- GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
- /* The following entry must not be removed, as it is required for
- the GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST. */
- { "ldapserverlist-file",
- GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
- "dirmngr", "|FILE|read LDAP server list from FILE",
- GC_ARG_TYPE_PATHNAME, GC_BACKEND_DIRMNGR },
- /* This entry must come after at least one entry for
- GC_BACKEND_DIRMNGR in this component, so that the entry for
- "ldapserverlist-file will be initialized before this one. */
- { "LDAP Server", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
- NULL, "LDAP server list",
- GC_ARG_TYPE_LDAP_SERVER, GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST },
- { "max-replies", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "dirmngr", "|N|do not return more than N items in one query",
- GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
-
- { "OCSP",
- GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
- NULL, "Configuration for OCSP" },
- { "allow-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
- "dirmngr", "allow sending OCSP requests",
- GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
- { "ocsp-responder", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "dirmngr", "|URL|use OCSP responder URL",
- GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
- { "ocsp-signer", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
- "dirmngr", "|FPR|OCSP response signed by FPR",
- GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
-
-
- GC_OPTION_NULL
- };
-
-
-/* Component system. Each component is a set of options that can be
- configured at the same time. If you change this, don't forget to
- update GC_COMPONENT below. */
-typedef enum
- {
- /* The classic GPG for OpenPGP. */
- GC_COMPONENT_GPG,
-
- /* The GPG Agent. */
- GC_COMPONENT_GPG_AGENT,
-
- /* The Smardcard Daemon. */
- GC_COMPONENT_SCDAEMON,
-
- /* GPG for S/MIME. */
- GC_COMPONENT_GPGSM,
-
- /* The LDAP Directory Manager for CRLs. */
- GC_COMPONENT_DIRMNGR,
-
- /* The number of components. */
- GC_COMPONENT_NR
- } gc_component_t;
-
-
-/* The information associated with each component. */
-static struct
-{
- /* The name of this component. Must not contain a colon (':')
- character. */
- const char *name;
-
- /* The gettext domain for the description DESC. If this is NULL,
- then the description is not translated. */
- const char *desc_domain;
-
- /* The description for this domain. */
- const char *desc;
-
- /* The list of options for this component, terminated by
- GC_OPTION_NULL. */
- gc_option_t *options;
-} gc_component[] =
- {
- { "gpg", NULL, "GPG for OpenPGP", gc_options_gpg },
- { "gpg-agent", NULL, "GPG Agent", gc_options_gpg_agent },
- { "scdaemon", NULL, "Smartcard Daemon", gc_options_scdaemon },
- { "gpgsm", NULL, "GPG for S/MIME", gc_options_gpgsm },
- { "dirmngr", NULL, "Directory Manager", gc_options_dirmngr }
- };
-
-
-/* Engine specific support. */
-void
-gpg_agent_runtime_change (void)
-{
- char *agent = getenv ("GPG_AGENT_INFO");
- char *pid_str;
- unsigned long pid_long;
- char *tail;
- pid_t pid;
-
- if (!agent)
- return;
-
- pid_str = strchr (agent, ':');
- if (!pid_str)
- return;
-
- pid_str++;
- errno = 0;
- pid_long = strtoul (pid_str, &tail, 0);
- if (errno || (*tail != ':' && *tail != '\0'))
- return;
-
- pid = (pid_t) pid_long;
-
- /* Check for overflow. */
- if (pid_long != (unsigned long) pid)
- return;
-
- /* Ignore any errors here. */
- kill (pid, SIGHUP);
-}
-
-
-/* More or less Robust version of dgettext. It has the sidefeect of
- switching the codeset to utf-8 becuase this is what we want to
- output. In theory it is posible to keep the orginal code set and
- switch back for regular disgnostic output (redefine "_(" for that)
- but given the natur of this tool, being something invoked from
- other pograms, it does not make much sense. */
-static const char *
-my_dgettext (const char *domain, const char *msgid)
-{
-#ifdef ENABLE_NLS
- if (domain)
- {
- static int switched_codeset;
- char *text;
-
- if (!switched_codeset)
- {
- bind_textdomain_codeset (PACKAGE_GT, "utf-8");
- switched_codeset = 1;
- }
- text = dgettext (domain, msgid);
- return text ? text : msgid;
- }
- else
-#endif
- return msgid;
-}
-
-
-/* Percent-Escape special characters. The string is valid until the
- next invocation of the function. */
-static char *
-percent_escape (const char *src)
-{
- static char *esc_str;
- static int esc_str_len;
- int new_len = 3 * strlen (src) + 1;
- char *dst;
-
- if (esc_str_len < new_len)
- {
- char *new_esc_str = realloc (esc_str, new_len);
- if (!new_esc_str)
- gc_error (1, errno, "can not escape string");
- esc_str = new_esc_str;
- esc_str_len = new_len;
- }
-
- dst = esc_str;
- while (*src)
- {
- if (*src == '%')
- {
- *(dst++) = '%';
- *(dst++) = '2';
- *(dst++) = '5';
- }
- else if (*src == ':')
- {
- /* The colon is used as field separator. */
- *(dst++) = '%';
- *(dst++) = '3';
- *(dst++) = 'a';
- }
- else if (*src == ',')
- {
- /* The comma is used as list separator. */
- *(dst++) = '%';
- *(dst++) = '2';
- *(dst++) = 'c';
- }
- else
- *(dst++) = *(src);
- src++;
- }
- *dst = '\0';
- return esc_str;
-}
-
-
-/* Convert two hexadecimal digits from STR to the value they
- represent. Returns -1 if one of the characters is not a
- hexadecimal digit. */
-static int
-hextobyte (const char *str)
-{
- int val = 0;
- int i;
-
-#define NROFHEXDIGITS 2
- for (i = 0; i < NROFHEXDIGITS; i++)
- {
- if (*str >= '0' && *str <= '9')
- val += *str - '0';
- else if (*str >= 'A' && *str <= 'F')
- val += 10 + *str - 'A';
- else if (*str >= 'a' && *str <= 'f')
- val += 10 + *str - 'a';
- else
- return -1;
- if (i < NROFHEXDIGITS - 1)
- val *= 16;
- str++;
- }
- return val;
-}
-
-
-
-/* Percent-Deescape special characters. The string is valid until the
- next invocation of the function. */
-static char *
-percent_deescape (const char *src)
-{
- static char *str;
- static int str_len;
- int new_len = 3 * strlen (src) + 1;
- char *dst;
-
- if (str_len < new_len)
- {
- char *new_str = realloc (str, new_len);
- if (!new_str)
- gc_error (1, errno, "can not deescape string");
- str = new_str;
- str_len = new_len;
- }
-
- dst = str;
- while (*src)
- {
- if (*src == '%')
- {
- int val = hextobyte (src + 1);
-
- if (val < 0)
- gc_error (1, 0, "malformed end of string %s", src);
-
- *(dst++) = (char) val;
- src += 3;
- }
- else
- *(dst++) = *(src++);
- }
- *dst = '\0';
- return str;
-}
-
-
-/* List all components that are available. */
-void
-gc_component_list_components (FILE *out)
-{
- gc_component_t idx;
-
- for (idx = 0; idx < GC_COMPONENT_NR; idx++)
- {
- const char *desc = gc_component[idx].desc;
- desc = my_dgettext (gc_component[idx].desc_domain, desc);
- fprintf (out, "%s:%s\n", gc_component[idx].name, percent_escape (desc));
- }
-}
-
-
-/* Find the component with the name NAME. Returns -1 if not
- found. */
-int
-gc_component_find (const char *name)
-{
- gc_component_t idx;
-
- for (idx = 0; idx < GC_COMPONENT_NR; idx++)
- {
- if (!strcmp (name, gc_component[idx].name))
- return idx;
- }
- return -1;
-}
-
-
-/* List the option OPTION. */
-static void
-list_one_option (const gc_option_t *option, FILE *out)
-{
- const char *desc = NULL;
- char *arg_name = NULL;
-
- if (option->desc)
- {
- desc = my_dgettext (option->desc_domain, option->desc);
-
- if (*desc == '|')
- {
- const char *arg_tail = strchr (&desc[1], '|');
-
- if (arg_tail)
- {
- int arg_len = arg_tail - &desc[1];
- arg_name = xmalloc (arg_len + 1);
- memcpy (arg_name, &desc[1], arg_len);
- arg_name[arg_len] = '\0';
- desc = arg_tail + 1;
- }
- }
- }
-
-
- /* YOU MUST NOT REORDER THE FIELDS IN THIS OUTPUT, AS THEIR ORDER IS
- PART OF THE EXTERNAL INTERFACE. YOU MUST NOT REMOVE ANY
- FIELDS. */
-
- /* The name field. */
- fprintf (out, "%s", option->name);
-
- /* The flags field. */
- fprintf (out, ":%lu", option->flags);
- if (opt.verbose)
- {
- putc (' ', out);
-
- if (!option->flags)
- fprintf (out, "none");
- else
- {
- unsigned long flags = option->flags;
- unsigned long flag = 0;
- unsigned long first = 1;
-
- while (flags)
- {
- if (flags & 1)
- {
- if (first)
- first = 0;
- else
- putc (',', out);
- fprintf (out, "%s", gc_flag[flag].name);
- }
- flags >>= 1;
- flag++;
- }
- }
- }
-
- /* The level field. */
- fprintf (out, ":%u", option->level);
- if (opt.verbose)
- fprintf (out, " %s", gc_level[option->level].name);
-
- /* The description field. */
- fprintf (out, ":%s", desc ? percent_escape (desc) : "");
-
- /* The type field. */
- fprintf (out, ":%u", option->arg_type);
- if (opt.verbose)
- fprintf (out, " %s", gc_arg_type[option->arg_type].name);
-
- /* The alternate type field. */
- fprintf (out, ":%u", gc_arg_type[option->arg_type].fallback);
- if (opt.verbose)
- fprintf (out, " %s",
- gc_arg_type[gc_arg_type[option->arg_type].fallback].name);
-
- /* The argument name field. */
- fprintf (out, ":%s", arg_name ? percent_escape (arg_name) : "");
- if (arg_name)
- xfree (arg_name);
-
- /* The default value field. */
- fprintf (out, ":%s", option->default_value ? option->default_value : "");
-
- /* The default argument field. */
- fprintf (out, ":%s", option->default_arg ? option->default_arg : "");
-
- /* The value field. */
- if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE
- && (option->flags & GC_OPT_FLAG_LIST)
- && option->value)
- /* The special format "1,1,1,1,...,1" is converted to a number
- here. */
- fprintf (out, ":%u", (strlen (option->value) + 1) / 2);
- else
- fprintf (out, ":%s", option->value ? option->value : "");
-
- /* ADD NEW FIELDS HERE. */
-
- putc ('\n', out);
-}
-
-
-/* List all options of the component COMPONENT. */
-void
-gc_component_list_options (int component, FILE *out)
-{
- const gc_option_t *option = gc_component[component].options;
- const gc_option_t *group_option = NULL;
-
- while (option->name)
- {
- /* Do not output unknown or internal options. */
- if (!(option->flags & GC_OPT_FLAG_GROUP)
- && (!option->active || option->level == GC_LEVEL_INTERNAL))
- {
- option++;
- continue;
- }
-
- if (option->flags & GC_OPT_FLAG_GROUP)
- group_option = option;
- else
- {
- if (group_option)
- {
- list_one_option (group_option, out);
- group_option = NULL;
- }
-
- list_one_option (option, out);
- }
-
- option++;
- }
-}
-
-
-/* Find the option NAME in component COMPONENT, for the backend
- BACKEND. If BACKEND is GC_BACKEND_ANY, any backend will match. */
-static gc_option_t *
-find_option (gc_component_t component, const char *name,
- gc_backend_t backend)
-{
- gc_option_t *option = gc_component[component].options;
- while (option->name)
- {
- if (!(option->flags & GC_OPT_FLAG_GROUP)
- && !strcmp (option->name, name)
- && (backend == GC_BACKEND_ANY || option->backend == backend))
- break;
- option++;
- }
- return option->name ? option : NULL;
-}
-
-
-/* Determine the configuration pathname for the component COMPONENT
- and backend BACKEND. */
-static char *
-get_config_pathname (gc_component_t component, gc_backend_t backend)
-{
- char *pathname = NULL;
- gc_option_t *option = find_option
- (component, gc_backend[backend].option_config_filename, GC_BACKEND_ANY);
- assert (option);
- assert (option->arg_type == GC_ARG_TYPE_PATHNAME);
- assert (!(option->flags & GC_OPT_FLAG_LIST));
-
- if (!option->active || !option->default_value)
- gc_error (1, 0, "Option %s, needed by backend %s, was not initialized",
- gc_backend[backend].option_config_filename,
- gc_backend[backend].name);
-
- if (option->value && *option->value)
- pathname = percent_deescape (&option->value[1]);
- else if (option->default_value && *option->default_value)
- pathname = percent_deescape (&option->default_value[1]);
- else
- pathname = "";
-
- if (pathname[0] != '/')
- gc_error (1, 0, "Option %s, needed by backend %s, is not absolute",
- gc_backend[backend].option_config_filename,
- gc_backend[backend].name);
-
- return pathname;
-}
-
-
-/* Retrieve the options for the component COMPONENT from backend
- BACKEND, which we already know is a program-type backend. */
-static void
-retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
-{
- char *cmd_line;
- char *line = NULL;
- size_t line_len = 0;
- ssize_t length;
- FILE *config;
- char *config_pathname;
-
- cmd_line = xasprintf ("%s --gpgconf-list", gc_backend[backend].program);
-
- config = popen (cmd_line, "r");
- if (!config)
- gc_error (1, errno, "could not gather active options from %s", cmd_line);
-
- while ((length = read_line (config, &line, &line_len, NULL)) > 0)
- {
- gc_option_t *option;
- 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'))
- line[--length] = '\0';
-
- linep = strchr (line, ':');
- if (linep)
- *(linep++) = '\0';
-
- /* Extract additional flags. Default to none. */
- if (linep)
- {
- char *end;
- char *tail;
-
- end = strchr (linep, ':');
- if (end)
- *(end++) = '\0';
-
- errno = 0;
- flags = strtoul (linep, &tail, 0);
- if (errno)
- gc_error (1, errno, "malformed flags in option %s from %s", line, cmd_line);
- if (!(*tail == '\0' || *tail == ':' || *tail == ' '))
- gc_error (1, 0, "garbage after flags in option %s from %s", line, cmd_line);
-
- linep = end;
- }
-
- /* Extract default value, if present. Default to empty if
- not. */
- if (linep)
- {
- char *end;
-
- end = strchr (linep, ':');
- if (end)
- *(end++) = '\0';
-
- if (flags & GC_OPT_FLAG_DEFAULT)
- default_value = linep;
-
- linep = end;
- }
-
- /* Look up the option in the component and install the
- configuration data. */
- option = find_option (component, line, backend);
- if (option)
- {
- if (option->active)
- gc_error (1, errno, "option %s returned twice from %s",
- line, cmd_line);
- option->active = 1;
-
- option->flags |= flags;
- if (default_value && *default_value)
- option->default_value = xstrdup (default_value);
- }
- }
- if (length < 0 || ferror (config))
- gc_error (1, errno, "error reading from %s", cmd_line);
- if (fclose (config) && ferror (config))
- gc_error (1, errno, "error closing %s", cmd_line);
- xfree (cmd_line);
-
- /* At this point, we can parse the configuration file. */
- config_pathname = get_config_pathname (component, backend);
-
- config = fopen (config_pathname, "r");
- if (!config)
- gc_error (0, errno, "warning: can not open config file %s",
- config_pathname);
- else
- {
- while ((length = read_line (config, &line, &line_len, NULL)) > 0)
- {
- char *name;
- char *value;
- gc_option_t *option;
-
- name = line;
- while (*name == ' ' || *name == '\t')
- name++;
- if (!*name || *name == '#' || *name == '\r' || *name == '\n')
- continue;
-
- value = name;
- while (*value && *value != ' ' && *value != '\t'
- && *value != '#' && *value != '\r' && *value != '\n')
- value++;
- if (*value == ' ' || *value == '\t')
- {
- char *end;
-
- *(value++) = '\0';
- while (*value == ' ' || *value == '\t')
- value++;
-
- end = value;
- while (*end && *end != '#' && *end != '\r' && *end != '\n')
- end++;
- while (end > value && (end[-1] == ' ' || end[-1] == '\t'))
- end--;
- *end = '\0';
- }
- else
- *value = '\0';
-
- /* Look up the option in the component and install the
- configuration data. */
- option = find_option (component, line, backend);
- if (option)
- {
- char *opt_value;
-
- if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE)
- {
- if (*value)
- gc_error (0, 0,
- "warning: ignoring argument %s for option %s",
- value, name);
- opt_value = xstrdup ("1");
- }
- else if (gc_arg_type[option->arg_type].fallback
- == GC_ARG_TYPE_STRING)
- opt_value = xasprintf ("\"%s", percent_escape (value));
- else
- {
- /* FIXME: Verify that the number is sane. */
- opt_value = xstrdup (value);
- }
-
- /* Now enter the option into the table. */
- if (!(option->flags & GC_OPT_FLAG_LIST))
- {
- if (option->value)
- free (option->value);
- option->value = opt_value;
- }
- else
- {
- if (!option->value)
- option->value = opt_value;
- else
- {
- char *opt_val = opt_value;
-
- option->value = xasprintf ("%s,%s", option->value,
- opt_val);
- xfree (opt_value);
- }
- }
- }
- }
-
- if (length < 0 || ferror (config))
- gc_error (1, errno, "error reading from %s", config_pathname);
- if (fclose (config) && ferror (config))
- gc_error (1, errno, "error closing %s", config_pathname);
- }
-
- xfree (line);
-}
-
-
-/* Retrieve the options for the component COMPONENT from backend
- BACKEND, which we already know is of type file list. */
-static void
-retrieve_options_from_file (gc_component_t component, gc_backend_t backend)
-{
- gc_option_t *list_option;
- char *list_pathname;
- FILE *list_file;
- char *line = NULL;
- size_t line_len = 0;
- ssize_t length;
- char *list = NULL;
-
- list_option = find_option (component,
- gc_backend[backend].option_name, GC_BACKEND_ANY);
- assert (list_option);
- assert (!list_option->active);
-
- list_pathname = get_config_pathname (component, backend);
- list_file = fopen (list_pathname, "r");
- if (!list_file)
- gc_error (0, errno, "warning: can not open list file %s", list_pathname);
- else
- {
-
- while ((length = read_line (list_file, &line, &line_len, NULL)) > 0)
- {
- char *start;
- char *end;
- char *new_list;
-
- start = line;
- while (*start == ' ' || *start == '\t')
- start++;
- if (!*start || *start == '#' || *start == '\r' || *start == '\n')
- continue;
-
- end = start;
- while (*end && *end != '#' && *end != '\r' && *end != '\n')
- end++;
- /* Walk back to skip trailing white spaces. Looks evil, but
- works because of the conditions on START and END imposed
- at this point (END is at least START + 1, and START is
- not a whitespace character). */
- while (*(end - 1) == ' ' || *(end - 1) == '\t')
- end--;
- *end = '\0';
- /* FIXME: Oh, no! This is so lame! Should use realloc and
- really append. */
- if (list)
- {
- new_list = xasprintf ("%s,\"%s", list, percent_escape (start));
- xfree (list);
- list = new_list;
- }
- else
- list = xasprintf ("\"%s", percent_escape (start));
- }
- if (length < 0 || ferror (list_file))
- gc_error (1, errno, "can not read list file %s", list_pathname);
- }
-
- list_option->active = 1;
- list_option->value = list;
-
- xfree (line);
-}
-
-
-/* Retrieve the currently active options and their defaults from all
- involved backends for this component. */
-void
-gc_component_retrieve_options (int component)
-{
- int backend_seen[GC_BACKEND_NR];
- gc_backend_t backend;
- gc_option_t *option = gc_component[component].options;
-
- for (backend = 0; backend < GC_BACKEND_NR; backend++)
- backend_seen[backend] = 0;
-
- while (option->name)
- {
- 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
- retrieve_options_from_file (component, backend);
- }
- option++;
- }
-}
-
-
-/* Perform a simple validity check based on the type. Return in
- NEW_VALUE_NR the value of the number in NEW_VALUE if OPTION is of
- type GC_ARG_TYPE_NONE. */
-static void
-option_check_validity (gc_option_t *option, unsigned long flags,
- char *new_value, unsigned long *new_value_nr)
-{
- char *arg;
-
- if (!option->active)
- gc_error (1, 0, "option %s not supported by backend", option->name);
-
- if (option->new_flags || option->new_value)
- gc_error (1, 0, "option %s already changed", option->name);
-
- if (flags & GC_OPT_FLAG_DEFAULT)
- {
- if (*new_value)
- gc_error (1, 0, "argument %s provided for deleted option %s",
- new_value, option->name);
-
- return;
- }
-
- /* GC_ARG_TYPE_NONE options have special list treatment. */
- if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE)
- {
- char *tail;
-
- errno = 0;
- *new_value_nr = strtoul (new_value, &tail, 0);
-
- if (errno)
- gc_error (1, errno, "invalid argument for option %s",
- option->name);
- if (*tail)
- gc_error (1, 0, "garbage after argument for option %s",
- option->name);
-
- if (!(option->flags & GC_OPT_FLAG_LIST))
- {
- if (*new_value_nr != 1)
- gc_error (1, 0, "argument for non-list option %s of type 0 "
- "(none) must be 1", option->name);
- }
- else
- {
- if (*new_value_nr == 0)
- gc_error (1, 0, "argument for option %s of type 0 (none) "
- "must be positive", option->name);
- }
-
- return;
- }
-
- arg = new_value;
- do
- {
- if (*arg == '\0' || *arg == ',')
- {
- if (!(option->flags & GC_OPT_FLAG_ARG_OPT))
- gc_error (1, 0, "argument required for option %s", option->name);
-
- if (*arg == ',' && !(option->flags & GC_OPT_FLAG_LIST))
- gc_error (1, 0, "list found for non-list option %s", option->name);
- }
- else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING)
- {
- if (*arg != '"')
- gc_error (1, 0, "string argument for option %s must begin "
- "with a quote (\") character", option->name);
- }
- else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32)
- {
- errno = 0;
- (void) strtol (arg, &arg, 0);
-
- if (errno)
- gc_error (1, errno, "invalid argument for option %s",
- option->name);
-
- if (*arg != '\0' && *arg != ',')
- gc_error (1, 0, "garbage after argument for option %s",
- option->name);
- }
- else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32)
- {
- errno = 0;
- (void) strtoul (arg, &arg, 0);
-
- if (errno)
- gc_error (1, errno, "invalid argument for option %s",
- option->name);
-
- if (*arg != '\0' && *arg != ',')
- gc_error (1, 0, "garbage after argument for option %s",
- option->name);
- }
- arg = strchr (arg, ',');
- if (arg)
- arg++;
- }
- while (arg && *arg);
-}
-
-
-/* Create and verify the new configuration file for the specified
- backend and component. Returns 0 on success and -1 on error. */
-static int
-change_options_file (gc_component_t component, gc_backend_t backend,
- char **src_filenamep, char **dest_filenamep,
- char **orig_filenamep)
-{
- static const char marker[] = "###+++--- GPGConf ---+++###";
- /* True if we are within the marker in the config file. */
- int in_marker = 0;
- gc_option_t *option;
- char *line = NULL;
- size_t line_len;
- ssize_t length;
- int res;
- int fd;
- FILE *src_file = NULL;
- FILE *dest_file = NULL;
- char *src_filename;
- char *dest_filename;
- char *orig_filename;
- char *arg;
- char *cur_arg = NULL;
-
- option = find_option (component,
- gc_backend[backend].option_name, GC_BACKEND_ANY);
- assert (option);
- assert (option->active);
- assert (gc_arg_type[option->arg_type].fallback != GC_ARG_TYPE_NONE);
-
- /* FIXME. Throughout the function, do better error reporting. */
- /* Note that get_config_pathname() calls percent_deescape(), so we
- call this before processing the arguments. */
- dest_filename = xstrdup (get_config_pathname (component, backend));
- src_filename = xasprintf ("%s.gpgconf.%i.new", dest_filename, getpid ());
- orig_filename = xasprintf ("%s.gpgconf.%i.bak", dest_filename, getpid ());
-
- arg = option->new_value;
- if (arg && arg[0] == '\0')
- arg = NULL;
- else if (arg)
- {
- char *end;
-
- arg++;
- end = strchr (arg, ',');
- if (end)
- *end = '\0';
-
- cur_arg = percent_deescape (arg);
- if (end)
- {
- *end = ',';
- arg = end + 1;
- }
- else
- arg = NULL;
- }
-
- res = link (dest_filename, orig_filename);
- if (res < 0 && errno != ENOENT)
- return -1;
- if (res < 0)
- {
- xfree (orig_filename);
- orig_filename = NULL;
- }
-
- /* We now initialize the return strings, so the caller can do the
- cleanup for us. */
- *src_filenamep = src_filename;
- *dest_filenamep = dest_filename;
- *orig_filenamep = orig_filename;
-
- /* Use open() so that we can use O_EXCL. */
- fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644);
- if (fd < 0)
- return -1;
- src_file = fdopen (fd, "w");
- res = errno;
- if (!src_file)
- {
- errno = res;
- return -1;
- }
-
- /* Only if ORIG_FILENAME is not NULL did the configuration file
- exist already. In this case, we will copy its content into the
- new configuration file, changing it to our liking in the
- process. */
- if (orig_filename)
- {
- dest_file = fopen (dest_filename, "r");
- if (!dest_file)
- goto change_file_one_err;
-
- while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
- {
- int disable = 0;
- char *start;
-
- if (!strncmp (marker, line, sizeof (marker) - 1))
- {
- if (!in_marker)
- in_marker = 1;
- else
- break;
- }
-
- start = line;
- while (*start == ' ' || *start == '\t')
- start++;
- if (*start && *start != '\r' && *start != '\n' && *start != '#')
- {
- char *end;
- char *endp;
- char saved_end;
-
- endp = start;
- end = endp;
-
- /* Search for the end of the line. */
- while (*endp && *endp != '#' && *endp != '\r' && *endp != '\n')
- {
- endp++;
- if (*endp && *endp != ' ' && *endp != '\t'
- && *endp != '\r' && *endp != '\n' && *endp != '#')
- end = endp + 1;
- }
- saved_end = *end;
- *end = '\0';
-
- if ((option->new_flags & GC_OPT_FLAG_DEFAULT)
- || !cur_arg || strcmp (start, cur_arg))
- disable = 1;
- else
- {
- /* Find next argument. */
- if (arg)
- {
- char *arg_end;
-
- arg++;
- arg_end = strchr (arg, ',');
- if (arg_end)
- *arg_end = '\0';
-
- cur_arg = percent_deescape (arg);
- if (arg_end)
- {
- *arg_end = ',';
- arg = arg_end + 1;
- }
- else
- arg = NULL;
- }
- else
- cur_arg = NULL;
- }
-
- *end = saved_end;
- }
-
- if (disable)
- {
- if (!in_marker)
- {
- fprintf (src_file,
- "# GPGConf disabled this option here at %s\n",
- asctimestamp (gnupg_get_time ()));
- if (ferror (src_file))
- goto change_file_one_err;
- fprintf (src_file, "# %s", line);
- if (ferror (src_file))
- goto change_file_one_err;
- }
- }
- else
- {
- fprintf (src_file, "%s", line);
- if (ferror (src_file))
- goto change_file_one_err;
- }
- }
- if (length < 0 || ferror (dest_file))
- goto change_file_one_err;
- }
-
- if (!in_marker)
- {
- /* There was no marker. This is the first time we edit the
- file. We add our own marker at the end of the file and
- proceed. Note that we first write a newline, this guards us
- against files which lack the newline at the end of the last
- line, while it doesn't hurt us in all other cases. */
- fprintf (src_file, "\n%s\n", marker);
- if (ferror (src_file))
- goto change_file_one_err;
- }
-
- /* At this point, we have copied everything up to the end marker
- into the new file, except for the arguments we are going to add.
- Now, dump the new arguments and write the end marker, possibly
- followed by the rest of the original file. */
- while (cur_arg)
- {
- fprintf (src_file, "%s\n", cur_arg);
-
- /* Find next argument. */
- if (arg)
- {
- char *end;
-
- arg++;
- end = strchr (arg, ',');
- if (end)
- *end = '\0';
-
- cur_arg = percent_deescape (arg);
- if (end)
- {
- *end = ',';
- arg = end + 1;
- }
- else
- arg = NULL;
- }
- else
- cur_arg = NULL;
- }
-
- fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ()));
- if (ferror (src_file))
- goto change_file_one_err;
-
- if (!in_marker)
- {
- fprintf (src_file, "# GPGConf edited this configuration file.\n");
- if (ferror (src_file))
- goto change_file_one_err;
- fprintf (src_file, "# It will disable options before this marked "
- "block, but it will\n");
- if (ferror (src_file))
- goto change_file_one_err;
- fprintf (src_file, "# never change anything below these lines.\n");
- if (ferror (src_file))
- goto change_file_one_err;
- }
- if (dest_file)
- {
- while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
- {
- fprintf (src_file, "%s", line);
- if (ferror (src_file))
- goto change_file_one_err;
- }
- if (length < 0 || ferror (dest_file))
- goto change_file_one_err;
- }
- xfree (line);
- line = NULL;
-
- res = fclose (src_file);
- if (res)
- {
- res = errno;
- close (fd);
- if (dest_file)
- fclose (dest_file);
- errno = res;
- return -1;
- }
- close (fd);
- if (dest_file)
- {
- res = fclose (dest_file);
- if (res)
- return -1;
- }
- return 0;
-
- change_file_one_err:
- xfree (line);
- res = errno;
- if (src_file)
- {
- fclose (src_file);
- close (fd);
- }
- if (dest_file)
- fclose (dest_file);
- errno = res;
- return -1;
-}
-
-
-/* Create and verify the new configuration file for the specified
- backend and component. Returns 0 on success and -1 on error. */
-static int
-change_options_program (gc_component_t component, gc_backend_t backend,
- char **src_filenamep, char **dest_filenamep,
- char **orig_filenamep)
-{
- static const char marker[] = "###+++--- GPGConf ---+++###";
- /* True if we are within the marker in the config file. */
- int in_marker = 0;
- gc_option_t *option;
- char *line = NULL;
- size_t line_len;
- ssize_t length;
- int res;
- int fd;
- FILE *src_file = NULL;
- FILE *dest_file = NULL;
- char *src_filename;
- char *dest_filename;
- char *orig_filename;
-
- /* FIXME. Throughout the function, do better error reporting. */
- dest_filename = xstrdup (get_config_pathname (component, backend));
- src_filename = xasprintf ("%s.gpgconf.%i.new", dest_filename, getpid ());
- orig_filename = xasprintf ("%s.gpgconf.%i.bak", dest_filename, getpid ());
-
- res = link (dest_filename, orig_filename);
- if (res < 0 && errno != ENOENT)
- return -1;
- if (res < 0)
- {
- xfree (orig_filename);
- orig_filename = NULL;
- }
-
- /* We now initialize the return strings, so the caller can do the
- cleanup for us. */
- *src_filenamep = src_filename;
- *dest_filenamep = dest_filename;
- *orig_filenamep = orig_filename;
-
- /* Use open() so that we can use O_EXCL. */
- fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644);
- if (fd < 0)
- return -1;
- src_file = fdopen (fd, "w");
- res = errno;
- if (!src_file)
- {
- errno = res;
- return -1;
- }
-
- /* Only if ORIG_FILENAME is not NULL did the configuration file
- exist already. In this case, we will copy its content into the
- new configuration file, changing it to our liking in the
- process. */
- if (orig_filename)
- {
- dest_file = fopen (dest_filename, "r");
- if (!dest_file)
- goto change_one_err;
-
- while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
- {
- int disable = 0;
- char *start;
-
- if (!strncmp (marker, line, sizeof (marker) - 1))
- {
- if (!in_marker)
- in_marker = 1;
- else
- break;
- }
-
- start = line;
- while (*start == ' ' || *start == '\t')
- start++;
- if (*start && *start != '\r' && *start != '\n' && *start != '#')
- {
- char *end;
- char saved_end;
-
- end = start;
- while (*end && *end != ' ' && *end != '\t'
- && *end != '\r' && *end != '\n' && *end != '#')
- end++;
- saved_end = *end;
- *end = '\0';
-
- option = find_option (component, start, backend);
- *end = saved_end;
- if (option && ((option->new_flags & GC_OPT_FLAG_DEFAULT)
- || option->new_value))
- disable = 1;
- }
- if (disable)
- {
- if (!in_marker)
- {
- fprintf (src_file,
- "# GPGConf disabled this option here at %s\n",
- asctimestamp (gnupg_get_time ()));
- if (ferror (src_file))
- goto change_one_err;
- fprintf (src_file, "# %s", line);
- if (ferror (src_file))
- goto change_one_err;
- }
- }
- else
- {
- fprintf (src_file, "%s", line);
- if (ferror (src_file))
- goto change_one_err;
- }
- }
- if (length < 0 || ferror (dest_file))
- goto change_one_err;
- }
-
- if (!in_marker)
- {
- /* There was no marker. This is the first time we edit the
- file. We add our own marker at the end of the file and
- proceed. Note that we first write a newline, this guards us
- against files which lack the newline at the end of the last
- line, while it doesn't hurt us in all other cases. */
- fprintf (src_file, "\n%s\n", marker);
- if (ferror (src_file))
- goto change_one_err;
- }
- /* At this point, we have copied everything up to the end marker
- into the new file, except for the options we are going to change.
- Now, dump the changed options (except for those we are going to
- revert to their default), and write the end marker, possibly
- followed by the rest of the original file. */
-
- /* We have to turn on UTF8 strings for GnuPG. */
- if (backend == GC_BACKEND_GPG)
- fprintf (src_file, "utf8-strings\n");
-
- option = gc_component[component].options;
- while (option->name)
- {
- if (!(option->flags & GC_OPT_FLAG_GROUP)
- && option->backend == backend
- && option->new_value)
- {
- char *arg = option->new_value;
-
- do
- {
- if (*arg == '\0' || *arg == ',')
- {
- fprintf (src_file, "%s\n", option->name);
- if (ferror (src_file))
- goto change_one_err;
- }
- else if (gc_arg_type[option->arg_type].fallback
- == GC_ARG_TYPE_NONE)
- {
- assert (*arg == '1');
- fprintf (src_file, "%s\n", option->name);
- if (ferror (src_file))
- goto change_one_err;
-
- arg++;
- }
- else if (gc_arg_type[option->arg_type].fallback
- == GC_ARG_TYPE_STRING)
- {
- char *end;
-
- assert (*arg == '"');
- arg++;
-
- end = strchr (arg, ',');
- if (end)
- *end = '\0';
-
- fprintf (src_file, "%s %s\n", option->name,
- percent_deescape (arg));
- if (ferror (src_file))
- goto change_one_err;
-
- if (end)
- *end = ',';
- arg = end;
- }
- else
- {
- char *end;
-
- end = strchr (arg, ',');
- if (end)
- *end = '\0';
-
- fprintf (src_file, "%s %s\n", option->name, arg);
- if (ferror (src_file))
- goto change_one_err;
-
- if (end)
- *end = ',';
- arg = end;
- }
-
- assert (arg == NULL || *arg == '\0' || *arg == ',');
- if (arg && *arg == ',')
- arg++;
- }
- while (arg && *arg);
- }
- option++;
- }
-
- fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ()));
- if (ferror (src_file))
- goto change_one_err;
-
- if (!in_marker)
- {
- fprintf (src_file, "# GPGConf edited this configuration file.\n");
- if (ferror (src_file))
- goto change_one_err;
- fprintf (src_file, "# It will disable options before this marked "
- "block, but it will\n");
- if (ferror (src_file))
- goto change_one_err;
- fprintf (src_file, "# never change anything below these lines.\n");
- if (ferror (src_file))
- goto change_one_err;
- }
- if (dest_file)
- {
- while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
- {
- fprintf (src_file, "%s", line);
- if (ferror (src_file))
- goto change_one_err;
- }
- if (length < 0 || ferror (dest_file))
- goto change_one_err;
- }
- xfree (line);
- line = NULL;
-
- res = fclose (src_file);
- if (res)
- {
- res = errno;
- close (fd);
- if (dest_file)
- fclose (dest_file);
- errno = res;
- return -1;
- }
- close (fd);
- if (dest_file)
- {
- res = fclose (dest_file);
- if (res)
- return -1;
- }
- return 0;
-
- change_one_err:
- xfree (line);
- res = errno;
- if (src_file)
- {
- fclose (src_file);
- close (fd);
- }
- if (dest_file)
- fclose (dest_file);
- errno = res;
- return -1;
-}
-
-
-/* Read the modifications from IN and apply them. */
-void
-gc_component_change_options (int component, FILE *in)
-{
- int err = 0;
- int runtime[GC_BACKEND_NR];
- char *src_pathname[GC_BACKEND_NR];
- char *dest_pathname[GC_BACKEND_NR];
- char *orig_pathname[GC_BACKEND_NR];
- gc_backend_t backend;
- gc_option_t *option;
- char *line = NULL;
- size_t line_len = 0;
- ssize_t length;
-
- for (backend = 0; backend < GC_BACKEND_NR; backend++)
- {
- runtime[backend] = 0;
- src_pathname[backend] = NULL;
- dest_pathname[backend] = NULL;
- orig_pathname[backend] = NULL;
- }
-
- while ((length = read_line (in, &line, &line_len, NULL)) > 0)
- {
- char *linep;
- unsigned long flags = 0;
- char *new_value = "";
- unsigned long new_value_nr;
-
- /* 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)
- {
- char *end;
- char *tail;
-
- end = strchr (linep, ':');
- if (end)
- *(end++) = '\0';
-
- 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;
- }
-
- /* Extract default value, if present. Default to empty if
- not. */
- if (linep)
- {
- char *end;
-
- end = strchr (linep, ':');
- if (end)
- *(end++) = '\0';
-
- new_value = linep;
-
- linep = end;
- }
-
- option = find_option (component, line, GC_BACKEND_ANY);
- if (!option)
- gc_error (1, 0, "unknown option %s", line);
-
- option_check_validity (option, flags, new_value, &new_value_nr);
-
- if (option->flags & GC_OPT_FLAG_RUNTIME)
- runtime[option->backend] = 1;
-
- option->new_flags = flags;
- if (!(flags & GC_OPT_FLAG_DEFAULT))
- {
- if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE
- && (option->flags & GC_OPT_FLAG_LIST))
- {
- char *str;
-
- /* We convert the number to a list of 1's for
- convenient list handling. */
- assert (new_value_nr > 0);
- option->new_value = xmalloc ((2 * (new_value_nr - 1) + 1) + 1);
- str = option->new_value;
- *(str++) = '1';
- while (--new_value_nr > 0)
- {
- *(str++) = ',';
- *(str++) = '1';
- }
- *(str++) = '\0';
- }
- else
- option->new_value = xstrdup (new_value);
- }
- }
-
- /* Now that we have collected and locally verified the changes,
- write them out to new configuration files, verify them
- externally, and then commit them. */
- option = gc_component[component].options;
- while (option->name)
- {
- /* Go on if we have already seen this backend, or if there is
- nothing to do. */
- if (src_pathname[option->backend]
- || !(option->new_flags || option->new_value))
- {
- option++;
- continue;
- }
-
- if (gc_backend[option->backend].program)
- err = change_options_program (component, option->backend,
- &src_pathname[option->backend],
- &dest_pathname[option->backend],
- &orig_pathname[option->backend]);
- else
- err = change_options_file (component, option->backend,
- &src_pathname[option->backend],
- &dest_pathname[option->backend],
- &orig_pathname[option->backend]);
-
- if (err)
- break;
-
- option++;
- }
-
- if (!err)
- {
- int i;
-
- for (i = 0; i < GC_BACKEND_NR; i++)
- {
- if (src_pathname[i])
- {
- /* FIXME: Make a verification here. */
-
- assert (dest_pathname[i]);
-
- if (orig_pathname[i])
- err = rename (src_pathname[i], dest_pathname[i]);
- else
- {
- /* This is a bit safer than rename() because we
- expect DEST_PATHNAME not to be there. If it
- happens to be there, this will fail. */
- err = link (src_pathname[i], dest_pathname[i]);
- if (!err)
- unlink (src_pathname[i]);
- }
- if (err)
- break;
- src_pathname[i] = NULL;
- }
- }
- }
-
- if (err)
- {
- int i;
- int saved_errno = errno;
-
- /* An error occured. */
- for (i = 0; i < GC_BACKEND_NR; i++)
- {
- if (src_pathname[i])
- {
- /* The change was not yet committed. */
- unlink (src_pathname[i]);
- if (orig_pathname[i])
- unlink (orig_pathname[i]);
- }
- else
- {
- /* The changes were already committed. FIXME: This is a
- tad dangerous, as we don't know if we don't overwrite
- a version of the file that is even newer than the one
- we just installed. */
- if (orig_pathname[i])
- rename (orig_pathname[i], dest_pathname[i]);
- else
- unlink (dest_pathname[i]);
- }
- }
- gc_error (1, saved_errno, "could not commit changes");
- }
-
- /* If it all worked, notify the daemons of the changes. */
- if (opt.runtime)
- for (backend = 0; backend < GC_BACKEND_NR; backend++)
- {
- if (runtime[backend] && gc_backend[backend].runtime_change)
- (*gc_backend[backend].runtime_change) ();
- }
-
- /* Move the per-process backup file into its place. */
- for (backend = 0; backend < GC_BACKEND_NR; backend++)
- if (orig_pathname[backend])
- {
- char *backup_pathname;
-
- assert (dest_pathname[backend]);
-
- backup_pathname = xasprintf ("%s.gpgconf.bak", dest_pathname[backend]);
- rename (orig_pathname[backend], backup_pathname);
- }
-
- xfree (line);
-}
diff --git a/tools/gpgconf.c b/tools/gpgconf.c
deleted file mode 100644
index 7aca335fa..000000000
--- a/tools/gpgconf.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/* gpgconf.c - Configuration utility for GnuPG
- * Copyright (C) 2003 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "gpgconf.h"
-#include "i18n.h"
-
-/* Constants to identify the commands and options. */
-enum cmd_and_opt_values
- {
- aNull = 0,
- oDryRun = 'n',
- oOutput = 'o',
- oQuiet = 'q',
- oVerbose = 'v',
- oRuntime = 'r',
- oComponent = 'c',
- oNoVerbose = 500,
- oHomedir,
-
- aListComponents,
- aListOptions,
- aChangeOptions,
-
- };
-
-
-/* The list of commands and options. */
-static ARGPARSE_OPTS opts[] =
- {
- { 300, NULL, 0, N_("@Commands:\n ") },
-
- { aListComponents, "list-components", 256, N_("list all components") },
- { aListOptions, "list-options", 256, N_("|COMPONENT|list options") },
- { aChangeOptions, "change-options", 256, N_("|COMPONENT|change options") },
-
- { 301, NULL, 0, N_("@\nOptions:\n ") },
-
- { oOutput, "output", 2, N_("use as output file") },
- { oVerbose, "verbose", 0, N_("verbose") },
- { oQuiet, "quiet", 0, N_("quiet") },
- { oDryRun, "dry-run", 0, N_("do not make any changes") },
- { oRuntime, "runtime", 0, N_("activate changes at runtime, if possible") },
-
- /* hidden options */
- { oNoVerbose, "no-verbose", 0, "@"},
- {0}
- };
-
-
-/* Print usage information and and provide strings for help. */
-static const char *
-my_strusage( int level )
-{
- const char *p;
-
- switch (level)
- {
- case 11: p = "gpgconf (GnuPG)";
- break;
- case 13: p = VERSION; break;
- case 17: p = PRINTABLE_OS_NAME; break;
- case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
- break;
- case 1:
- case 40: p = _("Usage: gpgconf [options] (-h for help)");
- break;
- case 41:
- p = _("Syntax: gpgconf [options]\n"
- "Manage configuration options for tools of the GnuPG system\n");
- break;
-
- default: p = NULL; break;
- }
- return p;
-}
-
-
-/* Initialize the gettext system. */
-static void
-i18n_init(void)
-{
-#ifdef USE_SIMPLE_GETTEXT
- set_gettext_file (PACKAGE_GT);
-#else
-# ifdef ENABLE_NLS
-# ifdef HAVE_LC_MESSAGES
- setlocale (LC_TIME, "");
- setlocale (LC_MESSAGES, "");
-# else
- setlocale (LC_ALL, "" );
-# endif
- bindtextdomain (PACKAGE_GT, LOCALEDIR);
- textdomain (PACKAGE_GT);
-# endif
-#endif
-}
-
-
-/* gpgconf main. */
-int
-main (int argc, char **argv)
-{
- ARGPARSE_ARGS pargs;
- const char *fname;
- int no_more_options = 0;
- enum cmd_and_opt_values cmd = 0;
-
- set_strusage (my_strusage);
- log_set_prefix ("gpgconf", 1);
-
- i18n_init();
-
- /* Parse the command line. */
- pargs.argc = &argc;
- pargs.argv = &argv;
- pargs.flags = 1; /* Do not remove the args. */
- while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts))
- {
- switch (pargs.r_opt)
- {
- case oOutput: opt.outfile = pargs.r.ret_str; break;
- case oQuiet: opt.quiet = 1; break;
- case oDryRun: opt.dry_run = 1; break;
- case oRuntime:
- opt.runtime = 1;
- break;
- case oVerbose: opt.verbose++; break;
- case oNoVerbose: opt.verbose = 0; break;
-
- case aListComponents:
- case aListOptions:
- case aChangeOptions:
- cmd = pargs.r_opt;
- break;
-
- default: pargs.err = 2; break;
- }
- }
-
- if (log_get_errorcount (0))
- exit (2);
-
- fname = argc ? *argv : NULL;
-
- switch (cmd)
- {
- case aListComponents:
- default:
- /* List all components. */
- gc_component_list_components (stdout);
- break;
-
- case aListOptions:
- case aChangeOptions:
- if (!fname)
- {
- fputs (N_("usage: gpgconf [options] "), stderr);
- fputs (N_("Need one component argument"), stderr);
- putc ('\n',stderr);
- exit (2);
- }
- else
- {
- int idx = gc_component_find (fname);
- if (idx < 0)
- {
- fputs (N_("Component not found"), stderr);
- putc ('\n', stderr);
- exit (1);
- }
- gc_component_retrieve_options (idx);
- if (cmd == aListOptions)
- gc_component_list_options (idx, stdout);
- else
- gc_component_change_options (idx, stdin);
- }
- }
-
- return 0;
-}
-
-
-
diff --git a/tools/gpgconf.h b/tools/gpgconf.h
deleted file mode 100644
index 138380b6d..000000000
--- a/tools/gpgconf.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* gpgconf.h - Global definitions for gpgconf
- * Copyright (C) 2003 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef GPGCONF_H
-#define GPGCONF_H
-
-#include "../common/util.h"
-
-/* We keep all global options in the structure OPT. */
-struct
-{
- int verbose; /* Verbosity level. */
- int quiet; /* Be extra quiet. */
- int dry_run; /* Don't change any persistent data. */
- int runtime; /* Make changes active at runtime. */
- char *outfile; /* Name of output file. */
-
- int component; /* The active component. */
-} opt;
-
-
-
-/*-- gpgconf-comp.c --*/
-/* List all components that are available. */
-void gc_component_list_components (FILE *out);
-
-/* Find the component with the name NAME. Returns -1 if not
- found. */
-int gc_component_find (const char *name);
-
-/* Retrieve the currently active options and their defaults from all
- involved backends for this component. */
-void gc_component_retrieve_options (int component);
-
-/* List all options of the component COMPONENT. */
-void gc_component_list_options (int component, FILE *out);
-
-/* Read the modifications from IN and apply them. */
-void gc_component_change_options (int component, FILE *in);
-
-#endif /*GPGCONF_H*/
diff --git a/tools/gpgparsemail.c b/tools/gpgparsemail.c
deleted file mode 100644
index fa848c8f6..000000000
--- a/tools/gpgparsemail.c
+++ /dev/null
@@ -1,705 +0,0 @@
-/* gpgparsemail.c - Standalone crypto mail parser
- * Copyright (C) 2004 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-
-/* This utility prints an RFC8222, possible MIME structured, message
- in an annotated format with the first column having an indicator
- for the content of the line.. Several options are available to
- scrutinize the message. S/MIME and OpenPGP suuport is included. */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <time.h>
-#include <signal.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/wait.h>
-
-#include "rfc822parse.h"
-
-
-#define PGM "gpgparsemail"
-
-/* Option flags. */
-static int verbose;
-static int debug;
-static int opt_crypto; /* Decrypt or verify messages. */
-static int opt_no_header; /* Don't output the header lines. */
-
-/* Structure used to communicate with the parser callback. */
-struct parse_info_s {
- int show_header; /* Show the header lines. */
- int show_data; /* Show the data lines. */
- unsigned int skip_show; /* Temporary disable above for these
- number of lines. */
- int show_data_as_note; /* The next data line should be shown
- as a note. */
- int show_boundary;
- int nesting_level;
-
- int gpgsm_mime; /* gpgsm shall be used from S/MIME. */
- char *signing_protocol;
- int hashing_level; /* The nesting level we are hashing. */
- int hashing;
- FILE *hash_file;
- FILE *sig_file;
- int verify_now; /* Falg set when all signature data is
- available. */
-};
-
-
-/* Print diagnostic message and exit with failure. */
-static void
-die (const char *format, ...)
-{
- va_list arg_ptr;
-
- fflush (stdout);
- fprintf (stderr, "%s: ", PGM);
-
- va_start (arg_ptr, format);
- vfprintf (stderr, format, arg_ptr);
- va_end (arg_ptr);
- putc ('\n', stderr);
-
- exit (1);
-}
-
-
-/* Print diagnostic message. */
-static void
-err (const char *format, ...)
-{
- va_list arg_ptr;
-
- fflush (stdout);
- fprintf (stderr, "%s: ", PGM);
-
- va_start (arg_ptr, format);
- vfprintf (stderr, format, arg_ptr);
- va_end (arg_ptr);
- putc ('\n', stderr);
-}
-
-static void *
-xmalloc (size_t n)
-{
- void *p = malloc (n);
- if (!p)
- die ("out of core: %s", strerror (errno));
- return p;
-}
-
-/* static void * */
-/* xcalloc (size_t n, size_t m) */
-/* { */
-/* void *p = calloc (n, m); */
-/* if (!p) */
-/* die ("out of core: %s", strerror (errno)); */
-/* return p; */
-/* } */
-
-/* static void * */
-/* xrealloc (void *old, size_t n) */
-/* { */
-/* void *p = realloc (old, n); */
-/* if (!p) */
-/* die ("out of core: %s", strerror (errno)); */
-/* return p; */
-/* } */
-
-static char *
-xstrdup (const char *string)
-{
- void *p = malloc (strlen (string)+1);
- if (!p)
- die ("out of core: %s", strerror (errno));
- strcpy (p, string);
- return p;
-}
-
-static char *
-stpcpy (char *a,const char *b)
-{
- while (*b)
- *a++ = *b++;
- *a = 0;
-
- return (char*)a;
-}
-
-
-static int
-run_gnupg (int smime, int sig_fd, int data_fd, int *close_list)
-{
- int rp[2];
- pid_t pid;
- int i, c, is_status;
- unsigned int pos;
- char status_buf[10];
- const char *cmd = smime? "gpgsm":"gpg";
- FILE *fp;
-
- if (pipe (rp) == -1)
- die ("error creating a pipe: %s", strerror (errno));
-
- pid = fork ();
- if (pid == -1)
- die ("error forking process: %s", strerror (errno));
-
- if (!pid)
- { /* Child. */
- char data_fd_buf[50];
- int fd;
-
- /* Connect our signature fd to stdin. */
- if (sig_fd != 0)
- {
- if (dup2 (sig_fd, 0) == -1)
- die ("dup2 stdin failed: %s", strerror (errno));
- }
-
- /* Keep our data fd and format it for gpg/gpgsm use. */
- sprintf (data_fd_buf, "-&%d", data_fd);
-
- /* Send stdout to the bit bucket. */
- fd = open ("/dev/null", O_WRONLY);
- if (fd == -1)
- die ("can't open `/dev/null': %s", strerror (errno));
- if (fd != 1)
- {
- if (dup2 (fd, 1) == -1)
- die ("dup2 stderr failed: %s", strerror (errno));
- }
-
- /* Connect stderr to our pipe. */
- if (rp[1] != 2)
- {
- if (dup2 (rp[1], 2) == -1)
- die ("dup2 stderr failed: %s", strerror (errno));
- }
-
- /* Close other files. */
- for (i=0; (fd=close_list[i]) != -1; i++)
- if (fd > 2 && fd != data_fd)
- close (fd);
- errno = 0;
-
- execlp (cmd, cmd,
- "--enable-special-filenames",
- "--status-fd", "2",
- "--assume-base64",
- "--verify",
- "--",
- "-", data_fd_buf,
- NULL);
-
- die ("failed to exec the crypto command: %s", strerror (errno));
- }
-
- /* Parent. */
- close (rp[1]);
-
- fp = fdopen (rp[0], "r");
- if (!fp)
- die ("can't fdopen pipe for reading: %s", strerror (errno));
-
- pos = 0;
- is_status = 0;
- assert (sizeof status_buf > 9);
- while ((c=getc (fp)) != EOF)
- {
- if (pos < 9)
- status_buf[pos] = c;
- else
- {
- if (pos == 9)
- {
- is_status = !memcmp (status_buf, "[GNUPG:] ", 9);
- if (is_status)
- fputs ( "c ", stdout);
- else if (verbose)
- fputs ( "# ", stdout);
- fwrite (status_buf, 9, 1, stdout);
- }
- putchar (c);
- }
- if (c == '\n')
- {
- if (verbose && pos < 9)
- {
- fputs ( "# ", stdout);
- fwrite (status_buf, pos+1, 1, stdout);
- }
- pos = 0;
- }
- else
- pos++;
- }
- if (pos)
- {
- if (verbose && pos < 9)
- {
- fputs ( "# ", stdout);
- fwrite (status_buf, pos+1, 1, stdout);
- }
- putchar ('\n');
- }
- fclose (fp);
-
- while ( (i=waitpid (pid, NULL, 0)) == -1 && errno == EINTR)
- ;
- if (i == -1)
- die ("waiting for child failed: %s", strerror (errno));
-
- return 0;
-}
-
-
-
-
-/* Verify the signature in the current temp files. */
-static void
-verify_signature (struct parse_info_s *info)
-{
- int close_list[10];
-
- assert (info->hash_file);
- assert (info->sig_file);
- rewind (info->hash_file);
- rewind (info->sig_file);
-
-/* printf ("# Begin hashed data\n"); */
-/* while ( (c=getc (info->hash_file)) != EOF) */
-/* putchar (c); */
-/* printf ("# End hashed data signature\n"); */
-/* printf ("# Begin signature\n"); */
-/* while ( (c=getc (info->sig_file)) != EOF) */
-/* putchar (c); */
-/* printf ("# End signature\n"); */
-/* rewind (info->hash_file); */
-/* rewind (info->sig_file); */
-
- close_list[0] = -1;
- run_gnupg (1, fileno (info->sig_file), fileno (info->hash_file), close_list);
-}
-
-
-
-
-
-/* Prepare for a multipart/signed.
- FIELD_CTX is the parsed context of the content-type header.*/
-static void
-mime_signed_begin (struct parse_info_s *info, rfc822parse_t msg,
- rfc822parse_field_t field_ctx)
-{
- const char *s;
- s = rfc822parse_query_parameter (field_ctx, "protocol", 1);
- if (s)
- {
- printf ("h signed.protocol: %s\n", s);
- if (!strcmp (s, "application/pkcs7-signature")
- || !strcmp (s, "application/x-pkcs7-signature"))
- {
- if (info->gpgsm_mime)
- err ("note: ignoring nested pkcs7-signature");
- else
- {
- info->gpgsm_mime = 1;
- free (info->signing_protocol);
- info->signing_protocol = xstrdup (s);
- }
- }
- else if (verbose)
- printf ("# this protocol is not supported\n");
- }
-}
-
-
-/* Prepare for a multipart/encrypted.
- FIELD_CTX is the parsed context of the content-type header.*/
-static void
-mime_encrypted_begin (struct parse_info_s *info, rfc822parse_t msg,
- rfc822parse_field_t field_ctx)
-{
- const char *s;
- s = rfc822parse_query_parameter (field_ctx, "protocol", 0);
- if (s)
- printf ("h encrypted.protocol: %s\n", s);
-}
-
-
-
-/* Print the event received by the parser for debugging as comment
- line. */
-static void
-show_event (rfc822parse_event_t event)
-{
- const char *s;
-
- switch (event)
- {
- case RFC822PARSE_OPEN: s= "Open"; break;
- case RFC822PARSE_CLOSE: s= "Close"; break;
- case RFC822PARSE_CANCEL: s= "Cancel"; break;
- case RFC822PARSE_T2BODY: s= "T2Body"; break;
- case RFC822PARSE_FINISH: s= "Finish"; break;
- case RFC822PARSE_RCVD_SEEN: s= "Rcvd_Seen"; break;
- case RFC822PARSE_LEVEL_DOWN: s= "Level_Down"; break;
- case RFC822PARSE_LEVEL_UP: s= "Level_Up"; break;
- case RFC822PARSE_BOUNDARY: s= "Boundary"; break;
- case RFC822PARSE_LAST_BOUNDARY: s= "Last_Boundary"; break;
- case RFC822PARSE_BEGIN_HEADER: s= "Begin_Header"; break;
- case RFC822PARSE_PREAMBLE: s= "Preamble"; break;
- case RFC822PARSE_EPILOGUE: s= "Epilogue"; break;
- default: s= "[unknown event]"; break;
- }
- printf ("# *** got RFC822 event %s\n", s);
-}
-
-/* This function is called by the parser to communicate events. This
- callback comminucates with the main program using a structure
- passed in OPAQUE. Should retrun 0 or set errno and return -1. */
-static int
-message_cb (void *opaque, rfc822parse_event_t event, rfc822parse_t msg)
-{
- struct parse_info_s *info = opaque;
-
- if (debug)
- show_event (event);
- if (event == RFC822PARSE_OPEN)
- {
- /* Initialize for a new message. */
- info->show_header = 1;
- }
- else if (event == RFC822PARSE_T2BODY)
- {
- rfc822parse_field_t ctx;
-
- ctx = rfc822parse_parse_field (msg, "Content-Type", -1);
- if (ctx)
- {
- const char *s1, *s2;
- s1 = rfc822parse_query_media_type (ctx, &s2);
- if (s1)
- {
- printf ("h media: %*s%s %s\n",
- info->nesting_level*2, "", s1, s2);
- if (info->gpgsm_mime == 3)
- {
- char *buf = xmalloc (strlen (s1) + strlen (s2) + 2);
- strcpy (stpcpy (stpcpy (buf, s1), "/"), s2);
- assert (info->signing_protocol);
- if (strcmp (buf, info->signing_protocol))
- err ("invalid S/MIME structure; expected `%s', found `%s'",
- info->signing_protocol, buf);
- else
- {
- printf ("c begin_signature\n");
- info->gpgsm_mime++;
- if (opt_crypto)
- {
- assert (!info->sig_file);
- info->sig_file = tmpfile ();
- if (!info->sig_file)
- die ("error creating temp file: %s",
- strerror (errno));
- }
- }
- free (buf);
- }
- else if (!strcmp (s1, "multipart"))
- {
- if (!strcmp (s2, "signed"))
- mime_signed_begin (info, msg, ctx);
- else if (!strcmp (s2, "encrypted"))
- mime_encrypted_begin (info, msg, ctx);
- }
- }
- else
- printf ("h media: %*s none\n", info->nesting_level*2, "");
-
- rfc822parse_release_field (ctx);
- }
- else
- printf ("h media: %*stext plain [assumed]\n",
- info->nesting_level*2, "");
- info->show_header = 0;
- info->show_data = 1;
- info->skip_show = 1;
- }
- else if (event == RFC822PARSE_PREAMBLE)
- info->show_data_as_note = 1;
- else if (event == RFC822PARSE_LEVEL_DOWN)
- {
- printf ("b down\n");
- info->nesting_level++;
- }
- else if (event == RFC822PARSE_LEVEL_UP)
- {
- printf ("b up\n");
- if (info->nesting_level)
- info->nesting_level--;
- else
- err ("invalid structure (bad nesting level)");
- }
- else if (event == RFC822PARSE_BOUNDARY || event == RFC822PARSE_LAST_BOUNDARY)
- {
- info->show_data = 0;
- info->show_boundary = 1;
- if (event == RFC822PARSE_BOUNDARY)
- {
- info->show_header = 1;
- info->skip_show = 1;
- printf ("b part\n");
- }
- else
- printf ("b last\n");
-
- if (info->gpgsm_mime == 2 && info->nesting_level == info->hashing_level)
- {
- printf ("c end_hash\n");
- info->gpgsm_mime++;
- info->hashing = 0;
- }
- else if (info->gpgsm_mime == 4)
- {
- printf ("c end_signature\n");
- info->verify_now = 1;
- }
- }
- else if (event == RFC822PARSE_BEGIN_HEADER)
- {
- if (info->gpgsm_mime == 1)
- {
- printf ("c begin_hash\n");
- info->hashing = 1;
- info->hashing_level = info->nesting_level;
- info->gpgsm_mime++;
-
- if (opt_crypto)
- {
- assert (!info->hash_file);
- info->hash_file = tmpfile ();
- if (!info->hash_file)
- die ("failed to create temporary file: %s", strerror (errno));
- }
- }
- }
-
- return 0;
-}
-
-
-/* Read a message from FP and process it according to the global
- options. */
-static void
-parse_message (FILE *fp)
-{
- char line[5000];
- size_t length;
- rfc822parse_t msg;
- unsigned int lineno = 0;
- int no_cr_reported = 0;
- struct parse_info_s info;
-
- memset (&info, 0, sizeof info);
-
- msg = rfc822parse_open (message_cb, &info);
- if (!msg)
- die ("can't open parser: %s", strerror (errno));
-
- /* Fixme: We should not use fgets becuase it can't cope with
- embedded nul characters. */
- while (fgets (line, sizeof (line), fp))
- {
- lineno++;
- if (lineno == 1 && !strncmp (line, "From ", 5))
- continue; /* We better ignore a leading From line. */
-
- length = strlen (line);
- if (length && line[length - 1] == '\n')
- line[--length] = 0;
- else
- err ("line number %u too long or last line not terminated", lineno);
- if (length && line[length - 1] == '\r')
- line[--length] = 0;
- else if (verbose && !no_cr_reported)
- {
- err ("non canonical ended line detected (line %u)", lineno);
- no_cr_reported = 1;
- }
-
-
- if (rfc822parse_insert (msg, line, length))
- die ("parser failed: %s", strerror (errno));
-
- if (info.hashing)
- {
- /* Delay hashing of the CR/LF because the last line ending
- belongs to the next boundary. */
- if (debug)
- printf ("# hashing %s`%s'\n", info.hashing==2?"CR,LF+":"", line);
- if (opt_crypto)
- {
- if (info.hashing == 2)
- fputs ("\r\n", info.hash_file);
- fputs (line, info.hash_file);
- if (ferror (info.hash_file))
- die ("error writing to temporary file: %s", strerror (errno));
- }
-
- info.hashing = 2;
- }
-
- if (info.sig_file && opt_crypto)
- {
- if (info.verify_now)
- {
- verify_signature (&info);
- fclose (info.hash_file);
- info.hash_file = NULL;
- fclose (info.sig_file);
- info.sig_file = NULL;
- info.gpgsm_mime = 0;
- }
- else
- {
- fputs (line, info.sig_file);
- fputs ("\r\n", info.sig_file);
- if (ferror (info.sig_file))
- die ("error writing to temporary file: %s", strerror (errno));
- }
- }
-
- if (info.show_boundary)
- {
- if (!opt_no_header)
- printf (":%s\n", line);
- info.show_boundary = 0;
- }
-
- if (info.skip_show)
- info.skip_show--;
- else if (info.show_data)
- {
- if (info.show_data_as_note)
- {
- if (verbose)
- printf ("# DATA: %s\n", line);
- info.show_data_as_note = 0;
- }
- else
- printf (" %s\n", line);
- }
- else if (info.show_header && !opt_no_header)
- printf (".%s\n", line);
-
- }
-
- rfc822parse_close (msg);
-}
-
-
-int
-main (int argc, char **argv)
-{
- int last_argc = -1;
-
- if (argc)
- {
- argc--; argv++;
- }
- while (argc && last_argc != argc )
- {
- last_argc = argc;
- if (!strcmp (*argv, "--"))
- {
- argc--; argv++;
- break;
- }
- else if (!strcmp (*argv, "--help"))
- {
- puts (
- "Usage: " PGM " [OPTION] [FILE]\n"
- "Parse a mail message into an annotated format.\n\n"
- " --crypto decrypt or verify messages\n"
- " --no-header don't output the header lines\n"
- " --verbose enable extra informational output\n"
- " --debug enable additional debug output\n"
- " --help display this help and exit\n\n"
- "With no FILE, or when FILE is -, read standard input.\n\n"
- "Report bugs to <[email protected]>.");
- exit (0);
- }
- else if (!strcmp (*argv, "--verbose"))
- {
- verbose = 1;
- argc--; argv++;
- }
- else if (!strcmp (*argv, "--debug"))
- {
- verbose = debug = 1;
- argc--; argv++;
- }
- else if (!strcmp (*argv, "--crypto"))
- {
- opt_crypto = 1;
- argc--; argv++;
- }
- else if (!strcmp (*argv, "--no-header"))
- {
- opt_no_header = 1;
- argc--; argv++;
- }
- }
-
- if (argc > 1)
- die ("usage: " PGM " [OPTION] [FILE] (try --help for more information)\n");
-
- signal (SIGPIPE, SIG_IGN);
-
- if (argc && strcmp (*argv, "-"))
- {
- FILE *fp = fopen (*argv, "rb");
- if (!fp)
- die ("can't open `%s': %s", *argv, strerror (errno));
- parse_message (fp);
- fclose (fp);
- }
- else
- parse_message (stdin);
-
- return 0;
-}
-
-
-/*
-Local Variables:
-compile-command: "gcc -Wall -g -o gpgparsemail rfc822parse.c gpgparsemail.c"
-End:
-*/
diff --git a/tools/no-libgcrypt.c b/tools/no-libgcrypt.c
deleted file mode 100644
index 0fabec90d..000000000
--- a/tools/no-libgcrypt.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/* no-libgcrypt.c - Replacement functions for libgcrypt.
- * Copyright (C) 2003 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include "../common/util.h"
-#include "i18n.h"
-
-
-/* Replace libgcrypt's malloc functions which are used by
- ../jnlib/libjnlib.a . ../common/util.h defines macros to map them
- to xmalloc etc. */
-static void
-out_of_core (void)
-{
- log_fatal (_("error allocating enough memory: %s\n"), strerror (errno));
-}
-
-
-void *
-gcry_malloc (size_t n)
-{
- return malloc (n);
-}
-
-void *
-gcry_xmalloc (size_t n)
-{
- void *p = malloc (n);
- if (!p)
- out_of_core ();
- return p;
-}
-
-
-void *
-gcry_realloc (void *a, size_t n)
-{
- return realloc (a, n);
-}
-
-void *
-gcry_xrealloc (void *a, size_t n)
-{
- void *p = realloc (a, n);
- if (!p)
- out_of_core ();
- return p;
-}
-
-
-
-void *
-gcry_calloc (size_t n, size_t m)
-{
- return calloc (n, m);
-}
-
-void *
-gcry_xcalloc (size_t n, size_t m)
-{
- void *p = calloc (n, m);
- if (!p)
- out_of_core ();
- return p;
-}
-
-
-char *
-gcry_xstrdup (const char *string)
-{
- void *p = malloc (strlen (string)+1);
- if (!p)
- out_of_core ();
- strcpy( p, string );
- return p;
-}
-
-void
-gcry_free (void *a)
-{
- if (a)
- free (a);
-}
diff --git a/tools/rfc822parse.c b/tools/rfc822parse.c
deleted file mode 100644
index be1cf4a47..000000000
--- a/tools/rfc822parse.c
+++ /dev/null
@@ -1,1235 +0,0 @@
-/* rfc822parse.c - Simple mail and MIME parser
- * Copyright (C) 1999, 2000 Werner Koch, Duesseldorf
- * Copyright (C) 2003, g10 Code GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-
-/* According to RFC822 binary 0 are allowed at many places. We
- * do not handle this correct especially in the field parsing code. It
- * should be easy to fix and the API provides a interfcaes which returns
- * the length but in addition makes sure that returned strings are always
- * ended by a \0.
- *
- * Furthermore, the case of field names is changed and thus it is not
- * always a good idea to use these modified header
- * lines (e.g. signatures may break).
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <assert.h>
-
-#include "rfc822parse.h"
-
-enum token_type
-{
- tSPACE,
- tATOM,
- tQUOTED,
- tDOMAINLIT,
- tSPECIAL
-};
-
-/* For now we directly use our TOKEN as the parse context */
-typedef struct rfc822parse_field_context *TOKEN;
-struct rfc822parse_field_context
-{
- TOKEN next;
- enum token_type type;
- struct {
- unsigned int cont:1;
- unsigned int lowered:1;
- } flags;
- /*TOKEN owner_pantry; */
- char data[1];
-};
-
-struct hdr_line
-{
- struct hdr_line *next;
- int cont; /* This is a continuation of the previous line. */
- unsigned char line[1];
-};
-
-typedef struct hdr_line *HDR_LINE;
-
-
-struct part
-{
- struct part *right; /* The next part. */
- struct part *down; /* A contained part. */
- HDR_LINE hdr_lines; /* Header lines os that part. */
- HDR_LINE *hdr_lines_tail; /* Helper for adding lines. */
- char *boundary; /* Only used in the first part. */
-};
-typedef struct part *part_t;
-
-struct rfc822parse_context
-{
- rfc822parse_cb_t callback;
- void *callback_value;
- int callback_error;
- int in_body;
- int in_preamble; /* Wether we are before the first boundary. */
- part_t parts; /* The tree of parts. */
- part_t current_part; /* Whom we are processing (points into parts). */
- const char *boundary; /* Current boundary. */
-};
-
-static HDR_LINE find_header (rfc822parse_t msg, const char *name,
- int which, HDR_LINE * rprev);
-
-
-static size_t
-length_sans_trailing_ws (const unsigned char *line, size_t len)
-{
- const unsigned char *p, *mark;
- size_t n;
-
- for (mark=NULL, p=line, n=0; n < len; n++, p++)
- {
- if (strchr (" \t\r\n", *p ))
- {
- if( !mark )
- mark = p;
- }
- else
- mark = NULL;
- }
-
- if (mark)
- return mark - line;
- return len;
-}
-
-
-static void
-lowercase_string (unsigned char *string)
-{
- for (; *string; string++)
- if (*string >= 'A' && *string <= 'Z')
- *string = *string - 'A' + 'a';
-}
-
-/* Transform a header name into a standard capitalized format; i.e
- "Content-Type". Conversion stops at the colon. As usual we don't
- use the localized versions of ctype.h.
- */
-static void
-capitalize_header_name (unsigned char *name)
-{
- int first = 1;
-
- for (; *name && *name != ':'; name++)
- if (*name == '-')
- first = 1;
- else if (first)
- {
- if (*name >= 'a' && *name <= 'z')
- *name = *name - 'a' + 'A';
- first = 0;
- }
- else if (*name >= 'A' && *name <= 'Z')
- *name = *name - 'A' + 'a';
-}
-
-
-static char *
-stpcpy (char *a,const char *b)
-{
- while (*b)
- *a++ = *b++;
- *a = 0;
-
- return (char*)a;
-}
-
-
-/* If a callback has been registerd, call it for the event of type
- EVENT. */
-static int
-do_callback (rfc822parse_t msg, rfc822parse_event_t event)
-{
- int rc;
-
- if (!msg->callback || msg->callback_error)
- return 0;
- rc = msg->callback (msg->callback_value, event, msg);
- if (rc)
- msg->callback_error = rc;
- return rc;
-}
-
-static part_t
-new_part (void)
-{
- part_t part;
-
- part = calloc (1, sizeof *part);
- if (part)
- {
- part->hdr_lines_tail = &part->hdr_lines;
- }
- return part;
-}
-
-
-static void
-release_part (part_t part)
-{
- part_t tmp;
- HDR_LINE hdr, hdr2;
-
- for (; part; part = tmp)
- {
- tmp = part->right;
- if (part->down)
- release_part (part->down);
- for (hdr = part->hdr_lines; hdr; hdr = hdr2)
- {
- hdr2 = hdr->next;
- free (hdr);
- }
- free (part->boundary);
- free (part);
- }
-}
-
-
-static void
-release_handle_data (rfc822parse_t msg)
-{
- release_part (msg->parts);
- msg->parts = NULL;
- msg->current_part = NULL;
- msg->boundary = NULL;
-}
-
-
-/* Create a new parsing context for an entire rfc822 message and
- return it. CB and CB_VALUE may be given to callback for certain
- events. NULL is returned on error with errno set appropriately. */
-rfc822parse_t
-rfc822parse_open (rfc822parse_cb_t cb, void *cb_value)
-{
- rfc822parse_t msg = calloc (1, sizeof *msg);
- if (msg)
- {
- msg->parts = msg->current_part = new_part ();
- if (!msg->parts)
- {
- free (msg);
- msg = NULL;
- }
- else
- {
- msg->callback = cb;
- msg->callback_value = cb_value;
- if (do_callback (msg, RFC822PARSE_OPEN))
- {
- release_handle_data (msg);
- free (msg);
- msg = NULL;
- }
- }
- }
- return msg;
-}
-
-
-void
-rfc822parse_cancel (rfc822parse_t msg)
-{
- if (msg)
- {
- do_callback (msg, RFC822PARSE_CANCEL);
- release_handle_data (msg);
- free (msg);
- }
-}
-
-
-void
-rfc822parse_close (rfc822parse_t msg)
-{
- if (msg)
- {
- do_callback (msg, RFC822PARSE_CLOSE);
- release_handle_data (msg);
- free (msg);
- }
-}
-
-static part_t
-find_parent (part_t tree, part_t target)
-{
- part_t part;
-
- for (part = tree->down; part; part = part->right)
- {
- if (part == target)
- return tree; /* Found. */
- if (part->down)
- {
- part_t tmp = find_parent (part, target);
- if (tmp)
- return tmp;
- }
- }
- return NULL;
-}
-
-static void
-set_current_part_to_parent (rfc822parse_t msg)
-{
- part_t parent;
-
- assert (msg->current_part);
- parent = find_parent (msg->parts, msg->current_part);
- if (!parent)
- return; /* Already at the top. */
-
-#ifndef NDEBUG
- {
- part_t part;
- for (part = parent->down; part; part = part->right)
- if (part == msg->current_part)
- break;
- assert (part);
- }
-#endif
- msg->current_part = parent;
-
- parent = find_parent (msg->parts, parent);
- msg->boundary = parent? parent->boundary: NULL;
-}
-
-
-
-/****************
- * We have read in all header lines and are about to receive the body
- * part. The delimiter line has already been processed.
- *
- * FIXME: we's better return an error in case of memory failures.
- */
-static int
-transition_to_body (rfc822parse_t msg)
-{
- rfc822parse_field_t ctx;
- int rc;
-
- rc = do_callback (msg, RFC822PARSE_T2BODY);
- if (!rc)
- {
- /* Store the boundary if we have multipart type. */
- ctx = rfc822parse_parse_field (msg, "Content-Type", -1);
- if (ctx)
- {
- const char *s;
-
- s = rfc822parse_query_media_type (ctx, NULL);
- if (s && !strcmp (s,"multipart"))
- {
- s = rfc822parse_query_parameter (ctx, "boundary", 0);
- if (s)
- {
- assert (!msg->current_part->boundary);
- msg->current_part->boundary = malloc (strlen (s) + 1);
- if (msg->current_part->boundary)
- {
- part_t part;
-
- strcpy (msg->current_part->boundary, s);
- msg->boundary = msg->current_part->boundary;
- part = new_part ();
- if (!part)
- {
- int save_errno = errno;
- rfc822parse_release_field (ctx);
- errno = save_errno;
- return -1;
- }
- rc = do_callback (msg, RFC822PARSE_LEVEL_DOWN);
- assert (!msg->current_part->down);
- msg->current_part->down = part;
- msg->current_part = part;
- msg->in_preamble = 1;
- }
- }
- }
- rfc822parse_release_field (ctx);
- }
- }
-
- return rc;
-}
-
-/* We have just passed a MIME boundary and need to prepare for new part.
- headers. */
-static int
-transition_to_header (rfc822parse_t msg)
-{
- part_t part;
-
- assert (msg->current_part);
- assert (!msg->current_part->right);
-
- part = new_part ();
- if (!part)
- return -1;
-
- msg->current_part->right = part;
- msg->current_part = part;
- return 0;
-}
-
-
-static int
-insert_header (rfc822parse_t msg, const unsigned char *line, size_t length)
-{
- HDR_LINE hdr;
-
- assert (msg->current_part);
- if (!length)
- {
- msg->in_body = 1;
- return transition_to_body (msg);
- }
-
- if (!msg->current_part->hdr_lines)
- do_callback (msg, RFC822PARSE_BEGIN_HEADER);
-
- length = length_sans_trailing_ws (line, length);
- hdr = malloc (sizeof (*hdr) + length);
- if (!hdr)
- return -1;
- hdr->next = NULL;
- hdr->cont = (*line == ' ' || *line == '\t');
- memcpy (hdr->line, line, length);
- hdr->line[length] = 0; /* Make it a string. */
-
- /* Transform a field name into canonical format. */
- if (!hdr->cont && strchr (line, ':'))
- capitalize_header_name (hdr->line);
-
- *msg->current_part->hdr_lines_tail = hdr;
- msg->current_part->hdr_lines_tail = &hdr->next;
-
- /* Lets help the caller to prevent mail loops and issue an event for
- * every Received header. */
- if (length >= 9 && !memcmp (line, "Received:", 9))
- do_callback (msg, RFC822PARSE_RCVD_SEEN);
- return 0;
-}
-
-
-/****************
- * Note: We handle the body transparent to allow binary zeroes in it.
- */
-static int
-insert_body (rfc822parse_t msg, const unsigned char *line, size_t length)
-{
- int rc = 0;
-
- if (length > 2 && *line == '-' && line[1] == '-' && msg->boundary)
- {
- size_t blen = strlen (msg->boundary);
-
- if (length == blen + 2
- && !memcmp (line+2, msg->boundary, blen))
- {
- rc = do_callback (msg, RFC822PARSE_BOUNDARY);
- msg->in_body = 0;
- if (!rc && !msg->in_preamble)
- rc = transition_to_header (msg);
- msg->in_preamble = 0;
- }
- else if (length == blen + 4
- && line[length-2] =='-' && line[length-1] == '-'
- && !memcmp (line+2, msg->boundary, blen))
- {
- rc = do_callback (msg, RFC822PARSE_LAST_BOUNDARY);
- msg->boundary = NULL; /* No current boundary anymore. */
- set_current_part_to_parent (msg);
-
- /* Fixme: The next should acctually be sent right before the
- next boundary, so that we can mark the epilogue. */
- if (!rc)
- rc = do_callback (msg, RFC822PARSE_LEVEL_UP);
- }
- }
- if (msg->in_preamble && !rc)
- rc = do_callback (msg, RFC822PARSE_PREAMBLE);
-
- return rc;
-}
-
-/* Insert the next line into the parser. Return 0 on success or true
- on error with errno set appropriately. */
-int
-rfc822parse_insert (rfc822parse_t msg, const unsigned char *line, size_t length)
-{
- return (msg->in_body
- ? insert_body (msg, line, length)
- : insert_header (msg, line, length));
-}
-
-
-/* Tell the parser that we have finished the message. */
-int
-rfc822parse_finish (rfc822parse_t msg)
-{
- return do_callback (msg, RFC822PARSE_FINISH);
-}
-
-
-
-/****************
- * Get a copy of a header line. The line is returned as one long
- * string with LF to separate the continuation line. Caller must free
- * the return buffer. which may be used to enumerate over all lines.
- * Wildcards are allowed. This function works on the current headers;
- * i.e. the regular mail headers or the MIME headers of the current
- * part.
- *
- * WHICH gives the mode:
- * -1 := Take the last occurence
- * n := Take the n-th one.
- *
- * Returns a newly allocated buffer or NULL on error. errno is set in
- * case of a memory failure or set to 0 if the requested field is not
- * available.
- */
-char *
-rfc822parse_get_field (rfc822parse_t msg, const char *name, int which)
-{
- HDR_LINE h, h2;
- char *buf, *p;
- size_t n;
-
- h = find_header (msg, name, which, NULL);
- if (!h)
- {
- errno = 0;
- return NULL; /* no such field */
- }
-
- n = strlen (h->line) + 1;
- for (h2 = h->next; h2 && h2->cont; h2 = h2->next)
- n += strlen (h2->line) + 1;
-
- buf = p = malloc (n);
- if (buf)
- {
- p = stpcpy (p, h->line);
- *p++ = '\n';
- for (h2 = h->next; h2 && h2->cont; h2 = h2->next)
- {
- p = stpcpy (p, h2->line);
- *p++ = '\n';
- }
- p[-1] = 0;
- }
- return buf;
-}
-
-
-/****************
- * Enumerate all header. Caller has to provide the address of a pointer
- * which has to be initialzed to NULL, the caller should then never change this
- * pointer until he has closed the enumeration by passing again the address
- * of the pointer but with msg set to NULL.
- * The function returns pointers to all the header lines or NULL when
- * all lines have been enumerated or no headers are available.
- */
-const char *
-rfc822parse_enum_header_lines (rfc822parse_t msg, void **context)
-{
- HDR_LINE l;
-
- if (!msg) /* Close. */
- return NULL;
-
- if (*context == msg || !msg->current_part)
- return NULL;
-
- l = *context ? (HDR_LINE) *context : msg->current_part->hdr_lines;
-
- if (l)
- {
- *context = l->next ? (void *) (l->next) : (void *) msg;
- return l->line;
- }
- *context = msg; /* Mark end of list. */
- return NULL;
-}
-
-
-
-/****************
- * Find a header field. If the Name does end in an asterisk this is meant
- * to be a wildcard.
- *
- * which -1 : Retrieve the last field
- * >0 : Retrieve the n-th field
-
- * RPREV may be used to return the predecessor of the returned field;
- * which may be NULL for the very first one. It has to be initialzed
- * to either NULL in which case the search start at the first header line,
- * or it may point to a headerline, where the search should start
- */
-static HDR_LINE
-find_header (rfc822parse_t msg, const char *name, int which, HDR_LINE *rprev)
-{
- HDR_LINE hdr, prev = NULL, mark = NULL;
- unsigned char *p;
- size_t namelen, n;
- int found = 0;
- int glob = 0;
-
- if (!msg->current_part)
- return NULL;
-
- namelen = strlen (name);
- if (namelen && name[namelen - 1] == '*')
- {
- namelen--;
- glob = 1;
- }
-
- hdr = msg->current_part->hdr_lines;
- if (rprev && *rprev)
- {
- /* spool forward to the requested starting place.
- * we cannot simply set this as we have to return
- * the previous list element too */
- for (; hdr && hdr != *rprev; prev = hdr, hdr = hdr->next)
- ;
- }
-
- for (; hdr; prev = hdr, hdr = hdr->next)
- {
- if (hdr->cont)
- continue;
- if (!(p = strchr (hdr->line, ':')))
- continue; /* invalid header, just skip it. */
- n = p - hdr->line;
- if (!n)
- continue; /* invalid name */
- if ((glob ? (namelen <= n) : (namelen == n))
- && !memcmp (hdr->line, name, namelen))
- {
- found++;
- if (which == -1)
- mark = hdr;
- else if (found == which)
- {
- if (rprev)
- *rprev = prev;
- return hdr;
- }
- }
- }
- if (mark && rprev)
- *rprev = prev;
- return mark;
-}
-
-
-
-static const char *
-skip_ws (const char *s)
-{
- while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n')
- s++;
- return s;
-}
-
-
-static void
-release_token_list (TOKEN t)
-{
- while (t)
- {
- TOKEN t2 = t->next;
- /* fixme: If we have owner_pantry, put the token back to
- * this pantry so that it can be reused later */
- free (t);
- t = t2;
- }
-}
-
-
-static TOKEN
-new_token (enum token_type type, const char *buf, size_t length)
-{
- TOKEN t;
-
- /* fixme: look through our pantries to find a suitable
- * token for reuse */
- t = malloc (sizeof *t + length);
- if (t)
- {
- t->next = NULL;
- t->type = type;
- memset (&t->flags, 0, sizeof (t->flags));
- t->data[0] = 0;
- if (buf)
- {
- memcpy (t->data, buf, length);
- t->data[length] = 0; /* Make sure it is a C string. */
- }
- else
- t->data[0] = 0;
- }
- return t;
-}
-
-static TOKEN
-append_to_token (TOKEN old, const char *buf, size_t length)
-{
- size_t n = strlen (old->data);
- TOKEN t;
-
- t = malloc (sizeof *t + n + length);
- if (t)
- {
- t->next = old->next;
- t->type = old->type;
- t->flags = old->flags;
- memcpy (t->data, old->data, n);
- memcpy (t->data + n, buf, length);
- t->data[n + length] = 0;
- old->next = NULL;
- release_token_list (old);
- }
- return t;
-}
-
-
-
-/*
- Parse a field into tokens as defined by rfc822.
- */
-static TOKEN
-parse_field (HDR_LINE hdr)
-{
- static const char specials[] = "<>@.,;:\\[]\"()";
- static const char specials2[] = "<>@.,;:";
- static const char tspecials[] = "/?=<>@,;:\\[]\"()";
- static const char tspecials2[] = "/?=<>@.,;:";
- static struct
- {
- const unsigned char *name;
- size_t namelen;
- } tspecial_header[] = {
- { "Content-Type", 12},
- { "Content-Transfer-Encoding", 25},
- { NULL, 0}
- };
- const char *delimiters;
- const char *delimiters2;
- const unsigned char *line, *s, *s2;
- size_t n;
- int i, invalid = 0;
- TOKEN t, tok, *tok_tail;
-
- errno = 0;
- if (!hdr)
- return NULL;
-
- tok = NULL;
- tok_tail = &tok;
-
- line = hdr->line;
- if (!(s = strchr (line, ':')))
- return NULL; /* oops */
-
- n = s - line;
- if (!n)
- return NULL; /* oops: invalid name */
-
- delimiters = specials;
- delimiters2 = specials2;
- for (i = 0; tspecial_header[i].name; i++)
- {
- if (n == tspecial_header[i].namelen
- && !memcmp (line, tspecial_header[i].name, n))
- {
- delimiters = tspecials;
- delimiters2 = tspecials2;
- break;
- }
- }
-
- s++; /* Move over the colon. */
- for (;;)
- {
- if (!*s)
- {
- if (!hdr->next || !hdr->next->cont)
- break;
- hdr = hdr->next;
- s = hdr->line;
- }
-
- if (*s == '(')
- {
- int level = 1;
- int in_quote = 0;
-
- invalid = 0;
- for (s++;; s++)
- {
- if (!*s)
- {
- if (!hdr->next || !hdr->next->cont)
- break;
- hdr = hdr->next;
- s = hdr->line;
- }
-
- if (in_quote)
- {
- if (*s == '\"')
- in_quote = 0;
- else if (*s == '\\' && s[1]) /* what about continuation? */
- s++;
- }
- else if (*s == ')')
- {
- if (!--level)
- break;
- }
- else if (*s == '(')
- level++;
- else if (*s == '\"')
- in_quote = 1;
- }
- if (!*s)
- ; /* Actually this is an error, but we don't care about it. */
- else
- s++;
- }
- else if (*s == '\"' || *s == '[')
- {
- /* We do not check for non-allowed nesting of domainliterals */
- int term = *s == '\"' ? '\"' : ']';
- invalid = 0;
- s++;
- t = NULL;
-
- for (;;)
- {
- for (s2 = s; *s2; s2++)
- {
- if (*s2 == term)
- break;
- else if (*s2 == '\\' && s2[1]) /* what about continuation? */
- s2++;
- }
-
- t = (t
- ? append_to_token (t, s, s2 - s)
- : new_token (term == '\"'? tQUOTED : tDOMAINLIT, s, s2 - s));
- if (!t)
- goto failure;
-
- if (*s2 || !hdr->next || !hdr->next->cont)
- break;
- hdr = hdr->next;
- s = hdr->line;
- }
- *tok_tail = t;
- tok_tail = &t->next;
- s = s2;
- if (*s)
- s++; /* skip the delimiter */
- }
- else if ((s2 = strchr (delimiters2, *s)))
- { /* Special characters which are not handled above. */
- invalid = 0;
- t = new_token (tSPECIAL, s, 1);
- if (!t)
- goto failure;
- *tok_tail = t;
- tok_tail = &t->next;
- s++;
- }
- else if (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n')
- {
- invalid = 0;
- s = skip_ws (s + 1);
- }
- else if (*s > 0x20 && !(*s & 128))
- { /* Atom. */
- invalid = 0;
- for (s2 = s + 1; *s2 > 0x20
- && !(*s2 & 128) && !strchr (delimiters, *s2); s2++)
- ;
- t = new_token (tATOM, s, s2 - s);
- if (!t)
- goto failure;
- *tok_tail = t;
- tok_tail = &t->next;
- s = s2;
- }
- else
- { /* Invalid character. */
- if (!invalid)
- { /* For parsing we assume only one space. */
- t = new_token (tSPACE, NULL, 0);
- if (!t)
- goto failure;
- *tok_tail = t;
- tok_tail = &t->next;
- invalid = 1;
- }
- s++;
- }
- }
-
- return tok;
-
- failure:
- {
- int save = errno;
- release_token_list (tok);
- errno = save;
- }
- return NULL;
-}
-
-
-
-
-/****************
- * Find and parse a header field.
- * WHICH indicates what to do if there are multiple instance of the same
- * field (like "Received"); the following value are defined:
- * -1 := Take the last occurence
- * 0 := Reserved
- * n := Take the n-th one.
- * Returns a handle for further operations on the parse context of the field
- * or NULL if the field was not found.
- */
-rfc822parse_field_t
-rfc822parse_parse_field (rfc822parse_t msg, const char *name, int which)
-{
- HDR_LINE hdr;
-
- if (!which)
- return NULL;
-
- hdr = find_header (msg, name, which, NULL);
- if (!hdr)
- return NULL;
- return parse_field (hdr);
-}
-
-void
-rfc822parse_release_field (rfc822parse_field_t ctx)
-{
- if (ctx)
- release_token_list (ctx);
-}
-
-
-
-/****************
- * Check whether T points to a parameter.
- * A parameter starts with a semicolon and it is assumed that t
- * points to exactly this one.
- */
-static int
-is_parameter (TOKEN t)
-{
- t = t->next;
- if (!t || t->type != tATOM)
- return 0;
- t = t->next;
- if (!t || !(t->type == tSPECIAL && t->data[0] == '='))
- return 0;
- t = t->next;
- if (!t)
- return 1; /* We assume that an non existing value is an empty one. */
- return t->type == tQUOTED || t->type == tATOM;
-}
-
-/*
- Some header (Content-type) have a special syntax where attribute=value
- pairs are used after a leading semicolon. The parse_field code
- knows about these fields and changes the parsing to the one defined
- in RFC2045.
- Returns a pointer to the value which is valid as long as the
- parse context is valid; NULL is returned in case that attr is not
- defined in the header, a missing value is reppresented by an empty string.
-
- With LOWER_VALUE set to true, a matching field valuebe be
- lowercased.
-
- Note, that ATTR should be lowercase.
- */
-const char *
-rfc822parse_query_parameter (rfc822parse_field_t ctx, const char *attr,
- int lower_value)
-{
- TOKEN t, a;
-
- for (t = ctx; t; t = t->next)
- {
- /* skip to the next semicolon */
- for (; t && !(t->type == tSPECIAL && t->data[0] == ';'); t = t->next)
- ;
- if (!t)
- return NULL;
- if (is_parameter (t))
- { /* Look closer. */
- a = t->next; /* We know that this is an atom */
- if ( !a->flags.lowered )
- {
- lowercase_string (a->data);
- a->flags.lowered = 1;
- }
- if (!strcmp (a->data, attr))
- { /* found */
- t = a->next->next;
- /* Either T is now an atom, a quoted string or NULL in
- * which case we return an empty string. */
-
- if ( lower_value && t && !t->flags.lowered )
- {
- lowercase_string (t->data);
- t->flags.lowered = 1;
- }
- return t ? t->data : "";
- }
- }
- }
- return NULL;
-}
-
-/****************
- * This function may be used for the Content-Type header to figure out
- * the media type and subtype. Note, that the returned strings are
- * guaranteed to be lowercase as required by MIME.
- *
- * Returns: a pointer to the media type and if subtype is not NULL,
- * a pointer to the subtype.
- */
-const char *
-rfc822parse_query_media_type (rfc822parse_field_t ctx, const char **subtype)
-{
- TOKEN t = ctx;
- const char *type;
-
- if (t->type != tATOM)
- return NULL;
- if (!t->flags.lowered)
- {
- lowercase_string (t->data);
- t->flags.lowered = 1;
- }
- type = t->data;
- t = t->next;
- if (!t || t->type != tSPECIAL || t->data[0] != '/')
- return NULL;
- t = t->next;
- if (!t || t->type != tATOM)
- return NULL;
-
- if (subtype)
- {
- if (!t->flags.lowered)
- {
- lowercase_string (t->data);
- t->flags.lowered = 1;
- }
- *subtype = t->data;
- }
- return type;
-}
-
-
-
-
-
-#ifdef TESTING
-
-/* Internal debug function to print the structure of the message. */
-static void
-dump_structure (rfc822parse_t msg, part_t part, int indent)
-{
- if (!part)
- {
- printf ("*** Structure of this message:\n");
- part = msg->parts;
- }
-
- for (; part; part = part->right)
- {
- rfc822parse_field_t ctx;
- part_t save_part; /* ugly hack - we should have a function to
- get part inforation. */
- const char *s;
-
- save_part = msg->current_part;
- msg->current_part = part;
- ctx = rfc822parse_parse_field (msg, "Content-Type", -1);
- msg->current_part = save_part;
- if (ctx)
- {
- const char *s1, *s2;
- s1 = rfc822parse_query_media_type (ctx, &s2);
- if (s1)
- printf ("*** %*s %s/%s", indent*2, "", s1, s2);
- else
- printf ("*** %*s [not found]", indent*2, "");
-
- s = rfc822parse_query_parameter (ctx, "boundary", 0);
- if (s)
- printf (" (boundary=\"%s\")", s);
- rfc822parse_release_field (ctx);
- }
- else
- printf ("*** %*s text/plain [assumed]", indent*2, "");
- putchar('\n');
-
- if (part->down)
- dump_structure (msg, part->down, indent + 1);
- }
-
-}
-
-
-
-static void
-show_param (rfc822parse_field_t ctx, const char *name)
-{
- const char *s;
-
- if (!ctx)
- return;
- s = rfc822parse_query_parameter (ctx, name, 0);
- if (s)
- printf ("*** %s: `%s'\n", name, s);
-}
-
-
-
-static void
-show_event (rfc822parse_event_t event)
-{
- const char *s;
-
- switch (event)
- {
- case RFC822PARSE_OPEN: s= "Open"; break;
- case RFC822PARSE_CLOSE: s= "Close"; break;
- case RFC822PARSE_CANCEL: s= "Cancel"; break;
- case RFC822PARSE_T2BODY: s= "T2Body"; break;
- case RFC822PARSE_FINISH: s= "Finish"; break;
- case RFC822PARSE_RCVD_SEEN: s= "Rcvd_Seen"; break;
- case RFC822PARSE_BOUNDARY: s= "Boundary"; break;
- case RFC822PARSE_LAST_BOUNDARY: s= "Last_Boundary"; break;
- default: s= "***invalid event***"; break;
- }
- printf ("*** got RFC822 event %s\n", s);
-}
-
-static int
-msg_cb (void *dummy_arg, rfc822parse_event_t event, rfc822parse_t msg)
-{
- show_event (event);
- if (event == RFC822PARSE_T2BODY)
- {
- rfc822parse_field_t ctx;
- void *ectx;
- const char *line;
-
- for (ectx=NULL; (line = rfc822parse_enum_header_lines (msg, &ectx)); )
- {
- printf ("*** HDR: %s\n", line);
- }
- rfc822parse_enum_header_lines (NULL, &ectx); /* Close enumerator. */
-
- ctx = rfc822parse_parse_field (msg, "Content-Type", -1);
- if (ctx)
- {
- const char *s1, *s2;
- s1 = rfc822parse_query_media_type (ctx, &s2);
- if (s1)
- printf ("*** media: `%s/%s'\n", s1, s2);
- else
- printf ("*** media: [not found]\n");
- show_param (ctx, "boundary");
- show_param (ctx, "protocol");
- rfc822parse_release_field (ctx);
- }
- else
- printf ("*** media: text/plain [assumed]\n");
-
- }
-
-
- return 0;
-}
-
-
-
-int
-main (int argc, char **argv)
-{
- char line[5000];
- size_t length;
- rfc822parse_t msg;
-
- msg = rfc822parse_open (msg_cb, NULL);
- if (!msg)
- abort ();
-
- while (fgets (line, sizeof (line), stdin))
- {
- length = strlen (line);
- if (length && line[length - 1] == '\n')
- line[--length] = 0;
- if (length && line[length - 1] == '\r')
- line[--length] = 0;
- if (rfc822parse_insert (msg, line, length))
- abort ();
- }
-
- dump_structure (msg, NULL, 0);
-
- rfc822parse_close (msg);
- return 0;
-}
-#endif
-
-/*
-Local Variables:
-compile-command: "gcc -Wall -g -DTESTING -o rfc822parse rfc822parse.c"
-End:
-*/
diff --git a/tools/rfc822parse.h b/tools/rfc822parse.h
deleted file mode 100644
index 1293117ac..000000000
--- a/tools/rfc822parse.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* rfc822parse.h - Simple mail and MIME parser
- * Copyright (C) 1999 Werner Koch, Duesseldorf
- * Copyright (C) 2003, g10 Code GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifndef RFC822PARSE_H
-#define RFC822PARSE_H
-
-struct rfc822parse_context;
-typedef struct rfc822parse_context *rfc822parse_t;
-
-typedef enum
- {
- RFC822PARSE_OPEN = 1,
- RFC822PARSE_CLOSE,
- RFC822PARSE_CANCEL,
- RFC822PARSE_T2BODY,
- RFC822PARSE_FINISH,
- RFC822PARSE_RCVD_SEEN,
- RFC822PARSE_LEVEL_DOWN,
- RFC822PARSE_LEVEL_UP,
- RFC822PARSE_BOUNDARY,
- RFC822PARSE_LAST_BOUNDARY,
- RFC822PARSE_BEGIN_HEADER,
- RFC822PARSE_PREAMBLE,
- RFC822PARSE_EPILOGUE
- }
-rfc822parse_event_t;
-
-struct rfc822parse_field_context;
-typedef struct rfc822parse_field_context *rfc822parse_field_t;
-
-
-typedef int (*rfc822parse_cb_t) (void *opaque,
- rfc822parse_event_t event,
- rfc822parse_t msg);
-
-
-rfc822parse_t rfc822parse_open (rfc822parse_cb_t cb, void *opaque_value);
-
-void rfc822parse_close (rfc822parse_t msg);
-
-void rfc822parse_cancel (rfc822parse_t msg);
-int rfc822parse_finish (rfc822parse_t msg);
-
-int rfc822parse_insert (rfc822parse_t msg,
- const unsigned char *line, size_t length);
-
-char *rfc822parse_get_field (rfc822parse_t msg, const char *name, int which);
-
-const char *rfc822parse_enum_header_lines (rfc822parse_t msg, void **context);
-
-rfc822parse_field_t rfc822parse_parse_field (rfc822parse_t msg,
- const char *name,
- int which);
-
-void rfc822parse_release_field (rfc822parse_field_t field);
-
-const char *rfc822parse_query_parameter (rfc822parse_field_t ctx,
- const char *attr, int lower_value);
-
-const char *rfc822parse_query_media_type (rfc822parse_field_t ctx,
- const char **subtype);
-
-#endif /*RFC822PARSE_H */
diff --git a/tools/watchgnupg.c b/tools/watchgnupg.c
deleted file mode 100644
index 7f79f2f18..000000000
--- a/tools/watchgnupg.c
+++ /dev/null
@@ -1,389 +0,0 @@
-/* watchgnupg.c - Socket server for GnuPG logs
- * Copyright (C) 2003, 2004 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <fcntl.h>
-#include <time.h>
-
-#define PGM "watchgnupg"
-
-/* Allow for a standalone build. */
-#ifdef VERSION
-#define MYVERSION_LINE PGM " (GnuPG) " VERSION
-#define BUGREPORT_LINE "\nReport bugs to <[email protected]>.\n"
-#else
-#define MYVERSION_LINE PGM
-#define BUGREPORT_LINE ""
-#endif
-
-static int verbose;
-
-
-static void
-die (const char *format, ...)
-{
- va_list arg_ptr;
-
- fflush (stdout);
- fprintf (stderr, "%s: ", PGM);
-
- va_start (arg_ptr, format);
- vfprintf (stderr, format, arg_ptr);
- va_end (arg_ptr);
- putc ('\n', stderr);
-
- exit (1);
-}
-
-
-/* static void */
-/* err (const char *format, ...) */
-/* { */
-/* va_list arg_ptr; */
-
-/* fflush (stdout); */
-/* fprintf (stderr, "%s: ", PGM); */
-
-/* va_start (arg_ptr, format); */
-/* vfprintf (stderr, format, arg_ptr); */
-/* va_end (arg_ptr); */
-/* putc ('\n', stderr); */
-/* } */
-
-static void *
-xmalloc (size_t n)
-{
- void *p = malloc (n);
- if (!p)
- die ("out of core");
- return p;
-}
-
-static void *
-xcalloc (size_t n, size_t m)
-{
- void *p = calloc (n, m);
- if (!p)
- die ("out of core");
- return p;
-}
-
-static void *
-xrealloc (void *old, size_t n)
-{
- void *p = realloc (old, n);
- if (!p)
- die ("out of core");
- return p;
-}
-
-
-struct client_s {
- struct client_s *next;
- int fd;
- size_t size; /* Allocated size of buffer. */
- size_t len; /* Current length of buffer. */
- unsigned char *buffer; /* Buffer to with data already read. */
-
-};
-typedef struct client_s *client_t;
-
-
-
-static void
-print_fd_and_time (int fd)
-{
- struct tm *tp;
- time_t atime = time (NULL);
-
- tp = localtime (&atime);
- printf ("%3d - %04d-%02d-%02d %02d:%02d:%02d ",
- fd,
- 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
- tp->tm_hour, tp->tm_min, tp->tm_sec );
-}
-
-
-/* Print LINE for the client identified by C. Calling this function
- witgh LINE set to NULL, will flush the internal buffer. */
-static void
-print_line (client_t c, const char *line)
-{
- const char *s;
- size_t n;
-
- if (!line)
- {
- if (c->buffer && c->len)
- {
- print_fd_and_time (c->fd);
- fwrite (c->buffer, c->len, 1, stdout);
- putc ('\n', stdout);
- c->len = 0;
- }
- return;
- }
-
- while ((s = strchr (line, '\n')))
- {
- print_fd_and_time (c->fd);
- if (c->buffer && c->len)
- {
- fwrite (c->buffer, c->len, 1, stdout);
- c->len = 0;
- }
- fwrite (line, s - line + 1, 1, stdout);
- line = s + 1;
- }
- n = strlen (line);
- if (n)
- {
- if (c->len + n >= c->size)
- {
- c->size += ((n + 255) & ~255);
- c->buffer = (c->buffer
- ? xrealloc (c->buffer, c->size)
- : xmalloc (c->size));
- }
- memcpy (c->buffer + c->len, line, n);
- c->len += n;
- }
-}
-
-
-static void
-print_version (int with_help)
-{
- fputs (MYVERSION_LINE "\n"
- "Copyright (C) 2004 Free Software Foundation, Inc.\n"
- "This program comes with ABSOLUTELY NO WARRANTY.\n"
- "This is free software, and you are welcome to redistribute it\n"
- "under certain conditions. See the file COPYING for details.\n",
- stdout);
-
- if (with_help)
- fputs ("\n"
- "Usage: " PGM " [OPTIONS] SOCKETNAME\n"
- "Open the local socket SOCKETNAME and display log messages\n"
- "\n"
- " --force delete an already existing socket file\n"
- " --verbose enable extra informational output\n"
- " --version print version of the program and exit\n"
- " --help display this help and exit\n"
- BUGREPORT_LINE, stdout );
-
- exit (0);
-}
-
-int
-main (int argc, char **argv)
-{
- int last_argc = -1;
- int force = 0;
-
- struct sockaddr_un srvr_addr;
- int addrlen;
- int server;
- int flags;
- client_t client_list = NULL;
-
- if (argc)
- {
- argc--; argv++;
- }
- while (argc && last_argc != argc )
- {
- last_argc = argc;
- if (!strcmp (*argv, "--"))
- {
- argc--; argv++;
- break;
- }
- else if (!strcmp (*argv, "--version"))
- print_version (0);
- else if (!strcmp (*argv, "--help"))
- print_version (1);
- else if (!strcmp (*argv, "--verbose"))
- {
- verbose = 1;
- argc--; argv++;
- }
- else if (!strcmp (*argv, "--force"))
- {
- force = 1;
- argc--; argv++;
- }
- }
-
- if (argc != 1)
- {
- fprintf (stderr, "usage: " PGM " socketname\n");
- exit (1);
- }
-
-
- if (verbose)
- fprintf (stderr, "opening socket `%s'\n", *argv);
-
- setvbuf (stdout, NULL, _IOLBF, 0);
-
- server = socket (PF_LOCAL, SOCK_STREAM, 0);
- if (server == -1)
- die ("socket() failed: %s\n", strerror (errno));
-
- /* We better set the listening socket to non-blocking so that we
- don't get bitten by race conditions in accept. The should not
- happen for Unix Domain sockets but well, shit happens. */
- flags = fcntl (server, F_GETFL, 0);
- if (flags == -1)
- die ("fcntl (F_GETFL) failed: %s\n", strerror (errno));
- if ( fcntl (server, F_SETFL, (flags | O_NONBLOCK)) == -1)
- die ("fcntl (F_SETFL) failed: %s\n", strerror (errno));
-
-
- memset (&srvr_addr, 0, sizeof srvr_addr);
- srvr_addr.sun_family = AF_LOCAL;
- strncpy (srvr_addr.sun_path, *argv, sizeof (srvr_addr.sun_path) - 1);
- srvr_addr.sun_path[sizeof (srvr_addr.sun_path) - 1] = 0;
- addrlen = (offsetof (struct sockaddr_un, sun_path)
- + strlen (srvr_addr.sun_path) + 1);
-
-
- again:
- if (bind (server, (struct sockaddr *) &srvr_addr, addrlen))
- {
- if (errno == EADDRINUSE && force)
- {
- force = 0;
- remove (srvr_addr.sun_path);
- goto again;
- }
- die ("bind to `%s' failed: %s\n", *argv, strerror (errno));
- }
-
- if (listen (server, 5))
- die ("listen failed: %s\n", strerror (errno));
-
- for (;;)
- {
- fd_set rfds;
- int max_fd;
- client_t client;
-
- /* Usually we don't have that many connections, thus it is okay
- to set them allways from scratch and don't maintain an active
- fd_set. */
- FD_ZERO (&rfds);
- FD_SET (server, &rfds);
- max_fd = server;
- for (client = client_list; client; client = client->next)
- if (client->fd != -1)
- {
- FD_SET (client->fd, &rfds);
- if (client->fd > max_fd)
- max_fd = client->fd;
- }
-
- if (select (max_fd + 1, &rfds, NULL, NULL, NULL) <= 0)
- continue; /* Ignore any errors. */
-
- if (FD_ISSET (server, &rfds)) /* New connection. */
- {
- struct sockaddr_un clnt_addr;
- int fd;
-
- addrlen = sizeof clnt_addr;
- fd = accept (server, (struct sockaddr *) &clnt_addr, &addrlen);
- if (fd == -1)
- {
- printf ("[accepting connection failed: %s]\n", strerror (errno));
- }
- else if (fd >= FD_SETSIZE)
- {
- close (fd);
- printf ("[connection request denied: too many connections]\n");
- }
- else
- {
- for (client = client_list; client && client->fd != -1;
- client = client->next)
- ;
- if (!client)
- {
- client = xcalloc (1, sizeof *client);
- client->next = client_list;
- client_list = client;
- }
- client->fd = fd;
- printf ("[client at fd %d connected]\n", client->fd);
- }
- }
- for (client = client_list; client; client = client->next)
- if (client->fd != -1 && FD_ISSET (client->fd, &rfds))
- {
- char line[256];
- int n;
-
- n = read (client->fd, line, sizeof line - 1);
- if (n == 1)
- {
- int save_errno = errno;
- print_line (client, NULL); /* flush */
- printf ("[client at fd %d read error: %s]\n",
- client->fd, strerror (save_errno));
- close (client->fd);
- client->fd = -1;
- }
- else if (!n)
- {
- print_line (client, NULL); /* flush */
- close (client->fd);
- printf ("[client at fd %d disconnected]\n", client->fd);
- client->fd = -1;
- }
- else
- {
- line[n] = 0;
- print_line (client, line);
- }
- }
- }
-
- return 0;
-}
-
-
-/*
-Local Variables:
-compile-command: "gcc -Wall -g -o watchgnupg watchgnupg.c"
-End:
-*/