/*
Copyright (c) 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	useraudi.h	Internal definitions for the useraud daemon.
 */

#ifndef USERAUDI_H_INCLUDED

/** Avoid multiple inclusions. */
#define USERAUDI_H_INCLUDED 1

#include <stdio.h>

#include <dk.h>

#include <stdio.h>
#if DK_HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if DK_HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if DK_HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#if DK_HAVE_SYS_UN_H
#include <sys/un.h>
#endif
#if DK_HAVE_STRING_H
#include <string.h>
#endif
#if DK_HAVE_CTYPE_H
#include <ctype.h>
#endif
#if DK_HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if DK_HAVE_UNISTD_H
#include <unistd.h>
#endif
#if DK_HAVE_SYSLOG_H
#include <syslog.h>
#endif
#if DK_HAVE_PWD_H
#include <pwd.h>
#endif
#if DK_HAVE_GRP_H
#include <grp.h>
#endif
#if DK_HAVE_SHADOW_H
#include <shadow.h>
#endif
#if DK_HAVE_SIGNAL_H
#include <signal.h>
#endif
#if DK_HAVE_STDARG_H
#include <stdarg.h>
#endif
#if DK_HAVE_TERMIOS_H
#include <termios.h>
#endif
#if DK_HAVE_SYS_TERMIOS_H
#include <sys/termios.h>
#endif
#if DK_HAVE_SYS_TTOLD_H
#include <sys/ttold.h>
#endif
#if DK_HAVE_WINCON_H
#include <wincon.h>
#endif
#if DK_HAVE_PROCESS_H
#include <process.h>
#endif
#if DK_HAVE_ERRNO_H
#include <errno.h>
#endif
#if DK_HAVE_SYSLOG
#include <syslog.h>
#endif
#if DK_HAVE_GDBM_H
#include <gdbm.h>
#endif
#if DK_HAVE_NDBM_H
#include <ndbm.h>
#endif
#if DK_HAVE_DB_H
#include <db.h>
#endif
#if DK_HAVE_OPENSSL_RAND_H
#include <openssl/rand.h>
#else
#error "OpenSSL include file \"openssl/rand.h\" not found!"
#endif
#if !(DK_HAVE_GDBM_H || DK_HAVE_NDBM_H || DK_HAVE_DB_H)
#error "Neither Berkeley DB nor GDBM nor NDBM available!"
#endif
#if DK_HAVE_CRYPT_H
#include <crypt.h>
#else
#error "Include file <crypt.h> not found!"
#endif
#if DK_HAVE_OPENSSL_MD5_H
#include <openssl/md5.h>
#else
#error "OpenSSL include file \"openssl/md5.h\" not found!"
#endif
#if DK_HAVE_OPENSSL_SHA_H
#include <openssl/sha.h>
#else
#error "OpenSSL include file \"openssl/sha.h\" not found!"
#endif
#if DK_HAVE_OPENSSL_RIPEMD_H
#include <openssl/ripemd.h>
#else
#error "OpenSSL include file \"openssl/ripemd.h\" not found!"
#endif

#include <dkmem.h>
#include <dksf.h>
#include <dklogc.h>
#include <dkstr.h>
#include <dkenc.h>
#include <dksto.h>
#include <dksignal.h>
#include <dksdbi.h>

#include "useraud.h"


/** Abbreviation for a UNIX domain socket address. */
typedef struct sockaddr_un SOUN;

/** Size of a UNIX domain socket address. */
#define SZSOUN sizeof(SOUN)

/** Abbreviation for an internet domain socket address. */
typedef struct sockaddr_in SOIN;

/** Size of an internet domain socket address. */
#define SZSOIN sizeof(SOIN)


#ifndef MAXPATHLEN
/** Maximum length of file name. */
#define MAXPATHLEN 1024
#endif



/**	Data for one allowed host address.
 */
typedef struct {
  unsigned long	ip;	/**< IP address. */
  unsigned long mask;	/**< Net mask. */
} UAPEER;


/**	Group entry.
 */
typedef struct {
  gid_t	g;	/**< Group ID. */
  char	*n;	/**< Group name. */
} UAG;



/**	User property.
 */
typedef struct {
  int	major;	/**< Property major number. */
  int	minor;	/**< Property minor number. */
  char	*value;	/**< Property value. */
} UAP;



