/*
Copyright (c) 2000-2010, Dirk Krause
All rights reserved.

Redistribution and use in source and binary forms,
with or without modification, are permitted provided
that the following conditions are met:

* Redistributions of source code must retain the above
  copyright notice, this list of conditions and the
  following disclaimer.
* Redistributions in binary form must reproduce the above 
  opyright notice, this list of conditions and the following
  disclaimer in the documentation and/or other materials
  provided with the distribution.
* Neither the name of the Dirk Krause nor the names of
  contributors may be used to endorse or promote
  products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/

/**	@file dkapp.h	Application functions.
@section	overview	Overview
This module provides functions for command line applications
such as:
- preferences handling,
- internationization (file search depending on users language and region) and
- logging.

Preferences are persistent key/value pairs of strings stored in configuration
files or registry entries. Command line arguments can be used to overwrite
the stored preferences. The key consists of a scope and a name. The scope
activates or deactivates a preference for combinations of user name,
application name and host name. A scope is valid if the scope user name matches
the current user name, the application name matches the current application
name and the host name matches the current host name. Wildcards (``*'') may
be used in the configuration files or registry entries to match any name.

If user ``joe'' runs application ``dosomething'' on the host ``pc'', the
following scopes are searched to find a
preference: *|*|*, *|*|pc, *|dosomething|*, *|dosomething|pc,
joe|*|*, joe|*|pc, joe|dosomething|*, joe|dosomething|pc.

The last scope has highest priority, preferences in this scope overwrite
preferences defined in other scope.

Note: In scope names in registry entries or configuration files
use slashes ``/'' instead of the pipe symbols ``|''
used in the paragraph above. The pipe symbol was used as a separator here
because combinations of slashes and asterisks are treated as opening and
closing comments in header files.

\anchor searchorder
File search is based on the users preferred language and region and can
be used for internationalization.<br>
The search order is described in
<a href="../../search.html">dklibs - File search</a>.

\anchor stringtransform
To build file names one can use macros as described in
<a href="../../prefs.html#macros">dlibs - Preferences, section "Macros in preferences"</a>
and run a string transformation.

Log output can be written to multiple destinations:
- standard output,
- standard error output,
- log file or
- syslog system (if available).
A priority is assigned to each log message, preferences can be used to
specify the required priority for each log destination and message format.

Unless otherwise stated, int functions in this module return a positive
number to indicate success or a true condition, 0 to indicate an error
or an unfullfilled condition.
Pointer functions return valid pointers on success, NULL on error.

Some functions return pointers to internal data or other memory managed
the the application support structure. This memory is released during
dkapp_close(), so do not attempt to use the pointers after the application
support structure was destroyed.
*/

#ifndef DK_APP_INCLUDED
#define DK_APP_INCLUDED 1

#include <dk.h>
#include <dktypes.h>

#if defined(EXTERN)
#undef EXTERN
#endif
/** Keyword for functions in external files. */
#ifndef DK_APP_C
#if !DK_HAVE_PROTOTYPES
#define EXTERN extern
#else
#define EXTERN /* nix */
#endif
#else
#define EXTERN /* nix */
#endif

