diff options
Diffstat (limited to 'util')
-rw-r--r-- | util/ChangeLog | 1021 | ||||
-rw-r--r-- | util/Makefile.am | 37 | ||||
-rw-r--r-- | util/argparse.c | 1000 | ||||
-rw-r--r-- | util/dotlock.c | 420 | ||||
-rw-r--r-- | util/errors.c | 113 | ||||
-rw-r--r-- | util/fileutil.c | 242 | ||||
-rw-r--r-- | util/g10u.c | 40 | ||||
-rw-r--r-- | util/http.c | 903 | ||||
-rw-r--r-- | util/iobuf.c | 2189 | ||||
-rw-r--r-- | util/logger.c | 334 | ||||
-rw-r--r-- | util/memory.c | 634 | ||||
-rw-r--r-- | util/miscutil.c | 361 | ||||
-rw-r--r-- | util/riscos.c | 299 | ||||
-rw-r--r-- | util/secmem.c | 470 | ||||
-rw-r--r-- | util/simple-gettext.c | 497 | ||||
-rw-r--r-- | util/strgutil.c | 955 | ||||
-rw-r--r-- | util/ttyio.c | 481 | ||||
-rw-r--r-- | util/w32reg.c | 171 |
18 files changed, 0 insertions, 10167 deletions
diff --git a/util/ChangeLog b/util/ChangeLog deleted file mode 100644 index e9caf465a..000000000 --- a/util/ChangeLog +++ /dev/null @@ -1,1021 +0,0 @@ -2002-10-17 David Shaw <dshaw@jabberwocky.com> - - * 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 <dshaw@jabberwocky.com> - - * http.c (connect_server): Properly handle a single A record that - fails connect(). - -2002-10-03 David Shaw <dshaw@jabberwocky.com> - - * 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 <dshaw@jabberwocky.com> - - * http.c (connect_server): Try all A records for names with - multiple addresses until one answers (not MINGW32). - -2002-09-16 Werner Koch <wk@gnupg.org> - - * w32reg.c (read_w32_registry_string): Fallback to HLM. - -2002-09-12 Stefan Bellon <sbellon@sbellon.de> - - * 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 <wk@gnupg.org> - - * simple-gettext.c: Disable charset mappings. We do it now when - installing the files. - -2002-09-09 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <sbellon@sbellon.de> - - * 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 <sbellon@sbellon.de> - - * 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 <dshaw@jabberwocky.com> - - * secmem.c: "Warning" -> "WARNING" - -2002-07-05 Werner Koch <wk@gnupg.org> - - * 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 <dshaw@jabberwocky.com> - - * argparse.c (optfile_parse): Fix variable typo - 'p2' should be - 'p' :) - -2002-06-29 Werner Koch <wk@gnupg.org> - - * argparse.c (optfile_parse): Renamed an auto I to P2 to avoid - shadowing warning. - -2002-06-21 Stefan Bellon <sbellon@sbellon.de> - - * riscos.c (riscos_global_defaults): New. - -2002-06-20 Stefan Bellon <sbellon@sbellon.de> - - * riscos.c (riscos_set_filetype_by_number, riscos_set_filetype): - New. Set RISC OS filetype according to MIME type. - -2002-06-14 David Shaw <dshaw@jabberwocky.com> - - * strgutil.c (pop_strlist): New function to pop the head off of a - strlist. - -2002-06-05 Timo Schulz <ts@winpt.org> - - * fileutil.c (is_file_compressed): Corrected the magic values - for bzip2 and gzip. Noted by David. - -2002-05-22 Werner Koch <wk@gnupg.org> - - * 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 <sbellon@sbellon.de> - - * 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 <wk@gnupg.org> - - * http.c (write_server) [__MINGW32__]: Replaced WriteFile by send - because sockets don't work with WriteFile under NT anymore. - -2002-05-03 David Shaw <dshaw@jabberwocky.com> - - * 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 <wk@gnupg.org> - - * memory.c (alloc): Malloc at least 1 byte. Noted by Winona Brown. - -2002-04-23 David Shaw <dshaw@jabberwocky.com> - - * miscutil.c: New function answer_is_yes_no_default() to give a - default answer. - -2002-04-22 Stefan Bellon <sbellon@sbellon.de> - - * 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 <wk@gnupg.org> - - Fixed filename of last entry. - -2002-03-29 David Shaw <dshaw@jabberwocky.com> - - * 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 <wk@gnupg.org> - - * argparse.c (optfile_parse): Fixed missing argument handling. - -2002-02-28 Timo Schulz <ts@winpt.org> - - * http.c (write_server): Convert integer to a HANDLE for W32. - -2002-01-27 David Shaw <dshaw@jabberwocky.com> - - * iobuf.c (iobuf_fdopen, iobuf_sockopen): Do not cache fdopened - fds on close. - -2002-01-08 Werner Koch <wk@gnupg.org> - - * secmem.c (print_warn): Print a pointer to the FAQ. - -2002-01-05 Werner Koch <wk@gnupg.org> - - * argparse.c (default_strusage): Set default copyright date to 2002. - -2002-01-02 Stefan Bellon <sbellon@sbellon.de> - - * 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 <dshaw@jabberwocky.com> - - * errors.c (g10_errstr): Added G10ERR_KEYSERVER - -2001-12-27 Werner Koch <wk@gnupg.org> - - * simple-gettext.c [MINGW32]: Fixed last changed. - -2001-12-22 Stefan Bellon <sbellon@sbellon.de> - - * memory.c (realloc): Fixed realloc not working when M_GUARD is - defined and first parameter is NULL. - -2001-12-22 Timo Schulz <ts@winpt.org> - - * fileutil.c (is_file_compressed): New. - -2001-12-19 Werner Koch <wk@gnupg.org> - - * simple-gettext.c, w32reg.c [CYGWIN32]: Allow to use this file - -2001-10-11 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * miscutil.c (print_string): Use explicit ranges and not iscntrl(). - (make_printable_string): Ditto. - -2001-09-07 Werner Koch <wk@gnupg.org> - - * strgutil.c (strsep): New, taken from glibc 2.2.1. - -2001-09-03 Werner Koch <wk@gnupg.org> - - * miscutil.c (strtimestamp,asctimestamp): Avoid trigraphs. - -2001-08-21 Stefan Bellon <sbellon@sbellon.de> - - * riscos.c [__riscos__] (close_fds): Fixed possible endless loop. - -2001-08-20 Werner Koch <wk@gnupg.org> - - Applied patches from Stefan Bellon <sbellon@sbellon.de> 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * dotlock.c (make_dotlock): Typo fixes. - -2001-05-25 Werner Koch <wk@gnupg.org> - - * ttyio.c (do_get): Fixed a serious format string bug. Thanks to - fish stiqz. - -2001-05-23 Werner Koch <wk@gnupg.org> - - * secmem.c (EPERM): Try to work around a Slackware problem. - -2001-05-05 Werner Koch <wk@gnupg.org> - - * http.c (http_start_data): Flush before writing. - (http_wait_response): No need to flush here. - -2001-04-27 Werner Koch <wk@gnupg.org> - - * memory.c (out_of_core): Print an explanation on reasons why - secret memory can get exhausted. - -2001-04-23 Werner Koch <wk@gnupg.org> - - * http.c (http_wait_response): Implement new flag to inhibit the - TCP shutdown. - -2001-04-20 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * strgutil.c (utf8_to_native): Fixed a segv. Thanks to Keith Clayton. - -2001-04-13 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * strgutil.c (check_trailing_chars,check_trailing_ws): New. - -2001-03-08 Werner Koch <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * errors.c (g10_errstr): New codes UNU_SECKEY and UNU_PUBKEY. - -2000-12-28 Werner Koch <wk@gnupg.org> - - * dotlock.c: Made all_lockfiles volatile. - (remove_lockfiles): Made public. - -2000-11-30 Werner Koch <wk@gnupg.org> - - * iobuf.c (iobuf_translate_file_handle): New. - (iobuf_open, iobuf_create): Use it for special filenames - -2000-11-11 Paul Eggert <eggert@twinsun.com> - - * 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 <wk@gnupg.org> - - * 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 <wk@gnupg.org> - - * secmem.c (lock_pool): Don't print warning for Windows. - -2000-10-16 Werner Koch <wk@gnupg.org> - - * secmem.c (lock_pool): Fixed error checking for Linux. - By James Troup. - -Thu Sep 14 14:20:38 CEST 2000 Werner Koch <wk@openit.de> - - * 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 <wk@openit.de> - - * 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 <wk@openit.de> - - * 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 <wk@openit.de> - - * 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 <wk@openit.de> - - * ttyio.c: Simulate termios with termios. By Dave Dykstra. - -Thu Jun 8 20:22:00 CEST 2000 Werner Koch <wk@openit.de> - - * secmem.c (lock_pool,secmem_init): Additional check for dropped privs. - -Tue May 30 16:37:55 CEST 2000 Werner Koch <wk@openit.de> - - * iobuf.c (iobuf_cancel): Fix for MSDOS. - -Fri Apr 14 19:37:08 CEST 2000 Werner Koch <wk@openit.de> - - * dotlock.c (disable_dotlock): New. Implmented this in the module. - -2000-03-09 14:04:22 Werner Koch (wk@habibti.openit.de) - - * argparse.c (default_strusage): Changed year of default copyright. - -Tue Mar 7 18:45:31 CET 2000 Werner Koch <wk@gnupg.de> - - * secmem.c (lock_pool): No more warning for QNX. By Sam Roberts. - -2000-03-02 15:51:04 Werner Koch (wk@habibti.gnupg.de) - - * ttyio.c (tty_print_utf8_string): Oops. - -Thu Mar 2 15:37:46 CET 2000 Werner Koch <wk@gnupg.de> - - * ttyio.c (tty_print_utf8_string2): New to allow a max output size. - -Wed Feb 23 10:07:57 CET 2000 Werner Koch <wk@gnupg.de> - - * 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 <wk@gnupg.de> - - * logger.c (log_inc_errorcount): New. - -Sat Dec 4 12:30:28 CET 1999 Werner Koch <wk@gnupg.de> - - * iobuf.c (iobuf_cancel): Broadcast the new Cancel mesaage to all - filters. - -Mon Nov 22 11:14:53 CET 1999 Werner Koch <wk@gnupg.de> - - * strgutil.c (strcasecmp): New. - - * secmem.c (pool_is_mmapped): Made volatile. - -Sat Oct 9 20:34:41 CEST 1999 Werner Koch <wk@gnupg.de> - - * Makefile.am: Removed libtool. - -Fri Oct 8 20:32:01 CEST 1999 Werner Koch <wk@gnupg.de> - - * 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 <wk@isil.d.shuttle.de> - - - * 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 <wk@isil.d.shuttle.de> - - - * simple-gettext.c: New. - -Wed Sep 1 15:30:44 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - - * argparse.c (arg_parse): Add standard options to the dump-options - output. - -Tue Aug 31 17:20:44 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - - * 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 <wk@isil.d.shuttle.de> - - - * 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 <wk@isil.d.shuttle.de> - - - * argparse.c (initialize): Init ret_xxx. - (optfile_parse): Remove quotes from arguments. - -Wed Jul 7 13:08:40 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - - * 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 <wk@isil.d.shuttle.de> - - - * 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 <wk@isil.d.shuttle.de> - - - * secmem.c (USE_CAPABILITIES): Capabilities support (Remi). - -Sat Jun 26 12:15:59 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - - * 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 <mroth@nessie.de> - - * iobuf.c: file_filter() Detection of EOF on terminals - improved/fixed (see Bug #21). - -Mon Jun 14 21:18:54 CEST 1999 Michael Roth <mroth@nessie.de> - - * ttyio.c: tty_no_terminal() new. - -Sat Jun 5 15:30:33 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * strgutil.c (set_native_charset): Support Latin-2 - -Tue Jun 1 16:01:46 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * 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 <wk@isil.d.shuttle.de> - - * iobuf.c (file_filter,block_filter): Speed patches (Rémi). - -Thu May 27 09:40:55 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * miscutil.c (answer_is_yes_no_quit): New. - -Sun May 23 14:20:22 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * dotlock.c: Tweaked to make it compile under mingw32 - * http.c: Disabled for mingw32. - -Sat May 22 22:47:26 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * logger.c (log_set_logfile): New. - -Thu May 20 14:04:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * 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 <wk@isil.d.shuttle.de> - - * logger.c (g10_log_hexdump): Made 2nd arg a const. - -Wed Apr 28 13:03:03 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * miscutil.c (asctimestamp): Use nl_langinfo (Gaël Quéri). - -Sun Apr 18 10:11:28 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - - * 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 <wk@isil.d.shuttle.de> - - * http.c: Swapped to includes. - -Tue Mar 2 16:44:57 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * strgutil.c (get_native_charset): New. - -Fri Feb 26 17:55:41 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * secmem.c (memblock_struct): Force align (Rémi Guyomarch) - -Wed Feb 24 11:07:27 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * iobuf.c (block_filter): Fixed the oscillating partial packet chunks. - -Fri Feb 19 15:49:15 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * 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 <wk@isil.d.shuttle.de> - - * 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 <wk@isil.d.shuttle.de> - - * 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 <wk@isil.d.shuttle.de> - - * http.c (http_wait_response): Moved the shutdown behind the dup - -Wed Jan 20 18:59:49 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * http.c (send_request): Removed double LF - -Tue Jan 19 19:34:58 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * * 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 <wk@isil.d.shuttle.de> - - * strgutil.c (trim_trailing_ws): New. - -Sat Jan 16 12:03:27 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * http.c (connect_server): Fixed stupid bug. - -Sat Jan 16 09:27:30 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * http.c: New - - -Wed Jan 13 14:10:15 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * iobuf.c (iobuf_fdopen): New. - -Sat Jan 9 16:02:23 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * secmem.c (lock_pool): add another check that setuid() worked. - (secmem_init): Ditto. - -Thu Jan 7 18:00:58 CET 1999 Werner Koch <wk@isil.d.shuttle.de> - - * 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 <wk@isil.d.shuttle.de> - - * dotlock.c (make_dotlock): print another informal message. - - (make_dotlock): Removed the cpp checks. - - -Tue Dec 29 14:41:47 CET 1998 Werner Koch <wk@isil.d.shuttle.de> - - * 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 <wk@isil.d.shuttle.de> - - * argparse.c (arg_pars): fixed opts[i] with negative index. - -Fri Nov 27 21:37:41 CET 1998 Werner Koch <wk@isil.d.shuttle.de> - - * dotlock.c: Implemented - -Wed Nov 25 11:30:07 1998 Werner Koch (wk@isil.d.shuttle.de) - - * iobuf.c (iobuf_pop_filter): Fixed sigsegv after error. - -Thu Nov 19 07:09:55 1998 Werner Koch <werner.koch@guug.de> - - * miscutil.c (strtimevalue): New. - -Tue Nov 10 10:01:53 1998 Werner Koch (wk@isil.d.shuttle.de) - - * strgutil.c (set_native_charset): New. - (native_to_utf8): Now handles koi8-r. - -Tue Nov 3 16:17:56 1998 Werner Koch (wk@isil.d.shuttle.de) - - * 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 (mroth@nessie.de) - - * fileutil.c (make_basename): New. - (make_dirname): New. - -Wed Oct 21 12:20:29 1998 Werner Koch (wk@isil.d.shuttle.de) - - * util.c (iobuf_flush): autoincreasing of a temp. iobuf - (iobuf_temp_with_content): New. - -Tue Oct 13 12:40:13 1998 Werner Koch (wk@isil.d.shuttle.de) - - * util.c (.nofast): set this variable - -Wed Oct 7 19:27:50 1998 Werner Koch (wk@isil.d.shuttle.de) - - * memory.c (m_print_stats): New. - -Tue Oct 6 09:53:56 1998 Werner Koch (wk@isil.d.shuttle.de) - - * 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 (wk@isil.d.shuttle.de) - - * secmem.c (secmem_init): Drops setuid if called with 0. - -Tue Jul 7 11:49:25 1998 Werner Koch (wk@isil.d.shuttle.de) - - * logger.c (log_set_filename): New. - -Mon Jul 6 09:03:49 1998 Werner Koch (wk@isil.d.shuttle.de) - - * strgutil.c (append_to_strlist): New. - -Thu Jul 2 15:55:44 1998 Werner Koch (wk@isil.d.shuttle.de) - - * iobuf.c (block_filter): Add writing of OP partial length headers. - -Fri Jun 26 10:38:35 1998 Werner Koch (wk@isil.d.shuttle.de) - - * ttyio.c (do_get): all iso8859-1 characters are now allowed. - -Thu Jun 25 15:57:21 1998 Werner Koch (wk@isil.d.shuttle.de) - - * 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 (wk@isil.d.shuttle.de) - - * argparse.c (show_help): Add some formatting stuff - -Fri May 8 17:06:49 1998 Werner Koch (wk@isil.d.shuttle.de) - - * errors.c (strerror): New if !HAVE_STRERROR - -Mon May 4 19:48:03 1998 Werner Koch (wk@isil.d.shuttle.de) - - * iobuf.c (iobuf_read): Code is now faster. - * (iobuf_write): ditto. - -Mon Apr 27 11:01:32 1998 Werner Koch (wk@isil.d.shuttle.de) - - * strgutil.c (memicmp): New. - -Thu Mar 19 11:29:03 1998 Werner Koch (wk@isil.d.shuttle.de) - - * strgutil.c (memistr): Add const to return and first arg. - -Sat Mar 7 11:54:35 1998 Werner Koch (wk@isil.d.shuttle.de) - - * miscutil.c (print_string): New arg delim; changed all callers. - -Thu Mar 5 12:19:30 1998 Werner Koch (wk@isil.d.shuttle.de) - - * errors.c: New strings. - -Thu Mar 5 12:06:31 1998 Werner Koch (wk@isil.d.shuttle.de) - - * 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 (wk@isil.d.shuttle.de) - - * 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 (wk@isil.d.shuttle.de) - - * secmem.c (lock_pool): No error if EAGAIN is returned instead - of EPERM. - -Fri Feb 20 17:43:05 1998 Werner Koch (wk@isil.d.shuttle.de) - - * ttyio.c [MINGW32]: Add support for mingw32. - -Tue Feb 17 19:43:44 1998 Werner Koch (wk@isil.d.shuttle.de) - - * memory.c (dump_table_at_exit): New. - -Mon Feb 16 10:07:28 1998 Werner Koch (wk@isil.d.shuttle.de) - - * argparse.c (show_version, show_help, default_strusage): Changed - according to GNU standards. - -Mon Feb 16 08:58:25 1998 Werner Koch (wk@isil.d.shuttle.de) - - * iobuf.c (iobuf_peek): New - -Fri Feb 13 19:34:59 1998 Werner Koch (wk@isil.d.shuttle.de) - - * iobuf.c (iobuf_seek): Set counters to new offset. - -Fri Feb 13 17:13:04 1998 Werner Koch (wk@isil.d.shuttle.de) - - * 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 (wk@isil.d.shuttle.de) - - * argparse.c (show_help): New '\v' kludge. - - - - Copyright 1998, 1999, 2000, 2001 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 a8d40da2d..000000000 --- a/util/Makefile.am +++ /dev/null @@ -1,37 +0,0 @@ -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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_LDFLAGS = -libutil_a_SOURCES = g10u.c logger.c fileutil.c miscutil.c strgutil.c \ - ttyio.c argparse.c memory.c secmem.c errors.c iobuf.c \ - dotlock.c http.c simple-gettext.c w32reg.c - - -http-test: http.c - gcc -DHAVE_CONFIG_H -I. -I. -I.. $(INCLUDES) -g -Wall -DTEST \ - -o http-test http.c libutil.a ../mpi/libmpi.a @INTLLIBS@ - - - diff --git a/util/argparse.c b/util/argparse.c deleted file mode 100644 index 2ca0ff8ff..000000000 --- a/util/argparse.c +++ /dev/null @@ -1,1000 +0,0 @@ -/* [argparse.c wk 17.06.97] Argument Parser for option handling - * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 */ - const char *s; - - if( filename ) { - if( arg->r_opt == -6 ) - s = "%s:%u: argument not expected\n"; - else if( arg->r_opt == -5 ) - s = "%s:%u: read error\n"; - else if( arg->r_opt == -4 ) - s = "%s:%u: keyword too long\n"; - else if( arg->r_opt == -3 ) - s = "%s:%u: missing argument\n"; - else if( arg->r_opt == -7 ) - s = "%s:%u: invalid command\n"; - else if( arg->r_opt == -10 ) - s = "%s:%u: invalid alias definition\n"; - else - s = "%s:%u: invalid option\n"; - log_error(s, filename, *lineno ); - } - else { - if( arg->r_opt == -3 ) - s = "Missing argument for option \"%.50s\"\n"; - else if( arg->r_opt == -6 ) - s = "Option \"%.50s\" does not expect an argument\n"; - else if( arg->r_opt == -7 ) - s = "Invalid command \"%.50s\"\n"; - else if( arg->r_opt == -8 ) - s = "Option \"%.50s\" is ambiguous\n"; - else if( arg->r_opt == -9 ) - s = "Command \"%.50s\" is ambiguous\n"; - else - s = "Invalid option \"%.50s\"\n"; - log_error(s, 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 = m_alloc( 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 ) { - m_free( 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 = m_strdup(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) ) - m_free(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 = m_realloc(buffer, buflen); - buffer[i++] = c; - } - } - else if( i < DIM(keyword)-1 ) - keyword[i++] = c; - else { - buflen = DIM(keyword)+50; - buffer = m_alloc(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) 2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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/dotlock.c b/util/dotlock.c deleted file mode 100644 index fac825450..000000000 --- a/util/dotlock.c +++ /dev/null @@ -1,420 +0,0 @@ -/* dotlock.c - dotfile locking - * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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> -#include <sys/time.h> -#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; - -static int read_lockfile( const char *name ); - -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; - int fd = -1; - char pidstr[16]; - #if !defined (HAVE_DOSISH_SYSTEM) - struct utsname utsbuf; - #endif - const char *nodename; - const char *dirpart; - int dirpartlen; - - if( !initialized ) { - atexit( remove_lockfiles ); - initialized = 1; - } - if( !file_to_lock ) - return NULL; - - h = m_alloc_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 = m_alloc( dirpartlen + 6+30+ strlen(nodename) + 11 ); -#ifndef __riscos__ - sprintf( h->tname, "%.*s/.#lk%p.%s.%d", - dirpartlen, dirpart, h, nodename, (int)getpid() ); -#else /* __riscos__ */ - sprintf( h->tname, "%.*s.lk%p/%s/%d", - dirpartlen, dirpart, 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)); - m_free(h->tname); - m_free(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); - m_free(h->tname); - m_free(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); - m_free(h->tname); - m_free(h); - return NULL; - } - - #ifdef _REENTRANT - /* release mutex */ - #endif -#endif - h->lockname = m_alloc( strlen(file_to_lock) + 6 ); - strcpy(stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock"); - return h; -} - -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; -} - -/**************** - * 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( !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; - - 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( 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 -} - - -/**************** - * Read the lock file and return the pid, returns -1 on error. - */ -static int -read_lockfile( const char *name ) -{ - #if defined (HAVE_DOSISH_SYSTEM) - return 0; - #else - 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 -} - - -void -remove_lockfiles() -{ - #if !defined (HAVE_DOSISH_SYSTEM) - DOTLOCK h, h2; - - h = all_lockfiles; - all_lockfiles = NULL; - - while( h ) { - h2 = h->next; - if( !h->disable ) { - if( h->locked ) - unlink( h->lockname ); - unlink(h->tname); - m_free(h->tname); - m_free(h->lockname); - } - m_free(h); - h = h2; - } - #endif -} - diff --git a/util/errors.c b/util/errors.c deleted file mode 100644 index 25d5a088a..000000000 --- a/util/errors.c +++ /dev/null @@ -1,113 +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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")) - 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 c2a2a9df2..000000000 --- a/util/fileutil.c +++ /dev/null @@ -1,242 +0,0 @@ -/* fileutil.c - file utilities - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <assert.h> -#include <unistd.h> -#ifdef __riscos__ -#include <kernel.h> -#include <swis.h> -#endif /* __riscos__ */ -#include "util.h" -#include "memory.h" -#include "ttyio.h" - - -/*************** - * Extract from a given path the filename component. - * - */ -char * -make_basename(const char *filepath) -{ - char *p; - - if ( !(p=strrchr(filepath, DIRSEP_C)) ) - #ifdef HAVE_DRIVE_LETTERS - if ( !(p=strrchr(filepath, '\\')) ) - if ( !(p=strrchr(filepath, ':')) ) - #endif - { - return m_strdup(filepath); - } - - return m_strdup(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 m_strdup(EXTSEP_S); - } - - dirname_length = p-filepath; - dirname = m_alloc(dirname_length+1); - strncpy(dirname, filepath, dirname_length); - dirname[dirname_length] = 0; - - return dirname; -} - - - -/**************** - * Construct a filename from the NULL terminated list of parts. - * Tilde expansion is done here. - */ -char * -make_filename( const char *first_part, ... ) -{ - va_list arg_ptr ; - size_t n; - const char *s; -#ifndef __riscos__ - char *name, *home, *p; -#else - char *name, *p; -#endif - - 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__ - home = NULL; - if( *first_part == '~' && first_part[1] == DIRSEP_C - && (home = getenv("HOME")) && *home ) - n += strlen(home); - name = m_alloc(n); - p = home ? stpcpy(stpcpy(name,home), first_part+1) - : stpcpy(name, first_part); -#else /* __riscos__ */ - name = m_alloc(n); - p = stpcpy(name, first_part); -#endif /* __riscos__ */ - 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); - -#ifndef __riscos__ - return name; -#else /* __riscos__ */ - p = gstrans(name); - m_free(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 = gstrans(a); - bbuf = gstrans(b); - - c = strcasecmp (abuf, bbuf); - - m_free(abuf); - m_free(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; - - 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 ( !s || *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 ) < 4 ) { - *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/g10u.c b/util/g10u.c deleted file mode 100644 index 2ce3a4e36..000000000 --- a/util/g10u.c +++ /dev/null @@ -1,40 +0,0 @@ -/* g10u.c - Wrapper for utility functions - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include "mpi.h" -#include "util.h" - - -/* FIXME: The modules should use functions from libgcrypt */ - -const char *g10u_revision_string(int dummy) { return "$Revision$"; } - - -void *g10_malloc( size_t n ) { return m_alloc( n ); } -void *g10_calloc( size_t n ) { return m_alloc_clear( n ); } -void *g10_malloc_secure( size_t n ) { return m_alloc_secure( n ); } -void *g10_calloc_secure( size_t n ) { return m_alloc_secure_clear( n ); } -void *g10_realloc( void *a, size_t n ) { return m_realloc( a, n ); } -void g10_free( void *p ) { m_free( p ); } -char *g10_strdup( const char * a) { return m_strdup( a ); } - diff --git a/util/http.c b/util/http.c deleted file mode 100644 index fa3d512e9..000000000 --- a/util/http.c +++ /dev/null @@ -1,903 +0,0 @@ -/* http.c - HTTP protocol handler - * Copyright (C) 1999, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> - -#ifdef __MINGW32__ - #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" - -#ifdef __riscos__ - #define HTTP_PROXY_ENV "GnuPG$HttpProxy" - #define HTTP_PROXY_ENV_PRINTABLE "<GnuPG$HttpProxy>" -#else - #define HTTP_PROXY_ENV "http_proxy" - #define HTTP_PROXY_ENV_PRINTABLE "$http_proxy" -#endif - -#ifdef __MINGW32__ -#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 ); -static byte *build_rel_path( PARSED_URI uri ); -static int parse_response( HTTP_HD hd ); - -static int connect_server( const char *server, ushort port ); -static int write_server( int sock, const char *data, size_t length ); - -#ifdef __MINGW32__ -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 /*__MINGW32__*/ - - -int -http_open( HTTP_HD hd, HTTP_REQ_TYPE reqtype, const char *url, - unsigned int flags ) -{ - 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 ); - 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, unsigned int flags ) -{ - int rc; - - rc = http_open( hd, HTTP_REQ_GET, document, flags ); - 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 ); - m_free( 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 = m_alloc_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; - m_free( r ); - } - m_free( 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; - uri->port = 80; - if( !strcmp( uri->scheme, "http" ) ) - ; - else if( !strcmp( uri->scheme, "x-hkp" ) ) /* same as HTTP */ - 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; - 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 = m_alloc_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 ) { - m_free( 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 byte *server; - byte *request, *p; - ushort port; - int rc; - const char *http_proxy = NULL; - - server = *hd->uri->host? hd->uri->host : "localhost"; - port = hd->uri->port? hd->uri->port : 80; - - if( (hd->flags & HTTP_FLAG_TRY_PROXY) - && (http_proxy = getenv( HTTP_PROXY_ENV )) ) { - PARSED_URI uri; - - rc = parse_uri( &uri, http_proxy ); - if (rc) { - log_error("invalid " HTTP_PROXY_ENV_PRINTABLE ": %s\n", - g10_errstr(rc)); - release_parsed_uri( uri ); - return G10ERR_NETWORK; - } - hd->sock = connect_server( *uri->host? uri->host : "localhost", - uri->port? uri->port : 80 ); - release_parsed_uri( uri ); - } - else - hd->sock = connect_server( server, port ); - - if( hd->sock == -1 ) - return G10ERR_NETWORK; - - p = build_rel_path( hd->uri ); - request = m_alloc( strlen(server) + strlen(p) + 50 ); - if( http_proxy ) { - sprintf( request, "%s http://%s:%hu%s%s HTTP/1.0\r\n", - 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 ); - } - else { - sprintf( request, "%s %s%s HTTP/1.0\r\n", - hd->req_type == HTTP_REQ_GET ? "GET" : - hd->req_type == HTTP_REQ_HEAD? "HEAD": - hd->req_type == HTTP_REQ_POST? "POST": "OOPS", - *p == '/'? "":"/", p ); - } - m_free(p); - - rc = write_server( hd->sock, request, strlen(request) ); - m_free( request ); - - 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 = m_alloc( 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; -} - -#if 0 -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 ) -{ - int sock,i=0; - struct sockaddr_in addr; - struct hostent *host=NULL; - unsigned long l; - - memset(&addr,0,sizeof(addr)); - - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - -#ifdef __MINGW32__ - init_sockets (); - - if((sock=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET) - { - log_error("error creating socket: ec=%d\n",(int)WSAGetLastError()); - return -1; - } -#else - if((sock=socket(AF_INET,SOCK_STREAM,0))==-1) - { - log_error("error creating socket\n"); - return -1; - } -#endif - -#ifdef __MINGW32__ - /* Win32 gethostbyname doesn't handle IP addresses internally, so we - try inet_addr first on that platform only. */ - if((l=inet_addr(server))==SOCKET_ERROR) -#endif - if((host=gethostbyname(server))==NULL) - { -#ifdef __MINGW32__ - log_error("%s: host not found: ec=%d\n",server,(int)WSAGetLastError()); -#else - log_error("%s: host not found\n",server); -#endif - sock_close(sock); - return -1; - } - - if(host) - { - if(host->h_addrtype != AF_INET) - { - log_error ("%s: unknown address family\n", server); - sock_close(sock); - return -1; - } - - if(host->h_length != 4 ) - { - log_error ("%s: illegal address length\n", server); - sock_close(sock); - return -1; - } - - /* Try all A records until one responds. */ - while(host->h_addr_list[i]) - { - memcpy(&addr.sin_addr,host->h_addr_list[i],host->h_length); - - if(connect(sock,(struct sockaddr *)&addr,sizeof(addr))==0) - break; - - i++; - } - - if(host->h_addr_list[i]==0) - { - sock_close(sock); - return -1; - } - } - else - { - memcpy(&addr.sin_addr,&l,sizeof(l)); - - if(connect(sock,(struct sockaddr *)&addr,sizeof(addr))!=0) - { - sock_close(sock); - return -1; - } - } - - return sock; -} - - -static int -write_server( int sock, const char *data, size_t length ) -{ - int nleft; - - nleft = length; - while( nleft > 0 ) { - #ifdef __MINGW32__ - 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 ); - 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 a3e9ad3e6..000000000 --- a/util/iobuf.c +++ /dev/null @@ -1,2189 +0,0 @@ -/* iobuf.c - file handling - * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <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 "iobuf.h" - -#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 __MINGW32__ -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 /*__MINGW32__*/ - -/* 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 - -/* - * Invalidate (i.e. close) a cached iobuf - */ -static void -fd_cache_invalidate (const char *fname) -{ - CLOSE_CACHE cc; - - assert (fname); - if( DBG_IOBUF ) - log_debug ("fd_cache_invalidate (%s)\n", fname); - - for (cc=close_cache; cc; cc = cc->next ) { - if ( cc->fp != INVALID_FP && !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; - } -#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 && !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 = m_alloc_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 && !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: ec=%d\n", - fp, (int)GetLastError () ); - 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; - m_free(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 ) ) { - int ec = (int)GetLastError (); - if ( ec != ERROR_BROKEN_PIPE ) { - log_error("%s: read error: ec=%d\n", a->fname, ec); - 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) ) { - int ec = (int)GetLastError (); - log_error("%s: write error: ec=%d\n", a->fname, ec); - 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 - m_free (a); /* we can free our context now */ - } -#endif /* !stdio implementation */ - return rc; -} - -#ifdef __MINGW32__ -/* 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); - m_free (a); /* we can free our context now */ - } - return rc; -} -#endif /*__MINGW32__*/ - -/**************** - * 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; - } - 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 { /* the gnupg partial length scheme - much better :-) */ - c = iobuf_get(chain); - a->size = c << 8; - c = iobuf_get(chain); - a->size |= c; - if( c == -1 ) { - log_error("block_filter: error reading length info\n"); - rc = G10ERR_READ_FILE; - } - if( !a->size ) { - a->eof = 1; - if( !n ) - rc = -1; - break; - } - } - } - - 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 = m_alloc( 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 = m_alloc( OP_MIN_PARTIAL_CHUNK ); - memcpy( a->buffer, p, nbytes ); - a->buflen = nbytes; - } - } - } - else { /* the gnupg scheme (which is not openpgp compliant) */ - size_t avail, n; - - for(p=buf; !rc && size; ) { - n = size; - avail = a->size - a->count; - if( !avail ) { - if( n > a->size ) { - iobuf_put( chain, (a->size >> 8) & 0xff ); - iobuf_put( chain, a->size & 0xff ); - avail = a->size; - a->count = 0; - } - else { - iobuf_put( chain, (n >> 8) & 0xff ); - iobuf_put( chain, n & 0xff ); - avail = n; - a->count = a->size - n; - } - } - if( n > avail ) - n = avail; - if( iobuf_write(chain, p, n ) ) - rc = G10ERR_WRITE_FILE; - a->count += n; - p += n; - size -= n; - } - } - } - 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; - } - m_free( a->buffer ); a->buffer = NULL; a->buflen = 0; - } - else { - iobuf_writebyte(chain, 0); - iobuf_writebyte(chain, 0); - } - } - else if( a->size ) { - log_error("block_filter: pending bytes!\n"); - } - if( DBG_IOBUF ) - log_debug("free block_filter %p\n", a ); - m_free(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 = m_alloc_clear(sizeof *a); - a->use = use; - a->d.buf = m_alloc( 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 ); - m_free( 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) ); - m_free(a->real_fname); - if (a->d.buf) { - memset (a->d.buf, 0, a->d.size); /* erase the buffer */ - m_free(a->d.buf); - } - m_free(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 = m_strdup ( 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 ); - m_free ( 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, 8192 ); - - 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; isdigit (fname[i]); i++ ) - ; - if ( !fname[i] ) - return atoi (fname); - } - return -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, 8192 ); - fcx = m_alloc( sizeof *fcx + strlen(fname) ); - fcx->fp = fp; - fcx->print_only_name = print_only; - strcpy(fcx->fname, fname ); - if( !print_only ) - a->real_fname = m_strdup( 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, 8192 ); - fcx = m_alloc( 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 __MINGW32__ - sock_filter_ctx_t *scx; - size_t len; - - a = iobuf_alloc( strchr( mode, 'w')? 2:1, 8192 ); - scx = m_alloc( 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, 8192 ); - fcx = m_alloc( sizeof *fcx + strlen(fname) ); - fcx->fp = fp; - fcx->print_only_name = print_only; - strcpy(fcx->fname, fname ); - if( !print_only ) - a->real_fname = m_strdup( 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, 8192 ); - fcx = m_alloc( sizeof *fcx + strlen(fname) ); - fcx->fp = fp; - strcpy(fcx->fname, fname ); - a->real_fname = m_strdup( 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, 8192 ); - fcx = m_alloc( sizeof *fcx + strlen(fname) ); - fcx->fp = fp; - strcpy(fcx->fname, fname ); - a->real_fname = m_strdup( 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 __MINGW32__ - 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:"?"); - if ( !a && !intval && ptrval ) { - #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 __MINGW32__ - 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 = m_alloc(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? m_strdup(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 = m_alloc( a->d.size ); - b->d.len = 0; - b->d.start = 0; - } - else { /* allocate a fresh buffer for the new stream */ - a->d.buf = m_alloc( 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. - */ -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); - m_free(a->d.buf); - m_free(a->real_fname); - memcpy(a,b, sizeof *a); - m_free(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 ) { - m_free( 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; - m_free(a->d.buf); - m_free(a->real_fname); - memcpy(a,b, sizeof *a); - m_free(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 ); - m_free(a->d.buf); - m_free(a->real_fname); - memcpy(a, b, sizeof *a); - m_free(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 ) { - m_free( 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 ); - m_free(a->d.buf); - m_free(a->real_fname); - memcpy(a,b, sizeof *a); - m_free(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 + 8192; - - log_debug("increasing temp iobuf from %lu to %lu\n", - (ulong)a->d.size, (ulong)newsize ); - newbuf = m_alloc( newsize ); - memcpy( newbuf, a->d.buf, a->d.len ); - m_free(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++]; - m_free(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 - */ -off_t -iobuf_get_filelength( IOBUF a ) -{ - struct stat st; - - 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; - - if ( (size=GetFileSize (fp, NULL)) != 0xffffffff ) - return size; - log_error ("GetFileSize for handle %p failed: ec=%d\n", - fp, (int)GetLastError () ); - #else - if( !fstat(my_fileno(fp), &st) ) - return st.st_size; - log_error("fstat() failed: %s\n", strerror(errno) ); - #endif - break; - } - - return 0; -} - -/**************** - * 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: ec=%d\n", - b->fp, (int)GetLastError () ); - 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; -} - -/**************** - * Start the block write mode, see rfc1991.new for details. - * A value of 0 for N stops this mode (flushes and writes - * the end marker) - */ -void -iobuf_set_block_mode( IOBUF a, size_t n ) -{ - block_filter_ctx_t *ctx = m_alloc_clear( sizeof *ctx ); - - assert( a->use == 1 || a->use == 2 ); - ctx->use = a->use; - if( !n ) { - if( a->use == 1 ) - log_debug("pop_filter called in set_block_mode - please report\n"); - pop_filter(a, block_filter, NULL ); - } - else { - ctx->size = n; /* only needed for use 2 */ - iobuf_push_filter(a, block_filter, ctx ); - } -} - -/**************** - * 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 = m_alloc_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 ); - } -} - - -/**************** - * Checks whether the stream is in block mode - * Note: This does not work if other filters are pushed on the stream. - */ -int -iobuf_in_block_mode( IOBUF a ) -{ - if( a && a->filter == block_filter ) - return 1; /* yes */ - return 0; /* no */ -} - - -/**************** - * 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 = m_alloc( 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 = m_realloc( 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 __MINGW32__ - { - 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 __MINGW32__ - #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: ec=%d\n", - fd, (int)GetLastError () ); - - fd = x; - } - #endif - #endif - return fd; -} - - diff --git a/util/logger.c b/util/logger.c deleted file mode 100644 index 6990473b2..000000000 --- a/util/logger.c +++ /dev/null @@ -1,334 +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 ) -{ - m_free(pgm_name); - if( name ) - pgm_name = m_strdup(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__ */ -} - -static void -print_prefix_f(const char *text, const char *fname) -{ - if( !logfp ) - logfp = stderr; - if( pgm_name ) - fprintf(logfp, "%s%s:%s: %s", pgm_name, pidstring, fname, text ); - else - fprintf(logfp, "?%s:%s: %s", pidstring, fname, 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_info_f( const char *fname, const char *fmt, ... ) -{ - va_list arg_ptr ; - - print_prefix_f("", fname); - 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_error_f( const char *fname, const char *fmt, ... ) -{ - va_list arg_ptr ; - - print_prefix_f("", fname); - 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_fatal_f( const char *fname, const char *fmt, ... ) -{ - va_list arg_ptr ; - - print_prefix_f("fatal: ", fname); - 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_debug_f( const char *fname, const char *fmt, ... ) -{ - va_list arg_ptr ; - - print_prefix_f("DBG: ", fname); - 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/memory.c b/util/memory.c deleted file mode 100644 index 9fab9ea3b..000000000 --- a/util/memory.c +++ /dev/null @@ -1,634 +0,0 @@ -/* memory.c - memory allocation - * Copyright (C) 1998, 1999, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 m_alloc - #undef m_alloc_clear - #undef m_alloc_secure - #undef m_alloc_secure_clear - #undef m_realloc - #undef m_free - #undef m_check - #undef m_strdup - #define FNAME(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 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"); - } - exit (2); -} - -/**************** - * Allocate memory of size n. - * This function gives up if we do not have enough memory - */ -void * -FNAME(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 * -FNAME(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 * -FNAME(alloc_clear)( size_t n FNAMEPRT ) -{ - void *p; - p = FNAME(alloc)( n FNAMEARG ); - memset(p, 0, n ); - return p; -} - -void * -FNAME(alloc_secure_clear)( size_t n FNAMEPRT) -{ - void *p; - p = FNAME(alloc_secure)( n FNAMEARG ); - memset(p, 0, n ); - return p; -} - - -/**************** - * realloc and clear the old space - */ -void * -FNAME(realloc)( void *a, size_t n FNAMEPRT ) -{ - void *b; - - #ifdef M_GUARD - if( a ) { - 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 = secmem_realloc( 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 -FNAME(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 -} - - -#if 0 /* not used */ -/**************** - * Make a copy of the memory block at a - */ -void * -FNAME(copy)( const void *a FNAMEPRT ) -{ - void *b; - size_t n; - - if( !a ) - return NULL; - - n = m_size(a); Aiiiih woher nehmen - if( m_is_secure(a) ) - b = FNAME(alloc_secure)(n FNAMEARG); - else - b = FNAME(alloc)(n FNAMEARG); - memcpy(b, a, n ); - return b; -} -#endif - -char * -FNAME(strdup)( const char *a FNAMEPRT ) -{ - size_t n = strlen(a); - char *p = FNAME(alloc)(n+1 FNAMEARG); - strcpy(p, a); - return p; -} - diff --git a/util/miscutil.c b/util/miscutil.c deleted file mode 100644 index e1735cd59..000000000 --- a/util/miscutil.c +++ /dev/null @@ -1,361 +0,0 @@ -/* miscutil.c - miscellaneous utilities - * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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( !isdigit(string[i]) ) - return 0; - if( !isdigit(string[5]) || !isdigit(string[6]) ) - return 0; - if( !isdigit(string[8]) || !isdigit(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; -} - - -u32 -add_days_to_timestamp( u32 stamp, u16 days ) -{ - return stamp + days*86400L; -} - - -/**************** - * 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 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, "%c %Z", 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_string( FILE *fp, const byte *p, size_t n, int delim ) -{ - for( ; n; n--, p++ ) - if( *p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim || - (delim && *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); -} - -/**************** - * 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 ); - m_free( 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 m_free() - */ -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 = m_alloc( 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 += 2; - } - } - else - *d++ = *p; - } - *d = 0; - return buffer; -} - -int -answer_is_yes_no_default( const char *s, int def_answer ) -{ - const char *long_yes = _("yes"); - const char *short_yes = _("yY"); - const char *long_no = _("no"); - const char *short_no = _("nN"); - - /* Note: we have to use the local dependent strcasecmp here */ - if( !strcasecmp(s, long_yes ) ) - return 1; - if( *s && strchr( short_yes, *s ) && !s[1] ) - return 1; - /* test for no strings to catch ambiguities for the next test */ - if( !strcasecmp(s, long_no ) ) - 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 ) -{ - const char *long_yes = _("yes"); - const char *long_no = _("no"); - const char *long_quit = _("quit"); - const char *short_yes = _("yY"); - const char *short_no = _("nN"); - const char *short_quit = _("qQ"); - - /* Note: We have to use the locale dependent strcasecmp */ - if( !strcasecmp(s, long_no ) ) - return 0; - if( !strcasecmp(s, long_yes ) ) - return 1; - if( !strcasecmp(s, long_quit ) ) - 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; -} diff --git a/util/riscos.c b/util/riscos.c deleted file mode 100644 index c64da3751..000000000 --- a/util/riscos.c +++ /dev/null @@ -1,299 +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#ifndef __RISCOS__C__ -#define __RISCOS__C__ - -#include <config.h> -#include <stdlib.h> -#include <stdarg.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> -#include <kernel.h> -#include <swis.h> -#include "util.h" -#include "memory.h" - -#define __UNIXLIB_INTERNALS -#include <unixlib/unix.h> -#undef __UNIXLIB_INTERNALS - -/* RISC OS specific defines that are not yet in UnixLib */ - -#define MimeMap_Translate 0x50B00 -#define MMM_TYPE_RISCOS 0 -#define MMM_TYPE_RISCOS_STRING 1 -#define MMM_TYPE_MIME 2 -#define MMM_TYPE_DOT_EXTN 3 - -/* 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 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 %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; -} - -static 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); -} - -/* exported RISC OS functions */ - -void -riscos_global_defaults(void) -{ - __riscosify_control = __RISCOSIFY_NO_PROCESS; - __feature_imagefs_is_file = 1; -} - -void -riscos_set_filetype(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 -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 -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 (!initialized) { - atexit (close_fds); - initialized = 1; - } - - h = fds_list; - fds_list = (struct fds_item *) m_alloc(sizeof(struct fds_item)); - fds_list->fd = fd; - fds_list->next = h; - - return fd; -} - -void -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); - m_free(fds_list); - fds_list = h; - } -} - -int -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 * -gstrans(const char *old) -{ - int size = 256, last; - char *buf, *tmp; - - buf = (char *) m_alloc(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 *) m_realloc(buf, size); - if (!tmp) - log_fatal("Can't claim memory for OS_GSTrans buffer!\n"); - buf = tmp; - } - - buf[last] = '\0'; - tmp = (char *) m_realloc(buf, last + 1); - if (!tmp) - log_fatal("Can't realloc memory after OS_GSTrans!\n"); - - return tmp; -} - -#ifdef DEBUG -void -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 *) m_alloc(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)) { - m_free(name); - log_fatal("Error when calling OS_Args(7)!\n"); - } - - if (_swix(OS_Args, _INR(0,1) | _OUT(0), 254, i, &len)) { - m_free(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); - m_free(name); - } -} -#endif - -void -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 d077fed17..000000000 --- a/util/secmem.c +++ /dev/null @@ -1,470 +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <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" - -#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 - err = plock( DATLOCK ); - if( err && errno ) - err = errno; -#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) - /* 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); - } - } - #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; -} - -void -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"); - } -} - - -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 */ - 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 * -secmem_realloc( 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( 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: */ - memset(mb, 0xff, size ); - memset(mb, 0xaa, size ); - memset(mb, 0x55, size ); - memset(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; - - memset( pool, 0xff, poolsize); - memset( pool, 0xaa, poolsize); - memset( pool, 0x55, poolsize); - memset( 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 b5ee446cb..000000000 --- a/util/simple-gettext.c +++ /dev/null @@ -1,497 +0,0 @@ -/* simple-gettext.c - a simplified version of gettext. - * Copyright (C) 1995, 1996, 1997, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 (__MINGW32__) && !defined (__CYGWIN32__) -#error This file can only be used with MingW32 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 <windows.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 loaded_domain -{ - char *data; - int must_swap; - u32 nstrings; -/* char *mapped; */ - 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. - * WARNING: After changing the filename you shoudl not access any data - * retrieved by gettext(). - */ -int -set_gettext_file( const char *filename ) -{ - 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 { /* relative path - append ".mo" and get dir from the environment */ - char *buf = NULL; - char *dir; - char *p; - - dir = read_w32_registry_string( NULL, - "Control Panel\\Mingw32\\NLS", - "MODir" ); - if( dir && (buf=malloc(strlen(dir)+strlen(filename)+1+3+1)) ) { - strcpy(stpcpy(stpcpy(stpcpy( buf, dir),"\\"), filename),".mo"); - /* Better make sure that we don't mix forward and - backward slashes. It seems that some Windoze - versions don't accept this. */ - for (p=buf; *p; p++) - { - if (*p == '/') - *p = '\\'; - } - domain = load_domain( buf ); - free(buf); - } - free(dir); - } - if( !domain ) - return -1; - } - - if( the_domain ) { - free( the_domain->data ); -/* free( the_domain->mapped ); */ - free( the_domain ); - the_domain = NULL; - } - the_domain = domain; - return NULL; -} - - -static const char* -get_string( struct loaded_domain *domain, u32 idx ) -{ - char *p = domain->data + SWAPIT(domain->must_swap, - domain->trans_tab[idx].offset); -#if 0 /* Mapping is not used any more. Instead we convert the files when - Creating the binary distribution. */ - if( !domain->mapped[idx] ) { - byte *pp; - - domain->mapped[idx] = 1; - /* we assume Latin1 -> CP 850 for now */ - for( pp=p; *pp; pp++ ) { - if( (*pp & 0x80) ) { - switch( *pp ) { - /* ISO-8859-1 to IBM-CP-850 */ - case 0xa0: *pp = '\xff' ; break; /* nobreakspace */ - case 0xa1: *pp = '\xad' ; break; /* exclamdown */ - case 0xa2: *pp = '\xbd' ; break; /* cent */ - case 0xa3: *pp = '\x9c' ; break; /* sterling */ - case 0xa4: *pp = '\xcf' ; break; /* currency */ - case 0xa5: *pp = '\xbe' ; break; /* yen */ - case 0xa6: *pp = '\xdd' ; break; /* brokenbar */ - case 0xa7: *pp = '\xf5' ; break; /* section */ - case 0xa8: *pp = '\xf9' ; break; /* diaeresis */ - case 0xa9: *pp = '\xb8' ; break; /* copyright */ - case 0xaa: *pp = '\xa6' ; break; /* ordfeminine */ - case 0xab: *pp = '\xae' ; break; /* guillemotleft */ - case 0xac: *pp = '\xaa' ; break; /* notsign */ - case 0xad: *pp = '\xf0' ; break; /* hyphen */ - case 0xae: *pp = '\xa9' ; break; /* registered */ - case 0xaf: *pp = '\xee' ; break; /* macron */ - case 0xb0: *pp = '\xf8' ; break; /* degree */ - case 0xb1: *pp = '\xf1' ; break; /* plusminus */ - case 0xb2: *pp = '\xfd' ; break; /* twosuperior */ - case 0xb3: *pp = '\xfc' ; break; /* threesuperior */ - case 0xb4: *pp = '\xef' ; break; /* acute */ - case 0xb5: *pp = '\xe6' ; break; /* mu */ - case 0xb6: *pp = '\xf4' ; break; /* paragraph */ - case 0xb7: *pp = '\xfa' ; break; /* periodcentered */ - case 0xb8: *pp = '\xf7' ; break; /* cedilla */ - case 0xb9: *pp = '\xfb' ; break; /* onesuperior */ - case 0xba: *pp = '\xa7' ; break; /* masculine */ - case 0xbb: *pp = '\xaf' ; break; /* guillemotright */ - case 0xbc: *pp = '\xac' ; break; /* onequarter */ - case 0xbd: *pp = '\xab' ; break; /* onehalf */ - case 0xbe: *pp = '\xf3' ; break; /* threequarters */ - case 0xbf: *pp = '\xa8' ; break; /* questiondown */ - case 0xc0: *pp = '\xb7' ; break; /* Agrave */ - case 0xc1: *pp = '\xb5' ; break; /* Aacute */ - case 0xc2: *pp = '\xb6' ; break; /* Acircumflex */ - case 0xc3: *pp = '\xc7' ; break; /* Atilde */ - case 0xc4: *pp = '\x8e' ; break; /* Adiaeresis */ - case 0xc5: *pp = '\x8f' ; break; /* Aring */ - case 0xc6: *pp = '\x92' ; break; /* AE */ - case 0xc7: *pp = '\x80' ; break; /* Ccedilla */ - case 0xc8: *pp = '\xd4' ; break; /* Egrave */ - case 0xc9: *pp = '\x90' ; break; /* Eacute */ - case 0xca: *pp = '\xd2' ; break; /* Ecircumflex */ - case 0xcb: *pp = '\xd3' ; break; /* Ediaeresis */ - case 0xcc: *pp = '\xde' ; break; /* Igrave */ - case 0xcd: *pp = '\xd6' ; break; /* Iacute */ - case 0xce: *pp = '\xd7' ; break; /* Icircumflex */ - case 0xcf: *pp = '\xd8' ; break; /* Idiaeresis */ - case 0xd0: *pp = '\xd1' ; break; /* Eth */ - case 0xd1: *pp = '\xa5' ; break; /* Ntilde */ - case 0xd2: *pp = '\xe3' ; break; /* Ograve */ - case 0xd3: *pp = '\xe0' ; break; /* Oacute */ - case 0xd4: *pp = '\xe2' ; break; /* Ocircumflex */ - case 0xd5: *pp = '\xe5' ; break; /* Otilde */ - case 0xd6: *pp = '\x99' ; break; /* Odiaeresis */ - case 0xd7: *pp = '\x9e' ; break; /* multiply */ - case 0xd8: *pp = '\x9d' ; break; /* Ooblique */ - case 0xd9: *pp = '\xeb' ; break; /* Ugrave */ - case 0xda: *pp = '\xe9' ; break; /* Uacute */ - case 0xdb: *pp = '\xea' ; break; /* Ucircumflex */ - case 0xdc: *pp = '\x9a' ; break; /* Udiaeresis */ - case 0xdd: *pp = '\xed' ; break; /* Yacute */ - case 0xde: *pp = '\xe8' ; break; /* Thorn */ - case 0xdf: *pp = '\xe1' ; break; /* ssharp */ - case 0xe0: *pp = '\x85' ; break; /* agrave */ - case 0xe1: *pp = '\xa0' ; break; /* aacute */ - case 0xe2: *pp = '\x83' ; break; /* acircumflex */ - case 0xe3: *pp = '\xc6' ; break; /* atilde */ - case 0xe4: *pp = '\x84' ; break; /* adiaeresis */ - case 0xe5: *pp = '\x86' ; break; /* aring */ - case 0xe6: *pp = '\x91' ; break; /* ae */ - case 0xe7: *pp = '\x87' ; break; /* ccedilla */ - case 0xe8: *pp = '\x8a' ; break; /* egrave */ - case 0xe9: *pp = '\x82' ; break; /* eacute */ - case 0xea: *pp = '\x88' ; break; /* ecircumflex */ - case 0xeb: *pp = '\x89' ; break; /* ediaeresis */ - case 0xec: *pp = '\x8d' ; break; /* igrave */ - case 0xed: *pp = '\xa1' ; break; /* iacute */ - case 0xee: *pp = '\x8c' ; break; /* icircumflex */ - case 0xef: *pp = '\x8b' ; break; /* idiaeresis */ - case 0xf0: *pp = '\xd0' ; break; /* eth */ - case 0xf1: *pp = '\xa4' ; break; /* ntilde */ - case 0xf2: *pp = '\x95' ; break; /* ograve */ - case 0xf3: *pp = '\xa2' ; break; /* oacute */ - case 0xf4: *pp = '\x93' ; break; /* ocircumflex */ - case 0xf5: *pp = '\xe4' ; break; /* otilde */ - case 0xf6: *pp = '\x94' ; break; /* odiaeresis */ - case 0xf7: *pp = '\xf6' ; break; /* division */ - case 0xf8: *pp = '\x9b' ; break; /* oslash */ - case 0xf9: *pp = '\x97' ; break; /* ugrave */ - case 0xfa: *pp = '\xa3' ; break; /* uacute */ - case 0xfb: *pp = '\x96' ; break; /* ucircumflex */ - case 0xfc: *pp = '\x81' ; break; /* udiaeresis */ - case 0xfd: *pp = '\xec' ; break; /* yacute */ - case 0xfe: *pp = '\xe7' ; break; /* thorn */ - case 0xff: *pp = '\x98' ; break; /* ydiaeresis */ - default : break; - } - } - } - - } -#endif /* unused code */ - 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: %d\n", (int)GetLastError() ); - - cp1 = GetConsoleCP(); - cp2 = GetConsoleOutputCP(); - log_info("InputCP=%u OutputCP=%u after switch1\n", cp1, cp2 ); -#endif - -#endif /* USE_SIMPLE_GETTEXT */ diff --git a/util/strgutil.c b/util/strgutil.c deleted file mode 100644 index e793fc1ce..000000000 --- a/util/strgutil.c +++ /dev/null @@ -1,955 +0,0 @@ -/* strgutil.c - string utilities - * Copyright (C) 1994, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include <config.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#ifdef HAVE_LANGINFO_CODESET -#include <langinfo.h> -#endif - -#include "types.h" -#include "util.h" -#include "memory.h" - - -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 -}; - - -static const char *active_charset_name = "iso-8859-1"; -static ushort *active_charset = NULL; -static int no_translation = 0; - -void -free_strlist( STRLIST sl ) -{ - STRLIST sl2; - - for(; sl; sl = sl2 ) { - sl2 = sl->next; - m_free(sl); - } -} - - -STRLIST -add_to_strlist( STRLIST *list, const char *string ) -{ - STRLIST sl; - - sl = m_alloc( sizeof *sl + strlen(string)); - sl->flags = 0; - strcpy(sl->d, string); - sl->next = *list; - *list = sl; - return sl; -} - -/**************** - * ame 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 ); - m_free( p ); - } - return sl; -} - -STRLIST -append_to_strlist( STRLIST *list, const char *string ) -{ - STRLIST r, sl; - - sl = m_alloc( 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 ); - m_free( 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=m_alloc(strlen(sl->d)+1); - strcpy(str,sl->d); - - *list=sl->next; - m_free(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 ; -} - -/**************** - * Wie strncpy(), aber es werden maximal n-1 zeichen kopiert und ein - * '\0' angehängt. Ist n = 0, so geschieht nichts, ist Destination - * gleich NULL, so wird via m_alloc Speicher besorgt, ist dann nicht - * genügend Speicher vorhanden, so bricht die funktion ab. - */ -char * -mem2str( char *dest , const void *src , size_t n ) -{ - char *d; - const char *s; - - if( n ) { - if( !dest ) - dest = m_alloc( 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; -} - - -int -set_native_charset( const char *newset ) -{ - if (!newset) -#ifdef HAVE_LANGINFO_CODESET - newset = nl_langinfo (CODESET); -#else - newset = "8859-1"; -#endif - - if (strlen (newset) > 3 && !ascii_memcasecmp (newset, "iso", 3)) { - newset += 3; - if (*newset == '-' || *newset == '_') - newset++; - } - - if( !*newset - || !ascii_strcasecmp (newset, "8859-1" ) - || !ascii_strcasecmp (newset, "8859-15" ) ) { - active_charset_name = "iso-8859-1"; - no_translation = 0; - active_charset = NULL; - } - else if( !ascii_strcasecmp( newset, "8859-2" ) ) { - active_charset_name = "iso-8859-2"; - no_translation = 0; - active_charset = latin2_unicode; - } - else if( !ascii_strcasecmp( newset, "koi8-r" ) ) { - active_charset_name = "koi8-r"; - no_translation = 0; - active_charset = koi8_unicode; - } - else if( !ascii_strcasecmp (newset, "utf8" ) - || !ascii_strcasecmp(newset, "utf-8") ) { - active_charset_name = "utf-8"; - no_translation = 1; - active_charset = NULL; - } - else - return G10ERR_GENERAL; - 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) { - buffer = m_strdup (string); - } - else if( active_charset ) { - for(s=string; *s; s++ ) { - length++; - if( *s & 0x80 ) - length += 2; /* we may need 3 bytes */ - } - buffer = m_alloc( 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; - } - else { - for(s=string; *s; s++ ) { - length++; - if( *s & 0x80 ) - length++; - } - buffer = m_alloc( 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; - } - 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. - */ -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( *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; - } - 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 = m_alloc( n + 1 ); - } - 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(*p); - return s; -} -#endif - -#ifndef HAVE_STRCASECMP -int -strcasecmp( const char *a, const char *b ) -{ - for( ; *a && *b; a++, b++ ) { - if( *a != *b && toupper(*a) != toupper(*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(*a) != toupper(*b) ) - break; - } - if (!n) - return 0; - return *(const byte*)a - *(const byte*)b; -} -#endif - - -#ifdef __MINGW32__ -/* - * Like vsprintf but provides a pointer to malloc'd storage, which - * must be freed by the caller (m_free). 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 = m_alloc (total_width); - if (*result != NULL) - return vsprintf (*result, format, args); - else - return 0; -} - -#endif /*__MINGW32__*/ - diff --git a/util/ttyio.c b/util/ttyio.c deleted file mode 100644 index 40fe7eb52..000000000 --- a/util/ttyio.c +++ /dev/null @@ -1,481 +0,0 @@ -/* ttyio.c - tty i/O functions - * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 __MINGW32__ /* use the odd Win32 functions */ - #include <windows.h> - #ifdef HAVE_TCGETATTR - #error mingw32 and termios - #endif -#endif -#include <errno.h> -#include <ctype.h> -#include "util.h" -#include "memory.h" -#include "ttyio.h" - -#define CONTROL_D ('D' - 'A' + 1) -#ifdef __VMS - #define TERMDEVICE "/dev/tty" -#else - #define TERMDEVICE "/dev/tty" -#endif - -#ifdef __MINGW32__ /* 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 - - -#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(__MINGW32__) - { - 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: rc=%d", (int)GetLastError() ); - 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: rc=%d", (int)GetLastError() ); - } - 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(TERMDEVICE, "r+"); - if( !ttyfp ) { - log_error("cannot open /dev/tty: %s\n", strerror(errno) ); - exit(2); - } - #endif - #ifdef HAVE_TCGETATTR - atexit( cleanup ); - #endif - initialized = 1; -} - -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 __MINGW32__ - { - 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: rc=%d", (int)GetLastError() ); - if( n != nwritten ) - log_fatal("WriteConsole failed: %d != %d\n", n, (int)nwritten ); - last_prompt_len += n; - m_free (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( byte *p, size_t n ) -{ - if (no_terminal) - return; - - if( !initialized ) - init_ttyfp(); - - #ifdef __MINGW32__ - /* 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( 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( strlen( buf ) > max_n ) { - buf[max_n] = 0; - } - /*(utf8 conversion already does the control character quoting)*/ - tty_printf("%s", buf ); - m_free( buf ); - } - else { - if( n > max_n ) { - n = max_n; - } - tty_print_string( p, n ); - } -} - -void -tty_print_utf8_string( byte *p, size_t n ) -{ - tty_print_utf8_string2( p, n, n ); -} - - -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; - tty_printf( "%s", prompt ); - buf = m_alloc(n=50); - i = 0; - - #ifdef __MINGW32__ /* windoze version */ - if( hidden ) - SetConsoleMode(con.in, HID_INPMODE ); - - for(;;) { - DWORD nread; - - if( !ReadConsoleA( con.in, cbuf, 1, &nread, NULL ) ) - log_fatal("ReadConsole failed: rc=%d", (int)GetLastError() ); - 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 = m_realloc( buf, n ); - } - buf[i++] = c; - } - - if( hidden ) - SetConsoleMode(con.in, DEF_INPMODE ); - - #elif defined(__riscos__) - 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 = m_realloc(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 - } - - /* 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 = m_realloc( 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 ) -{ - 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 __MINGW32__ - 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); - m_free(p); - return yes; -} - diff --git a/util/w32reg.c b/util/w32reg.c deleted file mode 100644 index 5391c8027..000000000 --- a/util/w32reg.c +++ /dev/null @@ -1,171 +0,0 @@ -/* w32reg.c - MS-Windows Registry access - * Copyright (C) 1999, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include <config.h> -#if defined (__MINGW32__) || 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 m_free()!!! - */ -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 HLM. */ - 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 ) ) - 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); - 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, ®_key ) - != ERROR_SUCCESS ) - return -1; - - if ( RegSetValueEx( reg_key, name, 0, REG_SZ, (BYTE *)value, - strlen( value ) ) != ERROR_SUCCESS ) { - if ( RegCreateKey( root_key, name, ®_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__ */ |