/**	Data for one user.
 */
typedef struct {
  char			*user_name;	/**< Login name. */
  char			*pw_hash;	/**< Password hash. */
  char			*pg_name;	/**< Primary group name. */
  dk_storage_t		*s_g;		/**< Collection of groups. */
  dk_storage_iterator_t	*i_g;		/**< Iterator through groups. */
  dk_storage_t		*s_p;		/**< Collection of additional props. */
  dk_storage_iterator_t	*i_p;		/**< Iterator through props. */
  char			*gecos;		/**< User description. */
  uid_t			 uid;		/**< User ID. */
  gid_t			 primary_group;	/**< Primary group GID. */
  int			 ht;		/**< Hash type. */
  int			 st;		/**< Hash sub type. */
  int			 sl;		/**< Salt length. */
} UAU;


/**	API for communication between useraud and the backends.
 */
typedef struct {
  struct {
    int			c;	/**< Command (opcode). */
    int			f;	/**< Additional flags. */
    char		**t;	/**< Array of string pointers. */
    char		*v;	/**< Simple text. */
    char		*i;	/**< IP address used for cookie. */
  } a;		/**< Arguments. */
  struct {
    unsigned char	s;	/**< Flag: Success. */
    int			ec;	/**< Error code (if no success). */
    UAU			*u;	/**< User data. */
  } r;		/**< Results to return. */
} UAB_API;



/**	Configuration for the useraud daemon.
*/
typedef struct {
  char			*sockname;	/**< Name of socket to listen on. */
  char			*logname;	/**< Name of log file to write. */
  char			*dbname;	/**< Name of database file(s). */
  char			*seedname;	/**< Name of random seed file. */
  char			*run_as_user;	/**< User account to run. */
  char			*run_as_group;	/**< Group to run. */
  dk_storage_t		*s_be;		/**< Backends collection. */
  dk_storage_iterator_t	*i_be;		/**< Iterator through backends. */
  dk_storage_t		*s_allow;	/**< Allowed hosts collection. */
  dk_storage_iterator_t	*i_allow;	/**< Iterator through allowed hosts. */
  dk_sdbi_t		 sdbi;		/**< Database. */
  unsigned long		 ttl_challenge;	/**< Challenge time to live. */
  unsigned long		 ttl_cookie;	/**< Cookie time to live. */
  unsigned long		 ttl_salt;	/**< Faked user salt time to live. */
  unsigned long		 sec_cleanup;	/**< Cleanup interval in seconds. */
  unsigned long		 to_socket;	/**< Socket timeout. */
  time_t		 last_cleanup;	/**< Timestamp of last cleanup. */
  int			 ll_file;	/**< Log level for file. */
  int			 ll_syslog;	/**< Log level for syslog. */
  int			 hash_types;	/**< Allowed hash types. */
  int			 sock;		/**< Session socket. */
  int			 lgt_cookie;	/**< Maximum cookie length. */
  int			 username_test;	/**< Flag: Allow user name test. */
  unsigned char		 f_no_such;	/**< Flag: Report "no such user". */
} UAC;



/**	Backend function prototype.
 */
#if DK_HAVE_PROTOTYPES
typedef void ua_be_fct_t(UAC *, /* UAB */ void *, UAB_API *);
#else
typedef void ua_be_fct_t();
#endif


/**	Useraud backend.
 */
typedef struct {
  dk_storage_t		*s_ex;		/**< Collection of excluded users. */
  dk_storage_iterator_t	*i_ex;		/**< Iterator trough excl users. */
  void			*spec;		/**< Backend-specific data. */
  ua_be_fct_t		*f;		/**< Backend function. */
  unsigned		nb;		/**< Number of backend. */
  int			bet;		/**< Backend type. */
  int			ht;		/**< Hash type. */
  int			st;		/**< Sub type. */
  int			sl;		/**< Salt length for faked salt. */
  dk_storage_t		*s_a;		/**< Added properties collection. */
  dk_storage_iterator_t	*i_a;		/**< Added properties iterator. */
  dk_storage_t		*s_m;		/**< Mapped properties collection. */
  dk_storage_iterator_t	*i_m;		/**< mapped properties iterator. */
} UAB;


/**	Hash type.
 */