#if defined(__cplusplus)
extern "C" {
#endif



/**	Create application support structure.
	This function creates a new application support structure and returns
	a pointer to it. Memory needed for the structure is allocated
	dynamically. Use dkapp_close() to destroy the structure and release
	the memory after usage.
	@param	argc	The argc argument of the main() function.
	@param	argv	The argv argument of the main() function.
	@param	grname	Pointer to string, program group name.
	@param	etc	System configuration directory (usually ``/etc'').
	@param	sil	Flag, run silently.
	@param	nostd	Use no standard output/standard error output.
	@return	Pointer to new application structure on success, NULL on error.
*/
EXTERN
dk_app_t *dkapp_open_ext1 DK_PR((int argc, char **argv, char *grname, char *etc, int sil, int nostd));



/**	Check command line arguments for --/log/off.
	This function can be used to set the \a s parameter for
	dkapp_open_ext1().
	@param	argc	The argc parameter from the main() function.
	@param	argv	The argv parameter from the main() function.
	@return	Flag to indicate whether --/log/off was found.
*/
EXTERN int
dkapp_silence_check DK_PR((int argc, char **argv));



/**	Create application support structure (obsoleted).
	@param	argc	The argc argument of the main() function.
	@param	argv	The argv argument of the main() function.
	@return	Pointer to new application structure on success, NULL on error.
*/
EXTERN
dk_app_t *
dkapp_open DK_PR((int argc, char **argv));



/**	Set application group name for application opened with dkapp_open().
	As the group name is unknown while dkapp_open() is running
	there might be problems finding files in dkapp_open().
	I recommend to use dkapp_open_ext1() instead od dkapp_open() and
	dkapp_set_groupname() to avoid this problem.
	@param	a	Application support structure.
	@param	n	Application group name.
	@return	Flag to indicate success.
*/
EXTERN int
dkapp_set_groupname DK_PR((dk_app_t *a, char *n));



/**	Set silence flag for application opened with dkapp_open().
	When using dkapp_open() and dkapp_set_silent() the application
	will _not_ be in silent mode while dkapp_open() is running.
	Errors from dkapp_open() will be reported.
	I recommend to use dkapp_open_ext1() and set the silence flag
	there.
	@param	a	Application support structure.
	@param	f	New silence flag value.
*/
EXTERN void
dkapp_set_silent DK_PR((dk_app_t *a, int f));



/**	Set no-standard-output flag for application opened with dkapp_open().
	When using dkapp_open() and dkapp_set_nostdio() the application
	will probably report errors to standard output and standard
	error output while dkapp_open() is running.
	I recommend to use dkapp_open_ext1() instead and set the
	no-standard-output flag there.
	@param	a	Application support structure.
	@param	f	New flag value.
*/
EXTERN void
dkapp_set_nostdio DK_PR((dk_app_t *a, int f));



/**	Destroy application support structure and release memory.
	@param	a	Pointer to the structure.
*/
EXTERN
void dkapp_close DK_PR((dk_app_t *a));



/**	Retrieve application name.
	This function returns the application name without leading
	directory name and without trailing ``.exe'' (on Windows systems).
	@param	a	Application support structure.
	@return	The application name.
*/
EXTERN char *
dkapp_get_appname DK_PR((dk_app_t *a));



/**	Retrieve number of ``real'' command line arguments
	(command line options to overwrite preferences removed).
	@param	a	Application support structure.
*/
EXTERN int
dkapp_get_argc DK_PR((dk_app_t *a));



/**	Retrieve array of ``real'' command line arguments
	(command line options to overwrite preferences removed).
	@param	a	Application support structure.
*/
EXTERN char **
dkapp_get_argv DK_PR((dk_app_t *a));



/**	Get preference.
	@param	a	Application support structure.
	@param	k	Key (preference name without scope).
	@param	b	Buffer to receive result.
	@param	l	Length of buffer \a b.
	@param	x	Scopes to exclude (0 or combination of
	DK_APP_PREF_EXCL_xxx constants).
	@return	Flag to indicate success.
*/
EXTERN
int
dkapp_get_pref DK_PR((dk_app_t *a, char *k, char *b, size_t l, int x));



/**	Get preference or environment variable contents.
	Search order is:
	- command line options to overwrite preferences
	- environment variable
	- user and system dependant configuration entries.
	@param	a	Application support structure.
	@param	key	Key (preference name without scope).
	@param	b	Buffer to receive result.
	@param	lgt	Length of buffer \a b.
	@param	excl	Scopes to exclude (0 or combination of
	DK_APP_PREF_EXCL_xxx constants).
	@param	ep	Name of environment variable to test.
	@return	Flag to indicate success.
*/
EXTERN
int
dkapp_get_pref_env DK_PR(( dk_app_t *a, char *key, char *b, size_t lgt, int excl, char *ep));



/**	Set preference value.
	The preference is set in the user|application|* scope.
	On Windows system the new value is written to the registry
	immediately. On other systems the configuration entry is kept in
	memory, the configuration file is updated at the end of the
	application by the dkapp_close() function.
	@param	a	Application support structure.
	@param	k	Preference name (without scope).
	@param	v	Preference value.
	@return	Flag to indicate success.
*/
EXTERN
int dkapp_set_pref DK_PR((dk_app_t *a, char *k, char *v));



/**	Retrieve boolean value from preferences.
	@param	a	Application support structure.
	@param	k	Preference name.
	@return
	- -1 if preference not found,
	-  0 if value is false or
	-  1 if value is true.
*/
EXTERN int
dkapp_get_bool_pref DK_PR((dk_app_t *a, char *k));



/**	Retrieve unsigned long value from preferences.
	@param	a	Application support structure.
	@param	k	Preference name.
	@return	The value. If the preference was not found or is not
	an unsigned long the function returns 0.
*/
EXTERN unsigned long
dkapp_get_ul_pref DK_PR((dk_app_t *a, char *k));



/**	Retrieve string value from preferences.
	On success the function returns a pointer to a copy of the
	value in dynamically allocated memory. Use dk_delete() to release
	the memory after usage.
	@param	a	Application support structure.
	@param	k	Preference name
	@return	Pointer to string value on success, NULL on error
	(not found or not enough memory).
*/
EXTERN char *
dkapp_get_str_pref DK_PR((dk_app_t *a, char *k));



/**	Set unconfigure flag for the application.
	At the end of the application dkapp_close() does not update
	the configuration file. Instead the configuration file is
	removed, on Windows systems the registry key is removed.
	@param	a	Application support structure.
*/
EXTERN void
dkapp_unconfigure DK_PR((dk_app_t *a));



/**	Transform string (substitute placeholders).
	@param	a	Application support structure.
	@param	d	Destination (pointer to buffer to receive result).
	@param	l	Size of \a d in bytes.
	@param	s	Source string.
	@return	Flag to indicate success.
	See
	@ref stringtransform "String transformations in the dkapp module"
	for details about string transformations.
*/
EXTERN
int
dkapp_transform_string DK_PR((dk_app_t *a,char *d,size_t l,char *s));



/**	Transform string, correct slashes/backslashes in file names if
	necessary.
	@param	a	Application support structure.
	@param	d	Destination (pointer to buffer to receive result).
	@param	l	Size of \a d in bytes.
	@param	s	Source string.
	@param	f	Flag, the text to transform is a file name.
	@return	Flag to indicate success.
	See
	@ref stringtransform "String transformations in the dkapp module"
	for details about string transformations.
*/
EXTERN
int
dkapp_transform_string_ext1 DK_PR((dk_app_t *a,char *d,size_t l,char *s,int f));



/**	Create name for temporary file.
	A file name for a temporary file in the applications temporary
	directory is created.
	@param	a	Application support structure.
	@param	b	Buffer to receive result.
	@param	s	Length of buffer \a b in bytes.
	@return	Flag to indicate success.
*/
EXTERN int
dkapp_tmpnam DK_PR((dk_app_t *a, char *b, size_t s));



/**	Log multi-part message.
	Write a multi-part log message to the different log destinations.
	@param	a	Application support structure.
	@param	p	Log priority.
	@param	m	Pointer to array of pointers to messages parts.
	@param	n	Number of array elements in \a m.
	@return	Flag to indicate success.
*/
EXTERN
int dkapp_log_msg DK_PR((dk_app_t *a, int p, char **m, int n));



/**	Set name of source file to use in log messages (error position).
	Specify the error position (file and line number) before
	calling dkapp_log_msg() if necessary.

	The pointer is stored ``as is'' in the application support structure,
	no copy is created.
	As long as the file name in the error position remains the same
	do not change the buffer \a n points to.
	@param	a	Application support structure.
	@param	n	Name of source file or NULL (do not show error
	position).

*/
EXTERN void
dkapp_set_source_filename DK_PR((dk_app_t *a, char *n));



/**	Set line number to use in log messages (error position).
	Specify the error position (file and line number) before calling
	dkapp_log_msg().
	@param	a	Application support structure.
	@param	l	The line number (or 0 if the line number is not known).
*/
EXTERN void
dkapp_set_source_lineno DK_PR((dk_app_t *a, unsigned long l));



/**	Retrieve source file name for error positions.
	@param	a	Application support structure.
	@return	The file name currently configured to show error positions
	or NULL.
*/
EXTERN char *
dkapp_get_source_filename DK_PR((dk_app_t *a));



/**	Retrieve source line number for error positions.
	@param	a	Application support structure.
	@return	The line number used in error positions.
*/
EXTERN unsigned long
dkapp_get_source_lineno DK_PR((dk_app_t *a));



/**	Retrieve maximum log message priority found.
	@param	a	Application support structure.
	@return	The maximum priority of all log messages issued by the
	application since it was started.
*/
EXTERN
int dkapp_llmax_get DK_PR((dk_app_t *a));



/**	Get the minimum log priority required by all log destinations.
	If -- for instance -- the minimum log priority required by any
	destination is "warning" there is no need to load string tables
	for localized debug messages.
	@param	a	Application support structure.
	@return	The minimum log priority required by any log destination.
*/
EXTERN int
dkapp_get_min_loglevel DK_PR((dk_app_t *a));



/**	Get key indicating which output style to simulate.
	@param	s	Name of program to imitate:
	"gcc", "msvc", "workshop" or "tasm".
	@return	Numeric key for the type.
*/
EXTERN int
dkapp_ide_type DK_PR((char *s));



/**	Set log message priority required to not delete the
	temporary directory at the end of the application.
	Normally the applications temporary directory (and all it's
	contents) is removed by dkapp_close() at the end of the application.
	For debugging purposes you might want to keep the directory for
	inspection if there were log messages of specific priorities
	(i.e. errors or worse).
	@param	a	Application support structure.
	@param	p	Log message priority required to keep
	temporary directory.
*/
EXTERN void
dkapp_set_keep_temp DK_PR((dk_app_t *a, int p));



/**	Overwrite maximum log message priority found.
	Normally there should be no reason to use this function.
	But you may use this function together with dkapp_set_keep_temp()
	if you want to keep the temporary directory after the application
	exits.
	@param	a	Application support structure.
	@param	p	New maximum priority value.
*/
EXTERN
void dkapp_llmax_set DK_PR((dk_app_t *a, int p));



/**	Check whether or not a log priority was already used.
	This function checks whether there already were log messages
	of priority \a p or above.
	@param	a	Application support structure.
	@param	p	Log priority.
	@return	Flag, test result.
*/
EXTERN int
dkapp_log_level_in_use DK_PR((dk_app_t *a, int p));



/**	Find file, create copy of file name.
	@param	a	Application.
	@param	n	File name (short).
	@param	subdirtype	Flags for subdirectories to search.
	@return	Full path name in dynamically allocated memory,
	use dk_delete() to release the memory.
*/
EXTERN char *
dkapp_find_file_dup_ext1 DK_PR((dk_app_t *a,char *n,int *subdirtype));



/**	Find a file (find full path for short file name).
	@param	a	Application.
	@param	name	File name (short).
	@param	buffer	Result buffer.
	@param	sz	Size of \a buffer.
	@param	subdirtype	Pointer to a variable indicating which
		subdirectories to search.
	@return	1 on success, 0 on error.
*/
EXTERN int
dkapp_find_file_ext1 DK_PR((dk_app_t *a, char *name, char *buffer,\
size_t sz, int *subdirtype));



/**	Search for file.
This function searches for a file.
See ``Search order for dkapp_find_file() and dkapp_find_cfg()'' for a list of
directories searched.
@param	a	Application support structure.
@param	n	File name to search for.
@param	b	Buffer to receive the result.
@param	s	Size of \a b in bytes.
@return	Flag to indicate success.
See
@ref searchorder "Search order for dkapp_find_file() and dkapp_find_cfg()"
for details about the search order.
*/
EXTERN
int
dkapp_find_file DK_PR((dk_app_t *a, char *n, char *b, size_t s));



/**	Search for configuration file.
See ``Search order for dkapp_find_file() and dkapp_find_cfg()'' for a list of
directories searched.
@param	a	Application support structure.
@param	n	File name to search for.
@param	b	Buffer to receive the result.
@param	s	Size of \a b in bytes.
@return	Flag to indicate success.
See
@ref searchorder "Search order for dkapp_find_file() and dkapp_find_cfg()"
for details about the search order.
*/
EXTERN
int
dkapp_find_cfg DK_PR((dk_app_t *a, char *n, char *b, size_t s));



/**	Search for file, return copy of file name.
This function searches for a file and creates a copy of the file name found
in dynamically allocated memory. Use dk_delete() to release the memory
after usage.
See ``Search order for dkapp_find_file() and dkapp_find_cfg()'' for a list of
directories searched.
@param	a	Application support structure.
@param	n	File name to search for.
@return	Pointer to copy of file name found on success, NULL on error.
See
@ref searchorder "Search order for dkapp_find_file() and dkapp_find_cfg()"
for details about the search order.
*/
EXTERN char *
dkapp_find_file_dup DK_PR((dk_app_t *a, char *n));



/**	Search for configuration file, return copy of file name.
This function searches for a file and creates a copy of the file name found
in dynamically allocated memory. Use dk_delete() to release the memory
after usage.
See ``Search order for dkapp_find_file() and dkapp_find_cfg()'' for a list of
directories searched.
@param	a	Application support structure.
@param	n	File name to search for.
@return	Pointer to copy of file name found on success, NULL on error.
See
@ref searchorder "Search order for dkapp_find_file() and dkapp_find_cfg()"
for details about the search order.
*/
EXTERN char *
dkapp_find_cfg_dup DK_PR((dk_app_t *a, char *n));


/**	Open a file for reading, return stream.
	@param	a	Application support structure.
	@param	n	File name.
	@param	t	Pointer to variable to store sub directory type.
	@return	Pointer to stream, use dkstream_close() to
	close the stream and release memory.
*/
EXTERN dk_stream_t *
dkapp_read_file_ext1 DK_PR((dk_app_t *a, char *n, int *t));


/**	Open a file for reading, return stream.
	@param	a	Application support structure.
	@param	n	File name.
	@return	Pointer to stream, use dkstream_close() to
	close the stream and release memory.
*/
EXTERN dk_stream_t *
dkapp_read_file DK_PR((dk_app_t *a, char *n));


/**	Search for file and open file for reading.
See ``Search order for dkapp_find_file() and dkapp_find_cfg()'' for a list of
directories searched.
@param	a	Application support structure.
@param	n	File name.
@return	dk_stream_t pointer to read the file on success, NULL on error.
On success use dkstream_close() to close the dk_stream_t after usage.
See
@ref searchorder "Search order for dkapp_find_file() and dkapp_find_cfg()"
for details about the search order.
*/
EXTERN dk_stream_t *
dkapp_read_cfg DK_PR((dk_app_t *a, char *n));



/**	Open file for writing.
	This function opens file to write plain or compressed
	(gzip or bzip2 for suffixes ``.gz'' or ``.bz2'' if compiled
	with gzip/bzip2 support).
	@param	a	Application support structure.
	@param	n	File name.
	@return	dk_stream_t pointer to write to on success, NULL on error.
	On success use dkstream_close() to close the dk_stream_t after usage.
*/
EXTERN dk_stream_t *
dkapp_write_file DK_PR((dk_app_t *a, char *n));



/**	Find string (use for localization).
	The function attempts to read string table \a t and searches
	for a string for key \a k. On success a pointer to the string
	is returned, the string is placed in memory maintained by the
	application support structure. After dkapp_close() you must not
	longer use it.
	@param	a	Application support structure.
	@param	t	String table name.
	@param	k	String key.
	@param	d	Default value (if table not found, string not
			found or out of memory).
	@return	String found in string table or \a d. May be NULL.
*/
EXTERN
char *
dkapp_find_string DK_PR((dk_app_t *a, char *t, char *k, char *d));



/**	Find multiple strings (use for localization).
	The function attempts to load string table \a t (if not yet
	loaded).
	Now it attempts to find all the strings configured in \a f.
	@param	a	Application support structure
	@param	f	Configuration of all strings to search for.
	@param	t	String table name.
*/
EXTERN void
dkapp_find_multi DK_PR((dk_app_t *a, dk_string_finder_t *f, char *t));



/**	Find multiple strings.
	@param	a	Application support structure.
	@param	k	Array of key/value pairs, each element
			must be initialized to contain a string key
			and a default string.
	@param	s	The number of elements in \a k.
	@param	n	String table name.
	@param	b	Array of string pointers to receive the results,
			must have \a s elements. The array elements are
			either set to the strings found in the string table
			or to the defaults provided in \a k.
*/
EXTERN void
dkapp_init_key_value DK_PR((dk_app_t *a,dk_key_value_t *k,size_t s,char *n, char **b));



/**	Find multiple strings.
	@param	a	Application support structure.
	@param	k	Array of key/value pairs, each element
			must be initialized to contain a string key
			and a default string.
	@param	s	The number of elements in \a k.
	@param	n	String table name.
	@return	A char ** pointer (array to pointers of strings). The
	memory for the pointer array is allocated dynamically, use
	dk_delete() to release the memory.
*/
EXTERN char **
dkapp_find_key_value DK_PR((dk_app_t *a,dk_key_value_t *k,size_t s,char *n));



/**	Show localized help text.
	The function searches for file \a n and prints its contents
	to standard output. If the file is not found the elements of the
	string array \a d are shown instead. The final element in
	\a d must be a NULL pointer.
	@param	a	Application support structure.
	@param	n	File name of help file.
	@param	d	Array of pointers to strings (last element must
			be NULL).
*/
EXTERN void
dkapp_help DK_PR((dk_app_t *a, char *n, char **d));



/**	Open a file for use with dk_stream_t API (plain file),
	apply security checks before opening the file.
	@param	a	Application support  structure.
	@param	n	File name.
	@param	m	File open mode (i.e. "r", "w"...).
	@return	dk_stream_t pointer on success, NULL on error.
	On success call dkstream_close() on the dk_stream_t pointer after
	usage.
*/
EXTERN dk_stream_t *
dkapp_stream_openfile DK_PR((dk_app_t *a, char *n, char *m));



/**	Open a file for use with dk_stream_t API (gzip compressed file,
	requires gzip support), apply security checks before opening the file.
	@param	a	Application support  structure.
	@param	n	File name.
	@param	m	File open mode (i.e. "r", "w"...).
	@return	dk_stream_t pointer on success, NULL on error.
	On success call dkstream_close() on the dk_stream_t pointer after
	usage.
*/
EXTERN dk_stream_t *
dkapp_stream_opengz DK_PR((dk_app_t *a, char *n, char *m));



/**	Open a file for use with dk_stream_t API (bzip2 compressed file,
	requires bzip2 support), apply security checks before opening the file.
	@param	a	Application support  structure.
	@param	n	File name.
	@param	m	File open mode (i.e. "r", "w"...).
	@return	dk_stream_t pointer on success, NULL on error.
	On success call dkstream_close() on the dk_stream_t pointer after
	usage.
*/
EXTERN dk_stream_t *
dkapp_stream_openbz2 DK_PR((dk_app_t *a, char *n, char *m));



/**	Open a file, apply security checks before opening the file.
	@param	a	Application support  structure.
	@param	n	File name.
	@param	m	File open mode (i.e. "r", "w"...).
	@return	FILE pointer on success, NULL on error.
	On success call fclose() on the pointer after usage.
*/
EXTERN FILE *
dkapp_fopen DK_PR((dk_app_t *a, char *n, char *m));



/**	Get security checks ignored by dkapp_fopen(), dkapp_stream_openfile(),
	dkapp_stream_opengz() and dkapp_stream_openbz2().
	You can use command line options to set preferences to ignore
	some of the additional security checks applied when opening files.
	This is not recommended.
	@param	a	Application support structure.
	@return	Or-combined DK_SF_SEC_xxx constants for checks to ignore,
	see dksf.h.
*/
EXTERN int
dkapp_get_relaxed_fopen_check DK_PR((dk_app_t *a));



/**	Get pointer to codepage.
	@param	a	Application support structure.
	@return	Pointer to 256 byte codepage on success, NULL on error.
*/
EXTERN unsigned char *
dkapp_get_stdout_codepage DK_PR((dk_app_t *a));



/**	Check whether a file name expander matches exactly one entry,
	report error if necessary. The function returns a copy of the file
	name placed in dynamically allocated memory on success. Use
	dk_delete() to release the memory.
	@param	a	Application support structure.
	@param	f	File name expander.
	@param	p	Pattern to match.
	@return	Pointer to file name on success, NULL on error.
	On success use dk_delete() for the pointer to release the
	memory after usage.
*/
EXTERN char *
dkapp_fne_one DK_PR((dk_app_t *a, dk_fne_t *f, char *p));



/**	Print a string to standard output, do codepage translations if
	necessary.
	@param	a	Application support structure.
	@param	s	String to print.
*/
EXTERN void
dkapp_stdout DK_PR((dk_app_t *a, char *s));



/**	Print string to standard error output, do codepage translations
	if necessary.
	@param	a	Application support structure.
	@param	s	String to print.
*/
EXTERN void
dkapp_stderr DK_PR((dk_app_t *a, char *s));



/**	Print string to file, do codepage translations if necessary.
	@param	a	Application support structure.
	@param	s	String to print.
	@param	f	Destination file.
*/
EXTERN void
dkapp_fputs DK_PR((dk_app_t *a, char *s, FILE *f));



/**	Get number of glyphs to print.
	Some encodings -- i.e. UTF-8 -- use multiple bytes for one
	character/glyph.
	@param	a	Application support structure.
	@param	s	String.
*/
EXTERN size_t
dkapp_prlen DK_PR((dk_app_t *a, char *s));


/**	Information message: No OpenSSL support available.
	@param	a	Application support structure.
*/
EXTERN void
dkapp_info_no_openssl_support DK_PR((dk_app_t *a));



/**	Error message: Failed to traverse directory.
	@param	a	Application support structure.
	@param	n	Directory name.
*/
EXTERN void
dkapp_err_traverse_dir DK_PR((dk_app_t *a, char *n));



/**	Error message: Failed to obtain information about file.
	@param	a	Application support structure.
	@param	n	File name.
*/
EXTERN void
dkapp_err_stat_failed DK_PR((dk_app_t *a, char *n));



/**	Error message: Failed to find current working directory.
	@param	a	Application support structure.
*/
EXTERN void
dkapp_err_cwd DK_PR((dk_app_t *a));



/**	Error message: Failed to allocate memory.
	@param	a	Application support structure.
	@param	e	Element size.
	@param	n	Number of elements.
*/
EXTERN void
dkapp_err_memory DK_PR((dk_app_t *a, size_t e, size_t n));



/**	Error message: No file name is matching the name pattern
	@param	a	Application support structure.
	@param	n	File name pattern.
*/
EXTERN void
dkapp_err_matchfile DK_PR((dk_app_t *a, char *n));



/**	Error message: No directory name is matching the pattern.
	@param	a	Application support structure.
	@param	n	Directory name.
*/
EXTERN void
dkapp_err_matchdir DK_PR((dk_app_t *a, char *n));



/**	Error message: Failed to open file for reading.
	@param	a	Application support structure.
	@param	n	File name.
*/
EXTERN void
dkapp_err_fopenr DK_PR((dk_app_t *a, char *n));



/**	Error message: Failed to open file for writing.
	@param	a	Application support structure.
	@param	n	File name.
*/
EXTERN void
dkapp_err_fopenw DK_PR((dk_app_t *a, char *n));



/**	Error message: Error while writing to file.
	@param	a	Application support structure.
	@param	n	File name.
*/
EXTERN void
dkapp_err_fwrite DK_PR((dk_app_t *a, char *n));



/**	Error message: Error while reading from file.
	@param	a	Application support structure.
	@param	n	File name.
*/
EXTERN void
dkapp_err_fread DK_PR((dk_app_t *a, char *n));



/**	Error message: Additional security checks deny write operations to
	file.
	@param	a	Application support structure.
	@param	n	File name.
	@param	r	Key for the failed security check.
*/
EXTERN void
dkapp_err_nowrite DK_PR((dk_app_t *a, char *n, int r));



/**	Error message: TCP/IP protocol not available.
	@param	a	Application support structure.
*/
EXTERN void
dkapp_err_tcpip DK_PR((dk_app_t *a));



/**	Error message: No such file.
	@param	a	Application support structure.
	@param	n	File name.
*/
EXTERN void
dkapp_err_no_such_file DK_PR((dk_app_t *a, char *n));



/**	Error message: Pattern matches multiple files.
	@param	a	Application support structure.
	@param	p	File name pattern.
*/
EXTERN void
dkapp_err_multiple_files DK_PR((dk_app_t *a, char *p));



/**	Error message: Not a regular file.
	@param	app	Application support structure.
	@param	pat	File name.
*/
EXTERN void
dkapp_err_not_a_regular_file DK_PR((dk_app_t *app, char *pat));



/**	Informational message: File does not exist.
	@param	a	Application support structure.
	@param	n	File name.
*/
EXTERN void
dkapp_info_file_does_not_exist DK_PR((dk_app_t *a, char *n));



/**	Error message: Invalid file owner.
	@param	app	Application support structure.
	@param	pat	File name.
*/
EXTERN void
dkapp_err_invalid_owner DK_PR((dk_app_t *app, char *pat));



/**	Error message: No zlib support available.
	@param	a	Application support structure.
	@param	n	File name.
*/
EXTERN void
dkapp_err_no_zlib_support_for DK_PR((dk_app_t *a, char *n));



/**	Error message: No bzip2 support available.
	@param	a	Application support structure.
	@param	n	File name.
*/
EXTERN void
dkapp_err_no_bzlib_support_for DK_PR((dk_app_t *a, char *n));

#if defined(__cplusplus)
}
#endif


