aboutsummaryrefslogtreecommitdiffstats
path: root/util
diff options
context:
space:
mode:
Diffstat (limited to 'util')
-rw-r--r--util/ChangeLog1695
-rw-r--r--util/Makefile.am73
-rw-r--r--util/argparse.c1004
-rw-r--r--util/assuan-buffer.c485
-rw-r--r--util/assuan-client.c282
-rw-r--r--util/assuan-connect.c96
-rw-r--r--util/assuan-defs.h244
-rw-r--r--util/assuan-errors.c105
-rw-r--r--util/assuan-logging.c116
-rw-r--r--util/assuan-socket-connect.c191
-rw-r--r--util/assuan-socket.c97
-rw-r--r--util/assuan-util.c171
-rw-r--r--util/cert.c251
-rw-r--r--util/dotlock.c454
-rw-r--r--util/errors.c116
-rw-r--r--util/fileutil.c297
-rw-r--r--util/http.c1076
-rw-r--r--util/iobuf.c2276
-rw-r--r--util/isascii.c30
-rw-r--r--util/logger.c265
-rw-r--r--util/membuf.c84
-rw-r--r--util/memory.c647
-rw-r--r--util/memrchr.c49
-rw-r--r--util/miscutil.c480
-rw-r--r--util/mkdtemp.c99
-rw-r--r--util/pka.c254
-rw-r--r--util/regcomp.c3495
-rw-r--r--util/regex.c62
-rw-r--r--util/regex_internal.c1229
-rw-r--r--util/regex_internal.h643
-rw-r--r--util/regexec.c3225
-rw-r--r--util/riscos.c436
-rw-r--r--util/secmem.c499
-rw-r--r--util/simple-gettext.c467
-rw-r--r--util/srv.c257
-rw-r--r--util/srv.h51
-rw-r--r--util/strgutil.c1373
-rw-r--r--util/timegm.c68
-rw-r--r--util/ttyio.c629
-rw-r--r--util/w32reg.c181
40 files changed, 0 insertions, 23552 deletions
diff --git a/util/ChangeLog b/util/ChangeLog
deleted file mode 100644
index 426d4d3c9..000000000
--- a/util/ChangeLog
+++ /dev/null
@@ -1,1695 +0,0 @@
-2006-07-31 Werner Koch <[email protected]>
-
- * iobuf.c (iobuf_ioctl, fd_cache_invalidate): Allow closing all
- open files.
-
-2006-07-29 Marcus Brinkmann <[email protected]>
-
- * secmem.c (init_pool): Close FD after establishing the mapping.
-
-2006-07-20 David Shaw <[email protected]>
-
- * http.c (send_request): A zero-length proxy is the same as no
- proxy at all. Suggested by J. Scott Berg.
-
-2006-04-17 David Shaw <[email protected]>
-
- * miscutil.c (make_printable_string): Fix bug where some control
- characters lose part of their ASCII representation.
-
-2006-04-11 David Shaw <[email protected]>
-
- * memory.c (realloc): Revert m_guard fix and stick an #error in
- there to inform people not to use it.
-
-2006-04-11 Werner Koch <[email protected]>
-
- * iobuf.c (IOBUF_BUFFER_SIZE): New to replace hardwired 8192.
-
-2006-04-06 David Shaw <[email protected]>
-
- * memory.c (realloc): Fix compile problem with --enable-m-guard.
-
-2006-03-30 David Shaw <[email protected]>
-
- * cert.c (main): Fix test program build warning on OSX.
-
-2006-03-16 David Shaw <[email protected]>
-
- * cert.c (get_cert): Handle the fixed IPGP type with fingerprint.
-
-2006-03-08 David Shaw <[email protected]>
-
- * argparse.c (default_strusage): Update copyright year to 2006.
-
-2006-02-19 David Shaw <[email protected]>
-
- * http.c (send_request): A zero length proxy is the same as no
- proxy.
-
-2006-02-14 Werner Koch <[email protected]>
-
- * errors.c (g10_errstr): Add NO_DATA.
-
-2006-01-26 David Shaw <[email protected]>
-
- * cert.c (get_cert): Disable IPGP types for now until the format
- questions in the draft are settled.
-
- * srv.c (getsrv): Error on oversize SRV responses.
-
-2005-12-24 David Shaw <[email protected]>
-
- * cert.c (get_cert): Properly chase down CNAMEs pointing to CERTs.
-
-2005-12-23 David Shaw <[email protected]>
-
- * cert.c, Makefile.am: New code to do DNS CERT queries.
-
-2005-12-22 David Shaw <[email protected]>
-
- * srv.c, Makefile.am: Only build srv.c if we need to.
-
-2005-12-10 Ryan Lortie <[email protected]> (dshaw)
-
- * ttyio.c (tty_enable_completion, tty_disable_completion): Add
- checks for no_terminal so we don't try to open("/dev/tty") when
- invoked with --no-tty.
-
-2005-12-06 David Shaw <[email protected]>
-
- * Makefile.am: Some cleanup so we don't build files that are
- completely ifdeffed out. This causes a warning on Sun's cc. Do
- the internal regex code as well for consistency.
-
- * mkdtemp.c (mkdtemp): Fix warning.
-
- * secmem.c, assuan-buffer.c, dotlock.c: Fix a few warnings from
- printf-ing %p where the arg wasn't void *.
-
-2005-11-02 David Shaw <[email protected]>
-
- * util.c [!HAVE_DECL_GETPAGESIZE]: Prototype getpagesize() if
- unistd.h doesn't have it (for MinGW).
-
-2005-09-22 Werner Koch <[email protected]>
-
- * iobuf.c (iobuf_get_filelength): New arg OVERFLOW.
- (iobuf_get_filelength) [W32]: Use GetFileSizeEx if available.
- * fileutil.c (is_file_compressed): Take care of the OVERFLOW
-
-2005-08-31 David Shaw <[email protected]>
-
- * fileutil.c (untilde): New. Expand ~/foo and ~username/foo
- filenames into full paths using $HOME if possible, or
- getpwuid/getpwnam if necessary.
- (make_filename): Use it here.
-
-2005-07-28 Werner Koch <[email protected]>
-
- * pka.c: New.
- (parse_txt_record): Changed from v=1 to v=pka1.
-
- * Makefile.am (pka-test): new.
-
-2005-07-27 Werner Koch <[email protected]>
-
- * memory.c (FNAMEX, FNAMEXM): New macros to cope with the now used
- names xmalloc style names.
-
-2005-07-18 Werner Koch <[email protected]>
-
- * ttyio.c (do_get): Move printing of the prompt after disabling
- echo. Suggested by Scott Worley.
-
-2005-06-23 David Shaw <[email protected]>
-
- * http.c (make_radix64_string): Add '=' padding as per standard.
- (send_request, http_open, http_open_document): Clean up auth code.
- Can now support different auth for a proxy and the file being
- requested via that proxy. Unescape auth strings.
-
-2005-06-22 David Shaw <[email protected]>
-
- * memrchr.c (memrchr): Not all compilers allow initializing based
- on a variable that is also being initialized. Noted by Nelson
- H. F. Beebe.
-
-2005-06-21 David Shaw <[email protected]>
-
- * http.c (send_request, http_open, http_open_document): Pass in
- auth and proxyauth that can override the in-url auth.
-
- * http.c (send_request): Need == after the radix64-encoded basic
- auth string.
-
-2005-06-08 David Shaw <[email protected]>
-
- * dotlock.c [HAVE_DOSISH_SYSTEM]: Fix unused function warnings on
- mingw32. Noted by Joe Vender.
-
-2005-05-31 Werner Koch <[email protected]>
-
- * regcomp.c (MB_CUR_MAX) [_WIN32]: Define it only if not defined.
-
-2005-05-29 David Shaw <[email protected]>
-
- * strgutil.c (set_native_charset) [_WIN32]: Add alias for codepage
- CP65001 to utf-8.
-
-2005-05-19 Werner Koch <[email protected]>
-
- * membuf.c: New. Taken from gnupg 1.9.
-
-2005-05-05 David Shaw <[email protected]>
-
- * miscutil.c (add_days_to_timestamp): Remove as unused.
-
-2005-04-12 David Shaw <[email protected]>
-
- * assuan-client.c: Fix warning on OSX.
-
- * memrchr.c: New replacement function.
-
- * assuan-buffer.c: Use it here.
-
-2005-04-04 Werner Koch <[email protected]>
-
- * memory.c (xcalloc, xcalloc_secure): New wrappers.
-
- * assuan-client.c (assuan_transact): Factored all code out to ..
- (assuan_transact2): .. new. Add arg OKAY_CB. Wipe the memory
- processed though that callback.
-
-2005-03-31 Werner Koch <[email protected]>
-
- * isascii.c: New. This is an autoconf replacement function.
-
- * Makefile.am (assuan_source): New. Only used when agent support
- has been requested.
- * assuan-buffer.c, assuan-client.c, assuan-defs.h,
- * assuan-errors.c, assuan-logging.c, assuan-socket-connect.c,
- * assuan-socket.c, assuan-util.c, assuan-connect.c: New. Taken
- from libassuan 0.6.9 and adjusted for our limited use of Assuan.
-
-2005-03-18 David Shaw <[email protected]>
-
- * ttyio.c (tty_enable_completion, tty_disable_completion): Enable
- and disable readline completion.
- (init_ttyfp): Completion is disabled by default.
-
-2005-03-14 Werner Koch <[email protected]>
-
- * miscutil.c (isotimestamp): New.
-
-2005-03-10 Werner Koch <[email protected]>
-
- * secmem.c (secmem_realloc): Take control information into account
- when checking whether a resize is needed.
-
-2005-03-08 Werner Koch <[email protected]>
-
- * miscutil.c (asctimestamp) [W32]: Don't use %Z.
-
-2005-02-03 Werner Koch <[email protected]>
-
- * w32reg.c (read_w32_registry_string): Fallback to HKLM also for a
- missing name.
-
- * http.c (connect_server): Define ERR outside of the !W32 block.
-
-2005-02-01 David Shaw <[email protected]>
-
- * http.c (connect_server): Fix fd leak when connecting to a
- round-robin server set that has some down servers. Noted by Phil
- Pennock.
-
-2005-01-20 Werner Koch <[email protected]>
-
- * simple-gettext.c (set_gettext_file): Use MO files depending on
- the installation directory. Add new arg REGKEY.
-
-2005-01-18 Werner Koch <[email protected]>
-
- * argparse.c (default_strusage): Changed default copyright year to
- 2005.
-
- * strgutil.c (handle_iconv_error): Print error messages only once.
- (native_to_utf8, utf8_to_native): Ditto.
-
-2005-01-11 Werner Koch <[email protected]>
-
- * strgutil.c (set_native_charset) [W32]: Use the alias table from
- libiconv 1.9.2.
-
-2005-01-13 David Shaw <[email protected]>
-
- * http.c (connect_server): Use INADDR_NONE instead of
- SOCKET_ERROR. Noted by Timo.
-
-2005-01-06 Werner Koch <[email protected]>
-
- * strgutil.c (set_native_charset): Assume that ASCII,
- ANSI_X3.4-1968 and 646 are actually meant as Latin-1. If
- nl_langinfo is not available get the charset from environment
- variables. For W32 use GetACP as error fallback. Removed Latin-15
- to Latin-1 aliasing.
-
-2004-12-28 David Shaw <[email protected]>
-
- * srv.h: Better implementation for the SRV check. We don't need
- to actually check all the header files individually since the SRV
- test compile uses them together.
-
-2004-12-20 Werner Koch <[email protected]>
-
- * strgutil.c (handle_iconv_error): Turn diagnostics into warnings
- so that gpg does not return with failure.
- (native_to_utf8, utf8_to_native): Ditto.
-
-2004-12-16 Werner Koch <[email protected]>
-
- * iobuf.c (fd_cache_strcmp) [W32]: Casting is a Bad Thing. Cast to
- an unsigned char pointer and to an unsigned integer.
-
-2004-12-18 David Shaw <[email protected]>
-
- * ttyio.c: Use only HAVE_LIBREADLINE to detect readline
- availability.
-
-2004-12-16 David Shaw <[email protected]>
-
- * srv.h: Don't include arpa/nameser.h unless we have it. Include
- "types.h" for u16.
-
- * secmem.c (secmem_init): Return a flag to indicate whether we got
- the lock.
-
-2004-12-06 Werner Koch <[email protected]>
-
- * iobuf.c (fd_cache_strcmp): New. Use whenever we compare
- filenames for the fd_cache. This is needed because the backslash
- is an alias for a slash under W32. Reported by Tobias Winkler.
-
-2004-12-03 David Shaw <[email protected]>
-
- * http.c (send_request): Include the port if non-80 in the Host:
- header. Noted by Jason Harris.
-
-2004-11-03 Timo Schulz <[email protected]>
-
- * strgutil.c (w32_strerror): New.
- * ttyio.c (init_ttyfp, tty_printf, do_get): Use it here.
- * iobuf.c (fd_cache_open, file_filter): Likewise.
- (iobuf_seek, translate_file_handle): Likewise.
-
-2004-11-02 Werner Koch <[email protected]>
-
- * strgutil.c (load_libiconv): Use log_info to avoid failures when
- iconv.dll is not installed.
-
-2004-10-31 Werner Koch <[email protected]>
-
- * simple-gettext.c (get_string): Removed debugging hack.
-
-2004-10-27 Werner Koch <[email protected]>
-
- * simple-gettext.c: Removed windows.h.
- (get_string): On the fly translation from utf-8 to active
- character set.
-
- * strgutil.c (load_libiconv) [_WIN32]: new.
- (set_native_charset) [_WIN32]: Call it here and autodetect the
- used code page.
- (native_to_utf8, utf8_to_native): Reverted arguments for
- iconv_open.
- (handle_iconv_error): Made this function match iconv_open argumnet
- ordering.
- (utf8_to_native): Disable all quoting for DELIM == -1.
-
-2004-10-26 Werner Koch <[email protected]>
-
- * strgutil.c (mem2str): Translated comment to English.
- (handle_iconv_error) [USE_GNUPG_ICONV]: New.
- (set_native_charset) [USE_GNUPG_ICONV]: Added iconv based
- conversion checks.
- (native_to_utf8, utf8_to_native): Added iconv based conversion.
-
-2004-10-21 Werner Koch <[email protected]>
-
- * vasprintf.c: Removed. It was used only at one place and I don't
- want to get into build problems in 1.4.
-
-2004-10-18 David Shaw <[email protected]>
-
- * http.c (connect_server, send_request): Use the URI scheme as the
- SRV tag rather than hard-coding _hkp.
-
-2004-10-16 David Shaw <[email protected]>
-
- * http.c (connect_server): [_WIN32] actually fill in the sin_addr
- so we aren't always talking to localhost. Add some general sanity
- checking of parameters learned from gethostbyname().
-
-2004-10-15 Werner Koch <[email protected]>
-
- * vasprintf.c: New. Taken from gnupg 1.9.
-
-2004-10-14 Werner Koch <[email protected]>
-
- * iobuf.c (iobuf_get_fd): Removed double check on directfp and
- cats it to FILEP becuase directfp is actually a void *. Notes by
- Stefan.
-
-2004-10-13 Werner Koch <[email protected]>
-
- * logger.c (g10_log_error_f, g10_log_fatal_f, g10_log_info_f)
- (g10_log_debug_f, print_prefix_f): Removed.
-
- * iobuf.c (iobuf_is_pipe_filename): New.
- (iobuf_get_fd): New.
-
- * fileutil.c (is_file_compressed): Use it here.
-
-2004-09-30 David Shaw <[email protected]>
-
- * iobuf.c (pop_filter): Make static.
-
- * dotlock.c (destroy_dotlock): New. Remove the handle from the
- list of locks.
- (release_dotlock): Don't act if we don't have any locks at all.
- From Werner on stable branch.
-
-2004-09-10 David Shaw <[email protected]>
-
- * http.c (make_radix64_string, do_parse_uri, send_request): Add
- basic auth for proxies and direct requests. Suggested by Florent
- Thoumie.
-
- * http.c (main): Fix test code for http-test.
-
-2004-09-09 Werner Koch <[email protected]>
-
- * errors.c (g10_errstr): New error codes G10ERR_NO_CARD,
- G10ERR_CANCELED.
-
- * ttyio.c (tty_get): Add readline support.
-
- * iobuf.c (iobuf_skip_rest): New. Orginal patch by Florian
- Weimer. Added new argument PARTIAL.
-
-2004-08-19 David Shaw <[email protected]>
-
- * http.c (insert_escapes): Fix encoding problem for non-URI-safe
- characters. Noted by Vladimir Novak.
-
-2004-05-21 David Shaw <[email protected]>
-
- * timegm.c: New replacement function. Removes the need for
- setenv.c and unsetenv.c.
-
- * setenv.c: Removed.
-
- * unsetenv.c: Removed.
-
-2004-03-04 David Shaw <[email protected]>
-
- * iobuf.c (block_filter): Remove the old gpg indeterminate length
- mode.
- (iobuf_set_block_mode, iobuf_in_block_mode): Removed as
- superfluous.
-
-2004-03-01 David Shaw <[email protected]>
-
- * iobuf.c (block_filter): Properly handle a partial body stream
- that ends with a 5-byte length that happens to be zero.
-
-2004-02-28 David Shaw <[email protected]>
-
- * unsetenv.c: Fixed debugging typo.
-
-2004-02-24 Werner Koch <[email protected]>
-
- * secmem.c (lock_pool) [_AIX]: Also set errno.
-
-2004-02-21 David Shaw <[email protected]>
-
- * miscutil.c (hextobyte): Moved here from g10/misc.c so I can use
- it in the keyserver helpers.
-
-2004-02-20 David Shaw <[email protected]>
-
- * mkdtemp.c: New (moved from g10/), setenv.c: New, unsetenv.c:
- New.
-
- * Makefile.am: Include @LIBOBJS@ for replacement functions.
-
-2004-01-15 David Shaw <[email protected]>
-
- * argparse.c (default_strusage): Update copyright date.
- (initialize): Avoid a number of -Wformat-nonliteral warnings.
- These aren't actual problems, but the warnings bothered me.
-
- * miscutil.c (print_string2): New variation on print_string that
- allows two delimiters.
- (print_string): Call print_string2 to do work.
-
-2003-12-29 David Shaw <[email protected]>
-
- * g10u.c: Dead code. Remove.
-
- * Makefile.am: Don't compile g10u.c.
-
- * iobuf.c (block_filter): Properly handle a partial body stream
- that ends with a 5-byte length.
-
-2003-12-28 David Shaw <[email protected]>
-
- * http.c (send_request, http_open_document, http_open): Pass the
- http proxy from outside rather than pulling it from the
- evironment.
-
-2003-12-28 Stefan Bellon <[email protected]>
-
- * riscos.c [__riscos__]: Better filetype handling (use a
- different SWI) and removal of unnecessary function.
-
- * memory.c (out_of_core) [__riscos__]: Produce stack backtrace on
- RISC OS if out_of_core() is called and M_GUARD is compiled in.
-
-2003-12-06 David Shaw <[email protected]>
-
- * http.c (send_request): Add a Host: header for virtual hosts.
-
-2003-12-04 David Shaw <[email protected]>
-
- * miscutil.c (answer_is_yes_no_default, answer_is_yes_no_quit):
- Don't use alternate strings when not needed so we don't have to
- re-translate them. Hopefully the comment will be enough to
- indicate multiple match strings.
-
-2003-11-20 David Shaw <[email protected]>
-
- * miscutil.c (match_multistr): New. Match against each segment in
- a string with tokens separated by |.
- (answer_is_yes_no_default, answer_is_yes_no_quit,
- answer_is_okay_cancel): Use it here to enable alternate
- translations.
-
-2003-11-01 David Shaw <[email protected]>
-
- * http.c (connect_server): Differentiate between generic "can't
- connect" errors and the more specific "host not found". Suggested
- by Samuel Tardieu.
-
-2003-10-29 Werner Koch <[email protected]>
-
- * miscutil.c (answer_is_okay_cancel): New.
-
-2003-10-25 Werner Koch <[email protected]>
-
- * Makefile.am: Replaced INTLLIBS by LIBINTL.
-
-2003-10-23 Werner Koch <[email protected]>
-
- * secmem.c (lock_pool) [_AIX]: Don't use plock.
-
-2003-10-12 David Shaw <[email protected]>
-
- * srv.c: OSX 10.2.8/Darwin 6.8 seems to have some #include
- ordering issues? Move sys/types.h up higher to work around.
-
-2003-10-08 Werner Koch <[email protected]>
-
- * ttyio.c (tty_print_string, tty_print_utf8_string2)
- (tty_print_utf8_string): Made string arg const.
-
-2003-09-28 Timo Schulz <[email protected]>
-
- * strgutil.c [WIN32] (asprintf): New.
-
-2003-09-28 Werner Koch <[email protected]>
-
- * ttyio.c (tty_fprintf): New.
-
-2003-09-21 Timo Schulz <[email protected]>
-
- * http.c [WIN32]: Define MB_CUR_MAX.
- (connect_server): use unsigned long since W32 does not have in_addr_t.
-
-2003-08-28 David Shaw <[email protected]>
-
- * dotlock.c, http.c, iobuf.c, simple-gettext.c, srv.c, srv.h,
- strgutil.c, ttyio.c, w32reg.c: s/__MINGW32__/_WIN32/ to help
- building on native Windows compilers. Requested by Brian Gladman.
- From Werner on stable branch.
-
- * http.c (connect_server): Oops - forgot to freeaddrinfo().
-
-2003-08-24 David Shaw <[email protected]>
-
- * http.c (connect_server): Try and use getaddrinfo if it is
- available. Try for IPv6 via getaddrinfo() or a IPv6-ized
- gethostbyname(). Suggested by Jun-ichiro itojun Hagino.
-
-2003-07-10 David Shaw <[email protected]> (from Werner on stable branch)
-
- * iobuf.c (check_special_filename): Replaced is isdigit by digitp
- to avoid passing negative values and potential locale problems.
- Problem noted by Christian Biere.
- * strgutil.c (strlwr,strcasecmp,strncasecmp): Make sure we don't
- pass a negative value.
- * miscutil.c (scan_isodatestr): Ditto.
-
-2003-05-30 David Shaw <[email protected]>
-
- * srv.h, srv.c: Include windows.h with MINGW32.
-
-2003-05-24 David Shaw <[email protected]>
-
- * argparse.c, dotlock.c, fileutil.c, iobuf.c, miscutil.c,
- simple-gettext.c, errors.c, http.c, memory.c, secmem.c, ttyio.c:
- Edit all preprocessor instructions to remove whitespace before the
- '#'. This is not required by C89, but there are some compilers
- out there that don't like it.
-
-2003-05-21 Werner Koch <[email protected]>
-
- * fileutil.c (is_file_compressed): Fixed checking for "-" filename.
-
-2003-04-13 David Shaw <[email protected]>
-
- * srv.c (main): Test against wwwkeys.pgp.net.
-
- * srv.h: Grr. The RH7.3 Linux man page defines the fourth arg of
- dn_expand as unsigned char*, but it is really char* according to
- resolv.h.
-
-2003-03-23 David Shaw <[email protected]>
-
- * argparse.c (default_strusage): Change copyright date.
-
-2003-03-14 David Shaw <[email protected]>
-
- * srv.h, srv.c (getsrv): Use unsigned char rather than char.
- Noted by Stefan Bellon.
-
-2003-03-11 David Shaw <[email protected]>
-
- * http.c (connect_server): Use DNS SRV to get a server list. Fail
- over to A records if necessary.
-
- * Makefile.am, srv.h, srv.c: New DNS SRV handling code.
-
-2003-02-22 David Shaw <[email protected]>
-
- * ttyio.c (tty_print_utf8_string, tty_print_utf8_string2): Use 0
- to indicate a string with no maximum size. This prevents early
- truncation of strings that contain control chars which are
- expanded into \xXX form.
-
-2002-12-26 David Shaw <[email protected]>
-
- * iobuf.c (iobuf_flush): Only print debug info if debugging is on.
-
-2002-11-13 David Shaw <[email protected]>
-
- * secmem.c (lock_pool) [__CYGWIN__]: Don't print secmem warning.
- From Werner on stable branch.
-
-2002-11-09 Werner Koch <[email protected]>
-
- * ttyio.c (TERMDEVICE): Removed.
- (tty_get_ttyname): New.
- (init_ttyfp): Use it here instead of the TERMDEVICE macro.
-
-2002-11-06 David Shaw <[email protected]>
-
- * w32reg.c (read_w32_registry_string): Fixed expanding of the
- environment buffer; didn't worked at all. Reported by Thijmen
- Klok. From Werner on stable branch.
-
- * secmem.c (secmem_free, secmem_term): Use wipememory2() instead
- of memset() to overwrite secure memory
-
- * iobuf.c (direct_open): Handle mode 'b' if O_BINARY is available.
- From Werner on stable branch.
-
- * fileutil.c: Comment from stable branch.
-
-2002-10-31 Stefan Bellon <[email protected]>
-
- * riscos.c (riscos_load_module, riscos_check_regexp): New.
- (riscos_set_filetype_by_mimetype, riscos_dump_fdlist)
- (riscos_fdopenfile, riscos_close_fds, riscos_renamefile)
- (riscos_gstrans, riscos_list_openfiles, riscos_not_implemented):
- Renamed functions to contain riscos prefix.
- * dotlock.c [__riscos__]: Renames due to changes in riscos.c.
- * fileutil.c [__riscos__]: Likewise.
-
-2002-10-29 Stefan Bellon <[email protected]>
-
- * fileutil.c: Removed unnecessary left-over includes for RISC OS.
- (make_filename): Tidied up RISC OS stuff.
- (compare_filenames) [__riscos__]: Compare with ascii_strcasecmp().
- (make_basename) [__riscos__]: Branch to own RISC OS routine from
- here.
-
- * riscos.c (riscos_make_basename): New.
-
-2002-10-28 Stefan Bellon <[email protected]>
-
- * fileutil.c (make_basename) [__riscos__]: Cut off RISC OS' filing
- systems from filepath.
-
- * riscos.c (riscos_get_filetype_from_string, riscos_get_filetype):
- Added.
- (riscos_set_filetype_by_number): Made public.
-
-2002-10-19 David Shaw <[email protected]>
-
- * Makefile.am, regcomp.c, regex.c, regex_internal.c,
- regex_internal.h, regexec.c: Add new regex files from glibc 2.3.1.
-
-2002-10-17 David Shaw <[email protected]>
-
- * http.c (connect_server): Try all A records for names with
- multiple addresses until one answers for both MINGW32 and not
- MINGW32.
-
-2002-10-10 David Shaw <[email protected]>
-
- * http.c (connect_server): Properly handle a single A record that
- fails connect().
-
-2002-10-03 David Shaw <[email protected]>
-
- * logger.c (g10_log_warning, log_set_strict): Add new log_warning
- logger command which can be switched between log_info and
- log_error via log_set_strict.
-
-2002-09-24 David Shaw <[email protected]>
-
- * http.c (connect_server): Try all A records for names with
- multiple addresses until one answers (not MINGW32).
-
-2002-09-16 Werner Koch <[email protected]>
-
- * w32reg.c (read_w32_registry_string): Fallback to HLM.
-
-2002-09-12 Stefan Bellon <[email protected]>
-
- * fileutil.c (make_filename): Removed variable for RISC OS to
- avoid compiler warning.
-
- * secmem.c: Removed static variable for RISC OS to avoid
- compiler warning.
-
-2002-09-11 Werner Koch <[email protected]>
-
- * simple-gettext.c: Disable charset mappings. We do it now when
- installing the files.
-
-2002-09-09 Werner Koch <[email protected]>
-
- * w32reg.c (read_w32_registry_string): Handle REG_EXPAND_SZ.
- Suggested by Ryan Malayter.
-
- * strgutil.c (ascii_strcasecmp): Replaced by code from gnulib.
- (ascii_strncasecmp): New.
-
-2002-09-02 Werner Koch <[email protected]>
-
- * simple-gettext.c (set_gettext_file): Make sure that we only use
- backslashes.
-
- * strgutil.c (set_native_charset): Allow NULL as argument to use
- nl_langinfo for selection. Mapped latin-15 to latin-1.
-
-2002-08-30 Werner Koch <[email protected]>
-
- * iobuf.c (block_filter): Removed the assert, so that one can pass
- the first character of a message and use the block filter for
- non partial length encoded packets.
-
-2002-08-06 Stefan Bellon <[email protected]>
-
- * ttyio.c [__riscos__]: Moved low-level RISC OS stuff to riscos.c.
- * riscos.c: Use new SWI calling mechanism of UnixLib.
-
-2002-08-03 Stefan Bellon <[email protected]>
-
- * secmem.c (init_pool, secmem_term): Changed #if to #ifdef in
- order to avoid warning with RISC OS' Norcroft C.
-
-2002-07-25 David Shaw <[email protected]>
-
- * secmem.c: "Warning" -> "WARNING"
-
-2002-07-05 Werner Koch <[email protected]>
-
- * argparse.c (initialize): We better exit after a read error so
- that we don't run into an endless loop when reading a directory.
- Noted by Andrew Suffield.
-
-2002-07-01 David Shaw <[email protected]>
-
- * argparse.c (optfile_parse): Fix variable typo - 'p2' should be
- 'p' :)
-
-2002-06-29 Werner Koch <[email protected]>
-
- * argparse.c (optfile_parse): Renamed an auto I to P2 to avoid
- shadowing warning.
-
-2002-06-21 Stefan Bellon <[email protected]>
-
- * riscos.c (riscos_global_defaults): New.
-
-2002-06-20 Stefan Bellon <[email protected]>
-
- * riscos.c (riscos_set_filetype_by_number, riscos_set_filetype):
- New. Set RISC OS filetype according to MIME type.
-
-2002-06-14 David Shaw <[email protected]>
-
- * strgutil.c (pop_strlist): New function to pop the head off of a
- strlist.
-
-2002-06-05 Timo Schulz <[email protected]>
-
- * fileutil.c (is_file_compressed): Corrected the magic values
- for bzip2 and gzip. Noted by David.
-
-2002-05-22 Werner Koch <[email protected]>
-
- * fileutil.c (compare_filenames): Replaced stricmp by strcasecmp.
- * miscutil.c (answer_is_yes_no_quit,answer_is_yes_no_default): Ditto.
-
- * strgutil.c (strncasecmp): New.
- (memicmp): Removed.
-
-2002-05-10 Stefan Bellon <[email protected]>
-
- * memory.c (add_entry) [M_DEBUG]: Added some missing EXTRA_ALIGN.
- (free_entry) [M_DEBUG]: Free secure memory via secmem_free.
- (alloc_secure): Malloc at least 1 byte.
- (realloc) [M_GUARD]: Added missing FNAMEARG to function call.
-
- * logger.c (g10_log_bug0) [__riscos__]: Make use of first
- g10_log_bug0 function for later Norcroft compiler.
-
- * riscos.c: Added stdlib.h include.
-
-2002-05-04 Werner Koch <[email protected]>
-
- * http.c (write_server) [__MINGW32__]: Replaced WriteFile by send
- because sockets don't work with WriteFile under NT anymore.
-
-2002-05-03 David Shaw <[email protected]>
-
- * argparse.c (optfile_parse): Remove quotes only if they totally
- enclose the string, and do not occur within the string. This
- makes specifying a program under Win32 easier when you need quotes
- around part of a string, but not around the whole string.
-
-2002-05-02 Werner Koch <[email protected]>
-
- * memory.c (alloc): Malloc at least 1 byte. Noted by Winona Brown.
-
-2002-04-23 David Shaw <[email protected]>
-
- * miscutil.c: New function answer_is_yes_no_default() to give a
- default answer.
-
-2002-04-22 Stefan Bellon <[email protected]>
-
- * riscos.c (riscos_open, riscos_fopen, riscos_fstat, set_filetype):
- Removed as they're not needed anymore.
-
- * iobuf.c (direct_open) [__riscos__]: Don't allow opening of
- directories.
-
-2002-04-08 Werner Koch <[email protected]>
-
- Fixed filename of last entry.
-
-2002-03-29 David Shaw <[email protected]>
-
- * miscutil.c (print_string, utf8_to_native): If a delimiter is
- used, then quote the backslash character as well. Problem noted
- by Rainer Perske.
-
-2002-03-15 Werner Koch <[email protected]>
-
- * argparse.c (optfile_parse): Fixed missing argument handling.
-
-2002-02-28 Timo Schulz <[email protected]>
-
- * http.c (write_server): Convert integer to a HANDLE for W32.
-
-2002-01-27 David Shaw <[email protected]>
-
- * iobuf.c (iobuf_fdopen, iobuf_sockopen): Do not cache fdopened
- fds on close.
-
-2002-01-08 Werner Koch <[email protected]>
-
- * secmem.c (print_warn): Print a pointer to the FAQ.
-
-2002-01-05 Werner Koch <[email protected]>
-
- * argparse.c (default_strusage): Set default copyright date to 2002.
-
-2002-01-02 Stefan Bellon <[email protected]>
-
- * iobuf.c [__riscos__]: Updated include file name.
-
- * fileutil.c [__riscos__]: Ditto.
-
- * ttyio.d [__riscos__]: Ditto.
-
- * riscos.c [__riscos__]: Ditto. Added debugging code and
- unified error messages.
-
-2001-12-27 David Shaw <[email protected]>
-
- * errors.c (g10_errstr): Added G10ERR_KEYSERVER
-
-2001-12-27 Werner Koch <[email protected]>
-
- * simple-gettext.c [MINGW32]: Fixed last changed.
-
-2001-12-22 Stefan Bellon <[email protected]>
-
- * memory.c (realloc): Fixed realloc not working when M_GUARD is
- defined and first parameter is NULL.
-
-2001-12-22 Timo Schulz <[email protected]>
-
- * fileutil.c (is_file_compressed): New.
-
-2001-12-19 Werner Koch <[email protected]>
-
- * simple-gettext.c, w32reg.c [CYGWIN32]: Allow to use this file
-
-2001-10-11 Werner Koch <[email protected]>
-
- * http.c (do_parse_uri): Changed initialization of the port number
- so that it does also work with x-hkp. By David Shaw.
-
-2001-09-19 Werner Koch <[email protected]>
-
- * w32reg.c (get_root_key): New.
- (read_w32_registry_string): Use it here.
- (write_w32_registry_string): New. Contributed by Timo.
-
- * iobuf.c (iobuf_ioctl): New command to disable fd
- caching. Implemented no_cache flag where needed.
- (iobuf_sockopen): Always set no_cache flag.
-
- * strgutil.c (utf8_to_native): Add a delim arg and changed all
- callers. Make sure that quoting is done when translation is
- disabled.
- * miscutil.c (print_utf8_string2): New.
-
-2001-09-17 Werner Koch <[email protected]>
-
- * miscutil.c (print_string): Use explicit ranges and not iscntrl().
- (make_printable_string): Ditto.
-
-2001-09-07 Werner Koch <[email protected]>
-
- * strgutil.c (strsep): New, taken from glibc 2.2.1.
-
-2001-09-03 Werner Koch <[email protected]>
-
- * miscutil.c (strtimestamp,asctimestamp): Avoid trigraphs.
-
-2001-08-21 Stefan Bellon <[email protected]>
-
- * riscos.c [__riscos__] (close_fds): Fixed possible endless loop.
-
-2001-08-20 Werner Koch <[email protected]>
-
- Applied patches from Stefan Bellon <[email protected]> to support
- RISC OS. Nearly all of these patches are identified by the
- __riscos__ macro.
- * secmem.c [__riscos__]: Disabled secure memory stuff.
- * dotlock.c, ttyio.c [__riscos__]: Adapted for RISC OS
- * fileutil.c, iobuf.c: Adapted for RISC OS; mainly replaced
- hardcoded path separators with EXTSEP_S like macros.
- * http.c (send_request): Use macros for the env-var name.
- * logger.c [__riscos__]: Do an fflush at the end of each log
- function.
- * memory.c [__riscos__]: Minor patches
- * riscos.c (set_filetype): New.
-
- * secmem.c (lock_pool): Under HPUX mlock is broken but we might
- have plock, so we use this to lock the entire process. By Albert
- Chin.
-
-2001-07-03 Werner Koch <[email protected]>
-
- * strgutil.c (utf8_to_native): Fixed printing of invalid utf-8
- characters. Thomas Roessler reported that the escaping didn't work
- correct.
-
-2001-06-12 Werner Koch <[email protected]>
-
- * strgutil.c (ascii_memistr,ascii_isupper,ascii_islower,
- ascii_toupper,ascii_tolower, ascii_strcasecmp, ascii_memcasecmp): New.
- (set_native_charset): Use ascii_strcasecmp()
- * fileutil.c (compare_filenames): Ditto
- * miscutil.c (answer_is_yes): Ditto.
- (answer_is_yes_no_quit): Ditto.
-
-2001-06-06 Werner Koch <[email protected]>
-
- * strgutil.c (vasprintf) [__MINGW32__]: New. Taken from libiberty.
- * ttyio.c (tty_printf) [__MINGW32__]: Replaced the sprintf with
- the new vasprintf.
-
-2001-06-05 Werner Koch <[email protected]>
-
- * dotlock.c (make_dotlock): Typo fixes.
-
-2001-05-25 Werner Koch <[email protected]>
-
- * ttyio.c (do_get): Fixed a serious format string bug. Thanks to
- fish stiqz.
-
-2001-05-23 Werner Koch <[email protected]>
-
- * secmem.c (EPERM): Try to work around a Slackware problem.
-
-2001-05-05 Werner Koch <[email protected]>
-
- * http.c (http_start_data): Flush before writing.
- (http_wait_response): No need to flush here.
-
-2001-04-27 Werner Koch <[email protected]>
-
- * memory.c (out_of_core): Print an explanation on reasons why
- secret memory can get exhausted.
-
-2001-04-23 Werner Koch <[email protected]>
-
- * http.c (http_wait_response): Implement new flag to inhibit the
- TCP shutdown.
-
-2001-04-20 Werner Koch <[email protected]>
-
- * http.c (http_start_data): Use write_server and not the iobuf
- stuff. I wonder why we are at all using write_server - shouldn't
- it be handled by iobuf?
-
- * strgutil.c (set_native_charset): Allow utf-8 by introducing the
- new no_translation variable.
- (native_to_utf8): Handle no_translation.
- (utf8_to_native): Ditto.
-
-2001-04-19 Werner Koch <[email protected]>
-
- * miscutil.c (asctimestamp): Handle negative times. We must do
- this because Windoze segvs on negative times passed to gmtime().
- (strtimestamp): Ditto.
-
-2001-04-14 Werner Koch <[email protected]>
-
- * strgutil.c (utf8_to_native): Fixed a segv. Thanks to Keith Clayton.
-
-2001-04-13 Werner Koch <[email protected]>
-
- * iobuf.c (iobuf_fopen): Removed because it is not used and
- furthermore mode is ignored for an fname of "-". Suggested by
- Florian Weimer.
-
-2001-04-02 Werner Koch <[email protected]>
-
- * iobuf.c (translate_file_handle): New. Use this function
- everywhere in this file.
- (iobuf_translate_file_handle): Always use the osfhandle stuff here
- because callers don't know the implementation details of iobuf and
- they expect that the handles are translated.
-
-2001-03-29 Werner Koch <[email protected]>
-
- * miscutil.c (answer_is_yes): An empty string does now return no.
- (answer_is_yes_no_quit): Likewise.
-
- * iobuf.c (iobuf_close): Burn the buffers.
-
-2001-03-26 Werner Koch <[email protected]>
-
- * ttyio.c: Define TERMDEVICE depending on OS.
-
- * http.c (http_start_data): send a CRLF and not just a LF.
- Pointed out by Steven Murdoch.
-
-2001-03-13 Werner Koch <[email protected]>
-
- * iobuf.c (iobuf_sockopen): New.
- (sock_filter) [__MINGW32__]: New.
- (iobuf_ioctl): New.
- (file_filter): Implemented keep_open mode.
- * http.c (http_open, http_wait_response): Replaced iobuf_fdopen by
- iobuf_sockopen and use an iobuf_ioctl to avoid the dup().
- (deinit_sockets, init_sockets) [__MINGW32__]: New.
- (connect_server, write_server): Add code to work with W32 sockets.
-
-2001-03-12 Werner Koch <[email protected]>
-
- * strgutil.c (check_trailing_chars,check_trailing_ws): New.
-
-2001-03-08 Werner Koch <[email protected]>
-
- * argparse.c (default_strusage): Changed year of printed copyright
- to 2001.
-
- * iobuf.c (fd_cache_invalidate, fd_cache_close, fd_cache_open): New.
- (direct_open): Invalidate the fd_cache for read access.
- (file_filter): Cache the close here.
- (iobuf_open): Use new my_fopen_ro macro to try the cache first.
-
-2001-03-07 Werner Koch <[email protected]>
-
- * iobuf.c: Made the old stdio file handling cpp conditional
- controlled by FILE_FILTER_USES_STDIO and added a new
- open/read/close based one. We don't need the stdio buffering
- becuase we are doing our own buffering anyway. And it is a
- prerequesite to allow the use of ReadFile et al for W32 which in
- turn is needed to make the http stuff work there. The new W32
- stuff has also been implemented. Minor changes to all open functions.
- (direct_open): New.
- (file_filter): Core of the new read/write handling.
- (iobuf_get_filelength): Use W32 API function here. But it is
- currently limited to 2GB files.
- (iobuf_seek): Ditto.
-
-2001-03-01 Werner Koch <[email protected]>
-
- * errors.c (g10_errstr): New codes UNU_SECKEY and UNU_PUBKEY.
-
-2000-12-28 Werner Koch <[email protected]>
-
- * dotlock.c: Made all_lockfiles volatile.
- (remove_lockfiles): Made public.
-
-2000-11-30 Werner Koch <[email protected]>
-
- * iobuf.c (iobuf_translate_file_handle): New.
- (iobuf_open, iobuf_create): Use it for special filenames
-
-2000-11-11 Paul Eggert <[email protected]>
-
- * iobuf.c (iobuf_get_filelength): Now returns off_t, not u32.
- Remove kludges to worry about large files; the callers check
- for files that are too large, and they should already be doing
- the right thing in an implementation-independent way.
- (fopen, fstat): Remove macros.
-
- * iobuf.c (iobuf_set_limit, iobuf_tell, iobuf_seek):
- Use off_t, not ulong, for file offsets.
- (<limits.h>): Include if needed.
- (LONG_MAX, LONG_MIN): Define a substitute if needed.
- (fseeko): Define a substitute if needed.
-
- * iobuf.c (iobuf_seek): Do not use %lu to report file
-
-2000-11-09 Werner Koch <[email protected]>
-
- * iobuf.c (iobuf_enable_special_filenames): New.
- (check_special_filename): New.
- (iobuf_open): check for special filenames.
- (iobuf_create): Ditto.
-
-2000-10-23 Werner Koch <[email protected]>
-
- * secmem.c (lock_pool): Don't print warning for Windows.
-
-2000-10-16 Werner Koch <[email protected]>
-
- * secmem.c (lock_pool): Fixed error checking for Linux.
- By James Troup.
-
-Thu Sep 14 14:20:38 CEST 2000 Werner Koch <[email protected]>
-
- * miscutil.c (answer_is_yes_no_quit): Swapped order of yes/no test
- so that no is returned for an empty input. By David Champion.
-
-Wed Sep 6 17:55:47 CEST 2000 Werner Koch <[email protected]>
-
- * iobuf.c: Use fopen64 insead of fopen when available.
- (iobuf_get_filelength): Use fstat64 when available but return
- 2^32-1 if the file is larger than this value.
-
-Wed Sep 6 14:59:09 CEST 2000 Werner Koch <[email protected]>
-
- * secmem.c (secmem_realloc): check for failed secmem_malloc. By
- Matt Kraai.
-
- * strgutil.c (utf8_to_native): Fixed null ptr problem. By
- Giampaolo Tomassoni.
-
-Thu Jul 27 10:02:38 CEST 2000 Werner Koch <[email protected]>
-
- * iobuf.c: Use setmode() at several places to set stdin and stdout
- to binary mode for MSDOS based systems
-
- * iobuf.c (underflow): Initialize dummy_len to keep memory checker happy.
-
-Fri Jun 9 10:09:52 CEST 2000 Werner Koch <[email protected]>
-
- * ttyio.c: Simulate termios with termios. By Dave Dykstra.
-
-Thu Jun 8 20:22:00 CEST 2000 Werner Koch <[email protected]>
-
- * secmem.c (lock_pool,secmem_init): Additional check for dropped privs.
-
-Tue May 30 16:37:55 CEST 2000 Werner Koch <[email protected]>
-
- * iobuf.c (iobuf_cancel): Fix for MSDOS.
-
-Fri Apr 14 19:37:08 CEST 2000 Werner Koch <[email protected]>
-
- * dotlock.c (disable_dotlock): New. Implmented this in the module.
-
-2000-03-09 14:04:22 Werner Koch ([email protected])
-
- * argparse.c (default_strusage): Changed year of default copyright.
-
-Tue Mar 7 18:45:31 CET 2000 Werner Koch <[email protected]>
-
- * secmem.c (lock_pool): No more warning for QNX. By Sam Roberts.
-
-2000-03-02 15:51:04 Werner Koch ([email protected])
-
- * ttyio.c (tty_print_utf8_string): Oops.
-
-Thu Mar 2 15:37:46 CET 2000 Werner Koch <[email protected]>
-
- * ttyio.c (tty_print_utf8_string2): New to allow a max output size.
-
-Wed Feb 23 10:07:57 CET 2000 Werner Koch <[email protected]>
-
- * miscutil.c (asctimestamp): Fix for possible buffer overflow by
- large system returned date format string.
-
-Fri Dec 31 14:08:15 CET 1999 Werner Koch <[email protected]>
-
- * logger.c (log_inc_errorcount): New.
-
-Sat Dec 4 12:30:28 CET 1999 Werner Koch <[email protected]>
-
- * iobuf.c (iobuf_cancel): Broadcast the new Cancel mesaage to all
- filters.
-
-Mon Nov 22 11:14:53 CET 1999 Werner Koch <[email protected]>
-
- * strgutil.c (strcasecmp): New.
-
- * secmem.c (pool_is_mmapped): Made volatile.
-
-Sat Oct 9 20:34:41 CEST 1999 Werner Koch <[email protected]>
-
- * Makefile.am: Removed libtool.
-
-Fri Oct 8 20:32:01 CEST 1999 Werner Koch <[email protected]>
-
- * w32reg.c: New.
- * simple-gettext.c: Use the Registry to locate the mo file.
-
- * http.c (send_request): Add support for proxys; suggested by
- Walter Hofmann.
- (http_open_document): Pass flags to http_open.
-
-Fri Sep 17 12:56:42 CEST 1999 Werner Koch <[email protected]>
-
-
- * secmem.c (lock_pool): Check for ENOSYS return my mlock() on
- old SCOs.
-
- * ttyio.c (do_get): Replaced #if __MINGW32__ by #ifdef becuase
- gcc 2.95.1 assigns a floating point value (0.2) to this macro,
- which in turn can't be used in an expression.
-
-Wed Sep 15 16:22:17 CEST 1999 Werner Koch <[email protected]>
-
-
- * simple-gettext.c: New.
-
-Wed Sep 1 15:30:44 CEST 1999 Werner Koch <[email protected]>
-
-
- * argparse.c (arg_parse): Add standard options to the dump-options
- output.
-
-Tue Aug 31 17:20:44 CEST 1999 Werner Koch <[email protected]>
-
-
- * strgutil (utf8_to_native): Implemented.
- (check_utf8_string): Removed.
-
- * miscutil.c (make_printable_string): Fixed possible buffer overflow.
- (print_utf8_string): New.
-
- * ttyio.c (tty_print_utf8_string): New.
-
-Mon Aug 30 20:38:33 CEST 1999 Werner Koch <[email protected]>
-
-
- * secmem.c (pool_okay): declared volatile.
-
- * miscutil.c (answer_is_yes): Always check for plain "yes".
- (answer_is_yes_no_quit): Likewise.
-
- * dotlock.c (create_dotlock): Fixed segv during cleanup.
-
-Mon Jul 12 14:55:34 CEST 1999 Werner Koch <[email protected]>
-
-
- * argparse.c (initialize): Init ret_xxx.
- (optfile_parse): Remove quotes from arguments.
-
-Wed Jul 7 13:08:40 CEST 1999 Werner Koch <[email protected]>
-
-
- * memory.c (membug): Use if either M_DEBUG or M_GUARD is used.
-
- * miscutil.c (scan_isodatestr): New.
-
- * logger.c (g10_log_mpidump): Moved to ../mpi/mpicoder.c
- (g10_log_print_prefix): Renamed from print_prefix and made global.
-
- * Makefile.am: Support for libtool.
-
-Thu Jul 1 12:47:31 CEST 1999 Werner Koch <[email protected]>
-
-
- * miscutil.c (make_printable_string): New.
-
- * strgutil.c (add_to_strlist2,append_to_strlist2): New.
-
-Tue Jun 29 21:44:25 CEST 1999 Werner Koch <[email protected]>
-
-
- * secmem.c (USE_CAPABILITIES): Capabilities support (Remi).
-
-Sat Jun 26 12:15:59 CEST 1999 Werner Koch <[email protected]>
-
-
- * dotlock.c (create_dotlock): s/uts/utsbuf/ cause there an Amdahl
- system with the name UTS (Dave Dykstra).
-
- * secmem.c (DEFAULT_POOLSIZE): Doubled the size.
-
-Fri Jun 18 00:18:02 CEST 1999 Michael Roth <[email protected]>
-
- * iobuf.c: file_filter() Detection of EOF on terminals
- improved/fixed (see Bug #21).
-
-Mon Jun 14 21:18:54 CEST 1999 Michael Roth <[email protected]>
-
- * ttyio.c: tty_no_terminal() new.
-
-Sat Jun 5 15:30:33 CEST 1999 Werner Koch <[email protected]>
-
- * strgutil.c (set_native_charset): Support Latin-2
-
-Tue Jun 1 16:01:46 CEST 1999 Werner Koch <[email protected]>
-
- * iobuf.c (iobuf_get_real_fname): Made global and now keep a
- copy of the name in the iobuf struct.
-
-Mon May 31 19:41:10 CEST 1999 Werner Koch <[email protected]>
-
- * iobuf.c (file_filter,block_filter): Speed patches (R�mi).
-
-Thu May 27 09:40:55 CEST 1999 Werner Koch <[email protected]>
-
- * miscutil.c (answer_is_yes_no_quit): New.
-
-Sun May 23 14:20:22 CEST 1999 Werner Koch <[email protected]>
-
- * dotlock.c: Tweaked to make it compile under mingw32
- * http.c: Disabled for mingw32.
-
-Sat May 22 22:47:26 CEST 1999 Werner Koch <[email protected]>
-
- * logger.c (log_set_logfile): New.
-
-Thu May 20 14:04:08 CEST 1999 Werner Koch <[email protected]>
-
- * memory.c (membug): Nanu, there was a const instead of a static.
-
- * strgutil.c (trim_trailing_chars): New.
-
-Mon May 17 21:54:43 CEST 1999 Werner Koch <[email protected]>
-
- * logger.c (g10_log_hexdump): Made 2nd arg a const.
-
-Wed Apr 28 13:03:03 CEST 1999 Werner Koch <[email protected]>
-
- * miscutil.c (asctimestamp): Use nl_langinfo (Ga�l Qu�ri).
-
-Sun Apr 18 10:11:28 CEST 1999 Werner Koch <[email protected]>
-
- * argparse.c (store_alias): Disabled becuase it is not used.
-
- * ttyio.c (tty_batchmode): New
-
-Sat Mar 20 11:44:21 CET 1999 Werner Koch <[email protected]>
-
- * http.c: Swapped to includes.
-
-Tue Mar 2 16:44:57 CET 1999 Werner Koch <[email protected]>
-
- * strgutil.c (get_native_charset): New.
-
-Fri Feb 26 17:55:41 CET 1999 Werner Koch <[email protected]>
-
- * secmem.c (memblock_struct): Force align (R�mi Guyomarch)
-
-Wed Feb 24 11:07:27 CET 1999 Werner Koch <[email protected]>
-
- * iobuf.c (block_filter): Fixed the oscillating partial packet chunks.
-
-Fri Feb 19 15:49:15 CET 1999 Werner Koch <[email protected]>
-
- * iobuf.c (iobuf_push_filter2): New to allow transer of context
- ownership to the iobuf. Released the context where needed.
-
-Tue Feb 16 14:10:02 CET 1999 Werner Koch <[email protected]>
-
- * strgutil.c (add_to_strglist): Clear the new flags field
- (append_to_strglist): Ditto.
-
- * dotlock.c (read_lockfile): terminate pidstr (Michael).
-
-Wed Feb 10 17:15:39 CET 1999 Werner Koch <[email protected]>
-
- * dotlock.c (remove_lockfiles): Add cleanup function.
- (make_dotlock): Add deadlock check.
-
- * secmem.c (secmem_malloc): Changed error message.
-
-Wed Jan 20 21:40:21 CET 1999 Werner Koch <[email protected]>
-
- * http.c (http_wait_response): Moved the shutdown behind the dup
-
-Wed Jan 20 18:59:49 CET 1999 Werner Koch <[email protected]>
-
- * http.c (send_request): Removed double LF
-
-Tue Jan 19 19:34:58 CET 1999 Werner Koch <[email protected]>
-
- * * iobuf.c (iobuf_push_filter): Allow filters for temp streams
-
- (iobuf_write_temp): Ditto.
- (iobuf_flush_temp): New.
- (iobuf_unget_and_close_temp): Removed.
-
- * http.c (close_http_document): Renamed to http_close().
- (open_http_document): Renamed to http_open_document().
- (http_open): New.
- (http_start_data): New.
- (http_wait_response): New.
-
-
-Sun Jan 17 11:04:33 CET 1999 Werner Koch <[email protected]>
-
- * strgutil.c (trim_trailing_ws): New.
-
-Sat Jan 16 12:03:27 CET 1999 Werner Koch <[email protected]>
-
- * http.c (connect_server): Fixed stupid bug.
-
-Sat Jan 16 09:27:30 CET 1999 Werner Koch <[email protected]>
-
- * http.c: New
-
-
-Wed Jan 13 14:10:15 CET 1999 Werner Koch <[email protected]>
-
- * iobuf.c (iobuf_fdopen): New.
-
-Sat Jan 9 16:02:23 CET 1999 Werner Koch <[email protected]>
-
- * secmem.c (lock_pool): add another check that setuid() worked.
- (secmem_init): Ditto.
-
-Thu Jan 7 18:00:58 CET 1999 Werner Koch <[email protected]>
-
- * iobuf.c (iobuf_clear_eof): Removed.
- (underflow): Changed the eof handling.
- (iobuf_pop_filter): Made static and renamed to pop_filter.
-
- * iobuf.c (iobuf_read_line): New.
-
-Sun Jan 3 15:28:44 CET 1999 Werner Koch <[email protected]>
-
- * dotlock.c (make_dotlock): print another informal message.
-
- (make_dotlock): Removed the cpp checks.
-
-
-Tue Dec 29 14:41:47 CET 1998 Werner Koch <[email protected]>
-
- * secmem.c: Moved unistd.h out of the #ifdef
-
- * dotlock.c (make_dotlock): Sun has no SYS_NMLN
-
- * iobuf.c (iobuf_unget_and_close_temp): Reset .start
-
-Sat Dec 12 18:40:32 CET 1998 Werner Koch <[email protected]>
-
- * argparse.c (arg_pars): fixed opts[i] with negative index.
-
-Fri Nov 27 21:37:41 CET 1998 Werner Koch <[email protected]>
-
- * dotlock.c: Implemented
-
-Wed Nov 25 11:30:07 1998 Werner Koch ([email protected])
-
- * iobuf.c (iobuf_pop_filter): Fixed sigsegv after error.
-
-Thu Nov 19 07:09:55 1998 Werner Koch <[email protected]>
-
- * miscutil.c (strtimevalue): New.
-
-Tue Nov 10 10:01:53 1998 Werner Koch ([email protected])
-
- * strgutil.c (set_native_charset): New.
- (native_to_utf8): Now handles koi8-r.
-
-Tue Nov 3 16:17:56 1998 Werner Koch ([email protected])
-
- * strgutil.c (native_to_utf8): New.
- (utf8_to_native): New, but only as a stub.
-
- * argparse.c (optfile_parse): Trimmed spaces from args.
-
-
-Wed Oct 28 08:01:49 1998 me,,, (wk@tobold)
-
- * argparse.c (find_long_option): New.
- (arg_parse): option=value is now allowed. Add a new internal
- option "--dump-options".
-
-Thu Oct 22 16:25:49 1998 Michael Roth ([email protected])
-
- * fileutil.c (make_basename): New.
- (make_dirname): New.
-
-Wed Oct 21 12:20:29 1998 Werner Koch ([email protected])
-
- * util.c (iobuf_flush): autoincreasing of a temp. iobuf
- (iobuf_temp_with_content): New.
-
-Tue Oct 13 12:40:13 1998 Werner Koch ([email protected])
-
- * util.c (.nofast): set this variable
-
-Wed Oct 7 19:27:50 1998 Werner Koch ([email protected])
-
- * memory.c (m_print_stats): New.
-
-Tue Oct 6 09:53:56 1998 Werner Koch ([email protected])
-
- * strgutil.c (memicmp): Add HAVE_MEMICMP.
-
-Mon Sep 21 19:45:01 1998 Werner Koch (wk@(none))
-
- * secmem.c: New flags to allow suspend/resume of warnings.
-
-Fri Sep 18 16:25:47 1998 Werner Koch (wk@(none))
-
- * secmem.c (lock_pool): Kludge for broken mlock on HPUX 10.20
-
-Tue Sep 15 17:52:21 1998 Werner Koch (wk@(none))
-
- * miscutil.c (asctimestamp): New.
-
-Mon Sep 14 09:38:18 1998 Werner Koch (wk@(none))
-
- * secmem.c (init_pool): Now mmaps /dev/zero if we do not have MAP_ANON.
-
-Wed Sep 9 13:52:28 1998 Werner Koch (wk@(none))
-
- * ttyio.c (do_get): Ctrl-D is now a valid but special character
-
-Mon Sep 7 13:52:41 1998 Werner Koch (wk@(none))
-
- * iobuf.c (get_real_fname): New and changed file_filter datastructures
- and their initialization.
-
-Tue Aug 11 15:12:35 1998 Werner Koch (wk@(none))
-
- * miscutil.c (answer_is_yes): i18ned
-
-Sat Aug 8 18:35:00 1998 Werner Koch (wk@(none))
-
- * ttyio.c (cleanup): New.
-
-Mon Aug 3 17:06:00 1998 Werner Koch (wk@(none))
-
- * secmem.c (MAP_ANON): Add a macro test
-
-Wed Jul 29 14:53:34 1998 Werner Koch (wk@(none))
-
- * ttyio.c (tty_get_answer_is_yes): New.
-
-Tue Jul 21 10:35:48 1998 Werner Koch (wk@(none))
-
- * argparse.c: New option flag to distinguish options and commands.
-
-Sat Jul 18 19:49:30 1998 Werner Koch (wk@(none))
-
- * argparse.c (arg_parse): Added -? as alias for -h
-
-Thu Jul 9 14:47:20 1998 Werner Koch ([email protected])
-
- * secmem.c (secmem_init): Drops setuid if called with 0.
-
-Tue Jul 7 11:49:25 1998 Werner Koch ([email protected])
-
- * logger.c (log_set_filename): New.
-
-Mon Jul 6 09:03:49 1998 Werner Koch ([email protected])
-
- * strgutil.c (append_to_strlist): New.
-
-Thu Jul 2 15:55:44 1998 Werner Koch ([email protected])
-
- * iobuf.c (block_filter): Add writing of OP partial length headers.
-
-Fri Jun 26 10:38:35 1998 Werner Koch ([email protected])
-
- * ttyio.c (do_get): all iso8859-1 characters are now allowed.
-
-Thu Jun 25 15:57:21 1998 Werner Koch ([email protected])
-
- * secmem.c (lock_pool): Removed left over test code.
-
-Wed Jun 10 07:39:41 1998 Werner Koch,mobil,,, (wk@tobold)
-
- * fileutil.c (compare_filenames): New.
-
- * argparse.c (arg_parse): New flag bit 6 to ignore --version
-
-Thu May 14 16:45:13 1998 Werner Koch ([email protected])
-
- * argparse.c (show_help): Add some formatting stuff
-
-Fri May 8 17:06:49 1998 Werner Koch ([email protected])
-
- * errors.c (strerror): New if !HAVE_STRERROR
-
-Mon May 4 19:48:03 1998 Werner Koch ([email protected])
-
- * iobuf.c (iobuf_read): Code is now faster.
- * (iobuf_write): ditto.
-
-Mon Apr 27 11:01:32 1998 Werner Koch ([email protected])
-
- * strgutil.c (memicmp): New.
-
-Thu Mar 19 11:29:03 1998 Werner Koch ([email protected])
-
- * strgutil.c (memistr): Add const to return and first arg.
-
-Sat Mar 7 11:54:35 1998 Werner Koch ([email protected])
-
- * miscutil.c (print_string): New arg delim; changed all callers.
-
-Thu Mar 5 12:19:30 1998 Werner Koch ([email protected])
-
- * errors.c: New strings.
-
-Thu Mar 5 12:06:31 1998 Werner Koch ([email protected])
-
- * iobuf.c (iobuf_open): A name of "-" now opens stdin.
- * fileutil.c (print_fname_stdout, print_fname_stdin): New.
-
-Fri Feb 27 10:20:03 1998 Werner Koch ([email protected])
-
- * memory.c (m_is_secure): Removed.
- * secmem.c (m_is_secure): Moved to here.
-
- * secmem.c (secmem_realloc): New.
- * memory.c (M_GUARD,EXTRA_ALIGN): New (all functions).
-
-Thu Feb 26 14:36:51 1998 Werner Koch ([email protected])
-
- * secmem.c (lock_pool): No error if EAGAIN is returned instead
- of EPERM.
-
-Fri Feb 20 17:43:05 1998 Werner Koch ([email protected])
-
- * ttyio.c [MINGW32]: Add support for mingw32.
-
-Tue Feb 17 19:43:44 1998 Werner Koch ([email protected])
-
- * memory.c (dump_table_at_exit): New.
-
-Mon Feb 16 10:07:28 1998 Werner Koch ([email protected])
-
- * argparse.c (show_version, show_help, default_strusage): Changed
- according to GNU standards.
-
-Mon Feb 16 08:58:25 1998 Werner Koch ([email protected])
-
- * iobuf.c (iobuf_peek): New
-
-Fri Feb 13 19:34:59 1998 Werner Koch ([email protected])
-
- * iobuf.c (iobuf_seek): Set counters to new offset.
-
-Fri Feb 13 17:13:04 1998 Werner Koch ([email protected])
-
- * logger.c (log_set_name, log_get_name): New.
- (print_prefix, pgm_name): New, changed all function to make use it.
- (log_mpidump): Removed the "DBG" prefix.
- (log_hexdump): Ditto.
-
- * logger.c (printstr): Removed.
-
-Fri Feb 13 15:14:13 1998 Werner Koch ([email protected])
-
- * argparse.c (show_help): New '\v' kludge.
-
-
-
- Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005 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/util/Makefile.am b/util/Makefile.am
deleted file mode 100644
index 48457c29f..000000000
--- a/util/Makefile.am
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright (C) 1998, 1999, 2000, 2001, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-
-## Process this file with automake to produce Makefile.in
-
-INCLUDES = -I.. -I$(top_srcdir)/include -I$(top_srcdir)/intl
-
-noinst_LIBRARIES = libutil.a
-
-libutil_a_SOURCES = logger.c fileutil.c miscutil.c strgutil.c \
- ttyio.c argparse.c memory.c secmem.c errors.c iobuf.c \
- dotlock.c http.c pka.c membuf.c cert.c
-
-if USE_SIMPLE_GETTEXT
-libutil_a_SOURCES+=simple-gettext.c
-endif
-
-if HAVE_W32_SYSTEM
-libutil_a_SOURCES+=w32reg.c
-endif
-
-if ENABLE_AGENT_SUPPORT
-libutil_a_SOURCES+=assuan-buffer.c assuan-client.c assuan-defs.h \
- assuan-errors.c assuan-logging.c assuan-socket-connect.c \
- assuan-connect.c assuan-socket.c assuan-util.c
-endif
-
-if USE_INTERNAL_REGEX
-libutil_a_SOURCES+=regex.c
-endif
-
-if USE_DNS_SRV
-libutil_a_SOURCES+=srv.c srv.h
-endif
-
-# The internal regex code #includes these.
-EXTRA_libutil_a_SOURCES = regcomp.c regexec.c regex_internal.c \
- regex_internal.h
-
-# LIBOBJS is for the replacement functions
-libutil_a_DEPENDENCIES = @LIBOBJS@
-libutil_a_LIBADD = @LIBOBJS@
-
-http-test: http.c
- cc -DHAVE_CONFIG_H -I. -I. -I.. $(INCLUDES) $(LDFLAGS) -g -Wall \
- -DTEST -o http-test http.c libutil.a @LIBINTL@ @DNSLIBS@ @CAPLIBS@
-
-srv-test: srv.c
- cc -DHAVE_CONFIG_H -I. -I. -I.. $(INCLUDES) $(LDFLAGS) -g -Wall \
- -DTEST -o srv-test srv.c libutil.a @LIBINTL@ @DNSLIBS@ @CAPLIBS@
-
-pka-test: pka.c
- cc -DHAVE_CONFIG_H -I. -I. -I.. $(INCLUDES) $(LDFLAGS) -g -Wall \
- -DTEST -o pka-test pka.c libutil.a @LIBINTL@ @DNSLIBS@ @CAPLIBS@
-
-cert-test: cert.c
- cc -DHAVE_CONFIG_H -I. -I. -I.. $(INCLUDES) $(LDFLAGS) -g -Wall \
- -DTEST -o cert-test cert.c libutil.a @LIBINTL@ @DNSLIBS@ @CAPLIBS@
diff --git a/util/argparse.c b/util/argparse.c
deleted file mode 100644
index cdc56bf3a..000000000
--- a/util/argparse.c
+++ /dev/null
@@ -1,1004 +0,0 @@
-/* [argparse.c wk 17.06.97] Argument Parser for option handling
- * Copyright (C) 1998, 1999, 2000, 2001, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- *
- *
- * Note: This is an independent version of the one in WkLib
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-
-#include "util.h"
-#include "i18n.h"
-
-
-/*********************************
- * @Summary arg_parse
- * #include <wk/lib.h>
- *
- * typedef struct {
- * char *argc; pointer to argc (value subject to change)
- * char ***argv; pointer to argv (value subject to change)
- * unsigned flags; Global flags (DO NOT CHANGE)
- * int err; print error about last option
- * 1 = warning, 2 = abort
- * int r_opt; return option
- * int r_type; type of return value (0 = no argument found)
- * union {
- * int ret_int;
- * long ret_long
- * ulong ret_ulong;
- * char *ret_str;
- * } r; Return values
- * struct {
- * int idx;
- * const char *last;
- * void *aliases;
- * } internal; DO NOT CHANGE
- * } ARGPARSE_ARGS;
- *
- * typedef struct {
- * int short_opt;
- * const char *long_opt;
- * unsigned flags;
- * } ARGPARSE_OPTS;
- *
- * int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts );
- *
- * @Description
- * This is my replacement for getopt(). See the example for a typical usage.
- * Global flags are:
- * Bit 0 : Do not remove options form argv
- * Bit 1 : Do not stop at last option but return other args
- * with r_opt set to -1.
- * Bit 2 : Assume options and real args are mixed.
- * Bit 3 : Do not use -- to stop option processing.
- * Bit 4 : Do not skip the first arg.
- * Bit 5 : allow usage of long option with only one dash
- * Bit 6 : ignore --version and --help
- * all other bits must be set to zero, this value is modified by the
- * function, so assume this is write only.
- * Local flags (for each option):
- * Bit 2-0 : 0 = does not take an argument
- * 1 = takes int argument
- * 2 = takes string argument
- * 3 = takes long argument
- * 4 = takes ulong argument
- * Bit 3 : argument is optional (r_type will the be set to 0)
- * Bit 4 : allow 0x etc. prefixed values.
- * Bit 7 : this is a command and not an option
- * You stop the option processing by setting opts to NULL, the function will
- * then return 0.
- * @Return Value
- * Returns the args.r_opt or 0 if ready
- * r_opt may be -2/-7 to indicate an unknown option/command.
- * @See Also
- * ArgExpand
- * @Notes
- * You do not need to process the options 'h', '--help' or '--version'
- * because this function includes standard help processing; but if you
- * specify '-h', '--help' or '--version' you have to do it yourself.
- * The option '--' stops argument processing; if bit 1 is set the function
- * continues to return normal arguments.
- * To process float args or unsigned args you must use a string args and do
- * the conversion yourself.
- * @Example
- *
- * ARGPARSE_OPTS opts[] = {
- * { 'v', "verbose", 0 },
- * { 'd', "debug", 0 },
- * { 'o', "output", 2 },
- * { 'c', "cross-ref", 2|8 },
- * { 'm', "my-option", 1|8 },
- * { 500, "have-no-short-option-for-this-long-option", 0 },
- * {0} };
- * ARGPARSE_ARGS pargs = { &argc, &argv, 0 }
- *
- * while( ArgParse( &pargs, &opts) ) {
- * switch( pargs.r_opt ) {
- * case 'v': opt.verbose++; break;
- * case 'd': opt.debug++; break;
- * case 'o': opt.outfile = pargs.r.ret_str; break;
- * case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
- * case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
- * case 500: opt.a_long_one++; break
- * default : pargs.err = 1; break; -- force warning output --
- * }
- * }
- * if( argc > 1 )
- * log_fatal( "Too many args");
- *
- */
-
-typedef struct alias_def_s *ALIAS_DEF;
-struct alias_def_s {
- ALIAS_DEF next;
- char *name; /* malloced buffer with name, \0, value */
- const char *value; /* ptr into name */
-};
-
-static int set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s);
-static void show_help(ARGPARSE_OPTS *opts, unsigned flags);
-static void show_version(void);
-
-static void
-initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
-{
- if( !(arg->flags & (1<<15)) ) { /* initialize this instance */
- arg->internal.idx = 0;
- arg->internal.last = NULL;
- arg->internal.inarg = 0;
- arg->internal.stopped = 0;
- arg->internal.aliases = NULL;
- arg->internal.cur_alias = NULL;
- arg->err = 0;
- arg->flags |= 1<<15; /* mark initialized */
- if( *arg->argc < 0 )
- log_bug("Invalid argument for ArgParse\n");
- }
-
-
- if( arg->err ) { /* last option was erroneous */
-
- if( filename ) {
- if( arg->r_opt == -6 )
- log_error("%s:%u: argument not expected\n", filename, *lineno );
- else if( arg->r_opt == -5 )
- log_error("%s:%u: read error\n", filename, *lineno );
- else if( arg->r_opt == -4 )
- log_error("%s:%u: keyword too long\n", filename, *lineno );
- else if( arg->r_opt == -3 )
- log_error("%s:%u: missing argument\n", filename, *lineno );
- else if( arg->r_opt == -7 )
- log_error("%s:%u: invalid command\n", filename, *lineno );
- else if( arg->r_opt == -10 )
- log_error("%s:%u: invalid alias definition\n",filename,*lineno);
- else
- log_error("%s:%u: invalid option\n", filename, *lineno );
- }
- else {
- if( arg->r_opt == -3 )
- log_error("Missing argument for option \"%.50s\"\n",
- arg->internal.last? arg->internal.last:"[??]" );
- else if( arg->r_opt == -6 )
- log_error("Option \"%.50s\" does not expect an argument\n",
- arg->internal.last? arg->internal.last:"[??]" );
- else if( arg->r_opt == -7 )
- log_error("Invalid command \"%.50s\"\n",
- arg->internal.last? arg->internal.last:"[??]" );
- else if( arg->r_opt == -8 )
- log_error("Option \"%.50s\" is ambiguous\n",
- arg->internal.last? arg->internal.last:"[??]" );
- else if( arg->r_opt == -9 )
- log_error("Command \"%.50s\" is ambiguous\n",
- arg->internal.last? arg->internal.last:"[??]" );
- else
- log_error("Invalid option \"%.50s\"\n",
- arg->internal.last? arg->internal.last:"[??]" );
- }
- if( arg->err != 1 || arg->r_opt == -5 )
- exit(2);
- arg->err = 0;
- }
-
- /* clearout the return value union */
- arg->r.ret_str = NULL;
- arg->r.ret_long= 0;
-}
-
-
-static void
-store_alias( ARGPARSE_ARGS *arg, char *name, char *value )
-{
- /* TODO: replace this dummy function with a rea one
- * and fix the probelms IRIX has with (ALIAS_DEV)arg..
- * used as lvalue
- */
-#if 0
- ALIAS_DEF a = xmalloc( sizeof *a );
- a->name = name;
- a->value = value;
- a->next = (ALIAS_DEF)arg->internal.aliases;
- (ALIAS_DEF)arg->internal.aliases = a;
-#endif
-}
-
-/****************
- * Get options from a file.
- * Lines starting with '#' are comment lines.
- * Syntax is simply a keyword and the argument.
- * Valid keywords are all keywords from the long_opt list without
- * the leading dashes. The special keywords "help", "warranty" and "version"
- * are not valid here.
- * The special keyword "alias" may be used to store alias definitions,
- * which are later expanded like long options.
- * Caller must free returned strings.
- * If called with FP set to NULL command line args are parse instead.
- *
- * Q: Should we allow the syntax
- * keyword = value
- * and accept for boolean options a value of 1/0, yes/no or true/false?
- * Note: Abbreviation of options is here not allowed.
- */
-int
-optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
- ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
-{
- int state, i, c;
- int idx=0;
- char keyword[100];
- char *buffer = NULL;
- size_t buflen = 0;
- int inverse=0;
- int in_alias=0;
-
- if( !fp ) /* same as arg_parse() in this case */
- return arg_parse( arg, opts );
-
- initialize( arg, filename, lineno );
-
- /* find the next keyword */
- state = i = 0;
- for(;;) {
- c=getc(fp);
- if( c == '\n' || c== EOF ) {
- if( c != EOF )
- ++*lineno;
- if( state == -1 )
- break;
- else if( state == 2 ) {
- keyword[i] = 0;
- for(i=0; opts[i].short_opt; i++ )
- if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
- break;
- idx = i;
- arg->r_opt = opts[idx].short_opt;
- if( inverse ) /* this does not have an effect, hmmm */
- arg->r_opt = -arg->r_opt;
- if( !opts[idx].short_opt ) /* unknown command/option */
- arg->r_opt = (opts[idx].flags & 256)? -7:-2;
- else if( !(opts[idx].flags & 7) ) /* does not take an arg */
- arg->r_type = 0; /* okay */
- else if( (opts[idx].flags & 8) ) /* argument is optional */
- arg->r_type = 0; /* okay */
- else /* required argument */
- arg->r_opt = -3; /* error */
- break;
- }
- else if( state == 3 ) { /* no argument found */
- if( in_alias )
- arg->r_opt = -3; /* error */
- else if( !(opts[idx].flags & 7) ) /* does not take an arg */
- arg->r_type = 0; /* okay */
- else if( (opts[idx].flags & 8) ) /* no optional argument */
- arg->r_type = 0; /* okay */
- else /* no required argument */
- arg->r_opt = -3; /* error */
- break;
- }
- else if( state == 4 ) { /* have an argument */
- if( in_alias ) {
- if( !buffer )
- arg->r_opt = -6;
- else {
- char *p;
-
- buffer[i] = 0;
- p = strpbrk( buffer, " \t" );
- if( p ) {
- *p++ = 0;
- trim_spaces( p );
- }
- if( !p || !*p ) {
- xfree( buffer );
- arg->r_opt = -10;
- }
- else {
- store_alias( arg, buffer, p );
- }
- }
- }
- else if( !(opts[idx].flags & 7) ) /* does not take an arg */
- arg->r_opt = -6; /* error */
- else {
- char *p;
- if( !buffer ) {
- keyword[i] = 0;
- buffer = xstrdup(keyword);
- }
- else
- buffer[i] = 0;
-
- trim_spaces( buffer );
- p = buffer;
- /* remove quotes if they totally enclose the
- string, and do not occur within the string */
- if( *p == '"' && p[strlen(p)-1]=='"') {
- char *p2=p;
-
- while(*(++p2))
- if(*p2=='"')
- break;
-
- if(*p2=='"' && *(p2+1)=='\0') {
- p[strlen(p)-1] = 0;
- p++;
- }
- }
- if( !set_opt_arg(arg, opts[idx].flags, p) )
- xfree(buffer);
- }
- break;
- }
- else if( c == EOF ) {
- if( ferror(fp) )
- arg->r_opt = -5; /* read error */
- else
- arg->r_opt = 0; /* eof */
- break;
- }
- state = 0;
- i = 0;
- }
- else if( state == -1 )
- ; /* skip */
- else if( !state && isspace(c) )
- ; /* skip leading white space */
- else if( !state && c == '#' )
- state = 1; /* start of a comment */
- else if( state == 1 )
- ; /* skip comments */
- else if( state == 2 && isspace(c) ) {
- keyword[i] = 0;
- for(i=0; opts[i].short_opt; i++ )
- if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
- break;
- idx = i;
- arg->r_opt = opts[idx].short_opt;
- if( !opts[idx].short_opt ) {
- if( !strcmp( keyword, "alias" ) ) {
- in_alias = 1;
- state = 3;
- }
- else {
- arg->r_opt = (opts[idx].flags & 256)? -7:-2;
- state = -1; /* skip rest of line and leave */
- }
- }
- else
- state = 3;
- }
- else if( state == 3 ) { /* skip leading spaces of the argument */
- if( !isspace(c) ) {
- i = 0;
- keyword[i++] = c;
- state = 4;
- }
- }
- else if( state == 4 ) { /* collect the argument */
- if( buffer ) {
- if( i < buflen-1 )
- buffer[i++] = c;
- else {
- buflen += 50;
- buffer = xrealloc(buffer, buflen);
- buffer[i++] = c;
- }
- }
- else if( i < DIM(keyword)-1 )
- keyword[i++] = c;
- else {
- buflen = DIM(keyword)+50;
- buffer = xmalloc(buflen);
- memcpy(buffer, keyword, i);
- buffer[i++] = c;
- }
- }
- else if( i >= DIM(keyword)-1 ) {
- arg->r_opt = -4; /* keyword to long */
- state = -1; /* skip rest of line and leave */
- }
- else {
- keyword[i++] = c;
- state = 2;
- }
- }
-
- return arg->r_opt;
-}
-
-
-
-static int
-find_long_option( ARGPARSE_ARGS *arg,
- ARGPARSE_OPTS *opts, const char *keyword )
-{
- int i;
- size_t n;
-
- /* Would be better if we can do a binary search, but it is not
- possible to reorder our option table because we would mess
- up our help strings - What we can do is: Build a nice option
- lookup table wehn this function is first invoked */
- if( !*keyword )
- return -1;
- for(i=0; opts[i].short_opt; i++ )
- if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
- return i;
-#if 0
- {
- ALIAS_DEF a;
- /* see whether it is an alias */
- for( a = args->internal.aliases; a; a = a->next ) {
- if( !strcmp( a->name, keyword) ) {
- /* todo: must parse the alias here */
- args->internal.cur_alias = a;
- return -3; /* alias available */
- }
- }
- }
-#endif
- /* not found, see whether it is an abbreviation */
- /* aliases may not be abbreviated */
- n = strlen( keyword );
- for(i=0; opts[i].short_opt; i++ ) {
- if( opts[i].long_opt && !strncmp( opts[i].long_opt, keyword, n ) ) {
- int j;
- for(j=i+1; opts[j].short_opt; j++ ) {
- if( opts[j].long_opt
- && !strncmp( opts[j].long_opt, keyword, n ) )
- return -2; /* abbreviation is ambiguous */
- }
- return i;
- }
- }
- return -1;
-}
-
-int
-arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
-{
- int idx;
- int argc;
- char **argv;
- char *s, *s2;
- int i;
-
- initialize( arg, NULL, NULL );
- argc = *arg->argc;
- argv = *arg->argv;
- idx = arg->internal.idx;
-
- if( !idx && argc && !(arg->flags & (1<<4)) ) { /* skip the first entry */
- argc--; argv++; idx++;
- }
-
- next_one:
- if( !argc ) { /* no more args */
- arg->r_opt = 0;
- goto leave; /* ready */
- }
-
- s = *argv;
- arg->internal.last = s;
-
- if( arg->internal.stopped && (arg->flags & (1<<1)) ) {
- arg->r_opt = -1; /* not an option but a argument */
- arg->r_type = 2;
- arg->r.ret_str = s;
- argc--; argv++; idx++; /* set to next one */
- }
- else if( arg->internal.stopped ) { /* ready */
- arg->r_opt = 0;
- goto leave;
- }
- else if( *s == '-' && s[1] == '-' ) { /* long option */
- char *argpos;
-
- arg->internal.inarg = 0;
- if( !s[2] && !(arg->flags & (1<<3)) ) { /* stop option processing */
- arg->internal.stopped = 1;
- argc--; argv++; idx++;
- goto next_one;
- }
-
- argpos = strchr( s+2, '=' );
- if( argpos )
- *argpos = 0;
- i = find_long_option( arg, opts, s+2 );
- if( argpos )
- *argpos = '=';
-
- if( i < 0 && !strcmp( "help", s+2) ) {
- if( !(arg->flags & (1<<6)) ) {
- show_help(opts, arg->flags);
- }
- }
- else if( i < 0 && !strcmp( "version", s+2) ) {
- if( !(arg->flags & (1<<6)) ) {
- show_version();
- exit(0);
- }
- }
- else if( i < 0 && !strcmp( "warranty", s+2) ) {
- puts( strusage(16) );
- exit(0);
- }
- else if( i < 0 && !strcmp( "dump-options", s+2) ) {
- for(i=0; opts[i].short_opt; i++ ) {
- if( opts[i].long_opt )
- printf( "--%s\n", opts[i].long_opt );
- }
- fputs("--dump-options\n--help\n--version\n--warranty\n", stdout );
- exit(0);
- }
-
- if( i == -2 ) /* ambiguous option */
- arg->r_opt = -8;
- else if( i == -1 ) {
- arg->r_opt = -2;
- arg->r.ret_str = s+2;
- }
- else
- arg->r_opt = opts[i].short_opt;
- if( i < 0 )
- ;
- else if( (opts[i].flags & 7) ) {
- if( argpos ) {
- s2 = argpos+1;
- if( !*s2 )
- s2 = NULL;
- }
- else
- s2 = argv[1];
- if( !s2 && (opts[i].flags & 8) ) { /* no argument but it is okay*/
- arg->r_type = 0; /* because it is optional */
- }
- else if( !s2 ) {
- arg->r_opt = -3; /* missing argument */
- }
- else if( !argpos && *s2 == '-' && (opts[i].flags & 8) ) {
- /* the argument is optional and the next seems to be
- * an option. We do not check this possible option
- * but assume no argument */
- arg->r_type = 0;
- }
- else {
- set_opt_arg(arg, opts[i].flags, s2);
- if( !argpos ) {
- argc--; argv++; idx++; /* skip one */
- }
- }
- }
- else { /* does not take an argument */
- if( argpos )
- arg->r_type = -6; /* argument not expected */
- else
- arg->r_type = 0;
- }
- argc--; argv++; idx++; /* set to next one */
- }
- else if( (*s == '-' && s[1]) || arg->internal.inarg ) { /* short option */
- int dash_kludge = 0;
- i = 0;
- if( !arg->internal.inarg ) {
- arg->internal.inarg++;
- if( arg->flags & (1<<5) ) {
- for(i=0; opts[i].short_opt; i++ )
- if( opts[i].long_opt && !strcmp( opts[i].long_opt, s+1)) {
- dash_kludge=1;
- break;
- }
- }
- }
- s += arg->internal.inarg;
-
- if( !dash_kludge ) {
- for(i=0; opts[i].short_opt; i++ )
- if( opts[i].short_opt == *s )
- break;
- }
-
- if( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) ) {
- if( !(arg->flags & (1<<6)) ) {
- show_help(opts, arg->flags);
- }
- }
-
- arg->r_opt = opts[i].short_opt;
- if( !opts[i].short_opt ) {
- arg->r_opt = (opts[i].flags & 256)? -7:-2;
- arg->internal.inarg++; /* point to the next arg */
- arg->r.ret_str = s;
- }
- else if( (opts[i].flags & 7) ) {
- if( s[1] && !dash_kludge ) {
- s2 = s+1;
- set_opt_arg(arg, opts[i].flags, s2);
- }
- else {
- s2 = argv[1];
- if( !s2 && (opts[i].flags & 8) ) { /* no argument but it is okay*/
- arg->r_type = 0; /* because it is optional */
- }
- else if( !s2 ) {
- arg->r_opt = -3; /* missing argument */
- }
- else if( *s2 == '-' && s2[1] && (opts[i].flags & 8) ) {
- /* the argument is optional and the next seems to be
- * an option. We do not check this possible option
- * but assume no argument */
- arg->r_type = 0;
- }
- else {
- set_opt_arg(arg, opts[i].flags, s2);
- argc--; argv++; idx++; /* skip one */
- }
- }
- s = "x"; /* so that !s[1] yields false */
- }
- else { /* does not take an argument */
- arg->r_type = 0;
- arg->internal.inarg++; /* point to the next arg */
- }
- if( !s[1] || dash_kludge ) { /* no more concatenated short options */
- arg->internal.inarg = 0;
- argc--; argv++; idx++;
- }
- }
- else if( arg->flags & (1<<2) ) {
- arg->r_opt = -1; /* not an option but a argument */
- arg->r_type = 2;
- arg->r.ret_str = s;
- argc--; argv++; idx++; /* set to next one */
- }
- else {
- arg->internal.stopped = 1; /* stop option processing */
- goto next_one;
- }
-
- leave:
- *arg->argc = argc;
- *arg->argv = argv;
- arg->internal.idx = idx;
- return arg->r_opt;
-}
-
-
-
-static int
-set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s)
-{
- int base = (flags & 16)? 0 : 10;
-
- switch( arg->r_type = (flags & 7) ) {
- case 1: /* takes int argument */
- arg->r.ret_int = (int)strtol(s,NULL,base);
- return 0;
- case 3: /* takes long argument */
- arg->r.ret_long= strtol(s,NULL,base);
- return 0;
- case 4: /* takes ulong argument */
- arg->r.ret_ulong= strtoul(s,NULL,base);
- return 0;
- case 2: /* takes string argument */
- default:
- arg->r.ret_str = s;
- return 1;
- }
-}
-
-
-static size_t
-long_opt_strlen( ARGPARSE_OPTS *o )
-{
- size_t n = strlen(o->long_opt);
-
- if( o->description && *o->description == '|' ) {
- const char *s;
-
- s=o->description+1;
- if( *s != '=' )
- n++;
- for(; *s && *s != '|'; s++ )
- n++;
- }
- return n;
-}
-
-/****************
- * Print formatted help. The description string has some special
- * meanings:
- * - A description string which is "@" suppresses help output for
- * this option
- * - a description,ine which starts with a '@' and is followed by
- * any other characters is printed as is; this may be used for examples
- * ans such.
- * - A description which starts with a '|' outputs the string between this
- * bar and the next one as arguments of the long option.
- */
-static void
-show_help( ARGPARSE_OPTS *opts, unsigned flags )
-{
- const char *s;
-
- show_version();
- putchar('\n');
- s = strusage(41);
- puts(s);
- if( opts[0].description ) { /* auto format the option description */
- int i,j, indent;
- /* get max. length of long options */
- for(i=indent=0; opts[i].short_opt; i++ ) {
- if( opts[i].long_opt )
- if( !opts[i].description || *opts[i].description != '@' )
- if( (j=long_opt_strlen(opts+i)) > indent && j < 35 )
- indent = j;
- }
- /* example: " -v, --verbose Viele Sachen ausgeben" */
- indent += 10;
- if( *opts[0].description != '@' )
- puts("Options:");
- for(i=0; opts[i].short_opt; i++ ) {
- s = _( opts[i].description );
- if( s && *s== '@' && !s[1] ) /* hide this line */
- continue;
- if( s && *s == '@' ) { /* unindented comment only line */
- for(s++; *s; s++ ) {
- if( *s == '\n' ) {
- if( s[1] )
- putchar('\n');
- }
- else
- putchar(*s);
- }
- putchar('\n');
- continue;
- }
-
- j = 3;
- if( opts[i].short_opt < 256 ) {
- printf(" -%c", opts[i].short_opt );
- if( !opts[i].long_opt ) {
- if(s && *s == '|' ) {
- putchar(' '); j++;
- for(s++ ; *s && *s != '|'; s++, j++ )
- putchar(*s);
- if( *s )
- s++;
- }
- }
- }
- else
- fputs(" ", stdout);
- if( opts[i].long_opt ) {
- j += printf("%c --%s", opts[i].short_opt < 256?',':' ',
- opts[i].long_opt );
- if(s && *s == '|' ) {
- if( *++s != '=' ) {
- putchar(' ');
- j++;
- }
- for( ; *s && *s != '|'; s++, j++ )
- putchar(*s);
- if( *s )
- s++;
- }
- fputs(" ", stdout);
- j += 3;
- }
- for(;j < indent; j++ )
- putchar(' ');
- if( s ) {
- if( *s && j > indent ) {
- putchar('\n');
- for(j=0;j < indent; j++ )
- putchar(' ');
- }
- for(; *s; s++ ) {
- if( *s == '\n' ) {
- if( s[1] ) {
- putchar('\n');
- for(j=0;j < indent; j++ )
- putchar(' ');
- }
- }
- else
- putchar(*s);
- }
- }
- putchar('\n');
- }
- if( flags & 32 )
- puts("\n(A single dash may be used instead of the double ones)");
- }
- if( (s=strusage(19)) ) { /* bug reports to ... */
- putchar('\n');
- fputs(s, stdout);
- }
- fflush(stdout);
- exit(0);
-}
-
-static void
-show_version()
-{
- const char *s;
- int i;
- /* version line */
- fputs(strusage(11), stdout);
- if( (s=strusage(12)) )
- printf(" (%s)", s );
- printf(" %s\n", strusage(13) );
- /* additional version lines */
- for(i=20; i < 30; i++ )
- if( (s=strusage(i)) )
- printf("%s\n", s );
- /* copyright string */
- if( (s=strusage(14)) )
- printf("%s\n", s );
- /* copying conditions */
- if( (s=strusage(15)) )
- fputs(s, stdout);
- /* thanks */
- if( (s=strusage(18)) )
- fputs(s, stdout);
- /* additional program info */
- for(i=30; i < 40; i++ )
- if( (s=strusage(i)) )
- fputs( (const byte*)s, stdout);
- fflush(stdout);
-}
-
-
-void
-usage( int level )
-{
- if( !level ) {
- fprintf(stderr,"%s %s; %s\n", strusage(11), strusage(13),
- strusage(14) );
- fflush(stderr);
- }
- else if( level == 1 ) {
- fputs(strusage(40),stderr);
- exit(2);
- }
- else if( level == 2 ) {
- puts(strusage(41));
- exit(0);
- }
-}
-
-/* Level
- * 0: Copyright String auf stderr ausgeben
- * 1: Kurzusage auf stderr ausgeben und beenden
- * 2: Langusage auf stdout ausgeben und beenden
- * 11: name of program
- * 12: optional name of package which includes this program.
- * 13: version string
- * 14: copyright string
- * 15: Short copying conditions (with LFs)
- * 16: Long copying conditions (with LFs)
- * 17: Optional printable OS name
- * 18: Optional thanks list (with LFs)
- * 19: Bug report info
- *20..29: Additional lib version strings.
- *30..39: Additional program info (with LFs)
- * 40: short usage note (with LF)
- * 41: long usage note (with LF)
- */
-const char *
-default_strusage( int level )
-{
- const char *p = NULL;
- switch( level ) {
- case 11: p = "foo"; break;
- case 13: p = "0.0"; break;
- case 14: p = "Copyright (C) 2006 Free Software Foundation, Inc."; break;
- case 15: p =
-"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"; break;
- case 16: p =
-"This is free software; you can redistribute it and/or modify\n"
-"it under the terms of the GNU General Public License as published by\n"
-"the Free Software Foundation; either version 2 of the License, or\n"
-"(at your option) any later version.\n\n"
-"It is distributed in the hope that it will be useful,\n"
-"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
-"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
-"GNU General Public License for more details.\n\n"
-"You should have received a copy of the GNU General Public License\n"
-"along with this program; if not, write to the Free Software\n"
-"Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n";
- break;
- case 40: /* short and long usage */
- case 41: p = ""; break;
- }
-
- return p;
-}
-
-
-
-#ifdef TEST
-static struct {
- int verbose;
- int debug;
- char *outfile;
- char *crf;
- int myopt;
- int echo;
- int a_long_one;
-}opt;
-
-int
-main(int argc, char **argv)
-{
- ARGPARSE_OPTS opts[] = {
- { 'v', "verbose", 0 , "Laut sein"},
- { 'e', "echo" , 0 , "Zeile ausgeben, damit wir sehen, was wir einegegeben haben"},
- { 'd', "debug", 0 , "Debug\nfalls mal etasws\nSchief geht"},
- { 'o', "output", 2 },
- { 'c', "cross-ref", 2|8, "cross-reference erzeugen\n" },
- { 'm', "my-option", 1|8 },
- { 500, "a-long-option", 0 },
- {0} };
- ARGPARSE_ARGS pargs = { &argc, &argv, 2|4|32 };
- int i;
-
- while( ArgParse( &pargs, opts) ) {
- switch( pargs.r_opt ) {
- case -1 : printf( "arg=`%s'\n", pargs.r.ret_str); break;
- case 'v': opt.verbose++; break;
- case 'e': opt.echo++; break;
- case 'd': opt.debug++; break;
- case 'o': opt.outfile = pargs.r.ret_str; break;
- case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
- case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
- case 500: opt.a_long_one++; break;
- default : pargs.err = 1; break; /* force warning output */
- }
- }
- for(i=0; i < argc; i++ )
- printf("%3d -> (%s)\n", i, argv[i] );
- puts("Options:");
- if( opt.verbose )
- printf(" verbose=%d\n", opt.verbose );
- if( opt.debug )
- printf(" debug=%d\n", opt.debug );
- if( opt.outfile )
- printf(" outfile=`%s'\n", opt.outfile );
- if( opt.crf )
- printf(" crffile=`%s'\n", opt.crf );
- if( opt.myopt )
- printf(" myopt=%d\n", opt.myopt );
- if( opt.a_long_one )
- printf(" a-long-one=%d\n", opt.a_long_one );
- if( opt.echo )
- printf(" echo=%d\n", opt.echo );
- return 0;
-}
-#endif
-
-/**** bottom of file ****/
diff --git a/util/assuan-buffer.c b/util/assuan-buffer.c
deleted file mode 100644
index 3c0108601..000000000
--- a/util/assuan-buffer.c
+++ /dev/null
@@ -1,485 +0,0 @@
-/* assuan-buffer.c - read and send data
- * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
- *
- * This file is part of Assuan.
- *
- * Assuan is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Assuan is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-/* Please note that this is a stripped down and modified version of
- the orginal Assuan code from libassuan. */
-
-
-#include <config.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <assert.h>
-#ifdef HAVE_W32_SYSTEM
-#include <process.h>
-#endif
-#include "assuan-defs.h"
-
-#ifndef HAVE_MEMRCHR
-void *memrchr(const void *s, int c, size_t n);
-#endif
-
-static int
-writen (assuan_context_t ctx, const char *buffer, size_t length)
-{
- while (length)
- {
- ssize_t nwritten = ctx->io->writefnc (ctx, buffer, length);
-
- if (nwritten < 0)
- {
- if (errno == EINTR)
- continue;
- return -1; /* write error */
- }
- length -= nwritten;
- buffer += nwritten;
- }
- return 0; /* okay */
-}
-
-/* Read an entire line. */
-static int
-readaline (assuan_context_t ctx, char *buf, size_t buflen,
- int *r_nread, int *r_eof)
-{
- size_t nleft = buflen;
- char *p;
-
- *r_eof = 0;
- *r_nread = 0;
- while (nleft > 0)
- {
- ssize_t n = ctx->io->readfnc (ctx, buf, nleft);
-
- if (n < 0)
- {
- if (errno == EINTR)
- continue;
- return -1; /* read error */
- }
- else if (!n)
- {
- *r_eof = 1;
- break; /* allow incomplete lines */
- }
- p = buf;
- nleft -= n;
- buf += n;
- *r_nread += n;
-
- p = memrchr (p, '\n', n);
- if (p)
- break; /* at least one full line available - that's enough for now */
- }
-
- return 0;
-}
-
-
-int
-_assuan_read_line (assuan_context_t ctx)
-{
- char *line = ctx->inbound.line;
- int nread, atticlen;
- int rc;
- char *endp = 0;
-
- if (ctx->inbound.eof)
- return -1;
-
- atticlen = ctx->inbound.attic.linelen;
- if (atticlen)
- {
- memcpy (line, ctx->inbound.attic.line, atticlen);
- ctx->inbound.attic.linelen = 0;
-
- endp = memchr (line, '\n', atticlen);
- if (endp)
- /* Found another line in the attic. */
- {
- rc = 0;
- nread = atticlen;
- atticlen = 0;
- }
- else
- /* There is pending data but not a full line. */
- {
- assert (atticlen < LINELENGTH);
- rc = readaline (ctx, line + atticlen,
- LINELENGTH - atticlen, &nread, &ctx->inbound.eof);
- }
- }
- else
- /* No pending data. */
- rc = readaline (ctx, line, LINELENGTH,
- &nread, &ctx->inbound.eof);
- if (rc)
- {
- if (ctx->log_fp)
- fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [Error: %s]\n",
- assuan_get_assuan_log_prefix (),
- (unsigned int)getpid (), (void *)ctx, strerror (errno));
- return ASSUAN_Read_Error;
- }
- if (!nread)
- {
- assert (ctx->inbound.eof);
- if (ctx->log_fp)
- fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [EOF]\n",
- assuan_get_assuan_log_prefix (),
- (unsigned int)getpid (), (void *)ctx);
- return -1;
- }
-
- ctx->inbound.attic.pending = 0;
- nread += atticlen;
-
- if (! endp)
- endp = memchr (line, '\n', nread);
-
- if (endp)
- {
- int n = endp - line + 1;
- if (n < nread)
- /* LINE contains more than one line. We copy it to the attic
- now as handlers are allowed to modify the passed
- buffer. */
- {
- int len = nread - n;
- memcpy (ctx->inbound.attic.line, endp + 1, len);
- ctx->inbound.attic.pending = memrchr (endp + 1, '\n', len) ? 1 : 0;
- ctx->inbound.attic.linelen = len;
- }
-
- if (endp != line && endp[-1] == '\r')
- endp --;
- *endp = 0;
-
- ctx->inbound.linelen = endp - line;
- if (ctx->log_fp)
- {
- fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- ",
- assuan_get_assuan_log_prefix (),
- (unsigned int)getpid (), (void *)ctx);
- if (ctx->confidential)
- fputs ("[Confidential data not shown]", ctx->log_fp);
- else
- _assuan_log_print_buffer (ctx->log_fp,
- ctx->inbound.line,
- ctx->inbound.linelen);
- putc ('\n', ctx->log_fp);
- }
- return 0;
- }
- else
- {
- if (ctx->log_fp)
- fprintf (ctx->log_fp, "%s[%u.%p] DBG: <- [Invalid line]\n",
- assuan_get_assuan_log_prefix (),
- (unsigned int)getpid (), (void *)ctx);
- *line = 0;
- ctx->inbound.linelen = 0;
- return ctx->inbound.eof ? ASSUAN_Line_Not_Terminated
- : ASSUAN_Line_Too_Long;
- }
-}
-
-
-/* Read the next line from the client or server and return a pointer
- in *LINE to a buffer holding the line. LINELEN is the length of
- *LINE. The buffer is valid until the next read operation on it.
- The caller may modify the buffer. The buffer is invalid (i.e. must
- not be used) if an error is returned.
-
- Returns 0 on success or an assuan error code.
- See also: assuan_pending_line().
-*/
-assuan_error_t
-assuan_read_line (assuan_context_t ctx, char **line, size_t *linelen)
-{
- assuan_error_t err;
-
- if (!ctx)
- return ASSUAN_Invalid_Value;
-
- err = _assuan_read_line (ctx);
- *line = ctx->inbound.line;
- *linelen = ctx->inbound.linelen;
- return err;
-}
-
-
-/* Return true if a full line is buffered (i.e. an entire line may be
- read without any I/O). */
-int
-assuan_pending_line (assuan_context_t ctx)
-{
- return ctx && ctx->inbound.attic.pending;
-}
-
-
-assuan_error_t
-_assuan_write_line (assuan_context_t ctx, const char *prefix,
- const char *line, size_t len)
-{
- int rc = 0;
- size_t prefixlen = prefix? strlen (prefix):0;
-
- /* Make sure that the line is short enough. */
- if (len + prefixlen + 2 > ASSUAN_LINELENGTH)
- {
- if (ctx->log_fp)
- fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> "
- "[supplied line too long -truncated]\n",
- assuan_get_assuan_log_prefix (),
- (unsigned int)getpid (), (void *)ctx);
- if (prefixlen > 5)
- prefixlen = 5;
- if (len > ASSUAN_LINELENGTH - prefixlen - 2)
- len = ASSUAN_LINELENGTH - prefixlen - 2 - 1;
- }
-
- /* Fixme: we should do some kind of line buffering. */
- if (ctx->log_fp)
- {
- fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ",
- assuan_get_assuan_log_prefix (),
- (unsigned int)getpid (), (void *)ctx);
- if (ctx->confidential)
- fputs ("[Confidential data not shown]", ctx->log_fp);
- else
- _assuan_log_print_buffer (ctx->log_fp, line, len);
- putc ('\n', ctx->log_fp);
- }
-
- if (prefixlen)
- {
- rc = writen (ctx, prefix, prefixlen);
- if (rc)
- rc = ASSUAN_Write_Error;
- }
- if (!rc)
- {
- rc = writen (ctx, line, len);
- if (rc)
- rc = ASSUAN_Write_Error;
- if (!rc)
- {
- rc = writen (ctx, "\n", 1);
- if (rc)
- rc = ASSUAN_Write_Error;
- }
- }
- return rc;
-}
-
-
-assuan_error_t
-assuan_write_line (assuan_context_t ctx, const char *line)
-{
- size_t len;
- const char *s;
-
- if (!ctx)
- return ASSUAN_Invalid_Value;
-
- /* Make sure that we never take a LF from the user - this might
- violate the protocol. */
- s = strchr (line, '\n');
- len = s? (s-line) : strlen (line);
-
- if (ctx->log_fp && s)
- fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> "
- "[supplied line contained a LF -truncated]\n",
- assuan_get_assuan_log_prefix (),
- (unsigned int)getpid (), (void *)ctx);
-
- return _assuan_write_line (ctx, NULL, line, len);
-}
-
-
-
-/* Write out the data in buffer as datalines with line wrapping and
- percent escaping. This function is used for GNU's custom streams */
-int
-_assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
-{
- assuan_context_t ctx = cookie;
- size_t size = orig_size;
- char *line;
- size_t linelen;
-
- if (ctx->outbound.data.error)
- return 0;
-
- line = ctx->outbound.data.line;
- linelen = ctx->outbound.data.linelen;
- line += linelen;
- while (size)
- {
- /* insert data line header */
- if (!linelen)
- {
- *line++ = 'D';
- *line++ = ' ';
- linelen += 2;
- }
-
- /* copy data, keep some space for the CRLF and to escape one character */
- while (size && linelen < LINELENGTH-2-2)
- {
- if (*buffer == '%' || *buffer == '\r' || *buffer == '\n')
- {
- sprintf (line, "%%%02X", *(unsigned char*)buffer);
- line += 3;
- linelen += 3;
- buffer++;
- }
- else
- {
- *line++ = *buffer++;
- linelen++;
- }
- size--;
- }
-
- if (linelen >= LINELENGTH-2-2)
- {
- if (ctx->log_fp)
- {
- fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ",
- assuan_get_assuan_log_prefix (),
- (unsigned int)getpid (), (void *)ctx);
-
- if (ctx->confidential)
- fputs ("[Confidential data not shown]", ctx->log_fp);
- else
- _assuan_log_print_buffer (ctx->log_fp,
- ctx->outbound.data.line,
- linelen);
- putc ('\n', ctx->log_fp);
- }
- *line++ = '\n';
- linelen++;
- if (writen (ctx, ctx->outbound.data.line, linelen))
- {
- ctx->outbound.data.error = ASSUAN_Write_Error;
- return 0;
- }
- line = ctx->outbound.data.line;
- linelen = 0;
- }
- }
-
- ctx->outbound.data.linelen = linelen;
- return (int)orig_size;
-}
-
-
-/* Write out any buffered data
- This function is used for GNU's custom streams */
-int
-_assuan_cookie_write_flush (void *cookie)
-{
- assuan_context_t ctx = cookie;
- char *line;
- size_t linelen;
-
- if (ctx->outbound.data.error)
- return 0;
-
- line = ctx->outbound.data.line;
- linelen = ctx->outbound.data.linelen;
- line += linelen;
- if (linelen)
- {
- if (ctx->log_fp)
- {
- fprintf (ctx->log_fp, "%s[%u.%p] DBG: -> ",
- assuan_get_assuan_log_prefix (),
- (unsigned int)getpid (), (void *)ctx);
- if (ctx->confidential)
- fputs ("[Confidential data not shown]", ctx->log_fp);
- else
- _assuan_log_print_buffer (ctx->log_fp,
- ctx->outbound.data.line, linelen);
- putc ('\n', ctx->log_fp);
- }
- *line++ = '\n';
- linelen++;
- if (writen (ctx, ctx->outbound.data.line, linelen))
- {
- ctx->outbound.data.error = ASSUAN_Write_Error;
- return 0;
- }
- ctx->outbound.data.linelen = 0;
- }
- return 0;
-}
-
-
-/**
- * assuan_send_data:
- * @ctx: An assuan context
- * @buffer: Data to send or NULL to flush
- * @length: length of the data to send/
- *
- * This function may be used by the server or the client to send data
- * lines. The data will be escaped as required by the Assuan protocol
- * and may get buffered until a line is full. To force sending the
- * data out @buffer may be passed as NULL (in which case @length must
- * also be 0); however when used by a client this flush operation does
- * also send the terminating "END" command to terminate the reponse on
- * a INQUIRE response. However, when assuan_transact() is used, this
- * function takes care of sending END itself.
- *
- * Return value: 0 on success or an error code
- **/
-
-assuan_error_t
-assuan_send_data (assuan_context_t ctx, const void *buffer, size_t length)
-{
- if (!ctx)
- return ASSUAN_Invalid_Value;
- if (!buffer && length)
- return ASSUAN_Invalid_Value;
-
- if (!buffer)
- { /* flush what we have */
- _assuan_cookie_write_flush (ctx);
- if (ctx->outbound.data.error)
- return ctx->outbound.data.error;
- if (!ctx->is_server)
- return assuan_write_line (ctx, "END");
- }
- else
- {
- _assuan_cookie_write_data (ctx, buffer, length);
- if (ctx->outbound.data.error)
- return ctx->outbound.data.error;
- }
-
- return 0;
-}
-
diff --git a/util/assuan-client.c b/util/assuan-client.c
deleted file mode 100644
index 0467f6dc5..000000000
--- a/util/assuan-client.c
+++ /dev/null
@@ -1,282 +0,0 @@
-/* assuan-client.c - client functions
- * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
- * Copyright (C) 2005 Free Software Foundation, Inc.
- *
- * This file is part of Assuan.
- *
- * Assuan is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Assuan is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-/* Please note that this is a stripped down and modified version of
- the orginal Assuan code from libassuan. */
-
-#include <config.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <assert.h>
-#include <string.h>
-
-#include "assuan-defs.h"
-
-#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
- *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
-#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
-
-
-assuan_error_t
-_assuan_read_from_server (assuan_context_t ctx, int *okay, int *off)
-{
- char *line;
- int linelen;
- assuan_error_t rc;
-
- *okay = 0;
- *off = 0;
- do
- {
- rc = _assuan_read_line (ctx);
- if (rc)
- return rc;
- line = ctx->inbound.line;
- linelen = ctx->inbound.linelen;
- }
- while (*line == '#' || !linelen);
-
- if (linelen >= 1
- && line[0] == 'D' && line[1] == ' ')
- {
- *okay = 2; /* data line */
- *off = 2;
- }
- else if (linelen >= 1
- && line[0] == 'S'
- && (line[1] == '\0' || line[1] == ' '))
- {
- *okay = 4;
- *off = 1;
- while (line[*off] == ' ')
- ++*off;
- }
- else if (linelen >= 2
- && line[0] == 'O' && line[1] == 'K'
- && (line[2] == '\0' || line[2] == ' '))
- {
- *okay = 1;
- *off = 2;
- while (line[*off] == ' ')
- ++*off;
- }
- else if (linelen >= 3
- && line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
- && (line[3] == '\0' || line[3] == ' '))
- {
- *okay = 0;
- *off = 3;
- while (line[*off] == ' ')
- ++*off;
- }
- else if (linelen >= 7
- && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
- && line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
- && line[6] == 'E'
- && (line[7] == '\0' || line[7] == ' '))
- {
- *okay = 3;
- *off = 7;
- while (line[*off] == ' ')
- ++*off;
- }
- else if (linelen >= 3
- && line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
- && (line[3] == '\0' || line[3] == ' '))
- {
- *okay = 5; /* end line */
- *off = 3;
- }
- else
- rc = ASSUAN_Invalid_Response;
- return rc;
-}
-
-
-
-assuan_error_t
-assuan_transact (assuan_context_t ctx,
- const char *command,
- assuan_error_t (*data_cb)(void *, const void *, size_t),
- void *data_cb_arg,
- assuan_error_t (*inquire_cb)(void*, const char *),
- void *inquire_cb_arg,
- assuan_error_t (*status_cb)(void*, const char *),
- void *status_cb_arg)
-{
- return assuan_transact2 (ctx, command,
- data_cb, data_cb_arg,
- inquire_cb, inquire_cb_arg,
- status_cb, status_cb_arg,
- NULL, NULL);
-}
-
-
-/**
- * assuan_transact2:
- * @ctx: The Assuan context
- * @command: Coimmand line to be send to server
- * @data_cb: Callback function for data lines
- * @data_cb_arg: first argument passed to @data_cb
- * @inquire_cb: Callback function for a inquire response
- * @inquire_cb_arg: first argument passed to @inquire_cb
- * @status_cb: Callback function for a status response
- * @status_cb_arg: first argument passed to @status_cb
- * @okay_cb: Callback function for the final OK response
- * @okay_cb_arg: first argument passed to @okay_cb
- *
- * FIXME: Write documentation
- *
- * Return value: 0 on success or error code. The error code may be
- * the one one returned by the server in error lines or from the
- * callback functions.
- **/
-assuan_error_t
-assuan_transact2 (assuan_context_t ctx,
- const char *command,
- assuan_error_t (*data_cb)(void *, const void *, size_t),
- void *data_cb_arg,
- assuan_error_t (*inquire_cb)(void*, const char *),
- void *inquire_cb_arg,
- assuan_error_t (*status_cb)(void*, const char *),
- void *status_cb_arg,
- assuan_error_t (*okay_cb)(void*, const char *),
- void *okay_cb_arg)
-{
- int rc, okay, off;
- unsigned char *line;
- int linelen;
-
- rc = assuan_write_line (ctx, command);
- if (rc)
- return rc;
-
- if (*command == '#' || !*command)
- return 0; /* Don't expect a response for a comment line. */
-
- again:
- rc = _assuan_read_from_server (ctx, &okay, &off);
- if (rc)
- return rc; /* error reading from server */
-
- line = ctx->inbound.line + off;
- linelen = ctx->inbound.linelen - off;
-
- if (!okay)
- {
- rc = atoi (line);
- if (rc < 100)
- rc = ASSUAN_Server_Fault;
- }
- else if (okay == 1) /* Received OK. */
- {
- if (okay_cb)
- {
- rc = okay_cb (okay_cb_arg, line);
- /* We better wipe out the buffer after processing it. This
- is no real guarantee that it won't get swapped out but at
- least for the standard cases we can make sure that a
- passphrase returned with the OK line is rendered
- unreadable. In fact the current Assuan interface suffers
- from the problem that it is not possible to do assuan I/O
- through secure memory. There is no easy solution given
- the current implementation but we need to address it
- sooner or later. The problem was introduced with
- gpg-agent's GET_PASPHRASE command but it might also make
- sense to have a way to convey sessions keys through
- secured memory. Note that the old implementation in gpg
- for accessing the passphrase in fact used secure memory
- but had the drawback of using a limited and not fully
- conforming Assuan implementation - given that pinentry
- and gpg-agent neither use secured memory for Assuan I/O,
- it is negligible to drop the old implementation in gpg's
- passphrase.c and use the wipememory workaround here. */
- memset (line, 0, strlen (line));
- }
- }
- else if (okay == 2)
- {
- if (!data_cb)
- rc = ASSUAN_No_Data_Callback;
- else
- {
- unsigned char *s, *d;
-
- for (s=d=line; linelen; linelen--)
- {
- if (*s == '%' && linelen > 2)
- { /* handle escaping */
- s++;
- *d++ = xtoi_2 (s);
- s += 2;
- linelen -= 2;
- }
- else
- *d++ = *s++;
- }
- *d = 0; /* add a hidden string terminator */
- rc = data_cb (data_cb_arg, line, d - line);
- if (!rc)
- goto again;
- }
- }
- else if (okay == 3)
- {
- if (!inquire_cb)
- {
- assuan_write_line (ctx, "END"); /* get out of inquire mode */
- _assuan_read_from_server (ctx, &okay, &off); /* dummy read */
- rc = ASSUAN_No_Inquire_Callback;
- }
- else
- {
- rc = inquire_cb (inquire_cb_arg, line);
- if (!rc)
- rc = assuan_send_data (ctx, NULL, 0); /* flush and send END */
- if (!rc)
- goto again;
- }
- }
- else if (okay == 4)
- {
- if (status_cb)
- rc = status_cb (status_cb_arg, line);
- if (!rc)
- goto again;
- }
- else if (okay == 5)
- {
- if (!data_cb)
- rc = ASSUAN_No_Data_Callback;
- else
- {
- rc = data_cb (data_cb_arg, NULL, 0);
- if (!rc)
- goto again;
- }
- }
-
- return rc;
-}
-
diff --git a/util/assuan-connect.c b/util/assuan-connect.c
deleted file mode 100644
index 9952b4406..000000000
--- a/util/assuan-connect.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* assuan-connect.c - Establish a connection (client)
- * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
- *
- * This file is part of Assuan.
- *
- * Assuan is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Assuan is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-/* Please note that this is a stripped down and modified version of
- the orginal Assuan code from libassuan. */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/types.h>
-#ifndef HAVE_W32_SYSTEM
-#include <sys/wait.h>
-#endif
-
-#include "assuan-defs.h"
-
-/* Create a new context. */
-int
-_assuan_new_context (assuan_context_t *r_ctx)
-{
- assuan_context_t ctx;
-
- *r_ctx = NULL;
- ctx = xcalloc (1, sizeof *ctx);
-
- ctx->input_fd = -1;
- ctx->output_fd = -1;
-
- ctx->inbound.fd = -1;
- ctx->outbound.fd = -1;
- ctx->io = NULL;
-
- ctx->listen_fd = -1;
- *r_ctx = ctx;
- return 0;
-}
-
-
-void
-_assuan_release_context (assuan_context_t ctx)
-{
- if (ctx)
- {
- xfree (ctx->hello_line);
- xfree (ctx->okay_line);
- xfree (ctx);
- }
-}
-
-
-/* Disconnect and release the context CTX. */
-void
-assuan_disconnect (assuan_context_t ctx)
-{
- if (ctx)
- {
- assuan_write_line (ctx, "BYE");
- ctx->finish_handler (ctx);
- ctx->deinit_handler (ctx);
- ctx->deinit_handler = NULL;
- _assuan_release_context (ctx);
- }
-}
-
-/* Return the PID of the peer or -1 if not known. */
-pid_t
-assuan_get_pid (assuan_context_t ctx)
-{
- return (ctx && ctx->pid)? ctx->pid : -1;
-}
-
diff --git a/util/assuan-defs.h b/util/assuan-defs.h
deleted file mode 100644
index 67c4e13ce..000000000
--- a/util/assuan-defs.h
+++ /dev/null
@@ -1,244 +0,0 @@
-/* assuan-defs.c - Internal definitions to Assuan
- * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
- * Copyright (C) 2005 Free Software Foundation, Inc.
- *
- * This file is part of Assuan.
- *
- * Assuan is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Assuan is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-/* Please note that this is a stripped down and modified version of
- the orginal Assuan code from libassuan. */
-
-
-#ifndef ASSUAN_DEFS_H
-#define ASSUAN_DEFS_H
-
-#include <sys/types.h>
-#ifndef HAVE_W32_SYSTEM
-#include <sys/socket.h>
-#include <sys/un.h>
-#else
-#include <windows.h>
-#endif
-#include <unistd.h>
-
-#include "assuan.h"
-#include "memory.h"
-
-#ifndef HAVE_W32_SYSTEM
-#define DIRSEP_C '/'
-#else
-#define DIRSEP_C '\\'
-#endif
-
-#ifdef HAVE_W32_SYSTEM
-#define AF_LOCAL AF_UNIX
-/* We need to prefix the structure with a sockaddr_in header so we can
- use it later for sendto and recvfrom. */
-struct sockaddr_un
-{
- short sun_family;
- unsigned short sun_port;
- struct in_addr sun_addr;
- char sun_path[108-2-4]; /* Path name. */
-};
-
-/* Not needed anymore because the current mingw32 defines this in
- sys/types.h */
-/* typedef int ssize_t; */
-
-/* Missing W32 functions */
-int putc_unlocked (int c, FILE *stream);
-void * memrchr (const void *block, int c, size_t size);
-char * stpcpy (char *dest, const char *src);
-#endif
-
-#define LINELENGTH ASSUAN_LINELENGTH
-
-struct cmdtbl_s
-{
- const char *name;
- int (*handler)(assuan_context_t, char *line);
-};
-
-struct assuan_io
-{
- /* Routine to read from input_fd. */
- ssize_t (*readfnc) (assuan_context_t, void *, size_t);
- /* Routine to write to output_fd. */
- ssize_t (*writefnc) (assuan_context_t, const void *, size_t);
- /* Send a file descriptor. */
- assuan_error_t (*sendfd) (assuan_context_t, int);
- /* Receive a file descriptor. */
- assuan_error_t (*receivefd) (assuan_context_t, int *);
-};
-
-struct assuan_context_s
-{
- assuan_error_t err_no;
- const char *err_str;
- int os_errno; /* last system error number used with certain error codes*/
-
- int confidential;
- int is_server; /* set if this is context belongs to a server */
- int in_inquire;
- char *hello_line;
- char *okay_line; /* see assan_set_okay_line() */
-
- void *user_pointer; /* for assuan_[gs]et_pointer () */
-
- FILE *log_fp;
-
- struct {
- int fd;
- int eof;
- char line[LINELENGTH];
- int linelen; /* w/o CR, LF - might not be the same as
- strlen(line) due to embedded nuls. However a nul
- is always written at this pos */
- struct {
- char line[LINELENGTH];
- int linelen ;
- int pending; /* i.e. at least one line is available in the attic */
- } attic;
- } inbound;
-
- struct {
- int fd;
- struct {
- FILE *fp;
- char line[LINELENGTH];
- int linelen;
- int error;
- } data;
- } outbound;
-
- int pipe_mode; /* We are in pipe mode, i.e. we can handle just one
- connection and must terminate then */
- pid_t pid; /* The the pid of the peer. */
- int listen_fd; /* The fd we are listening on (used by socket servers) */
- int connected_fd; /* helper */
-
- /* Used for Unix domain sockets. */
- struct sockaddr_un myaddr;
- struct sockaddr_un serveraddr;
- /* When reading from datagram sockets, we must read an entire
- message at a time. This means that we have to do our own
- buffering to be able to get the semantics of read. */
- void *domainbuffer;
- /* Offset of start of buffer. */
- int domainbufferoffset;
- /* Bytes buffered. */
- int domainbuffersize;
- /* Memory allocated. */
- int domainbufferallocated;
-
- int *pendingfds;
- int pendingfdscount;
-
- void (*deinit_handler)(assuan_context_t);
- int (*accept_handler)(assuan_context_t);
- int (*finish_handler)(assuan_context_t);
-
- struct cmdtbl_s *cmdtbl;
- size_t cmdtbl_used; /* used entries */
- size_t cmdtbl_size; /* allocated size of table */
-
- void (*bye_notify_fnc)(assuan_context_t);
- void (*reset_notify_fnc)(assuan_context_t);
- void (*cancel_notify_fnc)(assuan_context_t);
- int (*option_handler_fnc)(assuan_context_t,const char*, const char*);
- void (*input_notify_fnc)(assuan_context_t, const char *);
- void (*output_notify_fnc)(assuan_context_t, const char *);
-
- int input_fd; /* set by INPUT command */
- int output_fd; /* set by OUTPUT command */
-
- /* io routines. */
- struct assuan_io *io;
-};
-
-/*-- assuan-pipe-server.c --*/
-int _assuan_new_context (assuan_context_t *r_ctx);
-void _assuan_release_context (assuan_context_t ctx);
-
-/*-- assuan-domain-connect.c --*/
-/* Make a connection to the Unix domain socket NAME and return a new
- Assuan context in CTX. SERVER_PID is currently not used but may
- become handy in the future. */
-assuan_error_t _assuan_domain_init (assuan_context_t *r_ctx,
- int rendezvousfd,
- pid_t peer);
-
-/*-- assuan-handler.c --*/
-int _assuan_register_std_commands (assuan_context_t ctx);
-
-/*-- assuan-buffer.c --*/
-int _assuan_read_line (assuan_context_t ctx);
-int _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size);
-int _assuan_cookie_write_flush (void *cookie);
-assuan_error_t _assuan_write_line (assuan_context_t ctx, const char *prefix,
- const char *line, size_t len);
-
-/*-- assuan-client.c --*/
-assuan_error_t _assuan_read_from_server (assuan_context_t ctx, int *okay, int *off);
-
-
-/*-- assuan-util.c --*/
-
-#define set_error(c,e,t) assuan_set_error ((c), ASSUAN_ ## e, (t))
-
-void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length);
-void _assuan_log_sanitized_string (const char *string);
-
-#ifdef HAVE_W32_SYSTEM
-const char *_assuan_w32_strerror (int ec);
-#define w32_strerror(e) _assuan_w32_strerror ((e))
-#endif /*HAVE_W32_SYSTEM*/
-
-
-/*-- assuan-logging.c --*/
-void _assuan_set_default_log_stream (FILE *fp);
-
-void _assuan_log_printf (const char *format, ...)
-#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
- __attribute__ ((format (printf,1,2)))
-#endif
- ;
-
-/*-- assuan-io.c --*/
-ssize_t _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size);
-ssize_t _assuan_simple_write (assuan_context_t ctx, const void *buffer,
- size_t size);
-
-/*-- assuan-socket.c --*/
-int _assuan_close (int fd);
-int _assuan_sock_new (int domain, int type, int proto);
-int _assuan_sock_connect (int sockfd, struct sockaddr *addr, int addrlen);
-
-#ifdef HAVE_FOPENCOOKIE
-/* We have to implement funopen in terms of glibc's fopencookie. */
-FILE *_assuan_funopen(void *cookie,
- cookie_read_function_t *readfn,
- cookie_write_function_t *writefn,
- cookie_seek_function_t *seekfn,
- cookie_close_function_t *closefn);
-#define funopen(a,r,w,s,c) _assuan_funopen ((a), (r), (w), (s), (c))
-#endif /*HAVE_FOPENCOOKIE*/
-
-#endif /*ASSUAN_DEFS_H*/
-
diff --git a/util/assuan-errors.c b/util/assuan-errors.c
deleted file mode 100644
index c3a8770cb..000000000
--- a/util/assuan-errors.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/* assuan-errors.c - error codes
- * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
- * Copyright (C) 2005 Free Software Foundation, Inc.
- *
- * This file is part of Assuan.
- *
- * Assuan is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Assuan is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-/* Please note that this is a stripped down and modified version of
- the orginal Assuan code from libassuan. */
-
-#include <stdio.h>
-#include "assuan.h"
-
-/* This function returns a textual representaion of the given error
- code. If this is an unknown value, a string with the value is
- returned (Beware: it is hold in a static buffer). Return value:
- String with the error description.
- */
-const char *
-assuan_strerror (assuan_error_t err)
-{
- const char *s;
- static char buf[50];
-
- switch (err)
- {
- case ASSUAN_No_Error: s="no error"; break;
- case ASSUAN_General_Error: s="general error"; break;
- case ASSUAN_Out_Of_Core: s="out of core"; break;
- case ASSUAN_Invalid_Value: s="invalid value"; break;
- case ASSUAN_Timeout: s="timeout"; break;
- case ASSUAN_Read_Error: s="read error"; break;
- case ASSUAN_Write_Error: s="write error"; break;
- case ASSUAN_Problem_Starting_Server: s="problem starting server"; break;
- case ASSUAN_Not_A_Server: s="not a server"; break;
- case ASSUAN_Not_A_Client: s="not a client"; break;
- case ASSUAN_Nested_Commands: s="nested commands"; break;
- case ASSUAN_Invalid_Response: s="invalid response"; break;
- case ASSUAN_No_Data_Callback: s="no data callback"; break;
- case ASSUAN_No_Inquire_Callback: s="no inquire callback"; break;
- case ASSUAN_Connect_Failed: s="connect failed"; break;
- case ASSUAN_Accept_Failed: s="accept failed"; break;
- case ASSUAN_Not_Implemented: s="not implemented"; break;
- case ASSUAN_Server_Fault: s="server fault"; break;
- case ASSUAN_Invalid_Command: s="invalid command"; break;
- case ASSUAN_Unknown_Command: s="unknown command"; break;
- case ASSUAN_Syntax_Error: s="syntax error"; break;
- case ASSUAN_Parameter_Error: s="parameter error"; break;
- case ASSUAN_Parameter_Conflict: s="parameter conflict"; break;
- case ASSUAN_Line_Too_Long: s="line too long"; break;
- case ASSUAN_Line_Not_Terminated: s="line not terminated"; break;
- case ASSUAN_No_Input: s="no input"; break;
- case ASSUAN_No_Output: s="no output"; break;
- case ASSUAN_Canceled: s="canceled"; break;
- case ASSUAN_Unsupported_Algorithm: s="unsupported algorithm"; break;
- case ASSUAN_Server_Resource_Problem: s="server resource problem"; break;
- case ASSUAN_Server_IO_Error: s="server io error"; break;
- case ASSUAN_Server_Bug: s="server bug"; break;
- case ASSUAN_No_Data_Available: s="no data available"; break;
- case ASSUAN_Invalid_Data: s="invalid data"; break;
- case ASSUAN_Unexpected_Command: s="unexpected command"; break;
- case ASSUAN_Too_Much_Data: s="too much data"; break;
- case ASSUAN_Inquire_Unknown: s="inquire unknown"; break;
- case ASSUAN_Inquire_Error: s="inquire error"; break;
- case ASSUAN_Invalid_Option: s="invalid option"; break;
- case ASSUAN_Invalid_Index: s="invalid index"; break;
- case ASSUAN_Unexpected_Status: s="unexpected status"; break;
- case ASSUAN_Unexpected_Data: s="unexpected data"; break;
- case ASSUAN_Invalid_Status: s="invalid status"; break;
- case ASSUAN_Locale_Problem: s="locale problem"; break;
- case ASSUAN_Not_Confirmed: s="not confirmed"; break;
- case ASSUAN_USER_ERROR_FIRST: s="user error first"; break;
- case ASSUAN_USER_ERROR_LAST: s="user error last"; break;
- default:
- {
- unsigned int source, code;
-
- source = ((err >> 24) & 0xff);
- code = (err & 0x00ffffff);
- if (source) /* Assume this is an libgpg-error. */
- sprintf (buf, "ec=%u.%u", source, code );
- else
- sprintf (buf, "ec=%d", err );
- s=buf; break;
- }
- }
-
- return s;
-}
-
diff --git a/util/assuan-logging.c b/util/assuan-logging.c
deleted file mode 100644
index f2d6c876d..000000000
--- a/util/assuan-logging.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/* assuan-logging.c - Default logging function.
- * Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
- *
- * This file is part of Assuan.
- *
- * Assuan is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Assuan is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-/* Please note that this is a stripped down and modified version of
- the orginal Assuan code from libassuan. */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#ifdef HAVE_W32_SYSTEM
-#include <windows.h>
-#endif /*HAVE_W32_SYSTEM*/
-
-#include "assuan-defs.h"
-
-static char prefix_buffer[80];
-static FILE *_assuan_log;
-
-void
-_assuan_set_default_log_stream (FILE *fp)
-{
- if (!_assuan_log)
- _assuan_log = fp;
-}
-
-void
-assuan_set_assuan_log_stream (FILE *fp)
-{
- _assuan_log = fp;
-}
-
-FILE *
-assuan_get_assuan_log_stream (void)
-{
- return _assuan_log ? _assuan_log : stderr;
-}
-
-
-/* Set the prefix to be used for logging to TEXT or
- resets it to the default if TEXT is NULL. */
-void
-assuan_set_assuan_log_prefix (const char *text)
-{
- if (text)
- {
- strncpy (prefix_buffer, text, sizeof (prefix_buffer)-1);
- prefix_buffer[sizeof (prefix_buffer)-1] = 0;
- }
- else
- *prefix_buffer = 0;
-}
-
-const char *
-assuan_get_assuan_log_prefix (void)
-{
- return prefix_buffer;
-}
-
-
-void
-_assuan_log_printf (const char *format, ...)
-{
- va_list arg_ptr;
- FILE *fp;
- const char *prf;
-
- fp = assuan_get_assuan_log_stream ();
- prf = assuan_get_assuan_log_prefix ();
- if (*prf)
- {
- fputs (prf, fp);
- fputs (": ", fp);
- }
-
- va_start (arg_ptr, format);
- vfprintf (fp, format, arg_ptr );
- va_end (arg_ptr);
-}
-
-
-
-#ifdef HAVE_W32_SYSTEM
-const char *
-_assuan_w32_strerror (int ec)
-{
- static char strerr[256];
-
- if (ec == -1)
- ec = (int)GetLastError ();
- FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec,
- MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
- strerr, sizeof (strerr)-1, NULL);
- return strerr;
-}
-#endif /*HAVE_W32_SYSTEM*/
diff --git a/util/assuan-socket-connect.c b/util/assuan-socket-connect.c
deleted file mode 100644
index 0c580cd5f..000000000
--- a/util/assuan-socket-connect.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/* assuan-socket-connect.c - Assuan socket based client
- * Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
- *
- * This file is part of Assuan.
- *
- * Assuan is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Assuan is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-/* Please note that this is a stripped down and modified version of
- the orginal Assuan code from libassuan. */
-
-#include <config.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/types.h>
-#ifndef HAVE_W32_SYSTEM
-#include <sys/socket.h>
-#include <sys/un.h>
-#else
-#include <windows.h>
-#endif
-
-#include "assuan-defs.h"
-
-/* Hacks for Slowaris. */
-#ifndef PF_LOCAL
-# ifdef PF_UNIX
-# define PF_LOCAL PF_UNIX
-# else
-# define PF_LOCAL AF_UNIX
-# endif
-#endif
-#ifndef AF_LOCAL
-# define AF_LOCAL AF_UNIX
-#endif
-
-#ifndef SUN_LEN
-# define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
- + strlen ((ptr)->sun_path))
-#endif
-
-
-static int
-do_finish (assuan_context_t ctx)
-{
- if (ctx->inbound.fd != -1)
- {
- _assuan_close (ctx->inbound.fd);
- }
- ctx->inbound.fd = -1;
- ctx->outbound.fd = -1;
- return 0;
-}
-
-static void
-do_deinit (assuan_context_t ctx)
-{
- do_finish (ctx);
-}
-
-
-static ssize_t
-simple_read (assuan_context_t ctx, void *buffer, size_t size)
-{
-#ifndef HAVE_W32_SYSTEM
- return read (ctx->inbound.fd, buffer, size);
-#else
- return recv (ctx->inbound.fd, buffer, size, 0);
-#endif
-}
-
-static ssize_t
-simple_write (assuan_context_t ctx, const void *buffer, size_t size)
-{
-#ifndef HAVE_W32_SYSTEM
- return write (ctx->outbound.fd, buffer, size);
-#else
- return send (ctx->outbound.fd, buffer, size, 0);
-#endif
-}
-
-
-/* Make a connection to the Unix domain socket NAME and return a new
- Assuan context in CTX. SERVER_PID is currently not used but may
- become handy in the future. */
-assuan_error_t
-assuan_socket_connect (assuan_context_t *r_ctx,
- const char *name, pid_t server_pid)
-{
- static struct assuan_io io = { simple_read, simple_write };
-
- assuan_error_t err;
- assuan_context_t ctx;
- int fd;
- struct sockaddr_un srvr_addr;
- size_t len;
- const char *s;
-
- if (!r_ctx || !name)
- return ASSUAN_Invalid_Value;
- *r_ctx = NULL;
-
- /* We require that the name starts with a slash, so that we can
- alter reuse this function for other socket types. To make things
- easier we allow an optional dirver prefix. */
- s = name;
- if (*s && s[1] == ':')
- s += 2;
- if (*s != DIRSEP_C && *s != '/')
- return ASSUAN_Invalid_Value;
-
- if (strlen (name)+1 >= sizeof srvr_addr.sun_path)
- return ASSUAN_Invalid_Value;
-
- err = _assuan_new_context (&ctx);
- if (err)
- return err;
- ctx->deinit_handler = do_deinit;
- ctx->finish_handler = do_finish;
-
-
- fd = _assuan_sock_new (PF_LOCAL, SOCK_STREAM, 0);
- if (fd == -1)
- {
- _assuan_log_printf ("can't create socket: %s\n", strerror (errno));
- _assuan_release_context (ctx);
- return ASSUAN_General_Error;
- }
-
- memset (&srvr_addr, 0, sizeof srvr_addr);
- srvr_addr.sun_family = AF_LOCAL;
- strncpy (srvr_addr.sun_path, name, sizeof (srvr_addr.sun_path) - 1);
- srvr_addr.sun_path[sizeof (srvr_addr.sun_path) - 1] = 0;
- len = SUN_LEN (&srvr_addr);
-
-
- if (_assuan_sock_connect (fd, (struct sockaddr *) &srvr_addr, len) == -1)
- {
- _assuan_log_printf ("can't connect to `%s': %s\n",
- name, strerror (errno));
- _assuan_release_context (ctx);
- _assuan_close (fd);
- return ASSUAN_Connect_Failed;
- }
-
- ctx->inbound.fd = fd;
- ctx->outbound.fd = fd;
- ctx->io = &io;
-
- /* initial handshake */
- {
- int okay, off;
-
- err = _assuan_read_from_server (ctx, &okay, &off);
- if (err)
- _assuan_log_printf ("can't connect to server: %s\n",
- assuan_strerror (err));
- else if (okay != 1)
- {
- /*LOG ("can't connect to server: `");*/
- _assuan_log_sanitized_string (ctx->inbound.line);
- fprintf (assuan_get_assuan_log_stream (), "'\n");
- err = ASSUAN_Connect_Failed;
- }
- }
-
- if (err)
- {
- assuan_disconnect (ctx);
- }
- else
- *r_ctx = ctx;
- return 0;
-}
diff --git a/util/assuan-socket.c b/util/assuan-socket.c
deleted file mode 100644
index 4d79792ce..000000000
--- a/util/assuan-socket.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/* assuan-socket.c
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-/* Please note that this is a stripped down and modified version of
- the orginal Assuan code from libassuan. */
-
-#include <config.h>
-#include <stdio.h>
-#ifdef HAVE_W32_SYSTEM
-#include <windows.h>
-#include <io.h>
-#else
-#include <sys/types.h>
-#include <sys/socket.h>
-#endif
-#include "assuan-defs.h"
-
-int
-_assuan_close (int fd)
-{
-#ifndef HAVE_W32_SYSTEM
- return close (fd);
-#else
- int rc = closesocket (fd);
- if (rc && WSAGetLastError () == WSAENOTSOCK)
- rc = close (fd);
- return rc;
-#endif
-}
-
-
-int
-_assuan_sock_new (int domain, int type, int proto)
-{
-#ifndef HAVE_W32_SYSTEM
- return socket (domain, type, proto);
-#else
- if (domain == AF_UNIX || domain == AF_LOCAL)
- domain = AF_INET;
- return socket (domain, type, proto);
-#endif
-}
-
-
-int
-_assuan_sock_connect (int sockfd, struct sockaddr * addr, int addrlen)
-{
-#ifndef HAVE_W32_SYSTEM
- return connect (sockfd, addr, addrlen);
-#else
- struct sockaddr_in myaddr;
- struct sockaddr_un * unaddr;
- FILE * fp;
- int port = 0;
-
- unaddr = (struct sockaddr_un *)addr;
- fp = fopen (unaddr->sun_path, "rb");
- if (!fp)
- return -1;
- fscanf (fp, "%d", &port);
- fclose (fp);
- /* XXX: set errno in this case */
- if (port < 0 || port > 65535)
- return -1;
-
- myaddr.sin_family = AF_INET;
- myaddr.sin_port = port;
- myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
-
- /* we need this later. */
- unaddr->sun_family = myaddr.sin_family;
- unaddr->sun_port = myaddr.sin_port;
- unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
-
- return connect (sockfd, (struct sockaddr *)&myaddr, sizeof myaddr);
-#endif
-}
-
-
diff --git a/util/assuan-util.c b/util/assuan-util.c
deleted file mode 100644
index db3cb7232..000000000
--- a/util/assuan-util.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/* assuan-util.c - Utility functions for Assuan
- * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
- * Copyright (C) 2005 Free Software Foundation, Inc.
- *
- * This file is part of Assuan.
- *
- * Assuan is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * Assuan is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-/* Please note that this is a stripped down and modified version of
- the orginal Assuan code from libassuan. */
-
-#include <config.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "assuan-defs.h"
-
-
-
-/* Store the error in the context so that the error sending function
- can take out a descriptive text. Inside the assuan code, use the
- macro set_error instead of this function. */
-int
-assuan_set_error (assuan_context_t ctx, int err, const char *text)
-{
- ctx->err_no = err;
- ctx->err_str = text;
- return err;
-}
-
-void
-assuan_set_pointer (assuan_context_t ctx, void *pointer)
-{
- if (ctx)
- ctx->user_pointer = pointer;
-}
-
-void *
-assuan_get_pointer (assuan_context_t ctx)
-{
- return ctx? ctx->user_pointer : NULL;
-}
-
-
-void
-assuan_set_log_stream (assuan_context_t ctx, FILE *fp)
-{
- if (ctx)
- {
- if (ctx->log_fp)
- fflush (ctx->log_fp);
- ctx->log_fp = fp;
- _assuan_set_default_log_stream (fp);
- }
-}
-
-
-void
-assuan_begin_confidential (assuan_context_t ctx)
-{
- if (ctx)
- {
- ctx->confidential = 1;
- }
-}
-
-void
-assuan_end_confidential (assuan_context_t ctx)
-{
- if (ctx)
- {
- ctx->confidential = 0;
- }
-}
-
-/* Dump a possibly binary string (used for debugging). Distinguish
- ascii text from binary and print it accordingly. */
-void
-_assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length)
-{
- const unsigned char *s;
- int n;
-
- for (n=length,s=buffer; n; n--, s++)
- if ((!isascii (*s) || iscntrl (*s) || !isprint (*s)) && !(*s >= 0x80))
- break;
-
- s = buffer;
- if (!n && *s != '[')
- fwrite (buffer, length, 1, fp);
- else
- {
- putc ('[', fp);
- for (n=0; n < length; n++, s++)
- fprintf (fp, " %02x", *s);
- putc (' ', fp);
- putc (']', fp);
- }
-}
-
-/* Log a user supplied string. Escapes non-printable before
- printing. */
-void
-_assuan_log_sanitized_string (const char *string)
-{
- const unsigned char *s = string;
- FILE *fp = assuan_get_assuan_log_stream ();
-
- if (! *s)
- return;
-
- for (; *s; s++)
- {
- int c = 0;
-
- switch (*s)
- {
- case '\r':
- c = 'r';
- break;
-
- case '\n':
- c = 'n';
- break;
-
- case '\f':
- c = 'f';
- break;
-
- case '\v':
- c = 'v';
- break;
-
- case '\b':
- c = 'b';
- break;
-
- default:
- if ((isascii (*s) && isprint (*s)) || (*s >= 0x80))
- putc (*s, fp);
- else
- {
- putc ('\\', fp);
- fprintf (fp, "x%02x", *s);
- }
- }
-
- if (c)
- {
- putc ('\\', fp);
- putc (c, fp);
- }
- }
-}
-
diff --git a/util/cert.c b/util/cert.c
deleted file mode 100644
index 1b3390b80..000000000
--- a/util/cert.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/* cert.c - DNS CERT code
- * Copyright (C) 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <config.h>
-#include <sys/types.h>
-#ifdef USE_DNS_CERT
-#ifdef _WIN32
-#include <windows.h>
-#else
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-#endif
-#include <string.h>
-#include "memory.h"
-#endif
-#include "iobuf.h"
-#include "util.h"
-
-/* Not every installation has gotten around to supporting CERTs
- yet... */
-#ifndef T_CERT
-#define T_CERT 37
-#endif
-
-#ifdef USE_DNS_CERT
-
-/* Returns -1 on error, 0 for no answer, 1 for PGP provided and 2 for
- IPGP provided. */
-int
-get_cert(const char *name,size_t max_size,IOBUF *iobuf,
- unsigned char **fpr,size_t *fpr_len,char **url)
-{
- unsigned char *answer;
- int r,ret=-1;
- u16 count;
-
- if(fpr)
- *fpr=NULL;
-
- if(url)
- *url=NULL;
-
- answer=xmalloc(max_size);
-
- r=res_query(name,C_IN,T_CERT,answer,max_size);
- /* Not too big, not too small, no errors and at least 1 answer. */
- if(r>=sizeof(HEADER) && r<=max_size
- && (((HEADER *)answer)->rcode)==NOERROR
- && (count=ntohs(((HEADER *)answer)->ancount)))
- {
- int rc;
- unsigned char *pt,*emsg;
-
- emsg=&answer[r];
-
- pt=&answer[sizeof(HEADER)];
-
- /* Skip over the query */
-
- rc=dn_skipname(pt,emsg);
- if(rc==-1)
- goto fail;
-
- pt+=rc+QFIXEDSZ;
-
- /* There are several possible response types for a CERT request.
- We're interested in the PGP (a key) and IPGP (a URI) types.
- Skip all others. TODO: A key is better than a URI since
- we've gone through all this bother to fetch it, so favor that
- if we have both PGP and IPGP? */
-
- while(count-->0 && pt<emsg)
- {
- u16 type,class,dlen,ctype;
-
- rc=dn_skipname(pt,emsg); /* the name we just queried for */
- if(rc==-1)
- break;
-
- pt+=rc;
-
- /* Truncated message? 15 bytes takes us to the point where
- we start looking at the ctype. */
- if((emsg-pt)<15)
- break;
-
- type=*pt++ << 8;
- type|=*pt++;
-
- class=*pt++ << 8;
- class|=*pt++;
- /* We asked for IN and got something else !? */
- if(class!=C_IN)
- break;
-
- /* ttl */
- pt+=4;
-
- /* data length */
- dlen=*pt++ << 8;
- dlen|=*pt++;
-
- /* We asked for CERT and got something else - might be a
- CNAME, so loop around again. */
- if(type!=T_CERT)
- {
- pt+=dlen;
- continue;
- }
-
- /* The CERT type */
- ctype=*pt++ << 8;
- ctype|=*pt++;
-
- /* Skip the CERT key tag and algo which we don't need. */
- pt+=3;
-
- dlen-=5;
-
- /* 15 bytes takes us to here */
-
- if(ctype==3 && iobuf && dlen)
- {
- /* PGP type */
- *iobuf=iobuf_temp_with_content((char *)pt,dlen);
- ret=1;
- break;
- }
- else if(ctype==6 && dlen && dlen<1023 && dlen>=pt[0]+1
- && fpr && fpr_len && url)
- {
- /* IPGP type */
- *fpr_len=pt[0];
-
- if(*fpr_len)
- {
- *fpr=xmalloc(*fpr_len);
- memcpy(*fpr,&pt[1],*fpr_len);
- }
- else
- *fpr=NULL;
-
- if(dlen>*fpr_len+1)
- {
- *url=xmalloc(dlen-(*fpr_len+1)+1);
- memcpy(*url,&pt[*fpr_len+1],dlen-(*fpr_len+1));
- (*url)[dlen-(*fpr_len+1)]='\0';
- }
- else
- *url=NULL;
-
- ret=2;
- break;
- }
-
- /* Neither type matches, so go around to the next answer. */
- pt+=dlen;
- }
- }
-
- fail:
- xfree(answer);
-
- return ret;
-}
-
-#else /* !USE_DNS_CERT */
-
-int
-get_cert(const char *name,size_t max_size,IOBUF *iobuf,
- unsigned char **fpr,size_t *fpr_len,char **url)
-{
- return -1;
-}
-
-#endif
-
-/* Test with simon.josefsson.org */
-
-#ifdef TEST
-int
-main(int argc,char *argv[])
-{
- unsigned char *fpr;
- size_t fpr_len;
- char *url;
- int rc;
- IOBUF iobuf;
-
- if(argc!=2)
- {
- printf("cert-test [name]\n");
- return 1;
- }
-
- printf("CERT lookup on %s\n",argv[1]);
-
- rc=get_cert(argv[1],16384,&iobuf,&fpr,&fpr_len,&url);
- if(rc==-1)
- printf("error\n");
- else if(rc==0)
- printf("no answer\n");
- else if(rc==1)
- {
- printf("key found: %d bytes\n",(int)iobuf_get_temp_length(iobuf));
- iobuf_close(iobuf);
- }
- else if(rc==2)
- {
- if(fpr)
- {
- size_t i;
- printf("Fingerprint found (%d bytes): ",(int)fpr_len);
- for(i=0;i<fpr_len;i++)
- printf("%02X",fpr[i]);
- printf("\n");
- }
- else
- printf("No fingerprint found\n");
-
- if(url)
- printf("URL found: %s\n",url);
- else
- printf("No URL found\n");
-
- xfree(fpr);
- xfree(url);
- }
-
- return 0;
-}
-#endif /* TEST */
diff --git a/util/dotlock.c b/util/dotlock.c
deleted file mode 100644
index 9edac57ed..000000000
--- a/util/dotlock.c
+++ /dev/null
@@ -1,454 +0,0 @@
-/* dotlock.c - dotfile locking
- * Copyright (C) 1998, 1999, 2000, 2001, 2004,
- * 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <config.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <errno.h>
-#include <unistd.h>
-#if !defined (HAVE_DOSISH_SYSTEM)
-#include <sys/utsname.h>
-#endif
-#include <sys/types.h>
-#ifndef _WIN32
-#include <sys/time.h>
-#endif
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <signal.h>
-#include "types.h"
-#include "util.h"
-#include "memory.h"
-
-struct dotlock_handle {
- struct dotlock_handle *next;
- char *tname; /* name of lockfile template */
- char *lockname; /* name of the real lockfile */
- int locked; /* lock status */
- int disable; /* locking */
-};
-
-
-static volatile DOTLOCK all_lockfiles;
-static int never_lock;
-
-void
-disable_dotlock(void)
-{
- never_lock = 1;
-}
-
-/****************
- * Create a lockfile with the given name and return an object of
- * type DOTLOCK which may be used later to actually do the lock.
- * A cleanup routine gets installed to cleanup left over locks
- * or other files used together with the lockmechanism.
- * Althoug the function is called dotlock, this does not necessarily
- * mean that real lockfiles are used - the function may decide to
- * use fcntl locking. Calling the function with NULL only install
- * the atexit handler and maybe used to assure that the cleanup
- * is called after all other atexit handlers.
- *
- * Notes: This function creates a lock file in the same directory
- * as file_to_lock with the name "file_to_lock.lock"
- * A temporary file ".#lk.<hostname>.pid[.threadid] is used.
- * This function does nothing for Windoze.
- */
-DOTLOCK
-create_dotlock( const char *file_to_lock )
-{
- static int initialized;
- DOTLOCK h;
-#if !defined (HAVE_DOSISH_SYSTEM)
- int fd = -1;
- char pidstr[16];
- struct utsname utsbuf;
- const char *nodename;
- const char *dirpart;
- int dirpartlen;
-#endif
-
- if( !initialized ) {
- atexit( remove_lockfiles );
- initialized = 1;
- }
- if( !file_to_lock )
- return NULL;
-
- h = xmalloc_clear( sizeof *h );
- if( never_lock ) {
- h->disable = 1;
-#ifdef _REENTRANT
- /* fixme: aquire mutex on all_lockfiles */
-#endif
- h->next = all_lockfiles;
- all_lockfiles = h;
- return h;
- }
-
-
-#if !defined (HAVE_DOSISH_SYSTEM)
- sprintf( pidstr, "%10d\n", (int)getpid() );
- /* fixme: add the hostname to the second line (FQDN or IP addr?) */
-
- /* create a temporary file */
- if( uname( &utsbuf ) )
- nodename = "unknown";
- else
- nodename = utsbuf.nodename;
-
-#ifdef __riscos__
- {
- char *iter = (char *) nodename;
- for (; iter[0]; iter++)
- if (iter[0] == '.')
- iter[0] = '/';
- }
-#endif /* __riscos__ */
-
- if( !(dirpart = strrchr( file_to_lock, DIRSEP_C )) ) {
- dirpart = EXTSEP_S;
- dirpartlen = 1;
- }
- else {
- dirpartlen = dirpart - file_to_lock;
- dirpart = file_to_lock;
- }
-
-#ifdef _REENTRANT
- /* fixme: aquire mutex on all_lockfiles */
-#endif
- h->next = all_lockfiles;
- all_lockfiles = h;
-
- h->tname = xmalloc( dirpartlen + 6+30+ strlen(nodename) + 11 );
-#ifndef __riscos__
- sprintf( h->tname, "%.*s/.#lk%p.%s.%d",
- dirpartlen, dirpart, (void *)h, nodename, (int)getpid() );
-#else /* __riscos__ */
- sprintf( h->tname, "%.*s.lk%p/%s/%d",
- dirpartlen, dirpart, (void *)h, nodename, (int)getpid() );
-#endif /* __riscos__ */
-
- do {
- errno = 0;
- fd = open( h->tname, O_WRONLY|O_CREAT|O_EXCL,
- S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR );
- } while( fd == -1 && errno == EINTR );
- if( fd == -1 ) {
- all_lockfiles = h->next;
- log_error( "failed to create temporary file `%s': %s\n",
- h->tname, strerror(errno));
- xfree(h->tname);
- xfree(h);
- return NULL;
- }
- if( write(fd, pidstr, 11 ) != 11 ) {
- all_lockfiles = h->next;
-#ifdef _REENTRANT
- /* release mutex */
-#endif
- log_fatal( "error writing to `%s': %s\n", h->tname, strerror(errno) );
- close(fd);
- unlink(h->tname);
- xfree(h->tname);
- xfree(h);
- return NULL;
- }
- if( close(fd) ) {
- all_lockfiles = h->next;
-#ifdef _REENTRANT
- /* release mutex */
-#endif
- log_error( "error closing `%s': %s\n", h->tname, strerror(errno));
- unlink(h->tname);
- xfree(h->tname);
- xfree(h);
- return NULL;
- }
-
-#ifdef _REENTRANT
- /* release mutex */
-#endif
-#endif
- h->lockname = xmalloc( strlen(file_to_lock) + 6 );
- strcpy(stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock");
- return h;
-}
-
-
-void
-destroy_dotlock ( DOTLOCK h )
-{
-#if !defined (HAVE_DOSISH_SYSTEM)
- if ( h )
- {
- DOTLOCK hprev, htmp;
-
- /* First remove the handle from our global list of all locks. */
- for (hprev=NULL, htmp=all_lockfiles; htmp; hprev=htmp, htmp=htmp->next)
- if (htmp == h)
- {
- if (hprev)
- hprev->next = htmp->next;
- else
- all_lockfiles = htmp->next;
- h->next = NULL;
- break;
- }
-
- /* Second destroy the lock. */
- if (!h->disable)
- {
- if (h->locked && h->lockname)
- unlink (h->lockname);
- if (h->tname)
- unlink (h->tname);
- xfree (h->tname);
- xfree (h->lockname);
- }
- xfree(h);
-
- }
-#endif
-}
-
-#ifndef HAVE_DOSISH_SYSTEM
-
-static int
-maybe_deadlock( DOTLOCK h )
-{
- DOTLOCK r;
-
- for( r=all_lockfiles; r; r = r->next ) {
- if( r != h && r->locked )
- return 1;
- }
- return 0;
-}
-
-/****************
- * Read the lock file and return the pid, returns -1 on error.
- */
-static int
-read_lockfile( const char *name )
-{
- int fd, pid;
- char pidstr[16];
-
- if( (fd = open(name, O_RDONLY)) == -1 ) {
- int e = errno;
- log_debug("error opening lockfile `%s': %s\n", name, strerror(errno) );
- errno = e;
- return -1;
- }
- if( read(fd, pidstr, 10 ) != 10 ) { /* Read 10 digits w/o newline */
- log_debug("error reading lockfile `%s'", name );
- close(fd);
- errno = 0;
- return -1;
- }
- pidstr[10] = 0; /* terminate pid string */
- close(fd);
- pid = atoi(pidstr);
-#ifndef __riscos__
- if( !pid || pid == -1 ) {
-#else /* __riscos__ */
- if( (!pid && riscos_getpid()) || pid == -1 ) {
-#endif /* __riscos__ */
- log_error("invalid pid %d in lockfile `%s'", pid, name );
- errno = 0;
- return -1;
- }
- return pid;
-}
-#endif /* !HAVE_DOSISH_SYSTEM */
-
-/****************
- * Do a lock on H. A TIMEOUT of 0 returns immediately,
- * -1 waits forever (hopefully not), other
- * values are timeouts in milliseconds.
- * Returns: 0 on success
- */
-int
-make_dotlock( DOTLOCK h, long timeout )
-{
-#if defined (HAVE_DOSISH_SYSTEM)
- return 0;
-#else
- int pid;
- const char *maybe_dead="";
- int backoff=0;
-
- if( h->disable ) {
- return 0;
- }
-
- if( h->locked ) {
-#ifndef __riscos__
- log_debug("oops, `%s' is already locked\n", h->lockname );
-#endif /* !__riscos__ */
- return 0;
- }
-
- for(;;) {
-#ifndef __riscos__
- if( !link(h->tname, h->lockname) ) {
- /* fixme: better use stat to check the link count */
- h->locked = 1;
- return 0; /* okay */
- }
- if( errno != EEXIST ) {
- log_error( "lock not made: link() failed: %s\n", strerror(errno) );
- return -1;
- }
-#else /* __riscos__ */
- if( !riscos_renamefile(h->tname, h->lockname) ) {
- h->locked = 1;
- return 0; /* okay */
- }
- if( errno != EEXIST ) {
- log_error( "lock not made: rename() failed: %s\n", strerror(errno) );
- return -1;
- }
-#endif /* __riscos__ */
- if( (pid = read_lockfile(h->lockname)) == -1 ) {
- if( errno != ENOENT ) {
- log_info("cannot read lockfile\n");
- return -1;
- }
- log_info( "lockfile disappeared\n");
- continue;
- }
- else if( pid == getpid() ) {
- log_info( "Oops: lock already held by us\n");
- h->locked = 1;
- return 0; /* okay */
- }
- else if( kill(pid, 0) && errno == ESRCH ) {
-#ifndef __riscos__
- maybe_dead = " - probably dead";
-#if 0 /* we should not do this without checking the permissions */
- /* and the hostname */
- log_info( "removing stale lockfile (created by %d)", pid );
-#endif
-#else /* __riscos__ */
- /* we are *pretty* sure that the other task is dead and therefore
- we remove the other lock file */
- maybe_dead = " - probably dead - removing lock";
- unlink(h->lockname);
-#endif /* __riscos__ */
- }
- if( timeout == -1 ) {
- struct timeval tv;
- log_info( "waiting for lock (held by %d%s) %s...\n",
- pid, maybe_dead, maybe_deadlock(h)? "(deadlock?) ":"");
-
-
- /* can't use sleep, cause signals may be blocked */
- tv.tv_sec = 1 + backoff;
- tv.tv_usec = 0;
- select(0, NULL, NULL, NULL, &tv);
- if( backoff < 10 )
- backoff++ ;
- }
- else
- return -1;
- }
- /*not reached */
-#endif
-}
-
-
-/****************
- * release a lock
- * Returns: 0 := success
- */
-int
-release_dotlock( DOTLOCK h )
-{
-#if defined (HAVE_DOSISH_SYSTEM)
- return 0;
-#else
- int pid;
-
- /* To avoid atexit race conditions we first check whether there
- are any locks left. It might happen that another atexit
- handler tries to release the lock while the atexit handler of
- this module already ran and thus H is undefined. */
- if(!all_lockfiles)
- return 0;
-
- if( h->disable )
- return 0;
-
- if( !h->locked ) {
- log_debug("oops, `%s' is not locked\n", h->lockname );
- return 0;
- }
-
- pid = read_lockfile( h->lockname );
- if( pid == -1 ) {
- log_error( "release_dotlock: lockfile error\n");
- return -1;
- }
- if( pid != getpid() ) {
- log_error( "release_dotlock: not our lock (pid=%d)\n", pid);
- return -1;
- }
-#ifndef __riscos__
- if( unlink( h->lockname ) ) {
- log_error( "release_dotlock: error removing lockfile `%s'",
- h->lockname);
- return -1;
- }
-#else /* __riscos__ */
- if( riscos_renamefile(h->lockname, h->tname) ) {
- log_error( "release_dotlock: error renaming lockfile `%s' to `%s'",
- h->lockname, h->tname);
- return -1;
- }
-#endif /* __riscos__ */
- /* fixme: check that the link count is now 1 */
- h->locked = 0;
- return 0;
-#endif
-}
-
-void
-remove_lockfiles()
-{
-#if !defined (HAVE_DOSISH_SYSTEM)
- DOTLOCK h, h2;
-
- h = all_lockfiles;
- all_lockfiles = NULL;
-
- while( h ) {
- h2 = h->next;
- destroy_dotlock (h);
- h = h2;
- }
-#endif
-}
diff --git a/util/errors.c b/util/errors.c
deleted file mode 100644
index 75498f80e..000000000
--- a/util/errors.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/* errors.c - error strings
- * Copyright (C) 1998, 1999, 2000, 2001 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-#include "errors.h"
-#include "i18n.h"
-
-#ifndef HAVE_STRERROR
-char *
-strerror( int n )
-{
- extern char *sys_errlist[];
- extern int sys_nerr;
- static char buf[15];
-
- if( n >= 0 && n < sys_nerr )
- return sys_errlist[n];
- strcpy( buf, "Unknown error" );
- return buf;
-}
-#endif /* !HAVE_STRERROR */
-
-const char *
-g10_errstr( int err )
-{
- static char buf[50];
- const char *p;
-
-#define X(n,s) case G10ERR_##n : p = s; break;
- switch( err ) {
- case -1: p = "eof"; break;
- case 0: p = "okay"; break;
- X(GENERAL, N_("general error"))
- X(UNKNOWN_PACKET, N_("unknown packet type"))
- X(UNKNOWN_VERSION,N_("unknown version"))
- X(PUBKEY_ALGO ,N_("unknown pubkey algorithm"))
- X(DIGEST_ALGO ,N_("unknown digest algorithm"))
- X(BAD_PUBKEY ,N_("bad public key"))
- X(BAD_SECKEY ,N_("bad secret key"))
- X(BAD_SIGN ,N_("bad signature"))
- X(CHECKSUM , N_("checksum error"))
- X(BAD_PASS , N_("bad passphrase"))
- X(NO_PUBKEY ,N_("public key not found"))
- X(CIPHER_ALGO ,N_("unknown cipher algorithm"))
- X(KEYRING_OPEN ,N_("can't open the keyring"))
- X(INVALID_PACKET ,N_("invalid packet"))
- X(INVALID_ARMOR ,N_("invalid armor"))
- X(NO_USER_ID ,N_("no such user id"))
- X(NO_SECKEY ,N_("secret key not available"))
- X(WRONG_SECKEY ,N_("wrong secret key used"))
- X(UNSUPPORTED ,N_("not supported"))
- X(BAD_KEY ,N_("bad key"))
- X(READ_FILE ,N_("file read error"))
- X(WRITE_FILE ,N_("file write error"))
- X(COMPR_ALGO ,N_("unknown compress algorithm"))
- X(OPEN_FILE ,N_("file open error"))
- X(CREATE_FILE ,N_("file create error"))
- X(PASSPHRASE ,N_("invalid passphrase"))
- X(NI_PUBKEY ,N_("unimplemented pubkey algorithm"))
- X(NI_CIPHER ,N_("unimplemented cipher algorithm"))
- X(SIG_CLASS ,N_("unknown signature class"))
- X(TRUSTDB ,N_("trust database error"))
- X(BAD_MPI ,N_("bad MPI"))
- X(RESOURCE_LIMIT ,N_("resource limit"))
- X(INV_KEYRING ,N_("invalid keyring"))
- X(BAD_CERT ,N_("bad certificate"))
- X(INV_USER_ID ,N_("malformed user id"))
- X(CLOSE_FILE ,N_("file close error"))
- X(RENAME_FILE ,N_("file rename error"))
- X(DELETE_FILE ,N_("file delete error"))
- X(UNEXPECTED ,N_("unexpected data"))
- X(TIME_CONFLICT ,N_("timestamp conflict"))
- X(WR_PUBKEY_ALGO ,N_("unusable pubkey algorithm"))
- X(FILE_EXISTS ,N_("file exists"))
- X(WEAK_KEY ,N_("weak key"))
- X(INV_ARG ,N_("invalid argument"))
- X(BAD_URI ,N_("bad URI"))
- X(INVALID_URI ,N_("unsupported URI"))
- X(NETWORK ,N_("network error"))
- X(SELFTEST_FAILED,"selftest failed")
- X(NOT_ENCRYPTED ,N_("not encrypted"))
- X(NOT_PROCESSED ,N_("not processed"))
- /* the key cannot be used for a specific usage */
- X(UNU_PUBKEY ,N_("unusable public key"))
- X(UNU_SECKEY ,N_("unusable secret key"))
- X(KEYSERVER ,N_("keyserver error"))
- X(CANCELED ,N_("canceled"))
- X(NO_CARD ,N_("no card"))
- X(NO_DATA ,N_("no data"))
- default: p = buf; sprintf(buf, "g10err=%d", err); break;
- }
-#undef X
- return _(p);
-}
diff --git a/util/fileutil.c b/util/fileutil.c
deleted file mode 100644
index 5834e3d89..000000000
--- a/util/fileutil.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/* fileutil.c - file utilities
- * Copyright (C) 1998, 2003, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <assert.h>
-#include <unistd.h>
-#include <sys/types.h>
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-#include "util.h"
-#include "memory.h"
-#include "ttyio.h"
-
-
-/***************
- * Extract from a given path the filename component.
- *
- */
-char *
-make_basename(const char *filepath, const char *inputpath)
-{
-#ifdef __riscos__
- return riscos_make_basename(filepath, inputpath);
-#endif
-
- char *p;
-
- if ( !(p=strrchr(filepath, DIRSEP_C)) )
-#ifdef HAVE_DRIVE_LETTERS
- if ( !(p=strrchr(filepath, '\\')) )
- if ( !(p=strrchr(filepath, ':')) )
-#endif
- {
- return xstrdup(filepath);
- }
-
- return xstrdup(p+1);
-}
-
-
-
-/***************
- * Extract from a given filename the path prepended to it.
- * If their isn't a path prepended to the filename, a dot
- * is returned ('.').
- *
- */
-char *
-make_dirname(const char *filepath)
-{
- char *dirname;
- int dirname_length;
- char *p;
-
- if ( !(p=strrchr(filepath, DIRSEP_C)) )
-#ifdef HAVE_DRIVE_LETTERS
- if ( !(p=strrchr(filepath, '\\')) )
- if ( !(p=strrchr(filepath, ':')) )
-#endif
- {
- return xstrdup(EXTSEP_S);
- }
-
- dirname_length = p-filepath;
- dirname = xmalloc(dirname_length+1);
- strncpy(dirname, filepath, dirname_length);
- dirname[dirname_length] = 0;
-
- return dirname;
-}
-
-/* Expand tildes. Handles both the ~/foo and ~username/foo cases.
- Returns what the tilde expands to. *name is advanced to be past
- the tilde expansion. */
-static char *
-untilde(const char **name)
-{
- char *home=NULL;
-
- assert((*name)[0]=='~');
-
- if((*name)[1]==DIRSEP_C || (*name)[1]=='\0')
- {
- /* This is the "~/foo" or "~" case. */
- char *tmp=getenv("HOME");
- if(tmp)
- home=xstrdup(tmp);
-
-#ifdef HAVE_GETPWUID
- if(!home)
- {
- struct passwd *pwd;
-
- pwd=getpwuid(getuid());
- if(pwd)
- home=xstrdup(pwd->pw_dir);
- }
-#endif
- if(home)
- (*name)++;
- }
-#ifdef HAVE_GETPWNAM
- else
- {
- /* This is the "~username" case. */
- char *user,*sep;
- struct passwd *pwd;
-
- user=xstrdup((*name)+1);
-
- sep=strchr(user,DIRSEP_C);
- if(sep)
- *sep='\0';
-
- pwd=getpwnam(user);
- if(pwd)
- {
- home=xstrdup(pwd->pw_dir);
- (*name)+=1+strlen(user);
- }
-
- xfree(user);
- }
-#endif
-
- return home;
-}
-
-/*
- Construct a filename from the NULL terminated list of parts. Tilde
- expansion is done here. Note that FIRST_PART must never be NULL and
- that this function is guaranteed to return an allocated string. */
-char *
-make_filename( const char *first_part, ... )
-{
- va_list arg_ptr ;
- size_t n;
- const char *s;
- char *name, *p, *home=NULL;
-
- va_start( arg_ptr, first_part ) ;
- n = strlen(first_part)+1;
- while( (s=va_arg(arg_ptr, const char *)) )
- n += strlen(s) + 1;
- va_end(arg_ptr);
-
-#ifndef __riscos__
- if(*first_part=='~')
- {
- home=untilde(&first_part);
- if(home)
- n+=strlen(home);
- }
-#endif
- name = xmalloc(n);
- p = home ? stpcpy(stpcpy(name,home), first_part)
- : stpcpy(name, first_part);
- va_start( arg_ptr, first_part ) ;
- while( (s=va_arg(arg_ptr, const char *)) )
- p = stpcpy(stpcpy(p, DIRSEP_S), s);
- va_end(arg_ptr);
- xfree(home);
-
-#ifndef __riscos__
- return name;
-#else /* __riscos__ */
- p = riscos_gstrans(name);
- xfree(name);
- return p;
-#endif /* __riscos__ */
-}
-
-
-int
-compare_filenames( const char *a, const char *b )
-{
- /* ? check whether this is an absolute filename and
- * resolve symlinks?
- */
-#ifndef __riscos__
-#ifdef HAVE_DRIVE_LETTERS
- return ascii_strcasecmp(a,b);
-#else
- return strcmp(a,b);
-#endif
-#else /* __riscos__ */
- int c = 0;
- char *abuf, *bbuf;
-
- abuf = riscos_gstrans(a);
- bbuf = riscos_gstrans(b);
-
- c = ascii_strcasecmp (abuf, bbuf);
-
- xfree(abuf);
- xfree(bbuf);
-
- return c;
-#endif /* __riscos__ */
-}
-
-
-/****************
- * A simple function to decide whether the filename is stdout
- * or a real filename.
- */
-const char *
-print_fname_stdout( const char *s )
-{
- if( !s || (*s == '-' && !s[1]) )
- return "[stdout]";
- return s;
-}
-
-
-const char *
-print_fname_stdin( const char *s )
-{
- if( !s || (*s == '-' && !s[1]) )
- return "[stdin]";
- return s;
-}
-
-/****************
- * Check if the file is compressed.
- **/
-int
-is_file_compressed( const char *s, int *ret_rc )
-{
- IOBUF a;
- byte buf[4];
- int i, rc = 0;
- int overflow;
-
- struct magic_compress_s {
- size_t len;
- byte magic[4];
- } magic[] = {
- { 3, { 0x42, 0x5a, 0x68, 0x00 } }, /* bzip2 */
- { 3, { 0x1f, 0x8b, 0x08, 0x00 } }, /* gzip */
- { 4, { 0x50, 0x4b, 0x03, 0x04 } }, /* (pk)zip */
- };
-
- if ( iobuf_is_pipe_filename (s) || !ret_rc )
- return 0; /* We can't check stdin or no file was given */
-
- a = iobuf_open( s );
- if ( a == NULL ) {
- *ret_rc = G10ERR_OPEN_FILE;
- return 0;
- }
-
- if ( iobuf_get_filelength( a, &overflow ) < 4 && !overflow) {
- *ret_rc = 0;
- goto leave;
- }
-
- if ( iobuf_read( a, buf, 4 ) == -1 ) {
- *ret_rc = G10ERR_READ_FILE;
- goto leave;
- }
-
- for ( i = 0; i < DIM( magic ); i++ ) {
- if ( !memcmp( buf, magic[i].magic, magic[i].len ) ) {
- *ret_rc = 0;
- rc = 1;
- break;
- }
- }
-
-leave:
- iobuf_close( a );
- return rc;
-}
diff --git a/util/http.c b/util/http.c
deleted file mode 100644
index 41000024f..000000000
--- a/util/http.c
+++ /dev/null
@@ -1,1076 +0,0 @@
-/* http.c - HTTP protocol handler
- * Copyright (C) 1999, 2001, 2002, 2003, 2004,
- * 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-
-#ifdef _WIN32
-#include <windows.h>
-#else
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <time.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#endif
-
-#include "util.h"
-#include "iobuf.h"
-#include "i18n.h"
-#include "http.h"
-#include "srv.h"
-
-#ifdef _WIN32
-#define sock_close(a) closesocket(a)
-#else
-#define sock_close(a) close(a)
-#endif
-
-#define MAX_LINELEN 20000 /* max. length of a HTTP line */
-#define VALID_URI_CHARS "abcdefghijklmnopqrstuvwxyz" \
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
- "01234567890@" \
- "!\"#$%&'()*+,-./:;<=>?[\\]^_{|}~"
-
-#ifndef EAGAIN
-#define EAGAIN EWOULDBLOCK
-#endif
-
-static int parse_uri( PARSED_URI *ret_uri, const char *uri );
-static void release_parsed_uri( PARSED_URI uri );
-static int do_parse_uri( PARSED_URI uri, int only_local_part );
-static int remove_escapes( byte *string );
-static int insert_escapes( byte *buffer, const byte *string,
- const byte *special );
-static URI_TUPLE parse_tuple( byte *string );
-static int send_request( HTTP_HD hd, const char *auth, const char *proxy );
-static byte *build_rel_path( PARSED_URI uri );
-static int parse_response( HTTP_HD hd );
-
-static int connect_server( const char *server, ushort port, unsigned int flags,
- const char *srvtag );
-static int write_server( int sock, const char *data, size_t length );
-
-#ifdef _WIN32
-static void
-deinit_sockets (void)
-{
- WSACleanup();
-}
-
-static void
-init_sockets (void)
-{
- static int initialized;
- static WSADATA wsdata;
-
- if (initialized)
- return;
-
- if( WSAStartup( 0x0101, &wsdata ) ) {
- log_error ("error initializing socket library: ec=%d\n",
- (int)WSAGetLastError () );
- return;
- }
- if( wsdata.wVersion < 0x0001 ) {
- log_error ("socket library version is %x.%x - but 1.1 needed\n",
- LOBYTE(wsdata.wVersion), HIBYTE(wsdata.wVersion));
- WSACleanup();
- return;
- }
- atexit ( deinit_sockets );
- initialized = 1;
-}
-#endif /*_WIN32*/
-
-static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789+/";
-
-/****************
- * create a radix64 encoded string.
- */
-
-/* TODO: This is a duplicate of code in g10/armor.c modified to do the
- "=" padding. Better to use a single copy in strgutil.c ? */
-static char *
-make_radix64_string( const byte *data, size_t len )
-{
- char *buffer, *p;
-
- buffer = p = xmalloc( (len+2)/3*4 + 1 );
- for( ; len >= 3 ; len -= 3, data += 3 ) {
- *p++ = bintoasc[(data[0] >> 2) & 077];
- *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
- *p++ = bintoasc[(((data[1]<<2)&074)|((data[2]>>6)&03))&077];
- *p++ = bintoasc[data[2]&077];
- }
- if( len == 2 ) {
- *p++ = bintoasc[(data[0] >> 2) & 077];
- *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
- *p++ = bintoasc[((data[1]<<2)&074)];
- *p++ = '=';
- }
- else if( len == 1 ) {
- *p++ = bintoasc[(data[0] >> 2) & 077];
- *p++ = bintoasc[(data[0] <<4)&060];
- *p++ = '=';
- *p++ = '=';
- }
- *p = 0;
- return buffer;
-}
-
-int
-http_open( HTTP_HD hd, HTTP_REQ_TYPE reqtype, const char *url,
- char *auth, unsigned int flags, const char *proxy )
-{
- int rc;
-
- if( !(reqtype == HTTP_REQ_GET || reqtype == HTTP_REQ_POST) )
- return G10ERR_INV_ARG;
-
- /* initialize the handle */
- memset( hd, 0, sizeof *hd );
- hd->sock = -1;
- hd->initialized = 1;
- hd->req_type = reqtype;
- hd->flags = flags;
-
- rc = parse_uri( &hd->uri, url );
- if( !rc ) {
- rc = send_request( hd, auth, proxy );
- if( !rc ) {
- hd->fp_write = iobuf_sockopen( hd->sock , "w" );
- if( hd->fp_write )
- return 0;
- rc = G10ERR_GENERAL;
- }
- }
-
- if( !hd->fp_read && !hd->fp_write && hd->sock != -1 )
- sock_close( hd->sock );
- iobuf_close( hd->fp_read );
- iobuf_close( hd->fp_write);
- release_parsed_uri( hd->uri );
- hd->initialized = 0;
-
- return rc;
-}
-
-
-void
-http_start_data( HTTP_HD hd )
-{
- iobuf_flush ( hd->fp_write );
- if( !hd->in_data ) {
- write_server (hd->sock, "\r\n", 2);
- hd->in_data = 1;
- }
-}
-
-
-int
-http_wait_response( HTTP_HD hd, unsigned int *ret_status )
-{
- int rc;
-
- http_start_data( hd ); /* make sure that we are in the data */
-
-#if 0
- hd->sock = dup( hd->sock );
- if( hd->sock == -1 )
- return G10ERR_GENERAL;
-#endif
- iobuf_ioctl (hd->fp_write, 1, 1, NULL); /* keep the socket open */
- iobuf_close (hd->fp_write);
- hd->fp_write = NULL;
- if ( !(hd->flags & HTTP_FLAG_NO_SHUTDOWN) )
- shutdown( hd->sock, 1 );
- hd->in_data = 0;
-
- hd->fp_read = iobuf_sockopen( hd->sock , "r" );
- if( !hd->fp_read )
- return G10ERR_GENERAL;
-
- rc = parse_response( hd );
- if( !rc && ret_status )
- *ret_status = hd->status_code;
-
- return rc;
-}
-
-
-int
-http_open_document( HTTP_HD hd, const char *document, char *auth,
- unsigned int flags, const char *proxy )
-{
- int rc;
-
- rc = http_open(hd, HTTP_REQ_GET, document, auth, flags, proxy );
- if( rc )
- return rc;
-
- rc = http_wait_response( hd, NULL );
- if( rc )
- http_close( hd );
-
- return rc;
-}
-
-
-void
-http_close( HTTP_HD hd )
-{
- if( !hd || !hd->initialized )
- return;
- if( !hd->fp_read && !hd->fp_write && hd->sock != -1 )
- sock_close( hd->sock );
- iobuf_close( hd->fp_read );
- iobuf_close( hd->fp_write );
- release_parsed_uri( hd->uri );
- xfree( hd->buffer );
- hd->initialized = 0;
-}
-
-
-
-/****************
- * Parse an URI and put the result into the newly allocated ret_uri.
- * The caller must always use release_parsed_uri to releases the
- * resources (even on an error).
- */
-static int
-parse_uri( PARSED_URI *ret_uri, const char *uri )
-{
- *ret_uri = xmalloc_clear( sizeof(**ret_uri) + strlen(uri) );
- strcpy( (*ret_uri)->buffer, uri );
- return do_parse_uri( *ret_uri, 0 );
-}
-
-static void
-release_parsed_uri( PARSED_URI uri )
-{
- if( uri )
- {
- URI_TUPLE r, r2;
-
- for( r = uri->query; r; r = r2 ) {
- r2 = r->next;
- xfree( r );
- }
- xfree( uri );
- }
-}
-
-static int
-do_parse_uri( PARSED_URI uri, int only_local_part )
-{
- URI_TUPLE *tail;
- char *p, *p2, *p3;
- int n;
-
- p = uri->buffer;
- n = strlen( uri->buffer );
- /* initialize all fields to an empty string or an empty list */
- uri->scheme = uri->host = uri->path = p + n;
- uri->port = 0;
- uri->params = uri->query = NULL;
-
- /* a quick validity check */
- if( strspn( p, VALID_URI_CHARS) != n )
- return G10ERR_BAD_URI; /* invalid characters found */
-
- if( !only_local_part ) {
- /* find the scheme */
- if( !(p2 = strchr( p, ':' ) ) || p2 == p )
- return G10ERR_BAD_URI; /* No scheme */
- *p2++ = 0;
- strlwr( p );
- uri->scheme = p;
- if(strcmp(uri->scheme,"http")==0)
- uri->port = 80;
- else if(strcmp(uri->scheme,"hkp")==0)
- uri->port = 11371;
- else
- return G10ERR_INVALID_URI; /* Unsupported scheme */
-
- p = p2;
-
- /* find the hostname */
- if( *p != '/' )
- return G10ERR_INVALID_URI; /* does not start with a slash */
-
- p++;
- if( *p == '/' ) { /* there seems to be a hostname */
- p++;
- if( (p2 = strchr(p, '/')) )
- *p2++ = 0;
-
- /* Check for username/password encoding */
- if((p3=strchr(p,'@')))
- {
- uri->auth=p;
- *p3++='\0';
- p=p3;
- }
-
- strlwr( p );
- uri->host = p;
- if( (p3=strchr( p, ':' )) ) {
- *p3++ = 0;
- uri->port = atoi( p3 );
- }
-
- uri->host = p;
- if( (n = remove_escapes( uri->host )) < 0 )
- return G10ERR_BAD_URI;
- if( n != strlen( p ) )
- return G10ERR_BAD_URI; /* hostname with a Nul in it */
- p = p2 ? p2 : NULL;
- }
- } /* end global URI part */
-
- /* parse the pathname part */
- if( !p || !*p ) /* we don't have a path */
- return 0; /* and this is okay */
-
- /* todo: here we have to check params */
-
- /* do we have a query part */
- if( (p2 = strchr( p, '?' )) )
- *p2++ = 0;
-
- uri->path = p;
- if( (n = remove_escapes( p )) < 0 )
- return G10ERR_BAD_URI;
- if( n != strlen( p ) )
- return G10ERR_BAD_URI; /* path with a Nul in it */
- p = p2 ? p2 : NULL;
-
- if( !p || !*p ) /* we don't have a query string */
- return 0; /* okay */
-
- /* now parse the query string */
- tail = &uri->query;
- for(;;) {
- URI_TUPLE elem;
-
- if( (p2 = strchr( p, '&' )) )
- *p2++ = 0;
- if( !(elem = parse_tuple( p )) )
- return G10ERR_BAD_URI;
- *tail = elem;
- tail = &elem->next;
-
- if( !p2 )
- break; /* ready */
- p = p2;
- }
-
- return 0;
-}
-
-
-
-/****************
- * Remove all %xx escapes; this is done inplace.
- * Returns: new length of the string.
- */
-static int
-remove_escapes( byte *string )
-{
- int n = 0;
- byte *p, *s;
-
- for(p=s=string; *s ; s++ ) {
- if( *s == '%' ) {
- if( s[1] && s[2] && isxdigit(s[1]) && isxdigit(s[2]) ) {
- s++;
- *p = *s >= '0' && *s <= '9' ? *s - '0' :
- *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10 ;
- *p <<= 4;
- s++;
- *p |= *s >= '0' && *s <= '9' ? *s - '0' :
- *s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : *s - 'a' + 10 ;
- p++;
- n++;
- }
- else {
- *p++ = *s++;
- if( *s )
- *p++ = *s++;
- if( *s )
- *p++ = *s++;
- if( *s )
- *p = 0;
- return -1; /* bad URI */
- }
- }
- else
- {
- *p++ = *s;
- n++;
- }
- }
- *p = 0; /* always keep a string terminator */
- return n;
-}
-
-
-static int
-insert_escapes( byte *buffer, const byte *string, const byte *special )
-{
- int n = 0;
-
- for( ; *string; string++ ) {
- if( strchr( VALID_URI_CHARS, *string )
- && !strchr( special, *string ) ) {
- if( buffer )
- *buffer++ = *string;
- n++;
- }
- else {
- if( buffer ) {
- sprintf( buffer, "%%%02X", *string );
- buffer += 3;
- }
- n += 3;
- }
- }
- return n;
-}
-
-
-static URI_TUPLE
-parse_tuple( byte *string )
-{
- byte *p = string;
- byte *p2;
- int n;
- URI_TUPLE tuple;
-
- if( (p2 = strchr( p, '=' )) )
- *p2++ = 0;
- if( (n = remove_escapes( p )) < 0 )
- return NULL; /* bad URI */
- if( n != strlen( p ) )
- return NULL; /* name with a Nul in it */
- tuple = xmalloc_clear( sizeof *tuple );
- tuple->name = p;
- if( !p2 ) {
- /* we have only the name, so we assume an empty value string */
- tuple->value = p + strlen(p);
- tuple->valuelen = 0;
- }
- else { /* name and value */
- if( (n = remove_escapes( p2 )) < 0 ) {
- xfree( tuple );
- return NULL; /* bad URI */
- }
- tuple->value = p2;
- tuple->valuelen = n;
- }
- return tuple;
-}
-
-
-/****************
- * Send a HTTP request to the server
- * Returns 0 if the request was successful
- */
-static int
-send_request( HTTP_HD hd, const char *auth, const char *proxy )
-{
- const byte *server;
- byte *request, *p;
- ushort port;
- int rc;
- char *proxy_authstr=NULL,*authstr=NULL;
-
- server = *hd->uri->host? hd->uri->host : "localhost";
- port = hd->uri->port? hd->uri->port : 80;
-
- if(proxy && *proxy)
- {
- PARSED_URI uri;
-
- rc = parse_uri( &uri, proxy );
- if (rc)
- {
- log_error("invalid HTTP proxy (%s): %s\n",proxy,g10_errstr(rc));
- release_parsed_uri( uri );
- return G10ERR_NETWORK;
- }
- hd->sock = connect_server( *uri->host? uri->host : "localhost",
- uri->port? uri->port : 80, 0, NULL );
- if(uri->auth)
- {
- char *x;
- remove_escapes(uri->auth);
- x=make_radix64_string(uri->auth,strlen(uri->auth));
- proxy_authstr=xmalloc(52+strlen(x));
- sprintf(proxy_authstr,"Proxy-Authorization: Basic %s\r\n",x);
- xfree(x);
- }
-
- release_parsed_uri( uri );
- }
- else
- hd->sock = connect_server( server, port, hd->flags, hd->uri->scheme );
-
- if(auth || hd->uri->auth)
- {
- char *x,*tempauth=NULL;
-
- if(auth)
- {
- tempauth=xstrdup(auth);
- remove_escapes(tempauth);
- }
- else if(hd->uri->auth)
- remove_escapes(hd->uri->auth);
-
- x=make_radix64_string(tempauth?tempauth:hd->uri->auth,
- strlen(tempauth?tempauth:hd->uri->auth));
- authstr=xmalloc(52+strlen(x));
- sprintf(authstr,"Authorization: Basic %s\r\n",x);
- xfree(x);
- xfree(tempauth);
- }
-
- if( hd->sock == -1 )
- return G10ERR_NETWORK;
-
- p = build_rel_path( hd->uri );
-
- request=xmalloc(strlen(server)*2 + strlen(p)
- + (authstr?strlen(authstr):0)
- + (proxy_authstr?strlen(proxy_authstr):0) + 65);
- if( proxy && *proxy )
- sprintf( request, "%s http://%s:%hu%s%s HTTP/1.0\r\n%s%s",
- hd->req_type == HTTP_REQ_GET ? "GET" :
- hd->req_type == HTTP_REQ_HEAD? "HEAD":
- hd->req_type == HTTP_REQ_POST? "POST": "OOPS",
- server, port, *p == '/'? "":"/", p,
- authstr?authstr:"",proxy_authstr?proxy_authstr:"" );
- else
- {
- char portstr[15];
-
- if(port!=80)
- sprintf(portstr,":%u",port);
-
- sprintf( request, "%s %s%s HTTP/1.0\r\nHost: %s%s\r\n%s",
- hd->req_type == HTTP_REQ_GET ? "GET" :
- hd->req_type == HTTP_REQ_HEAD? "HEAD":
- hd->req_type == HTTP_REQ_POST? "POST": "OOPS",
- *p == '/'? "":"/", p, server, (port!=80)?portstr:"",
- authstr?authstr:"");
- }
-
- xfree(p);
-
- rc = write_server( hd->sock, request, strlen(request) );
- xfree( request );
- xfree(proxy_authstr);
- xfree(authstr);
-
- return rc;
-}
-
-
-/****************
- * Build the relative path from the parsed URI.
- * Minimal implementation.
- */
-static byte*
-build_rel_path( PARSED_URI uri )
-{
- URI_TUPLE r;
- byte *rel_path, *p;
- int n;
-
- /* count the needed space */
- n = insert_escapes( NULL, uri->path, "%;?&" );
- /* todo: build params */
- for( r=uri->query; r; r = r->next ) {
- n++; /* '?'/'&' */
- n += insert_escapes( NULL, r->name, "%;?&=" );
- n++; /* '='*/
- n += insert_escapes( NULL, r->value, "%;?&=" );
- }
- n++;
-
- /* now allocate and copy */
- p = rel_path = xmalloc( n );
- n = insert_escapes( p, uri->path, "%;?&" );
- p += n;
- /* todo: add params */
- for( r=uri->query; r; r = r->next ) {
- *p++ = r == uri->query? '?':'&';
- n = insert_escapes( p, r->name, "%;?&=" );
- p += n;
- *p++ = '=';
- /* todo: use valuelen */
- n = insert_escapes( p, r->value, "%;?&=" );
- p += n;
- }
- *p = 0;
- return rel_path;
-}
-
-
-
-/***********************
- * Parse the response from a server.
- * Returns: errorcode and sets some fileds in the handle
- */
-static int
-parse_response( HTTP_HD hd )
-{
- byte *line, *p, *p2;
- unsigned maxlen, len;
-
- /* Wait for the status line */
- do {
- maxlen = MAX_LINELEN;
- len = iobuf_read_line( hd->fp_read, &hd->buffer,
- &hd->buffer_size, &maxlen );
- line = hd->buffer;
- if( !maxlen )
- return -1; /* line has been truncated */
- if( !len )
- return -1; /* eof */
- } while( !*line );
-
- if( (p = strchr( line, '/')) )
- *p++ = 0;
- if( !p || strcmp( line, "HTTP" ) )
- return 0; /* assume http 0.9 */
-
- if( (p2 = strpbrk( p, " \t" ) ) ) {
- *p2++ = 0;
- p2 += strspn( p2, " \t" );
- }
- if( !p2 )
- return 0; /* assume http 0.9 */
- p = p2;
- /* todo: add HTTP version number check here */
- if( (p2 = strpbrk( p, " \t" ) ) )
- *p2++ = 0;
- if( !isdigit(p[0]) || !isdigit(p[1]) || !isdigit(p[2]) || p[3] ) {
- /* malformed HTTP statuscode - assume HTTP 0.9 */
- hd->is_http_0_9 = 1;
- hd->status_code = 200;
- return 0;
- }
- hd->status_code = atoi( p );
-
- /* skip all the header lines and wait for the empty line */
- do {
- maxlen = MAX_LINELEN;
- len = iobuf_read_line( hd->fp_read, &hd->buffer,
- &hd->buffer_size, &maxlen );
- line = hd->buffer;
- /* we ignore truncated lines */
- if( !len )
- return -1; /* eof */
- /* time lineendings */
- if( (*line == '\r' && line[1] == '\n') || *line == '\n' )
- *line = 0;
- } while( len && *line );
-
- return 0;
-}
-
-#ifdef TEST
-static int
-start_server()
-{
- struct sockaddr_in mya;
- struct sockaddr_in peer;
- int fd, client;
- fd_set rfds;
- int addrlen;
- int i;
-
- if( (fd=socket(AF_INET,SOCK_STREAM, 0)) == -1 ) {
- log_error("socket() failed: %s\n", strerror(errno));
- return -1;
- }
- i = 1;
- if( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, (byte*)&i, sizeof(i) ) )
- log_info("setsockopt(SO_REUSEADDR) failed: %s\n", strerror(errno) );
-
- mya.sin_family=AF_INET;
- memset(&mya.sin_addr, 0, sizeof(mya.sin_addr));
- mya.sin_port=htons(11371);
-
- if( bind( fd, (struct sockaddr *)&mya, sizeof(mya)) ) {
- log_error("bind to port 11371 failed: %s\n", strerror(errno) );
- sock_close( fd );
- return -1;
- }
-
- if( listen( fd, 5 ) ) {
- log_error("listen failed: %s\n", strerror(errno) );
- sock_close( fd );
- return -1;
- }
-
- for(;;) {
- FD_ZERO(&rfds);
- FD_SET( fd, &rfds );
-
- if( select( fd+1, &rfds, NULL, NULL, NULL) <= 0 )
- continue; /* ignore any errors */
-
- if( !FD_ISSET( fd, &rfds ) )
- continue;
-
- addrlen = sizeof peer;
- client = accept( fd, (struct sockaddr *)&peer, &addrlen);
- if( client == -1 )
- continue; /* oops */
-
- log_info("connect from %s\n", inet_ntoa( peer.sin_addr ) );
-
- fflush(stdout);
- fflush(stderr);
- if( !fork() ) {
- int c;
- FILE *fp;
-
- fp = fdopen( client , "r" );
- while( (c=getc(fp)) != EOF )
- putchar(c);
- fclose(fp);
- exit(0);
- }
- sock_close( client );
- }
-
-
- return 0;
-}
-#endif
-
-
-static int
-connect_server( const char *server, ushort port, unsigned int flags,
- const char *srvtag )
-{
- int sock=-1,srv,srvcount=0,connected=0,hostfound=0;
- struct srventry *srvlist=NULL;
-
-#ifdef _WIN32
- unsigned long inaddr;
-
- init_sockets();
- /* Win32 gethostbyname doesn't handle IP addresses internally, so we
- try inet_addr first on that platform only. */
- if((inaddr=inet_addr(server))!=INADDR_NONE)
- {
- struct sockaddr_in addr;
-
- memset(&addr,0,sizeof(addr));
-
- if((sock=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET)
- {
- log_error("error creating socket: ec=%d\n",(int)WSAGetLastError());
- return -1;
- }
-
- addr.sin_family=AF_INET;
- addr.sin_port=htons(port);
- memcpy(&addr.sin_addr,&inaddr,sizeof(inaddr));
-
- if(connect(sock,(struct sockaddr *)&addr,sizeof(addr))==0)
- return sock;
- else
- {
- sock_close(sock);
- return -1;
- }
- }
-#endif
-
-#ifdef USE_DNS_SRV
- /* Do the SRV thing */
- if(flags&HTTP_FLAG_TRY_SRV && srvtag)
- {
- /* We're using SRV, so append the tags */
- if(1+strlen(srvtag)+6+strlen(server)+1<=MAXDNAME)
- {
- char srvname[MAXDNAME];
-
- strcpy(srvname,"_");
- strcat(srvname,srvtag);
- strcat(srvname,"._tcp.");
- strcat(srvname,server);
- srvcount=getsrv(srvname,&srvlist);
- }
- }
-#endif
-
- if(srvlist==NULL)
- {
- /* Either we're not using SRV, or the SRV lookup failed. Make
- up a fake SRV record. */
- srvlist=xmalloc_clear(sizeof(struct srventry));
- srvlist->port=port;
- strncpy(srvlist->target,server,MAXDNAME);
- srvlist->target[MAXDNAME-1]='\0';
- srvcount=1;
- }
-
-#ifdef HAVE_GETADDRINFO
-
- for(srv=0;srv<srvcount;srv++)
- {
- struct addrinfo hints,*res,*ai;
- char portstr[6];
-
- sprintf(portstr,"%u",srvlist[srv].port);
- memset(&hints,0,sizeof(hints));
- hints.ai_socktype=SOCK_STREAM;
- if(getaddrinfo(srvlist[srv].target,portstr,&hints,&res)==0)
- hostfound=1;
- else
- continue;
-
- for(ai=res;ai;ai=ai->ai_next)
- {
- if((sock=socket(ai->ai_family,ai->ai_socktype,ai->ai_protocol))==-1)
- {
- log_error("error creating socket: %s\n",strerror(errno));
- freeaddrinfo(res);
- return -1;
- }
-
- if(connect(sock,ai->ai_addr,ai->ai_addrlen)==0)
- {
- connected=1;
- break;
- }
-
- sock_close(sock);
- }
-
- freeaddrinfo(res);
-
- if(ai)
- break;
- }
-
-#else /* !HAVE_GETADDRINFO */
-
- for(srv=0;srv<srvcount;srv++)
- {
- int i=0;
- struct hostent *host=NULL;
- struct sockaddr_in addr;
-
- memset(&addr,0,sizeof(addr));
-
- if((host=gethostbyname(srvlist[srv].target))==NULL)
- continue;
-
- hostfound=1;
-
- if((sock=socket(host->h_addrtype,SOCK_STREAM,0))==-1)
- {
- log_error("error creating socket: %s\n",strerror(errno));
- return -1;
- }
-
- addr.sin_family=host->h_addrtype;
- if(addr.sin_family!=AF_INET)
- {
- log_error("%s: unknown address family\n",srvlist[srv].target);
- return -1;
- }
-
- addr.sin_port=htons(srvlist[srv].port);
-
- /* Try all A records until one responds. */
- while(host->h_addr_list[i])
- {
- if(host->h_length!=4)
- {
- log_error("%s: illegal address length\n",srvlist[srv].target);
- return -1;
- }
-
- memcpy(&addr.sin_addr,host->h_addr_list[i],host->h_length);
-
- if(connect(sock,(struct sockaddr *)&addr,sizeof(addr))==0)
- {
- connected=1;
- break;
- }
-
- i++;
- }
-
- if(host->h_addr_list[i])
- break;
-
- sock_close(sock);
- }
-#endif /* !HAVE_GETADDRINFO */
-
- xfree(srvlist);
-
- if(!connected)
- {
- int err=errno;
-#ifdef _WIN32
- if(hostfound)
- log_error("%s: Unable to connect: ec=%d\n",server,(int)WSAGetLastError());
- else
- log_error("%s: Host not found: ec=%d\n",server,(int)WSAGetLastError());
-#else
- if(hostfound)
- log_error("%s: %s\n",server,strerror(err));
- else
- log_error("%s: Host not found\n",server);
-#endif
- if(sock!=-1)
- sock_close(sock);
- errno=err;
- return -1;
- }
-
- return sock;
-}
-
-
-static int
-write_server( int sock, const char *data, size_t length )
-{
- int nleft;
-
- nleft = length;
- while( nleft > 0 ) {
-#ifdef _WIN32
- int nwritten;
-
- nwritten = send (sock, data, nleft, 0);
- if ( nwritten == SOCKET_ERROR ) {
- log_info ("write failed: ec=%d\n", (int)WSAGetLastError ());
- return G10ERR_NETWORK;
- }
-#else
- int nwritten = write( sock, data, nleft );
- if( nwritten == -1 ) {
- if( errno == EINTR )
- continue;
- if( errno == EAGAIN ) {
- struct timeval tv;
-
- tv.tv_sec = 0;
- tv.tv_usec = 50000;
- select(0, NULL, NULL, NULL, &tv);
- continue;
- }
- log_info("write failed: %s\n", strerror(errno));
- return G10ERR_NETWORK;
- }
-#endif
- nleft -=nwritten;
- data += nwritten;
- }
-
- return 0;
-}
-
-/**** Test code ****/
-#ifdef TEST
-
-int
-main(int argc, char **argv)
-{
- int rc;
- PARSED_URI uri;
- URI_TUPLE r;
- struct http_context hd;
- int c;
-
- log_set_name("http-test");
- if( argc == 1 ) {
- start_server();
- return 0;
- }
-
- if( argc != 2 ) {
- fprintf(stderr,"usage: http-test uri\n");
- return 1;
- }
- argc--; argv++;
-
- rc = parse_uri( &uri, *argv );
- if( rc ) {
- log_error("`%s': %s\n", *argv, g10_errstr(rc));
- release_parsed_uri( uri );
- return 1;
- }
-
- printf("Scheme: %s\n", uri->scheme );
- printf("Host : %s\n", uri->host );
- printf("Port : %u\n", uri->port );
- printf("Path : %s\n", uri->path );
- for( r=uri->params; r; r = r->next ) {
- printf("Params: %s=%s", r->name, r->value );
- if( strlen( r->value ) != r->valuelen )
- printf(" [real length=%d]", (int)r->valuelen );
- putchar('\n');
- }
- for( r=uri->query; r; r = r->next ) {
- printf("Query : %s=%s", r->name, r->value );
- if( strlen( r->value ) != r->valuelen )
- printf(" [real length=%d]", (int)r->valuelen );
- putchar('\n');
- }
- release_parsed_uri( uri ); uri = NULL;
-
- rc = http_open_document( &hd, *argv, 0, NULL );
- if( rc ) {
- log_error("can't get `%s': %s\n", *argv, g10_errstr(rc));
- return 1;
- }
- log_info("open_http_document succeeded; status=%u\n", hd.status_code );
- while( (c=iobuf_get( hd.fp_read)) != -1 )
- putchar(c);
- http_close( &hd );
- return 0;
-}
-#endif /*TEST*/
diff --git a/util/iobuf.c b/util/iobuf.c
deleted file mode 100644
index f6e817c42..000000000
--- a/util/iobuf.c
+++ /dev/null
@@ -1,2276 +0,0 @@
-/* iobuf.c - file handling
- * Copyright (C) 1998, 1999, 2000, 2001, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#ifdef HAVE_DOSISH_SYSTEM
-#include <windows.h>
-#endif
-#ifdef __riscos__
-#include <kernel.h>
-#include <swis.h>
-#endif /* __riscos__ */
-
-#include "memory.h"
-#include "util.h"
-#include "dynload.h"
-#include "iobuf.h"
-
-/* The size of the internal buffers.
- NOTE: If you change this value you MUST also adjust the regression
- test "armored_key_8192" in armor.test! */
-#define IOBUF_BUFFER_SIZE 8192
-
-
-#undef FILE_FILTER_USES_STDIO
-
-#ifdef HAVE_DOSISH_SYSTEM
-#define USE_SETMODE 1
-#endif
-
-#ifdef FILE_FILTER_USES_STDIO
-#define my_fileno(a) fileno ((a))
-#define my_fopen_ro(a,b) fopen ((a),(b))
-#define my_fopen(a,b) fopen ((a),(b))
-typedef FILE *FILEP_OR_FD;
-#define INVALID_FP NULL
-#define FILEP_OR_FD_FOR_STDIN (stdin)
-#define FILEP_OR_FD_FOR_STDOUT (stdout)
-typedef struct {
- FILE *fp; /* open file handle */
- int keep_open;
- int no_cache;
- int print_only_name; /* flags indicating that fname is not a real file*/
- char fname[1]; /* name of the file */
- } file_filter_ctx_t ;
-#else
-#define my_fileno(a) (a)
-#define my_fopen_ro(a,b) fd_cache_open ((a),(b))
-#define my_fopen(a,b) direct_open ((a),(b))
-#ifdef HAVE_DOSISH_SYSTEM
-typedef HANDLE FILEP_OR_FD;
-#define INVALID_FP ((HANDLE)-1)
-#define FILEP_OR_FD_FOR_STDIN (GetStdHandle (STD_INPUT_HANDLE))
-#define FILEP_OR_FD_FOR_STDOUT (GetStdHandle (STD_OUTPUT_HANDLE))
-#undef USE_SETMODE
-#else
-typedef int FILEP_OR_FD;
-#define INVALID_FP (-1)
-#define FILEP_OR_FD_FOR_STDIN (0)
-#define FILEP_OR_FD_FOR_STDOUT (1)
-#endif
-typedef struct {
- FILEP_OR_FD fp; /* open file handle */
- int keep_open;
- int no_cache;
- int eof_seen;
- int print_only_name; /* flags indicating that fname is not a real file*/
- char fname[1]; /* name of the file */
- } file_filter_ctx_t ;
-
- struct close_cache_s {
- struct close_cache_s *next;
- FILEP_OR_FD fp;
- char fname[1];
- };
- typedef struct close_cache_s *CLOSE_CACHE;
- static CLOSE_CACHE close_cache;
-#endif
-
-#ifdef _WIN32
-typedef struct {
- int sock;
- int keep_open;
- int no_cache;
- int eof_seen;
- int print_only_name; /* flags indicating that fname is not a real file*/
- char fname[1]; /* name of the file */
-} sock_filter_ctx_t ;
-#endif /*_WIN32*/
-
-/* The first partial length header block must be of size 512
- * to make it easier (and efficienter) we use a min. block size of 512
- * for all chunks (but the last one) */
-#define OP_MIN_PARTIAL_CHUNK 512
-#define OP_MIN_PARTIAL_CHUNK_2POW 9
-
-typedef struct {
- int use;
- size_t size;
- size_t count;
- int partial; /* 1 = partial header, 2 in last partial packet */
- char *buffer; /* used for partial header */
- size_t buflen; /* used size of buffer */
- int first_c; /* of partial header (which is > 0)*/
- int eof;
-} block_filter_ctx_t;
-
-static int special_names_enabled;
-
-static int underflow(IOBUF a);
-static int translate_file_handle ( int fd, int for_write );
-
-
-
-#ifndef FILE_FILTER_USES_STDIO
-
-/* This is a replacement for strcmp. Under W32 it does not
- distinguish between backslash and slash. */
-static int
-fd_cache_strcmp (const char *a, const char *b)
-{
-#ifdef HAVE_DOSISH_SYSTEM
- for (; *a && *b; a++, b++)
- {
- if (*a != *b && !((*a == '/' && *b == '\\')
- || (*a == '\\' && *b == '/')) )
- break;
- }
- return *(const unsigned char *)a - *(const unsigned char *)b;
-#else
- return strcmp (a, b);
-#endif
-}
-
-/*
- * Invalidate (i.e. close) a cached iobuf or all iobufs if NULL is
- * used for FNAME.
- */
-static void
-fd_cache_invalidate (const char *fname)
-{
- CLOSE_CACHE cc;
-
- if (!fname) {
- if( DBG_IOBUF )
- log_debug ("fd_cache_invalidate (all)\n");
-
- for (cc=close_cache; cc; cc = cc->next ) {
- if ( cc->fp != INVALID_FP ) {
-#ifdef HAVE_DOSISH_SYSTEM
- CloseHandle (cc->fp);
-#else
- close(cc->fp);
-#endif
- cc->fp = INVALID_FP;
- }
- }
- return;
- }
-
- if( DBG_IOBUF )
- log_debug ("fd_cache_invalidate (%s)\n", fname);
-
- for (cc=close_cache; cc; cc = cc->next ) {
- if ( cc->fp != INVALID_FP && !fd_cache_strcmp (cc->fname, fname) ) {
- if( DBG_IOBUF )
- log_debug (" did (%s)\n", cc->fname);
-#ifdef HAVE_DOSISH_SYSTEM
- CloseHandle (cc->fp);
-#else
- close(cc->fp);
-#endif
- cc->fp = INVALID_FP;
- }
- }
-}
-
-
-
-static FILEP_OR_FD
-direct_open (const char *fname, const char *mode)
-{
-#ifdef HAVE_DOSISH_SYSTEM
- unsigned long da, cd, sm;
- HANDLE hfile;
-
- /* Note, that we do not handle all mode combinations */
-
- /* According to the ReactOS source it seems that open() of the
- * standard MSW32 crt does open the file in share mode which is
- * something new for MS applications ;-)
- */
- if ( strchr (mode, '+') ) {
- fd_cache_invalidate (fname);
- da = GENERIC_READ|GENERIC_WRITE;
- cd = OPEN_EXISTING;
- sm = FILE_SHARE_READ | FILE_SHARE_WRITE;
- }
- else if ( strchr (mode, 'w') ) {
- fd_cache_invalidate (fname);
- da = GENERIC_WRITE;
- cd = CREATE_ALWAYS;
- sm = FILE_SHARE_WRITE;
- }
- else {
- da = GENERIC_READ;
- cd = OPEN_EXISTING;
- sm = FILE_SHARE_READ;
- }
-
- hfile = CreateFile (fname, da, sm, NULL, cd, FILE_ATTRIBUTE_NORMAL, NULL);
- return hfile;
-#else
- int oflag;
- int cflag = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
-
- /* Note, that we do not handle all mode combinations */
- if ( strchr (mode, '+') ) {
- fd_cache_invalidate (fname);
- oflag = O_RDWR;
- }
- else if ( strchr (mode, 'w') ) {
- fd_cache_invalidate (fname);
- oflag = O_WRONLY | O_CREAT | O_TRUNC;
- }
- else {
- oflag = O_RDONLY;
- }
-#ifdef O_BINARY
- if (strchr (mode, 'b'))
- oflag |= O_BINARY;
-#endif
-#ifndef __riscos__
- return open (fname, oflag, cflag );
-#else
- {
- struct stat buf;
- int rc = stat( fname, &buf );
-
- /* Don't allow iobufs on directories */
- if( !rc && S_ISDIR(buf.st_mode) && !S_ISREG(buf.st_mode) )
- return __set_errno( EISDIR );
- else
- return open( fname, oflag, cflag );
- }
-#endif
-#endif
-}
-
-
-/*
- * Instead of closing an FD we keep it open and cache it for later reuse
- * Note that this caching strategy only works if the process does not chdir.
- */
-static void
-fd_cache_close (const char *fname, FILEP_OR_FD fp)
-{
- CLOSE_CACHE cc;
-
- assert (fp);
- if ( !fname || !*fname ) {
-#ifdef HAVE_DOSISH_SYSTEM
- CloseHandle (fp);
-#else
- close(fp);
-#endif
- if( DBG_IOBUF )
- log_debug ("fd_cache_close (%p) real\n", (void*)fp);
- return;
- }
- /* try to reuse a slot */
- for (cc=close_cache; cc; cc = cc->next ) {
- if ( cc->fp == INVALID_FP && !fd_cache_strcmp (cc->fname, fname) ) {
- cc->fp = fp;
- if( DBG_IOBUF )
- log_debug ("fd_cache_close (%s) used existing slot\n", fname);
- return;
- }
- }
- /* add a new one */
- if( DBG_IOBUF )
- log_debug ("fd_cache_close (%s) new slot created\n", fname);
- cc = xmalloc_clear (sizeof *cc + strlen (fname));
- strcpy (cc->fname, fname);
- cc->fp = fp;
- cc->next = close_cache;
- close_cache = cc;
-}
-
-/*
- * Do an direct_open on FNAME but first try to reuse one from the fd_cache
- */
-static FILEP_OR_FD
-fd_cache_open (const char *fname, const char *mode)
-{
- CLOSE_CACHE cc;
-
- assert (fname);
- for (cc=close_cache; cc; cc = cc->next ) {
- if ( cc->fp != INVALID_FP && !fd_cache_strcmp (cc->fname, fname) ) {
- FILEP_OR_FD fp = cc->fp;
- cc->fp = INVALID_FP;
- if( DBG_IOBUF )
- log_debug ("fd_cache_open (%s) using cached fp\n", fname);
-#ifdef HAVE_DOSISH_SYSTEM
- if (SetFilePointer (fp, 0, NULL, FILE_BEGIN) == 0xffffffff ) {
- log_error ("rewind file failed on handle %p: %s\n",
- fp, w32_strerror (errno));
- fp = INVALID_FP;
- }
-#else
- if ( lseek (fp, 0, SEEK_SET) == (off_t)-1 ) {
- log_error("can't rewind fd %d: %s\n", fp, strerror(errno) );
- fp = INVALID_FP;
- }
-#endif
- return fp;
- }
- }
- if( DBG_IOBUF )
- log_debug ("fd_cache_open (%s) not cached\n", fname);
- return direct_open (fname, mode);
-}
-
-
-#endif /*FILE_FILTER_USES_STDIO*/
-
-
-/****************
- * Read data from a file into buf which has an allocated length of *LEN.
- * return the number of read bytes in *LEN. OPAQUE is the FILE * of
- * the stream. A is not used.
- * control may be:
- * IOBUFCTRL_INIT: called just before the function is linked into the
- * list of function. This can be used to prepare internal
- * data structures of the function.
- * IOBUFCTRL_FREE: called just before the function is removed from the
- * list of functions and can be used to release internal
- * data structures or close a file etc.
- * IOBUFCTRL_UNDERFLOW: called by iobuf_underflow to fill the buffer
- * with new stuff. *RET_LEN is the available size of the
- * buffer, and should be set to the number of bytes
- * which were put into the buffer. The function
- * returns 0 to indicate success, -1 on EOF and
- * G10ERR_xxxxx for other errors.
- *
- * IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff.
- * *RET_LAN is the number of bytes in BUF.
- *
- * IOBUFCTRL_CANCEL: send to all filters on behalf of iobuf_cancel. The
- * filter may take appropriate action on this message.
- */
-static int
-file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
-{
- file_filter_ctx_t *a = opaque;
- FILEP_OR_FD f = a->fp;
- size_t size = *ret_len;
- size_t nbytes = 0;
- int rc = 0;
-
-#ifdef FILE_FILTER_USES_STDIO
- if( control == IOBUFCTRL_UNDERFLOW ) {
- assert( size ); /* need a buffer */
- if ( feof(f)) { /* On terminals you could easiely read as many EOFs as you call */
- rc = -1; /* fread() or fgetc() repeatly. Every call will block until you press */
- *ret_len = 0; /* CTRL-D. So we catch this case before we call fread() again. */
- }
- else {
- clearerr( f );
- nbytes = fread( buf, 1, size, f );
- if( feof(f) && !nbytes ) {
- rc = -1; /* okay: we can return EOF now. */
- }
- else if( ferror(f) && errno != EPIPE ) {
- log_error("%s: read error: %s\n",
- a->fname, strerror(errno));
- rc = G10ERR_READ_FILE;
- }
- *ret_len = nbytes;
- }
- }
- else if( control == IOBUFCTRL_FLUSH ) {
- if( size ) {
- clearerr( f );
- nbytes = fwrite( buf, 1, size, f );
- if( ferror(f) ) {
- log_error("%s: write error: %s\n", a->fname, strerror(errno));
- rc = G10ERR_WRITE_FILE;
- }
- }
- *ret_len = nbytes;
- }
- else if( control == IOBUFCTRL_INIT ) {
- a->keep_open = a->no_cache = 0;
- }
- else if( control == IOBUFCTRL_DESC ) {
- *(char**)buf = "file_filter";
- }
- else if( control == IOBUFCTRL_FREE ) {
- if( f != stdin && f != stdout ) {
- if( DBG_IOBUF )
- log_debug("%s: close fd %d\n", a->fname, fileno(f) );
- if (!a->keep_open)
- fclose(f);
- }
- f = NULL;
- xfree(a); /* we can free our context now */
- }
-#else /* !stdio implementation */
-
- if( control == IOBUFCTRL_UNDERFLOW ) {
- assert( size ); /* need a buffer */
- if ( a->eof_seen) {
- rc = -1;
- *ret_len = 0;
- }
- else {
-#ifdef HAVE_DOSISH_SYSTEM
- unsigned long nread;
-
- nbytes = 0;
- if ( !ReadFile ( f, buf, size, &nread, NULL ) ) {
- if ((int)GetLastError () != ERROR_BROKEN_PIPE) {
- log_error ("%s: read error: %s\n", a->fname,
- w32_strerror (0));
- rc = G10ERR_READ_FILE;
- }
- }
- else if ( !nread ) {
- a->eof_seen = 1;
- rc = -1;
- }
- else {
- nbytes = nread;
- }
-
-#else
-
- int n;
-
- nbytes = 0;
- do {
- n = read ( f, buf, size );
- } while (n == -1 && errno == EINTR );
- if ( n == -1 ) { /* error */
- if (errno != EPIPE) {
- log_error("%s: read error: %s\n",
- a->fname, strerror(errno));
- rc = G10ERR_READ_FILE;
- }
- }
- else if ( !n ) { /* eof */
- a->eof_seen = 1;
- rc = -1;
- }
- else {
- nbytes = n;
- }
-#endif
- *ret_len = nbytes;
- }
- }
- else if( control == IOBUFCTRL_FLUSH ) {
- if( size ) {
-#ifdef HAVE_DOSISH_SYSTEM
- byte *p = buf;
- unsigned long n;
-
- nbytes = size;
- do {
- if (size && !WriteFile (f, p, nbytes, &n, NULL)) {
- log_error ("%s: write error: %s\n", a->fname,
- w32_strerror (0));
- rc = G10ERR_WRITE_FILE;
- break;
- }
- p += n;
- nbytes -= n;
- } while ( nbytes );
- nbytes = p - buf;
-#else
- byte *p = buf;
- int n;
-
- nbytes = size;
- do {
- do {
- n = write ( f, p, nbytes );
- } while ( n == -1 && errno == EINTR );
- if ( n > 0 ) {
- p += n;
- nbytes -= n;
- }
- } while ( n != -1 && nbytes );
- if( n == -1 ) {
- log_error("%s: write error: %s\n", a->fname, strerror(errno));
- rc = G10ERR_WRITE_FILE;
- }
- nbytes = p - buf;
-#endif
- }
- *ret_len = nbytes;
- }
- else if ( control == IOBUFCTRL_INIT ) {
- a->eof_seen = 0;
- a->keep_open = 0;
- a->no_cache = 0;
- }
- else if ( control == IOBUFCTRL_DESC ) {
- *(char**)buf = "file_filter(fd)";
- }
- else if ( control == IOBUFCTRL_FREE ) {
-#ifdef HAVE_DOSISH_SYSTEM
- if ( f != FILEP_OR_FD_FOR_STDIN && f != FILEP_OR_FD_FOR_STDOUT ) {
- if( DBG_IOBUF )
- log_debug("%s: close handle %p\n", a->fname, f );
- if (!a->keep_open)
- fd_cache_close (a->no_cache?NULL:a->fname, f);
- }
-#else
- if ( (int)f != 0 && (int)f != 1 ) {
- if( DBG_IOBUF )
- log_debug("%s: close fd %d\n", a->fname, f );
- if (!a->keep_open)
- fd_cache_close (a->no_cache?NULL:a->fname, f);
- }
- f = INVALID_FP;
-#endif
- xfree (a); /* we can free our context now */
- }
-#endif /* !stdio implementation */
- return rc;
-}
-
-#ifdef _WIN32
-/* Becuase sockets are an special object under Lose32 we have to
- * use a special filter */
-static int
-sock_filter (void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
-{
- sock_filter_ctx_t *a = opaque;
- size_t size = *ret_len;
- size_t nbytes = 0;
- int rc = 0;
-
- if( control == IOBUFCTRL_UNDERFLOW ) {
- assert( size ); /* need a buffer */
- if ( a->eof_seen) {
- rc = -1;
- *ret_len = 0;
- }
- else {
- int nread;
-
- nread = recv ( a->sock, buf, size, 0 );
- if ( nread == SOCKET_ERROR ) {
- int ec = (int)WSAGetLastError ();
- log_error("socket read error: ec=%d\n", ec);
- rc = G10ERR_READ_FILE;
- }
- else if ( !nread ) {
- a->eof_seen = 1;
- rc = -1;
- }
- else {
- nbytes = nread;
- }
- *ret_len = nbytes;
- }
- }
- else if( control == IOBUFCTRL_FLUSH ) {
- if( size ) {
- byte *p = buf;
- int n;
-
- nbytes = size;
- do {
- n = send (a->sock, p, nbytes, 0);
- if ( n == SOCKET_ERROR ) {
- int ec = (int)WSAGetLastError ();
- log_error("socket write error: ec=%d\n", ec);
- rc = G10ERR_WRITE_FILE;
- break;
- }
- p += n;
- nbytes -= n;
- } while ( nbytes );
- nbytes = p - buf;
- }
- *ret_len = nbytes;
- }
- else if ( control == IOBUFCTRL_INIT ) {
- a->eof_seen = 0;
- a->keep_open = 0;
- a->no_cache = 0;
- }
- else if ( control == IOBUFCTRL_DESC ) {
- *(char**)buf = "sock_filter";
- }
- else if ( control == IOBUFCTRL_FREE ) {
- if (!a->keep_open)
- closesocket (a->sock);
- xfree (a); /* we can free our context now */
- }
- return rc;
-}
-#endif /*_WIN32*/
-
-/****************
- * This is used to implement the block write mode.
- * Block reading is done on a byte by byte basis in readbyte(),
- * without a filter
- */
-static int
-block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
-{
- block_filter_ctx_t *a = opaque;
- size_t size = *ret_len;
- int c, needed, rc = 0;
- char *p;
-
- if( control == IOBUFCTRL_UNDERFLOW ) {
- size_t n=0;
-
- p = buf;
- assert( size ); /* need a buffer */
- if( a->eof ) /* don't read any further */
- rc = -1;
- while( !rc && size ) {
- if( !a->size ) { /* get the length bytes */
- if( a->partial == 2 ) {
- a->eof = 1;
- if( !n )
- rc = -1;
- break;
- }
- else if( a->partial ) {
- /* These OpenPGP introduced huffman like encoded length
- * bytes are really a mess :-( */
- if( a->first_c ) {
- c = a->first_c;
- a->first_c = 0;
- }
- else if( (c = iobuf_get(chain)) == -1 ) {
- log_error("block_filter: 1st length byte missing\n");
- rc = G10ERR_READ_FILE;
- break;
- }
- if( c < 192 ) {
- a->size = c;
- a->partial = 2;
- if( !a->size ) {
- a->eof = 1;
- if( !n )
- rc = -1;
- break;
- }
- }
- else if( c < 224 ) {
- a->size = (c - 192) * 256;
- if( (c = iobuf_get(chain)) == -1 ) {
- log_error("block_filter: 2nd length byte missing\n");
- rc = G10ERR_READ_FILE;
- break;
- }
- a->size += c + 192;
- a->partial = 2;
- if( !a->size ) {
- a->eof = 1;
- if( !n )
- rc = -1;
- break;
- }
- }
- else if( c == 255 ) {
- a->size = iobuf_get(chain) << 24;
- a->size |= iobuf_get(chain) << 16;
- a->size |= iobuf_get(chain) << 8;
- if( (c = iobuf_get(chain)) == -1 ) {
- log_error("block_filter: invalid 4 byte length\n");
- rc = G10ERR_READ_FILE;
- break;
- }
- a->size |= c;
- a->partial = 2;
- if( !a->size ) {
- a->eof = 1;
- if( !n )
- rc = -1;
- break;
- }
- }
- else { /* next partial body length */
- a->size = 1 << (c & 0x1f);
- }
- /* log_debug("partial: ctx=%p c=%02x size=%u\n", a, c, a->size);*/
- }
- else
- BUG();
- }
-
- while( !rc && size && a->size ) {
- needed = size < a->size ? size : a->size;
- c = iobuf_read( chain, p, needed );
- if( c < needed ) {
- if( c == -1 ) c = 0;
- log_error("block_filter %p: read error (size=%lu,a->size=%lu)\n",
- a, (ulong)size+c, (ulong)a->size+c);
- rc = G10ERR_READ_FILE;
- }
- else {
- size -= c;
- a->size -= c;
- p += c;
- n += c;
- }
- }
- }
- *ret_len = n;
- }
- else if( control == IOBUFCTRL_FLUSH ) {
- if( a->partial ) { /* the complicated openpgp scheme */
- size_t blen, n, nbytes = size + a->buflen;
-
- assert( a->buflen <= OP_MIN_PARTIAL_CHUNK );
- if( nbytes < OP_MIN_PARTIAL_CHUNK ) {
- /* not enough to write a partial block out; so we store it*/
- if( !a->buffer )
- a->buffer = xmalloc( OP_MIN_PARTIAL_CHUNK );
- memcpy( a->buffer + a->buflen, buf, size );
- a->buflen += size;
- }
- else { /* okay, we can write out something */
- /* do this in a loop to use the most efficient block lengths */
- p = buf;
- do {
- /* find the best matching block length - this is limited
- * by the size of the internal buffering */
- for( blen=OP_MIN_PARTIAL_CHUNK*2,
- c=OP_MIN_PARTIAL_CHUNK_2POW+1; blen <= nbytes;
- blen *=2, c++ )
- ;
- blen /= 2; c--;
- /* write the partial length header */
- assert( c <= 0x1f ); /*;-)*/
- c |= 0xe0;
- iobuf_put( chain, c );
- if( (n=a->buflen) ) { /* write stuff from the buffer */
- assert( n == OP_MIN_PARTIAL_CHUNK);
- if( iobuf_write(chain, a->buffer, n ) )
- rc = G10ERR_WRITE_FILE;
- a->buflen = 0;
- nbytes -= n;
- }
- if( (n = nbytes) > blen )
- n = blen;
- if( n && iobuf_write(chain, p, n ) )
- rc = G10ERR_WRITE_FILE;
- p += n;
- nbytes -= n;
- } while( !rc && nbytes >= OP_MIN_PARTIAL_CHUNK );
- /* store the rest in the buffer */
- if( !rc && nbytes ) {
- assert( !a->buflen );
- assert( nbytes < OP_MIN_PARTIAL_CHUNK );
- if( !a->buffer )
- a->buffer = xmalloc( OP_MIN_PARTIAL_CHUNK );
- memcpy( a->buffer, p, nbytes );
- a->buflen = nbytes;
- }
- }
- }
- else
- BUG();
- }
- else if( control == IOBUFCTRL_INIT ) {
- if( DBG_IOBUF )
- log_debug("init block_filter %p\n", a );
- if( a->partial )
- a->count = 0;
- else if( a->use == 1 )
- a->count = a->size = 0;
- else
- a->count = a->size; /* force first length bytes */
- a->eof = 0;
- a->buffer = NULL;
- a->buflen = 0;
- }
- else if( control == IOBUFCTRL_DESC ) {
- *(char**)buf = "block_filter";
- }
- else if( control == IOBUFCTRL_FREE ) {
- if( a->use == 2 ) { /* write the end markers */
- if( a->partial ) {
- u32 len;
- /* write out the remaining bytes without a partial header
- * the length of this header may be 0 - but if it is
- * the first block we are not allowed to use a partial header
- * and frankly we can't do so, because this length must be
- * a power of 2. This is _really_ complicated because we
- * have to check the possible length of a packet prior
- * to it's creation: a chain of filters becomes complicated
- * and we need a lot of code to handle compressed packets etc.
- * :-(((((((
- */
- /* construct header */
- len = a->buflen;
- /*log_debug("partial: remaining length=%u\n", len );*/
- if( len < 192 )
- rc = iobuf_put(chain, len );
- else if( len < 8384 ) {
- if( !(rc=iobuf_put( chain, ((len-192) / 256) + 192)) )
- rc = iobuf_put( chain, ((len-192) % 256));
- }
- else { /* use a 4 byte header */
- if( !(rc=iobuf_put( chain, 0xff )) )
- if( !(rc=iobuf_put( chain, (len >> 24)&0xff )) )
- if( !(rc=iobuf_put( chain, (len >> 16)&0xff )) )
- if( !(rc=iobuf_put( chain, (len >> 8)&0xff )))
- rc=iobuf_put( chain, len & 0xff );
- }
- if( !rc && len )
- rc = iobuf_write(chain, a->buffer, len );
- if( rc ) {
- log_error("block_filter: write error: %s\n",strerror(errno));
- rc = G10ERR_WRITE_FILE;
- }
- xfree( a->buffer ); a->buffer = NULL; a->buflen = 0;
- }
- else
- BUG();
- }
- else if( a->size ) {
- log_error("block_filter: pending bytes!\n");
- }
- if( DBG_IOBUF )
- log_debug("free block_filter %p\n", a );
- xfree(a); /* we can free our context now */
- }
-
- return rc;
-}
-
-
-static void
-print_chain( IOBUF a )
-{
- if( !DBG_IOBUF )
- return;
- for(; a; a = a->chain ) {
- size_t dummy_len = 0;
- const char *desc = "[none]";
-
- if( a->filter )
- a->filter( a->filter_ov, IOBUFCTRL_DESC, NULL,
- (byte*)&desc, &dummy_len );
-
- log_debug("iobuf chain: %d.%d `%s' filter_eof=%d start=%d len=%d\n",
- a->no, a->subno, desc, a->filter_eof,
- (int)a->d.start, (int)a->d.len );
- }
-}
-
-int
-iobuf_print_chain( IOBUF a )
-{
- print_chain(a);
- return 0;
-}
-
-/****************
- * Allocate a new io buffer, with no function assigned.
- * Use is the desired usage: 1 for input, 2 for output, 3 for temp buffer
- * BUFSIZE is a suggested buffer size.
- */
-IOBUF
-iobuf_alloc(int use, size_t bufsize)
-{
- IOBUF a;
- static int number=0;
-
- a = xmalloc_clear(sizeof *a);
- a->use = use;
- a->d.buf = xmalloc( bufsize );
- a->d.size = bufsize;
- a->no = ++number;
- a->subno = 0;
- a->opaque = NULL;
- a->real_fname = NULL;
- return a;
-}
-
-int
-iobuf_close ( IOBUF a )
-{
- IOBUF a2;
- size_t dummy_len=0;
- int rc=0;
-
- if( a && a->directfp ) {
- fclose( a->directfp );
- xfree( a->real_fname );
- if( DBG_IOBUF )
- log_debug("iobuf_close -> %p\n", a->directfp );
- return 0;
- }
-
- for( ; a && !rc ; a = a2 ) {
- a2 = a->chain;
- if( a->use == 2 && (rc=iobuf_flush(a)) )
- log_error("iobuf_flush failed on close: %s\n", g10_errstr(rc));
-
- if( DBG_IOBUF )
- log_debug("iobuf-%d.%d: close `%s'\n", a->no, a->subno, a->desc );
- if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE,
- a->chain, NULL, &dummy_len)) )
- log_error("IOBUFCTRL_FREE failed on close: %s\n", g10_errstr(rc) );
- xfree(a->real_fname);
- if (a->d.buf) {
- memset (a->d.buf, 0, a->d.size); /* erase the buffer */
- xfree(a->d.buf);
- }
- xfree(a);
- }
- return rc;
-}
-
-int
-iobuf_cancel( IOBUF a )
-{
- const char *s;
- IOBUF a2;
- int rc;
-#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
- char *remove_name = NULL;
-#endif
-
- if( a && a->use == 2 ) {
- s = iobuf_get_real_fname(a);
- if( s && *s ) {
-#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
- remove_name = xstrdup ( s );
-#else
- remove(s);
-#endif
- }
- }
-
- /* send a cancel message to all filters */
- for( a2 = a; a2 ; a2 = a2->chain ) {
- size_t dummy;
- if( a2->filter )
- a2->filter( a2->filter_ov, IOBUFCTRL_CANCEL, a2->chain,
- NULL, &dummy );
- }
-
- rc = iobuf_close(a);
-#if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
- if ( remove_name ) {
- /* Argg, MSDOS does not allow to remove open files. So
- * we have to do it here */
- remove ( remove_name );
- xfree ( remove_name );
- }
-#endif
- return rc;
-}
-
-
-/****************
- * create a temporary iobuf, which can be used to collect stuff
- * in an iobuf and later be written by iobuf_write_temp() to another
- * iobuf.
- */
-IOBUF
-iobuf_temp()
-{
- IOBUF a;
-
- a = iobuf_alloc(3, IOBUF_BUFFER_SIZE );
-
- return a;
-}
-
-IOBUF
-iobuf_temp_with_content( const char *buffer, size_t length )
-{
- IOBUF a;
-
- a = iobuf_alloc(3, length );
- memcpy( a->d.buf, buffer, length );
- a->d.len = length;
-
- return a;
-}
-
-void
-iobuf_enable_special_filenames ( int yes )
-{
- special_names_enabled = yes;
-}
-
-/*
- * see whether the filename has the for "-&nnnn", where n is a
- * non-zero number.
- * Returns this number or -1 if it is not the case.
- */
-static int
-check_special_filename ( const char *fname )
-{
- if ( special_names_enabled
- && fname && *fname == '-' && fname[1] == '&' ) {
- int i;
-
- fname += 2;
- for (i=0; digitp (fname+i); i++ )
- ;
- if ( !fname[i] )
- return atoi (fname);
- }
- return -1;
-}
-
-/* This fucntion returns true if FNAME indicates a PIPE (stdout or
- stderr) or a special file name if those are enabled. */
-int
-iobuf_is_pipe_filename (const char *fname)
-{
- if (!fname || (*fname=='-' && !fname[1]) )
- return 1;
- return check_special_filename (fname) != -1;
-}
-
-/****************
- * Create a head iobuf for reading from a file
- * returns: NULL if an error occures and sets errno
- */
-IOBUF
-iobuf_open( const char *fname )
-{
- IOBUF a;
- FILEP_OR_FD fp;
- file_filter_ctx_t *fcx;
- size_t len;
- int print_only = 0;
- int fd;
-
- if( !fname || (*fname=='-' && !fname[1]) ) {
- fp = FILEP_OR_FD_FOR_STDIN;
-#ifdef USE_SETMODE
- setmode ( my_fileno(fp) , O_BINARY );
-#endif
- fname = "[stdin]";
- print_only = 1;
- }
- else if ( (fd = check_special_filename ( fname )) != -1 )
- return iobuf_fdopen ( translate_file_handle (fd,0), "rb" );
- else if( (fp = my_fopen_ro(fname, "rb")) == INVALID_FP )
- return NULL;
- a = iobuf_alloc(1, IOBUF_BUFFER_SIZE );
- fcx = xmalloc( sizeof *fcx + strlen(fname) );
- fcx->fp = fp;
- fcx->print_only_name = print_only;
- strcpy(fcx->fname, fname );
- if( !print_only )
- a->real_fname = xstrdup( fname );
- a->filter = file_filter;
- a->filter_ov = fcx;
- file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
- file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
- if( DBG_IOBUF )
- log_debug("iobuf-%d.%d: open `%s' fd=%d\n",
- a->no, a->subno, fname, (int)my_fileno(fcx->fp) );
-
- return a;
-}
-
-/****************
- * Create a head iobuf for reading from a file
- * returns: NULL if an error occures and sets errno
- */
-IOBUF
-iobuf_fdopen( int fd, const char *mode )
-{
- IOBUF a;
- FILEP_OR_FD fp;
- file_filter_ctx_t *fcx;
- size_t len;
-
-#ifdef FILE_FILTER_USES_STDIO
- if( !(fp = fdopen(fd, mode)) )
- return NULL;
-#else
- fp = (FILEP_OR_FD)fd;
-#endif
- a = iobuf_alloc( strchr( mode, 'w')? 2:1, IOBUF_BUFFER_SIZE );
- fcx = xmalloc( sizeof *fcx + 20 );
- fcx->fp = fp;
- fcx->print_only_name = 1;
- sprintf(fcx->fname, "[fd %d]", fd );
- a->filter = file_filter;
- a->filter_ov = fcx;
- file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
- file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
- if( DBG_IOBUF )
- log_debug("iobuf-%d.%d: fdopen `%s'\n", a->no, a->subno, fcx->fname );
- iobuf_ioctl (a,3,1,NULL); /* disable fd caching */
- return a;
-}
-
-
-IOBUF
-iobuf_sockopen ( int fd, const char *mode )
-{
- IOBUF a;
-#ifdef _WIN32
- sock_filter_ctx_t *scx;
- size_t len;
-
- a = iobuf_alloc( strchr( mode, 'w')? 2:1, IOBUF_BUFFER_SIZE );
- scx = xmalloc( sizeof *scx + 25 );
- scx->sock = fd;
- scx->print_only_name = 1;
- sprintf(scx->fname, "[sock %d]", fd );
- a->filter = sock_filter;
- a->filter_ov = scx;
- sock_filter( scx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
- sock_filter( scx, IOBUFCTRL_INIT, NULL, NULL, &len );
- if( DBG_IOBUF )
- log_debug("iobuf-%d.%d: sockopen `%s'\n", a->no, a->subno, scx->fname);
- iobuf_ioctl (a,3,1,NULL); /* disable fd caching */
-#else
- a = iobuf_fdopen (fd, mode);
-#endif
- return a;
-}
-
-/****************
- * create an iobuf for writing to a file; the file will be created.
- */
-IOBUF
-iobuf_create( const char *fname )
-{
- IOBUF a;
- FILEP_OR_FD fp;
- file_filter_ctx_t *fcx;
- size_t len;
- int print_only = 0;
- int fd;
-
- if( !fname || (*fname=='-' && !fname[1]) ) {
- fp = FILEP_OR_FD_FOR_STDOUT;
-#ifdef USE_SETMODE
- setmode ( my_fileno(fp) , O_BINARY );
-#endif
- fname = "[stdout]";
- print_only = 1;
- }
- else if ( (fd = check_special_filename ( fname )) != -1 )
- return iobuf_fdopen ( translate_file_handle (fd, 1), "wb" );
- else if( (fp = my_fopen(fname, "wb")) == INVALID_FP )
- return NULL;
- a = iobuf_alloc(2, IOBUF_BUFFER_SIZE );
- fcx = xmalloc( sizeof *fcx + strlen(fname) );
- fcx->fp = fp;
- fcx->print_only_name = print_only;
- strcpy(fcx->fname, fname );
- if( !print_only )
- a->real_fname = xstrdup( fname );
- a->filter = file_filter;
- a->filter_ov = fcx;
- file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
- file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
- if( DBG_IOBUF )
- log_debug("iobuf-%d.%d: create `%s'\n", a->no, a->subno, a->desc );
-
- return a;
-}
-
-/****************
- * append to an iobuf; if the file does not exist, create it.
- * cannot be used for stdout.
- * Note: This is not used.
- */
-#if 0 /* not used */
-IOBUF
-iobuf_append( const char *fname )
-{
- IOBUF a;
- FILE *fp;
- file_filter_ctx_t *fcx;
- size_t len;
-
- if( !fname )
- return NULL;
- else if( !(fp = my_fopen(fname, "ab")) )
- return NULL;
- a = iobuf_alloc(2, IOBUF_BUFFER_SIZE );
- fcx = xmalloc( sizeof *fcx + strlen(fname) );
- fcx->fp = fp;
- strcpy(fcx->fname, fname );
- a->real_fname = xstrdup( fname );
- a->filter = file_filter;
- a->filter_ov = fcx;
- file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
- file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
- if( DBG_IOBUF )
- log_debug("iobuf-%d.%d: append `%s'\n", a->no, a->subno, a->desc );
-
- return a;
-}
-#endif
-
-IOBUF
-iobuf_openrw( const char *fname )
-{
- IOBUF a;
- FILEP_OR_FD fp;
- file_filter_ctx_t *fcx;
- size_t len;
-
- if( !fname )
- return NULL;
- else if( (fp = my_fopen(fname, "r+b")) == INVALID_FP )
- return NULL;
- a = iobuf_alloc(2, IOBUF_BUFFER_SIZE );
- fcx = xmalloc( sizeof *fcx + strlen(fname) );
- fcx->fp = fp;
- strcpy(fcx->fname, fname );
- a->real_fname = xstrdup( fname );
- a->filter = file_filter;
- a->filter_ov = fcx;
- file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
- file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
- if( DBG_IOBUF )
- log_debug("iobuf-%d.%d: openrw `%s'\n", a->no, a->subno, a->desc );
-
- return a;
-}
-
-
-int
-iobuf_ioctl ( IOBUF a, int cmd, int intval, void *ptrval )
-{
- if ( cmd == 1 ) { /* keep system filepointer/descriptor open */
- if( DBG_IOBUF )
- log_debug("iobuf-%d.%d: ioctl `%s' keep=%d\n",
- a? a->no:-1, a?a->subno:-1, a?a->desc:"?", intval );
- for( ; a; a = a->chain )
- if( !a->chain && a->filter == file_filter ) {
- file_filter_ctx_t *b = a->filter_ov;
- b->keep_open = intval;
- return 0;
- }
-#ifdef _WIN32
- else if( !a->chain && a->filter == sock_filter ) {
- sock_filter_ctx_t *b = a->filter_ov;
- b->keep_open = intval;
- return 0;
- }
-#endif
- }
- else if ( cmd == 2 ) { /* invalidate cache */
- if( DBG_IOBUF )
- log_debug("iobuf-*.*: ioctl `%s' invalidate\n",
- ptrval? (char*)ptrval:"[all]");
- if ( !a && !intval ) {
-#ifndef FILE_FILTER_USES_STDIO
- fd_cache_invalidate (ptrval);
-#endif
- return 0;
- }
- }
- else if ( cmd == 3 ) { /* disallow/allow caching */
- if( DBG_IOBUF )
- log_debug("iobuf-%d.%d: ioctl `%s' no_cache=%d\n",
- a? a->no:-1, a?a->subno:-1, a?a->desc:"?", intval );
- for( ; a; a = a->chain )
- if( !a->chain && a->filter == file_filter ) {
- file_filter_ctx_t *b = a->filter_ov;
- b->no_cache = intval;
- return 0;
- }
-#ifdef _WIN32
- else if( !a->chain && a->filter == sock_filter ) {
- sock_filter_ctx_t *b = a->filter_ov;
- b->no_cache = intval;
- return 0;
- }
-#endif
- }
-
- return -1;
-}
-
-
-/****************
- * Register an i/o filter.
- */
-int
-iobuf_push_filter( IOBUF a,
- int (*f)(void *opaque, int control,
- IOBUF chain, byte *buf, size_t *len), void *ov )
-{
- return iobuf_push_filter2( a, f, ov, 0 );
-}
-
-int
-iobuf_push_filter2( IOBUF a,
- int (*f)(void *opaque, int control,
- IOBUF chain, byte *buf, size_t *len),
- void *ov, int rel_ov )
-{
- IOBUF b;
- size_t dummy_len=0;
- int rc=0;
-
- if( a->directfp )
- BUG();
-
- if( a->use == 2 && (rc=iobuf_flush(a)) )
- return rc;
- /* make a copy of the current stream, so that
- * A is the new stream and B the original one.
- * The contents of the buffers are transferred to the
- * new stream.
- */
- b = xmalloc(sizeof *b);
- memcpy(b, a, sizeof *b );
- /* fixme: it is stupid to keep a copy of the name at every level
- * but we need the name somewhere because the name known by file_filter
- * may have been released when we need the name of the file */
- b->real_fname = a->real_fname? xstrdup(a->real_fname):NULL;
- /* remove the filter stuff from the new stream */
- a->filter = NULL;
- a->filter_ov = NULL;
- a->filter_ov_owner = 0;
- a->filter_eof = 0;
- if( a->use == 3 )
- a->use = 2; /* make a write stream from a temp stream */
-
- if( a->use == 2 ) { /* allocate a fresh buffer for the original stream */
- b->d.buf = xmalloc( a->d.size );
- b->d.len = 0;
- b->d.start = 0;
- }
- else { /* allocate a fresh buffer for the new stream */
- a->d.buf = xmalloc( a->d.size );
- a->d.len = 0;
- a->d.start = 0;
- }
- /* disable nlimit for the new stream */
- a->ntotal = b->ntotal + b->nbytes;
- a->nlimit = a->nbytes = 0;
- a->nofast &= ~1;
- /* make a link from the new stream to the original stream */
- a->chain = b;
- a->opaque = b->opaque;
-
- /* setup the function on the new stream */
- a->filter = f;
- a->filter_ov = ov;
- a->filter_ov_owner = rel_ov;
-
- a->subno = b->subno + 1;
- f( ov, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &dummy_len );
-
- if( DBG_IOBUF ) {
- log_debug("iobuf-%d.%d: push `%s'\n", a->no, a->subno, a->desc );
- print_chain( a );
- }
-
- /* now we can initialize the new function if we have one */
- if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_INIT, a->chain,
- NULL, &dummy_len)) )
- log_error("IOBUFCTRL_INIT failed: %s\n", g10_errstr(rc) );
- return rc;
-}
-
-/****************
- * Remove an i/o filter.
- */
-static int
-pop_filter( IOBUF a, int (*f)(void *opaque, int control,
- IOBUF chain, byte *buf, size_t *len), void *ov )
-{
- IOBUF b;
- size_t dummy_len=0;
- int rc=0;
-
- if( a->directfp )
- BUG();
-
- if( DBG_IOBUF )
- log_debug("iobuf-%d.%d: pop `%s'\n", a->no, a->subno, a->desc );
- if( !a->filter ) { /* this is simple */
- b = a->chain;
- assert(b);
- xfree(a->d.buf);
- xfree(a->real_fname);
- memcpy(a,b, sizeof *a);
- xfree(b);
- return 0;
- }
- for(b=a ; b; b = b->chain )
- if( b->filter == f && (!ov || b->filter_ov == ov) )
- break;
- if( !b )
- log_bug("pop_filter(): filter function not found\n");
-
- /* flush this stream if it is an output stream */
- if( a->use == 2 && (rc=iobuf_flush(b)) ) {
- log_error("iobuf_flush failed in pop_filter: %s\n", g10_errstr(rc));
- return rc;
- }
- /* and tell the filter to free it self */
- if( b->filter && (rc = b->filter(b->filter_ov, IOBUFCTRL_FREE, b->chain,
- NULL, &dummy_len)) ) {
- log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) );
- return rc;
- }
- if( b->filter_ov && b->filter_ov_owner ) {
- xfree( b->filter_ov );
- b->filter_ov = NULL;
- }
-
-
- /* and see how to remove it */
- if( a == b && !b->chain )
- log_bug("can't remove the last filter from the chain\n");
- else if( a == b ) { /* remove the first iobuf from the chain */
- /* everything from b is copied to a. This is save because
- * a flush has been done on the to be removed entry
- */
- b = a->chain;
- xfree(a->d.buf);
- xfree(a->real_fname);
- memcpy(a,b, sizeof *a);
- xfree(b);
- if( DBG_IOBUF )
- log_debug("iobuf-%d.%d: popped filter\n", a->no, a->subno );
- }
- else if( !b->chain ) { /* remove the last iobuf from the chain */
- log_bug("Ohh jeee, trying to remove a head filter\n");
- }
- else { /* remove an intermediate iobuf from the chain */
- log_bug("Ohh jeee, trying to remove an intermediate filter\n");
- }
-
- return rc;
-}
-
-
-/****************
- * read underflow: read more bytes into the buffer and return
- * the first byte or -1 on EOF.
- */
-static int
-underflow(IOBUF a)
-{
- size_t len;
- int rc;
-
- assert( a->d.start == a->d.len );
- if( a->use == 3 )
- return -1; /* EOF because a temp buffer can't do an underflow */
-
- if( a->filter_eof ) {
- if( a->chain ) {
- IOBUF b = a->chain;
- if( DBG_IOBUF )
- log_debug("iobuf-%d.%d: pop `%s' in underflow\n",
- a->no, a->subno, a->desc );
- xfree(a->d.buf);
- xfree(a->real_fname);
- memcpy(a, b, sizeof *a);
- xfree(b);
- print_chain(a);
- }
- else
- a->filter_eof = 0; /* for the top level filter */
- if( DBG_IOBUF )
- log_debug("iobuf-%d.%d: underflow: eof (due to filter eof)\n",
- a->no, a->subno );
- return -1; /* return one(!) EOF */
- }
- if( a->error ) {
- if( DBG_IOBUF )
- log_debug("iobuf-%d.%d: error\n", a->no, a->subno );
- return -1;
- }
-
- if( a->directfp ) {
- FILE *fp = a->directfp;
-
- len = fread( a->d.buf, 1, a->d.size, fp);
- if( len < a->d.size ) {
- if( ferror(fp) )
- a->error = 1;
- }
- a->d.len = len;
- a->d.start = 0;
- return len? a->d.buf[a->d.start++] : -1;
- }
-
-
- if( a->filter ) {
- len = a->d.size;
- if( DBG_IOBUF )
- log_debug("iobuf-%d.%d: underflow: req=%lu\n",
- a->no, a->subno, (ulong)len );
- rc = a->filter( a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
- a->d.buf, &len );
- if( DBG_IOBUF ) {
- log_debug("iobuf-%d.%d: underflow: got=%lu rc=%d\n",
- a->no, a->subno, (ulong)len, rc );
-/* if( a->no == 1 ) */
-/* log_hexdump (" data:", a->d.buf, len); */
- }
- if( a->use == 1 && rc == -1 ) { /* EOF: we can remove the filter */
- size_t dummy_len=0;
-
- /* and tell the filter to free itself */
- if( (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE, a->chain,
- NULL, &dummy_len)) )
- log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) );
- if( a->filter_ov && a->filter_ov_owner ) {
- xfree( a->filter_ov );
- a->filter_ov = NULL;
- }
- a->filter = NULL;
- a->desc = NULL;
- a->filter_ov = NULL;
- a->filter_eof = 1;
- if( !len && a->chain ) {
- IOBUF b = a->chain;
- if( DBG_IOBUF )
- log_debug("iobuf-%d.%d: pop `%s' in underflow (!len)\n",
- a->no, a->subno, a->desc );
- xfree(a->d.buf);
- xfree(a->real_fname);
- memcpy(a,b, sizeof *a);
- xfree(b);
- print_chain(a);
- }
- }
- else if( rc )
- a->error = 1;
-
- if( !len ) {
- if( DBG_IOBUF )
- log_debug("iobuf-%d.%d: underflow: eof\n", a->no, a->subno );
- return -1;
- }
- a->d.len = len;
- a->d.start = 0;
- return a->d.buf[a->d.start++];
- }
- else {
- if( DBG_IOBUF )
- log_debug("iobuf-%d.%d: underflow: eof (no filter)\n",
- a->no, a->subno );
- return -1; /* no filter; return EOF */
- }
-}
-
-
-int
-iobuf_flush(IOBUF a)
-{
- size_t len;
- int rc;
-
- if( a->directfp )
- return 0;
-
- if( a->use == 3 ) { /* increase the temp buffer */
- char *newbuf;
- size_t newsize = a->d.size + IOBUF_BUFFER_SIZE;
-
- if( DBG_IOBUF )
- log_debug("increasing temp iobuf from %lu to %lu\n",
- (ulong)a->d.size, (ulong)newsize );
- newbuf = xmalloc( newsize );
- memcpy( newbuf, a->d.buf, a->d.len );
- xfree(a->d.buf);
- a->d.buf = newbuf;
- a->d.size = newsize;
- return 0;
- }
- else if( a->use != 2 )
- log_bug("flush on non-output iobuf\n");
- else if( !a->filter )
- log_bug("iobuf_flush: no filter\n");
- len = a->d.len;
- rc = a->filter( a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len );
- if( !rc && len != a->d.len ) {
- log_info("iobuf_flush did not write all!\n");
- rc = G10ERR_WRITE_FILE;
- }
- else if( rc )
- a->error = 1;
- a->d.len = 0;
-
- return rc;
-}
-
-
-/****************
- * Read a byte from the iobuf; returns -1 on EOF
- */
-int
-iobuf_readbyte(IOBUF a)
-{
- int c;
-
- /* nlimit does not work together with unget */
- /* nbytes is also not valid! */
- if( a->unget.buf ) {
- if( a->unget.start < a->unget.len )
- return a->unget.buf[a->unget.start++];
- xfree(a->unget.buf);
- a->unget.buf = NULL;
- a->nofast &= ~2;
- }
-
- if( a->nlimit && a->nbytes >= a->nlimit )
- return -1; /* forced EOF */
-
- if( a->d.start < a->d.len ) {
- c = a->d.buf[a->d.start++];
- }
- else if( (c=underflow(a)) == -1 )
- return -1; /* EOF */
-
- a->nbytes++;
- return c;
-}
-
-
-int
-iobuf_read(IOBUF a, byte *buf, unsigned buflen )
-{
- int c, n;
-
- if( a->unget.buf || a->nlimit ) {
- /* handle special cases */
- for(n=0 ; n < buflen; n++ ) {
- if( (c = iobuf_readbyte(a)) == -1 ) {
- if( !n )
- return -1; /* eof */
- break;
- }
- else
- if( buf ) *buf = c;
- if( buf ) buf++;
- }
- return n;
- }
-
- n = 0;
- do {
- if( n < buflen && a->d.start < a->d.len ) {
- unsigned size = a->d.len - a->d.start;
- if( size > buflen - n )
- size = buflen - n;
- if( buf )
- memcpy( buf, a->d.buf + a->d.start, size );
- n += size;
- a->d.start += size;
- if( buf )
- buf += size;
- }
- if( n < buflen ) {
- if( (c=underflow(a)) == -1 ) {
- a->nbytes += n;
- return n? n : -1/*EOF*/;
- }
- if( buf )
- *buf++ = c;
- n++;
- }
- } while( n < buflen );
- a->nbytes += n;
- return n;
-}
-
-
-/****************
- * Have a look at the iobuf.
- * NOTE: This only works in special cases.
- */
-int
-iobuf_peek(IOBUF a, byte *buf, unsigned buflen )
-{
- int n=0;
-
- if( a->filter_eof )
- return -1;
-
- if( !(a->d.start < a->d.len) ) {
- if( underflow(a) == -1 )
- return -1;
- /* and unget this character */
- assert(a->d.start == 1);
- a->d.start = 0;
- }
-
- for(n=0 ; n < buflen && (a->d.start+n) < a->d.len ; n++, buf++ )
- *buf = a->d.buf[n];
- return n;
-}
-
-
-
-
-int
-iobuf_writebyte(IOBUF a, unsigned c)
-{
-
- if( a->directfp )
- BUG();
-
- if( a->d.len == a->d.size )
- if( iobuf_flush(a) )
- return -1;
-
- assert( a->d.len < a->d.size );
- a->d.buf[a->d.len++] = c;
- return 0;
-}
-
-
-int
-iobuf_write(IOBUF a, byte *buf, unsigned buflen )
-{
-
- if( a->directfp )
- BUG();
-
- do {
- if( buflen && a->d.len < a->d.size ) {
- unsigned size = a->d.size - a->d.len;
- if( size > buflen ) size = buflen;
- memcpy( a->d.buf + a->d.len, buf, size );
- buflen -= size;
- buf += size;
- a->d.len += size;
- }
- if( buflen ) {
- if( iobuf_flush(a) )
- return -1;
- }
- } while( buflen );
- return 0;
-}
-
-
-int
-iobuf_writestr(IOBUF a, const char *buf )
-{
- for( ; *buf; buf++ )
- if( iobuf_writebyte(a, *buf) )
- return -1;
- return 0;
-}
-
-
-
-/****************
- * copy the contents of TEMP to A.
- */
-int
-iobuf_write_temp( IOBUF a, IOBUF temp )
-{
- while( temp->chain )
- pop_filter( temp, temp->filter, NULL );
- return iobuf_write(a, temp->d.buf, temp->d.len );
-}
-
-/****************
- * copy the contents of the temp io stream to BUFFER.
- */
-size_t
-iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen )
-{
- size_t n = a->d.len;
-
- if( n > buflen )
- n = buflen;
- memcpy( buffer, a->d.buf, n );
- return n;
-}
-
-
-/****************
- * Call this function to terminate processing of the temp stream
- * without closing it. This removes all filters from the stream
- * makes sure that iobuf_get_temp_{buffer,length}() returns correct
- * values.
- */
-void
-iobuf_flush_temp( IOBUF temp )
-{
- while( temp->chain )
- pop_filter( temp, temp->filter, NULL );
-}
-
-
-/****************
- * Set a limit on how many bytes may be read from the input stream A.
- * Setting the limit to 0 disables this feature.
- */
-void
-iobuf_set_limit( IOBUF a, off_t nlimit )
-{
- if( nlimit )
- a->nofast |= 1;
- else
- a->nofast &= ~1;
- a->nlimit = nlimit;
- a->ntotal += a->nbytes;
- a->nbytes = 0;
-}
-
-
-
-/* Return the length of an open file A. IF OVERFLOW is not NULL it
- will be set to true if the file is larger than what off_t can cope
- with. The function return 0 on error or on overflow condition. */
-off_t
-iobuf_get_filelength (IOBUF a, int *overflow )
-{
- struct stat st;
-
- if (overflow)
- *overflow = 0;
-
- if( a->directfp ) {
- FILE *fp = a->directfp;
-
- if( !fstat(fileno(fp), &st) )
- return st.st_size;
- log_error("fstat() failed: %s\n", strerror(errno) );
- return 0;
- }
-
- /* Hmmm: file_filter may have already been removed */
- for( ; a; a = a->chain )
- if( !a->chain && a->filter == file_filter ) {
- file_filter_ctx_t *b = a->filter_ov;
- FILEP_OR_FD fp = b->fp;
-
-#if defined(HAVE_DOSISH_SYSTEM) && !defined(FILE_FILTER_USES_STDIO)
- ulong size;
- static int (* __stdcall get_file_size_ex)
- (void *handle, LARGE_INTEGER *size);
- static int get_file_size_ex_initialized;
-
- if (!get_file_size_ex_initialized)
- {
- void *handle;
-
- handle = dlopen ("kernel32.dll", RTLD_LAZY);
- if (handle)
- {
- get_file_size_ex = dlsym (handle, "GetFileSizeEx");
- if (!get_file_size_ex)
- dlclose (handle);
- }
- get_file_size_ex_initialized = 1;
- }
-
- if (get_file_size_ex)
- {
- /* This is a newer system with GetFileSizeEx; we use
- this then becuase it seem that GetFileSize won't
- return a proper error in case a file is larger than
- 4GB. */
- LARGE_INTEGER size;
-
- if (get_file_size_ex (fp, &size))
- {
- if (!size.u.HighPart)
- return size.u.LowPart;
- if (overflow)
- *overflow = 1;
- return 0;
- }
- }
- else
- {
- if ((size=GetFileSize (fp, NULL)) != 0xffffffff)
- return size;
- }
- log_error ("GetFileSize for handle %p failed: %s\n",
- fp, w32_strerror (0));
-#else
- if( !fstat(my_fileno(fp), &st) )
- return st.st_size;
- log_error("fstat() failed: %s\n", strerror(errno) );
-#endif
- break;
- }
-
- return 0;
-}
-
-
-/* Return the file descriptor of the underlying file or -1 if it is
- not available. */
-int
-iobuf_get_fd (IOBUF a)
-{
- if (a->directfp)
- return fileno ( (FILE*)a->directfp );
-
- for ( ; a; a = a->chain )
- if (!a->chain && a->filter == file_filter)
- {
- file_filter_ctx_t *b = a->filter_ov;
- FILEP_OR_FD fp = b->fp;
-
- return my_fileno (fp);
- }
-
- return -1;
-}
-
-
-/****************
- * Tell the file position, where the next read will take place
- */
-off_t
-iobuf_tell( IOBUF a )
-{
- return a->ntotal + a->nbytes;
-}
-
-
-#if !defined(HAVE_FSEEKO) && !defined(fseeko)
-
-#ifdef HAVE_LIMITS_H
-# include <limits.h>
-#endif
-#ifndef LONG_MAX
-# define LONG_MAX ((long) ((unsigned long) -1 >> 1))
-#endif
-#ifndef LONG_MIN
-# define LONG_MIN (-1 - LONG_MAX)
-#endif
-
-/****************
- * A substitute for fseeko, for hosts that don't have it.
- */
-static int
-fseeko( FILE *stream, off_t newpos, int whence )
-{
- while( newpos != (long) newpos ) {
- long pos = newpos < 0 ? LONG_MIN : LONG_MAX;
- if( fseek( stream, pos, whence ) != 0 )
- return -1;
- newpos -= pos;
- whence = SEEK_CUR;
- }
- return fseek( stream, (long)newpos, whence );
-}
-#endif
-
-/****************
- * This is a very limited implementation. It simply discards all internal
- * buffering and removes all filters but the first one.
- */
-int
-iobuf_seek( IOBUF a, off_t newpos )
-{
- file_filter_ctx_t *b = NULL;
-
- if( a->directfp ) {
- FILE *fp = a->directfp;
- if( fseeko( fp, newpos, SEEK_SET ) ) {
- log_error("can't seek: %s\n", strerror(errno) );
- return -1;
- }
- clearerr(fp);
- }
- else {
- for( ; a; a = a->chain ) {
- if( !a->chain && a->filter == file_filter ) {
- b = a->filter_ov;
- break;
- }
- }
- if( !a )
- return -1;
-#ifdef FILE_FILTER_USES_STDIO
- if( fseeko( b->fp, newpos, SEEK_SET ) ) {
- log_error("can't fseek: %s\n", strerror(errno) );
- return -1;
- }
-#else
-#ifdef HAVE_DOSISH_SYSTEM
- if (SetFilePointer (b->fp, newpos, NULL, FILE_BEGIN) == 0xffffffff ) {
- log_error ("SetFilePointer failed on handle %p: %s\n",
- b->fp, w32_strerror (0));
- return -1;
- }
-#else
- if ( lseek (b->fp, newpos, SEEK_SET) == (off_t)-1 ) {
- log_error("can't lseek: %s\n", strerror(errno) );
- return -1;
- }
-#endif
-#endif
- }
- a->d.len = 0; /* discard buffer */
- a->d.start = 0;
- a->nbytes = 0;
- a->nlimit = 0;
- a->nofast &= ~1;
- a->ntotal = newpos;
- a->error = 0;
- /* remove filters, but the last */
- if( a->chain )
- log_debug("pop_filter called in iobuf_seek - please report\n");
- while( a->chain )
- pop_filter( a, a->filter, NULL );
-
- return 0;
-}
-
-
-
-
-
-
-/****************
- * Retrieve the real filename
- */
-const char *
-iobuf_get_real_fname( IOBUF a )
-{
- if( a->real_fname )
- return a->real_fname;
-
- /* the old solution */
- for( ; a; a = a->chain )
- if( !a->chain && a->filter == file_filter ) {
- file_filter_ctx_t *b = a->filter_ov;
- return b->print_only_name? NULL : b->fname;
- }
-
- return NULL;
-}
-
-
-/****************
- * Retrieve the filename
- */
-const char *
-iobuf_get_fname( IOBUF a )
-{
- for( ; a; a = a->chain )
- if( !a->chain && a->filter == file_filter ) {
- file_filter_ctx_t *b = a->filter_ov;
- return b->fname;
- }
-
- return NULL;
-}
-
-
-/****************
- * enable partial block mode as described in the OpenPGP draft.
- * LEN is the first length byte on read, but ignored on writes.
- */
-void
-iobuf_set_partial_block_mode( IOBUF a, size_t len )
-{
- block_filter_ctx_t *ctx = xmalloc_clear( sizeof *ctx );
-
- assert( a->use == 1 || a->use == 2 );
- ctx->use = a->use;
- if( !len ) {
- if( a->use == 1 )
- log_debug("pop_filter called in set_partial_block_mode"
- " - please report\n");
- pop_filter(a, block_filter, NULL );
- }
- else {
- ctx->partial = 1;
- ctx->size = 0;
- ctx->first_c = len;
- iobuf_push_filter(a, block_filter, ctx );
- }
-}
-
-
-/****************
- * Same as fgets() but if the buffer is too short a larger one will
- * be allocated up to some limit *max_length.
- * A line is considered a byte stream ending in a LF.
- * Returns the length of the line. EOF is indicated by a line of
- * length zero. The last LF may be missing due to an EOF.
- * is max_length is zero on return, the line has been truncated.
- *
- * Note: The buffer is allocated with enough space to append a CR,LF,EOL
- */
-unsigned
-iobuf_read_line( IOBUF a, byte **addr_of_buffer,
- unsigned *length_of_buffer, unsigned *max_length )
-{
- int c;
- char *buffer = *addr_of_buffer;
- unsigned length = *length_of_buffer;
- unsigned nbytes = 0;
- unsigned maxlen = *max_length;
- char *p;
-
- if( !buffer ) { /* must allocate a new buffer */
- length = 256;
- buffer = xmalloc( length );
- *addr_of_buffer = buffer;
- *length_of_buffer = length;
- }
-
- length -= 3; /* reserve 3 bytes (cr,lf,eol) */
- p = buffer;
- while( (c=iobuf_get(a)) != -1 ) {
- if( nbytes == length ) { /* increase the buffer */
- if( length > maxlen ) { /* this is out limit */
- /* skip the rest of the line */
- while( c != '\n' && (c=iobuf_get(a)) != -1 )
- ;
- *p++ = '\n'; /* always append a LF (we have reserved space) */
- nbytes++;
- *max_length = 0; /* indicate truncation */
- break;
- }
- length += 3; /* correct for the reserved byte */
- length += length < 1024? 256 : 1024;
- buffer = xrealloc( buffer, length );
- *addr_of_buffer = buffer;
- *length_of_buffer = length;
- length -= 3; /* and reserve again */
- p = buffer + nbytes;
- }
- *p++ = c;
- nbytes++;
- if( c == '\n' )
- break;
- }
- *p = 0; /* make sure the line is a string */
-
- return nbytes;
-}
-
-/* This is the non iobuf specific function */
-int
-iobuf_translate_file_handle ( int fd, int for_write )
-{
-#ifdef _WIN32
- {
- int x;
-
- if ( fd <= 2 )
- return fd; /* do not do this for error, stdin, stdout, stderr */
-
- x = _open_osfhandle ( fd, for_write? 1:0 );
- if (x==-1 )
- log_error ("failed to translate osfhandle %p\n", (void*)fd );
- else {
- /*log_info ("_open_osfhandle %p yields %d%s\n",
- (void*)fd, x, for_write? " for writing":"" );*/
- fd = x;
- }
- }
-#endif
- return fd;
-}
-
-static int
-translate_file_handle ( int fd, int for_write )
-{
-#ifdef _WIN32
-#ifdef FILE_FILTER_USES_STDIO
- fd = iobuf_translate_file_handle (fd, for_write);
-#else
- {
- int x;
-
- if ( fd == 0 )
- x = (int)GetStdHandle (STD_INPUT_HANDLE);
- else if (fd == 1)
- x = (int)GetStdHandle (STD_OUTPUT_HANDLE);
- else if (fd == 2)
- x = (int)GetStdHandle (STD_ERROR_HANDLE);
- else
- x = fd;
-
- if (x == -1)
- log_debug ("GetStdHandle(%d) failed: %s\n",
- fd, w32_strerror (0));
-
- fd = x;
- }
-#endif
-#endif
- return fd;
-}
-
-
-void
-iobuf_skip_rest(IOBUF a, unsigned long n, int partial)
-{
- if ( partial ) {
- for (;;) {
- if (a->nofast || a->d.start >= a->d.len) {
- if (iobuf_readbyte (a) == -1) {
- break;
- }
- } else {
- unsigned long count = a->d.len - a->d.start;
- a->nbytes += count;
- a->d.start = a->d.len;
- }
- }
- } else {
- unsigned long remaining = n;
- while (remaining > 0) {
- if (a->nofast || a->d.start >= a->d.len) {
- if (iobuf_readbyte (a) == -1) {
- break;
- }
- --remaining;
- } else {
- unsigned long count = a->d.len - a->d.start;
- if (count > remaining) {
- count = remaining;
- }
- a->nbytes += count;
- a->d.start += count;
- remaining -= count;
- }
- }
- }
-}
diff --git a/util/isascii.c b/util/isascii.c
deleted file mode 100644
index b71febe99..000000000
--- a/util/isascii.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* isascii.c - Replacement for isascii.
- * Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-int
-isascii (int c)
-{
- return (((c) & ~0x7f) == 0);
-}
diff --git a/util/logger.c b/util/logger.c
deleted file mode 100644
index 857436c43..000000000
--- a/util/logger.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/* logger.c - log functions
- * Copyright (C) 1998, 1999 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-
-#include "util.h"
-#include "i18n.h"
-
-static char pidstring[15];
-static char *pgm_name;
-static int errorcount;
-static int strict;
-static FILE *logfp;
-
-/****************
- * Set the logfile to use (not yet implemneted) or, if logfile is NULL,
- * the Fd where logoutputs should go.
- */
-void
-log_set_logfile( const char *name, int fd )
-{
- if( name )
- BUG();
-
- if( logfp && logfp != stderr && logfp != stdout )
- fclose( logfp );
- if( fd == 1 )
- logfp = stdout;
- else if( fd == 2 )
- logfp = stderr;
- else
- logfp = fdopen( fd, "a" );
- if( !logfp ) {
- logfp = stderr;
- log_fatal("can't open fd %d for logging: %s\n", fd, strerror(errno));
- }
-}
-
-FILE *
-log_stream()
-{
- if( !logfp )
- logfp = stderr;
- return logfp;
-}
-
-
-void
-log_set_name( const char *name )
-{
- xfree(pgm_name);
- if( name )
- pgm_name = xstrdup(name);
- else
- pgm_name = NULL;
-}
-
-const char *
-log_get_name(void)
-{
- return pgm_name? pgm_name : "";
-}
-
-
-void
-log_set_pid( int pid )
-{
- if( pid )
- sprintf(pidstring,"[%u]", (unsigned)pid );
- else
- *pidstring = 0;
-}
-
-int
-log_get_errorcount( int clear)
-{
- int n = errorcount;
- if( clear )
- errorcount = 0;
- return n;
-}
-
-void
-log_inc_errorcount()
-{
- errorcount++;
-}
-
-int
-log_set_strict(int val)
-{
- int old=strict;
- strict=val;
- return old;
-}
-
-void
-g10_log_print_prefix(const char *text)
-{
- if( !logfp )
- logfp = stderr;
- if( pgm_name )
- fprintf(logfp, "%s%s: %s", pgm_name, pidstring, text );
- else
- fprintf(logfp, "?%s: %s", pidstring, text );
-#ifdef __riscos__
- fflush( logfp );
-#endif /* __riscos__ */
-}
-
-
-void
-g10_log_info( const char *fmt, ... )
-{
- va_list arg_ptr ;
-
- g10_log_print_prefix("");
- va_start( arg_ptr, fmt ) ;
- vfprintf(logfp,fmt,arg_ptr) ;
- va_end(arg_ptr);
-#ifdef __riscos__
- fflush( logfp );
-#endif /* __riscos__ */
-}
-
-
-void
-g10_log_warning( const char *fmt, ... )
-{
- va_list arg_ptr ;
-
- if(strict)
- {
- errorcount++;
- g10_log_print_prefix(_("ERROR: "));
- }
- else
- g10_log_print_prefix(_("WARNING: "));
-
- va_start( arg_ptr, fmt ) ;
- vfprintf(logfp,fmt,arg_ptr) ;
- va_end(arg_ptr);
-#ifdef __riscos__
- fflush( logfp );
-#endif /* __riscos__ */
-}
-
-
-void
-g10_log_error( const char *fmt, ... )
-{
- va_list arg_ptr ;
-
- g10_log_print_prefix("");
- va_start( arg_ptr, fmt ) ;
- vfprintf(logfp,fmt,arg_ptr) ;
- va_end(arg_ptr);
- errorcount++;
-#ifdef __riscos__
- fflush( logfp );
-#endif /* __riscos__ */
-}
-
-
-void
-g10_log_fatal( const char *fmt, ... )
-{
- va_list arg_ptr ;
-
- g10_log_print_prefix("fatal: ");
- va_start( arg_ptr, fmt ) ;
- vfprintf(logfp,fmt,arg_ptr) ;
- va_end(arg_ptr);
- secmem_dump_stats();
-#ifdef __riscos__
- fflush( logfp );
-#endif /* __riscos__ */
- exit(2);
-}
-
-void
-g10_log_bug( const char *fmt, ... )
-{
- va_list arg_ptr ;
-
- putc('\n', stderr );
- g10_log_print_prefix("Ohhhh jeeee: ");
- va_start( arg_ptr, fmt ) ;
- vfprintf(stderr,fmt,arg_ptr) ;
- va_end(arg_ptr);
- fflush(stderr);
- secmem_dump_stats();
- abort();
-}
-
-#if defined (__riscos__) \
- || ( __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ))
-void
-g10_log_bug0( const char *file, int line, const char *func )
-{
- log_bug(_("... this is a bug (%s:%d:%s)\n"), file, line, func );
-}
-#else
-void
-g10_log_bug0( const char *file, int line )
-{
- log_bug(_("you found a bug ... (%s:%d)\n"), file, line);
-}
-#endif
-
-void
-g10_log_debug( const char *fmt, ... )
-{
- va_list arg_ptr ;
-
- g10_log_print_prefix("DBG: ");
- va_start( arg_ptr, fmt ) ;
- vfprintf(logfp,fmt,arg_ptr) ;
- va_end(arg_ptr);
-#ifdef __riscos__
- fflush( logfp );
-#endif /* __riscos__ */
-}
-
-
-
-void
-g10_log_hexdump( const char *text, const char *buf, size_t len )
-{
- int i;
-
- g10_log_print_prefix(text);
- for(i=0; i < len; i++ )
- fprintf(logfp, " %02X", ((const byte*)buf)[i] );
- fputc('\n', logfp);
-#ifdef __riscos__
- fflush( logfp );
-#endif /* __riscos__ */
-}
-
-
-
diff --git a/util/membuf.c b/util/membuf.c
deleted file mode 100644
index 44347fa1b..000000000
--- a/util/membuf.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* membuf.c - A simple implementation of a dynamic buffer
- * Copyright (C) 2001, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <config.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-
-#include "util.h"
-
-
-/* A simple implementation of a dynamic buffer. Use init_membuf() to
- create a buffer, put_membuf to append bytes and get_membuf to
- release and return the buffer. Allocation errors are detected but
- only returned at the final get_membuf(), this helps not to clutter
- the code with out of core checks. */
-
-void
-init_membuf (membuf_t *mb, int initiallen)
-{
- mb->len = 0;
- mb->size = initiallen;
- mb->out_of_core = 0;
- mb->buf = xmalloc (initiallen);
- if (!mb->buf)
- mb->out_of_core = errno;
-}
-
-
-void
-put_membuf (membuf_t *mb, const void *buf, size_t len)
-{
- if (mb->out_of_core)
- return;
-
- if (mb->len + len >= mb->size)
- {
- char *p;
-
- mb->size += len + 1024;
- p = xrealloc (mb->buf, mb->size);
- mb->buf = p;
- }
- memcpy (mb->buf + mb->len, buf, len);
- mb->len += len;
-}
-
-
-void *
-get_membuf (membuf_t *mb, size_t *len)
-{
- char *p;
-
- if (mb->out_of_core)
- {
- xfree (mb->buf);
- mb->buf = NULL;
- return NULL;
- }
-
- p = mb->buf;
- *len = mb->len;
- mb->buf = NULL;
- mb->out_of_core = ENOMEM; /* hack to make sure it won't get reused. */
- return p;
-}
diff --git a/util/memory.c b/util/memory.c
deleted file mode 100644
index e16c3d8f7..000000000
--- a/util/memory.c
+++ /dev/null
@@ -1,647 +0,0 @@
-/* memory.c - memory allocation
- * Copyright (C) 1998, 1999, 2001, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- *
- *
- * We use our own memory allocation functions instead of plain malloc(),
- * so that we can provide some special enhancements:
- * a) functions to provide memory from a secure memory.
- * b) by looking at the requested allocation size we
- * can reuse memory very quickly (e.g. MPI storage)
- * (really needed?)
- * c) memory usage reporting if compiled with M_DEBUG
- * d) memory checking if compiled with M_GUARD
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-
-#include "types.h"
-#include "memory.h"
-#include "util.h"
-
-
-#define MAGIC_NOR_BYTE 0x55
-#define MAGIC_SEC_BYTE 0xcc
-#define MAGIC_END_BYTE 0xaa
-
-/* This is a very crude alignment check which does not work on all CPUs
- * IIRC, I once introduced it for testing on an Alpha. We should better
- * replace this guard stuff with one provided by a modern malloc library
- */
-#if SIZEOF_UNSIGNED_LONG == 8
-#define EXTRA_ALIGN 4
-#else
-#define EXTRA_ALIGN 0
-#endif
-
-#if defined(M_DEBUG) || defined(M_GUARD)
- static void membug( const char *fmt, ... );
-#endif
-
-#ifdef M_DEBUG
-
-#ifndef M_GUARD
-#define M_GUARD 1
-#endif
-#undef xmalloc
-#undef xmalloc_clear
-#undef xmalloc_secure
-#undef xmalloc_secure_clear
-#undef xrealloc
-#undef xfree
-#undef m_check
-#undef xstrdup
-#define FNAME(a) m_debug_ ##a
-#define FNAMEX(a) m_debug_ ##a
-#define FNAMEXM(a) m_debug_ ##a
-#define FNAMEPRT , const char *info
-#define FNAMEARG , info
-#ifndef __riscos__
-#define store_len(p,n,m) do { add_entry(p,n,m, \
- info, __FUNCTION__); } while(0)
-#else
-#define store_len(p,n,m) do { add_entry(p,n,m, \
- info, __func__ ); } while(0)
-#endif
-#else
-#define FNAME(a) m_ ##a
-#define FNAMEX(a) x ##a
-#define FNAMEXM(a) xm ##a
-#define FNAMEPRT
-#define FNAMEARG
-#define store_len(p,n,m) do { ((byte*)p)[EXTRA_ALIGN+0] = n; \
- ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ; \
- ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ; \
- ((byte*)p)[EXTRA_ALIGN+3] = m? MAGIC_SEC_BYTE \
- : MAGIC_NOR_BYTE; \
- } while(0)
-#endif
-
-
-#ifdef M_GUARD
-static long used_memory;
-#endif
-
-#ifdef M_DEBUG /* stuff used for memory debuging */
-
-struct info_entry {
- struct info_entry *next;
- unsigned count; /* call count */
- const char *info; /* the reference to the info string */
-};
-
-struct memtbl_entry {
- const void *user_p; /* for reference: the pointer given to the user */
- size_t user_n; /* length requested by the user */
- struct memtbl_entry *next; /* to build a list of unused entries */
- const struct info_entry *info; /* points into the table with */
- /* the info strings */
- unsigned inuse:1; /* this entry is in use */
- unsigned count:31;
-};
-
-
-#define INFO_BUCKETS 53
-#define info_hash(p) ( *(u32*)((p)) % INFO_BUCKETS )
-static struct info_entry *info_strings[INFO_BUCKETS]; /* hash table */
-
-static struct memtbl_entry *memtbl; /* the table with the memory info */
-static unsigned memtbl_size; /* number of allocated entries */
-static unsigned memtbl_len; /* number of used entries */
-static struct memtbl_entry *memtbl_unused;/* to keep track of unused entries */
-
-static void dump_table_at_exit(void);
-static void dump_table(void);
-static void check_allmem( const char *info );
-
-/****************
- * Put the new P into the debug table and return a pointer to the table entry.
- * mode is true for security. BY is the name of the function which called us.
- */
-static void
-add_entry( byte *p, unsigned n, int mode, const char *info, const char *by )
-{
- unsigned index;
- struct memtbl_entry *e;
- struct info_entry *ie;
-
- if( memtbl_len < memtbl_size )
- index = memtbl_len++;
- else {
- struct memtbl_entry *e;
- /* look for a used entry in the table. We take the first one,
- * so that freed entries remain as long as possible in the table
- * (free appends a new one)
- */
- if( (e = memtbl_unused) ) {
- index = e - memtbl;
- memtbl_unused = e->next;
- e->next = NULL;
- }
- else { /* no free entries in the table: extend the table */
- if( !memtbl_size ) { /* first time */
- memtbl_size = 100;
- if( !(memtbl = calloc( memtbl_size, sizeof *memtbl )) )
- membug("memory debug table malloc failed\n");
- index = 0;
- memtbl_len = 1;
- atexit( dump_table_at_exit );
- }
- else { /* realloc */
- unsigned n = memtbl_size / 4; /* enlarge by 25% */
- if(!(memtbl = realloc(memtbl, (memtbl_size+n)*sizeof *memtbl)))
- membug("memory debug table realloc failed\n");
- memset(memtbl+memtbl_size, 0, n*sizeof *memtbl );
- memtbl_size += n;
- index = memtbl_len++;
- }
- }
- }
- e = memtbl+index;
- if( e->inuse )
- membug("Ooops: entry %u is flagged as in use\n", index);
- e->user_p = p + EXTRA_ALIGN + 4;
- e->user_n = n;
- e->count++;
- if( e->next )
- membug("Ooops: entry is in free entry list\n");
- /* do we already have this info string */
- for( ie = info_strings[info_hash(info)]; ie; ie = ie->next )
- if( ie->info == info )
- break;
- if( !ie ) { /* no: make a new entry */
- if( !(ie = malloc( sizeof *ie )) )
- membug("can't allocate info entry\n");
- ie->next = info_strings[info_hash(info)];
- info_strings[info_hash(info)] = ie;
- ie->info = info;
- ie->count = 0;
- }
- ie->count++;
- e->info = ie;
- e->inuse = 1;
-
- /* put the index at the start of the memory */
- p[EXTRA_ALIGN+0] = index;
- p[EXTRA_ALIGN+1] = index >> 8 ;
- p[EXTRA_ALIGN+2] = index >> 16 ;
- p[EXTRA_ALIGN+3] = mode? MAGIC_SEC_BYTE : MAGIC_NOR_BYTE ;
- if( DBG_MEMORY )
- log_debug( "%s allocates %u bytes using %s\n", info, e->user_n, by );
-}
-
-
-
-/****************
- * Check that the memory block is correct. The magic byte has already been
- * checked. Checks which are done here:
- * - see whether the index points into our memory table
- * - see whether P is the same as the one stored in the table
- * - see whether we have already freed this block.
- */
-struct memtbl_entry *
-check_mem( const byte *p, const char *info )
-{
- unsigned n;
- struct memtbl_entry *e;
-
- n = p[EXTRA_ALIGN+0];
- n |= p[EXTRA_ALIGN+1] << 8;
- n |= p[EXTRA_ALIGN+2] << 16;
-
- if( n >= memtbl_len )
- membug("memory at %p corrupted: index=%u table_len=%u (%s)\n",
- p+EXTRA_ALIGN+4, n, memtbl_len, info );
- e = memtbl+n;
-
- if( e->user_p != p+EXTRA_ALIGN+4 )
- membug("memory at %p corrupted: reference mismatch (%s)\n",
- p+EXTRA_ALIGN+4, info );
- if( !e->inuse )
- membug("memory at %p corrupted: marked as free (%s)\n",
- p+EXTRA_ALIGN+4, info );
-
- if( !(p[EXTRA_ALIGN+3] == MAGIC_NOR_BYTE
- || p[EXTRA_ALIGN+3] == MAGIC_SEC_BYTE) )
- membug("memory at %p corrupted: underflow=%02x (%s)\n",
- p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+3], info );
- if( p[EXTRA_ALIGN+4+e->user_n] != MAGIC_END_BYTE )
- membug("memory at %p corrupted: overflow=%02x (%s)\n",
- p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+4+e->user_n], info );
- return e;
-}
-
-
-/****************
- * free the entry and the memory (replaces free)
- */
-static void
-free_entry( byte *p, const char *info )
-{
- struct memtbl_entry *e, *e2;
-
- check_allmem("add_entry");
-
- e = check_mem(p, info);
- if( DBG_MEMORY )
- log_debug( "%s frees %u bytes alloced by %s\n",
- info, e->user_n, e->info->info );
- if( !e->inuse ) {
- if( e->user_p == p + EXTRA_ALIGN+ 4 )
- membug("freeing an already freed pointer at %p\n", p+EXTRA_ALIGN+4 );
- else
- membug("freeing pointer %p which is flagged as freed\n", p+EXTRA_ALIGN+4 );
- }
-
- e->inuse = 0;
- e->next = NULL;
- if( !memtbl_unused )
- memtbl_unused = e;
- else {
- for(e2=memtbl_unused; e2->next; e2 = e2->next )
- ;
- e2->next = e;
- }
- if( m_is_secure(p+EXTRA_ALIGN+4) )
- secmem_free(p);
- else {
- memset(p,'f', e->user_n+5);
- free(p);
- }
-}
-
-static void
-dump_entry(struct memtbl_entry *e )
-{
- unsigned n = e - memtbl;
-
- fprintf(stderr, "mem %4u%c %5u %p %5u %s (%u)\n",
- n, e->inuse?'a':'u', e->count, e->user_p, e->user_n,
- e->info->info, e->info->count );
-
-
-}
-
-
-static void
-dump_table_at_exit( void)
-{
- if( DBG_MEMSTAT )
- dump_table();
-}
-
-static void
-dump_table( void)
-{
- unsigned n;
- struct memtbl_entry *e;
- ulong sum = 0, chunks =0;
-
- for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
- if(e->inuse) {
- dump_entry(e);
- sum += e->user_n;
- chunks++;
- }
- }
- fprintf(stderr, " memory used: %8lu bytes in %ld chunks\n",
- sum, chunks );
-}
-
-
-static void
-check_allmem( const char *info )
-{
- unsigned n;
- struct memtbl_entry *e;
-
- for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
- if( e->inuse ) {
-#ifndef __riscos__
- check_mem(e->user_p-4-EXTRA_ALIGN, info);
-#else
- check_mem((const byte *) e->user_p-4-EXTRA_ALIGN, info);
-#endif
- }
- }
-}
-
-#endif /* M_DEBUG */
-
-#if defined(M_DEBUG) || defined(M_GUARD)
-static void
-membug( const char *fmt, ... )
-{
- va_list arg_ptr ;
-
- fprintf(stderr, "\nMemory Error: " ) ;
- va_start( arg_ptr, fmt ) ;
- vfprintf(stderr,fmt,arg_ptr) ;
- va_end(arg_ptr);
- fflush(stderr);
-#ifdef M_DEBUG
- if( DBG_MEMSTAT )
- dump_table();
-#endif
- abort();
-}
-#endif
-
-void
-m_print_stats( const char *prefix )
-{
-#ifdef M_DEBUG
- unsigned n;
- struct memtbl_entry *e;
- ulong sum = 0, chunks =0;
-
- for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
- if(e->inuse) {
- sum += e->user_n;
- chunks++;
- }
- }
-
- log_debug( "%s%smemstat: %8lu bytes in %ld chunks used\n",
- prefix? prefix:"", prefix? ": ":"", sum, chunks );
-#elif defined(M_GUARD)
- log_debug( "%s%smemstat: %8ld bytes\n",
- prefix? prefix:"", prefix? ": ":"", used_memory );
-#endif
-}
-
-void
-m_dump_table( const char *prefix )
-{
-#ifdef M_DEBUG
- fprintf(stderr,"Memory-Table-Dump: %s\n", prefix);
- dump_table();
-#endif
- m_print_stats( prefix );
-}
-
-
-static void
-out_of_core(size_t n, int secure)
-{
- log_error ("out of %s memory while allocating %u bytes\n",
- secure? "secure":"" ,(unsigned)n );
- if (secure) {
- /*secmem_dump_stats ();*/
- log_info ("(this may be caused by too many secret keys used "
- "simultaneously or due to excessive large key sizes)\n");
- }
-#if defined(M_GUARD) && defined(__riscos__)
- abort();
-#endif
- exit (2);
-}
-
-/****************
- * Allocate memory of size n.
- * This function gives up if we do not have enough memory
- */
-void *
-FNAMEXM(alloc)( size_t n FNAMEPRT )
-{
- char *p;
-
-#ifdef M_GUARD
- if(!n)
- out_of_core(n,0); /* should never happen */
- if( !(p = malloc( n + EXTRA_ALIGN+5 )) )
- out_of_core(n,0);
- store_len(p,n,0);
- used_memory += n;
- p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
- return p+EXTRA_ALIGN+4;
-#else
- /* mallocing zero bytes is undefined by ISO-C, so we better make
- sure that it won't happen */
- if (!n)
- n = 1;
- if( !(p = malloc( n )) )
- out_of_core(n,0);
- return p;
-#endif
-}
-
-/****************
- * Allocate memory of size n from the secure memory pool.
- * This function gives up if we do not have enough memory
- */
-void *
-FNAMEXM(alloc_secure)( size_t n FNAMEPRT )
-{
- char *p;
-
-#ifdef M_GUARD
- if(!n)
- out_of_core(n,1); /* should never happen */
- if( !(p = secmem_malloc( n +EXTRA_ALIGN+ 5 )) )
- out_of_core(n,1);
- store_len(p,n,1);
- p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
- return p+EXTRA_ALIGN+4;
-#else
- /* mallocing zero bytes is undefined by ISO-C, so we better make
- sure that it won't happen */
- if (!n)
- n = 1;
- if( !(p = secmem_malloc( n )) )
- out_of_core(n,1);
- return p;
-#endif
-}
-
-void *
-FNAMEXM(alloc_clear)( size_t n FNAMEPRT )
-{
- void *p;
- p = FNAMEXM(alloc)( n FNAMEARG );
- memset(p, 0, n );
- return p;
-}
-
-void *
-FNAMEXM(alloc_secure_clear)( size_t n FNAMEPRT)
-{
- void *p;
- p = FNAMEXM(alloc_secure)( n FNAMEARG );
- memset(p, 0, n );
- return p;
-}
-
-
-/****************
- * realloc and clear the old space
- */
-void *
-FNAMEX(realloc)( void *a, size_t n FNAMEPRT )
-{
- void *b;
-
-#ifdef M_GUARD
- if( a ) {
-#error "--enable-m-guard does not currently work"
- unsigned char *p = a;
- size_t len = m_size(a);
-
- if( len >= n ) /* we don't shrink for now */
- return a;
- if( p[-1] == MAGIC_SEC_BYTE )
- b = FNAME(alloc_secure_clear)(n FNAMEARG);
- else
- b = FNAME(alloc_clear)(n FNAMEARG);
- FNAME(check)(NULL FNAMEARG);
- memcpy(b, a, len );
- FNAME(free)(p FNAMEARG);
- }
- else
- b = FNAME(alloc)(n FNAMEARG);
-#else
- if( m_is_secure(a) ) {
- if( !(b = secmexrealloc( a, n )) )
- out_of_core(n,1);
- }
- else {
- if( !(b = realloc( a, n )) )
- out_of_core(n,0);
- }
-#endif
-
- return b;
-}
-
-
-
-/****************
- * Free a pointer
- */
-void
-FNAMEX(free)( void *a FNAMEPRT )
-{
- byte *p = a;
-
- if( !p )
- return;
-#ifdef M_DEBUG
- free_entry(p-EXTRA_ALIGN-4, info);
-#elif defined M_GUARD
- m_check(p);
- if( m_is_secure(a) )
- secmem_free(p-EXTRA_ALIGN-4);
- else {
- used_memory -= m_size(a);
- free(p-EXTRA_ALIGN-4);
- }
-#else
- if( m_is_secure(a) )
- secmem_free(p);
- else
- free(p);
-#endif
-}
-
-
-void
-FNAME(check)( const void *a FNAMEPRT )
-{
-#ifdef M_GUARD
- const byte *p = a;
-
-#ifdef M_DEBUG
- if( p )
- check_mem(p-EXTRA_ALIGN-4, info);
- else
- check_allmem(info);
-#else
- if( !p )
- return;
- if( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) )
- membug("memory at %p corrupted (underflow=%02x)\n", p, p[-1] );
- else if( p[m_size(p)] != MAGIC_END_BYTE )
- membug("memory at %p corrupted (overflow=%02x)\n", p, p[-1] );
-#endif
-#endif
-}
-
-
-size_t
-m_size( const void *a )
-{
-#ifndef M_GUARD
- log_debug("dummy m_size called\n");
- return 0;
-#else
- const byte *p = a;
- size_t n;
-
-#ifdef M_DEBUG
- n = check_mem(p-EXTRA_ALIGN-4, "m_size")->user_n;
-#else
- n = ((byte*)p)[-4];
- n |= ((byte*)p)[-3] << 8;
- n |= ((byte*)p)[-2] << 16;
-#endif
- return n;
-#endif
-}
-
-
-char *
-FNAMEX(strdup)( const char *a FNAMEPRT )
-{
- size_t n = strlen(a);
- char *p = FNAMEXM(alloc)(n+1 FNAMEARG);
- strcpy(p, a);
- return p;
-}
-
-
-/* Wrapper around xmalloc_clear to take the usual 2 arguments of a
- calloc style function. */
-void *
-xcalloc (size_t n, size_t m)
-{
- size_t nbytes;
-
- nbytes = n * m;
- if (m && nbytes / m != n)
- out_of_core (nbytes, 0);
- return xmalloc_clear (nbytes);
-}
-
-/* Wrapper around xmalloc_csecure_lear to take the usual 2 arguments
- of a calloc style function. */
-void *
-xcalloc_secure (size_t n, size_t m)
-{
- size_t nbytes;
-
- nbytes = n * m;
- if (m && nbytes / m != n)
- out_of_core (nbytes, 1);
- return xmalloc_secure_clear (nbytes);
-}
-
diff --git a/util/memrchr.c b/util/memrchr.c
deleted file mode 100644
index 5621f7323..000000000
--- a/util/memrchr.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/* memrchr.c - libc replacement function
- * Copyright (C) 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-/*
- memrchr() is a GNU function that might not be available everywhere.
- It's basically the inverse of memchr() - search backwards in a
- memory block for a particular character.
-*/
-
-#include <config.h>
-#include <string.h>
-
-/* There are many ways to optimize this, but this is a simple
- unoptimized implementation. */
-void *
-memrchr(const void *s, int c, size_t n)
-{
- const unsigned char *start=s,*end=s;
-
- end+=n-1;
-
- while(end>=start)
- {
- if(*end==c)
- return (void *)end;
- else
- end--;
- }
-
- return NULL;
-}
diff --git a/util/miscutil.c b/util/miscutil.c
deleted file mode 100644
index 698e80691..000000000
--- a/util/miscutil.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/* miscutil.c - miscellaneous utilities
- * Copyright (C) 1998, 1999, 2000, 2001, 2003,
- * 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <config.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <ctype.h>
-#ifdef HAVE_LANGINFO_H
-#include <langinfo.h>
-#endif
-#include "types.h"
-#include "util.h"
-#include "i18n.h"
-
-/****************
- * I know that the OpenPGP protocol has a Y2106 problem ;-)
- */
-u32
-make_timestamp()
-{
- return time(NULL);
-}
-
-/****************
- * Scan a date string and return a timestamp.
- * The only supported format is "yyyy-mm-dd"
- * Returns 0 for an invalid date.
- */
-u32
-scan_isodatestr( const char *string )
-{
- int year, month, day;
- struct tm tmbuf;
- time_t stamp;
- int i;
-
- if( strlen(string) != 10 || string[4] != '-' || string[7] != '-' )
- return 0;
- for( i=0; i < 4; i++ )
- if( !digitp(string+i) )
- return 0;
- if( !digitp(string+5) || !digitp(string+6) )
- return 0;
- if( !digitp(string+8) || !digitp(string+9) )
- return 0;
- year = atoi(string);
- month = atoi(string+5);
- day = atoi(string+8);
- /* some basic checks */
- if( year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 )
- return 0;
- memset( &tmbuf, 0, sizeof tmbuf );
- tmbuf.tm_mday = day;
- tmbuf.tm_mon = month-1;
- tmbuf.tm_year = year - 1900;
- tmbuf.tm_isdst = -1;
- stamp = mktime( &tmbuf );
- if( stamp == (time_t)-1 )
- return 0;
- return stamp;
-}
-
-
-/****************
- * Return a string with a time value in the form: x Y, n D, n H
- */
-
-const char *
-strtimevalue( u32 value )
-{
- static char buffer[30];
- unsigned int years, days, hours, minutes;
-
- value /= 60;
- minutes = value % 60;
- value /= 60;
- hours = value % 24;
- value /= 24;
- days = value % 365;
- value /= 365;
- years = value;
-
- sprintf(buffer,"%uy%ud%uh%um", years, days, hours, minutes );
- if( years )
- return buffer;
- if( days )
- return strchr( buffer, 'y' ) + 1;
- return strchr( buffer, 'd' ) + 1;
-}
-
-
-/****************
- * Note: this function returns GMT
- */
-const char *
-strtimestamp( u32 stamp )
-{
- static char buffer[11+5];
- struct tm *tp;
- time_t atime = stamp;
-
- if (atime < 0) {
- strcpy (buffer, "????" "-??" "-??");
- }
- else {
- tp = gmtime( &atime );
- sprintf(buffer,"%04d-%02d-%02d",
- 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
- }
- return buffer;
-}
-
-
-/****************
- * Note: this function returns GMT
- */
-const char *
-isotimestamp (u32 stamp)
-{
- static char buffer[25+5];
- struct tm *tp;
- time_t atime = stamp;
-
- if (atime < 0) {
- strcpy (buffer, "????" "-??" "-??" " " "??" ":" "??" ":" "??");
- }
- else {
- tp = gmtime( &atime );
- sprintf(buffer,"%04d-%02d-%02d %02d:%02d:%02d",
- 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
- tp->tm_hour, tp->tm_min, tp->tm_sec);
- }
- return buffer;
-}
-
-/****************
- * Note: this function returns local time
- */
-const char *
-asctimestamp( u32 stamp )
-{
- static char buffer[50];
-#if defined (HAVE_STRFTIME) && defined (HAVE_NL_LANGINFO)
- static char fmt[50];
-#endif
- struct tm *tp;
- time_t atime = stamp;
-
- if (atime < 0) {
- strcpy (buffer, "????" "-??" "-??");
- return buffer;
- }
-
- tp = localtime( &atime );
-#ifdef HAVE_STRFTIME
-#if defined(HAVE_NL_LANGINFO)
- mem2str( fmt, nl_langinfo(D_T_FMT), DIM(fmt)-3 );
- if( strstr( fmt, "%Z" ) == NULL )
- strcat( fmt, " %Z");
- strftime( buffer, DIM(buffer)-1, fmt, tp );
-#else
- /* fixme: we should check whether the locale appends a " %Z"
- * These locales from glibc don't put the " %Z":
- * fi_FI hr_HR ja_JP lt_LT lv_LV POSIX ru_RU ru_SU sv_FI sv_SE zh_CN
- */
- strftime( buffer, DIM(buffer)-1,
-#ifdef HAVE_W32_SYSTEM
- "%c"
-#else
- "%c %Z"
-#endif
- , tp );
-#endif
- buffer[DIM(buffer)-1] = 0;
-#else
- mem2str( buffer, asctime(tp), DIM(buffer) );
-#endif
- return buffer;
-}
-
-
-/****************
- * Print a string to FP, but filter all control characters out.
- */
-void
-print_string2( FILE *fp, const byte *p, size_t n, int delim, int delim2 )
-{
- for( ; n; n--, p++ )
- if( *p < 0x20 || (*p >= 0x7f && *p < 0xa0)
- || *p == delim || *p == delim2
- || ((delim || delim2) && *p=='\\'))
- {
- putc('\\', fp);
- if( *p == '\n' )
- putc('n', fp);
- else if( *p == '\r' )
- putc('r', fp);
- else if( *p == '\f' )
- putc('f', fp);
- else if( *p == '\v' )
- putc('v', fp);
- else if( *p == '\b' )
- putc('b', fp);
- else if( !*p )
- putc('0', fp);
- else
- fprintf(fp, "x%02x", *p );
- }
- else
- putc(*p, fp);
-}
-
-void
-print_string( FILE *fp, const byte *p, size_t n, int delim )
-{
- print_string2(fp,p,n,delim,0);
-}
-
-/****************
- * Print an UTF8 string to FP and filter all control characters out.
- */
-void
-print_utf8_string2 ( FILE *fp, const byte *p, size_t n, int delim )
-{
- size_t i;
- char *buf;
-
- /* we can handle plain ascii simpler, so check for it first */
- for(i=0; i < n; i++ ) {
- if( p[i] & 0x80 )
- break;
- }
- if( i < n ) {
- buf = utf8_to_native ( p, n, delim );
- /*(utf8 conversion already does the control character quoting)*/
- fputs( buf, fp );
- xfree( buf );
- }
- else
- print_string( fp, p, n, delim );
-}
-
-void
-print_utf8_string( FILE *fp, const byte *p, size_t n )
-{
- print_utf8_string2 (fp, p, n, 0);
-}
-
-/****************
- * This function returns a string which is suitable for printing
- * Caller must release it with xfree()
- */
-char *
-make_printable_string( const byte *p, size_t n, int delim )
-{
- size_t save_n, buflen;
- const byte *save_p;
- char *buffer, *d;
-
- /* first count length */
- for(save_n = n, save_p = p, buflen=1 ; n; n--, p++ ) {
- if( *p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim ||
- (delim && *p=='\\')) {
- if( *p=='\n' || *p=='\r' || *p=='\f'
- || *p=='\v' || *p=='\b' || !*p )
- buflen += 2;
- else
- buflen += 4;
- }
- else
- buflen++;
- }
- p = save_p;
- n = save_n;
- /* and now make the string */
- d = buffer = xmalloc( buflen );
- for( ; n; n--, p++ ) {
- if( *p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim ||
- (delim && *p=='\\')) {
- *d++ = '\\';
- if( *p == '\n' )
- *d++ = 'n';
- else if( *p == '\r' )
- *d++ = 'r';
- else if( *p == '\f' )
- *d++ = 'f';
- else if( *p == '\v' )
- *d++ = 'v';
- else if( *p == '\b' )
- *d++ = 'b';
- else if( !*p )
- *d++ = '0';
- else {
- sprintf(d, "x%02x", *p );
- d += 3;
- }
- }
- else
- *d++ = *p;
- }
- *d = 0;
- return buffer;
-}
-
-int
-answer_is_yes_no_default( const char *s, int def_answer )
-{
- /* TRANSLATORS: See doc/TRANSLATE about this string. */
- const char *long_yes = _("yes");
- const char *short_yes = _("yY");
- /* TRANSLATORS: See doc/TRANSLATE about this string. */
- const char *long_no = _("no");
- const char *short_no = _("nN");
-
- /* Note: we have to use the local dependent strcasecmp here */
- if( match_multistr(long_yes,s) )
- return 1;
- if( *s && strchr( short_yes, *s ) && !s[1] )
- return 1;
- /* test for no strings to catch ambiguities for the next test */
- if( match_multistr(long_no,s) )
- return 0;
- if( *s && strchr( short_no, *s ) && !s[1] )
- return 0;
- /* test for the english version (for those who are used to type yes) */
- if( !ascii_strcasecmp(s, "yes" ) )
- return 1;
- if( *s && strchr( "yY", *s ) && !s[1] )
- return 1;
- return def_answer;
-}
-
-int
-answer_is_yes( const char *s )
-{
- return answer_is_yes_no_default(s,0);
-}
-
-/****************
- * Return 1 for yes, -1 for quit, or 0 for no
- */
-int
-answer_is_yes_no_quit( const char *s )
-{
- /* TRANSLATORS: See doc/TRANSLATE about this string. */
- const char *long_yes = _("yes");
- /* TRANSLATORS: See doc/TRANSLATE about this string. */
- const char *long_no = _("no");
- /* TRANSLATORS: See doc/TRANSLATE about this string. */
- const char *long_quit = _("quit");
- const char *short_yes = _("yY");
- const char *short_no = _("nN");
- const char *short_quit = _("qQ");
-
- if( match_multistr(long_no,s) )
- return 0;
- if( match_multistr(long_yes,s) )
- return 1;
- if( match_multistr(long_quit,s) )
- return -1;
- if( *s && strchr( short_no, *s ) && !s[1] )
- return 0;
- if( *s && strchr( short_yes, *s ) && !s[1] )
- return 1;
- if( *s && strchr( short_quit, *s ) && !s[1] )
- return -1;
- /* but not here */
- if( !ascii_strcasecmp(s, "yes" ) )
- return 1;
- if( !ascii_strcasecmp(s, "quit" ) )
- return -1;
- if( *s && strchr( "yY", *s ) && !s[1] )
- return 1;
- if( *s && strchr( "qQ", *s ) && !s[1] )
- return -1;
- return 0;
-}
-
-/*
- Return 1 for okay, 0 for for cancel or DEF_ANSWER for default.
- */
-int
-answer_is_okay_cancel (const char *s, int def_answer)
-{
- /* TRANSLATORS: See doc/TRANSLATE about this string. */
- const char *long_okay = _("okay|okay");
- /* TRANSLATORS: See doc/TRANSLATE about this string. */
- const char *long_cancel = _("cancel|cancel");
- const char *short_okay = _("oO");
- const char *short_cancel = _("cC");
-
- /* Note: We have to use the locale dependent strcasecmp */
- if ( match_multistr(long_okay,s) )
- return 1;
- if ( match_multistr(long_cancel,s) )
- return 0;
- if ( *s && strchr( short_okay, *s ) && !s[1] )
- return 1;
- if ( *s && strchr( short_cancel, *s ) && !s[1] )
- return 0;
- /* Always test for the English values (not locale here) */
- if ( !ascii_strcasecmp(s, "okay" ) )
- return 1;
- if ( !ascii_strcasecmp(s, "ok" ) )
- return 1;
- if ( !ascii_strcasecmp(s, "cancel" ) )
- return 0;
- if ( *s && strchr( "oO", *s ) && !s[1] )
- return 1;
- if ( *s && strchr( "cC", *s ) && !s[1] )
- return 0;
- return def_answer;
-}
-
-/* Try match against each substring of multistr, delimited by | */
-int
-match_multistr(const char *multistr,const char *match)
-{
- do
- {
- size_t seglen=strcspn(multistr,"|");
- if(!seglen)
- break;
- /* Using the localized strncasecmp */
- if(strncasecmp(multistr,match,seglen)==0)
- return 1;
- multistr+=seglen;
- if(*multistr=='|')
- multistr++;
- }
- while(*multistr);
-
- return 0;
-}
-
-int
-hextobyte( const char *s )
-{
- int c;
-
- if( *s >= '0' && *s <= '9' )
- c = 16 * (*s - '0');
- else if( *s >= 'A' && *s <= 'F' )
- c = 16 * (10 + *s - 'A');
- else if( *s >= 'a' && *s <= 'f' )
- c = 16 * (10 + *s - 'a');
- else
- return -1;
- s++;
- if( *s >= '0' && *s <= '9' )
- c += *s - '0';
- else if( *s >= 'A' && *s <= 'F' )
- c += 10 + *s - 'A';
- else if( *s >= 'a' && *s <= 'f' )
- c += 10 + *s - 'a';
- else
- return -1;
- return c;
-}
diff --git a/util/mkdtemp.c b/util/mkdtemp.c
deleted file mode 100644
index c0ee0bbdb..000000000
--- a/util/mkdtemp.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/* mkdtemp.c - libc replacement function
- * Copyright (C) 2001 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-/* This is a replacement function for mkdtemp in case the platform
- we're building on (like mine!) doesn't have it. */
-
-#include <config.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include "types.h"
-#include "cipher.h"
-
-#ifdef MKDIR_TAKES_ONE_ARG
-# undef mkdir
-# define mkdir(a,b) mkdir(a)
-#endif
-
-char *mkdtemp(char *template)
-{
- unsigned int attempts,idx,count=0;
- char *ch;
-
- idx=strlen(template);
-
- /* Walk backwards to count all the Xes */
- while(idx>0 && template[idx-1]=='X')
- {
- count++;
- idx--;
- }
-
- if(count==0)
- {
- errno=EINVAL;
- return NULL;
- }
-
- ch=&template[idx];
-
- /* Try 4 times to make the temp directory */
- for(attempts=0;attempts<4;attempts++)
- {
- unsigned int remaining=count;
- char *marker=ch;
- byte *randombits;
-
- idx=0;
-
- /* Using really random bits is probably overkill here. The
- worst thing that can happen with a directory name collision
- is that the function will return an error. */
-
- randombits=get_random_bits(4*remaining,0,0);
-
- while(remaining>1)
- {
- sprintf(marker,"%02X",randombits[idx++]);
- marker+=2;
- remaining-=2;
- }
-
- /* Any leftover Xes? get_random_bits rounds up to full bytes,
- so this is safe. */
- if(remaining>0)
- sprintf(marker,"%X",randombits[idx]&0xF);
-
- xfree(randombits);
-
- if(mkdir(template,0700)==0)
- break;
- }
-
- if(attempts==4)
- return NULL; /* keeps the errno from mkdir, whatever it is */
-
- return template;
-}
diff --git a/util/pka.c b/util/pka.c
deleted file mode 100644
index 3c9e5c437..000000000
--- a/util/pka.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/* pka.c - DNS Public Key Association RR access
- * Copyright (C) 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef USE_DNS_PKA
-#include <sys/types.h>
-#ifdef _WIN32
-#include <windows.h>
-#else
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-#endif
-#endif /* USE_DNS_PKA */
-
-#include "memory.h"
-#include "types.h"
-#include "util.h"
-
-
-#ifdef USE_DNS_PKA
-/* Parse the TXT resource record. Format is:
-
- v=pka1;fpr=a4d94e92b0986ab5ee9dcd755de249965b0358a2;uri=string
-
- For simplicity white spaces are not allowed. Because we expect to
- use a new RRTYPE for this in the future we define the TXT really
- strict for simplicity: No white spaces, case sensitivity of the
- names, order must be as given above. Only URI is optional.
-
- This function modifies BUFFER. On success 0 is returned, the 20
- byte fingerprint stored at FPR and BUFFER contains the URI or an
- empty string.
-*/
-static int
-parse_txt_record (char *buffer, unsigned char *fpr)
-{
- char *p, *pend;
- int i;
-
- p = buffer;
- pend = strchr (p, ';');
- if (!pend)
- return -1;
- *pend++ = 0;
- if (strcmp (p, "v=pka1"))
- return -1; /* Wrong or missing version. */
-
- p = pend;
- pend = strchr (p, ';');
- if (pend)
- *pend++ = 0;
- if (strncmp (p, "fpr=", 4))
- return -1; /* Missing fingerprint part. */
- p += 4;
- for (i=0; i < 20 && hexdigitp (p) && hexdigitp (p+1); i++, p += 2)
- fpr[i] = xtoi_2 (p);
- if (i != 20)
- return -1; /* Fingerprint consists not of exactly 40 hexbytes. */
-
- p = pend;
- if (!p || !*p)
- {
- *buffer = 0;
- return 0; /* Success (no URI given). */
- }
- if (strncmp (p, "uri=", 4))
- return -1; /* Unknown part. */
- p += 4;
- /* There is an URI, copy it to the start of the buffer. */
- while (*p)
- *buffer++ = *p++;
- *buffer = 0;
- return 0;
-}
-
-
-/* For the given email ADDRESS lookup the PKA information in the DNS.
-
- On success the 20 byte SHA-1 fingerprint is stored at FPR and the
- URI will be returned in an allocated buffer. Note that the URI
- might be an zero length string as this information is optiobnal.
- Caller must xfree the returned string.
-
- On error NULL is returned and the 20 bytes at FPR are not
- defined. */
-char *
-get_pka_info (const char *address, unsigned char *fpr)
-{
- unsigned char answer[PACKETSZ];
- int anslen;
- int qdcount, ancount, nscount, arcount;
- int rc;
- unsigned char *p, *pend;
- const char *domain;
- char *name;
-
-
- domain = strrchr (address, '@');
- if (!domain || domain == address || !domain[1])
- return NULL; /* invalid mail address given. */
-
- name = malloc (strlen (address) + 5 + 1);
- memcpy (name, address, domain - address);
- strcpy (stpcpy (name + (domain-address), "._pka."), domain+1);
-
- anslen = res_query (name, C_IN, T_TXT, answer, PACKETSZ);
- xfree (name);
- if (anslen < sizeof(HEADER))
- return NULL; /* DNS resolver returned a too short answer. */
- if ( (rc=((HEADER*)answer)->rcode) != NOERROR )
- return NULL; /* DNS resolver returned an error. */
-
- /* We assume that PACKETSZ is large enough and don't do dynmically
- expansion of the buffer. */
- if (anslen > PACKETSZ)
- return NULL; /* DNS resolver returned a too long answer */
-
- qdcount = ntohs (((HEADER*)answer)->qdcount);
- ancount = ntohs (((HEADER*)answer)->ancount);
- nscount = ntohs (((HEADER*)answer)->nscount);
- arcount = ntohs (((HEADER*)answer)->arcount);
-
- if (!ancount)
- return NULL; /* Got no answer. */
-
- p = answer + sizeof (HEADER);
- pend = answer + anslen; /* Actually points directly behind the buffer. */
-
- while (qdcount-- && p < pend)
- {
- rc = dn_skipname (p, pend);
- if (rc == -1)
- return NULL;
- p += rc + QFIXEDSZ;
- }
-
- if (ancount > 1)
- return NULL; /* more than one possible gpg trustdns record - none used. */
-
- while (ancount-- && p <= pend)
- {
- unsigned int type, class, txtlen, n;
- char *buffer, *bufp;
-
- rc = dn_skipname (p, pend);
- if (rc == -1)
- return NULL;
- p += rc;
- if (p >= pend - 10)
- return NULL; /* RR too short. */
-
- type = *p++ << 8;
- type |= *p++;
- class = *p++ << 8;
- class |= *p++;
- p += 4;
- txtlen = *p++ << 8;
- txtlen |= *p++;
- if (type != T_TXT || class != C_IN)
- return NULL; /* Answer does not match the query. */
-
- buffer = bufp = xmalloc (txtlen + 1);
- while (txtlen && p < pend)
- {
- for (n = *p++, txtlen--; txtlen && n && p < pend; txtlen--, n--)
- *bufp++ = *p++;
- }
- *bufp = 0;
- if (parse_txt_record (buffer, fpr))
- {
- xfree (buffer);
- return NULL; /* Not a valid gpg trustdns RR. */
- }
- return buffer;
- }
-
- return NULL;
-}
-#else /* !USE_DNS_PKA */
-
-/* Dummy version of the function if we can't use the resolver
- functions. */
-char *
-get_pka_info (const char *address, unsigned char *fpr)
-{
- return NULL;
-}
-#endif /* !USE_DNS_PKA */
-
-
-#ifdef TEST
-int
-main(int argc,char *argv[])
-{
- unsigned char fpr[20];
- char *uri;
- int i;
-
- if (argc < 2)
- {
- fprintf (stderr, "usage: pka mail-addresses\n");
- return 1;
- }
- argc--;
- argv++;
-
- for (; argc; argc--, argv++)
- {
- uri = get_pka_info ( *argv, fpr );
- printf ("%s", *argv);
- if (uri)
- {
- putchar (' ');
- for (i=0; i < 20; i++)
- printf ("%02X", fpr[i]);
- if (*uri)
- printf (" %s", uri);
- xfree (uri);
- }
- putchar ('\n');
- }
- return 0;
-}
-#endif /* TEST */
-
-/*
-Local Variables:
-compile-command: "cc -DUSE_DNS_PKA -DTEST -I.. -I../include -Wall -g -o pka pka.c -lresolv libutil.a"
-End:
-*/
diff --git a/util/regcomp.c b/util/regcomp.c
deleted file mode 100644
index 766339945..000000000
--- a/util/regcomp.c
+++ /dev/null
@@ -1,3495 +0,0 @@
-/* Extended regular expression matching and search library.
- Copyright (C) 2002 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Isamu Hasegawa <[email protected]>.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02110-1301 USA. */
-
-#include <assert.h>
-#include <ctype.h>
-#include <limits.h>
-#include <locale.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if defined(_WIN32) && !defined (MB_CUR_MAX)
-#define MB_CUR_MAX 2
-#endif
-
-#if defined HAVE_WCHAR_H || defined _LIBC
-# include <wchar.h>
-#endif /* HAVE_WCHAR_H || _LIBC */
-#if defined HAVE_WCTYPE_H || defined _LIBC
-# include <wctype.h>
-#endif /* HAVE_WCTYPE_H || _LIBC */
-
-/* In case that the system doesn't have isblank(). */
-#if !defined _LIBC && !defined HAVE_ISBLANK && !defined isblank
-# define isblank(ch) ((ch) == ' ' || (ch) == '\t')
-#endif
-
-#ifdef _LIBC
-# ifndef _RE_DEFINE_LOCALE_FUNCTIONS
-# define _RE_DEFINE_LOCALE_FUNCTIONS 1
-# include <locale/localeinfo.h>
-# include <locale/elem-hash.h>
-# include <locale/coll-lookup.h>
-# endif
-#endif
-
-/* This is for other GNU distributions with internationalized messages. */
-#if HAVE_LIBINTL_H || defined _LIBC
-# include <libintl.h>
-# ifdef _LIBC
-# undef gettext
-# define gettext(msgid) \
- INTUSE(__dcgettext) (INTUSE(_libc_intl_domainname), msgid, LC_MESSAGES)
-# endif
-#else
-# define gettext(msgid) (msgid)
-#endif
-
-#ifndef gettext_noop
-/* This define is so xgettext can find the internationalizable
- strings. */
-# define gettext_noop(String) String
-#endif
-
-#include "_regex.h" /* gnupg */
-#include "regex_internal.h"
-
-static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern,
- int length, reg_syntax_t syntax);
-static void re_compile_fastmap_iter (regex_t *bufp,
- const re_dfastate_t *init_state,
- char *fastmap);
-static reg_errcode_t init_dfa (re_dfa_t *dfa, int pat_len);
-static reg_errcode_t init_word_char (re_dfa_t *dfa);
-#ifdef RE_ENABLE_I18N
-static void free_charset (re_charset_t *cset);
-#endif /* RE_ENABLE_I18N */
-static void free_workarea_compile (regex_t *preg);
-static reg_errcode_t create_initial_state (re_dfa_t *dfa);
-static reg_errcode_t analyze (re_dfa_t *dfa);
-static reg_errcode_t analyze_tree (re_dfa_t *dfa, bin_tree_t *node);
-static void calc_first (re_dfa_t *dfa, bin_tree_t *node);
-static void calc_next (re_dfa_t *dfa, bin_tree_t *node);
-static void calc_epsdest (re_dfa_t *dfa, bin_tree_t *node);
-static reg_errcode_t duplicate_node (int *new_idx, re_dfa_t *dfa, int org_idx,
- unsigned int constraint);
-static reg_errcode_t calc_eclosure (re_dfa_t *dfa);
-static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa,
- int node, int root);
-static void calc_inveclosure (re_dfa_t *dfa);
-static int fetch_number (re_string_t *input, re_token_t *token,
- reg_syntax_t syntax);
-static re_token_t fetch_token (re_string_t *input, reg_syntax_t syntax);
-static int peek_token (re_token_t *token, re_string_t *input,
- reg_syntax_t syntax);
-static int peek_token_bracket (re_token_t *token, re_string_t *input,
- reg_syntax_t syntax);
-static bin_tree_t *parse (re_string_t *regexp, regex_t *preg,
- reg_syntax_t syntax, reg_errcode_t *err);
-static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg,
- re_token_t *token, reg_syntax_t syntax,
- int nest, reg_errcode_t *err);
-static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg,
- re_token_t *token, reg_syntax_t syntax,
- int nest, reg_errcode_t *err);
-static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg,
- re_token_t *token, reg_syntax_t syntax,
- int nest, reg_errcode_t *err);
-static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg,
- re_token_t *token, reg_syntax_t syntax,
- int nest, reg_errcode_t *err);
-static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp,
- re_dfa_t *dfa, re_token_t *token,
- reg_syntax_t syntax, reg_errcode_t *err);
-static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa,
- re_token_t *token, reg_syntax_t syntax,
- reg_errcode_t *err);
-static reg_errcode_t parse_bracket_element (bracket_elem_t *elem,
- re_string_t *regexp,
- re_token_t *token, int token_len,
- re_dfa_t *dfa,
- reg_syntax_t syntax);
-static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem,
- re_string_t *regexp,
- re_token_t *token);
-#ifndef _LIBC
-# ifdef RE_ENABLE_I18N
-static reg_errcode_t build_range_exp (re_bitset_ptr_t sbcset,
- re_charset_t *mbcset, int *range_alloc,
- bracket_elem_t *start_elem,
- bracket_elem_t *end_elem);
-static reg_errcode_t build_collating_symbol (re_bitset_ptr_t sbcset,
- re_charset_t *mbcset,
- int *coll_syxmalloc,
- const unsigned char *name);
-# else /* not RE_ENABLE_I18N */
-static reg_errcode_t build_range_exp (re_bitset_ptr_t sbcset,
- bracket_elem_t *start_elem,
- bracket_elem_t *end_elem);
-static reg_errcode_t build_collating_symbol (re_bitset_ptr_t sbcset,
- const unsigned char *name);
-# endif /* not RE_ENABLE_I18N */
-#endif /* not _LIBC */
-#ifdef RE_ENABLE_I18N
-static reg_errcode_t build_equiv_class (re_bitset_ptr_t sbcset,
- re_charset_t *mbcset,
- int *equiv_class_alloc,
- const unsigned char *name);
-static reg_errcode_t build_charclass (re_bitset_ptr_t sbcset,
- re_charset_t *mbcset,
- int *char_class_alloc,
- const unsigned char *class_name,
- reg_syntax_t syntax);
-#else /* not RE_ENABLE_I18N */
-static reg_errcode_t build_equiv_class (re_bitset_ptr_t sbcset,
- const unsigned char *name);
-static reg_errcode_t build_charclass (re_bitset_ptr_t sbcset,
- const unsigned char *class_name,
- reg_syntax_t syntax);
-#endif /* not RE_ENABLE_I18N */
-static bin_tree_t *build_word_op (re_dfa_t *dfa, int not, reg_errcode_t *err);
-static void free_bin_tree (bin_tree_t *tree);
-static bin_tree_t *create_tree (bin_tree_t *left, bin_tree_t *right,
- re_token_type_t type, int index);
-static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa);
-
-/* This table gives an error message for each of the error codes listed
- in regex.h. Obviously the order here has to be same as there.
- POSIX doesn't require that we do anything for REG_NOERROR,
- but why not be nice? */
-
-const char __re_error_msgid[] attribute_hidden =
- {
-#define REG_NOERROR_IDX 0
- gettext_noop ("Success") /* REG_NOERROR */
- "\0"
-#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success")
- gettext_noop ("No match") /* REG_NOMATCH */
- "\0"
-#define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match")
- gettext_noop ("Invalid regular expression") /* REG_BADPAT */
- "\0"
-#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression")
- gettext_noop ("Invalid collation character") /* REG_ECOLLATE */
- "\0"
-#define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character")
- gettext_noop ("Invalid character class name") /* REG_ECTYPE */
- "\0"
-#define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name")
- gettext_noop ("Trailing backslash") /* REG_EESCAPE */
- "\0"
-#define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash")
- gettext_noop ("Invalid back reference") /* REG_ESUBREG */
- "\0"
-#define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference")
- gettext_noop ("Unmatched [ or [^") /* REG_EBRACK */
- "\0"
-#define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^")
- gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */
- "\0"
-#define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(")
- gettext_noop ("Unmatched \\{") /* REG_EBRACE */
- "\0"
-#define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{")
- gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */
- "\0"
-#define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}")
- gettext_noop ("Invalid range end") /* REG_ERANGE */
- "\0"
-#define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end")
- gettext_noop ("Memory exhausted") /* REG_ESPACE */
- "\0"
-#define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted")
- gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */
- "\0"
-#define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression")
- gettext_noop ("Premature end of regular expression") /* REG_EEND */
- "\0"
-#define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression")
- gettext_noop ("Regular expression too big") /* REG_ESIZE */
- "\0"
-#define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big")
- gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */
- };
-
-const size_t __re_error_msgid_idx[] attribute_hidden =
- {
- REG_NOERROR_IDX,
- REG_NOMATCH_IDX,
- REG_BADPAT_IDX,
- REG_ECOLLATE_IDX,
- REG_ECTYPE_IDX,
- REG_EESCAPE_IDX,
- REG_ESUBREG_IDX,
- REG_EBRACK_IDX,
- REG_EPAREN_IDX,
- REG_EBRACE_IDX,
- REG_BADBR_IDX,
- REG_ERANGE_IDX,
- REG_ESPACE_IDX,
- REG_BADRPT_IDX,
- REG_EEND_IDX,
- REG_ESIZE_IDX,
- REG_ERPAREN_IDX
- };
-
-/* Entry points for GNU code. */
-
-/* re_compile_pattern is the GNU regular expression compiler: it
- compiles PATTERN (of length LENGTH) and puts the result in BUFP.
- Returns 0 if the pattern was valid, otherwise an error string.
-
- Assumes the `allocated' (and perhaps `buffer') and `translate' fields
- are set in BUFP on entry. */
-
-const char *
-re_compile_pattern (pattern, length, bufp)
- const char *pattern;
- size_t length;
- struct re_pattern_buffer *bufp;
-{
- reg_errcode_t ret;
-
- /* GNU code is written to assume at least RE_NREGS registers will be set
- (and at least one extra will be -1). */
- bufp->regs_allocated = REGS_UNALLOCATED;
-
- /* And GNU code determines whether or not to get register information
- by passing null for the REGS argument to re_match, etc., not by
- setting no_sub. */
- bufp->no_sub = 0;
-
- /* Match anchors at newline. */
- bufp->newline_anchor = 1;
-
- ret = re_compile_internal (bufp, pattern, length, re_syntax_options);
-
- if (!ret)
- return NULL;
- return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
-}
-#ifdef _LIBC
-weak_alias (__re_compile_pattern, re_compile_pattern)
-#endif
-
-/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can
- also be assigned to arbitrarily: each pattern buffer stores its own
- syntax, so it can be changed between regex compilations. */
-/* This has no initializer because initialized variables in Emacs
- become read-only after dumping. */
-reg_syntax_t re_syntax_options;
-
-
-/* Specify the precise syntax of regexps for compilation. This provides
- for compatibility for various utilities which historically have
- different, incompatible syntaxes.
-
- The argument SYNTAX is a bit mask comprised of the various bits
- defined in regex.h. We return the old syntax. */
-
-reg_syntax_t
-re_set_syntax (syntax)
- reg_syntax_t syntax;
-{
- reg_syntax_t ret = re_syntax_options;
-
- re_syntax_options = syntax;
- return ret;
-}
-#ifdef _LIBC
-weak_alias (__re_set_syntax, re_set_syntax)
-#endif
-
-int
-re_compile_fastmap (bufp)
- struct re_pattern_buffer *bufp;
-{
- re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
- char *fastmap = bufp->fastmap;
-
- memset (fastmap, '\0', sizeof (char) * SBC_MAX);
- re_compile_fastmap_iter (bufp, dfa->init_state, fastmap);
- if (dfa->init_state != dfa->init_state_word)
- re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap);
- if (dfa->init_state != dfa->init_state_nl)
- re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap);
- if (dfa->init_state != dfa->init_state_begbuf)
- re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap);
- bufp->fastmap_accurate = 1;
- return 0;
-}
-#ifdef _LIBC
-weak_alias (__re_compile_fastmap, re_compile_fastmap)
-#endif
-
-/* Helper function for re_compile_fastmap.
- Compile fastmap for the initial_state INIT_STATE. */
-
-static void
-re_compile_fastmap_iter (bufp, init_state, fastmap)
- regex_t *bufp;
- const re_dfastate_t *init_state;
- char *fastmap;
-{
- re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
- int node_cnt;
- for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt)
- {
- int node = init_state->nodes.elems[node_cnt];
- re_token_type_t type = dfa->nodes[node].type;
- if (type == OP_CONTEXT_NODE)
- {
- node = dfa->nodes[node].opr.ctx_info->entity;
- type = dfa->nodes[node].type;
- }
-
- if (type == CHARACTER)
- fastmap[dfa->nodes[node].opr.c] = 1;
- else if (type == SIMPLE_BRACKET)
- {
- int i, j, ch;
- for (i = 0, ch = 0; i < BITSET_UINTS; ++i)
- for (j = 0; j < UINT_BITS; ++j, ++ch)
- if (dfa->nodes[node].opr.sbcset[i] & (1 << j))
- fastmap[ch] = 1;
- }
-#ifdef RE_ENABLE_I18N
- else if (type == COMPLEX_BRACKET)
- {
- int i;
- re_charset_t *cset = dfa->nodes[node].opr.mbcset;
- if (cset->non_match || cset->ncoll_syms || cset->nequiv_classes
- || cset->nranges || cset->nchar_classes)
- {
-# ifdef _LIBC
- if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0)
- {
- /* In this case we want to catch the bytes which are
- the first byte of any collation elements.
- e.g. In da_DK, we want to catch 'a' since "aa"
- is a valid collation element, and don't catch
- 'b' since 'b' is the only collation element
- which starts from 'b'. */
- int j, ch;
- const int32_t *table = (const int32_t *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
- for (i = 0, ch = 0; i < BITSET_UINTS; ++i)
- for (j = 0; j < UINT_BITS; ++j, ++ch)
- if (table[ch] < 0)
- fastmap[ch] = 1;
- }
-# else
- if (MB_CUR_MAX > 1)
- for (i = 0; i < SBC_MAX; ++i)
- if (__btowc (i) == WEOF)
- fastmap[i] = 1;
-# endif /* not _LIBC */
- }
- for (i = 0; i < cset->nmbchars; ++i)
- {
- char buf[256];
- wctomb (buf, cset->mbchars[i]);
- fastmap[*(unsigned char *) buf] = 1;
- }
- }
-#endif /* RE_ENABLE_I18N */
- else if (type == END_OF_RE || type == OP_PERIOD
-#ifdef RE_ENABLE_I18N
- || type == COMPLEX_BRACKET
-#endif /* RE_ENABLE_I18N */
- )
- {
- memset (fastmap, '\1', sizeof (char) * SBC_MAX);
- if (type == END_OF_RE)
- bufp->can_be_null = 1;
- return;
- }
- }
-}
-
-/* Entry point for POSIX code. */
-/* regcomp takes a regular expression as a string and compiles it.
-
- PREG is a regex_t *. We do not expect any fields to be initialized,
- since POSIX says we shouldn't. Thus, we set
-
- `buffer' to the compiled pattern;
- `used' to the length of the compiled pattern;
- `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
- REG_EXTENDED bit in CFLAGS is set; otherwise, to
- RE_SYNTAX_POSIX_BASIC;
- `newline_anchor' to REG_NEWLINE being set in CFLAGS;
- `fastmap' to an allocated space for the fastmap;
- `fastmap_accurate' to zero;
- `re_nsub' to the number of subexpressions in PATTERN.
-
- PATTERN is the address of the pattern string.
-
- CFLAGS is a series of bits which affect compilation.
-
- If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
- use POSIX basic syntax.
-
- If REG_NEWLINE is set, then . and [^...] don't match newline.
- Also, regexec will try a match beginning after every newline.
-
- If REG_ICASE is set, then we considers upper- and lowercase
- versions of letters to be equivalent when matching.
-
- If REG_NOSUB is set, then when PREG is passed to regexec, that
- routine will report only success or failure, and nothing about the
- registers.
-
- It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for
- the return codes and their meanings.) */
-
-int
-regcomp (preg, pattern, cflags)
- regex_t *__restrict preg;
- const char *__restrict pattern;
- int cflags;
-{
- reg_errcode_t ret;
- reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED
- : RE_SYNTAX_POSIX_BASIC);
-
- preg->buffer = NULL;
- preg->allocated = 0;
- preg->used = 0;
-
- /* Try to allocate space for the fastmap. */
- preg->fastmap = re_malloc (char, SBC_MAX);
- if (BE (preg->fastmap == NULL, 0))
- return REG_ESPACE;
-
- syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0;
-
- /* If REG_NEWLINE is set, newlines are treated differently. */
- if (cflags & REG_NEWLINE)
- { /* REG_NEWLINE implies neither . nor [^...] match newline. */
- syntax &= ~RE_DOT_NEWLINE;
- syntax |= RE_HAT_LISTS_NOT_NEWLINE;
- /* It also changes the matching behavior. */
- preg->newline_anchor = 1;
- }
- else
- preg->newline_anchor = 0;
- preg->no_sub = !!(cflags & REG_NOSUB);
- preg->translate = NULL;
-
- ret = re_compile_internal (preg, pattern, strlen (pattern), syntax);
-
- /* POSIX doesn't distinguish between an unmatched open-group and an
- unmatched close-group: both are REG_EPAREN. */
- if (ret == REG_ERPAREN)
- ret = REG_EPAREN;
-
- /* We have already checked preg->fastmap != NULL. */
- if (BE (ret == REG_NOERROR, 1))
- {
- /* Compute the fastmap now, since regexec cannot modify the pattern
- buffer. */
- if (BE (re_compile_fastmap (preg) == -2, 0))
- {
- /* Some error occurred while computing the fastmap, just forget
- about it. */
- re_free (preg->fastmap);
- preg->fastmap = NULL;
- }
- }
-
- return (int) ret;
-}
-#ifdef _LIBC
-weak_alias (__regcomp, regcomp)
-#endif
-
-/* Returns a message corresponding to an error code, ERRCODE, returned
- from either regcomp or regexec. We don't use PREG here. */
-
-size_t
-regerror (errcode, preg, errbuf, errbuf_size)
- int errcode;
- const regex_t *preg;
- char *errbuf;
- size_t errbuf_size;
-{
- const char *msg;
- size_t msg_size;
-
- if (BE (errcode < 0
- || errcode >= (int) (sizeof (__re_error_msgid_idx)
- / sizeof (__re_error_msgid_idx[0])), 0))
- /* Only error codes returned by the rest of the code should be passed
- to this routine. If we are given anything else, or if other regex
- code generates an invalid error code, then the program has a bug.
- Dump core so we can fix it. */
- abort ();
-
- msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]);
-
- msg_size = strlen (msg) + 1; /* Includes the null. */
-
- if (BE (errbuf_size != 0, 1))
- {
- if (BE (msg_size > errbuf_size, 0))
- {
-#if defined HAVE_MEMPCPY || defined _LIBC
- *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0';
-#else
- memcpy (errbuf, msg, errbuf_size - 1);
- errbuf[errbuf_size - 1] = 0;
-#endif
- }
- else
- memcpy (errbuf, msg, msg_size);
- }
-
- return msg_size;
-}
-#ifdef _LIBC
-weak_alias (__regerror, regerror)
-#endif
-
-/* Free dynamically allocated space used by PREG. */
-
-void
-regfree (preg)
- regex_t *preg;
-{
- int i, j;
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- if (BE (dfa != NULL, 1))
- {
- re_free (dfa->subexps);
-
- for (i = 0; i < dfa->nodes_len; ++i)
- {
- re_token_t *node = dfa->nodes + i;
-#ifdef RE_ENABLE_I18N
- if (node->type == COMPLEX_BRACKET && node->duplicated == 0)
- free_charset (node->opr.mbcset);
- else
-#endif /* RE_ENABLE_I18N */
- if (node->type == SIMPLE_BRACKET && node->duplicated == 0)
- re_free (node->opr.sbcset);
- else if (node->type == OP_CONTEXT_NODE)
- {
- if (dfa->nodes[node->opr.ctx_info->entity].type == OP_BACK_REF)
- {
- if (node->opr.ctx_info->bkref_eclosure != NULL)
- re_node_set_free (node->opr.ctx_info->bkref_eclosure);
- re_free (node->opr.ctx_info->bkref_eclosure);
- }
- re_free (node->opr.ctx_info);
- }
- }
- re_free (dfa->firsts);
- re_free (dfa->nexts);
- for (i = 0; i < dfa->nodes_len; ++i)
- {
- if (dfa->eclosures != NULL)
- re_node_set_free (dfa->eclosures + i);
- if (dfa->inveclosures != NULL)
- re_node_set_free (dfa->inveclosures + i);
- if (dfa->edests != NULL)
- re_node_set_free (dfa->edests + i);
- }
- re_free (dfa->edests);
- re_free (dfa->eclosures);
- re_free (dfa->inveclosures);
- re_free (dfa->nodes);
-
- for (i = 0; i <= dfa->state_hash_mask; ++i)
- {
- struct re_state_table_entry *entry = dfa->state_table + i;
- for (j = 0; j < entry->num; ++j)
- {
- re_dfastate_t *state = entry->array[j];
- if (state->entrance_nodes != &state->nodes)
- {
- re_node_set_free (state->entrance_nodes);
- re_free (state->entrance_nodes);
- }
- re_node_set_free (&state->nodes);
- re_free (state->trtable);
- re_free (state->trtable_search);
- re_free (state);
- }
- re_free (entry->array);
- }
- re_free (dfa->state_table);
-
- if (dfa->word_char != NULL)
- re_free (dfa->word_char);
-#ifdef DEBUG
- re_free (dfa->re_str);
-#endif
- re_free (dfa);
- }
- re_free (preg->fastmap);
-}
-#ifdef _LIBC
-weak_alias (__regfree, regfree)
-#endif
-
-/* Entry points compatible with 4.2 BSD regex library. We don't define
- them unless specifically requested. */
-
-#if defined _REGEX_RE_COMP || defined _LIBC
-
-/* BSD has one and only one pattern buffer. */
-static struct re_pattern_buffer re_comp_buf;
-
-char *
-# ifdef _LIBC
-/* Make these definitions weak in libc, so POSIX programs can redefine
- these names if they don't use our functions, and still use
- regcomp/regexec above without link errors. */
-weak_function
-# endif
-re_comp (s)
- const char *s;
-{
- reg_errcode_t ret;
-
- if (!s)
- {
- if (!re_comp_buf.buffer)
- return gettext ("No previous regular expression");
- return 0;
- }
-
- if (!re_comp_buf.buffer)
- {
- re_comp_buf.fastmap = (char *) malloc (SBC_MAX);
- if (re_comp_buf.fastmap == NULL)
- return (char *) gettext (__re_error_msgid
- + __re_error_msgid_idx[(int) REG_ESPACE]);
- }
-
- /* Since `re_exec' always passes NULL for the `regs' argument, we
- don't need to initialize the pattern buffer fields which affect it. */
-
- /* Match anchors at newlines. */
- re_comp_buf.newline_anchor = 1;
-
- ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options);
-
- if (!ret)
- return NULL;
-
- /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */
- return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
-}
-#endif /* _REGEX_RE_COMP */
-
-/* Internal entry point.
- Compile the regular expression PATTERN, whose length is LENGTH.
- SYNTAX indicate regular expression's syntax. */
-
-static reg_errcode_t
-re_compile_internal (preg, pattern, length, syntax)
- regex_t *preg;
- const char * pattern;
- int length;
- reg_syntax_t syntax;
-{
- reg_errcode_t err = REG_NOERROR;
- re_dfa_t *dfa;
- re_string_t regexp;
-
- /* Initialize the pattern buffer. */
- preg->fastmap_accurate = 0;
- preg->syntax = syntax;
- preg->not_bol = preg->not_eol = 0;
- preg->used = 0;
- preg->re_nsub = 0;
-
- /* Initialize the dfa. */
- dfa = (re_dfa_t *) preg->buffer;
- if (preg->allocated < sizeof (re_dfa_t))
- {
- /* If zero allocated, but buffer is non-null, try to realloc
- enough space. This loses if buffer's address is bogus, but
- that is the user's responsibility. If ->buffer is NULL this
- is a simple allocation. */
- dfa = re_realloc (preg->buffer, re_dfa_t, 1);
- if (dfa == NULL)
- return REG_ESPACE;
- preg->allocated = sizeof (re_dfa_t);
- }
- preg->buffer = (unsigned char *) dfa;
- preg->used = sizeof (re_dfa_t);
-
- err = init_dfa (dfa, length);
- if (BE (err != REG_NOERROR, 0))
- {
- re_free (dfa);
- preg->buffer = NULL;
- return err;
- }
-#ifdef DEBUG
- dfa->re_str = re_malloc (char, length + 1);
- strncpy (dfa->re_str, pattern, length + 1);
-#endif
-
- err = re_string_construct (&regexp, pattern, length, preg->translate,
- syntax & RE_ICASE);
- if (BE (err != REG_NOERROR, 0))
- {
- re_free (dfa);
- preg->buffer = NULL;
- return err;
- }
-
- /* Parse the regular expression, and build a structure tree. */
- preg->re_nsub = 0;
- dfa->str_tree = parse (&regexp, preg, syntax, &err);
- if (BE (dfa->str_tree == NULL, 0))
- goto re_compile_internal_free_return;
-
- /* Analyze the tree and collect information which is necessary to
- create the dfa. */
- err = analyze (dfa);
- if (BE (err != REG_NOERROR, 0))
- goto re_compile_internal_free_return;
-
- /* Then create the initial state of the dfa. */
- err = create_initial_state (dfa);
- if (BE (err != REG_NOERROR, 0))
- goto re_compile_internal_free_return;
-
- re_compile_internal_free_return:
- /* Release work areas. */
- free_workarea_compile (preg);
- re_string_destruct (&regexp);
-
- return err;
-}
-
-/* Initialize DFA. We use the length of the regular expression PAT_LEN
- as the initial length of some arrays. */
-
-static reg_errcode_t
-init_dfa (dfa, pat_len)
- re_dfa_t *dfa;
- int pat_len;
-{
- int table_size;
-
- memset (dfa, '\0', sizeof (re_dfa_t));
-
- dfa->nodes_alloc = pat_len + 1;
- dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc);
-
- dfa->states_alloc = pat_len + 1;
-
- /* table_size = 2 ^ ceil(log pat_len) */
- for (table_size = 1; table_size > 0; table_size <<= 1)
- if (table_size > pat_len)
- break;
-
- dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size);
- dfa->state_hash_mask = table_size - 1;
-
- dfa->subexps_alloc = 1;
- dfa->subexps = re_malloc (re_subexp_t, dfa->subexps_alloc);
- dfa->word_char = NULL;
-
- if (BE (dfa->nodes == NULL || dfa->state_table == NULL
- || dfa->subexps == NULL, 0))
- {
- /* We don't bother to free anything which was allocated. Very
- soon the process will go down anyway. */
- dfa->subexps = NULL;
- dfa->state_table = NULL;
- dfa->nodes = NULL;
- return REG_ESPACE;
- }
- return REG_NOERROR;
-}
-
-/* Initialize WORD_CHAR table, which indicate which character is
- "word". In this case "word" means that it is the word construction
- character used by some operators like "\<", "\>", etc. */
-
-static reg_errcode_t
-init_word_char (dfa)
- re_dfa_t *dfa;
-{
- int i, j, ch;
- dfa->word_char = (re_bitset_ptr_t) calloc (sizeof (bitset), 1);
- if (BE (dfa->word_char == NULL, 0))
- return REG_ESPACE;
- for (i = 0, ch = 0; i < BITSET_UINTS; ++i)
- for (j = 0; j < UINT_BITS; ++j, ++ch)
- if (isalnum (ch) || ch == '_')
- dfa->word_char[i] |= 1 << j;
- return REG_NOERROR;
-}
-
-/* Free the work area which are only used while compiling. */
-
-static void
-free_workarea_compile (preg)
- regex_t *preg;
-{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- free_bin_tree (dfa->str_tree);
- dfa->str_tree = NULL;
-}
-
-/* Create initial states for all contexts. */
-
-static reg_errcode_t
-create_initial_state (dfa)
- re_dfa_t *dfa;
-{
- int first, i;
- reg_errcode_t err;
- re_node_set init_nodes;
-
- /* Initial states have the epsilon closure of the node which is
- the first node of the regular expression. */
- first = dfa->str_tree->first;
- dfa->init_node = first;
- err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first);
- if (BE (err != REG_NOERROR, 0))
- return err;
-
- /* The back-references which are in initial states can epsilon transit,
- since in this case all of the subexpressions can be null.
- Then we add epsilon closures of the nodes which are the next nodes of
- the back-references. */
- if (dfa->nbackref > 0)
- for (i = 0; i < init_nodes.nelem; ++i)
- {
- int node_idx = init_nodes.elems[i];
- re_token_type_t type = dfa->nodes[node_idx].type;
-
- int clexp_idx;
- int entity = (type != OP_CONTEXT_NODE ? node_idx
- : dfa->nodes[node_idx].opr.ctx_info->entity);
- if ((type != OP_CONTEXT_NODE
- || (dfa->nodes[entity].type != OP_BACK_REF))
- && (type != OP_BACK_REF))
- continue;
- for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx)
- {
- re_token_t *clexp_node;
- clexp_node = dfa->nodes + init_nodes.elems[clexp_idx];
- if (clexp_node->type == OP_CLOSE_SUBEXP
- && clexp_node->opr.idx + 1 == dfa->nodes[entity].opr.idx)
- break;
- }
- if (clexp_idx == init_nodes.nelem)
- continue;
-
- if (type == OP_CONTEXT_NODE
- && (dfa->nodes[dfa->nodes[node_idx].opr.ctx_info->entity].type
- == OP_BACK_REF))
- {
- int prev_nelem = init_nodes.nelem;
- re_node_set_merge (&init_nodes,
- dfa->nodes[node_idx].opr.ctx_info->bkref_eclosure);
- if (prev_nelem < init_nodes.nelem)
- i = 0;
- }
- else if (type == OP_BACK_REF)
- {
- int next_idx = dfa->nexts[node_idx];
- if (!re_node_set_contains (&init_nodes, next_idx))
- {
- re_node_set_merge (&init_nodes, dfa->eclosures + next_idx);
- i = 0;
- }
- }
- }
-
- /* It must be the first time to invoke acquire_state. */
- dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0);
- /* We don't check ERR here, since the initial state must not be NULL. */
- if (BE (dfa->init_state == NULL, 0))
- return err;
- if (dfa->init_state->has_constraint)
- {
- dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes,
- CONTEXT_WORD);
- dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes,
- CONTEXT_NEWLINE);
- dfa->init_state_begbuf = re_acquire_state_context (&err, dfa,
- &init_nodes,
- CONTEXT_NEWLINE
- | CONTEXT_BEGBUF);
- if (BE (dfa->init_state_word == NULL || dfa->init_state_nl == NULL
- || dfa->init_state_begbuf == NULL, 0))
- return err;
- }
- else
- dfa->init_state_word = dfa->init_state_nl
- = dfa->init_state_begbuf = dfa->init_state;
-
- re_node_set_free (&init_nodes);
- return REG_NOERROR;
-}
-
-/* Analyze the structure tree, and calculate "first", "next", "edest",
- "eclosure", and "inveclosure". */
-
-static reg_errcode_t
-analyze (dfa)
- re_dfa_t *dfa;
-{
- int i;
- reg_errcode_t ret;
-
- /* Allocate arrays. */
- dfa->firsts = re_malloc (int, dfa->nodes_alloc);
- dfa->nexts = re_malloc (int, dfa->nodes_alloc);
- dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc);
- dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc);
- dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_alloc);
- if (BE (dfa->firsts == NULL || dfa->nexts == NULL || dfa->edests == NULL
- || dfa->eclosures == NULL || dfa->inveclosures == NULL, 0))
- return REG_ESPACE;
- /* Initialize them. */
- for (i = 0; i < dfa->nodes_len; ++i)
- {
- dfa->firsts[i] = -1;
- dfa->nexts[i] = -1;
- re_node_set_init_empty (dfa->edests + i);
- re_node_set_init_empty (dfa->eclosures + i);
- re_node_set_init_empty (dfa->inveclosures + i);
- }
-
- ret = analyze_tree (dfa, dfa->str_tree);
- if (BE (ret == REG_NOERROR, 1))
- {
- ret = calc_eclosure (dfa);
- if (ret == REG_NOERROR)
- calc_inveclosure (dfa);
- }
- return ret;
-}
-
-/* Helper functions for analyze.
- This function calculate "first", "next", and "edest" for the subtree
- whose root is NODE. */
-
-static reg_errcode_t
-analyze_tree (dfa, node)
- re_dfa_t *dfa;
- bin_tree_t *node;
-{
- reg_errcode_t ret;
- if (node->first == -1)
- calc_first (dfa, node);
- if (node->next == -1)
- calc_next (dfa, node);
- if (node->eclosure.nelem == 0)
- calc_epsdest (dfa, node);
- /* Calculate "first" etc. for the left child. */
- if (node->left != NULL)
- {
- ret = analyze_tree (dfa, node->left);
- if (BE (ret != REG_NOERROR, 0))
- return ret;
- }
- /* Calculate "first" etc. for the right child. */
- if (node->right != NULL)
- {
- ret = analyze_tree (dfa, node->right);
- if (BE (ret != REG_NOERROR, 0))
- return ret;
- }
- return REG_NOERROR;
-}
-
-/* Calculate "first" for the node NODE. */
-static void
-calc_first (dfa, node)
- re_dfa_t *dfa;
- bin_tree_t *node;
-{
- int idx, type;
- idx = node->node_idx;
- type = (node->type == 0) ? dfa->nodes[idx].type : node->type;
-
- switch (type)
- {
-#ifdef DEBUG
- case OP_OPEN_BRACKET:
- case OP_CLOSE_BRACKET:
- case OP_OPEN_DUP_NUM:
- case OP_CLOSE_DUP_NUM:
- case OP_NON_MATCH_LIST:
- case OP_OPEN_COLL_ELEM:
- case OP_CLOSE_COLL_ELEM:
- case OP_OPEN_EQUIV_CLASS:
- case OP_CLOSE_EQUIV_CLASS:
- case OP_OPEN_CHAR_CLASS:
- case OP_CLOSE_CHAR_CLASS:
- /* These must not be appeared here. */
- assert (0);
-#endif
- case END_OF_RE:
- case CHARACTER:
- case OP_PERIOD:
- case OP_DUP_ASTERISK:
- case OP_DUP_QUESTION:
-#ifdef RE_ENABLE_I18N
- case COMPLEX_BRACKET:
-#endif /* RE_ENABLE_I18N */
- case SIMPLE_BRACKET:
- case OP_BACK_REF:
- case ANCHOR:
- case OP_OPEN_SUBEXP:
- case OP_CLOSE_SUBEXP:
- node->first = idx;
- break;
- case OP_DUP_PLUS:
-#ifdef DEBUG
- assert (node->left != NULL);
-#endif
- if (node->left->first == -1)
- calc_first (dfa, node->left);
- node->first = node->left->first;
- break;
- case OP_ALT:
- node->first = idx;
- break;
- /* else fall through */
- default:
-#ifdef DEBUG
- assert (node->left != NULL);
-#endif
- if (node->left->first == -1)
- calc_first (dfa, node->left);
- node->first = node->left->first;
- break;
- }
- if (node->type == 0)
- dfa->firsts[idx] = node->first;
-}
-
-/* Calculate "next" for the node NODE. */
-
-static void
-calc_next (dfa, node)
- re_dfa_t *dfa;
- bin_tree_t *node;
-{
- int idx, type;
- bin_tree_t *parent = node->parent;
- if (parent == NULL)
- {
- node->next = -1;
- idx = node->node_idx;
- if (node->type == 0)
- dfa->nexts[idx] = node->next;
- return;
- }
-
- idx = parent->node_idx;
- type = (parent->type == 0) ? dfa->nodes[idx].type : parent->type;
-
- switch (type)
- {
- case OP_DUP_ASTERISK:
- case OP_DUP_PLUS:
- node->next = idx;
- break;
- case CONCAT:
- if (parent->left == node)
- {
- if (parent->right->first == -1)
- calc_first (dfa, parent->right);
- node->next = parent->right->first;
- break;
- }
- /* else fall through */
- default:
- if (parent->next == -1)
- calc_next (dfa, parent);
- node->next = parent->next;
- break;
- }
- idx = node->node_idx;
- if (node->type == 0)
- dfa->nexts[idx] = node->next;
-}
-
-/* Calculate "edest" for the node NODE. */
-
-static void
-calc_epsdest (dfa, node)
- re_dfa_t *dfa;
- bin_tree_t *node;
-{
- int idx;
- idx = node->node_idx;
- if (node->type == 0)
- {
- if (dfa->nodes[idx].type == OP_DUP_ASTERISK
- || dfa->nodes[idx].type == OP_DUP_PLUS
- || dfa->nodes[idx].type == OP_DUP_QUESTION)
- {
- if (node->left->first == -1)
- calc_first (dfa, node->left);
- if (node->next == -1)
- calc_next (dfa, node);
- re_node_set_init_2 (dfa->edests + idx, node->left->first,
- node->next);
- }
- else if (dfa->nodes[idx].type == OP_ALT)
- {
- int left, right;
- if (node->left != NULL)
- {
- if (node->left->first == -1)
- calc_first (dfa, node->left);
- left = node->left->first;
- }
- else
- {
- if (node->next == -1)
- calc_next (dfa, node);
- left = node->next;
- }
- if (node->right != NULL)
- {
- if (node->right->first == -1)
- calc_first (dfa, node->right);
- right = node->right->first;
- }
- else
- {
- if (node->next == -1)
- calc_next (dfa, node);
- right = node->next;
- }
- re_node_set_init_2 (dfa->edests + idx, left, right);
- }
- else if (dfa->nodes[idx].type == ANCHOR
- || dfa->nodes[idx].type == OP_OPEN_SUBEXP
- || dfa->nodes[idx].type == OP_CLOSE_SUBEXP)
- re_node_set_init_1 (dfa->edests + idx, node->next);
- }
-}
-
-/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT.
- The new index will be stored in NEW_IDX and return REG_NOERROR if succeeded,
- otherwise return the error code. */
-
-static reg_errcode_t
-duplicate_node (new_idx, dfa, org_idx, constraint)
- re_dfa_t *dfa;
- int *new_idx, org_idx;
- unsigned int constraint;
-{
- re_token_t dup;
- int dup_idx;
- reg_errcode_t err;
-
- dup.type = OP_CONTEXT_NODE;
- if (dfa->nodes[org_idx].type == OP_CONTEXT_NODE)
- {
- /* If the node whose index is ORG_IDX is the same as the intended
- node, use it. */
- if (dfa->nodes[org_idx].constraint == constraint)
- {
- *new_idx = org_idx;
- return REG_NOERROR;
- }
- dup.constraint = constraint |
- dfa->nodes[org_idx].constraint;
- }
- else
- dup.constraint = constraint;
-
- /* In case that `entity' points OP_CONTEXT_NODE,
- we correct `entity' to real entity in calc_inveclosures(). */
- dup.opr.ctx_info = malloc (sizeof (*dup.opr.ctx_info));
- dup_idx = re_dfa_add_node (dfa, dup, 1);
- if (BE (dup.opr.ctx_info == NULL || dup_idx == -1, 0))
- return REG_ESPACE;
- dup.opr.ctx_info->entity = org_idx;
- dup.opr.ctx_info->bkref_eclosure = NULL;
-
- dfa->nodes[dup_idx].duplicated = 1;
- dfa->firsts[dup_idx] = dfa->firsts[org_idx];
- dfa->nexts[dup_idx] = dfa->nexts[org_idx];
- err = re_node_set_init_copy (dfa->edests + dup_idx, dfa->edests + org_idx);
- if (BE (err != REG_NOERROR, 0))
- return err;
- /* Since we don't duplicate epsilon nodes, epsilon closure have
- only itself. */
- err = re_node_set_init_1 (dfa->eclosures + dup_idx, dup_idx);
- if (BE (err != REG_NOERROR, 0))
- return err;
- err = re_node_set_init_1 (dfa->inveclosures + dup_idx, dup_idx);
- if (BE (err != REG_NOERROR, 0))
- return err;
- /* Then we must update inveclosure for this node.
- We process them at last part of calc_eclosure(),
- since we don't complete to calculate them here. */
-
- *new_idx = dup_idx;
- return REG_NOERROR;
-}
-
-static void
-calc_inveclosure (dfa)
- re_dfa_t *dfa;
-{
- int src, idx, dest, entity;
- for (src = 0; src < dfa->nodes_len; ++src)
- {
- for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx)
- {
- dest = dfa->eclosures[src].elems[idx];
- re_node_set_insert (dfa->inveclosures + dest, src);
- }
-
- entity = src;
- while (dfa->nodes[entity].type == OP_CONTEXT_NODE)
- {
- entity = dfa->nodes[entity].opr.ctx_info->entity;
- re_node_set_merge (dfa->inveclosures + src,
- dfa->inveclosures + entity);
- dfa->nodes[src].opr.ctx_info->entity = entity;
- }
- }
-}
-
-/* Calculate "eclosure" for all the node in DFA. */
-
-static reg_errcode_t
-calc_eclosure (dfa)
- re_dfa_t *dfa;
-{
- int idx, node_idx, max, incomplete = 0;
-#ifdef DEBUG
- assert (dfa->nodes_len > 0);
-#endif
- /* For each nodes, calculate epsilon closure. */
- for (node_idx = 0, max = dfa->nodes_len; ; ++node_idx)
- {
- reg_errcode_t err;
- re_node_set eclosure_elem;
- if (node_idx == max)
- {
- if (!incomplete)
- break;
- incomplete = 0;
- node_idx = 0;
- }
-
-#ifdef DEBUG
- assert (dfa->nodes[node_idx].type != OP_CONTEXT_NODE);
- assert (dfa->eclosures[node_idx].nelem != -1);
-#endif
- /* If we have already calculated, skip it. */
- if (dfa->eclosures[node_idx].nelem != 0)
- continue;
- /* Calculate epsilon closure of `node_idx'. */
- err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, 1);
- if (BE (err != REG_NOERROR, 0))
- return err;
-
- if (dfa->eclosures[node_idx].nelem == 0)
- {
- incomplete = 1;
- re_node_set_free (&eclosure_elem);
- }
- }
-
- /* for duplicated nodes. */
- for (idx = max; idx < dfa->nodes_len; ++idx)
- {
- int entity, i, constraint;
- re_node_set *bkref_eclosure;
- entity = dfa->nodes[idx].opr.ctx_info->entity;
- re_node_set_merge (dfa->inveclosures + idx, dfa->inveclosures + entity);
- if (dfa->nodes[entity].type != OP_BACK_REF)
- continue;
-
- /* If the node is backreference, duplicate the epsilon closure of
- the next node. Since it may epsilon transit. */
- /* Note: duplicate_node() may realloc dfa->eclosures, etc. */
- bkref_eclosure = re_malloc (re_node_set, 1);
- if (BE (bkref_eclosure == NULL, 0))
- return REG_ESPACE;
- re_node_set_init_empty (bkref_eclosure);
- constraint = dfa->nodes[idx].constraint;
- for (i = 0; i < dfa->eclosures[dfa->nexts[idx]].nelem; ++i)
- {
- int dest_node_idx = dfa->eclosures[dfa->nexts[idx]].elems[i];
- if (!IS_EPSILON_NODE (dfa->nodes[dest_node_idx].type))
- {
- reg_errcode_t err;
- err = duplicate_node (&dest_node_idx, dfa, dest_node_idx,
- constraint);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- re_node_set_insert (bkref_eclosure, dest_node_idx);
- }
- dfa->nodes[idx].opr.ctx_info->bkref_eclosure = bkref_eclosure;
- }
-
- return REG_NOERROR;
-}
-
-/* Calculate epsilon closure of NODE. */
-
-static reg_errcode_t
-calc_eclosure_iter (new_set, dfa, node, root)
- re_node_set *new_set;
- re_dfa_t *dfa;
- int node, root;
-{
- reg_errcode_t err;
- unsigned int constraint;
- int i, max, incomplete = 0;
- re_node_set eclosure;
- err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1);
- if (BE (err != REG_NOERROR, 0))
- return err;
-
- /* This indicates that we are calculating this node now.
- We reference this value to avoid infinite loop. */
- dfa->eclosures[node].nelem = -1;
-
- constraint = ((dfa->nodes[node].type == ANCHOR)
- ? dfa->nodes[node].opr.ctx_type : 0);
-
- /* Expand each epsilon destination nodes. */
- if (dfa->edests[node].nelem != 0)
- for (i = 0; i < dfa->edests[node].nelem; ++i)
- {
- re_node_set eclosure_elem;
- int edest = dfa->edests[node].elems[i];
- /* If calculating the epsilon closure of `edest' is in progress,
- return intermediate result. */
- if (dfa->eclosures[edest].nelem == -1)
- {
- incomplete = 1;
- continue;
- }
- /* If we haven't calculated the epsilon closure of `edest' yet,
- calculate now. Otherwise use calculated epsilon closure. */
- if (dfa->eclosures[edest].nelem == 0)
- {
- err = calc_eclosure_iter (&eclosure_elem, dfa, edest, 0);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- else
- eclosure_elem = dfa->eclosures[edest];
- /* Merge the epsilon closure of `edest'. */
- re_node_set_merge (&eclosure, &eclosure_elem);
- /* If the epsilon closure of `edest' is incomplete,
- the epsilon closure of this node is also incomplete. */
- if (dfa->eclosures[edest].nelem == 0)
- {
- incomplete = 1;
- re_node_set_free (&eclosure_elem);
- }
- }
-
- /* If the current node has constraints, duplicate all non-epsilon nodes.
- Since they must inherit the constraints. */
- if (constraint)
- for (i = 0, max = eclosure.nelem; i < max; ++i)
- {
- int dest = eclosure.elems[i];
- if (!IS_EPSILON_NODE (dfa->nodes[dest].type))
- {
- int dup_dest;
- reg_errcode_t err;
- err = duplicate_node (&dup_dest, dfa, dest, constraint);
- if (BE (err != REG_NOERROR, 0))
- return err;
- if (dest != dup_dest)
- {
- re_node_set_remove_at (&eclosure, i--);
- re_node_set_insert (&eclosure, dup_dest);
- --max;
- }
- }
- }
-
- /* Epsilon closures include itself. */
- re_node_set_insert (&eclosure, node);
- if (incomplete && !root)
- dfa->eclosures[node].nelem = 0;
- else
- dfa->eclosures[node] = eclosure;
- *new_set = eclosure;
- return REG_NOERROR;
-}
-
-/* Functions for token which are used in the parser. */
-
-/* Fetch a token from INPUT.
- We must not use this function inside bracket expressions. */
-
-static re_token_t
-fetch_token (input, syntax)
- re_string_t *input;
- reg_syntax_t syntax;
-{
- re_token_t token;
- int consumed_byte;
- consumed_byte = peek_token (&token, input, syntax);
- re_string_skip_bytes (input, consumed_byte);
- return token;
-}
-
-/* Peek a token from INPUT, and return the length of the token.
- We must not use this function inside bracket expressions. */
-
-static int
-peek_token (token, input, syntax)
- re_token_t *token;
- re_string_t *input;
- reg_syntax_t syntax;
-{
- unsigned char c;
-
- if (re_string_eoi (input))
- {
- token->type = END_OF_RE;
- return 0;
- }
-
- c = re_string_peek_byte (input, 0);
- token->opr.c = c;
-
-#ifdef RE_ENABLE_I18N
- token->mb_partial = 0;
- if (MB_CUR_MAX > 1 &&
- !re_string_first_byte (input, re_string_cur_idx (input)))
- {
- token->type = CHARACTER;
- token->mb_partial = 1;
- return 1;
- }
-#endif
- if (c == '\\')
- {
- unsigned char c2;
- if (re_string_cur_idx (input) + 1 >= re_string_length (input))
- {
- token->type = BACK_SLASH;
- return 1;
- }
-
- c2 = re_string_peek_byte_case (input, 1);
- token->opr.c = c2;
- token->type = CHARACTER;
- switch (c2)
- {
- case '|':
- if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR))
- token->type = OP_ALT;
- break;
- case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9':
- if (!(syntax & RE_NO_BK_REFS))
- {
- token->type = OP_BACK_REF;
- token->opr.idx = c2 - '0';
- }
- break;
- case '<':
- if (!(syntax & RE_NO_GNU_OPS))
- {
- token->type = ANCHOR;
- token->opr.idx = WORD_FIRST;
- }
- break;
- case '>':
- if (!(syntax & RE_NO_GNU_OPS))
- {
- token->type = ANCHOR;
- token->opr.idx = WORD_LAST;
- }
- break;
- case 'b':
- if (!(syntax & RE_NO_GNU_OPS))
- {
- token->type = ANCHOR;
- token->opr.idx = WORD_DELIM;
- }
- break;
- case 'B':
- if (!(syntax & RE_NO_GNU_OPS))
- {
- token->type = ANCHOR;
- token->opr.idx = INSIDE_WORD;
- }
- break;
- case 'w':
- if (!(syntax & RE_NO_GNU_OPS))
- token->type = OP_WORD;
- break;
- case 'W':
- if (!(syntax & RE_NO_GNU_OPS))
- token->type = OP_NOTWORD;
- break;
- case '`':
- if (!(syntax & RE_NO_GNU_OPS))
- {
- token->type = ANCHOR;
- token->opr.idx = BUF_FIRST;
- }
- break;
- case '\'':
- if (!(syntax & RE_NO_GNU_OPS))
- {
- token->type = ANCHOR;
- token->opr.idx = BUF_LAST;
- }
- break;
- case '(':
- if (!(syntax & RE_NO_BK_PARENS))
- token->type = OP_OPEN_SUBEXP;
- break;
- case ')':
- if (!(syntax & RE_NO_BK_PARENS))
- token->type = OP_CLOSE_SUBEXP;
- break;
- case '+':
- if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))
- token->type = OP_DUP_PLUS;
- break;
- case '?':
- if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))
- token->type = OP_DUP_QUESTION;
- break;
- case '{':
- if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))
- token->type = OP_OPEN_DUP_NUM;
- break;
- case '}':
- if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))
- token->type = OP_CLOSE_DUP_NUM;
- break;
- default:
- break;
- }
- return 2;
- }
-
- token->type = CHARACTER;
- switch (c)
- {
- case '\n':
- if (syntax & RE_NEWLINE_ALT)
- token->type = OP_ALT;
- break;
- case '|':
- if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR))
- token->type = OP_ALT;
- break;
- case '*':
- token->type = OP_DUP_ASTERISK;
- break;
- case '+':
- if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))
- token->type = OP_DUP_PLUS;
- break;
- case '?':
- if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))
- token->type = OP_DUP_QUESTION;
- break;
- case '{':
- if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
- token->type = OP_OPEN_DUP_NUM;
- break;
- case '}':
- if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
- token->type = OP_CLOSE_DUP_NUM;
- break;
- case '(':
- if (syntax & RE_NO_BK_PARENS)
- token->type = OP_OPEN_SUBEXP;
- break;
- case ')':
- if (syntax & RE_NO_BK_PARENS)
- token->type = OP_CLOSE_SUBEXP;
- break;
- case '[':
- token->type = OP_OPEN_BRACKET;
- break;
- case '.':
- token->type = OP_PERIOD;
- break;
- case '^':
- if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) &&
- re_string_cur_idx (input) != 0)
- {
- char prev = re_string_peek_byte (input, -1);
- if (prev != '|' && prev != '(' &&
- (!(syntax & RE_NEWLINE_ALT) || prev != '\n'))
- break;
- }
- token->type = ANCHOR;
- token->opr.idx = LINE_FIRST;
- break;
- case '$':
- if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) &&
- re_string_cur_idx (input) + 1 != re_string_length (input))
- {
- re_token_t next;
- re_string_skip_bytes (input, 1);
- peek_token (&next, input, syntax);
- re_string_skip_bytes (input, -1);
- if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP)
- break;
- }
- token->type = ANCHOR;
- token->opr.idx = LINE_LAST;
- break;
- default:
- break;
- }
- return 1;
-}
-
-/* Peek a token from INPUT, and return the length of the token.
- We must not use this function out of bracket expressions. */
-
-static int
-peek_token_bracket (token, input, syntax)
- re_token_t *token;
- re_string_t *input;
- reg_syntax_t syntax;
-{
- unsigned char c;
- if (re_string_eoi (input))
- {
- token->type = END_OF_RE;
- return 0;
- }
- c = re_string_peek_byte (input, 0);
- token->opr.c = c;
-
-#ifdef RE_ENABLE_I18N
- if (MB_CUR_MAX > 1 &&
- !re_string_first_byte (input, re_string_cur_idx (input)))
- {
- token->type = CHARACTER;
- return 1;
- }
-#endif /* RE_ENABLE_I18N */
-
- if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS))
- {
- /* In this case, '\' escape a character. */
- unsigned char c2;
- c2 = re_string_peek_byte (input, 1);
- token->opr.c = c2;
- token->type = CHARACTER;
- return 1;
- }
- if (c == '[') /* '[' is a special char in a bracket exps. */
- {
- unsigned char c2;
- int token_len;
- c2 = re_string_peek_byte (input, 1);
- token->opr.c = c2;
- token_len = 2;
- switch (c2)
- {
- case '.':
- token->type = OP_OPEN_COLL_ELEM;
- break;
- case '=':
- token->type = OP_OPEN_EQUIV_CLASS;
- break;
- case ':':
- if (syntax & RE_CHAR_CLASSES)
- {
- token->type = OP_OPEN_CHAR_CLASS;
- break;
- }
- /* else fall through. */
- default:
- token->type = CHARACTER;
- token->opr.c = c;
- token_len = 1;
- break;
- }
- return token_len;
- }
- switch (c)
- {
- case '-':
- token->type = OP_CHARSET_RANGE;
- break;
- case ']':
- token->type = OP_CLOSE_BRACKET;
- break;
- case '^':
- token->type = OP_NON_MATCH_LIST;
- break;
- default:
- token->type = CHARACTER;
- }
- return 1;
-}
-
-/* Functions for parser. */
-
-/* Entry point of the parser.
- Parse the regular expression REGEXP and return the structure tree.
- If an error is occured, ERR is set by error code, and return NULL.
- This function build the following tree, from regular expression <reg_exp>:
- CAT
- / \
- / \
- <reg_exp> EOR
-
- CAT means concatenation.
- EOR means end of regular expression. */
-
-static bin_tree_t *
-parse (regexp, preg, syntax, err)
- re_string_t *regexp;
- regex_t *preg;
- reg_syntax_t syntax;
- reg_errcode_t *err;
-{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- bin_tree_t *tree, *eor, *root;
- re_token_t current_token;
- int new_idx;
- current_token = fetch_token (regexp, syntax);
- tree = parse_reg_exp (regexp, preg, &current_token, syntax, 0, err);
- if (BE (*err != REG_NOERROR && tree == NULL, 0))
- return NULL;
- new_idx = re_dfa_add_node (dfa, current_token, 0);
- eor = create_tree (NULL, NULL, 0, new_idx);
- if (tree != NULL)
- root = create_tree (tree, eor, CONCAT, 0);
- else
- root = eor;
- if (BE (new_idx == -1 || eor == NULL || root == NULL, 0))
- return *err = REG_ESPACE, NULL;
- return root;
-}
-
-/* This function build the following tree, from regular expression
- <branch1>|<branch2>:
- ALT
- / \
- / \
- <branch1> <branch2>
-
- ALT means alternative, which represents the operator `|'. */
-
-static bin_tree_t *
-parse_reg_exp (regexp, preg, token, syntax, nest, err)
- re_string_t *regexp;
- regex_t *preg;
- re_token_t *token;
- reg_syntax_t syntax;
- int nest;
- reg_errcode_t *err;
-{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- bin_tree_t *tree, *branch = NULL;
- int new_idx;
- tree = parse_branch (regexp, preg, token, syntax, nest, err);
- if (BE (*err != REG_NOERROR && tree == NULL, 0))
- return NULL;
-
- while (token->type == OP_ALT)
- {
- re_token_t alt_token = *token;
- new_idx = re_dfa_add_node (dfa, alt_token, 0);
- *token = fetch_token (regexp, syntax);
- if (token->type != OP_ALT && token->type != END_OF_RE
- && (nest == 0 || token->type != OP_CLOSE_SUBEXP))
- {
- branch = parse_branch (regexp, preg, token, syntax, nest, err);
- if (BE (*err != REG_NOERROR && branch == NULL, 0))
- {
- free_bin_tree (tree);
- return NULL;
- }
- }
- else
- branch = NULL;
- tree = create_tree (tree, branch, 0, new_idx);
- if (BE (new_idx == -1 || tree == NULL, 0))
- return *err = REG_ESPACE, NULL;
- dfa->has_plural_match = 1;
- }
- return tree;
-}
-
-/* This function build the following tree, from regular expression
- <exp1><exp2>:
- CAT
- / \
- / \
- <exp1> <exp2>
-
- CAT means concatenation. */
-
-static bin_tree_t *
-parse_branch (regexp, preg, token, syntax, nest, err)
- re_string_t *regexp;
- regex_t *preg;
- re_token_t *token;
- reg_syntax_t syntax;
- int nest;
- reg_errcode_t *err;
-{
- bin_tree_t *tree, *exp;
- tree = parse_expression (regexp, preg, token, syntax, nest, err);
- if (BE (*err != REG_NOERROR && tree == NULL, 0))
- return NULL;
-
- while (token->type != OP_ALT && token->type != END_OF_RE
- && (nest == 0 || token->type != OP_CLOSE_SUBEXP))
- {
- exp = parse_expression (regexp, preg, token, syntax, nest, err);
- if (BE (*err != REG_NOERROR && exp == NULL, 0))
- {
- free_bin_tree (tree);
- return NULL;
- }
- if (tree != NULL && exp != NULL)
- {
- tree = create_tree (tree, exp, CONCAT, 0);
- if (tree == NULL)
- return *err = REG_ESPACE, NULL;
- }
- else if (tree == NULL)
- tree = exp;
- /* Otherwise exp == NULL, we don't need to create new tree. */
- }
- return tree;
-}
-
-/* This function build the following tree, from regular expression a*:
- *
- |
- a
-*/
-
-static bin_tree_t *
-parse_expression (regexp, preg, token, syntax, nest, err)
- re_string_t *regexp;
- regex_t *preg;
- re_token_t *token;
- reg_syntax_t syntax;
- int nest;
- reg_errcode_t *err;
-{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- bin_tree_t *tree;
- int new_idx;
- switch (token->type)
- {
- case CHARACTER:
- new_idx = re_dfa_add_node (dfa, *token, 0);
- tree = create_tree (NULL, NULL, 0, new_idx);
- if (BE (new_idx == -1 || tree == NULL, 0))
- return *err = REG_ESPACE, NULL;
-#ifdef RE_ENABLE_I18N
- if (MB_CUR_MAX > 1)
- {
- while (!re_string_eoi (regexp)
- && !re_string_first_byte (regexp, re_string_cur_idx (regexp)))
- {
- bin_tree_t *mbc_remain;
- *token = fetch_token (regexp, syntax);
- new_idx = re_dfa_add_node (dfa, *token, 0);
- mbc_remain = create_tree (NULL, NULL, 0, new_idx);
- tree = create_tree (tree, mbc_remain, CONCAT, 0);
- if (BE (new_idx == -1 || mbc_remain == NULL || tree == NULL, 0))
- return *err = REG_ESPACE, NULL;
- }
- }
-#endif
- break;
- case OP_OPEN_SUBEXP:
- tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err);
- if (BE (*err != REG_NOERROR && tree == NULL, 0))
- return NULL;
- break;
- case OP_OPEN_BRACKET:
- tree = parse_bracket_exp (regexp, dfa, token, syntax, err);
- if (BE (*err != REG_NOERROR && tree == NULL, 0))
- return NULL;
- break;
- case OP_BACK_REF:
- if (BE (preg->re_nsub < token->opr.idx
- || dfa->subexps[token->opr.idx - 1].end == -1, 0))
- {
- *err = REG_ESUBREG;
- return NULL;
- }
- new_idx = re_dfa_add_node (dfa, *token, 0);
- tree = create_tree (NULL, NULL, 0, new_idx);
- if (BE (new_idx == -1 || tree == NULL, 0))
- return *err = REG_ESPACE, NULL;
- ++dfa->nbackref;
- dfa->has_mb_node = 1;
- break;
- case OP_DUP_ASTERISK:
- case OP_DUP_PLUS:
- case OP_DUP_QUESTION:
- case OP_OPEN_DUP_NUM:
- if (syntax & RE_CONTEXT_INVALID_OPS)
- return *err = REG_BADRPT, NULL;
- else if (syntax & RE_CONTEXT_INDEP_OPS)
- {
- *token = fetch_token (regexp, syntax);
- return parse_expression (regexp, preg, token, syntax, nest, err);
- }
- /* else fall through */
- case OP_CLOSE_SUBEXP:
- if ((token->type == OP_CLOSE_SUBEXP) &&
- !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD))
- return *err = REG_ERPAREN, NULL;
- /* else fall through */
- case OP_CLOSE_DUP_NUM:
- /* We treat it as a normal character. */
-
- /* Then we can these characters as normal characters. */
- token->type = CHARACTER;
- new_idx = re_dfa_add_node (dfa, *token, 0);
- tree = create_tree (NULL, NULL, 0, new_idx);
- if (BE (new_idx == -1 || tree == NULL, 0))
- return *err = REG_ESPACE, NULL;
- break;
- case ANCHOR:
- if (dfa->word_char == NULL)
- {
- *err = init_word_char (dfa);
- if (BE (*err != REG_NOERROR, 0))
- return NULL;
- }
- if (token->opr.ctx_type == WORD_DELIM)
- {
- bin_tree_t *tree_first, *tree_last;
- int idx_first, idx_last;
- token->opr.ctx_type = WORD_FIRST;
- idx_first = re_dfa_add_node (dfa, *token, 0);
- tree_first = create_tree (NULL, NULL, 0, idx_first);
- token->opr.ctx_type = WORD_LAST;
- idx_last = re_dfa_add_node (dfa, *token, 0);
- tree_last = create_tree (NULL, NULL, 0, idx_last);
- token->type = OP_ALT;
- new_idx = re_dfa_add_node (dfa, *token, 0);
- tree = create_tree (tree_first, tree_last, 0, new_idx);
- if (BE (idx_first == -1 || idx_last == -1 || new_idx == -1
- || tree_first == NULL || tree_last == NULL
- || tree == NULL, 0))
- return *err = REG_ESPACE, NULL;
- }
- else
- {
- new_idx = re_dfa_add_node (dfa, *token, 0);
- tree = create_tree (NULL, NULL, 0, new_idx);
- if (BE (new_idx == -1 || tree == NULL, 0))
- return *err = REG_ESPACE, NULL;
- }
- /* We must return here, since ANCHORs can't be followed
- by repetition operators.
- eg. RE"^*" is invalid or "<ANCHOR(^)><CHAR(*)>",
- it must not be "<ANCHOR(^)><REPEAT(*)>". */
- *token = fetch_token (regexp, syntax);
- return tree;
- case OP_PERIOD:
- new_idx = re_dfa_add_node (dfa, *token, 0);
- tree = create_tree (NULL, NULL, 0, new_idx);
- if (BE (new_idx == -1 || tree == NULL, 0))
- return *err = REG_ESPACE, NULL;
- if (MB_CUR_MAX > 1)
- dfa->has_mb_node = 1;
- break;
- case OP_WORD:
- tree = build_word_op (dfa, 0, err);
- if (BE (*err != REG_NOERROR && tree == NULL, 0))
- return NULL;
- break;
- case OP_NOTWORD:
- tree = build_word_op (dfa, 1, err);
- if (BE (*err != REG_NOERROR && tree == NULL, 0))
- return NULL;
- break;
- case OP_ALT:
- case END_OF_RE:
- return NULL;
- case BACK_SLASH:
- *err = REG_EESCAPE;
- return NULL;
- default:
- /* Must not happen? */
-#ifdef DEBUG
- assert (0);
-#endif
- return NULL;
- }
- *token = fetch_token (regexp, syntax);
-
- while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS
- || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM)
- {
- tree = parse_dup_op (tree, regexp, dfa, token, syntax, err);
- if (BE (*err != REG_NOERROR && tree == NULL, 0))
- return NULL;
- dfa->has_plural_match = 1;
- }
-
- return tree;
-}
-
-/* This function build the following tree, from regular expression
- (<reg_exp>):
- SUBEXP
- |
- <reg_exp>
-*/
-
-static bin_tree_t *
-parse_sub_exp (regexp, preg, token, syntax, nest, err)
- re_string_t *regexp;
- regex_t *preg;
- re_token_t *token;
- reg_syntax_t syntax;
- int nest;
- reg_errcode_t *err;
-{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- bin_tree_t *tree, *left_par, *right_par;
- size_t cur_nsub;
- int new_idx;
- cur_nsub = preg->re_nsub++;
- if (dfa->subexps_alloc < preg->re_nsub)
- {
- re_subexp_t *new_array;
- dfa->subexps_alloc *= 2;
- new_array = re_realloc (dfa->subexps, re_subexp_t, dfa->subexps_alloc);
- if (BE (new_array == NULL, 0))
- {
- dfa->subexps_alloc /= 2;
- *err = REG_ESPACE;
- return NULL;
- }
- dfa->subexps = new_array;
- }
- dfa->subexps[cur_nsub].start = dfa->nodes_len;
- dfa->subexps[cur_nsub].end = -1;
-
- new_idx = re_dfa_add_node (dfa, *token, 0);
- left_par = create_tree (NULL, NULL, 0, new_idx);
- if (BE (new_idx == -1 || left_par == NULL, 0))
- return *err = REG_ESPACE, NULL;
- dfa->nodes[new_idx].opr.idx = cur_nsub;
- *token = fetch_token (regexp, syntax);
-
- /* The subexpression may be a null string. */
- if (token->type == OP_CLOSE_SUBEXP)
- tree = NULL;
- else
- {
- tree = parse_reg_exp (regexp, preg, token, syntax, nest, err);
- if (BE (*err != REG_NOERROR && tree == NULL, 0))
- return NULL;
- }
- if (BE (token->type != OP_CLOSE_SUBEXP, 0))
- {
- free_bin_tree (tree);
- *err = REG_BADPAT;
- return NULL;
- }
- new_idx = re_dfa_add_node (dfa, *token, 0);
- dfa->subexps[cur_nsub].end = dfa->nodes_len;
- right_par = create_tree (NULL, NULL, 0, new_idx);
- tree = ((tree == NULL) ? right_par
- : create_tree (tree, right_par, CONCAT, 0));
- tree = create_tree (left_par, tree, CONCAT, 0);
- if (BE (new_idx == -1 || right_par == NULL || tree == NULL, 0))
- return *err = REG_ESPACE, NULL;
- dfa->nodes[new_idx].opr.idx = cur_nsub;
-
- return tree;
-}
-
-/* This function parse repetition operators like "*", "+", "{1,3}" etc. */
-
-static bin_tree_t *
-parse_dup_op (dup_elem, regexp, dfa, token, syntax, err)
- bin_tree_t *dup_elem;
- re_string_t *regexp;
- re_dfa_t *dfa;
- re_token_t *token;
- reg_syntax_t syntax;
- reg_errcode_t *err;
-{
- re_token_t dup_token;
- bin_tree_t *tree = dup_elem, *work_tree;
- int new_idx, start_idx = re_string_cur_idx (regexp);
- re_token_t start_token = *token;
- if (token->type == OP_OPEN_DUP_NUM)
- {
- int i;
- int end = 0;
- int start = fetch_number (regexp, token, syntax);
- bin_tree_t *elem;
- if (start == -1)
- {
- if (token->type == CHARACTER && token->opr.c == ',')
- start = 0; /* We treat "{,m}" as "{0,m}". */
- else
- {
- *err = REG_BADBR; /* <re>{} is invalid. */
- return NULL;
- }
- }
- if (BE (start != -2, 1))
- {
- /* We treat "{n}" as "{n,n}". */
- end = ((token->type == OP_CLOSE_DUP_NUM) ? start
- : ((token->type == CHARACTER && token->opr.c == ',')
- ? fetch_number (regexp, token, syntax) : -2));
- }
- if (BE (start == -2 || end == -2, 0))
- {
- /* Invalid sequence. */
- if (token->type == OP_CLOSE_DUP_NUM)
- goto parse_dup_op_invalid_interval;
- else
- goto parse_dup_op_ebrace;
- }
- if (BE (start == 0 && end == 0, 0))
- {
- /* We treat "<re>{0}" and "<re>{0,0}" as null string. */
- *token = fetch_token (regexp, syntax);
- free_bin_tree (dup_elem);
- return NULL;
- }
-
- /* Extract "<re>{n,m}" to "<re><re>...<re><re>{0,<m-n>}". */
- elem = tree;
- for (i = 0; i < start; ++i)
- if (i != 0)
- {
- work_tree = duplicate_tree (elem, dfa);
- tree = create_tree (tree, work_tree, CONCAT, 0);
- if (BE (work_tree == NULL || tree == NULL, 0))
- goto parse_dup_op_espace;
- }
-
- if (end == -1)
- {
- /* We treat "<re>{0,}" as "<re>*". */
- dup_token.type = OP_DUP_ASTERISK;
- if (start > 0)
- {
- elem = duplicate_tree (elem, dfa);
- new_idx = re_dfa_add_node (dfa, dup_token, 0);
- work_tree = create_tree (elem, NULL, 0, new_idx);
- tree = create_tree (tree, work_tree, CONCAT, 0);
- if (BE (elem == NULL || new_idx == -1 || work_tree == NULL
- || tree == NULL, 0))
- goto parse_dup_op_espace;
- }
- else
- {
- new_idx = re_dfa_add_node (dfa, dup_token, 0);
- tree = create_tree (elem, NULL, 0, new_idx);
- if (BE (new_idx == -1 || tree == NULL, 0))
- goto parse_dup_op_espace;
- }
- }
- else if (end - start > 0)
- {
- /* Then extract "<re>{0,m}" to "<re>?<re>?...<re>?". */
- dup_token.type = OP_DUP_QUESTION;
- if (start > 0)
- {
- elem = duplicate_tree (elem, dfa);
- new_idx = re_dfa_add_node (dfa, dup_token, 0);
- elem = create_tree (elem, NULL, 0, new_idx);
- tree = create_tree (tree, elem, CONCAT, 0);
- if (BE (elem == NULL || new_idx == -1 || tree == NULL, 0))
- goto parse_dup_op_espace;
- }
- else
- {
- new_idx = re_dfa_add_node (dfa, dup_token, 0);
- tree = elem = create_tree (elem, NULL, 0, new_idx);
- if (BE (new_idx == -1 || tree == NULL, 0))
- goto parse_dup_op_espace;
- }
- for (i = 1; i < end - start; ++i)
- {
- work_tree = duplicate_tree (elem, dfa);
- tree = create_tree (tree, work_tree, CONCAT, 0);
- if (BE (work_tree == NULL || tree == NULL, 0))
- return *err = REG_ESPACE, NULL;
- }
- }
- }
- else
- {
- new_idx = re_dfa_add_node (dfa, *token, 0);
- tree = create_tree (tree, NULL, 0, new_idx);
- if (BE (new_idx == -1 || tree == NULL, 0))
- return *err = REG_ESPACE, NULL;
- }
- *token = fetch_token (regexp, syntax);
- return tree;
-
- parse_dup_op_espace:
- free_bin_tree (tree);
- *err = REG_ESPACE;
- return NULL;
-
- parse_dup_op_ebrace:
- if (BE (!(syntax & RE_INVALID_INTERVAL_ORD), 0))
- {
- *err = REG_EBRACE;
- return NULL;
- }
- goto parse_dup_op_rollback;
- parse_dup_op_invalid_interval:
- if (BE (!(syntax & RE_INVALID_INTERVAL_ORD), 0))
- {
- *err = REG_BADBR;
- return NULL;
- }
- parse_dup_op_rollback:
- re_string_set_index (regexp, start_idx);
- *token = start_token;
- token->type = CHARACTER;
- return dup_elem;
-}
-
-/* Size of the names for collating symbol/equivalence_class/character_class.
- I'm not sure, but maybe enough. */
-#define BRACKET_NAME_BUF_SIZE 32
-
-#ifndef _LIBC
- /* Local function for parse_bracket_exp only used in case of NOT _LIBC.
- Build the range expression which starts from START_ELEM, and ends
- at END_ELEM. The result are written to MBCSET and SBCSET.
- RANGE_ALLOC is the allocated size of mbcset->range_starts, and
- mbcset->range_ends, is a pointer argument sinse we may
- update it. */
-
-static reg_errcode_t
-# ifdef RE_ENABLE_I18N
-build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem)
- re_charset_t *mbcset;
- int *range_alloc;
-# else /* not RE_ENABLE_I18N */
-build_range_exp (sbcset, start_elem, end_elem)
-# endif /* not RE_ENABLE_I18N */
- re_bitset_ptr_t sbcset;
- bracket_elem_t *start_elem, *end_elem;
-{
- unsigned int start_ch, end_ch;
- /* Equivalence Classes and Character Classes can't be a range start/end. */
- if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS
- || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS,
- 0))
- return REG_ERANGE;
-
- /* We can handle no multi character collating elements without libc
- support. */
- if (BE ((start_elem->type == COLL_SYM
- && strlen ((char *) start_elem->opr.name) > 1)
- || (end_elem->type == COLL_SYM
- && strlen ((char *) end_elem->opr.name) > 1), 0))
- return REG_ECOLLATE;
-
-# ifdef RE_ENABLE_I18N
- {
- wchar_t wc, start_wc, end_wc;
- wchar_t cmp_buf[6] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'};
-
- start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch
- : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
- : 0));
- end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch
- : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
- : 0));
- start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM)
- ? __btowc (start_ch) : start_elem->opr.wch);
- end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM)
- ? __btowc (end_ch) : end_elem->opr.wch);
- cmp_buf[0] = start_wc;
- cmp_buf[4] = end_wc;
- if (wcscoll (cmp_buf, cmp_buf + 4) > 0)
- return REG_ERANGE;
-
- /* Check the space of the arrays. */
- if (*range_alloc == mbcset->nranges)
- {
- /* There are not enough space, need realloc. */
- wchar_t *new_array_start, *new_array_end;
- int new_nranges;
-
- /* +1 in case of mbcset->nranges is 0. */
- new_nranges = 2 * mbcset->nranges + 1;
- /* Use realloc since mbcset->range_starts and mbcset->range_ends
- are NULL if *range_alloc == 0. */
- new_array_start = re_realloc (mbcset->range_starts, wchar_t,
- new_nranges);
- new_array_end = re_realloc (mbcset->range_ends, wchar_t,
- new_nranges);
-
- if (BE (new_array_start == NULL || new_array_end == NULL, 0))
- return REG_ESPACE;
-
- mbcset->range_starts = new_array_start;
- mbcset->range_ends = new_array_end;
- *range_alloc = new_nranges;
- }
-
- mbcset->range_starts[mbcset->nranges] = start_wc;
- mbcset->range_ends[mbcset->nranges++] = end_wc;
-
- /* Build the table for single byte characters. */
- for (wc = 0; wc <= SBC_MAX; ++wc)
- {
- cmp_buf[2] = wc;
- if (wcscoll (cmp_buf, cmp_buf + 2) <= 0
- && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0)
- bitset_set (sbcset, wc);
- }
- }
-# else /* not RE_ENABLE_I18N */
- {
- unsigned int ch;
- start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch
- : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
- : 0));
- end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch
- : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
- : 0));
- if (start_ch > end_ch)
- return REG_ERANGE;
- /* Build the table for single byte characters. */
- for (ch = 0; ch <= SBC_MAX; ++ch)
- if (start_ch <= ch && ch <= end_ch)
- bitset_set (sbcset, ch);
- }
-# endif /* not RE_ENABLE_I18N */
- return REG_NOERROR;
-}
-#endif /* not _LIBC */
-
-#ifndef _LIBC
-/* Helper function for parse_bracket_exp only used in case of NOT _LIBC..
- Build the collating element which is represented by NAME.
- The result are written to MBCSET and SBCSET.
- COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
- pointer argument since we may update it. */
-
-static reg_errcode_t
-# ifdef RE_ENABLE_I18N
-build_collating_symbol (sbcset, mbcset, coll_syxmalloc, name)
- re_charset_t *mbcset;
- int *coll_syxmalloc;
-# else /* not RE_ENABLE_I18N */
-build_collating_symbol (sbcset, name)
-# endif /* not RE_ENABLE_I18N */
- re_bitset_ptr_t sbcset;
- const unsigned char *name;
-{
- size_t name_len = strlen ((const char *) name);
- if (BE (name_len != 1, 0))
- return REG_ECOLLATE;
- else
- {
- bitset_set (sbcset, name[0]);
- return REG_NOERROR;
- }
-}
-#endif /* not _LIBC */
-
-/* This function parse bracket expression like "[abc]", "[a-c]",
- "[[.a-a.]]" etc. */
-
-static bin_tree_t *
-parse_bracket_exp (regexp, dfa, token, syntax, err)
- re_string_t *regexp;
- re_dfa_t *dfa;
- re_token_t *token;
- reg_syntax_t syntax;
- reg_errcode_t *err;
-{
-#ifdef _LIBC
- const unsigned char *collseqmb;
- const char *collseqwc;
- uint32_t nrules;
- int32_t table_size;
- const int32_t *symb_table;
- const unsigned char *extra;
-
- /* Local function for parse_bracket_exp used in _LIBC environement.
- Seek the collating symbol entry correspondings to NAME.
- Return the index of the symbol in the SYMB_TABLE. */
-
- static inline int32_t
- seek_collating_symbol_entry (name, name_len)
- const unsigned char *name;
- size_t name_len;
- {
- int32_t hash = elem_hash ((const char *) name, name_len);
- int32_t elem = hash % table_size;
- int32_t second = hash % (table_size - 2);
- while (symb_table[2 * elem] != 0)
- {
- /* First compare the hashing value. */
- if (symb_table[2 * elem] == hash
- /* Compare the length of the name. */
- && name_len == extra[symb_table[2 * elem + 1]]
- /* Compare the name. */
- && memcmp (name, &extra[symb_table[2 * elem + 1] + 1],
- name_len) == 0)
- {
- /* Yep, this is the entry. */
- break;
- }
-
- /* Next entry. */
- elem += second;
- }
- return elem;
- }
-
- /* Local function for parse_bracket_exp used in _LIBC environement.
- Look up the collation sequence value of BR_ELEM.
- Return the value if succeeded, UINT_MAX otherwise. */
-
- static inline unsigned int
- lookup_collation_sequence_value (br_elem)
- bracket_elem_t *br_elem;
- {
- if (br_elem->type == SB_CHAR)
- {
- /*
- if (MB_CUR_MAX == 1)
- */
- if (nrules == 0)
- return collseqmb[br_elem->opr.ch];
- else
- {
- wint_t wc = __btowc (br_elem->opr.ch);
- return collseq_table_lookup (collseqwc, wc);
- }
- }
- else if (br_elem->type == MB_CHAR)
- {
- return collseq_table_lookup (collseqwc, br_elem->opr.wch);
- }
- else if (br_elem->type == COLL_SYM)
- {
- size_t sym_name_len = strlen ((char *) br_elem->opr.name);
- if (nrules != 0)
- {
- int32_t elem, idx;
- elem = seek_collating_symbol_entry (br_elem->opr.name,
- sym_name_len);
- if (symb_table[2 * elem] != 0)
- {
- /* We found the entry. */
- idx = symb_table[2 * elem + 1];
- /* Skip the name of collating element name. */
- idx += 1 + extra[idx];
- /* Skip the byte sequence of the collating element. */
- idx += 1 + extra[idx];
- /* Adjust for the alignment. */
- idx = (idx + 3) & ~3;
- /* Skip the multibyte collation sequence value. */
- idx += sizeof (unsigned int);
- /* Skip the wide char sequence of the collating element. */
- idx += sizeof (unsigned int) *
- (1 + *(unsigned int *) (extra + idx));
- /* Return the collation sequence value. */
- return *(unsigned int *) (extra + idx);
- }
- else if (symb_table[2 * elem] == 0 && sym_name_len == 1)
- {
- /* No valid character. Match it as a single byte
- character. */
- return collseqmb[br_elem->opr.name[0]];
- }
- }
- else if (sym_name_len == 1)
- return collseqmb[br_elem->opr.name[0]];
- }
- return UINT_MAX;
- }
-
- /* Local function for parse_bracket_exp used in _LIBC environement.
- Build the range expression which starts from START_ELEM, and ends
- at END_ELEM. The result are written to MBCSET and SBCSET.
- RANGE_ALLOC is the allocated size of mbcset->range_starts, and
- mbcset->range_ends, is a pointer argument sinse we may
- update it. */
-
- static inline reg_errcode_t
-# ifdef RE_ENABLE_I18N
- build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem)
- re_charset_t *mbcset;
- int *range_alloc;
-# else /* not RE_ENABLE_I18N */
- build_range_exp (sbcset, start_elem, end_elem)
-# endif /* not RE_ENABLE_I18N */
- re_bitset_ptr_t sbcset;
- bracket_elem_t *start_elem, *end_elem;
- {
- unsigned int ch;
- uint32_t start_collseq;
- uint32_t end_collseq;
-
-# ifdef RE_ENABLE_I18N
- /* Check the space of the arrays. */
- if (*range_alloc == mbcset->nranges)
- {
- /* There are not enough space, need realloc. */
- uint32_t *new_array_start;
- uint32_t *new_array_end;
- int new_nranges;
-
- /* +1 in case of mbcset->nranges is 0. */
- new_nranges = 2 * mbcset->nranges + 1;
- /* Use realloc since mbcset->range_starts and mbcset->range_ends
- are NULL if *range_alloc == 0. */
- new_array_start = re_realloc (mbcset->range_starts, uint32_t,
- new_nranges);
- new_array_end = re_realloc (mbcset->range_ends, uint32_t,
- new_nranges);
-
- if (BE (new_array_start == NULL || new_array_end == NULL, 0))
- return REG_ESPACE;
-
- mbcset->range_starts = new_array_start;
- mbcset->range_ends = new_array_end;
- *range_alloc = new_nranges;
- }
-# endif /* RE_ENABLE_I18N */
-
- /* Equivalence Classes and Character Classes can't be a range
- start/end. */
- if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS
- || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS,
- 0))
- return REG_ERANGE;
-
- start_collseq = lookup_collation_sequence_value (start_elem);
- end_collseq = lookup_collation_sequence_value (end_elem);
- /* Check start/end collation sequence values. */
- if (BE (start_collseq == UINT_MAX || end_collseq == UINT_MAX, 0))
- return REG_ECOLLATE;
- if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_collseq > end_collseq, 0))
- return REG_ERANGE;
-
-# ifdef RE_ENABLE_I18N
- /* Got valid collation sequence values, add them as a new entry. */
- mbcset->range_starts[mbcset->nranges] = start_collseq;
- mbcset->range_ends[mbcset->nranges++] = end_collseq;
-# endif /* RE_ENABLE_I18N */
-
- /* Build the table for single byte characters. */
- for (ch = 0; ch <= SBC_MAX; ch++)
- {
- uint32_t ch_collseq;
- /*
- if (MB_CUR_MAX == 1)
- */
- if (nrules == 0)
- ch_collseq = collseqmb[ch];
- else
- ch_collseq = collseq_table_lookup (collseqwc, __btowc (ch));
- if (start_collseq <= ch_collseq && ch_collseq <= end_collseq)
- bitset_set (sbcset, ch);
- }
- return REG_NOERROR;
- }
-
- /* Local function for parse_bracket_exp used in _LIBC environement.
- Build the collating element which is represented by NAME.
- The result are written to MBCSET and SBCSET.
- COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
- pointer argument sinse we may update it. */
-
- static inline reg_errcode_t
-# ifdef RE_ENABLE_I18N
- build_collating_symbol (sbcset, mbcset, coll_syxmalloc, name)
- re_charset_t *mbcset;
- int *coll_syxmalloc;
-# else /* not RE_ENABLE_I18N */
- build_collating_symbol (sbcset, name)
-# endif /* not RE_ENABLE_I18N */
- re_bitset_ptr_t sbcset;
- const unsigned char *name;
- {
- int32_t elem, idx;
- size_t name_len = strlen ((const char *) name);
- if (nrules != 0)
- {
- elem = seek_collating_symbol_entry (name, name_len);
- if (symb_table[2 * elem] != 0)
- {
- /* We found the entry. */
- idx = symb_table[2 * elem + 1];
- /* Skip the name of collating element name. */
- idx += 1 + extra[idx];
- }
- else if (symb_table[2 * elem] == 0 && name_len == 1)
- {
- /* No valid character, treat it as a normal
- character. */
- bitset_set (sbcset, name[0]);
- return REG_NOERROR;
- }
- else
- return REG_ECOLLATE;
-
-# ifdef RE_ENABLE_I18N
- /* Got valid collation sequence, add it as a new entry. */
- /* Check the space of the arrays. */
- if (*coll_syxmalloc == mbcset->ncoll_syms)
- {
- /* Not enough, realloc it. */
- /* +1 in case of mbcset->ncoll_syms is 0. */
- *coll_syxmalloc = 2 * mbcset->ncoll_syms + 1;
- /* Use realloc since mbcset->coll_syms is NULL
- if *alloc == 0. */
- mbcset->coll_syms = re_realloc (mbcset->coll_syms, int32_t,
- *coll_syxmalloc);
- if (BE (mbcset->coll_syms == NULL, 0))
- return REG_ESPACE;
- }
- mbcset->coll_syms[mbcset->ncoll_syms++] = idx;
-# endif /* RE_ENABLE_I18N */
- return REG_NOERROR;
- }
- else
- {
- if (BE (name_len != 1, 0))
- return REG_ECOLLATE;
- else
- {
- bitset_set (sbcset, name[0]);
- return REG_NOERROR;
- }
- }
- }
-#endif
-
- re_token_t br_token;
- re_bitset_ptr_t sbcset;
-#ifdef RE_ENABLE_I18N
- re_charset_t *mbcset;
- int coll_syxmalloc = 0, range_alloc = 0, mbchar_alloc = 0;
- int equiv_class_alloc = 0, char_class_alloc = 0;
-#else /* not RE_ENABLE_I18N */
- int non_match = 0;
-#endif /* not RE_ENABLE_I18N */
- bin_tree_t *work_tree;
- int token_len, new_idx;
-#ifdef _LIBC
- collseqmb = (const unsigned char *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
- nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
- if (nrules)
- {
- /*
- if (MB_CUR_MAX > 1)
- */
- collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);
- table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB);
- symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE,
- _NL_COLLATE_SYMB_TABLEMB);
- extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
- _NL_COLLATE_SYMB_EXTRAMB);
- }
-#endif
- sbcset = (re_bitset_ptr_t) calloc (sizeof (unsigned int), BITSET_UINTS);
-#ifdef RE_ENABLE_I18N
- mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
-#endif /* RE_ENABLE_I18N */
-#ifdef RE_ENABLE_I18N
- if (BE (sbcset == NULL || mbcset == NULL, 0))
-#else
- if (BE (sbcset == NULL, 0))
-#endif /* RE_ENABLE_I18N */
- {
- *err = REG_ESPACE;
- return NULL;
- }
-
- token_len = peek_token_bracket (token, regexp, syntax);
- if (BE (token->type == END_OF_RE, 0))
- {
- *err = REG_BADPAT;
- goto parse_bracket_exp_free_return;
- }
- if (token->type == OP_NON_MATCH_LIST)
- {
-#ifdef RE_ENABLE_I18N
- int i;
- mbcset->non_match = 1;
-#else /* not RE_ENABLE_I18N */
- non_match = 1;
-#endif /* not RE_ENABLE_I18N */
- if (syntax & RE_HAT_LISTS_NOT_NEWLINE)
- bitset_set (sbcset, '\0');
- re_string_skip_bytes (regexp, token_len); /* Skip a token. */
- token_len = peek_token_bracket (token, regexp, syntax);
- if (BE (token->type == END_OF_RE, 0))
- {
- *err = REG_BADPAT;
- goto parse_bracket_exp_free_return;
- }
-#ifdef RE_ENABLE_I18N
- if (MB_CUR_MAX > 1)
- for (i = 0; i < SBC_MAX; ++i)
- if (__btowc (i) == WEOF)
- bitset_set (sbcset, i);
-#endif /* RE_ENABLE_I18N */
- }
-
- /* We treat the first ']' as a normal character. */
- if (token->type == OP_CLOSE_BRACKET)
- token->type = CHARACTER;
-
- while (1)
- {
- bracket_elem_t start_elem, end_elem;
- unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE];
- unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE];
- reg_errcode_t ret;
- int token_len2 = 0, is_range_exp = 0;
- re_token_t token2;
-
- start_elem.opr.name = start_name_buf;
- ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa,
- syntax);
- if (BE (ret != REG_NOERROR, 0))
- {
- *err = ret;
- goto parse_bracket_exp_free_return;
- }
-
- token_len = peek_token_bracket (token, regexp, syntax);
- if (BE (token->type == END_OF_RE, 0))
- {
- *err = REG_BADPAT;
- goto parse_bracket_exp_free_return;
- }
- if (token->type == OP_CHARSET_RANGE)
- {
- re_string_skip_bytes (regexp, token_len); /* Skip '-'. */
- token_len2 = peek_token_bracket (&token2, regexp, syntax);
- if (BE (token->type == END_OF_RE, 0))
- {
- *err = REG_BADPAT;
- goto parse_bracket_exp_free_return;
- }
- if (token2.type == OP_CLOSE_BRACKET)
- {
- /* We treat the last '-' as a normal character. */
- re_string_skip_bytes (regexp, -token_len);
- token->type = CHARACTER;
- }
- else
- is_range_exp = 1;
- }
-
- if (is_range_exp == 1)
- {
- end_elem.opr.name = end_name_buf;
- ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2,
- dfa, syntax);
- if (BE (ret != REG_NOERROR, 0))
- {
- *err = ret;
- goto parse_bracket_exp_free_return;
- }
-
- token_len = peek_token_bracket (token, regexp, syntax);
- if (BE (token->type == END_OF_RE, 0))
- {
- *err = REG_BADPAT;
- goto parse_bracket_exp_free_return;
- }
- *err = build_range_exp (sbcset,
-#ifdef RE_ENABLE_I18N
- mbcset, &range_alloc,
-#endif /* RE_ENABLE_I18N */
- &start_elem, &end_elem);
- if (BE (*err != REG_NOERROR, 0))
- goto parse_bracket_exp_free_return;
- }
- else
- {
- switch (start_elem.type)
- {
- case SB_CHAR:
- bitset_set (sbcset, start_elem.opr.ch);
- break;
-#ifdef RE_ENABLE_I18N
- case MB_CHAR:
- /* Check whether the array has enough space. */
- if (mbchar_alloc == mbcset->nmbchars)
- {
- /* Not enough, realloc it. */
- /* +1 in case of mbcset->nmbchars is 0. */
- mbchar_alloc = 2 * mbcset->nmbchars + 1;
- /* Use realloc since array is NULL if *alloc == 0. */
- mbcset->mbchars = re_realloc (mbcset->mbchars, wchar_t,
- mbchar_alloc);
- if (BE (mbcset->mbchars == NULL, 0))
- goto parse_bracket_exp_espace;
- }
- mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch;
- break;
-#endif /* RE_ENABLE_I18N */
- case EQUIV_CLASS:
- *err = build_equiv_class (sbcset,
-#ifdef RE_ENABLE_I18N
- mbcset, &equiv_class_alloc,
-#endif /* RE_ENABLE_I18N */
- start_elem.opr.name);
- if (BE (*err != REG_NOERROR, 0))
- goto parse_bracket_exp_free_return;
- break;
- case COLL_SYM:
- *err = build_collating_symbol (sbcset,
-#ifdef RE_ENABLE_I18N
- mbcset, &coll_syxmalloc,
-#endif /* RE_ENABLE_I18N */
- start_elem.opr.name);
- if (BE (*err != REG_NOERROR, 0))
- goto parse_bracket_exp_free_return;
- break;
- case CHAR_CLASS:
- ret = build_charclass (sbcset,
-#ifdef RE_ENABLE_I18N
- mbcset, &char_class_alloc,
-#endif /* RE_ENABLE_I18N */
- start_elem.opr.name, syntax);
- if (BE (ret != REG_NOERROR, 0))
- goto parse_bracket_exp_espace;
- break;
- default:
- assert (0);
- break;
- }
- }
- if (token->type == OP_CLOSE_BRACKET)
- break;
- }
-
- re_string_skip_bytes (regexp, token_len); /* Skip a token. */
-
- /* If it is non-matching list. */
-#ifdef RE_ENABLE_I18N
- if (mbcset->non_match)
-#else /* not RE_ENABLE_I18N */
- if (non_match)
-#endif /* not RE_ENABLE_I18N */
- bitset_not (sbcset);
-
- /* Build a tree for simple bracket. */
- br_token.type = SIMPLE_BRACKET;
- br_token.opr.sbcset = sbcset;
- new_idx = re_dfa_add_node (dfa, br_token, 0);
- work_tree = create_tree (NULL, NULL, 0, new_idx);
- if (BE (new_idx == -1 || work_tree == NULL, 0))
- goto parse_bracket_exp_espace;
-
-#ifdef RE_ENABLE_I18N
- if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes
- || mbcset->nranges || (MB_CUR_MAX > 1 && (mbcset->nchar_classes
- || mbcset->non_match)))
- {
- re_token_t alt_token;
- bin_tree_t *mbc_tree;
- /* Build a tree for complex bracket. */
- br_token.type = COMPLEX_BRACKET;
- br_token.opr.mbcset = mbcset;
- dfa->has_mb_node = 1;
- new_idx = re_dfa_add_node (dfa, br_token, 0);
- mbc_tree = create_tree (NULL, NULL, 0, new_idx);
- if (BE (new_idx == -1 || mbc_tree == NULL, 0))
- goto parse_bracket_exp_espace;
- /* Then join them by ALT node. */
- dfa->has_plural_match = 1;
- alt_token.type = OP_ALT;
- new_idx = re_dfa_add_node (dfa, alt_token, 0);
- work_tree = create_tree (work_tree, mbc_tree, 0, new_idx);
- if (BE (new_idx != -1 && mbc_tree != NULL, 1))
- return work_tree;
- }
- else
- {
- free_charset (mbcset);
- return work_tree;
- }
-#else /* not RE_ENABLE_I18N */
- return work_tree;
-#endif /* not RE_ENABLE_I18N */
-
- parse_bracket_exp_espace:
- *err = REG_ESPACE;
- parse_bracket_exp_free_return:
- re_free (sbcset);
-#ifdef RE_ENABLE_I18N
- free_charset (mbcset);
-#endif /* RE_ENABLE_I18N */
- return NULL;
-}
-
-/* Parse an element in the bracket expression. */
-
-static reg_errcode_t
-parse_bracket_element (elem, regexp, token, token_len, dfa, syntax)
- bracket_elem_t *elem;
- re_string_t *regexp;
- re_token_t *token;
- int token_len;
- re_dfa_t *dfa;
- reg_syntax_t syntax;
-{
-#ifdef RE_ENABLE_I18N
- int cur_char_size;
- cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp));
- if (cur_char_size > 1)
- {
- elem->type = MB_CHAR;
- elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp));
- re_string_skip_bytes (regexp, cur_char_size);
- return REG_NOERROR;
- }
-#endif /* RE_ENABLE_I18N */
- re_string_skip_bytes (regexp, token_len); /* Skip a token. */
- if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS
- || token->type == OP_OPEN_EQUIV_CLASS)
- return parse_bracket_symbol (elem, regexp, token);
- elem->type = SB_CHAR;
- elem->opr.ch = token->opr.c;
- return REG_NOERROR;
-}
-
-/* Parse a bracket symbol in the bracket expression. Bracket symbols are
- such as [:<character_class>:], [.<collating_element>.], and
- [=<equivalent_class>=]. */
-
-static reg_errcode_t
-parse_bracket_symbol (elem, regexp, token)
- bracket_elem_t *elem;
- re_string_t *regexp;
- re_token_t *token;
-{
- unsigned char ch, delim = token->opr.c;
- int i = 0;
- for (;; ++i)
- {
- if (re_string_eoi(regexp) || i >= BRACKET_NAME_BUF_SIZE)
- return REG_EBRACK;
- if (token->type == OP_OPEN_CHAR_CLASS)
- ch = re_string_fetch_byte_case (regexp);
- else
- ch = re_string_fetch_byte (regexp);
- if (ch == delim && re_string_peek_byte (regexp, 0) == ']')
- break;
- elem->opr.name[i] = ch;
- }
- re_string_skip_bytes (regexp, 1);
- elem->opr.name[i] = '\0';
- switch (token->type)
- {
- case OP_OPEN_COLL_ELEM:
- elem->type = COLL_SYM;
- break;
- case OP_OPEN_EQUIV_CLASS:
- elem->type = EQUIV_CLASS;
- break;
- case OP_OPEN_CHAR_CLASS:
- elem->type = CHAR_CLASS;
- break;
- default:
- break;
- }
- return REG_NOERROR;
-}
-
- /* Helper function for parse_bracket_exp.
- Build the equivalence class which is represented by NAME.
- The result are written to MBCSET and SBCSET.
- EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes,
- is a pointer argument sinse we may update it. */
-
-static reg_errcode_t
-#ifdef RE_ENABLE_I18N
-build_equiv_class (sbcset, mbcset, equiv_class_alloc, name)
- re_charset_t *mbcset;
- int *equiv_class_alloc;
-#else /* not RE_ENABLE_I18N */
-build_equiv_class (sbcset, name)
-#endif /* not RE_ENABLE_I18N */
- re_bitset_ptr_t sbcset;
- const unsigned char *name;
-{
-#if defined _LIBC && defined RE_ENABLE_I18N
- uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
- if (nrules != 0)
- {
- const int32_t *table, *indirect;
- const unsigned char *weights, *extra, *cp;
- unsigned char char_buf[2];
- int32_t idx1, idx2;
- unsigned int ch;
- size_t len;
- /* This #include defines a local function! */
-# include <locale/weight.h>
- /* Calculate the index for equivalence class. */
- cp = name;
- table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
- weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
- _NL_COLLATE_WEIGHTMB);
- extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
- _NL_COLLATE_EXTRAMB);
- indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
- _NL_COLLATE_INDIRECTMB);
- idx1 = findidx (&cp);
- if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0))
- /* This isn't a valid character. */
- return REG_ECOLLATE;
-
- /* Build single byte matcing table for this equivalence class. */
- char_buf[1] = (unsigned char) '\0';
- len = weights[idx1];
- for (ch = 0; ch < SBC_MAX; ++ch)
- {
- char_buf[0] = ch;
- cp = char_buf;
- idx2 = findidx (&cp);
-/*
- idx2 = table[ch];
-*/
- if (idx2 == 0)
- /* This isn't a valid character. */
- continue;
- if (len == weights[idx2])
- {
- int cnt = 0;
- while (cnt <= len &&
- weights[idx1 + 1 + cnt] == weights[idx2 + 1 + cnt])
- ++cnt;
-
- if (cnt > len)
- bitset_set (sbcset, ch);
- }
- }
- /* Check whether the array has enough space. */
- if (*equiv_class_alloc == mbcset->nequiv_classes)
- {
- /* Not enough, realloc it. */
- /* +1 in case of mbcset->nequiv_classes is 0. */
- *equiv_class_alloc = 2 * mbcset->nequiv_classes + 1;
- /* Use realloc since the array is NULL if *alloc == 0. */
- mbcset->equiv_classes = re_realloc (mbcset->equiv_classes, int32_t,
- *equiv_class_alloc);
- if (BE (mbcset->equiv_classes == NULL, 0))
- return REG_ESPACE;
- }
- mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1;
- }
- else
-#endif /* _LIBC && RE_ENABLE_I18N */
- {
- if (BE (strlen ((const char *) name) != 1, 0))
- return REG_ECOLLATE;
- bitset_set (sbcset, *name);
- }
- return REG_NOERROR;
-}
-
- /* Helper function for parse_bracket_exp.
- Build the character class which is represented by NAME.
- The result are written to MBCSET and SBCSET.
- CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes,
- is a pointer argument sinse we may update it. */
-
-static reg_errcode_t
-#ifdef RE_ENABLE_I18N
-build_charclass (sbcset, mbcset, char_class_alloc, class_name, syntax)
- re_charset_t *mbcset;
- int *char_class_alloc;
-#else /* not RE_ENABLE_I18N */
-build_charclass (sbcset, class_name, syntax)
-#endif /* not RE_ENABLE_I18N */
- re_bitset_ptr_t sbcset;
- const unsigned char *class_name;
- reg_syntax_t syntax;
-{
- int i;
- const char *name = (const char *) class_name;
-
- /* In case of REG_ICASE "upper" and "lower" match the both of
- upper and lower cases. */
- if ((syntax & RE_ICASE)
- && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0))
- name = "alpha";
-
-#ifdef RE_ENABLE_I18N
- /* Check the space of the arrays. */
- if (*char_class_alloc == mbcset->nchar_classes)
- {
- /* Not enough, realloc it. */
- /* +1 in case of mbcset->nchar_classes is 0. */
- *char_class_alloc = 2 * mbcset->nchar_classes + 1;
- /* Use realloc since array is NULL if *alloc == 0. */
- mbcset->char_classes = re_realloc (mbcset->char_classes, wctype_t,
- *char_class_alloc);
- if (BE (mbcset->char_classes == NULL, 0))
- return REG_ESPACE;
- }
- mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name);
-#endif /* RE_ENABLE_I18N */
-
-#define BUILD_CHARCLASS_LOOP(ctype_func)\
- for (i = 0; i < SBC_MAX; ++i) \
- { \
- if (ctype_func (i)) \
- bitset_set (sbcset, i); \
- }
-
- if (strcmp (name, "alnum") == 0)
- BUILD_CHARCLASS_LOOP (isalnum)
- else if (strcmp (name, "cntrl") == 0)
- BUILD_CHARCLASS_LOOP (iscntrl)
- else if (strcmp (name, "lower") == 0)
- BUILD_CHARCLASS_LOOP (islower)
- else if (strcmp (name, "space") == 0)
- BUILD_CHARCLASS_LOOP (isspace)
- else if (strcmp (name, "alpha") == 0)
- BUILD_CHARCLASS_LOOP (isalpha)
- else if (strcmp (name, "digit") == 0)
- BUILD_CHARCLASS_LOOP (isdigit)
- else if (strcmp (name, "print") == 0)
- BUILD_CHARCLASS_LOOP (isprint)
- else if (strcmp (name, "upper") == 0)
- BUILD_CHARCLASS_LOOP (isupper)
- else if (strcmp (name, "blank") == 0)
- BUILD_CHARCLASS_LOOP (isblank)
- else if (strcmp (name, "graph") == 0)
- BUILD_CHARCLASS_LOOP (isgraph)
- else if (strcmp (name, "punct") == 0)
- BUILD_CHARCLASS_LOOP (ispunct)
- else if (strcmp (name, "xdigit") == 0)
- BUILD_CHARCLASS_LOOP (isxdigit)
- else
- return REG_ECTYPE;
-
- return REG_NOERROR;
-}
-
-static bin_tree_t *
-build_word_op (dfa, not, err)
- re_dfa_t *dfa;
- int not;
- reg_errcode_t *err;
-{
- re_bitset_ptr_t sbcset;
-#ifdef RE_ENABLE_I18N
- re_charset_t *mbcset;
- int alloc = 0;
-#else /* not RE_ENABLE_I18N */
- int non_match = 0;
-#endif /* not RE_ENABLE_I18N */
- reg_errcode_t ret;
- re_token_t br_token;
- bin_tree_t *tree;
- int new_idx;
-
- sbcset = (re_bitset_ptr_t) calloc (sizeof (unsigned int), BITSET_UINTS);
-#ifdef RE_ENABLE_I18N
- mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
-#endif /* RE_ENABLE_I18N */
-
-#ifdef RE_ENABLE_I18N
- if (BE (sbcset == NULL || mbcset == NULL, 0))
-#else /* not RE_ENABLE_I18N */
- if (BE (sbcset == NULL, 0))
-#endif /* not RE_ENABLE_I18N */
- {
- *err = REG_ESPACE;
- return NULL;
- }
-
- if (not)
- {
-#ifdef RE_ENABLE_I18N
- int i;
- /*
- if (syntax & RE_HAT_LISTS_NOT_NEWLINE)
- bitset_set(cset->sbcset, '\0');
- */
- mbcset->non_match = 1;
- if (MB_CUR_MAX > 1)
- for (i = 0; i < SBC_MAX; ++i)
- if (__btowc (i) == WEOF)
- bitset_set (sbcset, i);
-#else /* not RE_ENABLE_I18N */
- non_match = 1;
-#endif /* not RE_ENABLE_I18N */
- }
-
- /* We don't care the syntax in this case. */
- ret = build_charclass (sbcset,
-#ifdef RE_ENABLE_I18N
- mbcset, &alloc,
-#endif /* RE_ENABLE_I18N */
- (const unsigned char *) "alpha", 0);
-
- if (BE (ret != REG_NOERROR, 0))
- {
- re_free (sbcset);
-#ifdef RE_ENABLE_I18N
- free_charset (mbcset);
-#endif /* RE_ENABLE_I18N */
- *err = REG_ESPACE;
- return NULL;
- }
- /* \w match '_' also. */
- bitset_set (sbcset, '_');
-
- /* If it is non-matching list. */
-#ifdef RE_ENABLE_I18N
- if (mbcset->non_match)
-#else /* not RE_ENABLE_I18N */
- if (non_match)
-#endif /* not RE_ENABLE_I18N */
- bitset_not (sbcset);
-
- /* Build a tree for simple bracket. */
- br_token.type = SIMPLE_BRACKET;
- br_token.opr.sbcset = sbcset;
- new_idx = re_dfa_add_node (dfa, br_token, 0);
- tree = create_tree (NULL, NULL, 0, new_idx);
- if (BE (new_idx == -1 || tree == NULL, 0))
- goto build_word_op_espace;
-
-#ifdef RE_ENABLE_I18N
- if (MB_CUR_MAX > 1)
- {
- re_token_t alt_token;
- bin_tree_t *mbc_tree;
- /* Build a tree for complex bracket. */
- br_token.type = COMPLEX_BRACKET;
- br_token.opr.mbcset = mbcset;
- dfa->has_mb_node = 1;
- new_idx = re_dfa_add_node (dfa, br_token, 0);
- mbc_tree = create_tree (NULL, NULL, 0, new_idx);
- if (BE (new_idx == -1 || mbc_tree == NULL, 0))
- goto build_word_op_espace;
- /* Then join them by ALT node. */
- alt_token.type = OP_ALT;
- new_idx = re_dfa_add_node (dfa, alt_token, 0);
- tree = create_tree (tree, mbc_tree, 0, new_idx);
- if (BE (new_idx != -1 && mbc_tree != NULL, 1))
- return tree;
- }
- else
- {
- free_charset (mbcset);
- return tree;
- }
-#else /* not RE_ENABLE_I18N */
- return tree;
-#endif /* not RE_ENABLE_I18N */
-
- build_word_op_espace:
- re_free (sbcset);
-#ifdef RE_ENABLE_I18N
- free_charset (mbcset);
-#endif /* RE_ENABLE_I18N */
- *err = REG_ESPACE;
- return NULL;
-}
-
-/* This is intended for the expressions like "a{1,3}".
- Fetch a number from `input', and return the number.
- Return -1, if the number field is empty like "{,1}".
- Return -2, If an error is occured. */
-
-static int
-fetch_number (input, token, syntax)
- re_string_t *input;
- re_token_t *token;
- reg_syntax_t syntax;
-{
- int num = -1;
- unsigned char c;
- while (1)
- {
- *token = fetch_token (input, syntax);
- c = token->opr.c;
- if (BE (token->type == END_OF_RE, 0))
- return -2;
- if (token->type == OP_CLOSE_DUP_NUM || c == ',')
- break;
- num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2)
- ? -2 : ((num == -1) ? c - '0' : num * 10 + c - '0'));
- num = (num > RE_DUP_MAX) ? -2 : num;
- }
- return num;
-}
-
-#ifdef RE_ENABLE_I18N
-static void
-free_charset (re_charset_t *cset)
-{
- re_free (cset->mbchars);
-# ifdef _LIBC
- re_free (cset->coll_syms);
- re_free (cset->equiv_classes);
- re_free (cset->range_starts);
- re_free (cset->range_ends);
-# endif
- re_free (cset->char_classes);
- re_free (cset);
-}
-#endif /* RE_ENABLE_I18N */
-
-/* Functions for binary tree operation. */
-
-/* Create a node of tree.
- Note: This function automatically free left and right if malloc fails. */
-
-static bin_tree_t *
-create_tree (left, right, type, index)
- bin_tree_t *left;
- bin_tree_t *right;
- re_token_type_t type;
- int index;
-{
- bin_tree_t *tree;
- tree = re_malloc (bin_tree_t, 1);
- if (BE (tree == NULL, 0))
- {
- free_bin_tree (left);
- free_bin_tree (right);
- return NULL;
- }
- tree->parent = NULL;
- tree->left = left;
- tree->right = right;
- tree->type = type;
- tree->node_idx = index;
- tree->first = -1;
- tree->next = -1;
- re_node_set_init_empty (&tree->eclosure);
-
- if (left != NULL)
- left->parent = tree;
- if (right != NULL)
- right->parent = tree;
- return tree;
-}
-
-/* Free the sub tree pointed by TREE. */
-
-static void
-free_bin_tree (tree)
- bin_tree_t *tree;
-{
- if (tree == NULL)
- return;
- /*re_node_set_free (&tree->eclosure);*/
- free_bin_tree (tree->left);
- free_bin_tree (tree->right);
- re_free (tree);
-}
-
-/* Duplicate the node SRC, and return new node. */
-
-static bin_tree_t *
-duplicate_tree (src, dfa)
- const bin_tree_t *src;
- re_dfa_t *dfa;
-{
- bin_tree_t *left = NULL, *right = NULL, *new_tree;
- int new_node_idx;
- /* Since node indies must be according to Post-order of the tree,
- we must duplicate the left at first. */
- if (src->left != NULL)
- {
- left = duplicate_tree (src->left, dfa);
- if (left == NULL)
- return NULL;
- }
-
- /* Secondaly, duplicate the right. */
- if (src->right != NULL)
- {
- right = duplicate_tree (src->right, dfa);
- if (right == NULL)
- {
- free_bin_tree (left);
- return NULL;
- }
- }
-
- /* At last, duplicate itself. */
- if (src->type == NON_TYPE)
- {
- new_node_idx = re_dfa_add_node (dfa, dfa->nodes[src->node_idx], 0);
- dfa->nodes[new_node_idx].duplicated = 1;
- if (BE (new_node_idx == -1, 0))
- {
- free_bin_tree (left);
- free_bin_tree (right);
- return NULL;
- }
- }
- else
- new_node_idx = src->type;
-
- new_tree = create_tree (left, right, src->type, new_node_idx);
- if (BE (new_tree == NULL, 0))
- {
- free_bin_tree (left);
- free_bin_tree (right);
- }
- return new_tree;
-}
diff --git a/util/regex.c b/util/regex.c
deleted file mode 100644
index 34d412002..000000000
--- a/util/regex.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* Extended regular expression matching and search library.
- Copyright (C) 2002 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Isamu Hasegawa <[email protected]>.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02110-1301 USA. */
-
-#ifdef _LIBC
-/* We have to keep the namespace clean. */
-# define regfree(preg) __regfree (preg)
-# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
-# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
-# define regerror(errcode, preg, errbuf, errbuf_size) \
- __regerror(errcode, preg, errbuf, errbuf_size)
-# define re_set_registers(bu, re, nu, st, en) \
- __re_set_registers (bu, re, nu, st, en)
-# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
- __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
-# define re_match(bufp, string, size, pos, regs) \
- __re_match (bufp, string, size, pos, regs)
-# define re_search(bufp, string, size, startpos, range, regs) \
- __re_search (bufp, string, size, startpos, range, regs)
-# define re_compile_pattern(pattern, length, bufp) \
- __re_compile_pattern (pattern, length, bufp)
-# define re_set_syntax(syntax) __re_set_syntax (syntax)
-# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
- __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)
-# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
-#endif
-
-#if _LIBC || __GNUC__ >= 3
-# define BE(expr, val) __builtin_expect (expr, val)
-#else
-# define BE(expr, val) (expr)
-# define inline
-#endif
-
-#include "regcomp.c"
-#include "regexec.c"
-#include "regex_internal.c"
-
-/* Binary backward compatibility. */
-#if _LIBC
-# include <shlib-compat.h>
-# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3)
-link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.")
-int re_max_failures = 2000;
-# endif
-#endif
diff --git a/util/regex_internal.c b/util/regex_internal.c
deleted file mode 100644
index 0f8b897b1..000000000
--- a/util/regex_internal.c
+++ /dev/null
@@ -1,1229 +0,0 @@
-/* Extended regular expression matching and search library.
- Copyright (C) 2002 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Isamu Hasegawa <[email protected]>.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02110-1301 USA. */
-
-#include <assert.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if defined HAVE_WCHAR_H || defined _LIBC
-# include <wchar.h>
-#endif /* HAVE_WCHAR_H || _LIBC */
-#if defined HAVE_WCTYPE_H || defined _LIBC
-# include <wctype.h>
-#endif /* HAVE_WCTYPE_H || _LIBC */
-
-#ifdef _LIBC
-# ifndef _RE_DEFINE_LOCALE_FUNCTIONS
-# define _RE_DEFINE_LOCALE_FUNCTIONS 1
-# include <locale/localeinfo.h>
-# include <locale/elem-hash.h>
-# include <locale/coll-lookup.h>
-# endif
-#endif
-
-/* This is for other GNU distributions with internationalized messages. */
-#if HAVE_LIBINTL_H || defined _LIBC
-# include <libintl.h>
-# ifdef _LIBC
-# undef gettext
-# define gettext(msgid) \
- INTUSE(__dcgettext) (_libc_intl_domainname_internal, msgid, LC_MESSAGES)
-# endif
-#else
-# define gettext(msgid) (msgid)
-#endif
-
-#ifndef gettext_noop
-/* This define is so xgettext can find the internationalizable
- strings. */
-# define gettext_noop(String) String
-#endif
-
-#include "_regex.h" /* gnupg */
-#include "regex_internal.h"
-
-static void re_string_construct_common (const char *str, int len,
- re_string_t *pstr,
- RE_TRANSLATE_TYPE trans, int icase);
-#ifdef RE_ENABLE_I18N
-static int re_string_skip_chars (re_string_t *pstr, int new_raw_idx);
-#endif /* RE_ENABLE_I18N */
-static re_dfastate_t *create_newstate_common (re_dfa_t *dfa,
- const re_node_set *nodes,
- unsigned int hash);
-static reg_errcode_t register_state (re_dfa_t *dfa, re_dfastate_t *newstate,
- unsigned int hash);
-static re_dfastate_t *create_ci_newstate (re_dfa_t *dfa,
- const re_node_set *nodes,
- unsigned int hash);
-static re_dfastate_t *create_cd_newstate (re_dfa_t *dfa,
- const re_node_set *nodes,
- unsigned int context,
- unsigned int hash);
-static unsigned int inline calc_state_hash (const re_node_set *nodes,
- unsigned int context);
-
-/* Functions for string operation. */
-
-/* This function allocate the buffers. It is necessary to call
- re_string_reconstruct before using the object. */
-
-static reg_errcode_t
-re_string_allocate (pstr, str, len, init_len, trans, icase)
- re_string_t *pstr;
- const char *str;
- int len, init_len, icase;
- RE_TRANSLATE_TYPE trans;
-{
- reg_errcode_t ret;
- int init_buf_len = (len + 1 < init_len) ? len + 1: init_len;
- re_string_construct_common (str, len, pstr, trans, icase);
- pstr->stop = pstr->len;
-
- ret = re_string_realloc_buffers (pstr, init_buf_len);
- if (BE (ret != REG_NOERROR, 0))
- return ret;
-
- pstr->mbs_case = (MBS_CASE_ALLOCATED (pstr) ? pstr->mbs_case
- : (unsigned char *) str);
- pstr->mbs = MBS_ALLOCATED (pstr) ? pstr->mbs : pstr->mbs_case;
- pstr->valid_len = (MBS_CASE_ALLOCATED (pstr) || MBS_ALLOCATED (pstr)
- || MB_CUR_MAX > 1) ? pstr->valid_len : len;
- return REG_NOERROR;
-}
-
-/* This function allocate the buffers, and initialize them. */
-
-static reg_errcode_t
-re_string_construct (pstr, str, len, trans, icase)
- re_string_t *pstr;
- const char *str;
- int len, icase;
- RE_TRANSLATE_TYPE trans;
-{
- reg_errcode_t ret;
- re_string_construct_common (str, len, pstr, trans, icase);
- pstr->stop = pstr->len;
- /* Set 0 so that this function can initialize whole buffers. */
- pstr->valid_len = 0;
-
- if (len > 0)
- {
- ret = re_string_realloc_buffers (pstr, len + 1);
- if (BE (ret != REG_NOERROR, 0))
- return ret;
- }
- pstr->mbs_case = (MBS_CASE_ALLOCATED (pstr) ? pstr->mbs_case
- : (unsigned char *) str);
- pstr->mbs = MBS_ALLOCATED (pstr) ? pstr->mbs : pstr->mbs_case;
-
- if (icase)
- {
-#ifdef RE_ENABLE_I18N
- if (MB_CUR_MAX > 1)
- build_wcs_upper_buffer (pstr);
- else
-#endif /* RE_ENABLE_I18N */
- build_upper_buffer (pstr);
- }
- else
- {
-#ifdef RE_ENABLE_I18N
- if (MB_CUR_MAX > 1)
- build_wcs_buffer (pstr);
- else
-#endif /* RE_ENABLE_I18N */
- {
- if (trans != NULL)
- re_string_translate_buffer (pstr);
- else
- pstr->valid_len = len;
- }
- }
-
- /* Initialized whole buffers, then valid_len == bufs_len. */
- pstr->valid_len = pstr->bufs_len;
- return REG_NOERROR;
-}
-
-/* Helper functions for re_string_allocate, and re_string_construct. */
-
-static reg_errcode_t
-re_string_realloc_buffers (pstr, new_buf_len)
- re_string_t *pstr;
- int new_buf_len;
-{
-#ifdef RE_ENABLE_I18N
- if (MB_CUR_MAX > 1)
- {
- pstr->wcs = re_realloc (pstr->wcs, wint_t, new_buf_len);
- if (BE (pstr->wcs == NULL, 0))
- return REG_ESPACE;
- }
-#endif /* RE_ENABLE_I18N */
- if (MBS_ALLOCATED (pstr))
- {
- pstr->mbs = re_realloc (pstr->mbs, unsigned char, new_buf_len);
- if (BE (pstr->mbs == NULL, 0))
- return REG_ESPACE;
- }
- if (MBS_CASE_ALLOCATED (pstr))
- {
- pstr->mbs_case = re_realloc (pstr->mbs_case, unsigned char, new_buf_len);
- if (BE (pstr->mbs_case == NULL, 0))
- return REG_ESPACE;
- if (!MBS_ALLOCATED (pstr))
- pstr->mbs = pstr->mbs_case;
- }
- pstr->bufs_len = new_buf_len;
- return REG_NOERROR;
-}
-
-
-static void
-re_string_construct_common (str, len, pstr, trans, icase)
- const char *str;
- int len;
- re_string_t *pstr;
- RE_TRANSLATE_TYPE trans;
- int icase;
-{
- memset (pstr, '\0', sizeof (re_string_t));
- pstr->raw_mbs = (const unsigned char *) str;
- pstr->len = len;
- pstr->trans = trans;
- pstr->icase = icase ? 1 : 0;
-}
-
-#ifdef RE_ENABLE_I18N
-
-/* Build wide character buffer PSTR->WCS.
- If the byte sequence of the string are:
- <mb1>(0), <mb1>(1), <mb2>(0), <mb2>(1), <sb3>
- Then wide character buffer will be:
- <wc1> , WEOF , <wc2> , WEOF , <wc3>
- We use WEOF for padding, they indicate that the position isn't
- a first byte of a multibyte character.
-
- Note that this function assumes PSTR->VALID_LEN elements are already
- built and starts from PSTR->VALID_LEN. */
-
-static void
-build_wcs_buffer (pstr)
- re_string_t *pstr;
-{
- mbstate_t prev_st;
- int byte_idx, end_idx, mbclen, remain_len;
- /* Build the buffers from pstr->valid_len to either pstr->len or
- pstr->bufs_len. */
- end_idx = (pstr->bufs_len > pstr->len)? pstr->len : pstr->bufs_len;
- for (byte_idx = pstr->valid_len; byte_idx < end_idx;)
- {
- wchar_t wc;
- remain_len = end_idx - byte_idx;
- prev_st = pstr->cur_state;
- mbclen = mbrtowc (&wc, ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx
- + byte_idx), remain_len, &pstr->cur_state);
- if (BE (mbclen == (size_t) -2, 0))
- {
- /* The buffer doesn't have enough space, finish to build. */
- pstr->cur_state = prev_st;
- break;
- }
- else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0))
- {
- /* We treat these cases as a singlebyte character. */
- mbclen = 1;
- wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
- pstr->cur_state = prev_st;
- }
-
- /* Apply the translateion if we need. */
- if (pstr->trans != NULL && mbclen == 1)
- {
- int ch = pstr->trans[pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]];
- pstr->mbs_case[byte_idx] = ch;
- }
- /* Write wide character and padding. */
- pstr->wcs[byte_idx++] = wc;
- /* Write paddings. */
- for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
- pstr->wcs[byte_idx++] = WEOF;
- }
- pstr->valid_len = byte_idx;
-}
-
-/* Build wide character buffer PSTR->WCS like build_wcs_buffer,
- but for REG_ICASE. */
-
-static void
-build_wcs_upper_buffer (pstr)
- re_string_t *pstr;
-{
- mbstate_t prev_st;
- int byte_idx, end_idx, mbclen, remain_len;
- /* Build the buffers from pstr->valid_len to either pstr->len or
- pstr->bufs_len. */
- end_idx = (pstr->bufs_len > pstr->len)? pstr->len : pstr->bufs_len;
- for (byte_idx = pstr->valid_len; byte_idx < end_idx;)
- {
- wchar_t wc;
- remain_len = end_idx - byte_idx;
- prev_st = pstr->cur_state;
- mbclen = mbrtowc (&wc, ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx
- + byte_idx), remain_len, &pstr->cur_state);
- if (BE (mbclen == (size_t) -2, 0))
- {
- /* The buffer doesn't have enough space, finish to build. */
- pstr->cur_state = prev_st;
- break;
- }
- else if (mbclen == 1 || mbclen == (size_t) -1 || mbclen == 0)
- {
- /* In case of a singlebyte character. */
- int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
- /* Apply the translateion if we need. */
- if (pstr->trans != NULL && mbclen == 1)
- {
- ch = pstr->trans[ch];
- pstr->mbs_case[byte_idx] = ch;
- }
- pstr->wcs[byte_idx] = iswlower (wc) ? toupper (wc) : wc;
- pstr->mbs[byte_idx++] = islower (ch) ? toupper (ch) : ch;
- if (BE (mbclen == (size_t) -1, 0))
- pstr->cur_state = prev_st;
- }
- else /* mbclen > 1 */
- {
- if (iswlower (wc))
- wcrtomb ((char *) pstr->mbs + byte_idx, towupper (wc), &prev_st);
- else
- memcpy (pstr->mbs + byte_idx,
- pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen);
- pstr->wcs[byte_idx++] = iswlower (wc) ? toupper (wc) : wc;
- /* Write paddings. */
- for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
- pstr->wcs[byte_idx++] = WEOF;
- }
- }
- pstr->valid_len = byte_idx;
-}
-
-/* Skip characters until the index becomes greater than NEW_RAW_IDX.
- Return the index. */
-
-static int
-re_string_skip_chars (pstr, new_raw_idx)
- re_string_t *pstr;
- int new_raw_idx;
-{
- mbstate_t prev_st;
- int rawbuf_idx, mbclen;
-
- /* Skip the characters which are not necessary to check. */
- for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_len;
- rawbuf_idx < new_raw_idx;)
- {
- int remain_len = pstr->len - rawbuf_idx;
- prev_st = pstr->cur_state;
- mbclen = mbrlen ((const char *) pstr->raw_mbs + rawbuf_idx, remain_len,
- &pstr->cur_state);
- if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0))
- {
- /* We treat these cases as a singlebyte character. */
- mbclen = 1;
- pstr->cur_state = prev_st;
- }
- /* Then proceed the next character. */
- rawbuf_idx += mbclen;
- }
- return rawbuf_idx;
-}
-#endif /* RE_ENABLE_I18N */
-
-/* Build the buffer PSTR->MBS, and apply the translation if we need.
- This function is used in case of REG_ICASE. */
-
-static void
-build_upper_buffer (pstr)
- re_string_t *pstr;
-{
- int char_idx, end_idx;
- end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
-
- for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx)
- {
- int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx];
- if (pstr->trans != NULL)
- {
- ch = pstr->trans[ch];
- pstr->mbs_case[char_idx] = ch;
- }
- if (islower (ch))
- pstr->mbs[char_idx] = toupper (ch);
- else
- pstr->mbs[char_idx] = ch;
- }
- pstr->valid_len = char_idx;
-}
-
-/* Apply TRANS to the buffer in PSTR. */
-
-static void
-re_string_translate_buffer (pstr)
- re_string_t *pstr;
-{
- int buf_idx, end_idx;
- end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
-
- for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx)
- {
- int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx];
- pstr->mbs_case[buf_idx] = pstr->trans[ch];
- }
-
- pstr->valid_len = buf_idx;
-}
-
-/* This function re-construct the buffers.
- Concretely, convert to wide character in case of MB_CUR_MAX > 1,
- convert to upper case in case of REG_ICASE, apply translation. */
-
-static reg_errcode_t
-re_string_reconstruct (pstr, idx, eflags, newline)
- re_string_t *pstr;
- int idx, eflags, newline;
-{
- int offset = idx - pstr->raw_mbs_idx;
- if (offset < 0)
- {
- /* Reset buffer. */
-#ifdef RE_ENABLE_I18N
- if (MB_CUR_MAX > 1)
- memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
-#endif /* RE_ENABLE_I18N */
- pstr->len += pstr->raw_mbs_idx;
- pstr->stop += pstr->raw_mbs_idx;
- pstr->valid_len = pstr->raw_mbs_idx = 0;
- pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
- : CONTEXT_NEWLINE | CONTEXT_BEGBUF);
- if (!MBS_CASE_ALLOCATED (pstr))
- pstr->mbs_case = (unsigned char *) pstr->raw_mbs;
- if (!MBS_ALLOCATED (pstr) && !MBS_CASE_ALLOCATED (pstr))
- pstr->mbs = (unsigned char *) pstr->raw_mbs;
- offset = idx;
- }
-
- if (offset != 0)
- {
- pstr->tip_context = re_string_context_at (pstr, offset - 1, eflags,
- newline);
- /* Are the characters which are already checked remain? */
- if (offset < pstr->valid_len)
- {
- /* Yes, move them to the front of the buffer. */
-#ifdef RE_ENABLE_I18N
- if (MB_CUR_MAX > 1)
- memmove (pstr->wcs, pstr->wcs + offset,
- (pstr->valid_len - offset) * sizeof (wint_t));
-#endif /* RE_ENABLE_I18N */
- if (MBS_ALLOCATED (pstr))
- memmove (pstr->mbs, pstr->mbs + offset,
- pstr->valid_len - offset);
- if (MBS_CASE_ALLOCATED (pstr))
- memmove (pstr->mbs_case, pstr->mbs_case + offset,
- pstr->valid_len - offset);
- pstr->valid_len -= offset;
-#if DEBUG
- assert (pstr->valid_len > 0);
-#endif
- }
- else
- {
- /* No, skip all characters until IDX. */
- pstr->valid_len = 0;
-#ifdef RE_ENABLE_I18N
- if (MB_CUR_MAX > 1)
- {
- int wcs_idx;
- pstr->valid_len = re_string_skip_chars (pstr, idx) - idx;
- for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx)
- pstr->wcs[wcs_idx] = WEOF;
- }
-#endif /* RE_ENABLE_I18N */
- }
- if (!MBS_CASE_ALLOCATED (pstr))
- {
- pstr->mbs_case += offset;
- /* In case of !MBS_ALLOCATED && !MBS_CASE_ALLOCATED. */
- if (!MBS_ALLOCATED (pstr))
- pstr->mbs += offset;
- }
- }
- pstr->raw_mbs_idx = idx;
- pstr->len -= offset;
- pstr->stop -= offset;
-
- /* Then build the buffers. */
-#ifdef RE_ENABLE_I18N
- if (MB_CUR_MAX > 1)
- {
- if (pstr->icase)
- build_wcs_upper_buffer (pstr);
- else
- build_wcs_buffer (pstr);
- }
- else
-#endif /* RE_ENABLE_I18N */
- {
- if (pstr->icase)
- build_upper_buffer (pstr);
- else if (pstr->trans != NULL)
- re_string_translate_buffer (pstr);
- }
- pstr->cur_idx = 0;
-
- return REG_NOERROR;
-}
-
-static void
-re_string_destruct (pstr)
- re_string_t *pstr;
-{
-#ifdef RE_ENABLE_I18N
- re_free (pstr->wcs);
-#endif /* RE_ENABLE_I18N */
- if (MBS_ALLOCATED (pstr))
- re_free (pstr->mbs);
- if (MBS_CASE_ALLOCATED (pstr))
- re_free (pstr->mbs_case);
-}
-
-/* Return the context at IDX in INPUT. */
-
-static unsigned int
-re_string_context_at (input, idx, eflags, newline_anchor)
- const re_string_t *input;
- int idx, eflags, newline_anchor;
-{
- int c;
- if (idx < 0 || idx == input->len)
- {
- if (idx < 0)
- /* In this case, we use the value stored in input->tip_context,
- since we can't know the character in input->mbs[-1] here. */
- return input->tip_context;
- else /* (idx == input->len) */
- return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF
- : CONTEXT_NEWLINE | CONTEXT_ENDBUF);
- }
- c = re_string_byte_at (input, idx);
- if (IS_WORD_CHAR (c))
- return CONTEXT_WORD;
- return (newline_anchor && IS_NEWLINE (c)) ? CONTEXT_NEWLINE : 0;
-}
-
-/* Functions for set operation. */
-
-static reg_errcode_t
-re_node_set_alloc (set, size)
- re_node_set *set;
- int size;
-{
- set->alloc = size;
- set->nelem = 0;
- set->elems = re_malloc (int, size);
- if (BE (set->elems == NULL, 0))
- return REG_ESPACE;
- return REG_NOERROR;
-}
-
-static reg_errcode_t
-re_node_set_init_1 (set, elem)
- re_node_set *set;
- int elem;
-{
- set->alloc = 1;
- set->nelem = 1;
- set->elems = re_malloc (int, 1);
- if (BE (set->elems == NULL, 0))
- return REG_ESPACE;
- set->elems[0] = elem;
- return REG_NOERROR;
-}
-
-static reg_errcode_t
-re_node_set_init_2 (set, elem1, elem2)
- re_node_set *set;
- int elem1, elem2;
-{
- set->alloc = 2;
- set->elems = re_malloc (int, 2);
- if (BE (set->elems == NULL, 0))
- return REG_ESPACE;
- if (elem1 == elem2)
- {
- set->nelem = 1;
- set->elems[0] = elem1;
- }
- else
- {
- set->nelem = 2;
- if (elem1 < elem2)
- {
- set->elems[0] = elem1;
- set->elems[1] = elem2;
- }
- else
- {
- set->elems[0] = elem2;
- set->elems[1] = elem1;
- }
- }
- return REG_NOERROR;
-}
-
-static reg_errcode_t
-re_node_set_init_copy (dest, src)
- re_node_set *dest;
- const re_node_set *src;
-{
- dest->nelem = src->nelem;
- if (src->nelem > 0)
- {
- dest->alloc = dest->nelem;
- dest->elems = re_malloc (int, dest->alloc);
- if (BE (dest->elems == NULL, 0))
- return REG_ESPACE;
- memcpy (dest->elems, src->elems, src->nelem * sizeof (int));
- }
- else
- re_node_set_init_empty (dest);
- return REG_NOERROR;
-}
-
-/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to
- DEST. Return value indicate the error code or REG_NOERROR if succeeded.
- Note: We assume dest->elems is NULL, when dest->alloc is 0. */
-
-static reg_errcode_t
-re_node_set_add_intersect (dest, src1, src2)
- re_node_set *dest;
- const re_node_set *src1, *src2;
-{
- int i1, i2, id;
- if (src1->nelem > 0 && src2->nelem > 0)
- {
- if (src1->nelem + src2->nelem + dest->nelem > dest->alloc)
- {
- dest->alloc = src1->nelem + src2->nelem + dest->nelem;
- dest->elems = re_realloc (dest->elems, int, dest->alloc);
- if (BE (dest->elems == NULL, 0))
- return REG_ESPACE;
- }
- }
- else
- return REG_NOERROR;
-
- for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;)
- {
- if (src1->elems[i1] > src2->elems[i2])
- {
- ++i2;
- continue;
- }
- if (src1->elems[i1] == src2->elems[i2])
- {
- while (id < dest->nelem && dest->elems[id] < src2->elems[i2])
- ++id;
- if (id < dest->nelem && dest->elems[id] == src2->elems[i2])
- ++id;
- else
- {
- memmove (dest->elems + id + 1, dest->elems + id,
- sizeof (int) * (dest->nelem - id));
- dest->elems[id++] = src2->elems[i2++];
- ++dest->nelem;
- }
- }
- ++i1;
- }
- return REG_NOERROR;
-}
-
-/* Calculate the union set of the sets SRC1 and SRC2. And store it to
- DEST. Return value indicate the error code or REG_NOERROR if succeeded. */
-
-static reg_errcode_t
-re_node_set_init_union (dest, src1, src2)
- re_node_set *dest;
- const re_node_set *src1, *src2;
-{
- int i1, i2, id;
- if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0)
- {
- dest->alloc = src1->nelem + src2->nelem;
- dest->elems = re_malloc (int, dest->alloc);
- if (BE (dest->elems == NULL, 0))
- return REG_ESPACE;
- }
- else
- {
- if (src1 != NULL && src1->nelem > 0)
- return re_node_set_init_copy (dest, src1);
- else if (src2 != NULL && src2->nelem > 0)
- return re_node_set_init_copy (dest, src2);
- else
- re_node_set_init_empty (dest);
- return REG_NOERROR;
- }
- for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;)
- {
- if (src1->elems[i1] > src2->elems[i2])
- {
- dest->elems[id++] = src2->elems[i2++];
- continue;
- }
- if (src1->elems[i1] == src2->elems[i2])
- ++i2;
- dest->elems[id++] = src1->elems[i1++];
- }
- if (i1 < src1->nelem)
- {
- memcpy (dest->elems + id, src1->elems + i1,
- (src1->nelem - i1) * sizeof (int));
- id += src1->nelem - i1;
- }
- else if (i2 < src2->nelem)
- {
- memcpy (dest->elems + id, src2->elems + i2,
- (src2->nelem - i2) * sizeof (int));
- id += src2->nelem - i2;
- }
- dest->nelem = id;
- return REG_NOERROR;
-}
-
-/* Calculate the union set of the sets DEST and SRC. And store it to
- DEST. Return value indicate the error code or REG_NOERROR if succeeded. */
-
-static reg_errcode_t
-re_node_set_merge (dest, src)
- re_node_set *dest;
- const re_node_set *src;
-{
- int si, di;
- if (src == NULL || src->nelem == 0)
- return REG_NOERROR;
- if (dest->alloc < src->nelem + dest->nelem)
- {
- dest->alloc = 2 * (src->nelem + dest->alloc);
- dest->elems = re_realloc (dest->elems, int, dest->alloc);
- if (BE (dest->elems == NULL, 0))
- return REG_ESPACE;
- }
-
- for (si = 0, di = 0 ; si < src->nelem && di < dest->nelem ;)
- {
- int cp_from, ncp, mid, right, src_elem = src->elems[si];
- /* Binary search the spot we will add the new element. */
- right = dest->nelem;
- while (di < right)
- {
- mid = (di + right) / 2;
- if (dest->elems[mid] < src_elem)
- di = mid + 1;
- else
- right = mid;
- }
- if (di >= dest->nelem)
- break;
-
- if (dest->elems[di] == src_elem)
- {
- /* Skip since, DEST already has the element. */
- ++di;
- ++si;
- continue;
- }
-
- /* Skip the src elements which are less than dest->elems[di]. */
- cp_from = si;
- while (si < src->nelem && src->elems[si] < dest->elems[di])
- ++si;
- /* Copy these src elements. */
- ncp = si - cp_from;
- memmove (dest->elems + di + ncp, dest->elems + di,
- sizeof (int) * (dest->nelem - di));
- memcpy (dest->elems + di, src->elems + cp_from,
- sizeof (int) * ncp);
- /* Update counters. */
- di += ncp;
- dest->nelem += ncp;
- }
-
- /* Copy remaining src elements. */
- if (si < src->nelem)
- {
- memcpy (dest->elems + di, src->elems + si,
- sizeof (int) * (src->nelem - si));
- dest->nelem += src->nelem - si;
- }
- return REG_NOERROR;
-}
-
-/* Insert the new element ELEM to the re_node_set* SET.
- return 0 if SET already has ELEM,
- return -1 if an error is occured, return 1 otherwise. */
-
-static int
-re_node_set_insert (set, elem)
- re_node_set *set;
- int elem;
-{
- int idx, right, mid;
- /* In case of the set is empty. */
- if (set->elems == NULL || set->alloc == 0)
- {
- if (BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1))
- return 1;
- else
- return -1;
- }
-
- /* Binary search the spot we will add the new element. */
- idx = 0;
- right = set->nelem;
- while (idx < right)
- {
- mid = (idx + right) / 2;
- if (set->elems[mid] < elem)
- idx = mid + 1;
- else
- right = mid;
- }
-
- /* Realloc if we need. */
- if (set->alloc < set->nelem + 1)
- {
- int *new_array;
- set->alloc = set->alloc * 2;
- new_array = re_malloc (int, set->alloc);
- if (BE (new_array == NULL, 0))
- return -1;
- /* Copy the elements they are followed by the new element. */
- if (idx > 0)
- memcpy (new_array, set->elems, sizeof (int) * (idx));
- /* Copy the elements which follows the new element. */
- if (set->nelem - idx > 0)
- memcpy (new_array + idx + 1, set->elems + idx,
- sizeof (int) * (set->nelem - idx));
- re_free (set->elems);
- set->elems = new_array;
- }
- else
- {
- /* Move the elements which follows the new element. */
- if (set->nelem - idx > 0)
- memmove (set->elems + idx + 1, set->elems + idx,
- sizeof (int) * (set->nelem - idx));
- }
- /* Insert the new element. */
- set->elems[idx] = elem;
- ++set->nelem;
- return 1;
-}
-
-/* Compare two node sets SET1 and SET2.
- return 1 if SET1 and SET2 are equivalent, retrun 0 otherwise. */
-
-static int
-re_node_set_compare (set1, set2)
- const re_node_set *set1, *set2;
-{
- int i;
- if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem)
- return 0;
- for (i = 0 ; i < set1->nelem ; i++)
- if (set1->elems[i] != set2->elems[i])
- return 0;
- return 1;
-}
-
-/* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */
-
-static int
-re_node_set_contains (set, elem)
- const re_node_set *set;
- int elem;
-{
- int idx, right, mid;
- if (set->nelem <= 0)
- return 0;
-
- /* Binary search the element. */
- idx = 0;
- right = set->nelem - 1;
- while (idx < right)
- {
- mid = (idx + right) / 2;
- if (set->elems[mid] < elem)
- idx = mid + 1;
- else
- right = mid;
- }
- return set->elems[idx] == elem ? idx + 1 : 0;
-}
-
-static void
-re_node_set_remove_at (set, idx)
- re_node_set *set;
- int idx;
-{
- if (idx < 0 || idx >= set->nelem)
- return;
- if (idx < set->nelem - 1)
- memmove (set->elems + idx, set->elems + idx + 1,
- sizeof (int) * (set->nelem - idx - 1));
- --set->nelem;
-}
-
-
-/* Add the token TOKEN to dfa->nodes, and return the index of the token.
- Or return -1, if an error will be occured. */
-
-static int
-re_dfa_add_node (dfa, token, mode)
- re_dfa_t *dfa;
- re_token_t token;
- int mode;
-{
- if (dfa->nodes_len >= dfa->nodes_alloc)
- {
- re_token_t *new_array;
- dfa->nodes_alloc *= 2;
- new_array = re_realloc (dfa->nodes, re_token_t, dfa->nodes_alloc);
- if (BE (new_array == NULL, 0))
- return -1;
- else
- dfa->nodes = new_array;
- if (mode)
- {
- int *new_firsts, *new_nexts;
- re_node_set *new_edests, *new_eclosures, *new_inveclosures;
-
- new_firsts = re_realloc (dfa->firsts, int, dfa->nodes_alloc);
- new_nexts = re_realloc (dfa->nexts, int, dfa->nodes_alloc);
- new_edests = re_realloc (dfa->edests, re_node_set, dfa->nodes_alloc);
- new_eclosures = re_realloc (dfa->eclosures, re_node_set,
- dfa->nodes_alloc);
- new_inveclosures = re_realloc (dfa->inveclosures, re_node_set,
- dfa->nodes_alloc);
- if (BE (new_firsts == NULL || new_nexts == NULL || new_edests == NULL
- || new_eclosures == NULL || new_inveclosures == NULL, 0))
- return -1;
- dfa->firsts = new_firsts;
- dfa->nexts = new_nexts;
- dfa->edests = new_edests;
- dfa->eclosures = new_eclosures;
- dfa->inveclosures = new_inveclosures;
- }
- }
- dfa->nodes[dfa->nodes_len] = token;
- dfa->nodes[dfa->nodes_len].duplicated = 0;
- return dfa->nodes_len++;
-}
-
-static unsigned int inline
-calc_state_hash (nodes, context)
- const re_node_set *nodes;
- unsigned int context;
-{
- unsigned int hash = nodes->nelem + context;
- int i;
- for (i = 0 ; i < nodes->nelem ; i++)
- hash += nodes->elems[i];
- return hash;
-}
-
-/* Search for the state whose node_set is equivalent to NODES.
- Return the pointer to the state, if we found it in the DFA.
- Otherwise create the new one and return it. In case of an error
- return NULL and set the error code in ERR.
- Note: - We assume NULL as the invalid state, then it is possible that
- return value is NULL and ERR is REG_NOERROR.
- - We never return non-NULL value in case of any errors, it is for
- optimization. */
-
-static re_dfastate_t*
-re_acquire_state (err, dfa, nodes)
- reg_errcode_t *err;
- re_dfa_t *dfa;
- const re_node_set *nodes;
-{
- unsigned int hash;
- re_dfastate_t *new_state;
- struct re_state_table_entry *spot;
- int i;
- if (BE (nodes->nelem == 0, 0))
- {
- *err = REG_NOERROR;
- return NULL;
- }
- hash = calc_state_hash (nodes, 0);
- spot = dfa->state_table + (hash & dfa->state_hash_mask);
-
- for (i = 0 ; i < spot->num ; i++)
- {
- re_dfastate_t *state = spot->array[i];
- if (hash != state->hash)
- continue;
- if (re_node_set_compare (&state->nodes, nodes))
- return state;
- }
-
- /* There are no appropriate state in the dfa, create the new one. */
- new_state = create_ci_newstate (dfa, nodes, hash);
- if (BE (new_state != NULL, 1))
- return new_state;
- else
- {
- *err = REG_ESPACE;
- return NULL;
- }
-}
-
-/* Search for the state whose node_set is equivalent to NODES and
- whose context is equivalent to CONTEXT.
- Return the pointer to the state, if we found it in the DFA.
- Otherwise create the new one and return it. In case of an error
- return NULL and set the error code in ERR.
- Note: - We assume NULL as the invalid state, then it is possible that
- return value is NULL and ERR is REG_NOERROR.
- - We never return non-NULL value in case of any errors, it is for
- optimization. */
-
-static re_dfastate_t*
-re_acquire_state_context (err, dfa, nodes, context)
- reg_errcode_t *err;
- re_dfa_t *dfa;
- const re_node_set *nodes;
- unsigned int context;
-{
- unsigned int hash;
- re_dfastate_t *new_state;
- struct re_state_table_entry *spot;
- int i;
- if (nodes->nelem == 0)
- {
- *err = REG_NOERROR;
- return NULL;
- }
- hash = calc_state_hash (nodes, context);
- spot = dfa->state_table + (hash & dfa->state_hash_mask);
-
- for (i = 0 ; i < spot->num ; i++)
- {
- re_dfastate_t *state = spot->array[i];
- if (hash != state->hash)
- continue;
- if (re_node_set_compare (state->entrance_nodes, nodes)
- && state->context == context)
- return state;
- }
- /* There are no appropriate state in `dfa', create the new one. */
- new_state = create_cd_newstate (dfa, nodes, context, hash);
- if (BE (new_state != NULL, 1))
- return new_state;
- else
- {
- *err = REG_ESPACE;
- return NULL;
- }
-}
-
-/* Allocate memory for DFA state and initialize common properties.
- Return the new state if succeeded, otherwise return NULL. */
-
-static re_dfastate_t *
-create_newstate_common (dfa, nodes, hash)
- re_dfa_t *dfa;
- const re_node_set *nodes;
- unsigned int hash;
-{
- re_dfastate_t *newstate;
- newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
- if (BE (newstate == NULL, 0))
- return NULL;
- re_node_set_init_copy (&newstate->nodes, nodes);
- newstate->trtable = NULL;
- newstate->trtable_search = NULL;
- newstate->hash = hash;
- return newstate;
-}
-
-/* Store the new state NEWSTATE whose hash value is HASH in appropriate
- position. Return value indicate the error code if failed. */
-
-static reg_errcode_t
-register_state (dfa, newstate, hash)
- re_dfa_t *dfa;
- re_dfastate_t *newstate;
- unsigned int hash;
-{
- struct re_state_table_entry *spot;
- spot = dfa->state_table + (hash & dfa->state_hash_mask);
-
- if (spot->alloc <= spot->num)
- {
- spot->alloc = 2 * spot->num + 2;
- spot->array = re_realloc (spot->array, re_dfastate_t *, spot->alloc);
- if (BE (spot->array == NULL, 0))
- return REG_ESPACE;
- }
- spot->array[spot->num++] = newstate;
- return REG_NOERROR;
-}
-
-/* Create the new state which is independ of contexts.
- Return the new state if succeeded, otherwise return NULL. */
-
-static re_dfastate_t *
-create_ci_newstate (dfa, nodes, hash)
- re_dfa_t *dfa;
- const re_node_set *nodes;
- unsigned int hash;
-{
- int i;
- reg_errcode_t err;
- re_dfastate_t *newstate;
- newstate = create_newstate_common (dfa, nodes, hash);
- if (BE (newstate == NULL, 0))
- return NULL;
- newstate->entrance_nodes = &newstate->nodes;
-
- for (i = 0 ; i < nodes->nelem ; i++)
- {
- re_token_t *node = dfa->nodes + nodes->elems[i];
- re_token_type_t type = node->type;
- if (type == CHARACTER)
- continue;
-
- /* If the state has the halt node, the state is a halt state. */
- else if (type == END_OF_RE)
- newstate->halt = 1;
-#ifdef RE_ENABLE_I18N
- else if (type == COMPLEX_BRACKET
- || (type == OP_PERIOD && MB_CUR_MAX > 1))
- newstate->accept_mb = 1;
-#endif /* RE_ENABLE_I18N */
- else if (type == OP_BACK_REF)
- newstate->has_backref = 1;
- else if (type == ANCHOR || OP_CONTEXT_NODE)
- {
- newstate->has_constraint = 1;
- if (type == OP_CONTEXT_NODE
- && dfa->nodes[node->opr.ctx_info->entity].type == END_OF_RE)
- newstate->halt = 1;
- }
- }
- err = register_state (dfa, newstate, hash);
- return (err != REG_NOERROR) ? NULL : newstate;
-}
-
-/* Create the new state which is depend on the context CONTEXT.
- Return the new state if succeeded, otherwise return NULL. */
-
-static re_dfastate_t *
-create_cd_newstate (dfa, nodes, context, hash)
- re_dfa_t *dfa;
- const re_node_set *nodes;
- unsigned int context, hash;
-{
- int i, nctx_nodes = 0;
- reg_errcode_t err;
- re_dfastate_t *newstate;
-
- newstate = create_newstate_common (dfa, nodes, hash);
- if (BE (newstate == NULL, 0))
- return NULL;
- newstate->context = context;
- newstate->entrance_nodes = &newstate->nodes;
-
- for (i = 0 ; i < nodes->nelem ; i++)
- {
- unsigned int constraint = 0;
- re_token_t *node = dfa->nodes + nodes->elems[i];
- re_token_type_t type = node->type;
- if (type == CHARACTER)
- continue;
-
- /* If the state has the halt node, the state is a halt state. */
- else if (type == END_OF_RE)
- newstate->halt = 1;
-#ifdef RE_ENABLE_I18N
- else if (type == COMPLEX_BRACKET
- || (type == OP_PERIOD && MB_CUR_MAX > 1))
- newstate->accept_mb = 1;
-#endif /* RE_ENABLE_I18N */
- else if (type == OP_BACK_REF)
- newstate->has_backref = 1;
- else if (type == ANCHOR)
- constraint = node->opr.ctx_type;
- else if (type == OP_CONTEXT_NODE)
- {
- re_token_type_t ctype = dfa->nodes[node->opr.ctx_info->entity].type;
- constraint = node->constraint;
- if (ctype == END_OF_RE)
- newstate->halt = 1;
- else if (ctype == OP_BACK_REF)
- newstate->has_backref = 1;
-#ifdef RE_ENABLE_I18N
- else if (ctype == COMPLEX_BRACKET
- || (type == OP_PERIOD && MB_CUR_MAX > 1))
- newstate->accept_mb = 1;
-#endif /* RE_ENABLE_I18N */
- }
-
- if (constraint)
- {
- if (newstate->entrance_nodes == &newstate->nodes)
- {
- newstate->entrance_nodes = re_malloc (re_node_set, 1);
- if (BE (newstate->entrance_nodes == NULL, 0))
- return NULL;
- re_node_set_init_copy (newstate->entrance_nodes, nodes);
- nctx_nodes = 0;
- newstate->has_constraint = 1;
- }
-
- if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context))
- {
- re_node_set_remove_at (&newstate->nodes, i - nctx_nodes);
- ++nctx_nodes;
- }
- }
- }
- err = register_state (dfa, newstate, hash);
- return (err != REG_NOERROR) ? NULL : newstate;
-}
diff --git a/util/regex_internal.h b/util/regex_internal.h
deleted file mode 100644
index 679bea11b..000000000
--- a/util/regex_internal.h
+++ /dev/null
@@ -1,643 +0,0 @@
-/* Extended regular expression matching and search library.
- Copyright (C) 2002 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Isamu Hasegawa <[email protected]>.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02110-1301 USA. */
-
-#ifndef _REGEX_INTERNAL_H
-#define _REGEX_INTERNAL_H 1
-
-/* Number of bits in a byte. */
-#define BYTE_BITS 8
-/* Number of single byte character. */
-#define SBC_MAX 256
-
-#define COLL_ELEM_LEN_MAX 8
-
-/* The character which represents newline. */
-#define NEWLINE_CHAR '\n'
-
-/* Rename to standard API for using out of glibc. */
-#ifndef _LIBC
-# define __wctype wctype
-# define __iswctype iswctype
-# define __btowc btowc
-# define __mempcpy memcpy
-# define attribute_hidden
-#endif /* not _LIBC */
-
-extern const char __re_error_msgid[] attribute_hidden;
-extern const size_t __re_error_msgid_idx[] attribute_hidden;
-
-/* Number of bits in an unsinged int. */
-#define UINT_BITS (sizeof (unsigned int) * BYTE_BITS)
-/* Number of unsigned int in an bit_set. */
-#define BITSET_UINTS ((SBC_MAX + UINT_BITS - 1) / UINT_BITS)
-typedef unsigned int bitset[BITSET_UINTS];
-typedef unsigned int *re_bitset_ptr_t;
-
-#define bitset_set(set,i) (set[i / UINT_BITS] |= 1 << i % UINT_BITS)
-#define bitset_clear(set,i) (set[i / UINT_BITS] &= ~(1 << i % UINT_BITS))
-#define bitset_contain(set,i) (set[i / UINT_BITS] & (1 << i % UINT_BITS))
-#define bitset_empty(set) memset (set, 0, sizeof (unsigned int) * BITSET_UINTS)
-#define bitset_set_all(set) \
- memset (set, 255, sizeof (unsigned int) * BITSET_UINTS)
-#define bitset_copy(dest,src) \
- memcpy (dest, src, sizeof (unsigned int) * BITSET_UINTS)
-static inline void bitset_not (bitset set);
-static inline void bitset_merge (bitset dest, const bitset src);
-#if 0 /* gnupg */
-static inline void bitset_not_merge (bitset dest, const bitset src);
-#endif
-
-#define PREV_WORD_CONSTRAINT 0x0001
-#define PREV_NOTWORD_CONSTRAINT 0x0002
-#define NEXT_WORD_CONSTRAINT 0x0004
-#define NEXT_NOTWORD_CONSTRAINT 0x0008
-#define PREV_NEWLINE_CONSTRAINT 0x0010
-#define NEXT_NEWLINE_CONSTRAINT 0x0020
-#define PREV_BEGBUF_CONSTRAINT 0x0040
-#define NEXT_ENDBUF_CONSTRAINT 0x0080
-#define DUMMY_CONSTRAINT 0x0100
-
-typedef enum
-{
- INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
- WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
- WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
- LINE_FIRST = PREV_NEWLINE_CONSTRAINT,
- LINE_LAST = NEXT_NEWLINE_CONSTRAINT,
- BUF_FIRST = PREV_BEGBUF_CONSTRAINT,
- BUF_LAST = NEXT_ENDBUF_CONSTRAINT,
- WORD_DELIM = DUMMY_CONSTRAINT
-} re_context_type;
-
-typedef struct
-{
- int alloc;
- int nelem;
- int *elems;
-} re_node_set;
-
-typedef enum
-{
- NON_TYPE = 0,
-
- /* Token type, these are used only by token. */
- OP_OPEN_BRACKET,
- OP_CLOSE_BRACKET,
- OP_CHARSET_RANGE,
- OP_OPEN_DUP_NUM,
- OP_CLOSE_DUP_NUM,
- OP_NON_MATCH_LIST,
- OP_OPEN_COLL_ELEM,
- OP_CLOSE_COLL_ELEM,
- OP_OPEN_EQUIV_CLASS,
- OP_CLOSE_EQUIV_CLASS,
- OP_OPEN_CHAR_CLASS,
- OP_CLOSE_CHAR_CLASS,
- OP_WORD,
- OP_NOTWORD,
- BACK_SLASH,
-
- /* Tree type, these are used only by tree. */
- CONCAT,
- ALT,
- SUBEXP,
- SIMPLE_BRACKET,
-#ifdef RE_ENABLE_I18N
- COMPLEX_BRACKET,
-#endif /* RE_ENABLE_I18N */
-
- /* Node type, These are used by token, node, tree. */
- OP_OPEN_SUBEXP,
- OP_CLOSE_SUBEXP,
- OP_PERIOD,
- CHARACTER,
- END_OF_RE,
- OP_ALT,
- OP_DUP_ASTERISK,
- OP_DUP_PLUS,
- OP_DUP_QUESTION,
- OP_BACK_REF,
- ANCHOR,
- OP_CONTEXT_NODE,
-
- /* Dummy marker. */
- END_OF_RE_TOKEN_T
-} re_token_type_t;
-
-#ifdef RE_ENABLE_I18N
-typedef struct
-{
- /* Multibyte characters. */
- wchar_t *mbchars;
-
- /* Collating symbols. */
-# ifdef _LIBC
- int32_t *coll_syms;
-# endif
-
- /* Equivalence classes. */
-# ifdef _LIBC
- int32_t *equiv_classes;
-# endif
-
- /* Range expressions. */
-# ifdef _LIBC
- uint32_t *range_starts;
- uint32_t *range_ends;
-# else /* not _LIBC */
- wchar_t *range_starts;
- wchar_t *range_ends;
-# endif /* not _LIBC */
-
- /* Character classes. */
- wctype_t *char_classes;
-
- /* If this character set is the non-matching list. */
- unsigned int non_match : 1;
-
- /* # of multibyte characters. */
- int nmbchars;
-
- /* # of collating symbols. */
- int ncoll_syms;
-
- /* # of equivalence classes. */
- int nequiv_classes;
-
- /* # of range expressions. */
- int nranges;
-
- /* # of character classes. */
- int nchar_classes;
-} re_charset_t;
-#endif /* RE_ENABLE_I18N */
-
-typedef struct
-{
- union
- {
- unsigned char c; /* for CHARACTER */
- re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */
-#ifdef RE_ENABLE_I18N
- re_charset_t *mbcset; /* for COMPLEX_BRACKET */
-#endif /* RE_ENABLE_I18N */
- int idx; /* for BACK_REF */
- re_context_type ctx_type; /* for ANCHOR */
- struct
- {
- int entity; /* for OP_CONTEXT_NODE, index of the entity */
- re_node_set *bkref_eclosure;
- } *ctx_info;
- } opr;
-#if __GNUC__ >= 2
- re_token_type_t type : 8;
-#else
- re_token_type_t type;
-#endif
- unsigned int constraint : 10; /* context constraint */
- unsigned int duplicated : 1;
-#ifdef RE_ENABLE_I18N
- unsigned int mb_partial : 1;
-#endif
-} re_token_t;
-
-#define IS_EPSILON_NODE(type) \
- ((type) == OP_ALT || (type) == OP_DUP_ASTERISK || (type) == OP_DUP_PLUS \
- || (type) == OP_DUP_QUESTION || (type) == ANCHOR \
- || (type) == OP_OPEN_SUBEXP || (type) == OP_CLOSE_SUBEXP)
-
-#define ACCEPT_MB_NODE(type) \
- ((type) == COMPLEX_BRACKET || (type) == OP_PERIOD)
-
-struct re_string_t
-{
- /* Indicate the raw buffer which is the original string passed as an
- argument of regexec(), re_search(), etc.. */
- const unsigned char *raw_mbs;
- /* Store the multibyte string. In case of "case insensitive mode" like
- REG_ICASE, upper cases of the string are stored, otherwise MBS points
- the same address that RAW_MBS points. */
- unsigned char *mbs;
- /* Store the case sensitive multibyte string. In case of
- "case insensitive mode", the original string are stored,
- otherwise MBS_CASE points the same address that MBS points. */
- unsigned char *mbs_case;
-#ifdef RE_ENABLE_I18N
- /* Store the wide character string which is corresponding to MBS. */
- wint_t *wcs;
- mbstate_t cur_state;
-#endif
- /* Index in RAW_MBS. Each character mbs[i] corresponds to
- raw_mbs[raw_mbs_idx + i]. */
- int raw_mbs_idx;
- /* The length of the valid characters in the buffers. */
- int valid_len;
- /* The length of the buffers MBS, MBS_CASE, and WCS. */
- int bufs_len;
- /* The index in MBS, which is updated by re_string_fetch_byte. */
- int cur_idx;
- /* This is length_of_RAW_MBS - RAW_MBS_IDX. */
- int len;
- /* End of the buffer may be shorter than its length in the cases such
- as re_match_2, re_search_2. Then, we use STOP for end of the buffer
- instead of LEN. */
- int stop;
-
- /* The context of mbs[0]. We store the context independently, since
- the context of mbs[0] may be different from raw_mbs[0], which is
- the beginning of the input string. */
- unsigned int tip_context;
- /* The translation passed as a part of an argument of re_compile_pattern. */
- RE_TRANSLATE_TYPE trans;
- /* 1 if REG_ICASE. */
- unsigned int icase : 1;
-};
-typedef struct re_string_t re_string_t;
-/* In case of REG_ICASE, we allocate the buffer dynamically for mbs. */
-#define MBS_ALLOCATED(pstr) (pstr->icase)
-/* In case that we need translation, we allocate the buffer dynamically
- for mbs_case. Note that mbs == mbs_case if not REG_ICASE. */
-#define MBS_CASE_ALLOCATED(pstr) (pstr->trans != NULL)
-
-
-static reg_errcode_t re_string_allocate (re_string_t *pstr, const char *str,
- int len, int init_len,
- RE_TRANSLATE_TYPE trans, int icase);
-static reg_errcode_t re_string_construct (re_string_t *pstr, const char *str,
- int len, RE_TRANSLATE_TYPE trans,
- int icase);
-static reg_errcode_t re_string_reconstruct (re_string_t *pstr, int idx,
- int eflags, int newline);
-static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr,
- int new_buf_len);
-#ifdef RE_ENABLE_I18N
-static void build_wcs_buffer (re_string_t *pstr);
-static void build_wcs_upper_buffer (re_string_t *pstr);
-#endif /* RE_ENABLE_I18N */
-static void build_upper_buffer (re_string_t *pstr);
-static void re_string_translate_buffer (re_string_t *pstr);
-static void re_string_destruct (re_string_t *pstr);
-#ifdef RE_ENABLE_I18N
-static int re_string_elem_size_at (const re_string_t *pstr, int idx);
-static inline int re_string_char_size_at (const re_string_t *pstr, int idx);
-static inline wint_t re_string_wchar_at (const re_string_t *pstr, int idx);
-#endif /* RE_ENABLE_I18N */
-static unsigned int re_string_context_at (const re_string_t *input, int idx,
- int eflags, int newline_anchor);
-#define re_string_peek_byte(pstr, offset) \
- ((pstr)->mbs[(pstr)->cur_idx + offset])
-#define re_string_peek_byte_case(pstr, offset) \
- ((pstr)->mbs_case[(pstr)->cur_idx + offset])
-#define re_string_fetch_byte(pstr) \
- ((pstr)->mbs[(pstr)->cur_idx++])
-#define re_string_fetch_byte_case(pstr) \
- ((pstr)->mbs_case[(pstr)->cur_idx++])
-#define re_string_first_byte(pstr, idx) \
- ((idx) == (pstr)->len || (pstr)->wcs[idx] != WEOF)
-#define re_string_is_single_byte_char(pstr, idx) \
- ((pstr)->wcs[idx] != WEOF && ((pstr)->len == (idx) \
- || (pstr)->wcs[(idx) + 1] != WEOF))
-#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx)
-#define re_string_cur_idx(pstr) ((pstr)->cur_idx)
-#define re_string_get_buffer(pstr) ((pstr)->mbs)
-#define re_string_length(pstr) ((pstr)->len)
-#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx])
-#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx))
-#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx))
-
-#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t)))
-#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t)))
-#define re_free(p) free (p)
-
-struct bin_tree_t
-{
- struct bin_tree_t *parent;
- struct bin_tree_t *left;
- struct bin_tree_t *right;
-
- /* `node_idx' is the index in dfa->nodes, if `type' == 0.
- Otherwise `type' indicate the type of this node. */
- re_token_type_t type;
- int node_idx;
-
- int first;
- int next;
- re_node_set eclosure;
-};
-typedef struct bin_tree_t bin_tree_t;
-
-
-#define CONTEXT_WORD 1
-#define CONTEXT_NEWLINE (CONTEXT_WORD << 1)
-#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1)
-#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1)
-
-#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD)
-#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE)
-#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF)
-#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF)
-#define IS_ORDINARY_CONTEXT(c) ((c) == 0)
-
-#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_')
-#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR)
-
-#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \
- ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
- || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
- || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\
- || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context)))
-
-#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \
- ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
- || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
- || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \
- || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context)))
-
-struct re_dfastate_t
-{
- unsigned int hash;
- re_node_set nodes;
- re_node_set *entrance_nodes;
- struct re_dfastate_t **trtable;
- struct re_dfastate_t **trtable_search;
- /* If this state is a special state.
- A state is a special state if the state is the halt state, or
- a anchor. */
- unsigned int context : 2;
- unsigned int halt : 1;
- /* If this state can accept `multi byte'.
- Note that we refer to multibyte characters, and multi character
- collating elements as `multi byte'. */
- unsigned int accept_mb : 1;
- /* If this state has backreference node(s). */
- unsigned int has_backref : 1;
- unsigned int has_constraint : 1;
-};
-typedef struct re_dfastate_t re_dfastate_t;
-
-typedef struct
-{
- /* start <= node < end */
- int start;
- int end;
-} re_subexp_t;
-
-struct re_state_table_entry
-{
- int num;
- int alloc;
- re_dfastate_t **array;
-};
-
-struct re_backref_cache_entry
-{
- int node;
- int str_idx;
- int subexp_from;
- int subexp_to;
- int flag;
-};
-
-typedef struct
-{
- /* EFLAGS of the argument of regexec. */
- int eflags;
- /* Where the matching ends. */
- int match_last;
- int last_node;
- /* The string object corresponding to the input string. */
- re_string_t *input;
- /* The state log used by the matcher. */
- re_dfastate_t **state_log;
- int state_log_top;
- /* Back reference cache. */
- int nbkref_ents;
- int abkref_ents;
- struct re_backref_cache_entry *bkref_ents;
- int max_mb_elem_len;
-} re_match_context_t;
-
-typedef struct
-{
- int cur_bkref;
- int cls_subexp_idx;
-
- re_dfastate_t **sifted_states;
- re_dfastate_t **limited_states;
-
- re_node_set limits;
-
- int last_node;
- int last_str_idx;
- int check_subexp;
-} re_sift_context_t;
-
-struct re_fail_stack_ent_t
-{
- int idx;
- int node;
- regmatch_t *regs;
- re_node_set eps_via_nodes;
-};
-
-struct re_fail_stack_t
-{
- int num;
- int alloc;
- struct re_fail_stack_ent_t *stack;
-};
-
-struct re_dfa_t
-{
- re_bitset_ptr_t word_char;
-
- /* number of subexpressions `re_nsub' is in regex_t. */
- int subexps_alloc;
- re_subexp_t *subexps;
-
- re_token_t *nodes;
- int nodes_alloc;
- int nodes_len;
- bin_tree_t *str_tree;
- int *firsts;
- int *nexts;
- re_node_set *edests;
- re_node_set *eclosures;
- re_node_set *inveclosures;
- struct re_state_table_entry *state_table;
- unsigned int state_hash_mask;
- re_dfastate_t *init_state;
- re_dfastate_t *init_state_word;
- re_dfastate_t *init_state_nl;
- re_dfastate_t *init_state_begbuf;
- int states_alloc;
- int init_node;
- int nbackref; /* The number of backreference in this dfa. */
- /* If this dfa has "multibyte node", which is a backreference or
- a node which can accept multibyte character or multi character
- collating element. */
-#ifdef DEBUG
- char* re_str;
-#endif
- unsigned int has_plural_match : 1;
- unsigned int has_mb_node : 1;
-};
-typedef struct re_dfa_t re_dfa_t;
-
-static reg_errcode_t re_node_set_alloc (re_node_set *set, int size);
-static reg_errcode_t re_node_set_init_1 (re_node_set *set, int elem);
-static reg_errcode_t re_node_set_init_2 (re_node_set *set, int elem1,
- int elem2);
-#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set))
-static reg_errcode_t re_node_set_init_copy (re_node_set *dest,
- const re_node_set *src);
-static reg_errcode_t re_node_set_add_intersect (re_node_set *dest,
- const re_node_set *src1,
- const re_node_set *src2);
-static reg_errcode_t re_node_set_init_union (re_node_set *dest,
- const re_node_set *src1,
- const re_node_set *src2);
-static reg_errcode_t re_node_set_merge (re_node_set *dest,
- const re_node_set *src);
-static int re_node_set_insert (re_node_set *set, int elem);
-static int re_node_set_compare (const re_node_set *set1,
- const re_node_set *set2);
-static int re_node_set_contains (const re_node_set *set, int elem);
-static void re_node_set_remove_at (re_node_set *set, int idx);
-#define re_node_set_empty(p) ((p)->nelem = 0)
-#define re_node_set_free(set) re_free ((set)->elems)
-static int re_dfa_add_node (re_dfa_t *dfa, re_token_t token, int mode);
-static re_dfastate_t *re_acquire_state (reg_errcode_t *err, re_dfa_t *dfa,
- const re_node_set *nodes);
-static re_dfastate_t *re_acquire_state_context (reg_errcode_t *err,
- re_dfa_t *dfa,
- const re_node_set *nodes,
- unsigned int context);
-
-
-typedef enum
-{
- SB_CHAR,
- MB_CHAR,
- EQUIV_CLASS,
- COLL_SYM,
- CHAR_CLASS
-} bracket_elem_type;
-
-typedef struct
-{
- bracket_elem_type type;
- union
- {
- unsigned char ch;
- unsigned char *name;
- wchar_t wch;
- } opr;
-} bracket_elem_t;
-
-
-/* Inline functions for bitset operation. */
-static inline void
-bitset_not (set)
- bitset set;
-{
- int bitset_i;
- for (bitset_i = 0; bitset_i < BITSET_UINTS; ++bitset_i)
- set[bitset_i] = ~set[bitset_i];
-}
-
-static inline void
-bitset_merge (dest, src)
- bitset dest;
- const bitset src;
-{
- int bitset_i;
- for (bitset_i = 0; bitset_i < BITSET_UINTS; ++bitset_i)
- dest[bitset_i] |= src[bitset_i];
-}
-
-#if 0 /* gnupg */
-static inline void
-bitset_not_merge (dest, src)
- bitset dest;
- const bitset src;
-{
- int i;
- for (i = 0; i < BITSET_UINTS; ++i)
- dest[i] |= ~src[i];
-}
-#endif
-
-#ifdef RE_ENABLE_I18N
-/* Inline functions for re_string. */
-static inline int
-re_string_char_size_at (pstr, idx)
- const re_string_t *pstr;
- int idx;
-{
- int byte_idx;
- if (MB_CUR_MAX == 1)
- return 1;
- for (byte_idx = 1; idx + byte_idx < pstr->len; ++byte_idx)
- if (pstr->wcs[idx + byte_idx] != WEOF)
- break;
- return byte_idx;
-}
-
-static inline wint_t
-re_string_wchar_at (pstr, idx)
- const re_string_t *pstr;
- int idx;
-{
- if (MB_CUR_MAX == 1)
- return (wint_t) pstr->mbs[idx];
- return (wint_t) pstr->wcs[idx];
-}
-
-static int
-re_string_elem_size_at (pstr, idx)
- const re_string_t *pstr;
- int idx;
-{
-#ifdef _LIBC
- const unsigned char *p, *extra;
- const int32_t *table, *indirect;
- int32_t tmp;
-# include <locale/weight.h>
- uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
-
- if (nrules != 0)
- {
- table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
- extra = (const unsigned char *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
- indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
- _NL_COLLATE_INDIRECTMB);
- p = pstr->mbs + idx;
- tmp = findidx (&p);
- return p - pstr->mbs - idx;
- }
- else
-#endif /* _LIBC */
- return 1;
-}
-#endif /* RE_ENABLE_I18N */
-
-#endif /* _REGEX_INTERNAL_H */
diff --git a/util/regexec.c b/util/regexec.c
deleted file mode 100644
index 40d305899..000000000
--- a/util/regexec.c
+++ /dev/null
@@ -1,3225 +0,0 @@
-/* Extended regular expression matching and search library.
- Copyright (C) 2002 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Isamu Hasegawa <[email protected]>.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02110-1301 USA. */
-
-#include <assert.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if defined HAVE_WCHAR_H || defined _LIBC
-# include <wchar.h>
-#endif /* HAVE_WCHAR_H || _LIBC */
-#if defined HAVE_WCTYPE_H || defined _LIBC
-# include <wctype.h>
-#endif /* HAVE_WCTYPE_H || _LIBC */
-
-#ifdef _LIBC
-# ifndef _RE_DEFINE_LOCALE_FUNCTIONS
-# define _RE_DEFINE_LOCALE_FUNCTIONS 1
-# include <locale/localeinfo.h>
-# include <locale/elem-hash.h>
-# include <locale/coll-lookup.h>
-# endif
-#endif
-
-#include "_regex.h" /* gnupg */
-#include "regex_internal.h"
-
-static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags,
- re_string_t *input, int n);
-static void match_ctx_free (re_match_context_t *cache);
-static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, int node,
- int str_idx, int from, int to);
-static void match_ctx_clear_flag (re_match_context_t *mctx);
-static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts,
- re_dfastate_t **limited_sts, int last_node,
- int last_str_idx, int check_subexp);
-static reg_errcode_t re_search_internal (const regex_t *preg,
- const char *string, int length,
- int start, int range, int stop,
- size_t nmatch, regmatch_t pmatch[],
- int eflags);
-static int re_search_2_stub (struct re_pattern_buffer *bufp,
- const char *string1, int length1,
- const char *string2, int length2,
- int start, int range, struct re_registers *regs,
- int stop, int ret_len);
-static int re_search_stub (struct re_pattern_buffer *bufp,
- const char *string, int length, int start,
- int range, int stop, struct re_registers *regs,
- int ret_len);
-static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch,
- int nregs, int regs_allocated);
-static inline re_dfastate_t *acquire_init_state_context (reg_errcode_t *err,
- const regex_t *preg,
- const re_match_context_t *mctx,
- int idx);
-static int check_matching (const regex_t *preg, re_match_context_t *mctx,
- int fl_search, int fl_longest_match);
-static int check_halt_node_context (const re_dfa_t *dfa, int node,
- unsigned int context);
-static int check_halt_state_context (const regex_t *preg,
- const re_dfastate_t *state,
- const re_match_context_t *mctx, int idx);
-static void update_regs (re_dfa_t *dfa, regmatch_t *pmatch, int cur_node,
- int cur_idx, int nmatch);
-static int proceed_next_node (const regex_t *preg, int nregs, regmatch_t *regs,
- const re_match_context_t *mctx,
- int *pidx, int node, re_node_set *eps_via_nodes,
- struct re_fail_stack_t *fs);
-static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs,
- int str_idx, int *dests, int nregs,
- regmatch_t *regs,
- re_node_set *eps_via_nodes);
-static int pop_fail_stack (struct re_fail_stack_t *fs, int *pidx, int nregs,
- regmatch_t *regs, re_node_set *eps_via_nodes);
-static reg_errcode_t set_regs (const regex_t *preg,
- const re_match_context_t *mctx,
- size_t nmatch, regmatch_t *pmatch,
- int fl_backtrack);
-#ifdef RE_ENABLE_I18N
-static int sift_states_iter_mb (const regex_t *preg,
- const re_match_context_t *mctx,
- re_sift_context_t *sctx,
- int node_idx, int str_idx, int max_str_idx);
-#endif /* RE_ENABLE_I18N */
-static reg_errcode_t sift_states_backward (const regex_t *preg,
- re_match_context_t *mctx,
- re_sift_context_t *sctx);
-static reg_errcode_t update_cur_sifted_state (const regex_t *preg,
- re_match_context_t *mctx,
- re_sift_context_t *sctx,
- int str_idx,
- re_node_set *dest_nodes);
-static reg_errcode_t add_epsilon_src_nodes (re_dfa_t *dfa,
- re_node_set *dest_nodes,
- const re_node_set *candidates);
-static reg_errcode_t sub_epsilon_src_nodes (re_dfa_t *dfa, int node,
- re_node_set *dest_nodes,
- const re_node_set *and_nodes);
-static int check_dst_limits (re_dfa_t *dfa, re_node_set *limits,
- re_match_context_t *mctx, int dst_node,
- int dst_idx, int src_node, int src_idx);
-static int check_dst_limits_calc_pos (re_dfa_t *dfa, re_match_context_t *mctx,
- int limit, re_node_set *eclosures,
- int subexp_idx, int node, int str_idx);
-static reg_errcode_t check_subexp_limits (re_dfa_t *dfa,
- re_node_set *dest_nodes,
- const re_node_set *candidates,
- re_node_set *limits,
- struct re_backref_cache_entry *bkref_ents,
- int str_idx);
-static reg_errcode_t search_subexp (const regex_t *preg,
- re_match_context_t *mctx,
- re_sift_context_t *sctx, int str_idx,
- re_node_set *dest_nodes);
-static reg_errcode_t sift_states_bkref (const regex_t *preg,
- re_match_context_t *mctx,
- re_sift_context_t *sctx,
- int str_idx, re_node_set *dest_nodes);
-static reg_errcode_t clean_state_log_if_need (re_match_context_t *mctx,
- int next_state_log_idx);
-static reg_errcode_t merge_state_array (re_dfa_t *dfa, re_dfastate_t **dst,
- re_dfastate_t **src, int num);
-static re_dfastate_t *transit_state (reg_errcode_t *err, const regex_t *preg,
- re_match_context_t *mctx,
- re_dfastate_t *state, int fl_search);
-static re_dfastate_t *transit_state_sb (reg_errcode_t *err, const regex_t *preg,
- re_dfastate_t *pstate,
- int fl_search,
- re_match_context_t *mctx);
-#ifdef RE_ENABLE_I18N
-static reg_errcode_t transit_state_mb (const regex_t *preg,
- re_dfastate_t *pstate,
- re_match_context_t *mctx);
-#endif /* RE_ENABLE_I18N */
-static reg_errcode_t transit_state_bkref (const regex_t *preg,
- re_dfastate_t *pstate,
- re_match_context_t *mctx);
-static reg_errcode_t transit_state_bkref_loop (const regex_t *preg,
- re_node_set *nodes,
- re_dfastate_t **work_state_log,
- re_match_context_t *mctx);
-static re_dfastate_t **build_trtable (const regex_t *dfa,
- const re_dfastate_t *state,
- int fl_search);
-#ifdef RE_ENABLE_I18N
-static int check_node_accept_bytes (const regex_t *preg, int node_idx,
- const re_string_t *input, int idx);
-# ifdef _LIBC
-static unsigned int find_collation_sequence_value (const unsigned char *mbs,
- size_t name_len);
-# endif /* _LIBC */
-#endif /* RE_ENABLE_I18N */
-static int group_nodes_into_DFAstates (const regex_t *dfa,
- const re_dfastate_t *state,
- re_node_set *states_node,
- bitset *states_ch);
-static int check_node_accept (const regex_t *preg, const re_token_t *node,
- const re_match_context_t *mctx, int idx);
-static reg_errcode_t extend_buffers (re_match_context_t *mctx);
-
-/* Entry point for POSIX code. */
-
-/* regexec searches for a given pattern, specified by PREG, in the
- string STRING.
-
- If NMATCH is zero or REG_NOSUB was set in the cflags argument to
- `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at
- least NMATCH elements, and we set them to the offsets of the
- corresponding matched substrings.
-
- EFLAGS specifies `execution flags' which affect matching: if
- REG_NOTBOL is set, then ^ does not match at the beginning of the
- string; if REG_NOTEOL is set, then $ does not match at the end.
-
- We return 0 if we find a match and REG_NOMATCH if not. */
-
-int
-regexec (preg, string, nmatch, pmatch, eflags)
- const regex_t *__restrict preg;
- const char *__restrict string;
- size_t nmatch;
- regmatch_t pmatch[];
- int eflags;
-{
- reg_errcode_t err;
- int length = strlen (string);
- if (preg->no_sub)
- err = re_search_internal (preg, string, length, 0, length, length, 0,
- NULL, eflags);
- else
- err = re_search_internal (preg, string, length, 0, length, length, nmatch,
- pmatch, eflags);
- return err != REG_NOERROR;
-}
-#ifdef _LIBC
-weak_alias (__regexec, regexec)
-#endif
-
-/* Entry points for GNU code. */
-
-/* re_match, re_search, re_match_2, re_search_2
-
- The former two functions operate on STRING with length LENGTH,
- while the later two operate on concatenation of STRING1 and STRING2
- with lengths LENGTH1 and LENGTH2, respectively.
-
- re_match() matches the compiled pattern in BUFP against the string,
- starting at index START.
-
- re_search() first tries matching at index START, then it tries to match
- starting from index START + 1, and so on. The last start position tried
- is START + RANGE. (Thus RANGE = 0 forces re_search to operate the same
- way as re_match().)
-
- The parameter STOP of re_{match,search}_2 specifies that no match exceeding
- the first STOP characters of the concatenation of the strings should be
- concerned.
-
- If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match
- and all groups is stroed in REGS. (For the "_2" variants, the offsets are
- computed relative to the concatenation, not relative to the individual
- strings.)
-
- On success, re_match* functions return the length of the match, re_search*
- return the position of the start of the match. Return value -1 means no
- match was found and -2 indicates an internal error. */
-
-int
-re_match (bufp, string, length, start, regs)
- struct re_pattern_buffer *bufp;
- const char *string;
- int length, start;
- struct re_registers *regs;
-{
- return re_search_stub (bufp, string, length, start, 0, length, regs, 1);
-}
-#ifdef _LIBC
-weak_alias (__re_match, re_match)
-#endif
-
-int
-re_search (bufp, string, length, start, range, regs)
- struct re_pattern_buffer *bufp;
- const char *string;
- int length, start, range;
- struct re_registers *regs;
-{
- return re_search_stub (bufp, string, length, start, range, length, regs, 0);
-}
-#ifdef _LIBC
-weak_alias (__re_search, re_search)
-#endif
-
-int
-re_match_2 (bufp, string1, length1, string2, length2, start, regs, stop)
- struct re_pattern_buffer *bufp;
- const char *string1, *string2;
- int length1, length2, start, stop;
- struct re_registers *regs;
-{
- return re_search_2_stub (bufp, string1, length1, string2, length2,
- start, 0, regs, stop, 1);
-}
-#ifdef _LIBC
-weak_alias (__re_match_2, re_match_2)
-#endif
-
-int
-re_search_2 (bufp, string1, length1, string2, length2, start, range, regs, stop)
- struct re_pattern_buffer *bufp;
- const char *string1, *string2;
- int length1, length2, start, range, stop;
- struct re_registers *regs;
-{
- return re_search_2_stub (bufp, string1, length1, string2, length2,
- start, range, regs, stop, 0);
-}
-#ifdef _LIBC
-weak_alias (__re_search_2, re_search_2)
-#endif
-
-static int
-re_search_2_stub (bufp, string1, length1, string2, length2, start, range, regs,
- stop, ret_len)
- struct re_pattern_buffer *bufp;
- const char *string1, *string2;
- int length1, length2, start, range, stop, ret_len;
- struct re_registers *regs;
-{
- const char *str;
- int rval;
- int len = length1 + length2;
- int free_str = 0;
-
- if (BE (length1 < 0 || length2 < 0 || stop < 0, 0))
- return -2;
-
- /* Concatenate the strings. */
- if (length2 > 0)
- if (length1 > 0)
- {
- char *s = re_malloc (char, len);
-
- if (BE (s == NULL, 0))
- return -2;
- memcpy (s, string1, length1);
- memcpy (s + length1, string2, length2);
- str = s;
- free_str = 1;
- }
- else
- str = string2;
- else
- str = string1;
-
- rval = re_search_stub (bufp, str, len, start, range, stop, regs,
- ret_len);
- if (free_str)
- re_free ((char *) str);
- return rval;
-}
-
-/* The parameters have the same meaning as those of re_search.
- Additional parameters:
- If RET_LEN is nonzero the length of the match is returned (re_match style);
- otherwise the position of the match is returned. */
-
-static int
-re_search_stub (bufp, string, length, start, range, stop, regs, ret_len)
- struct re_pattern_buffer *bufp;
- const char *string;
- int length, start, range, stop, ret_len;
- struct re_registers *regs;
-{
- reg_errcode_t result;
- regmatch_t *pmatch;
- int nregs, rval;
- int eflags = 0;
-
- /* Check for out-of-range. */
- if (BE (start < 0 || start > length, 0))
- return -1;
- if (BE (start + range > length, 0))
- range = length - start;
- else if (BE (start + range < 0, 0))
- range = -start;
-
- eflags |= (bufp->not_bol) ? REG_NOTBOL : 0;
- eflags |= (bufp->not_eol) ? REG_NOTEOL : 0;
-
- /* Compile fastmap if we haven't yet. */
- if (range > 0 && bufp->fastmap != NULL && !bufp->fastmap_accurate)
- re_compile_fastmap (bufp);
-
- if (BE (bufp->no_sub, 0))
- regs = NULL;
-
- /* We need at least 1 register. */
- if (regs == NULL)
- nregs = 1;
- else if (BE (bufp->regs_allocated == REGS_FIXED &&
- regs->num_regs < bufp->re_nsub + 1, 0))
- {
- nregs = regs->num_regs;
- if (BE (nregs < 1, 0))
- {
- /* Nothing can be copied to regs. */
- regs = NULL;
- nregs = 1;
- }
- }
- else
- nregs = bufp->re_nsub + 1;
- pmatch = re_malloc (regmatch_t, nregs);
- if (BE (pmatch == NULL, 0))
- return -2;
-
- result = re_search_internal (bufp, string, length, start, range, stop,
- nregs, pmatch, eflags);
-
- rval = 0;
-
- /* I hope we needn't fill ther regs with -1's when no match was found. */
- if (result != REG_NOERROR)
- rval = -1;
- else if (regs != NULL)
- {
- /* If caller wants register contents data back, copy them. */
- bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs,
- bufp->regs_allocated);
- if (BE (bufp->regs_allocated == REGS_UNALLOCATED, 0))
- rval = -2;
- }
-
- if (BE (rval == 0, 1))
- {
- if (ret_len)
- {
- assert (pmatch[0].rm_so == start);
- rval = pmatch[0].rm_eo - start;
- }
- else
- rval = pmatch[0].rm_so;
- }
- re_free (pmatch);
- return rval;
-}
-
-static unsigned
-re_copy_regs (regs, pmatch, nregs, regs_allocated)
- struct re_registers *regs;
- regmatch_t *pmatch;
- int nregs, regs_allocated;
-{
- int rval = REGS_REALLOCATE;
- int i;
- int need_regs = nregs + 1;
- /* We need one extra element beyond `num_regs' for the `-1' marker GNU code
- uses. */
-
- /* Have the register data arrays been allocated? */
- if (regs_allocated == REGS_UNALLOCATED)
- { /* No. So allocate them with malloc. */
- regs->start = re_malloc (regoff_t, need_regs);
- if (BE (regs->start == NULL, 0))
- return REGS_UNALLOCATED;
- regs->end = re_malloc (regoff_t, need_regs);
- if (BE (regs->end == NULL, 0))
- {
- re_free (regs->start);
- return REGS_UNALLOCATED;
- }
- regs->num_regs = need_regs;
- }
- else if (regs_allocated == REGS_REALLOCATE)
- { /* Yes. If we need more elements than were already
- allocated, reallocate them. If we need fewer, just
- leave it alone. */
- if (need_regs > regs->num_regs)
- {
- regs->start = re_realloc (regs->start, regoff_t, need_regs);
- if (BE (regs->start == NULL, 0))
- {
- if (regs->end != NULL)
- re_free (regs->end);
- return REGS_UNALLOCATED;
- }
- regs->end = re_realloc (regs->end, regoff_t, need_regs);
- if (BE (regs->end == NULL, 0))
- {
- re_free (regs->start);
- return REGS_UNALLOCATED;
- }
- regs->num_regs = need_regs;
- }
- }
- else
- {
- assert (regs_allocated == REGS_FIXED);
- /* This function may not be called with REGS_FIXED and nregs too big. */
- assert (regs->num_regs >= nregs);
- rval = REGS_FIXED;
- }
-
- /* Copy the regs. */
- for (i = 0; i < nregs; ++i)
- {
- regs->start[i] = pmatch[i].rm_so;
- regs->end[i] = pmatch[i].rm_eo;
- }
- for ( ; i < regs->num_regs; ++i)
- regs->start[i] = regs->end[i] = -1;
-
- return rval;
-}
-
-/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
- ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use
- this memory for recording register information. STARTS and ENDS
- must be allocated using the malloc library routine, and must each
- be at least NUM_REGS * sizeof (regoff_t) bytes long.
-
- If NUM_REGS == 0, then subsequent matches should allocate their own
- register data.
-
- Unless this function is called, the first search or match using
- PATTERN_BUFFER will allocate its own register data, without
- freeing the old data. */
-
-void
-re_set_registers (bufp, regs, num_regs, starts, ends)
- struct re_pattern_buffer *bufp;
- struct re_registers *regs;
- unsigned num_regs;
- regoff_t *starts, *ends;
-{
- if (num_regs)
- {
- bufp->regs_allocated = REGS_REALLOCATE;
- regs->num_regs = num_regs;
- regs->start = starts;
- regs->end = ends;
- }
- else
- {
- bufp->regs_allocated = REGS_UNALLOCATED;
- regs->num_regs = 0;
- regs->start = regs->end = (regoff_t *) 0;
- }
-}
-#ifdef _LIBC
-weak_alias (__re_set_registers, re_set_registers)
-#endif
-
-/* Entry points compatible with 4.2 BSD regex library. We don't define
- them unless specifically requested. */
-
-#if defined _REGEX_RE_COMP || defined _LIBC
-int
-# ifdef _LIBC
-weak_function
-# endif
-re_exec (s)
- const char *s;
-{
- return 0 == regexec (&re_comp_buf, s, 0, NULL, 0);
-}
-#endif /* _REGEX_RE_COMP */
-
-static re_node_set empty_set;
-
-/* Internal entry point. */
-
-/* Searches for a compiled pattern PREG in the string STRING, whose
- length is LENGTH. NMATCH, PMATCH, and EFLAGS have the same
- mingings with regexec. START, and RANGE have the same meanings
- with re_search.
- Return REG_NOERROR if we find a match, and REG_NOMATCH if not,
- otherwise return the error code.
- Note: We assume front end functions already check ranges.
- (START + RANGE >= 0 && START + RANGE <= LENGTH) */
-
-static reg_errcode_t
-re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch,
- eflags)
- const regex_t *preg;
- const char *string;
- int length, start, range, stop, eflags;
- size_t nmatch;
- regmatch_t pmatch[];
-{
- reg_errcode_t err;
- re_dfa_t *dfa = (re_dfa_t *)preg->buffer;
- re_string_t input;
- int left_lim, right_lim, incr;
- int fl_longest_match, match_first, match_last = -1;
- re_match_context_t mctx;
- char *fastmap = ((preg->fastmap != NULL && preg->fastmap_accurate)
- ? preg->fastmap : NULL);
-
- /* Check if the DFA haven't been compiled. */
- if (BE (preg->used == 0 || dfa->init_state == NULL
- || dfa->init_state_word == NULL || dfa->init_state_nl == NULL
- || dfa->init_state_begbuf == NULL, 0))
- return REG_NOMATCH;
-
- re_node_set_init_empty (&empty_set);
-
- /* We must check the longest matching, if nmatch > 0. */
- fl_longest_match = (nmatch != 0);
-
- err = re_string_allocate (&input, string, length, dfa->nodes_len + 1,
- preg->translate, preg->syntax & RE_ICASE);
- if (BE (err != REG_NOERROR, 0))
- return err;
- input.stop = stop;
-
- err = match_ctx_init (&mctx, eflags, &input, dfa->nbackref * 2);
- if (BE (err != REG_NOERROR, 0))
- return err;
-
- /* We will log all the DFA states through which the dfa pass,
- if nmatch > 1, or this dfa has "multibyte node", which is a
- back-reference or a node which can accept multibyte character or
- multi character collating element. */
- if (nmatch > 1 || dfa->has_mb_node)
- {
- mctx.state_log = re_malloc (re_dfastate_t *, dfa->nodes_len + 1);
- if (BE (mctx.state_log == NULL, 0))
- return REG_ESPACE;
- }
- else
- mctx.state_log = NULL;
-
-#ifdef DEBUG
- /* We assume front-end functions already check them. */
- assert (start + range >= 0 && start + range <= length);
-#endif
-
- match_first = start;
- input.tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
- : CONTEXT_NEWLINE | CONTEXT_BEGBUF);
-
- /* Check incrementally whether of not the input string match. */
- incr = (range < 0) ? -1 : 1;
- left_lim = (range < 0) ? start + range : start;
- right_lim = (range < 0) ? start : start + range;
-
- for (;;)
- {
- /* At first get the current byte from input string. */
- int ch;
- if (MB_CUR_MAX > 1 && (preg->syntax & RE_ICASE || preg->translate))
- {
- /* In this case, we can't determin easily the current byte,
- since it might be a component byte of a multibyte character.
- Then we use the constructed buffer instead. */
- /* If MATCH_FIRST is out of the valid range, reconstruct the
- buffers. */
- if (input.raw_mbs_idx + input.valid_len <= match_first)
- re_string_reconstruct (&input, match_first, eflags,
- preg->newline_anchor);
- /* If MATCH_FIRST is out of the buffer, leave it as '\0'.
- Note that MATCH_FIRST must not be smaller than 0. */
- ch = ((match_first >= length) ? 0
- : re_string_byte_at (&input, match_first - input.raw_mbs_idx));
- }
- else
- {
- /* We apply translate/conversion manually, since it is trivial
- in this case. */
- /* If MATCH_FIRST is out of the buffer, leave it as '\0'.
- Note that MATCH_FIRST must not be smaller than 0. */
- ch = (match_first < length) ? (unsigned char)string[match_first] : 0;
- /* Apply translation if we need. */
- ch = preg->translate ? preg->translate[ch] : ch;
- /* In case of case insensitive mode, convert to upper case. */
- ch = ((preg->syntax & RE_ICASE) && islower (ch)) ? toupper (ch) : ch;
- }
-
- /* Eliminate inappropriate one by fastmap. */
- if (preg->can_be_null || fastmap == NULL || fastmap[ch])
- {
- /* Reconstruct the buffers so that the matcher can assume that
- the matching starts from the begining of the buffer. */
- re_string_reconstruct (&input, match_first, eflags,
- preg->newline_anchor);
-#ifdef RE_ENABLE_I18N
- /* Eliminate it when it is a component of a multibyte character
- and isn't the head of a multibyte character. */
- if (MB_CUR_MAX == 1 || re_string_first_byte (&input, 0))
-#endif
- {
- /* It seems to be appropriate one, then use the matcher. */
- /* We assume that the matching starts from 0. */
- mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0;
- match_last = check_matching (preg, &mctx, 0, fl_longest_match);
- if (match_last != -1)
- {
- if (BE (match_last == -2, 0))
- return REG_ESPACE;
- else
- break; /* We found a matching. */
- }
- }
- }
- /* Update counter. */
- match_first += incr;
- if (match_first < left_lim || right_lim < match_first)
- break;
- }
-
- /* Set pmatch[] if we need. */
- if (match_last != -1 && nmatch > 0)
- {
- int reg_idx;
-
- /* Initialize registers. */
- for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
- pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1;
-
- /* Set the points where matching start/end. */
- pmatch[0].rm_so = 0;
- mctx.match_last = pmatch[0].rm_eo = match_last;
-
- if (!preg->no_sub && nmatch > 1)
- {
- /* We need the ranges of all the subexpressions. */
- int halt_node;
- re_dfastate_t **sifted_states;
- re_dfastate_t **lim_states = NULL;
- re_dfastate_t *pstate = mctx.state_log[match_last];
- re_sift_context_t sctx;
-#ifdef DEBUG
- assert (mctx.state_log != NULL);
-#endif
- halt_node = check_halt_state_context (preg, pstate, &mctx,
- match_last);
- if (dfa->has_plural_match)
- {
- match_ctx_clear_flag (&mctx);
- sifted_states = re_malloc (re_dfastate_t *, match_last + 1);
- if (BE (sifted_states == NULL, 0))
- return REG_ESPACE;
- if (dfa->nbackref)
- {
- lim_states = calloc (sizeof (re_dfastate_t *),
- match_last + 1);
- if (BE (lim_states == NULL, 0))
- return REG_ESPACE;
- }
- sift_ctx_init (&sctx, sifted_states, lim_states, halt_node,
- mctx.match_last, 0);
- err = sift_states_backward (preg, &mctx, &sctx);
- if (BE (err != REG_NOERROR, 0))
- return err;
- if (lim_states != NULL)
- {
- err = merge_state_array (dfa, sifted_states, lim_states,
- match_last + 1);
- if (BE (err != REG_NOERROR, 0))
- return err;
- re_free (lim_states);
- }
- re_node_set_free (&sctx.limits);
- re_free (mctx.state_log);
- mctx.state_log = sifted_states;
- }
- mctx.last_node = halt_node;
- err = set_regs (preg, &mctx, nmatch, pmatch,
- dfa->has_plural_match && dfa->nbackref > 0);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
-
- /* At last, add the offset to the each registers, since we slided
- the buffers so that We can assume that the matching starts from 0. */
- for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
- if (pmatch[reg_idx].rm_so != -1)
- {
- pmatch[reg_idx].rm_so += match_first;
- pmatch[reg_idx].rm_eo += match_first;
- }
- }
-
- re_free (mctx.state_log);
- if (dfa->nbackref)
- match_ctx_free (&mctx);
- re_string_destruct (&input);
-
- return (match_last == -1) ? REG_NOMATCH : REG_NOERROR;
-}
-
-/* Acquire an initial state and return it.
- We must select appropriate initial state depending on the context,
- since initial states may have constraints like "\<", "^", etc.. */
-
-static inline re_dfastate_t *
-acquire_init_state_context (err, preg, mctx, idx)
- reg_errcode_t *err;
- const regex_t *preg;
- const re_match_context_t *mctx;
- int idx;
-{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
-
- *err = REG_NOERROR;
- if (dfa->init_state->has_constraint)
- {
- unsigned int context;
- context = re_string_context_at (mctx->input, idx - 1, mctx->eflags,
- preg->newline_anchor);
- if (IS_WORD_CONTEXT (context))
- return dfa->init_state_word;
- else if (IS_ORDINARY_CONTEXT (context))
- return dfa->init_state;
- else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context))
- return dfa->init_state_begbuf;
- else if (IS_NEWLINE_CONTEXT (context))
- return dfa->init_state_nl;
- else if (IS_BEGBUF_CONTEXT (context))
- {
- /* It is relatively rare case, then calculate on demand. */
- return re_acquire_state_context (err, dfa,
- dfa->init_state->entrance_nodes,
- context);
- }
- else
- /* Must not happen? */
- return dfa->init_state;
- }
- else
- return dfa->init_state;
-}
-
-/* Check whether the regular expression match input string INPUT or not,
- and return the index where the matching end, return -1 if not match,
- or return -2 in case of an error.
- FL_SEARCH means we must search where the matching starts,
- FL_LONGEST_MATCH means we want the POSIX longest matching.
- Note that the matcher assume that the maching starts from the current
- index of the buffer. */
-
-static int
-check_matching (preg, mctx, fl_search, fl_longest_match)
- const regex_t *preg;
- re_match_context_t *mctx;
- int fl_search, fl_longest_match;
-{
- reg_errcode_t err;
- int match = 0;
- int match_last = -1;
- int cur_str_idx = re_string_cur_idx (mctx->input);
- re_dfastate_t *cur_state;
-
- cur_state = acquire_init_state_context (&err, preg, mctx, cur_str_idx);
- /* An initial state must not be NULL(invalid state). */
- if (BE (cur_state == NULL, 0))
- return -2;
- if (mctx->state_log != NULL)
- mctx->state_log[cur_str_idx] = cur_state;
-
- if (cur_state->has_backref)
- {
- int i;
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- for (i = 0; i < cur_state->nodes.nelem; ++i)
- {
- re_token_type_t type;
- int node = cur_state->nodes.elems[i];
- int entity = (dfa->nodes[node].type != OP_CONTEXT_NODE ? node
- : dfa->nodes[node].opr.ctx_info->entity);
- type = dfa->nodes[entity].type;
- if (type == OP_BACK_REF)
- {
- int clexp_idx;
- for (clexp_idx = 0; clexp_idx < cur_state->nodes.nelem;
- ++clexp_idx)
- {
- re_token_t *clexp_node;
- clexp_node = dfa->nodes + cur_state->nodes.elems[clexp_idx];
- if (clexp_node->type == OP_CLOSE_SUBEXP
- && clexp_node->opr.idx + 1== dfa->nodes[entity].opr.idx)
- {
- err = match_ctx_add_entry (mctx, node, 0, 0, 0);
- if (BE (err != REG_NOERROR, 0))
- return -2;
- break;
- }
- }
- }
- }
- }
-
- /* If the RE accepts NULL string. */
- if (cur_state->halt)
- {
- if (!cur_state->has_constraint
- || check_halt_state_context (preg, cur_state, mctx, cur_str_idx))
- {
- if (!fl_longest_match)
- return cur_str_idx;
- else
- {
- match_last = cur_str_idx;
- match = 1;
- }
- }
- }
-
- while (!re_string_eoi (mctx->input))
- {
- cur_state = transit_state (&err, preg, mctx, cur_state,
- fl_search && !match);
- if (cur_state == NULL) /* Reached at the invalid state or an error. */
- {
- cur_str_idx = re_string_cur_idx (mctx->input);
- if (BE (err != REG_NOERROR, 0))
- return -2;
- if (fl_search && !match)
- {
- /* Restart from initial state, since we are searching
- the point from where matching start. */
-#ifdef RE_ENABLE_I18N
- if (MB_CUR_MAX == 1
- || re_string_first_byte (mctx->input, cur_str_idx))
-#endif /* RE_ENABLE_I18N */
- cur_state = acquire_init_state_context (&err, preg, mctx,
- cur_str_idx);
- if (BE (cur_state == NULL && err != REG_NOERROR, 0))
- return -2;
- if (mctx->state_log != NULL)
- mctx->state_log[cur_str_idx] = cur_state;
- }
- else if (!fl_longest_match && match)
- break;
- else /* (fl_longest_match && match) || (!fl_search && !match) */
- {
- if (mctx->state_log == NULL)
- break;
- else
- {
- int max = mctx->state_log_top;
- for (; cur_str_idx <= max; ++cur_str_idx)
- if (mctx->state_log[cur_str_idx] != NULL)
- break;
- if (cur_str_idx > max)
- break;
- }
- }
- }
-
- if (cur_state != NULL && cur_state->halt)
- {
- /* Reached at a halt state.
- Check the halt state can satisfy the current context. */
- if (!cur_state->has_constraint
- || check_halt_state_context (preg, cur_state, mctx,
- re_string_cur_idx (mctx->input)))
- {
- /* We found an appropriate halt state. */
- match_last = re_string_cur_idx (mctx->input);
- match = 1;
- if (!fl_longest_match)
- break;
- }
- }
- }
- return match_last;
-}
-
-/* Check NODE match the current context. */
-
-static int check_halt_node_context (dfa, node, context)
- const re_dfa_t *dfa;
- int node;
- unsigned int context;
-{
- int entity;
- re_token_type_t type = dfa->nodes[node].type;
- if (type == END_OF_RE)
- return 1;
- if (type != OP_CONTEXT_NODE)
- return 0;
- entity = dfa->nodes[node].opr.ctx_info->entity;
- if (dfa->nodes[entity].type != END_OF_RE
- || NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[node].constraint, context))
- return 0;
- return 1;
-}
-
-/* Check the halt state STATE match the current context.
- Return 0 if not match, if the node, STATE has, is a halt node and
- match the context, return the node. */
-
-static int
-check_halt_state_context (preg, state, mctx, idx)
- const regex_t *preg;
- const re_dfastate_t *state;
- const re_match_context_t *mctx;
- int idx;
-{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- int i;
- unsigned int context;
-#ifdef DEBUG
- assert (state->halt);
-#endif
- context = re_string_context_at (mctx->input, idx, mctx->eflags,
- preg->newline_anchor);
- for (i = 0; i < state->nodes.nelem; ++i)
- if (check_halt_node_context (dfa, state->nodes.elems[i], context))
- return state->nodes.elems[i];
- return 0;
-}
-
-/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA
- corresponding to the DFA).
- Return the destination node, and update EPS_VIA_NODES, return -1 in case
- of errors. */
-
-static int
-proceed_next_node (preg, nregs, regs, mctx, pidx, node, eps_via_nodes, fs)
- const regex_t *preg;
- regmatch_t *regs;
- const re_match_context_t *mctx;
- int nregs, *pidx, node;
- re_node_set *eps_via_nodes;
- struct re_fail_stack_t *fs;
-{
- re_dfa_t *dfa = (re_dfa_t *)preg->buffer;
- int i, err, dest_node, cur_entity;
- dest_node = -1;
- cur_entity = ((dfa->nodes[node].type == OP_CONTEXT_NODE)
- ? dfa->nodes[node].opr.ctx_info->entity : node);
- if (IS_EPSILON_NODE (dfa->nodes[node].type))
- {
- int ndest, dest_nodes[2], dest_entities[2];
- err = re_node_set_insert (eps_via_nodes, node);
- if (BE (err < 0, 0))
- return -1;
- /* Pick up valid destinations. */
- for (ndest = 0, i = 0; i < mctx->state_log[*pidx]->nodes.nelem; ++i)
- {
- int candidate = mctx->state_log[*pidx]->nodes.elems[i];
- int entity;
- entity = ((dfa->nodes[candidate].type == OP_CONTEXT_NODE)
- ? dfa->nodes[candidate].opr.ctx_info->entity : candidate);
- if (!re_node_set_contains (dfa->edests + node, entity))
- continue;
- dest_nodes[0] = (ndest == 0) ? candidate : dest_nodes[0];
- dest_entities[0] = (ndest == 0) ? entity : dest_entities[0];
- dest_nodes[1] = (ndest == 1) ? candidate : dest_nodes[1];
- dest_entities[1] = (ndest == 1) ? entity : dest_entities[1];
- ++ndest;
- }
- if (ndest <= 1)
- return ndest == 0 ? -1 : (ndest == 1 ? dest_nodes[0] : 0);
- if (dest_entities[0] > dest_entities[1])
- {
- int swap_work = dest_nodes[0];
- dest_nodes[0] = dest_nodes[1];
- dest_nodes[1] = swap_work;
- }
- /* In order to avoid infinite loop like "(a*)*". */
- if (re_node_set_contains (eps_via_nodes, dest_nodes[0]))
- return dest_nodes[1];
- if (fs != NULL)
- push_fail_stack (fs, *pidx, dest_nodes, nregs, regs, eps_via_nodes);
- return dest_nodes[0];
- }
- else
- {
- int naccepted = 0, entity = node;
- re_token_type_t type = dfa->nodes[node].type;
- if (type == OP_CONTEXT_NODE)
- {
- entity = dfa->nodes[node].opr.ctx_info->entity;
- type = dfa->nodes[entity].type;
- }
-
-#ifdef RE_ENABLE_I18N
- if (ACCEPT_MB_NODE (type))
- naccepted = check_node_accept_bytes (preg, entity, mctx->input, *pidx);
- else
-#endif /* RE_ENABLE_I18N */
- if (type == OP_BACK_REF)
- {
- int subexp_idx = dfa->nodes[entity].opr.idx;
- naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so;
- if (fs != NULL)
- {
- if (regs[subexp_idx].rm_so == -1 || regs[subexp_idx].rm_eo == -1)
- return -1;
- else if (naccepted)
- {
- char *buf = re_string_get_buffer (mctx->input);
- if (strncmp (buf + regs[subexp_idx].rm_so, buf + *pidx,
- naccepted) != 0)
- return -1;
- }
- }
-
- if (naccepted == 0)
- {
- err = re_node_set_insert (eps_via_nodes, node);
- if (BE (err < 0, 0))
- return -2;
- dest_node = dfa->nexts[node];
- if (re_node_set_contains (&mctx->state_log[*pidx]->nodes,
- dest_node))
- return dest_node;
- for (i = 0; i < mctx->state_log[*pidx]->nodes.nelem; ++i)
- {
- dest_node = mctx->state_log[*pidx]->nodes.elems[i];
- if ((dfa->nodes[dest_node].type == OP_CONTEXT_NODE
- && (dfa->nexts[node]
- == dfa->nodes[dest_node].opr.ctx_info->entity)))
- return dest_node;
- }
- }
- }
-
- if (naccepted != 0
- || check_node_accept (preg, dfa->nodes + node, mctx, *pidx))
- {
- dest_node = dfa->nexts[node];
- *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted;
- if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL
- || !re_node_set_contains (&mctx->state_log[*pidx]->nodes,
- dest_node)))
- return -1;
- re_node_set_empty (eps_via_nodes);
- return dest_node;
- }
- }
- return -1;
-}
-
-static reg_errcode_t
-push_fail_stack (fs, str_idx, dests, nregs, regs, eps_via_nodes)
- struct re_fail_stack_t *fs;
- int str_idx, *dests, nregs;
- regmatch_t *regs;
- re_node_set *eps_via_nodes;
-{
- reg_errcode_t err;
- int num = fs->num++;
- if (fs->num == fs->alloc)
- {
- fs->alloc *= 2;
- fs->stack = realloc (fs->stack, (sizeof (struct re_fail_stack_ent_t)
- * fs->alloc));
- if (fs->stack == NULL)
- return REG_ESPACE;
- }
- fs->stack[num].idx = str_idx;
- fs->stack[num].node = dests[1];
- fs->stack[num].regs = re_malloc (regmatch_t, nregs);
- memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs);
- err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes);
- return err;
-}
-
-static int
-pop_fail_stack (fs, pidx, nregs, regs, eps_via_nodes)
- struct re_fail_stack_t *fs;
- int *pidx, nregs;
- regmatch_t *regs;
- re_node_set *eps_via_nodes;
-{
- int num = --fs->num;
- assert (num >= 0);
- *pidx = fs->stack[num].idx;
- memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs);
- re_node_set_free (eps_via_nodes);
- *eps_via_nodes = fs->stack[num].eps_via_nodes;
- return fs->stack[num].node;
-}
-
-/* Set the positions where the subexpressions are starts/ends to registers
- PMATCH.
- Note: We assume that pmatch[0] is already set, and
- pmatch[i].rm_so == pmatch[i].rm_eo == -1 (i > 1). */
-
-static reg_errcode_t
-set_regs (preg, mctx, nmatch, pmatch, fl_backtrack)
- const regex_t *preg;
- const re_match_context_t *mctx;
- size_t nmatch;
- regmatch_t *pmatch;
- int fl_backtrack;
-{
- re_dfa_t *dfa = (re_dfa_t *)preg->buffer;
- int idx, cur_node, real_nmatch;
- re_node_set eps_via_nodes;
- struct re_fail_stack_t *fs;
- struct re_fail_stack_t fs_body = {0, 2, NULL};
-#ifdef DEBUG
- assert (nmatch > 1);
- assert (mctx->state_log != NULL);
-#endif
- if (fl_backtrack)
- {
- fs = &fs_body;
- fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc);
- }
- else
- fs = NULL;
- cur_node = dfa->init_node;
- real_nmatch = (nmatch <= preg->re_nsub) ? nmatch : preg->re_nsub + 1;
- re_node_set_init_empty (&eps_via_nodes);
- for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;)
- {
- update_regs (dfa, pmatch, cur_node, idx, real_nmatch);
- if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node)
- {
- int reg_idx;
- if (fs)
- {
- for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
- if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1)
- break;
- if (reg_idx == nmatch)
- return REG_NOERROR;
- cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
- &eps_via_nodes);
- }
- else
- return REG_NOERROR;
- }
-
- /* Proceed to next node. */
- cur_node = proceed_next_node (preg, nmatch, pmatch, mctx, &idx, cur_node,
- &eps_via_nodes, fs);
-
- if (BE (cur_node < 0, 0))
- {
- if (cur_node == -2)
- return REG_ESPACE;
- if (fs)
- cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
- &eps_via_nodes);
- else
- return REG_NOMATCH;
- }
- }
- re_node_set_free (&eps_via_nodes);
- return REG_NOERROR;
-}
-
-static void
-update_regs (dfa, pmatch, cur_node, cur_idx, nmatch)
- re_dfa_t *dfa;
- regmatch_t *pmatch;
- int cur_node, cur_idx, nmatch;
-{
- int type = dfa->nodes[cur_node].type;
- int reg_num;
- if (type != OP_OPEN_SUBEXP && type != OP_CLOSE_SUBEXP)
- return;
- reg_num = dfa->nodes[cur_node].opr.idx + 1;
- if (reg_num >= nmatch)
- return;
- if (type == OP_OPEN_SUBEXP)
- {
- /* We are at the first node of this sub expression. */
- pmatch[reg_num].rm_so = cur_idx;
- pmatch[reg_num].rm_eo = -1;
- }
- else if (type == OP_CLOSE_SUBEXP)
- /* We are at the first node of this sub expression. */
- pmatch[reg_num].rm_eo = cur_idx;
-}
-
-#define NUMBER_OF_STATE 1
-
-/* This function checks the STATE_LOG from the SCTX->last_str_idx to 0
- and sift the nodes in each states according to the following rules.
- Updated state_log will be wrote to STATE_LOG.
-
- Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if...
- 1. When STR_IDX == MATCH_LAST(the last index in the state_log):
- If `a' isn't the LAST_NODE and `a' can't epsilon transit to
- the LAST_NODE, we throw away the node `a'.
- 2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts
- string `s' and transit to `b':
- i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw
- away the node `a'.
- ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is
- throwed away, we throw away the node `a'.
- 3. When 0 <= STR_IDX < n and 'a' epsilon transit to 'b':
- i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the
- node `a'.
- ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is throwed away,
- we throw away the node `a'. */
-
-#define STATE_NODE_CONTAINS(state,node) \
- ((state) != NULL && re_node_set_contains (&(state)->nodes, node))
-
-static reg_errcode_t
-sift_states_backward (preg, mctx, sctx)
- const regex_t *preg;
- re_match_context_t *mctx;
- re_sift_context_t *sctx;
-{
- reg_errcode_t err;
- re_dfa_t *dfa = (re_dfa_t *)preg->buffer;
- int null_cnt = 0;
- int str_idx = sctx->last_str_idx;
- re_node_set cur_dest;
- re_node_set *cur_src; /* Points the state_log[str_idx]->nodes */
-
-#ifdef DEBUG
- assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL);
-#endif
- cur_src = &mctx->state_log[str_idx]->nodes;
-
- /* Build sifted state_log[str_idx]. It has the nodes which can epsilon
- transit to the last_node and the last_node itself. */
- err = re_node_set_init_1 (&cur_dest, sctx->last_node);
- if (BE (err != REG_NOERROR, 0))
- return err;
- err = update_cur_sifted_state (preg, mctx, sctx, str_idx, &cur_dest);
- if (BE (err != REG_NOERROR, 0))
- return err;
-
- /* Then check each states in the state_log. */
- while (str_idx > 0)
- {
- int i, ret;
- /* Update counters. */
- null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0;
- if (null_cnt > mctx->max_mb_elem_len)
- {
- memset (sctx->sifted_states, '\0',
- sizeof (re_dfastate_t *) * str_idx);
- return REG_NOERROR;
- }
- re_node_set_empty (&cur_dest);
- --str_idx;
- cur_src = ((mctx->state_log[str_idx] == NULL) ? &empty_set
- : &mctx->state_log[str_idx]->nodes);
-
- /* Then build the next sifted state.
- We build the next sifted state on `cur_dest', and update
- `sifted_states[str_idx]' with `cur_dest'.
- Note:
- `cur_dest' is the sifted state from `state_log[str_idx + 1]'.
- `cur_src' points the node_set of the old `state_log[str_idx]'. */
- for (i = 0; i < cur_src->nelem; i++)
- {
- int prev_node = cur_src->elems[i];
- int entity = prev_node;
- int naccepted = 0;
- re_token_type_t type = dfa->nodes[prev_node].type;
-
- if (IS_EPSILON_NODE(type))
- continue;
- if (type == OP_CONTEXT_NODE)
- {
- entity = dfa->nodes[prev_node].opr.ctx_info->entity;
- type = dfa->nodes[entity].type;
- }
-#ifdef RE_ENABLE_I18N
- /* If the node may accept `multi byte'. */
- if (ACCEPT_MB_NODE (type))
- naccepted = sift_states_iter_mb (preg, mctx, sctx, entity, str_idx,
- sctx->last_str_idx);
-
-#endif /* RE_ENABLE_I18N */
- /* We don't check backreferences here.
- See update_cur_sifted_state(). */
-
- if (!naccepted
- && check_node_accept (preg, dfa->nodes + prev_node, mctx,
- str_idx)
- && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1],
- dfa->nexts[prev_node]))
- naccepted = 1;
-
- if (naccepted == 0)
- continue;
-
- if (sctx->limits.nelem)
- {
- int to_idx = str_idx + naccepted;
- if (check_dst_limits (dfa, &sctx->limits, mctx,
- dfa->nexts[prev_node], to_idx,
- prev_node, str_idx))
- continue;
- }
- ret = re_node_set_insert (&cur_dest, prev_node);
- if (BE (ret == -1, 0))
- return err;
- }
-
- /* Add all the nodes which satisfy the following conditions:
- - It can epsilon transit to a node in CUR_DEST.
- - It is in CUR_SRC.
- And update state_log. */
- err = update_cur_sifted_state (preg, mctx, sctx, str_idx, &cur_dest);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
-
- re_node_set_free (&cur_dest);
- return REG_NOERROR;
-}
-
-/* Helper functions. */
-
-static inline reg_errcode_t
-clean_state_log_if_need (mctx, next_state_log_idx)
- re_match_context_t *mctx;
- int next_state_log_idx;
-{
- int top = mctx->state_log_top;
-
- if (next_state_log_idx >= mctx->input->bufs_len
- || (next_state_log_idx >= mctx->input->valid_len
- && mctx->input->valid_len < mctx->input->len))
- {
- reg_errcode_t err;
- err = extend_buffers (mctx);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
-
- if (top < next_state_log_idx)
- {
- memset (mctx->state_log + top + 1, '\0',
- sizeof (re_dfastate_t *) * (next_state_log_idx - top));
- mctx->state_log_top = next_state_log_idx;
- }
- return REG_NOERROR;
-}
-
-static reg_errcode_t merge_state_array (dfa, dst, src, num)
- re_dfa_t *dfa;
- re_dfastate_t **dst;
- re_dfastate_t **src;
- int num;
-{
- int st_idx;
- reg_errcode_t err;
- for (st_idx = 0; st_idx < num; ++st_idx)
- {
- if (dst[st_idx] == NULL)
- dst[st_idx] = src[st_idx];
- else if (src[st_idx] != NULL)
- {
- re_node_set merged_set;
- err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes,
- &src[st_idx]->nodes);
- if (BE (err != REG_NOERROR, 0))
- return err;
- dst[st_idx] = re_acquire_state (&err, dfa, &merged_set);
- if (BE (err != REG_NOERROR, 0))
- return err;
- re_node_set_free (&merged_set);
- }
- }
- return REG_NOERROR;
-}
-
-static reg_errcode_t
-update_cur_sifted_state (preg, mctx, sctx, str_idx, dest_nodes)
- const regex_t *preg;
- re_match_context_t *mctx;
- re_sift_context_t *sctx;
- int str_idx;
- re_node_set *dest_nodes;
-{
- reg_errcode_t err;
- re_dfa_t *dfa = (re_dfa_t *)preg->buffer;
- const re_node_set *candidates;
- candidates = ((mctx->state_log[str_idx] == NULL) ? &empty_set
- : &mctx->state_log[str_idx]->nodes);
-
- /* At first, add the nodes which can epsilon transit to a node in
- DEST_NODE. */
- err = add_epsilon_src_nodes (dfa, dest_nodes, candidates);
- if (BE (err != REG_NOERROR, 0))
- return err;
-
- /* Then, check the limitations in the current sift_context. */
- if (sctx->limits.nelem)
- {
- err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits,
- mctx->bkref_ents, str_idx);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
-
- /* Update state_log. */
- sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes);
- if (BE (sctx->sifted_states[str_idx] == NULL && err != REG_NOERROR, 0))
- return err;
-
- /* If we are searching for the subexpression candidates.
- Note that we were from transit_state_bkref_loop() in this case. */
- if (sctx->check_subexp)
- {
- err = search_subexp (preg, mctx, sctx, str_idx, dest_nodes);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
-
- if ((mctx->state_log[str_idx] != NULL
- && mctx->state_log[str_idx]->has_backref))
- {
- err = sift_states_bkref (preg, mctx, sctx, str_idx, dest_nodes);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- return REG_NOERROR;
-}
-
-static reg_errcode_t
-add_epsilon_src_nodes (dfa, dest_nodes, candidates)
- re_dfa_t *dfa;
- re_node_set *dest_nodes;
- const re_node_set *candidates;
-{
- reg_errcode_t err;
- int src_idx;
- re_node_set src_copy;
-
- err = re_node_set_init_copy (&src_copy, dest_nodes);
- if (BE (err != REG_NOERROR, 0))
- return err;
- for (src_idx = 0; src_idx < src_copy.nelem; ++src_idx)
- {
- err = re_node_set_add_intersect (dest_nodes, candidates,
- dfa->inveclosures
- + src_copy.elems[src_idx]);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- re_node_set_free (&src_copy);
- return REG_NOERROR;
-}
-
-static reg_errcode_t
-sub_epsilon_src_nodes (dfa, node, dest_nodes, candidates)
- re_dfa_t *dfa;
- int node;
- re_node_set *dest_nodes;
- const re_node_set *candidates;
-{
- int ecl_idx;
- reg_errcode_t err;
- re_node_set *inv_eclosure = dfa->inveclosures + node;
- re_node_set except_nodes;
- re_node_set_init_empty (&except_nodes);
- for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)
- {
- int cur_node = inv_eclosure->elems[ecl_idx];
- if (cur_node == node)
- continue;
- if (dfa->edests[cur_node].nelem)
- {
- int edst1 = dfa->edests[cur_node].elems[0];
- int edst2 = ((dfa->edests[cur_node].nelem > 1)
- ? dfa->edests[cur_node].elems[1] : -1);
- if ((!re_node_set_contains (inv_eclosure, edst1)
- && re_node_set_contains (dest_nodes, edst1))
- || (edst2 > 0
- && !re_node_set_contains (inv_eclosure, edst2)
- && re_node_set_contains (dest_nodes, edst2)))
- {
- err = re_node_set_add_intersect (&except_nodes, candidates,
- dfa->inveclosures + cur_node);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- }
- }
- for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)
- {
- int cur_node = inv_eclosure->elems[ecl_idx];
- if (!re_node_set_contains (&except_nodes, cur_node))
- {
- int idx = re_node_set_contains (dest_nodes, cur_node) - 1;
- re_node_set_remove_at (dest_nodes, idx);
- }
- }
- re_node_set_free (&except_nodes);
- return REG_NOERROR;
-}
-
-static int
-check_dst_limits (dfa, limits, mctx, dst_node, dst_idx, src_node, src_idx)
- re_dfa_t *dfa;
- re_node_set *limits;
- re_match_context_t *mctx;
- int dst_node, dst_idx, src_node, src_idx;
-{
- int lim_idx, src_pos, dst_pos;
-
- for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)
- {
- int bkref, subexp_idx/*, node_idx, cls_node*/;
- struct re_backref_cache_entry *ent;
- ent = mctx->bkref_ents + limits->elems[lim_idx];
- bkref = (dfa->nodes[ent->node].type == OP_CONTEXT_NODE
- ? dfa->nodes[ent->node].opr.ctx_info->entity : ent->node);
- subexp_idx = dfa->nodes[bkref].opr.idx - 1;
-
- dst_pos = check_dst_limits_calc_pos (dfa, mctx, limits->elems[lim_idx],
- dfa->eclosures + dst_node,
- subexp_idx, dst_node, dst_idx);
- src_pos = check_dst_limits_calc_pos (dfa, mctx, limits->elems[lim_idx],
- dfa->eclosures + src_node,
- subexp_idx, src_node, src_idx);
-
- /* In case of:
- <src> <dst> ( <subexp> )
- ( <subexp> ) <src> <dst>
- ( <subexp1> <src> <subexp2> <dst> <subexp3> ) */
- if (src_pos == dst_pos)
- continue; /* This is unrelated limitation. */
- else
- return 1;
- }
- return 0;
-}
-
-static int
-check_dst_limits_calc_pos (dfa, mctx, limit, eclosures, subexp_idx, node,
- str_idx)
- re_dfa_t *dfa;
- re_match_context_t *mctx;
- re_node_set *eclosures;
- int limit, subexp_idx, node, str_idx;
-{
- struct re_backref_cache_entry *lim = mctx->bkref_ents + limit;
- int pos = (str_idx < lim->subexp_from ? -1
- : (lim->subexp_to < str_idx ? 1 : 0));
- if (pos == 0
- && (str_idx == lim->subexp_from || str_idx == lim->subexp_to))
- {
- int node_idx;
- for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx)
- {
- int node = eclosures->elems[node_idx];
- int entity = node;
- re_token_type_t type= dfa->nodes[node].type;
- if (type == OP_CONTEXT_NODE)
- {
- entity = dfa->nodes[node].opr.ctx_info->entity;
- type = dfa->nodes[entity].type;
- }
- if (type == OP_BACK_REF)
- {
- int bi;
- for (bi = 0; bi < mctx->nbkref_ents; ++bi)
- {
- struct re_backref_cache_entry *ent = mctx->bkref_ents + bi;
- if (ent->node == node && ent->subexp_from == ent->subexp_to
- && ent->str_idx == str_idx)
- {
- int cpos, dst;
- dst = dfa->nexts[node];
- cpos = check_dst_limits_calc_pos (dfa, mctx, limit,
- dfa->eclosures + dst,
- subexp_idx, dst,
- str_idx);
- if ((str_idx == lim->subexp_from && cpos == -1)
- || (str_idx == lim->subexp_to && cpos == 0))
- return cpos;
- }
- }
- }
- if (type == OP_OPEN_SUBEXP && subexp_idx == dfa->nodes[node].opr.idx
- && str_idx == lim->subexp_from)
- {
- pos = -1;
- break;
- }
- if (type == OP_CLOSE_SUBEXP && subexp_idx == dfa->nodes[node].opr.idx
- && str_idx == lim->subexp_to)
- break;
- }
- if (node_idx == eclosures->nelem && str_idx == lim->subexp_to)
- pos = 1;
- }
- return pos;
-}
-
-/* Check the limitations of sub expressions LIMITS, and remove the nodes
- which are against limitations from DEST_NODES. */
-
-static reg_errcode_t
-check_subexp_limits (dfa, dest_nodes, candidates, limits, bkref_ents, str_idx)
- re_dfa_t *dfa;
- re_node_set *dest_nodes;
- const re_node_set *candidates;
- re_node_set *limits;
- struct re_backref_cache_entry *bkref_ents;
- int str_idx;
-{
- reg_errcode_t err;
- int node_idx, lim_idx;
-
- for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)
- {
- int bkref, subexp_idx;
- struct re_backref_cache_entry *ent;
- ent = bkref_ents + limits->elems[lim_idx];
-
- if (str_idx <= ent->subexp_from || ent->str_idx < str_idx)
- continue; /* This is unrelated limitation. */
-
- bkref = (dfa->nodes[ent->node].type == OP_CONTEXT_NODE
- ? dfa->nodes[ent->node].opr.ctx_info->entity : ent->node);
- subexp_idx = dfa->nodes[bkref].opr.idx - 1;
-
- if (ent->subexp_to == str_idx)
- {
- int ops_node = -1;
- int cls_node = -1;
- for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
- {
- int node = dest_nodes->elems[node_idx];
- re_token_type_t type= dfa->nodes[node].type;
- if (type == OP_OPEN_SUBEXP
- && subexp_idx == dfa->nodes[node].opr.idx)
- ops_node = node;
- else if (type == OP_CLOSE_SUBEXP
- && subexp_idx == dfa->nodes[node].opr.idx)
- cls_node = node;
- }
-
- /* Check the limitation of the open subexpression. */
- /* Note that (ent->subexp_to = str_idx != ent->subexp_from). */
- if (ops_node >= 0)
- {
- err = sub_epsilon_src_nodes(dfa, ops_node, dest_nodes,
- candidates);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- /* Check the limitation of the close subexpression. */
- for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
- {
- int node = dest_nodes->elems[node_idx];
- if (!re_node_set_contains (dfa->inveclosures + node, cls_node)
- && !re_node_set_contains (dfa->eclosures + node, cls_node))
- {
- /* It is against this limitation.
- Remove it form the current sifted state. */
- err = sub_epsilon_src_nodes(dfa, node, dest_nodes,
- candidates);
- if (BE (err != REG_NOERROR, 0))
- return err;
- --node_idx;
- }
- }
- }
- else /* (ent->subexp_to != str_idx) */
- {
- for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
- {
- int node = dest_nodes->elems[node_idx];
- re_token_type_t type= dfa->nodes[node].type;
- if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP)
- {
- if (subexp_idx != dfa->nodes[node].opr.idx)
- continue;
- if ((type == OP_CLOSE_SUBEXP && ent->subexp_to != str_idx)
- || (type == OP_OPEN_SUBEXP))
- {
- /* It is against this limitation.
- Remove it form the current sifted state. */
- err = sub_epsilon_src_nodes(dfa, node, dest_nodes,
- candidates);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- }
- }
- }
- }
- return REG_NOERROR;
-}
-
-/* Search for the top (in case of sctx->check_subexp < 0) or the
- bottom (in case of sctx->check_subexp > 0) of the subexpressions
- which the backreference sctx->cur_bkref can match. */
-
-static reg_errcode_t
-search_subexp (preg, mctx, sctx, str_idx, dest_nodes)
- const regex_t *preg;
- re_match_context_t *mctx;
- re_sift_context_t *sctx;
- int str_idx;
- re_node_set *dest_nodes;
-{
- reg_errcode_t err;
- re_dfa_t *dfa = (re_dfa_t *)preg->buffer;
- re_sift_context_t local_sctx;
- int node_idx, node=0; /* gnupg */
- const re_node_set *candidates;
- re_dfastate_t **lim_states = NULL;
- candidates = ((mctx->state_log[str_idx] == NULL) ? &empty_set
- : &mctx->state_log[str_idx]->nodes);
- local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized. */
-
- for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
- {
- re_token_type_t type;
- int entity;
- node = dest_nodes->elems[node_idx];
- type = dfa->nodes[node].type;
- entity = (type != OP_CONTEXT_NODE ? node
- : dfa->nodes[node].opr.ctx_info->entity);
- type = (type != OP_CONTEXT_NODE ? type : dfa->nodes[entity].type);
-
- if (type == OP_CLOSE_SUBEXP
- && sctx->check_subexp == dfa->nodes[node].opr.idx + 1)
- {
- re_dfastate_t *cur_state;
- /* Found the bottom of the subexpression, then search for the
- top of it. */
- if (local_sctx.sifted_states == NULL)
- {
- /* It hasn't been initialized yet, initialize it now. */
- local_sctx = *sctx;
- err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- local_sctx.check_subexp = -sctx->check_subexp;
- local_sctx.limited_states = sctx->limited_states;
- local_sctx.last_node = node;
- local_sctx.last_str_idx = local_sctx.cls_subexp_idx = str_idx;
- cur_state = local_sctx.sifted_states[str_idx];
- err = sift_states_backward (preg, mctx, &local_sctx);
- local_sctx.sifted_states[str_idx] = cur_state;
- if (BE (err != REG_NOERROR, 0))
- return err;
- /* There must not 2 same node in a node set. */
- break;
- }
- else if (type == OP_OPEN_SUBEXP
- && -sctx->check_subexp == dfa->nodes[node].opr.idx + 1)
- {
- /* Found the top of the subexpression, check that the
- backreference can match the input string. */
- char *buf;
- int dest_str_idx;
- int bkref_str_idx = re_string_cur_idx (mctx->input);
- int subexp_len = sctx->cls_subexp_idx - str_idx;
- if (subexp_len < 0 || bkref_str_idx + subexp_len > mctx->input->len)
- break;
-
- if (bkref_str_idx + subexp_len > mctx->input->valid_len
- && mctx->input->valid_len < mctx->input->len)
- {
- reg_errcode_t err;
- err = extend_buffers (mctx);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- buf = (char *) re_string_get_buffer (mctx->input);
- if (strncmp (buf + str_idx, buf + bkref_str_idx, subexp_len) != 0)
- break;
-
- if (sctx->limits.nelem && str_idx > 0)
- {
- re_dfastate_t *cur_state = sctx->sifted_states[str_idx];
- if (lim_states == NULL)
- {
- lim_states = re_malloc (re_dfastate_t *, str_idx + 1);
- }
- if (local_sctx.sifted_states == NULL)
- {
- /* It hasn't been initialized yet, initialize it now. */
- local_sctx = *sctx;
- if (BE (lim_states == NULL, 0))
- return REG_ESPACE;
- err = re_node_set_init_copy (&local_sctx.limits,
- &sctx->limits);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- local_sctx.check_subexp = 0;
- local_sctx.last_node = node;
- local_sctx.last_str_idx = str_idx;
- local_sctx.limited_states = lim_states;
- memset (lim_states, '\0',
- sizeof (re_dfastate_t*) * (str_idx + 1));
- err = sift_states_backward (preg, mctx, &local_sctx);
- if (BE (err != REG_NOERROR, 0))
- return err;
- if (local_sctx.sifted_states[0] == NULL
- && local_sctx.limited_states[0] == NULL)
- {
- sctx->sifted_states[str_idx] = cur_state;
- break;
- }
- sctx->sifted_states[str_idx] = cur_state;
- }
- /* Successfully matched, add a new cache entry. */
- dest_str_idx = bkref_str_idx + subexp_len;
- err = match_ctx_add_entry (mctx, sctx->cur_bkref, bkref_str_idx,
- str_idx, sctx->cls_subexp_idx);
- if (BE (err != REG_NOERROR, 0))
- return err;
- err = clean_state_log_if_need (mctx, dest_str_idx);
- if (BE (err != REG_NOERROR, 0))
- return err;
- break;
- }
- }
-
- /* Remove the top/bottom of the sub expression we processed. */
- if (node_idx < dest_nodes->nelem)
- {
- err = sub_epsilon_src_nodes(dfa, node, dest_nodes, candidates);
- if (BE (err != REG_NOERROR, 0))
- return err;
- /* Update state_log. */
- sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
-
- if (local_sctx.sifted_states != NULL)
- re_node_set_free (&local_sctx.limits);
- if (lim_states != NULL)
- re_free (lim_states);
- return REG_NOERROR;
-}
-
-static reg_errcode_t
-sift_states_bkref (preg, mctx, sctx, str_idx, dest_nodes)
- const regex_t *preg;
- re_match_context_t *mctx;
- re_sift_context_t *sctx;
- int str_idx;
- re_node_set *dest_nodes;
-{
- reg_errcode_t err;
- re_dfa_t *dfa = (re_dfa_t *)preg->buffer;
- int node_idx, node;
- re_sift_context_t local_sctx;
- const re_node_set *candidates;
- candidates = ((mctx->state_log[str_idx] == NULL) ? &empty_set
- : &mctx->state_log[str_idx]->nodes);
- local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized. */
-
- for (node_idx = 0; node_idx < candidates->nelem; ++node_idx)
- {
- int entity;
- int cur_bkref_idx = re_string_cur_idx (mctx->input);
- re_token_type_t type;
- node = candidates->elems[node_idx];
- type = dfa->nodes[node].type;
- entity = (type != OP_CONTEXT_NODE ? node
- : dfa->nodes[node].opr.ctx_info->entity);
- type = (type != OP_CONTEXT_NODE ? type : dfa->nodes[entity].type);
- if (node == sctx->cur_bkref && str_idx == cur_bkref_idx)
- continue;
- /* Avoid infinite loop for the REs like "()\1+". */
- if (node == sctx->last_node && str_idx == sctx->last_str_idx)
- continue;
- if (type == OP_BACK_REF)
- {
- int enabled_idx;
- for (enabled_idx = 0; enabled_idx < mctx->nbkref_ents; ++enabled_idx)
- {
- int disabled_idx, subexp_len, to_idx;
- struct re_backref_cache_entry *entry;
- entry = mctx->bkref_ents + enabled_idx;
- subexp_len = entry->subexp_to - entry->subexp_from;
- to_idx = str_idx + subexp_len;
-
- if (entry->node != node || entry->str_idx != str_idx
- || to_idx > sctx->last_str_idx
- || sctx->sifted_states[to_idx] == NULL)
- continue;
- if (!STATE_NODE_CONTAINS (sctx->sifted_states[to_idx],
- dfa->nexts[node]))
- {
- int dst_idx;
- re_node_set *dsts = &sctx->sifted_states[to_idx]->nodes;
- for (dst_idx = 0; dst_idx < dsts->nelem; ++dst_idx)
- {
- int dst_node = dsts->elems[dst_idx];
- if (dfa->nodes[dst_node].type == OP_CONTEXT_NODE
- && (dfa->nodes[dst_node].opr.ctx_info->entity
- == dfa->nexts[node]))
- break;
- }
- if (dst_idx == dsts->nelem)
- continue;
- }
-
- if (check_dst_limits (dfa, &sctx->limits, mctx, node,
- str_idx, dfa->nexts[node], to_idx))
- continue;
- if (sctx->check_subexp == dfa->nodes[entity].opr.idx)
- {
- char *buf;
- buf = (char *) re_string_get_buffer (mctx->input);
- if (strncmp (buf + entry->subexp_from,
- buf + cur_bkref_idx, subexp_len) != 0)
- continue;
- err = match_ctx_add_entry (mctx, sctx->cur_bkref,
- cur_bkref_idx, entry->subexp_from,
- entry->subexp_to);
- if (BE (err != REG_NOERROR, 0))
- return err;
- err = clean_state_log_if_need (mctx, cur_bkref_idx
- + subexp_len);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- else
- {
- re_dfastate_t *cur_state;
- entry->flag = 0;
- for (disabled_idx = enabled_idx + 1;
- disabled_idx < mctx->nbkref_ents; ++disabled_idx)
- {
- struct re_backref_cache_entry *entry2;
- entry2 = mctx->bkref_ents + disabled_idx;
- if (entry2->node != node || entry2->str_idx != str_idx)
- continue;
- entry2->flag = 1;
- }
-
- if (local_sctx.sifted_states == NULL)
- {
- local_sctx = *sctx;
- err = re_node_set_init_copy (&local_sctx.limits,
- &sctx->limits);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- local_sctx.last_node = node;
- local_sctx.last_str_idx = str_idx;
- err = re_node_set_insert (&local_sctx.limits, enabled_idx);
- if (BE (err < 0, 0))
- return REG_ESPACE;
- cur_state = local_sctx.sifted_states[str_idx];
- err = sift_states_backward (preg, mctx, &local_sctx);
- if (BE (err != REG_NOERROR, 0))
- return err;
- if (sctx->limited_states != NULL)
- {
- err = merge_state_array (dfa, sctx->limited_states,
- local_sctx.sifted_states,
- str_idx + 1);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- local_sctx.sifted_states[str_idx] = cur_state;
- re_node_set_remove_at (&local_sctx.limits,
- local_sctx.limits.nelem - 1);
- entry->flag = 1;
- }
- }
- for (enabled_idx = 0; enabled_idx < mctx->nbkref_ents; ++enabled_idx)
- {
- struct re_backref_cache_entry *entry;
- entry = mctx->bkref_ents + enabled_idx;
- if (entry->node == node && entry->str_idx == str_idx)
- entry->flag = 0;
- }
- }
- }
- if (local_sctx.sifted_states != NULL)
- {
- re_node_set_free (&local_sctx.limits);
- }
-
- return REG_NOERROR;
-}
-
-
-#ifdef RE_ENABLE_I18N
-static int
-sift_states_iter_mb (preg, mctx, sctx, node_idx, str_idx, max_str_idx)
- const regex_t *preg;
- const re_match_context_t *mctx;
- re_sift_context_t *sctx;
- int node_idx, str_idx, max_str_idx;
-{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- int naccepted;
- /* Check the node can accept `multi byte'. */
- naccepted = check_node_accept_bytes (preg, node_idx, mctx->input, str_idx);
- if (naccepted > 0 && str_idx + naccepted <= max_str_idx &&
- !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted],
- dfa->nexts[node_idx]))
- /* The node can't accept the `multi byte', or the
- destination was already throwed away, then the node
- could't accept the current input `multi byte'. */
- naccepted = 0;
- /* Otherwise, it is sure that the node could accept
- `naccepted' bytes input. */
- return naccepted;
-}
-#endif /* RE_ENABLE_I18N */
-
-
-/* Functions for state transition. */
-
-/* Return the next state to which the current state STATE will transit by
- accepting the current input byte, and update STATE_LOG if necessary.
- If STATE can accept a multibyte char/collating element/back reference
- update the destination of STATE_LOG. */
-
-static re_dfastate_t *
-transit_state (err, preg, mctx, state, fl_search)
- reg_errcode_t *err;
- const regex_t *preg;
- re_match_context_t *mctx;
- re_dfastate_t *state;
- int fl_search;
-{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- re_dfastate_t **trtable, *next_state;
- unsigned char ch;
-
- if (re_string_cur_idx (mctx->input) + 1 >= mctx->input->bufs_len
- || (re_string_cur_idx (mctx->input) + 1 >= mctx->input->valid_len
- && mctx->input->valid_len < mctx->input->len))
- {
- *err = extend_buffers (mctx);
- if (BE (*err != REG_NOERROR, 0))
- return NULL;
- }
-
- *err = REG_NOERROR;
- if (state == NULL)
- {
- next_state = state;
- re_string_skip_bytes (mctx->input, 1);
- }
- else
- {
-#ifdef RE_ENABLE_I18N
- /* If the current state can accept multibyte. */
- if (state->accept_mb)
- {
- *err = transit_state_mb (preg, state, mctx);
- if (BE (*err != REG_NOERROR, 0))
- return NULL;
- }
-#endif /* RE_ENABLE_I18N */
-
- /* Then decide the next state with the single byte. */
- if (1)
- {
- /* Use transition table */
- ch = re_string_fetch_byte (mctx->input);
- trtable = fl_search ? state->trtable_search : state->trtable;
- if (trtable == NULL)
- {
- trtable = build_trtable (preg, state, fl_search);
- if (fl_search)
- state->trtable_search = trtable;
- else
- state->trtable = trtable;
- }
- next_state = trtable[ch];
- }
- else
- {
- /* don't use transition table */
- next_state = transit_state_sb (err, preg, state, fl_search, mctx);
- if (BE (next_state == NULL && err != REG_NOERROR, 0))
- return NULL;
- }
- }
-
- /* Update the state_log if we need. */
- if (mctx->state_log != NULL)
- {
- int cur_idx = re_string_cur_idx (mctx->input);
- if (cur_idx > mctx->state_log_top)
- {
- mctx->state_log[cur_idx] = next_state;
- mctx->state_log_top = cur_idx;
- }
- else if (mctx->state_log[cur_idx] == 0)
- {
- mctx->state_log[cur_idx] = next_state;
- }
- else
- {
- re_dfastate_t *pstate;
- unsigned int context;
- re_node_set next_nodes, *log_nodes, *table_nodes = NULL;
- /* If (state_log[cur_idx] != 0), it implies that cur_idx is
- the destination of a multibyte char/collating element/
- back reference. Then the next state is the union set of
- these destinations and the results of the transition table. */
- pstate = mctx->state_log[cur_idx];
- log_nodes = pstate->entrance_nodes;
- if (next_state != NULL)
- {
- table_nodes = next_state->entrance_nodes;
- *err = re_node_set_init_union (&next_nodes, table_nodes,
- log_nodes);
- if (BE (*err != REG_NOERROR, 0))
- return NULL;
- }
- else
- next_nodes = *log_nodes;
- /* Note: We already add the nodes of the initial state,
- then we don't need to add them here. */
-
- context = re_string_context_at (mctx->input,
- re_string_cur_idx (mctx->input) - 1,
- mctx->eflags, preg->newline_anchor);
- next_state = mctx->state_log[cur_idx]
- = re_acquire_state_context (err, dfa, &next_nodes, context);
- /* We don't need to check errors here, since the return value of
- this function is next_state and ERR is already set. */
-
- if (table_nodes != NULL)
- re_node_set_free (&next_nodes);
- }
- /* If the next state has back references. */
- if (next_state != NULL && next_state->has_backref)
- {
- *err = transit_state_bkref (preg, next_state, mctx);
- if (BE (*err != REG_NOERROR, 0))
- return NULL;
- next_state = mctx->state_log[cur_idx];
- }
- }
- return next_state;
-}
-
-/* Helper functions for transit_state. */
-
-/* Return the next state to which the current state STATE will transit by
- accepting the current input byte. */
-
-static re_dfastate_t *
-transit_state_sb (err, preg, state, fl_search, mctx)
- reg_errcode_t *err;
- const regex_t *preg;
- re_dfastate_t *state;
- int fl_search;
- re_match_context_t *mctx;
-{
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- re_node_set next_nodes;
- re_dfastate_t *next_state;
- int node_cnt, cur_str_idx = re_string_cur_idx (mctx->input);
- unsigned int context;
-
- *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1);
- if (BE (*err != REG_NOERROR, 0))
- return NULL;
- for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt)
- {
- int cur_node = state->nodes.elems[node_cnt];
- if (check_node_accept (preg, dfa->nodes + cur_node, mctx, cur_str_idx))
- {
- *err = re_node_set_merge (&next_nodes,
- dfa->eclosures + dfa->nexts[cur_node]);
- if (BE (*err != REG_NOERROR, 0))
- return NULL;
- }
- }
- if (fl_search)
- {
-#ifdef RE_ENABLE_I18N
- int not_initial = 0;
- if (MB_CUR_MAX > 1)
- for (node_cnt = 0; node_cnt < next_nodes.nelem; ++node_cnt)
- if (dfa->nodes[next_nodes.elems[node_cnt]].type == CHARACTER)
- {
- not_initial = dfa->nodes[next_nodes.elems[node_cnt]].mb_partial;
- break;
- }
- if (!not_initial)
-#endif
- {
- *err = re_node_set_merge (&next_nodes,
- dfa->init_state->entrance_nodes);
- if (BE (*err != REG_NOERROR, 0))
- return NULL;
- }
- }
- context = re_string_context_at (mctx->input, cur_str_idx, mctx->eflags,
- preg->newline_anchor);
- next_state = re_acquire_state_context (err, dfa, &next_nodes, context);
- /* We don't need to check errors here, since the return value of
- this function is next_state and ERR is already set. */
-
- re_node_set_free (&next_nodes);
- re_string_skip_bytes (mctx->input, 1);
- return next_state;
-}
-
-#ifdef RE_ENABLE_I18N
-static reg_errcode_t
-transit_state_mb (preg, pstate, mctx)
- const regex_t *preg;
- re_dfastate_t *pstate;
- re_match_context_t *mctx;
-{
- reg_errcode_t err;
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- int i;
-
- for (i = 0; i < pstate->nodes.nelem; ++i)
- {
- re_node_set dest_nodes, *new_nodes;
- int cur_node_idx = pstate->nodes.elems[i];
- int naccepted = 0, dest_idx;
- unsigned int context;
- re_dfastate_t *dest_state;
-
- if (dfa->nodes[cur_node_idx].type == OP_CONTEXT_NODE)
- {
- context = re_string_context_at (mctx->input,
- re_string_cur_idx (mctx->input),
- mctx->eflags, preg->newline_anchor);
- if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint,
- context))
- continue;
- cur_node_idx = dfa->nodes[cur_node_idx].opr.ctx_info->entity;
- }
-
- /* How many bytes the node can accepts? */
- if (ACCEPT_MB_NODE (dfa->nodes[cur_node_idx].type))
- naccepted = check_node_accept_bytes (preg, cur_node_idx, mctx->input,
- re_string_cur_idx (mctx->input));
- if (naccepted == 0)
- continue;
-
- /* The node can accepts `naccepted' bytes. */
- dest_idx = re_string_cur_idx (mctx->input) + naccepted;
- mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted
- : mctx->max_mb_elem_len);
- err = clean_state_log_if_need (mctx, dest_idx);
- if (BE (err != REG_NOERROR, 0))
- return err;
-#ifdef DEBUG
- assert (dfa->nexts[cur_node_idx] != -1);
-#endif
- /* `cur_node_idx' may point the entity of the OP_CONTEXT_NODE,
- then we use pstate->nodes.elems[i] instead. */
- new_nodes = dfa->eclosures + dfa->nexts[pstate->nodes.elems[i]];
-
- dest_state = mctx->state_log[dest_idx];
- if (dest_state == NULL)
- dest_nodes = *new_nodes;
- else
- {
- err = re_node_set_init_union (&dest_nodes,
- dest_state->entrance_nodes, new_nodes);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- context = re_string_context_at (mctx->input, dest_idx - 1, mctx->eflags,
- preg->newline_anchor);
- mctx->state_log[dest_idx]
- = re_acquire_state_context (&err, dfa, &dest_nodes, context);
- if (BE (mctx->state_log[dest_idx] == NULL && err != REG_NOERROR, 0))
- return err;
- if (dest_state != NULL)
- re_node_set_free (&dest_nodes);
- }
- return REG_NOERROR;
-}
-#endif /* RE_ENABLE_I18N */
-
-static reg_errcode_t
-transit_state_bkref (preg, pstate, mctx)
- const regex_t *preg;
- re_dfastate_t *pstate;
- re_match_context_t *mctx;
-{
- reg_errcode_t err;
- re_dfastate_t **work_state_log;
-
- work_state_log = re_malloc (re_dfastate_t *,
- re_string_cur_idx (mctx->input) + 1);
- if (BE (work_state_log == NULL, 0))
- return REG_ESPACE;
-
- err = transit_state_bkref_loop (preg, &pstate->nodes, work_state_log, mctx);
- re_free (work_state_log);
- return err;
-}
-
-/* Caller must allocate `work_state_log'. */
-
-static reg_errcode_t
-transit_state_bkref_loop (preg, nodes, work_state_log, mctx)
- const regex_t *preg;
- re_node_set *nodes;
- re_dfastate_t **work_state_log;
- re_match_context_t *mctx;
-{
- reg_errcode_t err;
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- int i;
- regmatch_t *cur_regs = re_malloc (regmatch_t, preg->re_nsub + 1);
- int cur_str_idx = re_string_cur_idx (mctx->input);
- if (BE (cur_regs == NULL, 0))
- return REG_ESPACE;
-
- for (i = 0; i < nodes->nelem; ++i)
- {
- int dest_str_idx, subexp_idx, prev_nelem, bkc_idx;
- int node_idx = nodes->elems[i];
- unsigned int context;
- re_token_t *node = dfa->nodes + node_idx;
- re_node_set *new_dest_nodes;
- re_sift_context_t sctx;
-
- /* Check whether `node' is a backreference or not. */
- if (node->type == OP_BACK_REF)
- subexp_idx = node->opr.idx;
- else if (node->type == OP_CONTEXT_NODE &&
- dfa->nodes[node->opr.ctx_info->entity].type == OP_BACK_REF)
- {
- context = re_string_context_at (mctx->input, cur_str_idx,
- mctx->eflags, preg->newline_anchor);
- if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context))
- continue;
- subexp_idx = dfa->nodes[node->opr.ctx_info->entity].opr.idx;
- }
- else
- continue;
-
- /* `node' is a backreference.
- Check the substring which the substring matched. */
- sift_ctx_init (&sctx, work_state_log, NULL, node_idx, cur_str_idx,
- subexp_idx);
- sctx.cur_bkref = node_idx;
- match_ctx_clear_flag (mctx);
- err = sift_states_backward (preg, mctx, &sctx);
- if (BE (err != REG_NOERROR, 0))
- return err;
-
- /* And add the epsilon closures (which is `new_dest_nodes') of
- the backreference to appropriate state_log. */
-#ifdef DEBUG
- assert (dfa->nexts[node_idx] != -1);
-#endif
- for (bkc_idx = 0; bkc_idx < mctx->nbkref_ents; ++bkc_idx)
- {
- int subexp_len;
- re_dfastate_t *dest_state;
- struct re_backref_cache_entry *bkref_ent;
- bkref_ent = mctx->bkref_ents + bkc_idx;
- if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx)
- continue;
- subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from;
- new_dest_nodes = ((node->type == OP_CONTEXT_NODE && subexp_len == 0)
- ? dfa->nodes[node_idx].opr.ctx_info->bkref_eclosure
- : dfa->eclosures + dfa->nexts[node_idx]);
- dest_str_idx = (cur_str_idx + bkref_ent->subexp_to
- - bkref_ent->subexp_from);
- context = (IS_WORD_CHAR (re_string_byte_at (mctx->input,
- dest_str_idx - 1))
- ? CONTEXT_WORD : 0);
- dest_state = mctx->state_log[dest_str_idx];
- prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0
- : mctx->state_log[cur_str_idx]->nodes.nelem);
- /* Add `new_dest_node' to state_log. */
- if (dest_state == NULL)
- {
- mctx->state_log[dest_str_idx]
- = re_acquire_state_context (&err, dfa, new_dest_nodes,
- context);
- if (BE (mctx->state_log[dest_str_idx] == NULL
- && err != REG_NOERROR, 0))
- return err;
- }
- else
- {
- re_node_set dest_nodes;
- err = re_node_set_init_union (&dest_nodes,
- dest_state->entrance_nodes,
- new_dest_nodes);
- if (BE (err != REG_NOERROR, 0))
- return err;
- mctx->state_log[dest_str_idx]
- = re_acquire_state_context (&err, dfa, &dest_nodes, context);
- if (BE (mctx->state_log[dest_str_idx] == NULL
- && err != REG_NOERROR, 0))
- return err;
- re_node_set_free (&dest_nodes);
- }
- /* We need to check recursively if the backreference can epsilon
- transit. */
- if (subexp_len == 0
- && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem)
- {
- err = transit_state_bkref_loop (preg, new_dest_nodes,
- work_state_log, mctx);
- if (BE (err != REG_NOERROR, 0))
- return err;
- }
- }
- }
- re_free (cur_regs);
- return REG_NOERROR;
-}
-
-/* Build transition table for the state.
- Return the new table if succeeded, otherwise return NULL. */
-
-static re_dfastate_t **
-build_trtable (preg, state, fl_search)
- const regex_t *preg;
- const re_dfastate_t *state;
- int fl_search;
-{
- reg_errcode_t err;
- re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- int i, j, k, ch;
- int ndests; /* Number of the destination states from `state'. */
- re_dfastate_t **trtable, **dest_states, **dest_states_word, **dest_states_nl;
- re_node_set follows, *dests_node;
- bitset *dests_ch;
- bitset acceptable;
-
- /* We build DFA states which corresponds to the destination nodes
- from `state'. `dests_node[i]' represents the nodes which i-th
- destination state contains, and `dests_ch[i]' represents the
- characters which i-th destination state accepts. */
- dests_node = re_malloc (re_node_set, SBC_MAX);
- dests_ch = re_malloc (bitset, SBC_MAX);
-
- /* Initialize transiton table. */
- trtable = (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX);
- if (BE (dests_node == NULL || dests_ch == NULL || trtable == NULL, 0))
- return NULL;
-
- /* At first, group all nodes belonging to `state' into several
- destinations. */
- ndests = group_nodes_into_DFAstates (preg, state, dests_node, dests_ch);
- if (BE (ndests <= 0, 0))
- {
- re_free (dests_node);
- re_free (dests_ch);
- /* Return NULL in case of an error, trtable otherwise. */
- return (ndests < 0) ? NULL : trtable;
- }
-
- dest_states = re_malloc (re_dfastate_t *, ndests);
- dest_states_word = re_malloc (re_dfastate_t *, ndests);
- dest_states_nl = re_malloc (re_dfastate_t *, ndests);
- bitset_empty (acceptable);
-
- err = re_node_set_alloc (&follows, ndests + 1);
- if (BE (dest_states == NULL || dest_states_word == NULL
- || dest_states_nl == NULL || err != REG_NOERROR, 0))
- return NULL;
-
- /* Then build the states for all destinations. */
- for (i = 0; i < ndests; ++i)
- {
- int next_node;
- re_node_set_empty (&follows);
- /* Merge the follows of this destination states. */
- for (j = 0; j < dests_node[i].nelem; ++j)
- {
- next_node = dfa->nexts[dests_node[i].elems[j]];
- if (next_node != -1)
- {
- err = re_node_set_merge (&follows, dfa->eclosures + next_node);
- if (BE (err != REG_NOERROR, 0))
- return NULL;
- }
- }
- /* If search flag is set, merge the initial state. */
- if (fl_search)
- {
-#ifdef RE_ENABLE_I18N
- int not_initial = 0;
- for (j = 0; j < follows.nelem; ++j)
- if (dfa->nodes[follows.elems[j]].type == CHARACTER)
- {
- not_initial = dfa->nodes[follows.elems[j]].mb_partial;
- break;
- }
- if (!not_initial)
-#endif
- {
- err = re_node_set_merge (&follows,
- dfa->init_state->entrance_nodes);
- if (BE (err != REG_NOERROR, 0))
- return NULL;
- }
- }
- dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0);
- if (BE (dest_states[i] == NULL && err != REG_NOERROR, 0))
- return NULL;
- /* If the new state has context constraint,
- build appropriate states for these contexts. */
- if (dest_states[i]->has_constraint)
- {
- dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows,
- CONTEXT_WORD);
- if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0))
- return NULL;
- dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows,
- CONTEXT_NEWLINE);
- if (BE (dest_states_nl[i] == NULL && err != REG_NOERROR, 0))
- return NULL;
- }
- else
- {
- dest_states_word[i] = dest_states[i];
- dest_states_nl[i] = dest_states[i];
- }
- bitset_merge (acceptable, dests_ch[i]);
- }
-
- /* Update the transition table. */
- /* For all characters ch...: */
- for (i = 0, ch = 0; i < BITSET_UINTS; ++i)
- for (j = 0; j < UINT_BITS; ++j, ++ch)
- if ((acceptable[i] >> j) & 1)
- {
- /* The current state accepts the character ch. */
- if (IS_WORD_CHAR (ch))
- {
- for (k = 0; k < ndests; ++k)
- if ((dests_ch[k][i] >> j) & 1)
- {
- /* k-th destination accepts the word character ch. */
- trtable[ch] = dest_states_word[k];
- /* There must be only one destination which accepts
- character ch. See group_nodes_into_DFAstates. */
- break;
- }
- }
- else /* not WORD_CHAR */
- {
- for (k = 0; k < ndests; ++k)
- if ((dests_ch[k][i] >> j) & 1)
- {
- /* k-th destination accepts the non-word character ch. */
- trtable[ch] = dest_states[k];
- /* There must be only one destination which accepts
- character ch. See group_nodes_into_DFAstates. */
- break;
- }
- }
- }
- /* new line */
- if (bitset_contain (acceptable, NEWLINE_CHAR))
- {
- /* The current state accepts newline character. */
- for (k = 0; k < ndests; ++k)
- if (bitset_contain (dests_ch[k], NEWLINE_CHAR))
- {
- /* k-th destination accepts newline character. */
- trtable[NEWLINE_CHAR] = dest_states_nl[k];
- /* There must be only one destination which accepts
- newline. See group_nodes_into_DFAstates. */
- break;
- }
- }
-
- re_free (dest_states_nl);
- re_free (dest_states_word);
- re_free (dest_states);
-
- re_node_set_free (&follows);
- for (i = 0; i < ndests; ++i)
- re_node_set_free (dests_node + i);
-
- re_free (dests_ch);
- re_free (dests_node);
-
- return trtable;
-}
-
-/* Group all nodes belonging to STATE into several destinations.
- Then for all destinations, set the nodes belonging to the destination
- to DESTS_NODE[i] and set the characters accepted by the destination
- to DEST_CH[i]. This function return the number of destinations. */
-
-static int
-group_nodes_into_DFAstates (preg, state, dests_node, dests_ch)
- const regex_t *preg;
- const re_dfastate_t *state;
- re_node_set *dests_node;
- bitset *dests_ch;
-{
- reg_errcode_t err;
- const re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- int i, j, k;
- int ndests; /* Number of the destinations from `state'. */
- bitset accepts; /* Characters a node can accept. */
- const re_node_set *cur_nodes = &state->nodes;
- bitset_empty (accepts);
- ndests = 0;
-
- /* For all the nodes belonging to `state', */
- for (i = 0; i < cur_nodes->nelem; ++i)
- {
- unsigned int constraint = 0;
- re_token_t *node = &dfa->nodes[cur_nodes->elems[i]];
- re_token_type_t type = node->type;
-
- if (type == OP_CONTEXT_NODE)
- {
- constraint = node->constraint;
- node = dfa->nodes + node->opr.ctx_info->entity;
- type = node->type;
- }
-
- /* Enumerate all single byte character this node can accept. */
- if (type == CHARACTER)
- bitset_set (accepts, node->opr.c);
- else if (type == SIMPLE_BRACKET)
- {
- bitset_merge (accepts, node->opr.sbcset);
- }
- else if (type == OP_PERIOD)
- {
- bitset_set_all (accepts);
- if (!(preg->syntax & RE_DOT_NEWLINE))
- bitset_clear (accepts, '\n');
- if (preg->syntax & RE_DOT_NOT_NULL)
- bitset_clear (accepts, '\0');
- }
- else
- continue;
-
- /* Check the `accepts' and sift the characters which are not
- match it the context. */
- if (constraint)
- {
- if (constraint & NEXT_WORD_CONSTRAINT)
- for (j = 0; j < BITSET_UINTS; ++j)
- accepts[j] &= dfa->word_char[j];
- else if (constraint & NEXT_NOTWORD_CONSTRAINT)
- for (j = 0; j < BITSET_UINTS; ++j)
- accepts[j] &= ~dfa->word_char[j];
- else if (constraint & NEXT_NEWLINE_CONSTRAINT)
- {
- int accepts_newline = bitset_contain (accepts, NEWLINE_CHAR);
- bitset_empty (accepts);
- if (accepts_newline)
- bitset_set (accepts, NEWLINE_CHAR);
- else
- continue;
- }
- }
-
- /* Then divide `accepts' into DFA states, or create a new
- state. */
- for (j = 0; j < ndests; ++j)
- {
- bitset intersec; /* Intersection sets, see below. */
- bitset remains;
- /* Flags, see below. */
- int has_intersec, not_subset, not_consumed;
-
- /* Optimization, skip if this state doesn't accept the character. */
- if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c))
- continue;
-
- /* Enumerate the intersection set of this state and `accepts'. */
- has_intersec = 0;
- for (k = 0; k < BITSET_UINTS; ++k)
- has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k];
- /* And skip if the intersection set is empty. */
- if (!has_intersec)
- continue;
-
- /* Then check if this state is a subset of `accepts'. */
- not_subset = not_consumed = 0;
- for (k = 0; k < BITSET_UINTS; ++k)
- {
- not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k];
- not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k];
- }
-
- /* If this state isn't a subset of `accepts', create a
- new group state, which has the `remains'. */
- if (not_subset)
- {
- bitset_copy (dests_ch[ndests], remains);
- bitset_copy (dests_ch[j], intersec);
- err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]);
- if (BE (err != REG_NOERROR, 0))
- return -1;
- ++ndests;
- }
-
- /* Put the position in the current group. */
- err = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]);
- if (BE (err < 0, 0))
- return -1;
-
- /* If all characters are consumed, go to next node. */
- if (!not_consumed)
- break;
- }
- /* Some characters remain, create a new group. */
- if (j == ndests)
- {
- bitset_copy (dests_ch[ndests], accepts);
- err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]);
- if (BE (err != REG_NOERROR, 0))
- return -1;
- ++ndests;
- bitset_empty (accepts);
- }
- }
- return ndests;
-}
-
-#ifdef RE_ENABLE_I18N
-/* Check how many bytes the node `dfa->nodes[node_idx]' accepts.
- Return the number of the bytes the node accepts.
- STR_IDX is the current index of the input string.
-
- This function handles the nodes which can accept one character, or
- one collating element like '.', '[a-z]', opposite to the other nodes
- can only accept one byte. */
-
-static int
-check_node_accept_bytes (preg, node_idx, input, str_idx)
- const regex_t *preg;
- int node_idx, str_idx;
- const re_string_t *input;
-{
- const re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- const re_token_t *node = dfa->nodes + node_idx;
- int elem_len = re_string_elem_size_at (input, str_idx);
- int char_len = re_string_char_size_at (input, str_idx);
- int i;
-# ifdef _LIBC
- int j;
- uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
-# endif /* _LIBC */
- if (elem_len <= 1 && char_len <= 1)
- return 0;
- if (node->type == OP_PERIOD)
- {
- /* '.' accepts any one character except the following two cases. */
- if ((!(preg->syntax & RE_DOT_NEWLINE) &&
- re_string_byte_at (input, str_idx) == '\n') ||
- ((preg->syntax & RE_DOT_NOT_NULL) &&
- re_string_byte_at (input, str_idx) == '\0'))
- return 0;
- return char_len;
- }
- else if (node->type == COMPLEX_BRACKET)
- {
- const re_charset_t *cset = node->opr.mbcset;
-# ifdef _LIBC
- const unsigned char *pin = re_string_get_buffer (input) + str_idx;
-# endif /* _LIBC */
- int match_len = 0;
- wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars)
- ? re_string_wchar_at (input, str_idx) : 0);
-
- /* match with multibyte character? */
- for (i = 0; i < cset->nmbchars; ++i)
- if (wc == cset->mbchars[i])
- {
- match_len = char_len;
- goto check_node_accept_bytes_match;
- }
- /* match with character_class? */
- for (i = 0; i < cset->nchar_classes; ++i)
- {
- wctype_t wt = cset->char_classes[i];
- if (__iswctype (wc, wt))
- {
- match_len = char_len;
- goto check_node_accept_bytes_match;
- }
- }
-
-# ifdef _LIBC
- if (nrules != 0)
- {
- unsigned int in_collseq = 0;
- const int32_t *table, *indirect;
- const unsigned char *weights, *extra;
- const char *collseqwc;
- int32_t idx;
- /* This #include defines a local function! */
-# include <locale/weight.h>
-
- /* match with collating_symbol? */
- if (cset->ncoll_syms)
- extra = (const unsigned char *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
- for (i = 0; i < cset->ncoll_syms; ++i)
- {
- const unsigned char *coll_sym = extra + cset->coll_syms[i];
- /* Compare the length of input collating element and
- the length of current collating element. */
- if (*coll_sym != elem_len)
- continue;
- /* Compare each bytes. */
- for (j = 0; j < *coll_sym; j++)
- if (pin[j] != coll_sym[1 + j])
- break;
- if (j == *coll_sym)
- {
- /* Match if every bytes is equal. */
- match_len = j;
- goto check_node_accept_bytes_match;
- }
- }
-
- if (cset->nranges)
- {
- if (elem_len <= char_len)
- {
- collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);
- in_collseq = collseq_table_lookup (collseqwc, wc);
- }
- else
- in_collseq = find_collation_sequence_value (pin, elem_len);
- }
- /* match with range expression? */
- for (i = 0; i < cset->nranges; ++i)
- if (cset->range_starts[i] <= in_collseq
- && in_collseq <= cset->range_ends[i])
- {
- match_len = elem_len;
- goto check_node_accept_bytes_match;
- }
-
- /* match with equivalence_class? */
- if (cset->nequiv_classes)
- {
- const unsigned char *cp = pin;
- table = (const int32_t *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
- weights = (const unsigned char *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
- extra = (const unsigned char *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
- indirect = (const int32_t *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
- idx = findidx (&cp);
- if (idx > 0)
- for (i = 0; i < cset->nequiv_classes; ++i)
- {
- int32_t equiv_class_idx = cset->equiv_classes[i];
- size_t weight_len = weights[idx];
- if (weight_len == weights[equiv_class_idx])
- {
- int cnt = 0;
- while (cnt <= weight_len
- && (weights[equiv_class_idx + 1 + cnt]
- == weights[idx + 1 + cnt]))
- ++cnt;
- if (cnt > weight_len)
- {
- match_len = elem_len;
- goto check_node_accept_bytes_match;
- }
- }
- }
- }
- }
- else
-# endif /* _LIBC */
- {
- /* match with range expression? */
-#if __GNUC__ >= 2
- wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'};
-#else
- wchar_t cmp_buf[] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'};
- cmp_buf[2] = wc;
-#endif
- for (i = 0; i < cset->nranges; ++i)
- {
- cmp_buf[0] = cset->range_starts[i];
- cmp_buf[4] = cset->range_ends[i];
- if (wcscoll (cmp_buf, cmp_buf + 2) <= 0
- && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0)
- {
- match_len = char_len;
- goto check_node_accept_bytes_match;
- }
- }
- }
- check_node_accept_bytes_match:
- if (!cset->non_match)
- return match_len;
- else
- {
- if (match_len > 0)
- return 0;
- else
- return (elem_len > char_len) ? elem_len : char_len;
- }
- }
- return 0;
-}
-
-# ifdef _LIBC
-static unsigned int
-find_collation_sequence_value (mbs, mbs_len)
- const unsigned char *mbs;
- size_t mbs_len;
-{
- uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
- if (nrules == 0)
- {
- if (mbs_len == 1)
- {
- /* No valid character. Match it as a single byte character. */
- const unsigned char *collseq = (const unsigned char *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
- return collseq[mbs[0]];
- }
- return UINT_MAX;
- }
- else
- {
- int32_t idx;
- const unsigned char *extra = (const unsigned char *)
- _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);
-
- for (idx = 0; ;)
- {
- int mbs_cnt, found = 0;
- int32_t elem_mbs_len;
- /* Skip the name of collating element name. */
- idx = idx + extra[idx] + 1;
- elem_mbs_len = extra[idx++];
- if (mbs_len == elem_mbs_len)
- {
- for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt)
- if (extra[idx + mbs_cnt] != mbs[mbs_cnt])
- break;
- if (mbs_cnt == elem_mbs_len)
- /* Found the entry. */
- found = 1;
- }
- /* Skip the byte sequence of the collating element. */
- idx += elem_mbs_len;
- /* Adjust for the alignment. */
- idx = (idx + 3) & ~3;
- /* Skip the collation sequence value. */
- idx += sizeof (uint32_t);
- /* Skip the wide char sequence of the collating element. */
- idx = idx + sizeof (uint32_t) * (extra[idx] + 1);
- /* If we found the entry, return the sequence value. */
- if (found)
- return *(uint32_t *) (extra + idx);
- /* Skip the collation sequence value. */
- idx += sizeof (uint32_t);
- }
- }
-}
-# endif /* _LIBC */
-#endif /* RE_ENABLE_I18N */
-
-/* Check whether the node accepts the byte which is IDX-th
- byte of the INPUT. */
-
-static int
-check_node_accept (preg, node, mctx, idx)
- const regex_t *preg;
- const re_token_t *node;
- const re_match_context_t *mctx;
- int idx;
-{
- const re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
- const re_token_t *cur_node;
- unsigned char ch;
- if (node->type == OP_CONTEXT_NODE)
- {
- /* The node has constraints. Check whether the current context
- satisfies the constraints. */
- unsigned int context = re_string_context_at (mctx->input, idx,
- mctx->eflags,
- preg->newline_anchor);
- if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context))
- return 0;
- cur_node = dfa->nodes + node->opr.ctx_info->entity;
- }
- else
- cur_node = node;
-
- ch = re_string_byte_at (mctx->input, idx);
- if (cur_node->type == CHARACTER)
- return cur_node->opr.c == ch;
- else if (cur_node->type == SIMPLE_BRACKET)
- return bitset_contain (cur_node->opr.sbcset, ch);
- else if (cur_node->type == OP_PERIOD)
- return !((ch == '\n' && !(preg->syntax & RE_DOT_NEWLINE))
- || (ch == '\0' && (preg->syntax & RE_DOT_NOT_NULL)));
- else
- return 0;
-}
-
-/* Extend the buffers, if the buffers have run out. */
-
-static reg_errcode_t
-extend_buffers (mctx)
- re_match_context_t *mctx;
-{
- reg_errcode_t ret;
- re_string_t *pstr = mctx->input;
-
- /* Double the lengthes of the buffers. */
- ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
- if (BE (ret != REG_NOERROR, 0))
- return ret;
-
- if (mctx->state_log != NULL)
- {
- /* And double the length of state_log. */
- mctx->state_log = re_realloc (mctx->state_log, re_dfastate_t *,
- pstr->bufs_len * 2);
- if (BE (mctx->state_log == NULL, 0))
- return REG_ESPACE;
- }
-
- /* Then reconstruct the buffers. */
- if (pstr->icase)
- {
-#ifdef RE_ENABLE_I18N
- if (MB_CUR_MAX > 1)
- build_wcs_upper_buffer (pstr);
- else
-#endif /* RE_ENABLE_I18N */
- build_upper_buffer (pstr);
- }
- else
- {
-#ifdef RE_ENABLE_I18N
- if (MB_CUR_MAX > 1)
- build_wcs_buffer (pstr);
- else
-#endif /* RE_ENABLE_I18N */
- {
- if (pstr->trans != NULL)
- re_string_translate_buffer (pstr);
- else
- pstr->valid_len = pstr->bufs_len;
- }
- }
- return REG_NOERROR;
-}
-
-
-/* Functions for matching context. */
-
-static reg_errcode_t
-match_ctx_init (mctx, eflags, input, n)
- re_match_context_t *mctx;
- int eflags, n;
- re_string_t *input;
-{
- mctx->eflags = eflags;
- mctx->input = input;
- mctx->match_last = -1;
- if (n > 0)
- {
- mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n);
- if (BE (mctx->bkref_ents == NULL, 0))
- return REG_ESPACE;
- }
- else
- mctx->bkref_ents = NULL;
- mctx->nbkref_ents = 0;
- mctx->abkref_ents = n;
- mctx->max_mb_elem_len = 0;
- return REG_NOERROR;
-}
-
-static void
-match_ctx_free (mctx)
- re_match_context_t *mctx;
-{
- re_free (mctx->bkref_ents);
-}
-
-/* Add a new backreference entry to the cache. */
-
-static reg_errcode_t
-match_ctx_add_entry (mctx, node, str_idx, from, to)
- re_match_context_t *mctx;
- int node, str_idx, from, to;
-{
- if (mctx->nbkref_ents >= mctx->abkref_ents)
- {
- mctx->bkref_ents = re_realloc (mctx->bkref_ents,
- struct re_backref_cache_entry,
- mctx->abkref_ents * 2);
- if (BE (mctx->bkref_ents == NULL, 0))
- return REG_ESPACE;
- memset (mctx->bkref_ents + mctx->nbkref_ents, '\0',
- sizeof (struct re_backref_cache_entry) * mctx->abkref_ents);
- mctx->abkref_ents *= 2;
- }
- mctx->bkref_ents[mctx->nbkref_ents].node = node;
- mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx;
- mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from;
- mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to;
- mctx->bkref_ents[mctx->nbkref_ents++].flag = 0;
- if (mctx->max_mb_elem_len < to - from)
- mctx->max_mb_elem_len = to - from;
- return REG_NOERROR;
-}
-
-static void
-match_ctx_clear_flag (mctx)
- re_match_context_t *mctx;
-{
- int i;
- for (i = 0; i < mctx->nbkref_ents; ++i)
- {
- mctx->bkref_ents[i].flag = 0;
- }
-}
-
-static void
-sift_ctx_init (sctx, sifted_sts, limited_sts, last_node, last_str_idx,
- check_subexp)
- re_sift_context_t *sctx;
- re_dfastate_t **sifted_sts, **limited_sts;
- int last_node, last_str_idx, check_subexp;
-{
- sctx->sifted_states = sifted_sts;
- sctx->limited_states = limited_sts;
- sctx->last_node = last_node;
- sctx->last_str_idx = last_str_idx;
- sctx->check_subexp = check_subexp;
- re_node_set_init_empty (&sctx->limits);
-}
diff --git a/util/riscos.c b/util/riscos.c
deleted file mode 100644
index b94ff5318..000000000
--- a/util/riscos.c
+++ /dev/null
@@ -1,436 +0,0 @@
-/* riscos.c - RISC OS stuff
- * Copyright (C) 2001 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG for RISC OS.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#ifndef __RISCOS__C__
-#define __RISCOS__C__
-
-#include <config.h>
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <kernel.h>
-#include <swis.h>
-#include "util.h"
-#include "memory.h"
-
-#include <unixlib/local.h> /* needed for RISCOSIFY_NO_PROCESS */
-#define __UNIXLIB_INTERNALS
-#include <unixlib/swiparams.h> /* needed for MMM_TYPE_* definitions */
-#undef __UNIXLIB_INTERNALS
-
-
-/* static symbols that trigger UnixLib behaviour */
-
-int __riscosify_control = __RISCOSIFY_NO_PROCESS;
-int __feature_imagefs_is_file = 1;
-
-
-/* RISC OS file open descriptor control list */
-
-struct fds_item {
- int fd;
- struct fds_item *next;
-};
-static struct fds_item *fds_list = NULL;
-static int fdlist_initialized = 0;
-
-
-/* local RISC OS functions */
-
-static int
-is_read_only(const char *filename)
-{
- int type, attr;
-
- if (_swix(OS_File, _INR(0,1) | _OUT(0) | _OUT(5),
- 17, filename, &type, &attr))
- log_fatal("Can't get file attributes for file \"%s\"!\n", filename);
-
- if (type == 0)
- log_fatal("Can't find file \"%s\"!\n", filename);
-
- if (_swix(OS_File, _INR(0,1) | _IN(5), 4, filename, attr))
- return 1;
-
- return 0;
-}
-
-/* exported RISC OS functions */
-
-int
-riscos_load_module(const char *name, const char * const path[], int fatal)
-{
- int i;
-
- /* Is module already loaded? */
- if (!_swix(OS_Module, _INR(0,1), 18, name))
- return 1;
-
- /* Check all the places where the module could be located */
- for (i=0; path[i]; ++i)
- if (!_swix(OS_Module, _INR(0,1), 1, path[i]))
- return 1;
-
- /* Can't find module in the default locations */
- if (fatal)
- log_fatal("Operation cannot be performed without \"%s\" module!\n",
- name);
- else
- log_info("Can't load \"%s\" module, continuing anyway!\n", name);
-
- return 0;
-}
-
-int
-riscos_get_filetype_from_string(const char *string, int len)
-{
- int result = 0xfff;
-
- if (strlen(string) < 5 || string[len - 4] != ',')
- return -1;
-
- sscanf(string+len-3, "%3x", &result);
-
- return result;
-}
-
-int
-riscos_get_filetype(const char *filename)
-{
- int result;
-
- if (_swix(OS_File, _INR(0,1) | _OUT(2), 17, filename, &result))
- log_fatal("Can't get filetype for file \"%s\"!\n", filename);
-
- if ((result & 0xfff00000) == 0xfff00000)
- return (result & 0xfff00) >> 8;
- else
- return 0;
-}
-
-void
-riscos_set_filetype_by_number(const char *filename, int type)
-{
- if (_swix(OS_File, _INR(0,2), 18, filename, type))
- log_fatal("Can't set filetype for file \"%s\"!\n"
- "Is the file on a read-only file system?\n", filename);
-}
-
-void
-riscos_set_filetype_by_mimetype(const char *filename, const char *mimetype)
-{
- int result;
-
- if (_swix(MimeMap_Translate, _INR(0,2) | _OUT(3),
- MMM_TYPE_MIME, mimetype, MMM_TYPE_RISCOS, &result))
- log_fatal("Can't translate MIME type \"%s\"!\n", mimetype);
-
- riscos_set_filetype_by_number(filename, result);
-}
-
-pid_t
-riscos_getpid(void)
-{
- int state;
-
- if (_swix(Wimp_ReadSysInfo, _IN(0) | _OUT(0), 3, &state))
- log_fatal("Wimp_ReadSysInfo failed: Can't get WimpState (R0=3)!\n");
-
- if (state)
- if (_swix(Wimp_ReadSysInfo, _IN(0) | _OUT(0), 5, &state))
- log_fatal("Wimp_ReadSysInfo failed: "
- "Can't get task handle (R0=5)!\n");
-
- return (pid_t) state;
-}
-
-int
-riscos_kill(pid_t pid, int sig)
-{
- int buf[4], iter = 0;
-
- if (sig)
- kill(pid, sig);
-
- do {
- if (_swix(TaskManager_EnumerateTasks, _INR(0,2) | _OUT(0),
- iter, buf, 16, &iter))
- log_fatal("TaskManager_EnumerateTasks failed!\n");
- if (buf[0] == pid)
- return 0;
- } while (iter >= 0);
-
- return __set_errno(ESRCH);
-}
-
-int
-riscos_access(const char *path, int amode)
-{
- /* Do additional check, i.e. whether path is on write-protected floppy */
- if ((amode & W_OK) && is_read_only(path))
- return 1;
- return access(path, amode);
-}
-
-int
-riscos_getchar(void)
-{
- int c, flags;
-
- if (_swix(OS_ReadC, _OUT(0) | _OUT(_FLAGS), &c, &flags))
- log_fatal("OS_ReadC failed: Couldn't read from keyboard!\n");
- if (flags & _C)
- log_fatal("OS_ReadC failed: Return Code = %i!\n", c);
-
- return c;
-}
-
-#ifdef DEBUG
-void
-riscos_dump_fdlist(void)
-{
- struct fds_item *iter = fds_list;
- printf("List of open file descriptors:\n");
- while (iter) {
- printf(" %i\n", iter->fd);
- iter = iter->next;
- }
-}
-#endif /* DEBUG */
-
-int
-riscos_fdopenfile(const char *filename, const int allow_write)
-{
- struct fds_item *h;
- int fd;
- if (allow_write)
- fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
- else
- fd = open(filename, O_RDONLY);
- if (fd == -1)
- log_error("Can't open file \"%s\": %i, %s!\n",
- filename, errno, strerror(errno));
-
- if (!fdlist_initialized) {
- atexit (riscos_close_fds);
- fdlist_initialized = 1;
- }
-
- h = fds_list;
- fds_list = (struct fds_item *) xmalloc(sizeof(struct fds_item));
- if (!fds_list)
- log_fatal("Can't claim memory for fdopenfile() buffer!\n");
- fds_list->fd = fd;
- fds_list->next = h;
-
- return fd;
-}
-
-void
-riscos_close_fds(void)
-{
- FILE *fp;
- struct fds_item *h = fds_list;
- while( fds_list ) {
- h = fds_list->next;
- fp = fdopen (fds_list->fd, "a");
- if (fp)
- fflush(fp);
- close(fds_list->fd);
- xfree(fds_list);
- fds_list = h;
- }
-}
-
-int
-riscos_renamefile(const char *old, const char *new)
-{
- _kernel_oserror *e;
-
- if (e = _swix(OS_FSControl, _INR(0,2), 25, old, new)) {
- if (e->errnum == 214)
- return __set_errno(ENOENT);
- if (e->errnum == 176)
- return __set_errno(EEXIST);
- printf("Error during renaming: %i, %s!\n", e->errnum, e->errmess);
- return __set_errno(EOPSYS);
- }
- return 0;
-}
-
-char *
-riscos_gstrans(const char *old)
-{
- int size = 256, last;
- char *buf, *tmp;
-
- buf = (char *) xmalloc(size);
- if (!buf)
- log_fatal("Can't claim memory for OS_GSTrans buffer!\n");
- while (_C & _swi(OS_GSTrans, _INR(0,2) | _OUT(2) | _RETURN(_FLAGS),
- old, buf, size, &last)) {
- size += 256;
- tmp = (char *) xrealloc(buf, size);
- if (!tmp)
- log_fatal("Can't claim memory for OS_GSTrans buffer!\n");
- buf = tmp;
- }
-
- buf[last] = '\0';
- tmp = (char *) xrealloc(buf, last + 1);
- if (!tmp)
- log_fatal("Can't realloc memory after OS_GSTrans!\n");
-
- return tmp;
-}
-
-/***************
- * Extract from a given path the filename component.
- * (cloned from util/fileutil.c and then heavily modified)
- */
-char *
-riscos_make_basename(const char *filepath, const char *realfname)
-{
- char *result, *p;
- int i, filetype;
-
- if ( (p = strrchr(filepath, DIRSEP_C)) )
- p++;
- else if ( (p = strrchr(filepath, ':')) )
- p++;
- else
- p = (char*) filepath;
-
- i = strlen(p);
- result = xmalloc(i + 5);
- if (!result)
- log_fatal("Can't claim memory for riscos_make_basename() buffer!\n");
- strcpy(result, p);
-
- filetype = riscos_get_filetype( realfname );
- result[i++] = ',';
- result[i++] = "0123456789abcdef"[(filetype >> 8) & 0xf];
- result[i++] = "0123456789abcdef"[(filetype >> 4) & 0xf];
- result[i++] = "0123456789abcdef"[(filetype >> 0) & 0xf];
- result[i] = 0;
-
- for(i=0; i<strlen(result); ++i)
- if(result[i] == '/')
- result[i] = '.';
-
- return result;
-}
-
-#define RegEx_CompilePattern 0x52AC0
-#define RegEx_Search 0x52AC2
-#define RegEx_Free 0x52AC7
-#define RegEx_CompileExtendedPattern 0x52AC9
-
-static const char * const regex_path[] = {
- "GnuPG:RegEx",
- "System:310.Modules.RegEx",
- "System:Modules.RegEx",
- NULL
-};
-
-int
-riscos_check_regexp(const char *exp, const char *string, int debug)
-{
- static int regex_initialized = 0;
- int ret;
- char *buf;
-
- if (!regex_initialized)
- regex_initialized = riscos_load_module("RegEx", regex_path, 0);
-
- if (!regex_initialized) {
- log_info("Regular expressions cannot be used!\n");
- return 0;
- }
-
- if (_swix(RegEx_CompileExtendedPattern, _INR(0,2) | _OUT(0) | _OUT(3),
- 0, exp, 1<<18,
- &buf, &ret)) {
- log_info("RegEx could not compile pattern \"%s\".\n", exp);
- log_info("ErrorCode = %i\n", ret);
- return 0;
- }
-
- if (_swix(RegEx_Search, _INR(0,4) | _OUT(5),
- buf, string, -1, 0, -1,
- &ret)) {
- log_info("RegEx error during execution of serach pattern \"%s\"\n",
- exp);
- log_info("on string \"%s\"\n", string);
- return 0;
- }
-
- _swix(RegEx_Free, _IN(0), buf);
-
- if(debug)
- log_debug("regexp \"%s\" on \"%s\": %s\n",exp,string,ret>=0?"YES":"NO");
-
- return (ret>=0);
-}
-
-#ifdef DEBUG
-void
-riscos_list_openfiles(void)
-{
- char *name;
- int i, len;
-
- for (i = 255; i >= 0; --i) {
- if (_swix(OS_Args, _INR(0,2) | _IN(5) | _OUT(5), 7, i, 0, 0, &len))
- continue;
-
- name = (char *) xmalloc(1-len);
- if (!name)
- log_fatal("Can't claim memory for OS_Args buffer!\n");
-
- if (_swix(OS_Args, _INR(0,2) | _IN(5), 7, i, name, 1-len)) {
- xfree(name);
- log_fatal("Error when calling OS_Args(7)!\n");
- }
-
- if (_swix(OS_Args, _INR(0,1) | _OUT(0), 254, i, &len)) {
- xfree(name);
- log_fatal("Error when calling OS_Args(254)!\n");
- }
-
- printf("%3i: %s (%c%c)\n", i, name,
- (len & 0x40) ? 'R' : 0,
- (len & 0x80) ? 'W' : 0);
- xfree(name);
- }
-}
-#endif
-
-void
-riscos_not_implemented(const char *feature)
-{
- log_info("%s is not implemented in the RISC OS version!\n", feature);
-}
-
-#endif /* !__RISCOS__C__ */
diff --git a/util/secmem.c b/util/secmem.c
deleted file mode 100644
index 5ffbfc6d3..000000000
--- a/util/secmem.c
+++ /dev/null
@@ -1,499 +0,0 @@
-/* secmem.c - memory allocation from a secure heap
- * Copyright (C) 1998, 1999, 2000 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <unistd.h>
-#if defined(HAVE_MLOCK) || defined(HAVE_MMAP)
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#ifdef USE_CAPABILITIES
-#include <sys/capability.h>
-#endif
-#ifdef HAVE_PLOCK
-#include <sys/lock.h>
-#endif
-#endif
-
-#include "types.h"
-#include "memory.h"
-#include "util.h"
-#include "i18n.h"
-
-/* MinGW doesn't seem to prototype getpagesize, though it does have
- it. */
-#if !HAVE_DECL_GETPAGESIZE
-int getpagesize(void);
-#endif
-
-#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-/* It seems that Slackware 7.1 does not know about EPERM */
-#if !defined(EPERM) && defined(ENOMEM)
-#define EPERM ENOMEM
-#endif
-
-
-#define DEFAULT_POOLSIZE 16384
-
-typedef struct memblock_struct MEMBLOCK;
-struct memblock_struct {
- unsigned size;
- union {
- MEMBLOCK *next;
- PROPERLY_ALIGNED_TYPE aligned;
- } u;
-};
-
-
-
-static void *pool;
-static volatile int pool_okay; /* may be checked in an atexit function */
-#ifdef HAVE_MMAP
-static volatile int pool_is_mmapped;
-#endif
-static size_t poolsize; /* allocated length */
-static size_t poollen; /* used length */
-static MEMBLOCK *unused_blocks;
-static unsigned max_alloced;
-static unsigned cur_alloced;
-static unsigned max_blocks;
-static unsigned cur_blocks;
-static int disable_secmem;
-static int show_warning;
-static int no_warning;
-static int suspend_warning;
-
-
-static void
-print_warn(void)
-{
- if (!no_warning)
- {
- log_info(_("WARNING: using insecure memory!\n"));
- log_info(_("please see http://www.gnupg.org/faq.html"
- " for more information\n"));
- }
-}
-
-
-static void
-lock_pool( void *p, size_t n )
-{
-#if defined(USE_CAPABILITIES) && defined(HAVE_MLOCK)
- int err;
-
- cap_set_proc( cap_from_text("cap_ipc_lock+ep") );
- err = mlock( p, n );
- if( err && errno )
- err = errno;
- cap_set_proc( cap_from_text("cap_ipc_lock+p") );
-
- if( err ) {
- if( errno != EPERM
-#ifdef EAGAIN /* OpenBSD returns this */
- && errno != EAGAIN
-#endif
-#ifdef ENOSYS /* Some SCOs return this (function not implemented) */
- && errno != ENOSYS
-#endif
-#ifdef ENOMEM /* Linux can return this */
- && errno != ENOMEM
-#endif
- )
- log_error("can't lock memory: %s\n", strerror(err));
- show_warning = 1;
- }
-
-#elif defined(HAVE_MLOCK)
- uid_t uid;
- int err;
-
- uid = getuid();
-
-#ifdef HAVE_BROKEN_MLOCK
- /* ick. but at least we get secured memory. about to lock
- entire data segment. */
-#ifdef HAVE_PLOCK
-# ifdef _AIX
- /* The configure for AIX returns broken mlock but the plock has
- the strange requirement to somehow set the stack limit first.
- The problem might turn out in indeterministic program behaviour
- and hanging processes which can somehow be solved when enough
- processes are clogging up the memory. To get this problem out
- of the way we simply don't try to lock the memory at all.
- */
- errno = EPERM;
- err = errno;
-# else /* !_AIX */
- err = plock( DATLOCK );
- if( err && errno )
- err = errno;
-# endif /*_AIX*/
-#else /*!HAVE_PLOCK*/
- if( uid ) {
- errno = EPERM;
- err = errno;
- }
- else {
- err = mlock( p, n );
- if( err && errno )
- err = errno;
- }
-#endif /*!HAVE_PLOCK*/
-#else
- err = mlock( p, n );
- if( err && errno )
- err = errno;
-#endif
-
- if( uid && !geteuid() ) {
- /* check that we really dropped the privs.
- * Note: setuid(0) should always fail */
- if( setuid( uid ) || getuid() != geteuid() || !setuid(0) )
- log_fatal("failed to reset uid: %s\n", strerror(errno));
- }
-
- if( err ) {
- if( errno != EPERM
-#ifdef EAGAIN /* OpenBSD returns this */
- && errno != EAGAIN
-#endif
-#ifdef ENOSYS /* Some SCOs return this (function not implemented) */
- && errno != ENOSYS
-#endif
-#ifdef ENOMEM /* Linux can return this */
- && errno != ENOMEM
-#endif
- )
- log_error("can't lock memory: %s\n", strerror(err));
- show_warning = 1;
- }
-
-#elif defined ( __QNX__ )
- /* QNX does not page at all, so the whole secure memory stuff does
- * not make much sense. However it is still of use because it
- * wipes out the memory on a free().
- * Therefore it is sufficient to suppress the warning
- */
-#elif defined (HAVE_DOSISH_SYSTEM) || defined (__CYGWIN__)
- /* It does not make sense to print such a warning, given the fact that
- * this whole Windows !@#$% and their user base are inherently insecure
- */
-#elif defined (__riscos__)
- /* no virtual memory on RISC OS, so no pages are swapped to disc,
- * besides we don't have mmap, so we don't use it! ;-)
- * But don't complain, as explained above.
- */
-#else
- log_info("Please note that you don't have secure memory on this system\n");
-#endif
-}
-
-
-static void
-init_pool( size_t n)
-{
- size_t pgsize;
-
- poolsize = n;
-
- if( disable_secmem )
- log_bug("secure memory is disabled");
-
-#ifdef HAVE_GETPAGESIZE
- pgsize = getpagesize();
-#else
- pgsize = 4096;
-#endif
-
-#ifdef HAVE_MMAP
- poolsize = (poolsize + pgsize -1 ) & ~(pgsize-1);
-#ifdef MAP_ANONYMOUS
- pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE,
- MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
-#else /* map /dev/zero instead */
- { int fd;
-
- fd = open("/dev/zero", O_RDWR);
- if( fd == -1 ) {
- log_error("can't open /dev/zero: %s\n", strerror(errno) );
- pool = (void*)-1;
- }
- else {
- pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE,
- MAP_PRIVATE, fd, 0);
- close (fd);
- }
- }
-#endif
- if( pool == (void*)-1 )
- log_info("can't mmap pool of %u bytes: %s - using malloc\n",
- (unsigned)poolsize, strerror(errno));
- else {
- pool_is_mmapped = 1;
- pool_okay = 1;
- }
-
-#endif
- if( !pool_okay ) {
- pool = malloc( poolsize );
- if( !pool )
- log_fatal("can't allocate memory pool of %u bytes\n",
- (unsigned)poolsize);
- else
- pool_okay = 1;
- }
- lock_pool( pool, poolsize );
- poollen = 0;
-}
-
-
-/* concatenate unused blocks */
-static void
-compress_pool(void)
-{
- /* fixme: we really should do this */
-}
-
-void
-secmem_set_flags( unsigned flags )
-{
- int was_susp = suspend_warning;
-
- no_warning = flags & 1;
- suspend_warning = flags & 2;
-
- /* and now issue the warning if it is not longer suspended */
- if( was_susp && !suspend_warning && show_warning ) {
- show_warning = 0;
- print_warn();
- }
-}
-
-unsigned
-secmem_get_flags(void)
-{
- unsigned flags;
-
- flags = no_warning ? 1:0;
- flags |= suspend_warning ? 2:0;
- return flags;
-}
-
-/* Returns 1 if memory was locked, 0 if not. */
-int
-secmem_init( size_t n )
-{
- if( !n ) {
-#ifndef __riscos__
-#ifdef USE_CAPABILITIES
- /* drop all capabilities */
- cap_set_proc( cap_from_text("all-eip") );
-
-#elif !defined(HAVE_DOSISH_SYSTEM)
- uid_t uid;
-
- disable_secmem=1;
- uid = getuid();
- if( uid != geteuid() ) {
- if( setuid( uid ) || getuid() != geteuid() || !setuid(0) )
- log_fatal("failed to drop setuid\n" );
- }
-#endif
-#endif /* !__riscos__ */
- }
- else {
- if( n < DEFAULT_POOLSIZE )
- n = DEFAULT_POOLSIZE;
- if( !pool_okay )
- init_pool(n);
- else
- log_error("Oops, secure memory pool already initialized\n");
- }
-
- return !show_warning;
-}
-
-
-void *
-secmem_malloc( size_t size )
-{
- MEMBLOCK *mb, *mb2;
- int compressed=0;
-
- if( !pool_okay ) {
- log_info(
- _("operation is not possible without initialized secure memory\n"));
- log_info(_("(you may have used the wrong program for this task)\n"));
- exit(2);
- }
- if( show_warning && !suspend_warning ) {
- show_warning = 0;
- print_warn();
- }
-
- /* Blocks are always a multiple of 32. Note that we allocate an
- extra of the size of an entire MEMBLOCK. This is required
- becuase we do not only need the SIZE info but also extra space
- to chain up unused memory blocks. */
- size += sizeof(MEMBLOCK);
- size = ((size + 31) / 32) * 32;
-
- retry:
- /* try to get it from the used blocks */
- for(mb = unused_blocks,mb2=NULL; mb; mb2=mb, mb = mb->u.next )
- if( mb->size >= size ) {
- if( mb2 )
- mb2->u.next = mb->u.next;
- else
- unused_blocks = mb->u.next;
- goto leave;
- }
- /* allocate a new block */
- if( (poollen + size <= poolsize) ) {
- mb = (void*)((char*)pool + poollen);
- poollen += size;
- mb->size = size;
- }
- else if( !compressed ) {
- compressed=1;
- compress_pool();
- goto retry;
- }
- else
- return NULL;
-
- leave:
- cur_alloced += mb->size;
- cur_blocks++;
- if( cur_alloced > max_alloced )
- max_alloced = cur_alloced;
- if( cur_blocks > max_blocks )
- max_blocks = cur_blocks;
-
- return &mb->u.aligned.c;
-}
-
-
-void *
-secmexrealloc( void *p, size_t newsize )
-{
- MEMBLOCK *mb;
- size_t size;
- void *a;
-
- mb = (MEMBLOCK*)((char*)p - ((size_t) &((MEMBLOCK*)0)->u.aligned.c));
- size = mb->size;
- if (size < sizeof(MEMBLOCK))
- log_bug ("secure memory corrupted at block %p\n", (void *)mb);
- size -= ((size_t) &((MEMBLOCK*)0)->u.aligned.c);
-
- if( newsize <= size )
- return p; /* It is easier not to shrink the memory. */
- a = secmem_malloc( newsize );
- if ( a ) {
- memcpy(a, p, size);
- memset((char*)a+size, 0, newsize-size);
- secmem_free(p);
- }
- return a;
-}
-
-
-void
-secmem_free( void *a )
-{
- MEMBLOCK *mb;
- size_t size;
-
- if( !a )
- return;
-
- mb = (MEMBLOCK*)((char*)a - ((size_t) &((MEMBLOCK*)0)->u.aligned.c));
- size = mb->size;
- /* This does not make much sense: probably this memory is held in the
- * cache. We do it anyway: */
- wipememory2(mb, 0xff, size );
- wipememory2(mb, 0xaa, size );
- wipememory2(mb, 0x55, size );
- wipememory2(mb, 0x00, size );
- mb->size = size;
- mb->u.next = unused_blocks;
- unused_blocks = mb;
- cur_blocks--;
- cur_alloced -= size;
-}
-
-int
-m_is_secure( const void *p )
-{
- return p >= pool && p < (void*)((char*)pool+poolsize);
-}
-
-
-
-/****************
- * Warning: This code might be called by an interrupt handler
- * and frankly, there should really be such a handler,
- * to make sure that the memory is wiped out.
- * We hope that the OS wipes out mlocked memory after
- * receiving a SIGKILL - it really should do so, otherwise
- * there is no chance to get the secure memory cleaned.
- */
-void
-secmem_term()
-{
- if( !pool_okay )
- return;
-
- wipememory2( pool, 0xff, poolsize);
- wipememory2( pool, 0xaa, poolsize);
- wipememory2( pool, 0x55, poolsize);
- wipememory2( pool, 0x00, poolsize);
-#ifdef HAVE_MMAP
- if( pool_is_mmapped )
- munmap( pool, poolsize );
-#endif
- pool = NULL;
- pool_okay = 0;
- poolsize=0;
- poollen=0;
- unused_blocks=NULL;
-}
-
-
-void
-secmem_dump_stats()
-{
- if( disable_secmem )
- return;
- fprintf(stderr,
- "secmem usage: %u/%u bytes in %u/%u blocks of pool %lu/%lu\n",
- cur_alloced, max_alloced, cur_blocks, max_blocks,
- (ulong)poollen, (ulong)poolsize );
-}
diff --git a/util/simple-gettext.c b/util/simple-gettext.c
deleted file mode 100644
index 3249775bf..000000000
--- a/util/simple-gettext.c
+++ /dev/null
@@ -1,467 +0,0 @@
-/* simple-gettext.c - a simplified version of gettext.
- * Copyright (C) 1995, 1996, 1997, 1999,
- * 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-/* This is a simplified version of gettext written by Ulrich Drepper.
- * It is used for the Win32 version of GnuPG beucase all the overhead
- * of gettext is not needed and we have to do some special Win32 stuff.
- * I decided that this is far easier than to tweak gettext for the special
- * cases (I tried it but it is a lot of code). wk 15.09.99
- */
-
-#include <config.h>
-#ifdef USE_SIMPLE_GETTEXT
-#if !defined (_WIN32) && !defined (__CYGWIN32__)
-#error This file can only be used under Windows or Cygwin32
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "types.h"
-#include "util.h"
-
-
-/* The magic number of the GNU message catalog format. */
-#define MAGIC 0x950412de
-#define MAGIC_SWAPPED 0xde120495
-
-/* Revision number of the currently used .mo (binary) file format. */
-#define MO_REVISION_NUMBER 0
-
-
-/* Header for binary .mo file format. */
-struct mo_file_header
-{
- /* The magic number. */
- u32 magic;
- /* The revision number of the file format. */
- u32 revision;
- /* The number of strings pairs. */
- u32 nstrings;
- /* Offset of table with start offsets of original strings. */
- u32 orig_tab_offset;
- /* Offset of table with start offsets of translation strings. */
- u32 trans_tab_offset;
- /* Size of hashing table. */
- u32 hash_tab_size;
- /* Offset of first hashing entry. */
- u32 hash_tab_offset;
-};
-
-struct string_desc
-{
- /* Length of addressed string. */
- u32 length;
- /* Offset of string in file. */
- u32 offset;
-};
-
-
-struct overflow_space_s
-{
- struct overflow_space_s *next;
- u32 idx;
- char d[1];
-};
-
-struct loaded_domain
-{
- char *data;
- int must_swap;
- u32 nstrings;
- char *mapped; /* 0 = not yet mapped, 1 = mapped,
- 2 = mapped to
- overflow space */
- struct overflow_space_s *overflow_space;
- struct string_desc *orig_tab;
- struct string_desc *trans_tab;
- u32 hash_size;
- u32 *hash_tab;
-};
-
-
-static struct loaded_domain *the_domain;
-
-static __inline__ u32
-do_swap_u32( u32 i )
-{
- return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
-}
-
-#define SWAPIT(flag, data) ((flag) ? do_swap_u32(data) : (data) )
-
-
-/* We assume to have `unsigned long int' value with at least 32 bits. */
-#define HASHWORDBITS 32
-
-/* The so called `hashpjw' function by P.J. Weinberger
- [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
- 1986, 1987 Bell Telephone Laboratories, Inc.] */
-
-static __inline__ ulong
-hash_string( const char *str_param )
-{
- unsigned long int hval, g;
- const char *str = str_param;
-
- hval = 0;
- while (*str != '\0')
- {
- hval <<= 4;
- hval += (unsigned long int) *str++;
- g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
- if (g != 0)
- {
- hval ^= g >> (HASHWORDBITS - 8);
- hval ^= g;
- }
- }
- return hval;
-}
-
-
-static struct loaded_domain *
-load_domain( const char *filename )
-{
- FILE *fp;
- size_t size;
- struct stat st;
- struct mo_file_header *data = NULL;
- struct loaded_domain *domain = NULL;
- size_t to_read;
- char *read_ptr;
-
- fp = fopen( filename, "rb" );
- if( !fp )
- return NULL; /* can't open the file */
- /* we must know about the size of the file */
- if( fstat( fileno(fp ), &st )
- || (size = (size_t)st.st_size) != st.st_size
- || size < sizeof (struct mo_file_header) ) {
- fclose( fp );
- return NULL;
- }
-
- data = malloc( size );
- if( !data ) {
- fclose( fp );
- return NULL; /* out of memory */
- }
-
- to_read = size;
- read_ptr = (char *) data;
- do {
- long int nb = fread( read_ptr, 1, to_read, fp );
- if( nb < to_read ) {
- fclose (fp);
- free(data);
- return NULL; /* read error */
- }
- read_ptr += nb;
- to_read -= nb;
- } while( to_read > 0 );
- fclose (fp);
-
- /* Using the magic number we can test whether it really is a message
- * catalog file. */
- if( data->magic != MAGIC && data->magic != MAGIC_SWAPPED ) {
- /* The magic number is wrong: not a message catalog file. */
- free( data );
- return NULL;
- }
-
- domain = calloc( 1, sizeof *domain );
- if( !domain ) {
- free( data );
- return NULL;
- }
- domain->data = (char *) data;
- domain->must_swap = data->magic != MAGIC;
-
- /* Fill in the information about the available tables. */
- switch( SWAPIT(domain->must_swap, data->revision) ) {
- case 0:
- domain->nstrings = SWAPIT(domain->must_swap, data->nstrings);
- domain->orig_tab = (struct string_desc *)
- ((char *) data + SWAPIT(domain->must_swap, data->orig_tab_offset));
- domain->trans_tab = (struct string_desc *)
- ((char *) data + SWAPIT(domain->must_swap, data->trans_tab_offset));
- domain->hash_size = SWAPIT(domain->must_swap, data->hash_tab_size);
- domain->hash_tab = (u32 *)
- ((char *) data + SWAPIT(domain->must_swap, data->hash_tab_offset));
- break;
-
- default: /* This is an invalid revision. */
- free( data );
- free( domain );
- return NULL;
- }
-
- /* Allocate an array to keep track of code page mappings. */
- domain->mapped = calloc( 1, domain->nstrings );
- if( !domain->mapped ) {
- free( data );
- free( domain );
- return NULL;
- }
-
- return domain;
-}
-
-
-/****************
- * Set the file used for translations. Pass a NULL to disable
- * translation. A new filename may be set at anytime. If REGKEY is
- * not NULL, the function tries to selected the language the registry
- * key "Lang" below that key. WARNING: After changing the filename you
- * should not access any data retrieved by gettext().
- */
-int
-set_gettext_file ( const char *filename, const char *regkey )
-{
- struct loaded_domain *domain = NULL;
-
- if( filename && *filename ) {
- if( filename[0] == '/'
-#ifdef HAVE_DRIVE_LETTERS
- || ( isalpha(filename[0])
- && filename[1] == ':'
- && (filename[2] == '/' || filename[2] == '\\') )
-#endif
- ) {
- /* absolute path - use it as is */
- domain = load_domain( filename );
- }
- else if (regkey) { /* Standard. */
- char *instdir, *langid, *fname;
- char *p;
-
- instdir = read_w32_registry_string ("HKEY_LOCAL_MACHINE",
- regkey,
- "Install Directory");
- if (!instdir)
- return -1;
- langid = read_w32_registry_string (NULL, /* HKCU then HKLM */
- regkey,
- "Lang");
- if (!langid) {
- free (instdir);
- return -1;
- }
- /* Strip stuff after a dot in case the user tried to enter
- * the entire locale synatcs as usual for POSIX. */
- p = strchr (langid, '.');
- if (p)
- *p = 0;
-
- /* Build the key: "<instdir>/<domain>.nls/<langid>.mo" We
- use a directory below the installation directory with
- the domain included in case the software has been
- insalled with other software altogether at the same
- place. */
- fname = malloc (strlen (instdir) + 1 + strlen (filename) + 5
- + strlen (langid) + 3 + 1);
- if (!fname) {
- free (instdir);
- free (langid);
- return -1;
- }
- strcpy (stpcpy (stpcpy (stpcpy (stpcpy ( stpcpy (fname,
- instdir),"\\"), filename), ".nls\\"), langid), ".mo");
- free (instdir);
- free (langid);
-
- /* Better make sure that we don't mix forward and
- backward slashes. It seems that some Windoze
- versions don't accept this. */
- for (p=fname; *p; p++) {
- if (*p == '/')
- *p = '\\';
- }
- domain = load_domain (fname);
- free(fname);
- }
-
- if (!domain)
- return -1;
- }
-
- if( the_domain ) {
- struct overflow_space_s *os, *os2;
- free( the_domain->data );
- free( the_domain->mapped );
- for (os=the_domain->overflow_space; os; os = os2) {
- os2 = os->next;
- free (os);
- }
- free( the_domain );
- the_domain = NULL;
- }
- the_domain = domain;
- return 0;
-}
-
-
-static const char*
-get_string( struct loaded_domain *domain, u32 idx )
-{
- struct overflow_space_s *os;
- char *p;
-
- p = domain->data + SWAPIT(domain->must_swap, domain->trans_tab[idx].offset);
- if (!domain->mapped[idx])
- {
- size_t plen, buflen;
- char *buf;
-
- domain->mapped[idx] = 1;
-
- plen = strlen (p);
- buf = utf8_to_native (p, plen, -1);
- buflen = strlen (buf);
- if (buflen <= plen)
- strcpy (p, buf);
- else
- {
- /* There is not enough space for the translation - store it
- in the overflow_space else and mark that in the mapped
- array. Because we expect that this won't happen too
- often, we use a simple linked list. */
- os = malloc (sizeof *os + buflen);
- if (os)
- {
- os->idx = idx;
- strcpy (os->d, buf);
- os->next = domain->overflow_space;
- domain->overflow_space = os;
- p = os->d;
- }
- else
- p = "ERROR in GETTEXT MALLOC";
- }
- xfree (buf);
- }
- else if (domain->mapped[idx] == 2)
- { /* We need to get the string from the overflow_space. */
- for (os=domain->overflow_space; os; os = os->next)
- if (os->idx == idx)
- return (const char*)os->d;
- p = "ERROR in GETTEXT\n";
- }
- return (const char*)p;
-}
-
-
-
-const char *
-gettext( const char *msgid )
-{
- struct loaded_domain *domain;
- size_t act = 0;
- size_t top, bottom;
-
- if( !(domain = the_domain) )
- goto not_found;
-
- /* Locate the MSGID and its translation. */
- if( domain->hash_size > 2 && domain->hash_tab ) {
- /* Use the hashing table. */
- u32 len = strlen (msgid);
- u32 hash_val = hash_string (msgid);
- u32 idx = hash_val % domain->hash_size;
- u32 incr = 1 + (hash_val % (domain->hash_size - 2));
- u32 nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx]);
-
- if ( !nstr ) /* Hash table entry is empty. */
- goto not_found;
-
- if( SWAPIT(domain->must_swap,
- domain->orig_tab[nstr - 1].length) == len
- && !strcmp( msgid,
- domain->data + SWAPIT(domain->must_swap,
- domain->orig_tab[nstr - 1].offset)) )
- return get_string( domain, nstr - 1 );
-
- for(;;) {
- if (idx >= domain->hash_size - incr)
- idx -= domain->hash_size - incr;
- else
- idx += incr;
-
- nstr = SWAPIT(domain->must_swap, domain->hash_tab[idx]);
- if( !nstr )
- goto not_found; /* Hash table entry is empty. */
-
- if ( SWAPIT(domain->must_swap,
- domain->orig_tab[nstr - 1].length) == len
- && !strcmp (msgid,
- domain->data + SWAPIT(domain->must_swap,
- domain->orig_tab[nstr - 1].offset)))
- return get_string( domain, nstr-1 );
- }
- /* NOTREACHED */
- }
-
- /* Now we try the default method: binary search in the sorted
- array of messages. */
- bottom = 0;
- top = domain->nstrings;
- while( bottom < top ) {
- int cmp_val;
-
- act = (bottom + top) / 2;
- cmp_val = strcmp(msgid, domain->data
- + SWAPIT(domain->must_swap,
- domain->orig_tab[act].offset));
- if (cmp_val < 0)
- top = act;
- else if (cmp_val > 0)
- bottom = act + 1;
- else
- return get_string( domain, act );
- }
-
- not_found:
- return msgid;
-}
-
-#if 0
- unsigned int cp1, cp2;
-
- cp1 = GetConsoleCP();
- cp2 = GetConsoleOutputCP();
-
- log_info("InputCP=%u OutputCP=%u\n", cp1, cp2 );
-
- if( !SetConsoleOutputCP( 1252 ) )
- log_info("SetConsoleOutputCP failed: %s\n", w32_strerror (0));
-
- cp1 = GetConsoleCP();
- cp2 = GetConsoleOutputCP();
- log_info("InputCP=%u OutputCP=%u after switch1\n", cp1, cp2 );
-#endif
-
-#endif /* USE_SIMPLE_GETTEXT */
diff --git a/util/srv.c b/util/srv.c
deleted file mode 100644
index 95187dbc8..000000000
--- a/util/srv.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/* srv.c - DNS SRV code
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <config.h>
-#include <sys/types.h>
-#ifdef _WIN32
-#include <windows.h>
-#else
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-#endif
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "memory.h"
-#include "types.h"
-#include "srv.h"
-
-/* Not every installation has gotten around to supporting SRVs
- yet... */
-#ifndef T_SRV
-#define T_SRV 33
-#endif
-
-static int
-priosort(const void *a,const void *b)
-{
- const struct srventry *sa=a,*sb=b;
- if(sa->priority>sb->priority)
- return 1;
- else if(sa->priority<sb->priority)
- return -1;
- else
- return 0;
-}
-
-int
-getsrv(const char *name,struct srventry **list)
-{
- unsigned char answer[PACKETSZ];
- int r,srvcount=0;
- unsigned char *pt,*emsg;
- u16 count,dlen;
-
- *list=NULL;
-
- r=res_query(name,C_IN,T_SRV,answer,PACKETSZ);
- if(r<sizeof(HEADER) || r>PACKETSZ)
- return -1;
-
- if((((HEADER *)answer)->rcode)==NOERROR &&
- (count=ntohs(((HEADER *)answer)->ancount)))
- {
- int i,rc;
-
- emsg=&answer[r];
- pt=&answer[sizeof(HEADER)];
-
- /* Skip over the query */
-
- rc=dn_skipname(pt,emsg);
- if(rc==-1)
- goto fail;
-
- pt+=rc+QFIXEDSZ;
-
- while(count-->0 && pt<emsg)
- {
- struct srventry *srv=NULL;
- u16 type,class;
-
- *list=xrealloc(*list,(srvcount+1)*sizeof(struct srventry));
- memset(&(*list)[srvcount],0,sizeof(struct srventry));
- srv=&(*list)[srvcount];
- srvcount++;
-
- rc=dn_skipname(pt,emsg); /* the name we just queried for */
- if(rc==-1)
- goto fail;
- pt+=rc;
-
- /* Truncated message? */
- if((emsg-pt)<16)
- goto fail;
-
- type=*pt++ << 8;
- type|=*pt++;
- /* We asked for SRV and got something else !? */
- if(type!=T_SRV)
- goto fail;
-
- class=*pt++ << 8;
- class|=*pt++;
- /* We asked for IN and got something else !? */
- if(class!=C_IN)
- goto fail;
-
- pt+=4; /* ttl */
- dlen=*pt++ << 8;
- dlen|=*pt++;
- srv->priority=*pt++ << 8;
- srv->priority|=*pt++;
- srv->weight=*pt++ << 8;
- srv->weight|=*pt++;
- srv->port=*pt++ << 8;
- srv->port|=*pt++;
-
- /* Get the name. 2782 doesn't allow name compression, but
- dn_expand still works to pull the name out of the
- packet. */
- rc=dn_expand(answer,emsg,pt,srv->target,MAXDNAME);
- if(rc==1 && srv->target[0]==0) /* "." */
- goto noanswer;
- if(rc==-1)
- goto fail;
- pt+=rc;
- /* Corrupt packet? */
- if(dlen!=rc+6)
- goto fail;
-
-#if 0
- printf("count=%d\n",srvcount);
- printf("priority=%d\n",srv->priority);
- printf("weight=%d\n",srv->weight);
- printf("port=%d\n",srv->port);
- printf("target=%s\n",srv->target);
-#endif
- }
-
- /* Now we have an array of all the srv records. */
-
- /* Order by priority */
- qsort(*list,srvcount,sizeof(struct srventry),priosort);
-
- /* For each priority, move the zero-weighted items first. */
- for(i=0;i<srvcount;i++)
- {
- int j;
-
- for(j=i;j<srvcount && (*list)[i].priority==(*list)[j].priority;j++)
- {
- if((*list)[j].weight==0)
- {
- /* Swap j with i */
- if(j!=i)
- {
- struct srventry temp;
-
- memcpy(&temp,&(*list)[j],sizeof(struct srventry));
- memcpy(&(*list)[j],&(*list)[i],sizeof(struct srventry));
- memcpy(&(*list)[i],&temp,sizeof(struct srventry));
- }
-
- break;
- }
- }
- }
-
- /* Run the RFC-2782 weighting algorithm. We don't need very
- high quality randomness for this, so regular libc srand/rand
- is sufficient. */
- srand(time(NULL)*getpid());
-
- for(i=0;i<srvcount;i++)
- {
- int j;
- float prio_count=0,chose;
-
- for(j=i;j<srvcount && (*list)[i].priority==(*list)[j].priority;j++)
- {
- prio_count+=(*list)[j].weight;
- (*list)[j].run_count=prio_count;
- }
-
- chose=prio_count*rand()/RAND_MAX;
-
- for(j=i;j<srvcount && (*list)[i].priority==(*list)[j].priority;j++)
- {
- if(chose<=(*list)[j].run_count)
- {
- /* Swap j with i */
- if(j!=i)
- {
- struct srventry temp;
-
- memcpy(&temp,&(*list)[j],sizeof(struct srventry));
- memcpy(&(*list)[j],&(*list)[i],sizeof(struct srventry));
- memcpy(&(*list)[i],&temp,sizeof(struct srventry));
- }
- break;
- }
- }
- }
- }
-
- return srvcount;
-
- noanswer:
- xfree(*list);
- *list=NULL;
- return 0;
-
- fail:
- xfree(*list);
- *list=NULL;
- return -1;
-}
-
-#ifdef TEST
-int
-main(int argc,char *argv[])
-{
- struct srventry *srv;
- int rc,i;
-
- rc=getsrv("_hkp._tcp.wwwkeys.pgp.net",&srv);
- printf("Count=%d\n\n",rc);
- for(i=0;i<rc;i++)
- {
- printf("priority=%d\n",srv[i].priority);
- printf("weight=%d\n",srv[i].weight);
- printf("port=%d\n",srv[i].port);
- printf("target=%s\n",srv[i].target);
- printf("\n");
- }
-
- xfree(srv);
-
- return 0;
-}
-#endif /* TEST */
-
-/*
-Local Variables:
-compile-command: "cc -DTEST -I.. -I../include -Wall -g -o srv srv.c -lresolv libutil.a"
-End:
-*/
diff --git a/util/srv.h b/util/srv.h
deleted file mode 100644
index a81ebd573..000000000
--- a/util/srv.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* srv.h
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#ifndef _SRV_H_
-#define _SRV_H_
-
-#ifdef USE_DNS_SRV
-#ifdef _WIN32
-#include <windows.h>
-#else
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-#endif /* !_WIN32 */
-#endif /* USE_DNS_SRV */
-#include "types.h"
-
-#ifndef MAXDNAME
-#define MAXDNAME 1025
-#endif
-
-struct srventry
-{
- u16 priority;
- u16 weight;
- u16 port;
- int run_count;
- char target[MAXDNAME];
-};
-
-int getsrv(const char *name,struct srventry **list);
-
-#endif /* !_SRV_H_ */
diff --git a/util/strgutil.c b/util/strgutil.c
deleted file mode 100644
index cffdfcf77..000000000
--- a/util/strgutil.c
+++ /dev/null
@@ -1,1373 +0,0 @@
-/* strgutil.c - string utilities
- * Copyright (C) 1994, 1998, 1999, 2000, 2001,
- * 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <config.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#ifdef HAVE_LANGINFO_CODESET
-#include <langinfo.h>
-#endif
-
-/* For W32 we use dynamic loading of the iconv dll and don't need any
- * iconv headers at all. */
-#ifndef _WIN32
-# ifndef HAVE_ICONV
-# undef USE_GNUPG_ICONV
-# endif
-#endif
-
-#ifdef USE_GNUPG_ICONV
-# include <limits.h>
-# ifndef _WIN32
-# include <iconv.h>
-# endif
-#endif
-
-#include "types.h"
-#include "util.h"
-#include "memory.h"
-#include "i18n.h"
-#include "dynload.h"
-
-
-#ifndef USE_GNUPG_ICONV
-static ushort koi8_unicode[128] = {
- 0x2500,0x2502,0x250c,0x2510,0x2514,0x2518,0x251c,0x2524,
- 0x252c,0x2534,0x253c,0x2580,0x2584,0x2588,0x258c,0x2590,
- 0x2591,0x2592,0x2593,0x2320,0x25a0,0x2219,0x221a,0x2248,
- 0x2264,0x2265,0x00a0,0x2321,0x00b0,0x00b2,0x00b7,0x00f7,
- 0x2550,0x2551,0x2552,0x0451,0x2553,0x2554,0x2555,0x2556,
- 0x2557,0x2558,0x2559,0x255a,0x255b,0x255c,0x255d,0x255e,
- 0x255f,0x2560,0x2561,0x0401,0x2562,0x2563,0x2564,0x2565,
- 0x2566,0x2567,0x2568,0x2569,0x256a,0x256b,0x256c,0x00a9,
- 0x044e,0x0430,0x0431,0x0446,0x0434,0x0435,0x0444,0x0433,
- 0x0445,0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e,
- 0x043f,0x044f,0x0440,0x0441,0x0442,0x0443,0x0436,0x0432,
- 0x044c,0x044b,0x0437,0x0448,0x044d,0x0449,0x0447,0x044a,
- 0x042e,0x0410,0x0411,0x0426,0x0414,0x0415,0x0424,0x0413,
- 0x0425,0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,
- 0x041f,0x042f,0x0420,0x0421,0x0422,0x0423,0x0416,0x0412,
- 0x042c,0x042b,0x0417,0x0428,0x042d,0x0429,0x0427,0x042a
-};
-
-static ushort latin2_unicode[128] = {
- 0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
- 0x0088,0x0089,0x008A,0x008B,0x008C,0x008D,0x008E,0x008F,
- 0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
- 0x0098,0x0099,0x009A,0x009B,0x009C,0x009D,0x009E,0x009F,
- 0x00A0,0x0104,0x02D8,0x0141,0x00A4,0x013D,0x015A,0x00A7,
- 0x00A8,0x0160,0x015E,0x0164,0x0179,0x00AD,0x017D,0x017B,
- 0x00B0,0x0105,0x02DB,0x0142,0x00B4,0x013E,0x015B,0x02C7,
- 0x00B8,0x0161,0x015F,0x0165,0x017A,0x02DD,0x017E,0x017C,
- 0x0154,0x00C1,0x00C2,0x0102,0x00C4,0x0139,0x0106,0x00C7,
- 0x010C,0x00C9,0x0118,0x00CB,0x011A,0x00CD,0x00CE,0x010E,
- 0x0110,0x0143,0x0147,0x00D3,0x00D4,0x0150,0x00D6,0x00D7,
- 0x0158,0x016E,0x00DA,0x0170,0x00DC,0x00DD,0x0162,0x00DF,
- 0x0155,0x00E1,0x00E2,0x0103,0x00E4,0x013A,0x0107,0x00E7,
- 0x010D,0x00E9,0x0119,0x00EB,0x011B,0x00ED,0x00EE,0x010F,
- 0x0111,0x0144,0x0148,0x00F3,0x00F4,0x0151,0x00F6,0x00F7,
- 0x0159,0x016F,0x00FA,0x0171,0x00FC,0x00FD,0x0163,0x02D9
-};
-#endif /*!USE_GNUPG_ICONV*/
-
-
-#ifndef MB_LEN_MAX
-#define MB_LEN_MAX 16
-#endif
-
-
-static const char *active_charset_name = "iso-8859-1";
-static ushort *active_charset = NULL;
-static int no_translation = 0;
-static int use_iconv = 0;
-
-
-#ifdef _WIN32
-typedef void* iconv_t;
-#ifndef ICONV_CONST
-#define ICONV_CONST const
-#endif
-
-iconv_t (* __stdcall iconv_open) (const char *tocode, const char *fromcode);
-size_t (* __stdcall iconv) (iconv_t cd,
- const char **inbuf, size_t *inbytesleft,
- char **outbuf, size_t *outbytesleft);
-int (* __stdcall iconv_close) (iconv_t cd);
-
-#endif /*_WIN32*/
-
-
-
-#ifdef _WIN32
-static int
-load_libiconv (void)
-{
- static int done;
-
- if (!done)
- {
- void *handle;
-
- done = 1; /* Do it right now because we might get called recursivly
- through gettext. */
-
- handle = dlopen ("iconv.dll", RTLD_LAZY);
- if (handle)
- {
- iconv_open = dlsym (handle, "libiconv_open");
- if (iconv_open)
- iconv = dlsym (handle, "libiconv");
- if (iconv)
- iconv_close = dlsym (handle, "libiconv_close");
- }
- if (!handle || !iconv_close)
- {
- log_info (_("error loading `%s': %s\n"),
- "iconv.dll", dlerror ());
- log_info(_("please see http://www.gnupg.org/download/iconv.html "
- "for more information\n"));
- iconv_open = NULL;
- iconv = NULL;
- iconv_close = NULL;
- if (handle)
- dlclose (handle);
- }
- }
- return iconv_open? 0: -1;
-}
-#endif /* _WIN32 */
-
-
-
-
-void
-free_strlist( STRLIST sl )
-{
- STRLIST sl2;
-
- for(; sl; sl = sl2 ) {
- sl2 = sl->next;
- xfree(sl);
- }
-}
-
-
-STRLIST
-add_to_strlist( STRLIST *list, const char *string )
-{
- STRLIST sl;
-
- sl = xmalloc( sizeof *sl + strlen(string));
- sl->flags = 0;
- strcpy(sl->d, string);
- sl->next = *list;
- *list = sl;
- return sl;
-}
-
-/****************
- * Same as add_to_strlist() but if is_utf8 is *not* set a conversion
- * to UTF8 is done
- */
-STRLIST
-add_to_strlist2( STRLIST *list, const char *string, int is_utf8 )
-{
- STRLIST sl;
-
- if( is_utf8 )
- sl = add_to_strlist( list, string );
- else {
- char *p = native_to_utf8( string );
- sl = add_to_strlist( list, p );
- xfree( p );
- }
- return sl;
-}
-
-STRLIST
-append_to_strlist( STRLIST *list, const char *string )
-{
- STRLIST r, sl;
-
- sl = xmalloc( sizeof *sl + strlen(string));
- sl->flags = 0;
- strcpy(sl->d, string);
- sl->next = NULL;
- if( !*list )
- *list = sl;
- else {
- for( r = *list; r->next; r = r->next )
- ;
- r->next = sl;
- }
- return sl;
-}
-
-STRLIST
-append_to_strlist2( STRLIST *list, const char *string, int is_utf8 )
-{
- STRLIST sl;
-
- if( is_utf8 )
- sl = append_to_strlist( list, string );
- else {
- char *p = native_to_utf8( string );
- sl = append_to_strlist( list, p );
- xfree( p );
- }
- return sl;
-}
-
-
-STRLIST
-strlist_prev( STRLIST head, STRLIST node )
-{
- STRLIST n;
-
- for(n=NULL; head && head != node; head = head->next )
- n = head;
- return n;
-}
-
-STRLIST
-strlist_last( STRLIST node )
-{
- if( node )
- for( ; node->next ; node = node->next )
- ;
- return node;
-}
-
-char *
-pop_strlist( STRLIST *list )
-{
- char *str=NULL;
- STRLIST sl=*list;
-
- if(sl)
- {
- str=xmalloc(strlen(sl->d)+1);
- strcpy(str,sl->d);
-
- *list=sl->next;
- xfree(sl);
- }
-
- return str;
-}
-
-/****************
- * Look for the substring SUB in buffer and return a pointer to that
- * substring in BUF or NULL if not found.
- * Comparison is case-insensitive.
- */
-const char *
-memistr( const char *buf, size_t buflen, const char *sub )
-{
- const byte *t, *s ;
- size_t n;
-
- for( t=buf, n=buflen, s=sub ; n ; t++, n-- )
- if( toupper(*t) == toupper(*s) ) {
- for( buf=t++, buflen = n--, s++;
- n && toupper(*t) == toupper(*s); t++, s++, n-- )
- ;
- if( !*s )
- return buf;
- t = buf; n = buflen; s = sub ;
- }
-
- return NULL ;
-}
-
-const char *
-ascii_memistr( const char *buf, size_t buflen, const char *sub )
-{
- const byte *t, *s ;
- size_t n;
-
- for( t=buf, n=buflen, s=sub ; n ; t++, n-- )
- if( ascii_toupper(*t) == ascii_toupper(*s) ) {
- for( buf=t++, buflen = n--, s++;
- n && ascii_toupper(*t) == ascii_toupper(*s); t++, s++, n-- )
- ;
- if( !*s )
- return buf;
- t = buf; n = buflen; s = sub ;
- }
-
- return NULL ;
-}
-
-
-/* Like strncpy() but copy at max N-1 bytes and append a '\0'. With
- * N given as 0 nothing is copied at all. With DEST given as NULL
- * sufficient memory is allocated using xmalloc (note that xmalloc is
- * guaranteed to succeed or to abort the process). */
-char *
-mem2str( char *dest , const void *src , size_t n )
-{
- char *d;
- const char *s;
-
- if( n ) {
- if( !dest )
- dest = xmalloc( n ) ;
- d = dest;
- s = src ;
- for(n--; n && *s; n-- )
- *d++ = *s++;
- *d = '\0' ;
- }
-
- return dest ;
-}
-
-
-/*
- * Remove leading and trailing white spaces
- */
-char *
-trim_spaces( char *str )
-{
- char *string, *p, *mark;
-
- string = str;
- /* Find first non space character. */
- for( p=string; *p && isspace( *(byte*)p ) ; p++ )
- ;
- /* Move characters. */
- for( (mark = NULL); (*string = *p); string++, p++ )
- if( isspace( *(byte*)p ) ) {
- if( !mark )
- mark = string ;
- }
- else
- mark = NULL ;
- if( mark )
- *mark = '\0' ; /* Remove trailing spaces. */
-
- return str ;
-}
-
-
-
-unsigned int
-trim_trailing_chars( byte *line, unsigned len, const char *trimchars )
-{
- byte *p, *mark;
- unsigned n;
-
- for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
- if( strchr(trimchars, *p ) ) {
- if( !mark )
- mark = p;
- }
- else
- mark = NULL;
- }
-
- if( mark ) {
- *mark = 0;
- return mark - line;
- }
- return len;
-}
-
-/****************
- * Remove trailing white spaces and return the length of the buffer
- */
-unsigned
-trim_trailing_ws( byte *line, unsigned len )
-{
- return trim_trailing_chars( line, len, " \t\r\n" );
-}
-
-
-unsigned int
-check_trailing_chars( const byte *line, unsigned int len,
- const char *trimchars )
-{
- const byte *p, *mark;
- unsigned int n;
-
- for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
- if( strchr(trimchars, *p ) ) {
- if( !mark )
- mark = p;
- }
- else
- mark = NULL;
- }
-
- if( mark ) {
- return mark - line;
- }
- return len;
-}
-
-
-/****************
- * Remove trailing white spaces and return the length of the buffer
- */
-unsigned int
-check_trailing_ws( const byte *line, unsigned int len )
-{
- return check_trailing_chars( line, len, " \t\r\n" );
-}
-
-
-
-int
-string_count_chr( const char *string, int c )
-{
- int count;
- for(count=0; *string; string++ )
- if( *string == c )
- count++;
- return count;
-}
-
-#ifdef USE_GNUPG_ICONV
-static void
-handle_iconv_error (const char *to, const char *from, int use_fallback)
-{
- if (errno == EINVAL)
- {
- static int shown1, shown2;
- int x;
-
- if (to && !strcmp (to, "utf-8"))
- {
- x = shown1;
- shown1 = 1;
- }
- else
- {
- x = shown2;
- shown2 = 1;
- }
-
- if (!x)
- log_info (_("conversion from `%s' to `%s' not available\n"),
- from, to);
- }
- else
- {
- static int shown;
-
- if (!shown)
- log_info (_("iconv_open failed: %s\n"), strerror (errno));
- shown = 1;
- }
-
- if (use_fallback)
- {
- /* To avoid further error messages we fallback to Latin-1 for the
- native encoding. This is justified as one can expect that on a
- utf-8 enabled system nl_langinfo() will work and thus we won't
- never get to here. Thus Latin-1 seems to be a reasonable
- default. */
- active_charset_name = "iso-8859-1";
- no_translation = 0;
- active_charset = NULL;
- use_iconv = 0;
- }
-}
-#endif /*USE_GNUPG_ICONV*/
-
-int
-set_native_charset( const char *newset )
-{
- const char *full_newset;
-
- if (!newset) {
-#ifdef _WIN32
- static char codepage[30];
- unsigned int cpno;
- const char *aliases;
-
- /* We are a console program thus we need to use the
- GetConsoleOutputCP function and not the the GetACP which
- would give the codepage for a GUI program. Note this is
- not a bulletproof detection because GetConsoleCP might
- return a different one for console input. Not sure how to
- cope with that. If the console Code page is not known we
- fall back to the system code page. */
- cpno = GetConsoleOutputCP ();
- if (!cpno)
- cpno = GetACP ();
- sprintf (codepage, "CP%u", cpno );
- /* Resolve alias. We use a long string string and not the
- usual array to optimize if the code is taken to a DSO.
- Taken from libiconv 1.9.2. */
- newset = codepage;
- for (aliases = ("CP936" "\0" "GBK" "\0"
- "CP1361" "\0" "JOHAB" "\0"
- "CP20127" "\0" "ASCII" "\0"
- "CP20866" "\0" "KOI8-R" "\0"
- "CP21866" "\0" "KOI8-RU" "\0"
- "CP28591" "\0" "ISO-8859-1" "\0"
- "CP28592" "\0" "ISO-8859-2" "\0"
- "CP28593" "\0" "ISO-8859-3" "\0"
- "CP28594" "\0" "ISO-8859-4" "\0"
- "CP28595" "\0" "ISO-8859-5" "\0"
- "CP28596" "\0" "ISO-8859-6" "\0"
- "CP28597" "\0" "ISO-8859-7" "\0"
- "CP28598" "\0" "ISO-8859-8" "\0"
- "CP28599" "\0" "ISO-8859-9" "\0"
- "CP28605" "\0" "ISO-8859-15" "\0"
- "CP65001" "\0" "UTF-8" "\0");
- *aliases;
- aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1)
- {
- if (!strcmp (codepage, aliases) ||(*aliases == '*' && !aliases[1]))
- {
- newset = aliases + strlen (aliases) + 1;
- break;
- }
- }
-
-#else
-#ifdef HAVE_LANGINFO_CODESET
- newset = nl_langinfo (CODESET);
-#else /* !HAVE_LANGINFO_CODESET */
- /* Try to get the used charset from environment variables. */
- static char codepage[30];
- const char *lc, *dot, *mod;
-
- strcpy (codepage, "iso-8859-1");
- lc = getenv ("LC_ALL");
- if (!lc || !*lc) {
- lc = getenv ("LC_CTYPE");
- if (!lc || !*lc)
- lc = getenv ("LANG");
- }
- if (lc && *lc) {
- dot = strchr (lc, '.');
- if (dot) {
- mod = strchr (++dot, '@');
- if (!mod)
- mod = dot + strlen (dot);
- if (mod - dot < sizeof codepage && dot != mod) {
- memcpy (codepage, dot, mod - dot);
- codepage [mod - dot] = 0;
- }
- }
- }
- newset = codepage;
-#endif /* !HAVE_LANGINFO_CODESET */
-#endif
- }
-
- full_newset = newset;
- if (strlen (newset) > 3 && !ascii_memcasecmp (newset, "iso", 3)) {
- newset += 3;
- if (*newset == '-' || *newset == '_')
- newset++;
- }
-
- /* Note that we silently assume that plain ASCII is actually meant
- as Latin-1. This makes sense because many Unix system don't
- have their locale set up properly and thus would get annoying
- error messages and we have to handle all the "bug"
- reports. Latin-1 has always been the character set used for 8
- bit characters on Unix systems. */
- if( !*newset
- || !ascii_strcasecmp (newset, "8859-1" )
- || !ascii_strcasecmp (newset, "646" )
- || !ascii_strcasecmp (newset, "ASCII" )
- || !ascii_strcasecmp (newset, "ANSI_X3.4-1968" )
- ) {
- active_charset_name = "iso-8859-1";
- no_translation = 0;
- active_charset = NULL;
- use_iconv = 0;
- }
- else if( !ascii_strcasecmp (newset, "utf8" )
- || !ascii_strcasecmp(newset, "utf-8") ) {
- active_charset_name = "utf-8";
- no_translation = 1;
- active_charset = NULL;
- use_iconv = 0;
- }
-#ifdef USE_GNUPG_ICONV
- else {
- iconv_t cd;
-
-#ifdef _WIN32
- if (load_libiconv ())
- return G10ERR_GENERAL;
-#endif /*_WIN32*/
-
- cd = iconv_open (full_newset, "utf-8");
- if (cd == (iconv_t)-1) {
- handle_iconv_error (full_newset, "utf-8", 0);
- return G10ERR_GENERAL;
- }
- iconv_close (cd);
- cd = iconv_open ("utf-8", full_newset);
- if (cd == (iconv_t)-1) {
- handle_iconv_error ("utf-8", full_newset, 0);
- return G10ERR_GENERAL;
- }
- iconv_close (cd);
- active_charset_name = full_newset;
- no_translation = 0;
- active_charset = NULL;
- use_iconv = 1;
- }
-#else /*!USE_GNUPG_ICONV*/
- else if( !ascii_strcasecmp( newset, "8859-2" ) ) {
- active_charset_name = "iso-8859-2";
- no_translation = 0;
- active_charset = latin2_unicode;
- use_iconv = 0;
- }
- else if( !ascii_strcasecmp( newset, "koi8-r" ) ) {
- active_charset_name = "koi8-r";
- no_translation = 0;
- active_charset = koi8_unicode;
- use_iconv = 0;
- }
- else
- return G10ERR_GENERAL;
-#endif /*!USE_GNUPG_ICONV*/
- return 0;
-}
-
-const char*
-get_native_charset()
-{
- return active_charset_name;
-}
-
-/****************
- * Convert string, which is in native encoding to UTF8 and return the
- * new allocated UTF8 string.
- */
-char *
-native_to_utf8( const char *string )
-{
- const byte *s;
- char *buffer;
- byte *p;
- size_t length=0;
-
- if (no_translation)
- { /* Already utf-8 encoded. */
- buffer = xstrdup (string);
- }
- else if( !active_charset && !use_iconv) /* Shortcut implementation
- for Latin-1. */
- {
- for(s=string; *s; s++ )
- {
- length++;
- if( *s & 0x80 )
- length++;
- }
- buffer = xmalloc( length + 1 );
- for(p=buffer, s=string; *s; s++ )
- {
- if( *s & 0x80 )
- {
- *p++ = 0xc0 | ((*s >> 6) & 3);
- *p++ = 0x80 | ( *s & 0x3f );
- }
- else
- *p++ = *s;
- }
- *p = 0;
- }
- else /* Need to use a translation table. */
- {
-#ifdef USE_GNUPG_ICONV
- iconv_t cd;
- const char *inptr;
- char *outptr;
- size_t inbytes, outbytes;
-
- cd = iconv_open ("utf-8", active_charset_name);
- if (cd == (iconv_t)-1)
- {
- handle_iconv_error ("utf-8", active_charset_name, 1);
- return native_to_utf8 (string);
- }
-
- for (s=string; *s; s++ )
- {
- length++;
- if ((*s & 0x80))
- length += 5; /* We may need up to 6 bytes for the utf8 output. */
- }
- buffer = xmalloc (length + 1);
-
- inptr = string;
- inbytes = strlen (string);
- outptr = buffer;
- outbytes = length;
- if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes,
- &outptr, &outbytes) == (size_t)-1)
- {
- static int shown;
-
- if (!shown)
- log_info (_("conversion from `%s' to `%s' failed: %s\n"),
- active_charset_name, "utf-8", strerror (errno));
- shown = 1;
- /* We don't do any conversion at all but use the strings as is. */
- strcpy (buffer, string);
- }
- else /* Success. */
- {
- *outptr = 0;
- /* We could realloc the buffer now but I doubt that it makes
- much sense given that it will get freed anyway soon
- after. */
- }
- iconv_close (cd);
-
-#else /*!USE_GNUPG_ICONV*/
- for(s=string; *s; s++ )
- {
- length++;
- if( *s & 0x80 )
- length += 2; /* We may need up to 3 bytes. */
- }
- buffer = xmalloc( length + 1 );
- for(p=buffer, s=string; *s; s++ ) {
- if( *s & 0x80 ) {
- ushort val = active_charset[ *s & 0x7f ];
- if( val < 0x0800 ) {
- *p++ = 0xc0 | ( (val >> 6) & 0x1f );
- *p++ = 0x80 | ( val & 0x3f );
- }
- else {
- *p++ = 0xe0 | ( (val >> 12) & 0x0f );
- *p++ = 0x80 | ( (val >> 6) & 0x3f );
- *p++ = 0x80 | ( val & 0x3f );
- }
- }
- else
- *p++ = *s;
- }
- *p = 0;
-#endif /*!USE_GNUPG_ICONV*/
-
- }
- return buffer;
-}
-
-
-/****************
- * Convert string, which is in UTF8 to native encoding. illegal
- * encodings by some "\xnn" and quote all control characters. A
- * character with value DELIM will always be quoted, it must be a
- * vanilla ASCII character. A DELIM value of -1 is special: it disables
- * all quoting of control characters.
- */
-char *
-utf8_to_native( const char *string, size_t length, int delim )
-{
- int nleft;
- int i;
- byte encbuf[8];
- int encidx;
- const byte *s;
- size_t n;
- byte *buffer = NULL, *p = NULL;
- unsigned long val = 0;
- size_t slen;
- int resync = 0;
-
- /* 1. pass (p==NULL): count the extended utf-8 characters */
- /* 2. pass (p!=NULL): create string */
- for( ;; ) {
- for( slen=length, nleft=encidx=0, n=0, s=string; slen; s++, slen-- ) {
- if( resync ) {
- if( !(*s < 128 || (*s >= 0xc0 && *s <= 0xfd)) ) {
- /* still invalid */
- if( p ) {
- sprintf(p, "\\x%02x", *s );
- p += 4;
- }
- n += 4;
- continue;
- }
- resync = 0;
- }
- if( !nleft ) {
- if( !(*s & 0x80) ) { /* plain ascii */
- if( delim != -1
- && (*s < 0x20 || *s == 0x7f || *s == delim
- || (delim && *s=='\\'))) {
- n++;
- if( p )
- *p++ = '\\';
- switch( *s ) {
- case '\n': n++; if( p ) *p++ = 'n'; break;
- case '\r': n++; if( p ) *p++ = 'r'; break;
- case '\f': n++; if( p ) *p++ = 'f'; break;
- case '\v': n++; if( p ) *p++ = 'v'; break;
- case '\b': n++; if( p ) *p++ = 'b'; break;
- case 0 : n++; if( p ) *p++ = '0'; break;
- default:
- n += 3;
- if ( p ) {
- sprintf( p, "x%02x", *s );
- p += 3;
- }
- break;
- }
- }
- else {
- if( p ) *p++ = *s;
- n++;
- }
- }
- else if( (*s & 0xe0) == 0xc0 ) { /* 110x xxxx */
- val = *s & 0x1f;
- nleft = 1;
- encidx = 0;
- encbuf[encidx++] = *s;
- }
- else if( (*s & 0xf0) == 0xe0 ) { /* 1110 xxxx */
- val = *s & 0x0f;
- nleft = 2;
- encidx = 0;
- encbuf[encidx++] = *s;
- }
- else if( (*s & 0xf8) == 0xf0 ) { /* 1111 0xxx */
- val = *s & 0x07;
- nleft = 3;
- encidx = 0;
- encbuf[encidx++] = *s;
- }
- else if( (*s & 0xfc) == 0xf8 ) { /* 1111 10xx */
- val = *s & 0x03;
- nleft = 4;
- encidx = 0;
- encbuf[encidx++] = *s;
- }
- else if( (*s & 0xfe) == 0xfc ) { /* 1111 110x */
- val = *s & 0x01;
- nleft = 5;
- encidx = 0;
- encbuf[encidx++] = *s;
- }
- else { /* invalid encoding: print as \xnn */
- if( p ) {
- sprintf(p, "\\x%02x", *s );
- p += 4;
- }
- n += 4;
- resync = 1;
- }
- }
- else if( *s < 0x80 || *s >= 0xc0 ) { /* invalid */
- if( p ) {
- for(i=0; i < encidx; i++ ) {
- sprintf(p, "\\x%02x", encbuf[i] );
- p += 4;
- }
- sprintf(p, "\\x%02x", *s );
- p += 4;
- }
- n += 4 + 4*encidx;
- nleft = 0;
- encidx = 0;
- resync = 1;
- }
- else {
- encbuf[encidx++] = *s;
- val <<= 6;
- val |= *s & 0x3f;
- if( !--nleft ) { /* ready */
- if (no_translation) {
- if( p ) {
- for(i=0; i < encidx; i++ )
- *p++ = encbuf[i];
- }
- n += encidx;
- encidx = 0;
- }
-#ifdef USE_GNUPG_ICONV
- else if(use_iconv) {
- /* Our strategy for using iconv is a bit
- * strange but it better keeps compatibility
- * with previous versions in regard to how
- * invalid encodings are displayed. What we
- * do is to keep the utf-8 as is and have the
- * real translation step then at the end.
- * Yes, I know that this is ugly. However we
- * are short of the 1.4 release and for this
- * branch we should not mee too much around
- * with iconv things. One reason for this is
- * that we don't know enough about non-GNU
- * iconv implementation and want to minimize
- * the risk of breaking the code on too many
- * platforms. */
- if( p ) {
- for(i=0; i < encidx; i++ )
- *p++ = encbuf[i];
- }
- n += encidx;
- encidx = 0;
- }
-#endif /*USE_GNUPG_ICONV*/
- else if( active_charset ) { /* table lookup */
- for(i=0; i < 128; i++ ) {
- if( active_charset[i] == val )
- break;
- }
- if( i < 128 ) { /* we can print this one */
- if( p ) *p++ = i+128;
- n++;
- }
- else { /* we do not have a translation: print utf8 */
- if( p ) {
- for(i=0; i < encidx; i++ ) {
- sprintf(p, "\\x%02x", encbuf[i] );
- p += 4;
- }
- }
- n += encidx*4;
- encidx = 0;
- }
- }
- else { /* native set */
- if( val >= 0x80 && val < 256 ) {
- n++; /* we can simply print this character */
- if( p ) *p++ = val;
- }
- else { /* we do not have a translation: print utf8 */
- if( p ) {
- for(i=0; i < encidx; i++ ) {
- sprintf(p, "\\x%02x", encbuf[i] );
- p += 4;
- }
- }
- n += encidx*4;
- encidx = 0;
- }
- }
- }
-
- }
- }
- if( !buffer ) { /* allocate the buffer after the first pass */
- buffer = p = xmalloc( n + 1 );
- }
-#ifdef USE_GNUPG_ICONV
- else if(use_iconv) {
- /* Note: See above for comments. */
- iconv_t cd;
- const char *inptr;
- char *outbuf, *outptr;
- size_t inbytes, outbytes;
-
- *p = 0; /* Terminate the buffer. */
-
- cd = iconv_open (active_charset_name, "utf-8");
- if (cd == (iconv_t)-1)
- {
- handle_iconv_error (active_charset_name, "utf-8", 1);
- xfree (buffer);
- return utf8_to_native (string, length, delim);
- }
-
- /* Allocate a new buffer large enough to hold all possible
- * encodings. */
- n = p - buffer + 1;
- inbytes = n - 1;;
- inptr = buffer;
- outbytes = n * MB_LEN_MAX;
- if (outbytes / MB_LEN_MAX != n)
- BUG (); /* Actually an overflow. */
- outbuf = outptr = xmalloc (outbytes);
- if ( iconv (cd, (ICONV_CONST char **)&inptr, &inbytes,
- &outptr, &outbytes) == (size_t)-1) {
- static int shown;
-
- if (!shown)
- log_info (_("conversion from `%s' to `%s' failed: %s\n"),
- "utf-8", active_charset_name, strerror (errno));
- shown = 1;
- /* Didn't worked out. Temporary disable the use of
- * iconv and fall back to our old code. */
- xfree (buffer);
- buffer = NULL;
- xfree (outbuf);
- use_iconv = 0;
- outbuf = utf8_to_native (string, length, delim);
- use_iconv = 1;
- }
- else { /* Success. */
- *outptr = 0;
- /* We could realloc the buffer now but I doubt that it makes
- much sense given that it will get freed anyway soon
- after. */
- xfree (buffer);
- }
- iconv_close (cd);
- return outbuf;
- }
-#endif /*USE_GNUPG_ICONV*/
- else {
- *p = 0; /* make a string */
- return buffer;
- }
- }
-}
-
-/****************************************************
- ******** locale insensitive ctype functions ********
- ****************************************************/
-/* FIXME: replace them by a table lookup and macros */
-int
-ascii_isupper (int c)
-{
- return c >= 'A' && c <= 'Z';
-}
-
-int
-ascii_islower (int c)
-{
- return c >= 'a' && c <= 'z';
-}
-
-int
-ascii_toupper (int c)
-{
- if (c >= 'a' && c <= 'z')
- c &= ~0x20;
- return c;
-}
-
-int
-ascii_tolower (int c)
-{
- if (c >= 'A' && c <= 'Z')
- c |= 0x20;
- return c;
-}
-
-
-int
-ascii_strcasecmp (const char *a, const char *b)
-{
- const unsigned char *p1 = (const unsigned char *)a;
- const unsigned char *p2 = (const unsigned char *)b;
- unsigned char c1, c2;
-
- if (p1 == p2)
- return 0;
-
- do
- {
- c1 = ascii_tolower (*p1);
- c2 = ascii_tolower (*p2);
-
- if (c1 == '\0')
- break;
-
- ++p1;
- ++p2;
- }
- while (c1 == c2);
-
- return c1 - c2;
-}
-
-int
-ascii_strncasecmp (const char *a, const char *b, size_t n)
-{
- const unsigned char *p1 = (const unsigned char *)a;
- const unsigned char *p2 = (const unsigned char *)b;
- unsigned char c1, c2;
-
- if (p1 == p2 || !n )
- return 0;
-
- do
- {
- c1 = ascii_tolower (*p1);
- c2 = ascii_tolower (*p2);
-
- if ( !--n || c1 == '\0')
- break;
-
- ++p1;
- ++p2;
- }
- while (c1 == c2);
-
- return c1 - c2;
-}
-
-
-int
-ascii_memcasecmp( const char *a, const char *b, size_t n )
-{
- if (a == b)
- return 0;
- for ( ; n; n--, a++, b++ ) {
- if( *a != *b && ascii_toupper (*a) != ascii_toupper (*b) )
- return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
- }
- return 0;
-}
-
-
-
-/*********************************************
- ********** missing string functions *********
- *********************************************/
-
-#ifndef HAVE_STPCPY
-char *
-stpcpy(char *a,const char *b)
-{
- while( *b )
- *a++ = *b++;
- *a = 0;
-
- return (char*)a;
-}
-#endif
-
-
-#ifndef HAVE_STRSEP
-/* code taken from glibc-2.2.1/sysdeps/generic/strsep.c */
-char *
-strsep (char **stringp, const char *delim)
-{
- char *begin, *end;
-
- begin = *stringp;
- if (begin == NULL)
- return NULL;
-
- /* A frequent case is when the delimiter string contains only one
- character. Here we don't need to call the expensive `strpbrk'
- function and instead work using `strchr'. */
- if (delim[0] == '\0' || delim[1] == '\0')
- {
- char ch = delim[0];
-
- if (ch == '\0')
- end = NULL;
- else
- {
- if (*begin == ch)
- end = begin;
- else if (*begin == '\0')
- end = NULL;
- else
- end = strchr (begin + 1, ch);
- }
- }
- else
- /* Find the end of the token. */
- end = strpbrk (begin, delim);
-
- if (end)
- {
- /* Terminate the token and set *STRINGP past NUL character. */
- *end++ = '\0';
- *stringp = end;
- }
- else
- /* No more delimiters; this is the last token. */
- *stringp = NULL;
-
- return begin;
-}
-#endif /*HAVE_STRSEP*/
-
-
-#ifndef HAVE_STRLWR
-char *
-strlwr(char *s)
-{
- char *p;
- for(p=s; *p; p++ )
- *p = tolower(*(unsigned char *)p);
- return s;
-}
-#endif
-
-#ifndef HAVE_STRCASECMP
-int
-strcasecmp( const char *a, const char *b )
-{
- for( ; *a && *b; a++, b++ ) {
- if( *a != *b
- && toupper(*(const byte *)a) != toupper(*(const byte *)b) )
- break;
- }
- return *(const byte*)a - *(const byte*)b;
-}
-#endif
-
-#ifndef HAVE_STRNCASECMP
-int
-strncasecmp( const char *a, const char *b, size_t n )
-{
- for( ; n && *a && *b; a++, b++, n--) {
- if( *a != *b
- && toupper(*(const byte *)a) != toupper(*(const byte *)b) )
- break;
- }
- if (!n)
- return 0;
- return *(const byte*)a - *(const byte*)b;
-}
-#endif
-
-
-#ifdef _WIN32
-/*
- * Like vsprintf but provides a pointer to malloc'd storage, which
- * must be freed by the caller (xfree). Taken from libiberty as
- * found in gcc-2.95.2 and a little bit modernized.
- * FIXME: Write a new CRT for W32.
- */
-int
-vasprintf (char **result, const char *format, va_list args)
-{
- const char *p = format;
- /* Add one to make sure that it is never zero, which might cause malloc
- to return NULL. */
- int total_width = strlen (format) + 1;
- va_list ap;
-
- /* this is not really portable but works under Windows */
- memcpy ( &ap, &args, sizeof (va_list));
-
- while (*p != '\0')
- {
- if (*p++ == '%')
- {
- while (strchr ("-+ #0", *p))
- ++p;
- if (*p == '*')
- {
- ++p;
- total_width += abs (va_arg (ap, int));
- }
- else
- {
- char *endp;
- total_width += strtoul (p, &endp, 10);
- p = endp;
- }
- if (*p == '.')
- {
- ++p;
- if (*p == '*')
- {
- ++p;
- total_width += abs (va_arg (ap, int));
- }
- else
- {
- char *endp;
- total_width += strtoul (p, &endp, 10);
- p = endp;
- }
- }
- while (strchr ("hlL", *p))
- ++p;
- /* Should be big enough for any format specifier except %s
- and floats. */
- total_width += 30;
- switch (*p)
- {
- case 'd':
- case 'i':
- case 'o':
- case 'u':
- case 'x':
- case 'X':
- case 'c':
- (void) va_arg (ap, int);
- break;
- case 'f':
- case 'e':
- case 'E':
- case 'g':
- case 'G':
- (void) va_arg (ap, double);
- /* Since an ieee double can have an exponent of 307, we'll
- make the buffer wide enough to cover the gross case. */
- total_width += 307;
-
- case 's':
- total_width += strlen (va_arg (ap, char *));
- break;
- case 'p':
- case 'n':
- (void) va_arg (ap, char *);
- break;
- }
- }
- }
- *result = xmalloc (total_width);
- if (*result != NULL)
- return vsprintf (*result, format, args);
- else
- return 0;
-}
-
-int
-asprintf (char **buf, const char *fmt, ...)
-{
- int status;
- va_list ap;
-
- va_start (ap, fmt);
- status = vasprintf (buf, fmt, ap);
- va_end (ap);
- return status;
-}
-
-const char *
-w32_strerror (int w32_errno)
-{
- static char strerr[256];
- int ec = (int)GetLastError ();
-
- if (w32_errno == 0)
- w32_errno = ec;
- FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, w32_errno,
- MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
- strerr, DIM (strerr)-1, NULL);
- return strerr;
-}
-#endif /*_WIN32*/
-
-
-
diff --git a/util/timegm.c b/util/timegm.c
deleted file mode 100644
index 3b7931e7c..000000000
--- a/util/timegm.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/* timegm.c - libc replacement function
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-/*
- timegm() is a GNU function that might not be available everywhere.
- It's basically the inverse of gmtime() - you give it a struct tm,
- and get back a time_t. It differs from mktime() in that it handles
- the case where the struct tm is UTC and the local environment isn't.
-
- Some BSDs don't handle the putenv("foo") case properly, so we use
- unsetenv if the platform has it to remove environment variables.
-*/
-
-#include <config.h>
-#include <time.h>
-#include <stdlib.h>
-#include <string.h>
-
-time_t
-timegm(struct tm *tm)
-{
- time_t answer;
- char *zone;
-
- zone=getenv("TZ");
- putenv("TZ=UTC");
- tzset();
- answer=mktime(tm);
- if(zone)
- {
- char *old_zone;
-
- old_zone=malloc(3+strlen(zone)+1);
- if(old_zone)
- {
- strcpy(old_zone,"TZ=");
- strcat(old_zone,zone);
- putenv(old_zone);
- }
- }
- else
-#ifdef HAVE_UNSETENV
- unsetenv("TZ");
-#else
- putenv("TZ");
-#endif
-
- tzset();
- return answer;
-}
diff --git a/util/ttyio.c b/util/ttyio.c
deleted file mode 100644
index 97b160ef2..000000000
--- a/util/ttyio.c
+++ /dev/null
@@ -1,629 +0,0 @@
-/* ttyio.c - tty i/O functions
- * Copyright (C) 1998, 1999, 2000, 2001, 2002,
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <unistd.h>
-#ifdef HAVE_TCGETATTR
-#include <termios.h>
-#else
-#ifdef HAVE_TERMIO_H
-/* simulate termios with termio */
-#include <termio.h>
-#define termios termio
-#define tcsetattr ioctl
-#define TCSAFLUSH TCSETAF
-#define tcgetattr(A,B) ioctl(A,TCGETA,B)
-#define HAVE_TCGETATTR
-#endif
-#endif
-#ifdef _WIN32 /* use the odd Win32 functions */
-#include <windows.h>
-#ifdef HAVE_TCGETATTR
-#error windows and termios
-#endif
-#endif
-#include <errno.h>
-#include <ctype.h>
-#ifdef HAVE_LIBREADLINE
-#include <readline/readline.h>
-#include <readline/history.h>
-#endif
-
-#include "util.h"
-#include "memory.h"
-#include "ttyio.h"
-
-#define CONTROL_D ('D' - 'A' + 1)
-
-#ifdef _WIN32 /* use the odd Win32 functions */
-static struct {
- HANDLE in, out;
-} con;
-#define DEF_INPMODE (ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT \
- |ENABLE_PROCESSED_INPUT )
-#define HID_INPMODE (ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT )
-#define DEF_OUTMODE (ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT)
-
-#else /* yeah, we have a real OS */
-static FILE *ttyfp = NULL;
-#endif
-
-static int initialized;
-static int last_prompt_len;
-static int batchmode;
-static int no_terminal;
-
-#ifdef HAVE_TCGETATTR
- static struct termios termsave;
- static int restore_termios;
-#endif
-
-
-
-/* This is a wrapper around ttyname so that we can use it even when
- the standard streams are redirected. It figures the name out the
- first time and returns it in a statically allocated buffer. */
-const char *
-tty_get_ttyname (void)
-{
- static char *name;
-
- /* On a GNU system ctermid() always return /dev/tty, so this does
- not make much sense - however if it is ever changed we do the
- Right Thing now. */
-#ifdef HAVE_CTERMID
- static int got_name;
-
- if (!got_name)
- {
- const char *s;
- s = ctermid (NULL);
- if (s)
- name = strdup (s);
- got_name = 1;
- }
-#endif
- /* Assume the standard tty on memory error or when there is no
- ctermid. */
- return name? name : "/dev/tty";
-}
-
-
-#ifdef HAVE_TCGETATTR
-static void
-cleanup(void)
-{
- if( restore_termios ) {
- restore_termios = 0; /* do it prios in case it is interrupted again */
- if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
- log_error("tcsetattr() failed: %s\n", strerror(errno) );
- }
-}
-#endif
-
-static void
-init_ttyfp(void)
-{
- if( initialized )
- return;
-
-#if defined(_WIN32)
- {
- SECURITY_ATTRIBUTES sa;
-
- memset(&sa, 0, sizeof(sa));
- sa.nLength = sizeof(sa);
- sa.bInheritHandle = TRUE;
- con.out = CreateFileA( "CONOUT$", GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- &sa, OPEN_EXISTING, 0, 0 );
- if( con.out == INVALID_HANDLE_VALUE )
- log_fatal ("open(CONOUT$) failed: %s", w32_strerror (0));
- memset(&sa, 0, sizeof(sa));
- sa.nLength = sizeof(sa);
- sa.bInheritHandle = TRUE;
- con.in = CreateFileA( "CONIN$", GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- &sa, OPEN_EXISTING, 0, 0 );
- if (con.in == INVALID_HANDLE_VALUE)
- log_fatal ("open(CONIN$) failed: %s", w32_strerror (0));
- }
- SetConsoleMode(con.in, DEF_INPMODE );
- SetConsoleMode(con.out, DEF_OUTMODE );
-
-#elif defined(__EMX__)
- ttyfp = stdout; /* Fixme: replace by the real functions: see wklib */
-#else
- ttyfp = batchmode? stderr : fopen( tty_get_ttyname (), "r+");
- if( !ttyfp ) {
- log_error("cannot open `%s': %s\n",
- tty_get_ttyname (), strerror(errno) );
- exit(2);
- }
-#ifdef HAVE_LIBREADLINE
- rl_catch_signals = 0;
- rl_instream = rl_outstream = ttyfp;
- rl_inhibit_completion = 1;
-#endif
-#endif
-#ifdef HAVE_TCGETATTR
- atexit( cleanup );
-#endif
- initialized = 1;
-}
-
-#ifdef HAVE_LIBREADLINE
-void
-tty_enable_completion(rl_completion_func_t *completer)
-{
- if( no_terminal )
- return;
-
- if( !initialized )
- init_ttyfp();
-
- rl_attempted_completion_function=completer;
- rl_inhibit_completion=0;
-}
-
-void
-tty_disable_completion(void)
-{
- if( no_terminal )
- return;
-
- if( !initialized )
- init_ttyfp();
-
- rl_inhibit_completion=1;
-}
-#endif /*HAVE_LIBREADLINE*/
-
-int
-tty_batchmode( int onoff )
-{
- int old = batchmode;
- if( onoff != -1 )
- batchmode = onoff;
- return old;
-}
-
-int
-tty_no_terminal(int onoff)
-{
- int old = no_terminal;
- no_terminal = onoff ? 1 : 0;
- return old;
-}
-
-void
-tty_printf( const char *fmt, ... )
-{
- va_list arg_ptr;
-
- if (no_terminal)
- return;
-
- if( !initialized )
- init_ttyfp();
-
- va_start( arg_ptr, fmt ) ;
-#ifdef _WIN32
- {
- char *buf = NULL;
- int n;
- DWORD nwritten;
-
- n = vasprintf(&buf, fmt, arg_ptr);
- if( !buf )
- log_bug("vasprintf() failed\n");
-
- if (!WriteConsoleA (con.out, buf, n, &nwritten, NULL))
- log_fatal ("WriteConsole failed: %s", w32_strerror (0));
- if( n != nwritten )
- log_fatal ("WriteConsole failed: %d != %d\n", n, (int)nwritten );
- last_prompt_len += n;
- xfree (buf);
- }
-#else
- last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ;
- fflush(ttyfp);
-#endif
- va_end(arg_ptr);
-}
-
-
-/* Same as tty_printf but if FP is not NULL, behave like the standard
- fprintf. */
-void
-tty_fprintf (FILE *fp, const char *fmt, ... )
-{
- va_list arg_ptr;
-
- if (fp)
- {
- va_start (arg_ptr, fmt) ;
- vfprintf (fp, fmt, arg_ptr );
- va_end (arg_ptr);
- return;
- }
-
- if (no_terminal)
- return;
-
- if( !initialized )
- init_ttyfp();
-
- va_start( arg_ptr, fmt ) ;
-#ifdef _WIN32
- {
- char *buf = NULL;
- int n;
- DWORD nwritten;
-
- n = vasprintf(&buf, fmt, arg_ptr);
- if( !buf )
- log_bug("vasprintf() failed\n");
-
- if (!WriteConsoleA (con.out, buf, n, &nwritten, NULL))
- log_fatal ("WriteConsole failed: %s", w32_strerror (0));
- if (n != nwritten)
- log_fatal ("WriteConsole failed: %d != %d\n", n, (int)nwritten);
- last_prompt_len += n;
- xfree (buf);
- }
-#else
- last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ;
- fflush(ttyfp);
-#endif
- va_end(arg_ptr);
-}
-
-
-/****************
- * Print a string, but filter all control characters out.
- */
-void
-tty_print_string( const byte *p, size_t n )
-{
- if (no_terminal)
- return;
-
- if( !initialized )
- init_ttyfp();
-
-#ifdef _WIN32
- /* not so effective, change it if you want */
- for( ; n; n--, p++ )
- if( iscntrl( *p ) ) {
- if( *p == '\n' )
- tty_printf("\\n");
- else if( !*p )
- tty_printf("\\0");
- else
- tty_printf("\\x%02x", *p);
- }
- else
- tty_printf("%c", *p);
-#else
- for( ; n; n--, p++ )
- if( iscntrl( *p ) ) {
- putc('\\', ttyfp);
- if( *p == '\n' )
- putc('n', ttyfp);
- else if( !*p )
- putc('0', ttyfp);
- else
- fprintf(ttyfp, "x%02x", *p );
- }
- else
- putc(*p, ttyfp);
-#endif
-}
-
-void
-tty_print_utf8_string2 (const byte *p, size_t n, size_t max_n )
-{
- size_t i;
- char *buf;
-
- if (no_terminal)
- return;
-
- /* we can handle plain ascii simpler, so check for it first */
- for(i=0; i < n; i++ ) {
- if( p[i] & 0x80 )
- break;
- }
- if( i < n ) {
- buf = utf8_to_native( p, n, 0 );
- if( max_n && (strlen( buf ) > max_n )) {
- buf[max_n] = 0;
- }
- /*(utf8 conversion already does the control character quoting)*/
- tty_printf("%s", buf );
- xfree( buf );
- }
- else {
- if( max_n && (n > max_n) ) {
- n = max_n;
- }
- tty_print_string( p, n );
- }
-}
-
-void
-tty_print_utf8_string( const byte *p, size_t n )
-{
- tty_print_utf8_string2( p, n, 0 );
-}
-
-
-static char *
-do_get( const char *prompt, int hidden )
-{
- char *buf;
-#ifndef __riscos__
- byte cbuf[1];
-#endif
- int c, n, i;
-
- if( batchmode ) {
- log_error("Sorry, we are in batchmode - can't get input\n");
- exit(2);
- }
-
- if (no_terminal) {
- log_error("Sorry, no terminal at all requested - can't get input\n");
- exit(2);
- }
-
- if( !initialized )
- init_ttyfp();
-
- last_prompt_len = 0;
- buf = xmalloc(n=50);
- i = 0;
-
-#ifdef _WIN32 /* windoze version */
- if( hidden )
- SetConsoleMode(con.in, HID_INPMODE );
-
- tty_printf( "%s", prompt );
-
- for(;;) {
- DWORD nread;
-
- if (!ReadConsoleA (con.in, cbuf, 1, &nread, NULL))
- log_fatal ("ReadConsole failed: %s", w32_strerror (0));
- if( !nread )
- continue;
- if( *cbuf == '\n' )
- break;
-
- if( !hidden )
- last_prompt_len++;
- c = *cbuf;
- if( c == '\t' )
- c = ' ';
- else if( c > 0xa0 )
- ; /* we don't allow 0xa0, as this is a protected blank which may
- * confuse the user */
- else if( iscntrl(c) )
- continue;
- if( !(i < n-1) ) {
- n += 50;
- buf = xrealloc( buf, n );
- }
- buf[i++] = c;
- }
-
- if( hidden )
- SetConsoleMode(con.in, DEF_INPMODE );
-
-#elif defined(__riscos__)
- tty_printf( "%s", prompt );
- do {
- c = riscos_getchar();
- if (c == 0xa || c == 0xd) { /* Return || Enter */
- c = (int) '\n';
- } else if (c == 0x8 || c == 0x7f) { /* Backspace || Delete */
- if (i>0) {
- i--;
- if (!hidden) {
- last_prompt_len--;
- fputc(8, ttyfp);
- fputc(32, ttyfp);
- fputc(8, ttyfp);
- fflush(ttyfp);
- }
- } else {
- fputc(7, ttyfp);
- fflush(ttyfp);
- }
- continue;
- } else if (c == (int) '\t') { /* Tab */
- c = ' ';
- } else if (c > 0xa0) {
- ; /* we don't allow 0xa0, as this is a protected blank which may
- * confuse the user */
- } else if (iscntrl(c)) {
- continue;
- }
- if(!(i < n-1)) {
- n += 50;
- buf = xrealloc(buf, n);
- }
- buf[i++] = c;
- if (!hidden) {
- last_prompt_len++;
- fputc(c, ttyfp);
- fflush(ttyfp);
- }
- } while (c != '\n');
- i = (i>0) ? i-1 : 0;
-#else /* unix version */
- if( hidden ) {
-#ifdef HAVE_TCGETATTR
- struct termios term;
-
- if( tcgetattr(fileno(ttyfp), &termsave) )
- log_fatal("tcgetattr() failed: %s\n", strerror(errno) );
- restore_termios = 1;
- term = termsave;
- term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
- if( tcsetattr( fileno(ttyfp), TCSAFLUSH, &term ) )
- log_fatal("tcsetattr() failed: %s\n", strerror(errno) );
-#endif
- }
-
- tty_printf( "%s", prompt );
-
- /* fixme: How can we avoid that the \n is echoed w/o disabling
- * canonical mode - w/o this kill_prompt can't work */
- while( read(fileno(ttyfp), cbuf, 1) == 1 && *cbuf != '\n' ) {
- if( !hidden )
- last_prompt_len++;
- c = *cbuf;
- if( c == CONTROL_D )
- log_info("control d found\n");
- if( c == '\t' )
- c = ' ';
- else if( c > 0xa0 )
- ; /* we don't allow 0xa0, as this is a protected blank which may
- * confuse the user */
- else if( iscntrl(c) )
- continue;
- if( !(i < n-1) ) {
- n += 50;
- buf = xrealloc( buf, n );
- }
- buf[i++] = c;
- }
- if( *cbuf != '\n' ) {
- buf[0] = CONTROL_D;
- i = 1;
- }
-
-
- if( hidden ) {
-#ifdef HAVE_TCGETATTR
- if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
- log_error("tcsetattr() failed: %s\n", strerror(errno) );
- restore_termios = 0;
-#endif
- }
-#endif /* end unix version */
- buf[i] = 0;
- return buf;
-}
-
-
-char *
-tty_get( const char *prompt )
-{
-#ifdef HAVE_LIBREADLINE
- if (!batchmode && !no_terminal) {
- char *line;
- char *buf;
-
- if( !initialized )
- init_ttyfp();
-
- last_prompt_len = 0;
-
- line = readline (prompt?prompt:"");
-
- /* We need to copy it to memory controlled by our malloc
- implementations; further we need to convert an EOF to our
- convention. */
- buf = xmalloc(line? strlen(line)+1:2);
- if (line)
- {
- strcpy (buf, line);
- trim_spaces (buf);
- if (strlen (buf) > 2 )
- add_history (line); /* Note that we test BUF but add LINE. */
- free (line);
- }
- else
- {
- buf[0] = CONTROL_D;
- buf[1] = 0;
- }
- return buf;
- }
- else
-#endif /* HAVE_LIBREADLINE */
- return do_get( prompt, 0 );
-}
-
-char *
-tty_get_hidden( const char *prompt )
-{
- return do_get( prompt, 1 );
-}
-
-
-void
-tty_kill_prompt()
-{
- if ( no_terminal )
- return;
-
- if( !initialized )
- init_ttyfp();
-
- if( batchmode )
- last_prompt_len = 0;
- if( !last_prompt_len )
- return;
-#ifdef _WIN32
- tty_printf("\r%*s\r", last_prompt_len, "");
-#else
- {
- int i;
- putc('\r', ttyfp);
- for(i=0; i < last_prompt_len; i ++ )
- putc(' ', ttyfp);
- putc('\r', ttyfp);
- fflush(ttyfp);
- }
-#endif
- last_prompt_len = 0;
-}
-
-
-int
-tty_get_answer_is_yes( const char *prompt )
-{
- int yes;
- char *p = tty_get( prompt );
- tty_kill_prompt();
- yes = answer_is_yes(p);
- xfree(p);
- return yes;
-}
diff --git a/util/w32reg.c b/util/w32reg.c
deleted file mode 100644
index f65c9542c..000000000
--- a/util/w32reg.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/* w32reg.c - MS-Windows Registry access
- * Copyright (C) 1999, 2002, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- */
-
-#include <config.h>
-#if defined (_WIN32) || defined (__CYGWIN32__)
- /* This module is only used in this environment */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <windows.h>
-#include "util.h"
-#include "memory.h"
-
-static HKEY
-get_root_key(const char *root)
-{
- HKEY root_key;
-
- if( !root )
- root_key = HKEY_CURRENT_USER;
- else if( !strcmp( root, "HKEY_CLASSES_ROOT" ) )
- root_key = HKEY_CLASSES_ROOT;
- else if( !strcmp( root, "HKEY_CURRENT_USER" ) )
- root_key = HKEY_CURRENT_USER;
- else if( !strcmp( root, "HKEY_LOCAL_MACHINE" ) )
- root_key = HKEY_LOCAL_MACHINE;
- else if( !strcmp( root, "HKEY_USERS" ) )
- root_key = HKEY_USERS;
- else if( !strcmp( root, "HKEY_PERFORMANCE_DATA" ) )
- root_key = HKEY_PERFORMANCE_DATA;
- else if( !strcmp( root, "HKEY_CURRENT_CONFIG" ) )
- root_key = HKEY_CURRENT_CONFIG;
- else
- return NULL;
-
- return root_key;
-}
-
-
-/****************
- * Return a string from the Win32 Registry or NULL in case of
- * error. Caller must release the return value. A NULL for root
- * is an alias for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn.
- * NOTE: The value is allocated with a plain malloc() - use free() and not
- * the usual xfree()!!!
- */
-char *
-read_w32_registry_string( const char *root, const char *dir, const char *name )
-{
- HKEY root_key, key_handle;
- DWORD n1, nbytes, type;
- char *result = NULL;
-
- if ( !(root_key = get_root_key(root) ) )
- return NULL;
-
- if( RegOpenKeyEx( root_key, dir, 0, KEY_READ, &key_handle ) )
- {
- if (root)
- return NULL; /* no need for a RegClose, so return direct */
- /* It seems to be common practise to fall back to HKLM. */
- if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) )
- return NULL; /* still no need for a RegClose, so return direct */
- }
-
- nbytes = 1;
- if( RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) ) {
- if (root)
- goto leave;
- /* Try to fallback to HKLM also vor a missing value. */
- RegCloseKey (key_handle);
- if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) )
- return NULL; /* Nope. */
- if (RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes))
- goto leave;
- }
- result = malloc( (n1=nbytes+1) );
- if( !result )
- goto leave;
- if( RegQueryValueEx( key_handle, name, 0, &type, result, &n1 ) ) {
- free(result); result = NULL;
- goto leave;
- }
- result[nbytes] = 0; /* make sure it is really a string */
- if (type == REG_EXPAND_SZ && strchr (result, '%')) {
- char *tmp;
-
- n1 += 1000;
- tmp = malloc (n1+1);
- if (!tmp)
- goto leave;
- nbytes = ExpandEnvironmentStrings (result, tmp, n1);
- if (nbytes && nbytes > n1) {
- free (tmp);
- n1 = nbytes;
- tmp = malloc (n1 + 1);
- if (!tmp)
- goto leave;
- nbytes = ExpandEnvironmentStrings (result, tmp, n1);
- if (nbytes && nbytes > n1) {
- free (tmp); /* oops - truncated, better don't expand at all */
- goto leave;
- }
- tmp[nbytes] = 0;
- free (result);
- result = tmp;
- }
- else if (nbytes) { /* okay, reduce the length */
- tmp[nbytes] = 0;
- free (result);
- result = malloc (strlen (tmp)+1);
- if (!result)
- result = tmp;
- else {
- strcpy (result, tmp);
- free (tmp);
- }
- }
- else { /* error - don't expand */
- free (tmp);
- }
- }
-
- leave:
- RegCloseKey( key_handle );
- return result;
-}
-
-
-int
-write_w32_registry_string(const char *root, const char *dir,
- const char *name, const char *value)
-{
- HKEY root_key, reg_key;
-
- if ( !(root_key = get_root_key(root) ) )
- return -1;
-
- if ( RegOpenKeyEx( root_key, dir, 0, KEY_WRITE, &reg_key )
- != ERROR_SUCCESS )
- return -1;
-
- if ( RegSetValueEx( reg_key, name, 0, REG_SZ, (BYTE *)value,
- strlen( value ) ) != ERROR_SUCCESS ) {
- if ( RegCreateKey( root_key, name, &reg_key ) != ERROR_SUCCESS ) {
- RegCloseKey(reg_key);
- return -1;
- }
- if ( RegSetValueEx( reg_key, name, 0, REG_SZ, (BYTE *)value,
- strlen( value ) ) != ERROR_SUCCESS ) {
- RegCloseKey(reg_key);
- return -1;
- }
- }
-
- RegCloseKey( reg_key );
-
- return 0;
-}
-
-#endif /* __MINGW32__ || __CYGWIN32__ */