typedef struct {
  int		t;	/**< Hash type. */
  char		*n;	/**< Name. */
} HT;


/** @defgroup backends Backend types. */
/*@{*/
/** No backend defined yet. */
#define USERAUD_BE_UNKNOWN		0

/** System users backend. */
#define USERAUD_BE_SYS			1

/** LDAP backend (not yet implemented). */
#define USERAUD_BE_LDAP			2

/* +++++ Define further backends here. +++++ */

/*@}*/

/** @defgroup hashtypes Hash types. */
/*@{*/
/** No hash type defined yet. */
#define USERAUD_HASH_UNKNOWN		0

/* +++++ Add further hash types here and in uatcs.ctr, ht array. +++++ */

/** Maximum value used for hash types (powers of 2).
 *  When adding further hash types, increase this entry too.
 *  The strongest (most secure) hashing algorithms must have
 *  the largest numbers assigned.
 */ 
#define USERAUD_HASH_MAXVAL		128

/** SHA-512. */
#define USERAUD_HASH_SHA512		128

/** SHA-384. */
#define USERAUD_HASH_SHA384		64

/** SHA-256. */
#define USERAUD_HASH_SHA256		32

/** SHA-224. */
#define USERAUD_HASH_SHA224		16

/** RIPE MD 160. */
#define USERAUD_HASH_RIPEMD160		8

/** SHA-1. */
#define USERAUD_HASH_SHA1		4

/** MD5. */
#define USERAUD_HASH_MD5		2

/** Crypt. */
#define USERAUD_HASH_CRYPT		1

/** Crypt subtype DES. */
#define USERAUD_HASHSUB_CRYPT_DES	0

/** Crypt subtype bigcrypt. */
#define USERAUD_HASHSUB_CRYPT_BIG	1

/** Crypt subtype MD5. */
#define USERAUD_HASHSUB_CRYPT_MD5	2

/** Crypt subtype SHA-256. */
#define USERAUD_HASHSUB_CRYPT_SHA256	3

/** Crypt subtype SHA-512. */
#define USERAUD_HASHSUB_CRYPT_SHA512	4

/** Crypt subtype Blowfish (not on all distributions). */
#define USERAUD_HASHSUB_CRYPT_BLOWFISH	5
/*@}*/



#ifdef EXTERN
#undef EXTERN
#endif
#if DK_HAVE_PROTOTYPES
#define EXTERN /* nix */
#else
#if USERAUD_C
#define EXTERN /* nix */
#else
#define EXTERN extern
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif


/**	Set exit code for the useraud daemon.
 * 	@param	i	New exit code.
 */
EXTERN
void
ua_set_exit_code DK_PR((int i));


/**	Check whether we are in debug mode.
 * 	@return	1 for debugging, 0 for no debugging.
 */
EXTERN
int
ua_get_debug DK_PR((void));

#ifdef __cplusplus
};
#endif



#ifdef EXTERN
#undef EXTERN
#endif
#if DK_HAVE_PROTOTYPES
#define EXTERN /* nix */
#else
#if UABESYS_C
#define EXTERN /* nix */
#else
#define EXTERN extern
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif

/**	System backend function.
 * 	@param	uac	UAC structure.
 * 	@param	bevp	Pointer to backend.
 * 	@param	a	Pointer to API structure.
 */
EXTERN
void
uabesys DK_PR((UAC *uac, void *bevp, UAB_API *a));

#ifdef __cplusplus
};
#endif



#ifdef EXTERN
#undef EXTERN
#endif
#if DK_HAVE_PROTOTYPES
#define EXTERN /* nix */
#else
#if UACONF_C
#define EXTERN /* nix */
#else
#define EXTERN extern
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif

/**	Create configuration data structure, read configuration file.
 * 	@param	fn	File name for configuration file.
 * 	@param	tp	Type of program, the useraud daemon uses 1 here.
 * 	@return	Pointer to new structure on success, NULL on error.
 */
EXTERN
UAC *
uac_open DK_PR((char *fn, int tp));


/**	Close a configuration data structure, release memory.
 * 	@param	u	Structure to destroy.
 *	
 */
EXTERN
void
uac_close DK_PR((UAC *u));

#ifdef __cplusplus
};
#endif