#if defined(EXTERN)
#undef EXTERN
#endif
#ifndef DKAPPR_C
#if !DK_HAVE_PROTOTYPES
#define EXTERN extern
#else
#define EXTERN /* nix */
#endif
#else
#define EXTERN /* nix */
#endif

#if defined(__cplusplus)
extern "C" {
#endif



/**	Convert string containing list of allowed PRNG types to key.
	@param	a	Application support structure.
	@param	s	Comma-separated list of allowed PRNG types,
	may include ``openssl'', ``random'', ``rand48'' and ``rand''
	or simply ``all''.
	@return	Numeric key indicating the allowed PRNG types.
*/
EXTERN int
dkapp_rand_types_from_string DK_PR((dk_app_t *a, char *s));



/**	Initialize random number generation seed PRNG.
	@param	a	Application support structure.
	@param	r	Key to indicate which PRNG types are allowed
			(or-combination of DK_RAND_TYPE_xxx).
	@return	Key to indicate which PRNG type is used (if any)
	or 0 (if no PRNG can be used and seeded).
*/
EXTERN int
dkapp_rand_begin DK_PR((dk_app_t *a, int r));



/**	Obtain random bytes.
	@param	a	Application support structure.
	@param	b	Buffer to receive the bytes.
	@param	s	Length of \a b in bytes.
	@return	The number of bytes received.
*/
EXTERN size_t
dkapp_rand_bytes DK_PR((dk_app_t *a, void *b, size_t s));



/**	Obtain random bytes for non-cryptographic purposes.
	@param	a	Application support structure.
	@param	b	Buffer to receive the bytes.
	@param	s	Length of \a b in bytes.
	@return	The number of bytes received.
*/
EXTERN size_t
dkapp_rand_bytes_non_crypto DK_PR((dk_app_t *a, void *b, size_t s));



/**	End random number generation, save seed and close PRNG.
	@param	a	Application support structure.
	@return	Flag to indicate success.
*/
EXTERN int
dkapp_rand_end DK_PR((dk_app_t *a));


/* ----- Functions for the dkappr module only (begin) ----- */

/**	Show text asking for random input.
	This function is used by the dkappr module if no
	source to seed the PRNG was found.
	@param	a	Application support structure.
*/
EXTERN void
dkapp_stderr_msg_need_random_input DK_PR((dk_app_t *a));

/**	Show text asking for more random input.
	@param	a	Application support structure.
*/
EXTERN void
dkapp_stderr_msg_need_more_random_input  DK_PR((dk_app_t *a));

/**	Show warning that keyboard echo was not turned off.
	@param	a	Application support structure.
*/
EXTERN void
dkapp_stderr_msg_echo_not_off  DK_PR((dk_app_t *a));

/**	Show error about invalid permissions to a random seed file.
	@param	app	Application support structure.
	@param	pat	File name.
*/
EXTERN void
dkapp_err_invalid_permissions  DK_PR((dk_app_t *app, char *pat));

/**	Show error message, seed source is not a device.
	@param	app	Application support structure.
	@param	pat	File name.
*/
EXTERN void
dkapp_err_not_a_device  DK_PR((dk_app_t *app, char *pat));

/**	Show debug message "attempting to seed OpenSSL PRNG".
	@param	a	Application support structure.
*/
EXTERN void
dkapp_debug_attempt_seed_openssl DK_PR((dk_app_t *a));

/**	Show debug message "attempting to seed random() prng".
	@param	a	Application support structure.
*/
EXTERN void
dkapp_debug_attempt_seed_random DK_PR((dk_app_t *a));

/**	Show debug message "attempting to seed rand48() prng".
	@param	a	Application support structure.
*/
EXTERN void
dkapp_debug_attempt_seed_rand48 DK_PR((dk_app_t *a));

/**	Show debug message "attempting to seed rand() PRNG".
	@param	a	Application support structure.
*/
EXTERN void
dkapp_debug_attempt_seed_rand DK_PR((dk_app_t *a));

/**	Show debug message "Failed to seed OpenSSL PRNG".
	@param	a	Application support structure.
*/
EXTERN void
dkapp_debug_failed_seed_openssl DK_PR((dk_app_t *a));

/**	Show debug message "Failed to seed random() PRNG".
	@param	a	Application support structure.
*/
EXTERN void
dkapp_debug_failed_seed_random DK_PR((dk_app_t *a));

/**	Show debug message "Failed to seed rand48() PRNG".
	@param	a	Application support structure.
*/
EXTERN void
dkapp_debug_failed_seed_rand48 DK_PR((dk_app_t *a));

/**	Show debug message "Failed to seed rand() PRNG".
	@param	a	Application support structure.
*/
EXTERN void
dkapp_debug_failed_seed_rand DK_PR((dk_app_t *a));

/**	Show debug message "OpenSSL PRNG not available".
	@param	a	Application support structure.
*/
EXTERN void
dkapp_debug_unavailable_openssl DK_PR((dk_app_t *a));

/**	Show debug message "random() PRNG not available".
	@param	a	Application support structure.
*/
EXTERN void
dkapp_debug_unavailable_random DK_PR((dk_app_t *a));

/**	Show debug message "rand48() PRNG not available".
	@param	a	Application support structure.
*/
EXTERN void
dkapp_debug_unavailable_rand48 DK_PR((dk_app_t *a));

/**	Show debug message "rand() PRNG not available".
	@param	a	Application support structure.
*/
EXTERN void
dkapp_debug_unavailable_rand DK_PR((dk_app_t *a));

/**	Show debug message "Attempting to seed from file".
	@param	a	Application support structure.
	@param	fn	File name.
*/
EXTERN void
dkapp_debug_attempt_seed_file DK_PR((dk_app_t *a, char *fn));

/**	Show debug message "Attempting to seed from EGD".
	@param	a	Application support structure.
	@param	fn	File name.
	
*/
EXTERN void
dkapp_debug_attempt_seed_egd DK_PR((dk_app_t *a, char *fn));

/**	Show debug message "attempting to seed from device".
	@param	a	Application support structure.
	@param	fn	File name.
*/
EXTERN void
dkapp_debug_attempt_seed_device DK_PR((dk_app_t *a, char *fn));

/**	Show debug message "attempting to seed from screen".
	@param	a	Application support structure.
*/
EXTERN void
dkapp_debug_attempt_seed_screen DK_PR((dk_app_t *a));

/**	Show debug message "attempting to seed from keyboard".
	@param	a	Application support structure.
*/
EXTERN void
dkapp_debug_attempt_seed_kbd DK_PR((dk_app_t *a));

/**	Show debug message "PRNG seeded successfully".
	@param	a	Application support structure.
*/
EXTERN void
dkapp_debug_prng_seeded_successfully DK_PR((dk_app_t *a));

/**	Show warning "PRNG not cryptographically strong".
	@param	a	Application support structure.
*/
EXTERN void
dkapp_warn_prng_not_crypto DK_PR((dk_app_t *a));

/**	Show error message "No PRNG found".
	@param	a	Application support structure.
*/
EXTERN void
dkapp_err_no_prng_found DK_PR((dk_app_t *a));

/**	Show error mssage "Application initialization failed".
 * 	@param	a	Application support structure.
*/
void
dkapp_err_init DK_PR((dk_app_t *a));

/**	Show warning "PRNG ... unknown".
	@param	a	Application support structure.
	@param	prng	Name of PRNG.
*/
EXTERN void
dkapp_warn_unknown_prng DK_PR((dk_app_t *a, char *prng));

/* ----- Functions for dkappr module only (end) ----- */


#if defined(__cplusplus)
};
#endif