#ifdef EXTERN
#undef EXTERN
#endif
#if DK_HAVE_PROTOTYPES
#define EXTERN /* nix */
#else
#if UATCS_C
#define EXTERN /* nix */
#else
#define EXTERN extern
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif

/**	Get default configuration file name.
 * 	@return	Default configuration file name.
 */
EXTERN
char *
uatcs_get_default_config_file_name DK_PR((void));

/**	Get default database name.
 * 	@return	Default database name.
 */
EXTERN
char *
uatcs_get_default_database_name DK_PR((void));

/**	Return default socket name.
 * 	@return	Default socket name.
 */
EXTERN
char *
uatcs_get_default_socket_name DK_PR((void));

/**	Return default log file name.
 * 	@return	Default log file name.
 */
EXTERN
char *
uatcs_get_default_log_file_name DK_PR((void));

/**	Return default random seed file name.
 * 	@return	Default random seed file name.
 */
EXTERN
char *
uatcs_get_default_random_seed DK_PR((void));

/**	Convert text containing IP address in dotted decimal notation.
 * 	@param	hn	String containing the IP address
 * 	@return	IP address in *host* byte order, use htonl() to convert
 * 	to network byte order.
 */
EXTERN
unsigned long
uatcs_dotted_string_to_ip DK_PR((char *hn));

/**	Apply one hashing step.
 * 	@param	uac	UAC structure.
 * 	@param	d	Destination (result) buffer.
 * 	@param	szd	Size of \a d in bytes.
 * 	@param	s	Input for this step (password for the first step).
 * 	@param	salt	Salt for hashing in text form.
 * 	@param	ht	Hash type.
 * 	@return	1 on success, 0 on error.
 */
EXTERN
int
uatcs_one_hash DK_PR((UAC *uac,char *d,size_t szd,char *s,char *salt,int ht));

/**	Correct salt length for crypt() hash salts.
 * 	@param	uac	UAC structure.
 * 	@param	st	Pointer to variable for sub-type.
 * 	@param	sl	Pointer to variable for salt length.
 * 	@param	hash	Password hash as retrieved from backend.
 */
EXTERN
void
uatcs_correct_crypt_st_sl DK_PR((UAC *uac, int *st, int *sl, char *hash));

/**	Find numeric representation of hash type.
 * 	@param	n	Hash type name.
 * 	@return	Numeric representation of the hash type on success, 0 on error.
 */
EXTERN
int
uatcs_hash_type DK_PR((char *n));

/**	Return or-combination of all hash types listed in \a n.
 * 	@param	n	Hash type names.
 * 	@return	Or-combination of all hash types listed in \a n.
 */
EXTERN
int
uatcs_all_hash_types DK_PR((char *n));

/**	Create salt for one hashing step.
 * 	@param	uac	UAC structure.
 * 	@param	d	Destination buffer.
 * 	@param	szd	Size of \a d in bytes.
 * 	@param	ht	Hash type.
 * 	@param	st	Hash sub-type, only used for crypt() hashes.
 */
EXTERN
int
uatcs_create_salt DK_PR((UAC *uac, char *d, size_t szd, int ht, int st));

/**	Get text representation of a hash type.
 * 	@param	t	Numeric representation of hash type.
 * 	@return	Name of hash type on success, NULL on error.
 */
EXTERN
char *
uatcs_get_hash_name DK_PR((int t));

/**	Get alpha-numeric character.
 * 	@param	i	Index.
 * 	@return	One character.
 */
EXTERN
char
uatcs_get_alnum DK_PR((unsigned i));

/**	Apply a challenge on a password to create the response.
 * 	@param	uac	UAC structure.
 * 	@param	ct	Challenge type (list of hash methods and salt lengths).
 * 	@param	ch	Challenge (the salts for the hashing steps).
 * 	@param	pw	Password to hash.
 * 	@param	o	Output buffer.
 * 	@param	szo	Size of \a o in bytes.
 * 	@param	rf	Flag: Do (1) or skip (0) the first hash step.
 * 	@return	1 on success, 0 on error.
 */
EXTERN
int
uatcs_apply_challenge DK_PR((UAC *uac, char *ct, char *ch, char *pw, char *o, size_t szo, int rf));


#ifdef __cplusplus
};
#endif



#ifdef EXTERN
#undef EXTERN
#endif
#if DK_HAVE_PROTOTYPES
#define EXTERN /* nix */
#else
#if UAB_C
#define EXTERN /* nix */
#else
#define EXTERN extern
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif

/**	Compare two lognames (used to build the sorted collection of
 * 	excluded users).
 * 	@param	l	Left name.
 * 	@param	r	Right name.
 * 	@param	cr	Comparison criteria (ignored).
 * 	@return	Comparison result.
 */
EXTERN
int
uab_compare_lognames DK_PR((void *l, void *r, int cr));

/**	Create new backend structure.
 * 	@param	uac	UAC structure.
 * 	@param	n	Index of the backend.
 * 	@param	t	Backend type.
 * 	@param	f	Backend function.
 * 	@param	fn	File name of configuration file.
 * 	@param	lineno	Line number in configuration file.
 */
EXTERN
UAB *
uab_new DK_PR((UAC *uac, unsigned n, int t, ua_be_fct_t *f, char *fn, unsigned long lineno));

/**	Delete a backend structure.
 * 	@param	uac	UAC structure.
 * 	@param	u	Backend structure to delete.
 */
EXTERN
void
uab_delete DK_PR((UAC *uac, UAB *u));

#ifdef __cplusplus
};
#endif



#ifdef EXTERN
#undef EXTERN
#endif
#if DK_HAVE_PROTOTYPES
#define EXTERN /* nix */
#else
#if UALOG_C
#define EXTERN /* nix */
#else
#define EXTERN extern
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif

/**	Set debug mode.
 * 	@param	f	Flag: Debug mode on (1) or off (0).
 */
EXTERN
void
ualog_set_debug DK_PR((int f));

/**	Write log message.
 * 	@param	u	UAC structure.
 * 	@param	ll	Log level (DK_LOG_LEVEL_xxx).
 * 	@param	msg	Array of texts to write.
 * 	@param	n	Number of texts in the array.
 */
EXTERN
void
ualog DK_PR((UAC *u, int ll, char **msg, int n));

/**	Log a simple message.
 * 	@param	u	UAC structure.
 * 	@param	ll	Log level.
 * 	@param	i	Index of message in the kw array in ualog.c.
 */
EXTERN
void
ualog_1 DK_PR((UAC *u, int ll, size_t i));

/**	Log a combined message consisting of a message start,
 * 	an additional text and a message end.
 * 	@param	u	UAC structure.
 * 	@param	ll	Log level.
 *	@param	i1	Index of the message start in the kw array.
 *	@param	i2	Index of the message end in the kw array.
 *	@param	s	Text between start and end (for example a file name).
 */
EXTERN
void
ualog_3 DK_PR((UAC *u, int ll, size_t i1, size_t i2, char *s));

/**	Write a simple log message with file name and line number.
 * 	This is used when processing the configuration file.
 * 	@param	u	UAC structure.
 * 	@param	ll	Log level.
 * 	@param	fn	File name to use for error position.
 * 	@param	l	Line number to use for error position.
 * 	@param	i	Index of message in th kw array.
 */
EXTERN
void
ualog_file_lineno_1 DK_PR((UAC *u,int ll,char *fn,unsigned long l,size_t i));

#ifdef __cplusplus
};
#endif



#ifdef EXTERN
#undef EXTERN
#endif
#if DK_HAVE_PROTOTYPES
#define EXTERN /* nix */
#else
#if UATOOL_C
#define EXTERN /* nix */
#else
#define EXTERN extern
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif

/**	Get modification time of a file. This is used to compare the last
 * 	modification time of the configuration file against the
 * 	time of the last configuration-read.
 * 	@param	fn	File name.
 * 	@return	Mofification timestamp.
 */
EXTERN
time_t
uat_modtime DK_PR((char *fn));

/**	Get a user password entry.
 * 	@param	n	User name.
 * 	@return	Password struct on success, NULL on error.
 */
EXTERN
struct passwd *
uat_getpwnam DK_PR((char *n));

/**	Get a user shadow entry.
 * 	@param	n	User name.
 * 	@return	Shadow struct on success, NULL on error.
 */
EXTERN
struct spwd *
uat_getspnam DK_PR((char *n));

/**	Get a group entry.
 * 	@param	gn	Group name.
 * 	@return	Group entry on success, NULL on error.
 */