/** Preferences: Exclude command line settings. */
#define DK_APP_PREF_EXCL_CMD	1

/** Preferences: Exclude programs own settings. */
#define DK_APP_PREF_EXCL_PROG	2

/** Preferences: Exclude users settings. */
#define DK_APP_PREF_EXCL_USER	4

/** Preferences: Exclude system settings. */
#define DK_APP_PREF_EXCL_SYSTEM	8

/** Logging: Do not behave as any of the programs below. */
#define DK_APP_IDE_NONE		0

/** Logging: Behave like gcc. */
#define DK_APP_IDE_GCC		1

/** Logging: Behave like MS VC. */
#define DK_APP_IDE_MSVC		2

/** Logging: Behave like Workshop compiler. */
#define DK_APP_IDE_WORKSHOP	3

/** Logging: Behave like tasm. */
#define DK_APP_IDE_TASM		4

/** File search: Take care of users language. */
#define DK_APP_PNC_LANGUAGE	2

/** File search: Take care of users region. */
#define DK_APP_PNC_REGION	1

/** File search: Take care of users encoding. */
#define DK_APP_PNC_ENCODING	4

/** Logging: No logging to standard output. */
#define DK_APP_LOG_NO_STDOUT	1

/** Logging: No logging to standard error output. */
#define DK_APP_LOG_NO_STDERR	2

/** Logging: No logging to standard output or standard error output. */
#define DK_APP_LOG_NO_STDIO (DK_APP_LOG_NO_STDOUT | DK_APP_LOG_NO_STDERR)

#endif
/* DK_APP_INCLUDED */