EXTERN
struct group *
uat_getgrnam DK_PR((char *gn));

/**	Save PRNG seed to file.
 * 	@param	uac	UAC structure.
 */
EXTERN
void
uat_save_seed DK_PR((UAC *uac));

/**	Attempt to seed PRNG.
 * 	We try to seed the PRNG from different sources: a file name specified
 * 	in the configuration file, a file specified in the "RANDFILE"
 * 	environment variable, /dev/urandom, /dev/random, and EGD socket
 * 	specified in the "EGDSOCKET" environment variable and the default
 * 	EGD socket file name /var/run/egd-pool.
 * 	@param	uac	UAC structure.
 * 	@return	1 on success, 0 on error.
 */
EXTERN
int
uat_get_seed DK_PR((UAC *uac));

/**	Create parent directories for a file and set ownership and group.
 * 	@param	uac	UAC structure.
 * 	@param	fn	File name to create parents for.
 * 	@param	nu	User ID to use for new directories.
 * 	@param	ng	Group ID to use for new directories.
 * 	@return	1 on success, 0 on error.
 */
EXTERN
int
uat_create_parent DK_PR((UAC *uac, char *fn, uid_t nu, gid_t ng));


#ifdef __cplusplus
};
#endif




#ifdef EXTERN
#undef EXTERN
#endif
#if DK_HAVE_PROTOTYPES
#define EXTERN /* nix */
#else
#if UABAPI_C
#define EXTERN /* nix */
#else
#define EXTERN extern
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif


/**	Initialize UAB_API structure.
 * 	@param	a	Structure to initialize.
 */
EXTERN
void
uabapi_init DK_PR((UAB_API *a));

#ifdef __cplusplus
};
#endif




#ifdef EXTERN
#undef EXTERN
#endif
#if DK_HAVE_PROTOTYPES
#define EXTERN /* nix */
#else
#if UAU_C
#define EXTERN /* nix */
#else
#define EXTERN extern
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif

/**	Create user structure, initialize it.
 * 	The structure is created in dynamically allocated memory,
 * 	use uau_delete() to release the memory.
 * 	@param	n	User name.
 * 	@return	Pointer to new structure on success, NULL on error.
 */
EXTERN
UAU *
uau_new DK_PR((char *n));

/**	Release memory used for a user structure.
 * 	@param	u	User structure to destroy.
 */
EXTERN
void
uau_delete DK_PR((UAU *u));

/**	Create a group structure.
 * 	The structure is created in dynamically allocated memory, use
 * 	uau_group_delete() to destroy the structure and release the memory.
 * 	@param	name	Group name.
 * 	@param	gid	Group ID.
 * 	@return	Pointer to the new structure on success, NULL on error.
 */
EXTERN
UAG *
uau_group_new DK_PR((char *name, gid_t gid));

/**	Destory group structure and release memory.
 * 	@param	g	Structure to destroy.
 */
EXTERN
void
uau_group_delete DK_PR((UAG *g));

/**	Create property structure.
 * 	The structure is created in dynamically allocated memory, use
 * 	uau_property_delete() do destroy the structure and release the
 * 	memory.
 * 	@param	maj	Major property number.
 * 	@param	min	Minor property number.
 * 	@param	v	Text value.
 * 	@return	Pointer to the new structure on success, NULL on error.
 */
EXTERN
UAP *
uau_property_new DK_PR((int maj, int min, char *v));

/**	Destroy property structure, release memory.
 * 	@param	uap	Property structure to destroy.
 */
EXTERN
void
uau_property_delete DK_PR((UAP *uap));

#ifdef __cplusplus
};
#endif





#ifdef EXTERN
#undef EXTERN
#endif
#if DK_HAVE_PROTOTYPES
#define EXTERN /* nix */
#else
#if USERAUD_C
#define EXTERN /* nix */
#else
#define EXTERN extern
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif

/**	Check whether we can continue in the outer loop.
 * 	If there was a signal, we should not execute actions taking
 * 	a longer time.
 * 	@return	Flag: Can continue.
 */
EXTERN
int
useraud_get_outer_loop DK_PR((void));

#ifdef __cplusplus
};
#endif



#endif
/* USERAUD_H_INCLUDED */


