VSI-FAX C/C++ API (Application Program Interface) for users

0.	Contents:

	1.	Introduction

	2.	API design philosophy

	3.	Overview

	4.	Function details

		4.1	Server functions
		4.2	Phone-book functions
		4.3	Tag/List functions
		4.4	Utility functions
		4.5	TIFF file functions
		4.6	Memory functions

	5.	Tags

	6.	Sample code

	7.	The FAXAPI package

	8.	Using the VSI-FAX C/C++ API

1.	Introduction

	There has been many requests for a simple, easy-to-use,
	C/C++ API for integration.  We have never before provided
	such an API, because we didn't have a cohesive underlying
	structure to base one on, and there has never been consensus
	as to what should be in such an API.

	The advantages of such an API are many:

	1.	We can use it internally for easy integration with
		packages such as Lotus Notes, QAD, etc.

	2.	Users can easily use it for their own integration.

	3.	It provides an access to the VSI-FAX environment
		without resorting to "shelling out" to external
		programs.

	The intent of this API is as follows:

	1.	Provide an easy-to-use API for C/C++ users which
		is also usable in non-C environments (such as Visual Basic
		and Lotus-Script).

	2.	Provide most of the basic functionality available
		from our command-line clients.

	3.	Make the interface as portable as possible (both in OS
		and language interfaces).

	4.	Provide only basic functionality, with no UI (user interface).
		Providing any UI functionality would restrict the use of
		this API to that environment.

	The purpose of this document is to provide a preliminary
	specification of this API.  It is written from the standpoint
	of "man" pages.  It does not provide an overall documentation
	of how the server works.

2.	API design philosophy

	This API was designed with the following ideas in mind:

	1.	Minimize the data structures needed by the user.

		Although we cannot get away from introducing
		unique data structures in an API (consider all
		the various fields necessary to a fax envelope),
		we can minimize proliferation to the user.

		The solution we took here was to define only
		four data structures:

			V_CTX	an opaque pointer to an internal
				context object.  This object contains
				all user configuration information.

			V_SYS	an opaque pointer to an internal
				connection object.  This object contains
				all information pertaining to
				communication with the server.

			V_TAG	a pointer to a list of tags
				(name/value pairs).

			V_LIST	a list of pointers to V_TAG lists.

	2.	Provide a consistent interface for all function
		calls.

		The goal here is not only to present a simple API
		interface, but make it so that, if a user is used to
		using some of the calls, the other calls are similar
		enough to make use of them easy.

	3.	Use the existing paradigm of tags (name/value pairs)
		for all data to be consistent with the interfaces used
		by the command-line clients.

		The concept of tags in the form of name/value pairs
		is already in use in the following areas:

		1.	Tag files used by vfx, autosend files, and elsewhere.

		2.	Input and output mechanisms used by all database
			programs (vdbtool, vfxolog, vfxilog, etc.).

		3.	Command line arguments in many commands such as vfx,
			vfxolog, etc.

		Rather than create a new interface for the user to learn
		when using the API, the approach taken is to use the same
		type of data presentation.  This also has the advantage of
		easy translation between command-line usage and API usage.

	4.	Keep the interface as portable as possible.

		The intent here is to create an interface which is as usable
		as possible from a variety of environments.

		For example, although this API is designed to be called
		from C/C++ programs, the design allows all calls to be
		accessable from a Visual Basic environment.

	5.	Provide most of the functionality of our command-line
		client programs.

		The more that we can provide this functionality, the
		easier it will be for a user to switch between using
		command-line programs and this API.

		For example, using vfx to submit a list of tags will
		output on stdout the request-id of the fax job.  So
		the fax-submit API call returns to the user the
		request-id of the fax.

		Another example is that all client programs will display
		any pertinent errors to stderr.  So all API calls also
		return to the user the same error messages in a message buffer.

3.	Overview

	The API would consist of the following:

	1.	One header file:	vsi.h

	2.	Library files:

		Unix			libvsi.a

		Windows			libvsis.lib	(built /MT)
					libvsidlls.lib
					libvsidlls.dll
					libvsidlls.exp
					libvsid.lib	(build /MD)
					libvsidlld.lib
					libvsidlld.dll
					libvsidlld.exp

	The intent of this API is to provide a simple-to-use API
	which is tailored for an integrator who wants to submit a
	fax request.

	Facility is provided for querying resources that are on the server,
	if the user wants to use it, but its use is optional.
	Calls are also provided to modify, cancel, or get status for a
	particular request, but the basic integrator will probably only
	be interested initially in submitting a request.

	The functions in this API are as follows:

	Context calls

		VSI_Context_Load		Load a context object
		VSI_Context_Load_Cmdline	Load a context object
		VSI_Context_Free		Free a context object
		VSI_Context_Update		Update context info

	Server calls

		VSI_Server_Query		Query for running servers

		VSI_Server_Login_By_Context	Login to the server
		VSI_Server_Login		Login to the server
		VSI_Server_Logout		Logout from the server

		VSI_Server_Submit		Submit a taglist to be faxed
		VSI_Server_Submit_Tags		Submit a taglist to be faxed
		VSI_Server_Image		Submit a taglist to be imaged
		VSI_Server_Modify		Modify a fax request
		VSI_Server_Cancel		Cancel a fax request
		VSI_Server_Status		Status a fax request

		VSI_Server_Olog_Get		Get an OLOG entry
		VSI_Server_Olog_List		Get a list of OLOG entries
		VSI_Server_Olog_Delete		Delete an OLOG entry

		VSI_Server_Ilog_Get		Get an ILOG entry
		VSI_Server_Ilog_List		Get a list of ILOG entries

		VSI_Server_File_List		Get list of fax files
		VSI_Server_File_Retrieve	Get a received/archived fax file
		VSI_Server_File_Delete		Delete a received fax file
		VSI_Server_File_Route		Route a fax to a user

		VSI_Server_Resource		Get list of resource tags
		VSI_Server_Newmsg		Check for new messages
		VSI_Server_Newmsg_Get		Get new message list

		VSI_Server_Delegate_Set		Set a delegate entry
		VSI_Server_Delegate_List	Get a list of delegate entries

		VSI_Server_User_List		Get a list of users
		VSI_Server_User_Delegate_List	Get a list of user delegates

		VSI_Server_Profile_Get		Get a user record
		VSI_Server_Profile_Set		Set fields in a user record

		VSI_Server_Info			Get server state info

	Phone-book calls

		VSI_PB_Person_Get		Get    a person entry
		VSI_PB_Person_Add		Add    a person entry
		VSI_PB_Person_Del		Delete a person entry
		VSI_PB_Person_Upd		Update a person entry

		VSI_PB_Group_Get		Get    a group entry
		VSI_PB_Group_Add		Add    a group entry
		VSI_PB_Group_Del		Delete a group entry
		VSI_PB_Group_Upd		Update a group entry

		VSI_PB_Member_Get		Get    a member entry
		VSI_PB_Member_Add		Add    a member entry
		VSI_PB_Member_Del		Delete a member entry

		VSI_PB_Person_List		Get a list of person entries
		VSI_PB_Person_List_Extended	Get a qualified list of persons
		VSI_PB_Group_List		Get a list of group  entries

		VSI_PB_Types_List		Get a list of phone-books

	Tag-list utilities

		VSI_Tag_Free			Free a tag-list

		VSI_Tag_Add			Add a name/value to a tag-list
		VSI_Tag_Add_Comp		Add a name/value/op to a list
		VSI_Tag_Add_Str			Add a tag string to a tag-list

		VSI_Tag_Add_Ini_Sys		Add entries from system ini file
		VSI_Tag_Add_Ini_Usr		Add entries from user   ini file

		VSI_Tag_Count			Get # of entries in a tag-list

		VSI_Tag_Find_By_Index		Find an entry by index
		VSI_Tag_Find_By_Name		Find a tag entry by name
		VSI_Tag_Find_By_Data		Find a tag entry be value

		VSI_Tag_Get_Name_By_Index	Get a tag name by index
		VSI_Tag_Get_Name_By_Data	Get a tag name by data
		VSI_Tag_Get_Data_By_Index	Get a tag data by index
		VSI_Tag_Get_Data_By_Name	Get a tag data by name

		VSI_Tag_Load			Load a tag-list from a file
		VSI_Tag_Save			Save a tag-list to a file

		VSI_Tag_Copy			Make a copy of a tag-list
		VSI_Tag_Append			Append  a tag-list
		VSI_Tag_Prepend			Prepend a tag-list

		VSI_Tag_To_Str			Convert a tag-list to a string
		VSI_Tag_From_Str		Convert a string to a tag-list
		VSI_Tag_Fields			Get fields for a tag table type

		VSI_Tag_Next			Get next tag entry (macro)
		VSI_Tag_Prev			Get prev tag entry (macro)
		VSI_Tag_Name			Get tag name (macro)
		VSI_Tag_Data			Get tag data (macro)

	List utilities

		VSI_List_Free			Free a list
		VSI_List_Count			Get # of entries in a list
		VSI_List_Find_By_Index		Find a list entry by index
		VSI_List_Get_Tags		Get tag-list from a list entry
		VSI_List_Add			Add a tag-list to a list

		VSI_List_Next			Get next list entry (macro)
		VSI_List_Prev			Get prev list entry (macro)
		VSI_List_Tags			Get tags from list  (macro)

	Miscellaneous utilities

		VSI_Util_Time_To_Str		Convert a UNIX time to a string
		VSI_Util_Word_To_Str		Convert a word to a string
		VSI_Util_Bool_To_Str		Convert a boolean to a string

		VSI_Util_Str_To_Time		Convert a string to a UNIX time
		VSI_Util_Str_To_Word		Convert a string to a word
		VSI_Util_Str_To_Bool		Convert a string to a boolean

		VSI_Util_Version		Get VSI version & build number
		VSI_Util_Crypt			Encrypt a password (one-way)
		VSI_Util_Encrypt		Encrypt a string
		VSI_Util_Decrypt		Decrypt a string

		VSI_Util_Temp_Dir		Get location of temp directory
		VSI_Util_Home_Dir		Get location of home directory

		VSI_Time_Format_Str		Format a time string
		VSI_Time_Format_Val		Format a time value

		VSI_Opt_Get			Parse command line options
		VSI_Opt_Index			Get argv index of option
		VSI_Opt_Option			Get actual option letter
		VSI_Opt_Argstr			Get option argument

	TIFF file utilities

		VSI_TIFF_Header			Get header tag-list for a file
		VSI_TIFF_Copy			Copy a TIFF file
		VSI_TIFF_Merge			Merge TIFF files together

	Memory utilities

		VSI_Memory_Malloc		Allocate a chunk of memory
		VSI_Memory_Calloc		Allocate & clear n chunks
		VSI_Memory_Realloc		Re-allocate a chunk of memory
		VSI_Memory_Free			Free a chunk of memory
		VSI_Memory_Strdup		Allocate a copy of a string
		VSI_Memory_Count		Get count of allocated chunks
		VSI_Memory_Dump			Dump memory allocation chain

4.	Function details

	Notes:

	1.	Most functions take for a final argument a pointer to
		an error message buffer.  This may be NULL if no error
		messages are wanted.  If provided, it will always be
		set to either an empty string ("") or filled with a message.
		A message buffer is assumed to be at least V_MSG_LEN bytes long.

		Thus, if a user provides a msgbuf argument in a call,
		he can test for (*msgbuf == 0) or (strlen(msgbuf) == 0)
		to see if any error occurred.

		As much as possible, routines will return an error
		return value, such as (-1) for int routines and
		(NULL) for pointer routines.  But list manipulation
		routines that require returning a new list pointer
		can only indicate an error in the msgbuf string.

	2.	Server calls:

		1.	Calls to either VSI_Server_Login() or
			VSI_Server_Login_By_Context() when already
			logged in will result in another login session
			being created (and a new V_SYS pointer being
			returned).  This is probably not what you want.

			Note that any logins via this API are treated by
			the server are subject to the same licensing issues
			as any other client.

		2.	Calls to VSI_Server_Logout() when already
			logged-out will probably result in a core-dump,
			since the V_SYS pointer passed as the argument
			was actually freed in the initial logout call
			and now points to an invalid memory location.

			A call to VSI_Server_Logout() with a NULL V_SYS
			pointer will be ignored.

		3.	Calls to other VSI_Server_*() routines when
			not logged-in (i.e., with a NULL V_SYS pointer)
			will automatically log the user in using the
			default username & hostname and log the user out
			before returning.

			This enables a user to make a specific request
			(such as submitting a fax) with only one server
			call.

			This is intended for only the most simple API
			usage.  Any API use requiring more than one call
			to the server should log-in first, do all the work,
			and then log-out.

		4.	Note that the phone-book server calls may
			reference the user's local phone-book and thus
			not make any calls to the server (except that a
			login/logout may still be required).

4.1	Server calls

	These functions involve communication with the server.  They
	may be complex functions, in that one call may result in
	more than one communication with the server and/or may involve
	one or more calls to lower-level API routines.

	Summary is as follows:

	V_CTX *
	VSI_Context_Load		(int argc,
					 char **argv,
					 const char *pgmname,
					 char *msgbuf)

	V_CTX *
	VSI_Context_Load_Cmdline	(const char *cmdline,
					 const char *pgmname,
					 char *msgbuf)

	int
	VSI_Context_Free		(V_CTX *vctx,
					 char *msgbuf)

	int
	VSI_Context_Update		(V_CTX *vctx,
					 const char *clientid,
					 const char *passwd,
					 const char *hostname,
					 char *msgbuf)

	V_TAG *
	VSI_Server_Query		(int timeout,
					 const char *netmask,
					 char *msgbuf)

	V_SYS *
	VSI_Server_Login_By_Context	(V_CTX *vctx,
					 char *msgbuf)

	V_SYS *
	VSI_Server_Login		(const char *clientid,
					 const char *passwd,
					 const char *hostname,
					 const char *pgmname,
					 char *msgbuf)

	int
	VSI_Server_Logout		(V_SYS *vptr,
					 char *msgbuf)

	int
	VSI_Server_Submit		(V_SYS *vptr,
					 char *reqid_buf,
					 const V_TAG *tags,
					 char *msgbuf)

	int
	VSI_Server_Image		(V_SYS *vptr,
					 const char *filename,
					 const V_TAG *tags,
					 char *msgbuf)

	int
	VSI_Server_Modify		(V_SYS *vptr,
					 const char *reqid,
					 const V_TAG *tags,
					 char *msgbuf)

	int
	VSI_Server_Cancel		(V_SYS *vptr,
					 const char *reqid,
					 char *msgbuf)

	V_TAG *
	VSI_Server_Status		(V_SYS *vptr,
					 const char *reqid,
					 char *msgbuf)

	V_TAG *
	VSI_Server_Olog_Get		(V_SYS *vptr,
					 char *reqid_buf,
					 int grp,
					 int dbcmd,
					 char *msgbuf)

	V_LIST *
	VSI_Server_Olog_List		(V_SYS *vptr,
					 char *reqid_buf,
					 int grp,
					 int dbcmd,
					 V_TAG *tags,
					 int detail,
					 int all,
					 int num,
					 char *msgbuf)

	int
	VSI_Server_Olog_Delete		(V_SYS *vptr,
					 const char *reqid,
					 char *msgbuf)

	V_TAG *
	VSI_Server_Ilog_Get		(V_SYS *vptr,
					 char *reqid_buf,
					 int dbcmd,
					 char *msgbuf)

	V_LIST *
	VSI_Server_Ilog_List		(V_SYS *vptr,
					 char *reqid_buf,
					 int dbcmd,
					 V_TAG *tags,
					 int num,
					 char *msgbuf)

	V_LIST *
	VSI_Server_File_List		(V_SYS *vptr,
					 const char *clientid,
					 char *msgbuf)

	int
	VSI_Server_File_Retrieve	(V_SYS *vptr,
					 const char *clientid,
					 const char *filename,
					 const char *path,
					 int archive,
					 char *msgbuf)

	int
	VSI_Server_File_Delete		(V_SYS *vptr,
					 const char *clientid,
					 const char *filename,
					 char *msgbuf)

	int
	VSI_Server_File_Route		(V_SYS *vptr,
					 const char *clientid,
					 const char *filename,
					 const char *to_id,
					 const char *comment,
					 const char *costcode,
					 int forward,
					 char *msgbuf)

	V_TAG *
	VSI_Server_Resource		(V_SYS *vptr,
					 const char *res_type,
					 char *msgbuf)

	time_t
	VSI_Server_Newmsg		(V_SYS *vptr,
					 const char *clientid,
					 int msgtype,
					 time_t since,
					 char *msgbuf)

	V_LIST *
	VSI_Server_Newmsg_Get		(V_SYS *vptr,
					 const char *clientid,
					 int msgtype,
					 time_t since,
					 char *msgbuf)

	int
	VSI_Server_Delegate_Set		(V_SYS *vptr,
					 const char *clientid,
					 int addmask,
					 int delmask,
					 char *msgbuf)

	V_TAG *
	VSI_Server_Delegate_List	(V_SYS *vptr,
					 int mask,
					 char *msgbuf)

	V_TAG *
	VSI_Server_User_List		(V_SYS *vptr,
					 int all,
					 char *msgbuf)

	V_LIST *
	VSI_Server_User_Delegate_List	(V_SYS *vptr,
					 char *msgbuf)

	V_TAG *
	VSI_Server_Profile_Get		(V_SYS *vptr,
					 char *msgbuf)

	int
	VSI_Server_Profile_Set		(V_SYS *vptr,
					 const V_TAG *tags,
					 char *msgbuf)

	V_TAG *
	VSI_Server_Info			(V_SYS *vptr,
					 char *msgbuf)

4.1.1	Load a context object

	This call loads a user's "context", which describes the user's
	environment used in communication with the server.

	This call will process the following:

	1.	The following command-line options, if found:

		-U clientid		clientid to login with
		-H hostname		hostname of the server to connect to
		-Z options		list of debug options to use

		Debug (-Z) options are in form "name=value[;...]".
		More than one -Z option may be present; they are all
		collected together.  Possible entries are:

			userid		clientid to login as
			username	full name of user
			password	password to login with
			language	language to use
			locale		locale to use   (not yet implemented)
			timezone	timezone to use (not yet implemented)
			datefmt		date format to use
			timefmt		time format to use

			workdir		full path of temp directory to use

			hostname	hostname of server to connect to
			xmlport		port to use (must match server's port)
			maxbuf		max size of data block to write
			timeout		time (in secs) to wait for reply

			dbgmem		debug memory usage
			dbgreads	debug TCP reads
			dbgsends	debug TCP sends
			savecmds	save cmd/rsp objects

			stdin		specify file to use for stdin
			stdout		specify file to use for stdout
			stderr		specify file to use for stderr

		Any unrecognized debug option is ignored.  Note that
		entry names are case-insensitive.

	2.	Any LOGIN entries in the "vsifax.ini" file in both
		the VSI system directory and the user's VSI home directory.
		The VSI home directory for <user> is found as follows:

			Unix		$HOME/.vsifax

			NT		%windir%\Profiles\<user>\
						Application Data\VSI

			WIN2K/XP	%APPDATA%\VSI
					or
					%HOMEDRIVE%\Documents and Settings\
						<user>\Application Data\VSI

			WIN9X		%windir%\Application Data\VSI

		Note that the default VSI home directory may be overridden
		by the VSIHOME environment variable, and entries in a user's
		home directory override any entries in the system directory.

		Ini file entries processed are:

			userid		clientid to login as
			username	full name of user
			password	encrypted password to use
			language	language to use
			locale		locale to use   (not yet implemented)
			timezone	timezone to use (not yet implemented)
			date-format	date format to use
			time-format	time format to use

			workdir		full path of temp directory to use

			hostname	name of server to connect to
			xmlport		port to use (must match server's port)
			maxbufsize	max size of data block to write
			timeout		time (in secs) to wait for a reply
			
			debug-memory	debug memory usage
			debug-reads	debug TCP reads
			debug-sends	debug TCP sends
			save-cmds	save cmd/rsp objects

		Note that entry names are case-insensitive and any dashes (-)
		are ignored.

	3.	Any VSI* environment variables found. These are:

			VSIUSER		clientid to login as
			VSINAME		full name of user
			VSILANG		language to use
			VSILOCALE	locale to use   (not yet implemented)
			VSITZ		timezone to use (not yet implemented)
			VSIDATE		default date format
			VSITIME		default time format
			VSIHOST		name of server to connect to
			VSIOPTS		list of debug options
			VSITEMP		full path of temp directory to use
			VSIHOME		full path of user's VSI home directory

	By using this call, client programs can present a consistent
	command-line syntax for users.  Note that all VFS programs
	use this syntax.

	V_CTX *
	VSI_Context_Load		(int argc,
					 char **argv,
					 const char *pgmname,
					 char *msgbuf)

	args:
		argc			argument count from main()
					This may be 0, indicating no argv
					vector is used.

		argv			argument vector from main()
					This may be NULL (in which case
					argc should be 0).

		pgmname			name of program (for logging purposes).
					If NULL, default will be the name of
					the program being run (from argv[0]
					if an argv was provided).

		msgbuf			error message buffer

	returns:
		pointer			pointer to a V_CTX struct
		NULL			error (message in msgbuf)

4.1.1	Load a context object using a cmdline string

	This call behaves the same as VSI_Context_Load(), except the
	cmd-line arguments to be processed exist in a string, rather
	than in a argv vector.

	V_CTX *
	VSI_Context_Load_Cmdline	(const char *cmdline,
					 const char *pgmname,
					 char *msgbuf)

	args:
		cmdline			a string containing the cmdline to
					be parsed.  Note that any arguments
					containg white-space must be enclosed
					in quotes.

		pgmname			name of program (for logging purposes)
					If NULL, it will be assumed that
					the first sub-string in the cmdline
					is the program name.

		msgbuf			error message buffer

	returns:
		pointer			pointer to a V_CTX struct
		NULL			error (message in msgbuf)

4.1.2	Free a context object

	int
	VSI_Context_Free		(V_CTX *vctx,
					 char *msgbuf)

	args:
		vctx			pointer from VSI_Context_Load()

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

4.1.3	Update information in a context object

	int
	VSI_Context_Update		(V_CTX *vctx,
					 const char *clientid,
					 const char *passwd,
					 const char *hostname,
					 char *msgbuf)

	args:
		vctx			pointer from VSI_Context_Load()

		clientid		optional clientid to set

		passwd			optional password to set

		hostname		optional hostname to set

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error

4.1.3	Query for running servers

	This call will query the network looking for any servers
	which are running.  It can only detect servers running on
	the local network.

	V_TAG *
	VSI_Server_Query		(int timeout,
					 const char *netmask,
					 char *msgbuf)

	args:
		timeout			timeout in seconds to wait

		netmask			broadcast netmask to use or NULL

		msgbuf			error message buffer

	returns:
		pointer			pointer to a list of servers
		NULL			error or no servers running

4.1.4	Login using a context object

	V_SYS *
	VSI_Server_Login_By_Context	(V_CTX *vctx,
					 char *msgbuf)

	args:
		vctx			pointer from VSI_Context_Load()

		msgbuf			error message buffer

	returns:
		pointer			pointer to a V_SYS struct
		NULL			error (message in msgbuf)

4.1.5	Login to server

	V_SYS *
	VSI_Server_Login		(const char *clientid,
					 const char *passwd,
					 const char *hostname,
					 const char *pgmname,
					 char *msgbuf)

	args:
		clientid		client-id
					(may be NULL for default)

		passwd			password
					If NULL, a VFS login will be done,
					otherwise the password is used for
					the login.  Note that this string
					must be encrypted via a call to
					VSI_Util_Crypt().

		hostname		host to connect to
					(may be NULL for default)

		pgmname			name of program (for logging purposes)
					If NULL, default will be "<VSI-API>".

		msgbuf			error message buffer

	returns:
		pointer			pointer to a V_SYS struct
		NULL			error (message in msgbuf)

4.1.6	Logout from server

	int
	VSI_Server_Logout		(V_SYS *vptr,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		msgbuf			error message buffer

	returns:
		0			logout OK
		-1			error (message in msgbuf)

	notes:
		This call will free the object pointed to by "vptr",
		and that this pointer must NOT be referenced
		after this call or a memory exception will probably
		result.

		Calling this routine with "vptr" set to NULL will result
		in nothing being done, but is not considered an error.

4.1.7	Submit a taglist to be faxed

	int
	VSI_Server_Submit		(V_SYS *vptr,
					 char *reqid_buf,
					 const V_TAG *tags,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		reqid_buf		request-id buffer

		list			pointer to list of V_TAG structs

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

4.1.8	Submit a taglist to be faxed (using a variable argument list)

	int
	VSI_Server_Submit_Tags		(V_SYS *vptr,
					 char *reqid_buf,
					 const char *tag_name,
					 const char *tag_data,
					 ...,
					 0,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		reqid_buf		request-id buffer

		tag_name		pointer to next tag-name or NULL
					to indicate the end of the tags.

		tag_data		pointer to tag value

					It is expected that there will be
					multiple name/data pairs, with a
					NULL argument after the last to
					the end of the list.

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

	example:

	{
		char	reqid_buf[V_TAG_DATALEN];
		char	msgbuf[V_MSG_LEN];
		int	rc;
	
		rc = VSI_Server_Submit_Tags(vptr,
			reqid_buf,
			V_TAG_ENV_TOFNUM,	"800-555-1212",
			V_TAG_ENV_FILELCL,	"faxtext.txt",
			V_TAG_ENV_COVERPAGE,	"classic",
			V_TAG_ENV_SUBJECT,	"this is a test",
			0,
			msgbuf);

		...
	}
			

4.1.9	Submit a taglist to be imaged

	This call is used to validate that a tag-list can be imaged and
	has no errors, and the resultant TIFF file can be displayed for
	a user's validation.  The TIFF file can then then be submitted
	as a whole for sending, if desired.

	int
	VSI_Server_Image		(V_SYS *vptr,
					 const char *filename,
					 const V_TAG *tags,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		filename		pathname of imaged file

		list			pointer to list of V_TAG structs

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

4.1.10	Modify a fax request

	int
	VSI_Server_Modify		(V_SYS *vptr,
					 const char *reqid,
					 const V_TAG *tags,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		reqid			request-id buffer

		list			pointer to list of V_TAG structs
					Note that if no tags are given to
					be changed, the call is assumed
					to be a call to "try" the job now.

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

	notes:
		If no tags are specified, then this call is assumed to
		be a "try", i.e., the job is then tried to be sent
		immediately.  If the job has been expired, then it is
		"unexpired" and is then treated as a regular job.  "Trying"
		an expired group job will result in trying to send again all
		group members which failed previously.

4.1.11	Cancel a fax request

	int
	VSI_Server_Cancel		(V_SYS *vptr,
					 const char *reqid,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		reqid			string containing request-id

		msgbuf			error message buffer

	returns:
		0			successful cancel
		-1			error (message in msgbuf)

	notes:
		Cancelling a group job will result in cancelling all members
		in the group which have not yet been sent.

4.1.12	Get status of a request

	V_TAG *
	VSI_Server_Status		(V_SYS *vptr,
					 const char *reqid,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		reqid			string containing request-id

		msgbuf			error message buffer

	returns:
		pointer			pointer to list of V_TAG structs
		NULL			error (message in msgbuf)

	notes:
		This call is equivalent to

		VSI_Server_Olog_Get(vptr, reqid, FALSE, V_DBCMD_EQUAL, msgbuf)

		except that, since the request-id is not modified, it
		takes a const reqid.

4.1.13	Get an OLOG entry

	V_TAG *
	VSI_Server_Olog_Get		(V_SYS *vptr,
					 char *reqid_buf,
					 int grp,
					 int dbcmd,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		reqid_buf		input:  reqid to get
					output: reqid of record read

		grp			TRUE  if group entry
					FALSE if reg entry

		dbcmd			database cmd
					V_DBCMD_NEXT	read next  entry
					V_DBCMD_PREV	read prev  entry
					V_DBCMD_FIRST	read first entry
					V_DBCMD_LAST	read last  entry
					V_DBCMD_EQUAL	read this  entry
					V_DBCMD_GTEQ	read next  entry >=

		msgbuf			error message buffer

	returns:
		pointer			pointer to list of V_TAG structs
		NULL			error (message in msgbuf)

4.1.14	Get a list of OLOG entries

	V_LIST *
	VSI_Server_Olog_List		(V_SYS *vptr,
					 char *reqid_buf,
					 int grp,
					 int dbcmd,
					 V_TAG *tags,
					 int detail,
					 int all,
					 int num,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		reqid_buf		input:  reqid to get
					output: reqid of last record read

		grp			TRUE  if group entry
					FALSE if reg entry

		dbcmd			database cmd
					V_DBCMD_NEXT	read next  entry
					V_DBCMD_PREV	read prev  entry
					V_DBCMD_FIRST	read first entry
					V_DBCMD_LAST	read last  entry
					V_DBCMD_EQUAL	read this  entry
					V_DBCMD_GTEQ	read next  entry >=

		tags			an optional list of tags to match

		detail			TRUE  for attempt records
					FALSE for master records only

		all			TRUE  for all records
					FALSE for non-deleted records only

		num			max number to get
					(0 for all)

		msgbuf			error message buffer

	returns:
		pointer			pointer to list of V_LIST structs
		NULL			error (message in msgbuf)

	notes:
		If a user does not have ADMIN privilege, then only fax
		requests for that user are reported.  An ADMIN user will
		have all entries reported, unless the call is limited via the
		"tags" list with a "cli=xxxx" entry.

4.1.15	Delete an OLOG entry

	int
	VSI_Server_Olog_Delete		(V_SYS *vptr,
					 const char *reqid,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		reqid			reqid to get to delete

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

	notes:
		This call does not actually delete the fax request from the
		OLOG database, but just notes the request as not being
		reported in subsequent OLOG requests.

4.1.16	Get an ILOG entry

	V_TAG *
	VSI_Server_Ilog_Get		(V_SYS *vptr,
					 char *reqid_buf,
					 int dbcmd,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		reqid_buf		input:  reqid to get
					output: reqid of record read

		dbcmd			database cmd
					V_DBCMD_NEXT	read next  entry
					V_DBCMD_PREV	read prev  entry
					V_DBCMD_FIRST	read first entry
					V_DBCMD_LAST	read last  entry
					V_DBCMD_EQUAL	read this  entry
					V_DBCMD_GTEQ	read next  entry >=

		msgbuf			error message buffer

	returns:
		pointer			pointer to list of V_TAG structs
		NULL			error (message in msgbuf)

	notes:
		If a user does not have ADMIN privilege, then only fax
		requests for that user are reported.  An ADMIN user will
		have all entries reported, unless the call is limited via the
		"tags" list with a "cli=xxxx" entry.

4.1.17	Get a list of ILOG entries

	V_LIST *
	VSI_Server_Ilog_List		(V_SYS *vptr,
					 char *reqid_buf,
					 int dbcmd,
					 V_TAG *tags,
					 int num,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		reqid_buf		input:  reqid to get
					output: reqid of last record read

		dbcmd			database cmd
					V_DBCMD_NEXT	read next  entry
					V_DBCMD_PREV	read prev  entry
					V_DBCMD_FIRST	read first entry
					V_DBCMD_LAST	read last  entry
					V_DBCMD_EQUAL	read this  entry
					V_DBCMD_GTEQ	read next  entry >=

		tags			optional list of tags to match

		num			max number of records to read
					(0 for all)

		msgbuf			error message buffer

	returns:
		pointer			pointer to list of V_LIST structs
		NULL			error (message in msgbuf)

	notes:
		If a user does not have ADMIN privilege, then only fax
		requests for that user are reported.  An ADMIN user will
		have all entries reported, unless the call is limited via the
		"tags" list with a "cli=xxxx" entry.

4.1.18	Get a list of fax files

	V_LIST *
	VSI_Server_File_List		(V_SYS *vptr,
					 const char *clientid,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		clientid		The ID of the user to fetch the list
					for. If NULL, the current userid is
					used.

		msgbuf			error message buffer

	returns:
		pointer			pointer to list of V_TAG entries
		NULL			error (message in msgbuf)

	notes:
		If the user does not have ADMIN privilege, then requesting
		a list of faxes for a user is subject to permissions found
		in the "delegates" database.

4.1.19	Get a received/routed fax file

	int
	VSI_Server_File_Retrieve	(V_SYS *vptr,
					 const char *clientid,
					 const char *filename,
					 const char *path,
					 int archive,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		clientid		The ID of the user to fetch the file
					for. If NULL, the current userid is
					used.

		filename		filename of the fax file to get
					This is usually gotten from a
					call to VSI_Server_Resource() for
					a list of fax files.

		path			pathname to store the fax file in

		archive			TRUE  to retrieve an archive file
					FALSE to retrieve a received file

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

	notes:
		If the user does not have ADMIN privilege, then requesting
		a fax for a user is subject to permissions found in the
		"delegates" database.

4.1.20	Delete a received/routed fax file

	int
	VSI_Server_File_Delete		(V_SYS *vptr,
					 const char *clientid,
					 const char *filename,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		clientid		The ID of the user to fetch the file
					for. If NULL, the current userid is
					used.

		filename		filename of the fax file to get
					This is usually gotten from a
					call to VSI_Server_Resource() for
					a list of fax files.

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

	notes:
		If the user does not have ADMIN privilege, then requesting
		a fax for a user is subject to permissions found in the
		"delegates" database.

4.1.21	Route a fax file to a user

	int
	VSI_Server_File_Route		(V_SYS *vptr,
					 const char *clientid,
					 const char *filename,
					 const char *to_id,
					 const char *comment,
					 const char *costcode,
					 int forward,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		clientid		The ID of the user owning the file.
					If NULL, the current userid is used.

		filename		filename of the fax file to route.
					This is usually gotten from a
					call to VSI_Server_Resource() for
					a list of fax files.

		to_id			The ID of the user to route to.
					This is usually gotten from a
					call to VSI_Server_Resource() for
					a list of routes.

		comment			an optional comment string

		costcode		an optional costcode string

		forward			TRUE  to forward the file
					FALSE to copy the file

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

4.1.22	Get resource list

	V_TAG *
	VSI_Server_Resource		(V_SYS *vptr,
					 const char *res_type,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		res_type		resource type to get
					Available types are:
						"covers"
						"envtags"
						"queues"
						"priorities"
						"retries"
						"groups"
						"resolutions"
						"pglengths"
						"filetypes"
						"folders"
						"srvfiles"
						"forms"
						"lnps"
						"gnps"
						"tnps"
						"routes"
						"faxfiles"
						"arcfiles"
						"gdrs"

		msgbuf			error message buffer

	returns:
		pointer			pointer to a list of V_TAG structs
		NULL			error or no such resource

	notes:
		If msgbuf is empty, then no error occurred;
		this indicates no such resources of the specified type exist.
		A non-empty msgbuf string indicates an error.

		If a NULL msgbuf parameter is passed, then there is no
		way to distinguish between an empty list and an error
		condition.

4.1.23	Check for new messages

	time_t
	VSI_Server_Newmsg		(V_SYS *vptr,
					 const char *clientid,
					 int msgtype,
					 time_t since,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		clientid		ID of person to query for

		msgtype			message type:
						V_MSG_ROUTE	new routes
						V_MSG_RCVFAX	new rcvd faxes
						V_MSG_SNTFAX	new sent faxes

		since			time of last message or 0 for all msgs

		msgbuf			error message buffer

	returns:
		> 0			time of last message
		0			no new messages
		-1			error

4.1.24	Get list of new messages

	V_LIST *
	VSI_Server_Newmsg_Get		(V_SYS *vptr,
					 const char *clientid,
					 int msgtype,
					 time_t since,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		clientid		ID of person to query for

		msgtype			message type:
						V_MSG_ROUTE	new routes
						V_MSG_RCVFAX	new rcvd faxes
						V_MSG_SNTFAX	new sent faxes

		since			time of last message or 0 for all msgs

		msgbuf			error message buffer

	returns:
		pointer			pointer to list of messages
		NULL			error

4.1.25	Set a delegate entry

	int
	VSI_Server_Delegate_Set		(V_SYS *vptr,
					 const char *clientid,
					 int addmask,
					 int delmask,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		clientid		ID of person to add

		addmask			bitmask of auth bits to add
					V_AUTH_LOGIN	user can login
					V_AUTH_RECVFAX	user can read faxes
					V_AUTH_COVERS	user can access covers
					V_AUTH_PB	user can access PB
					V_AUTH_FILES	user can access files

		delmask			bitmask of auth bits to delete

		msgbuf			error message buffer

	returns:
		0			no error
		-1			error (message in msgbuf)

4.1.26	Get a list of delegate entries

	V_TAG *
	VSI_Server_Delegate_List	(V_SYS *vptr,
					 int mask,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		mask			bitmask of auth bits to look for

		msgbuf			error message buffer

	returns:
		pointer			pointer to list of V_TAG structs
		NULL			error (message in msgbuf)

4.1.27	Get a list of users

	V_TAG *
	VSI_Server_User_List		(V_SYS *vptr,
					 int all,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		all			TRUE to get all users

		msgbuf			error message buffer

	returns:
		pointer			pointer to tag list of users
		NULL			error

4.1.28	Get a list of user delegates

	V_LIST *
	VSI_Server_User_Delegate_List	(V_SYS *vptr,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		msgbuf			error message buffer

	returns:
		pointer			pointer to tag list of users
		NULL			error

4.1.29	Get a user profile

	V_TAG *
	VSI_Server_Profile_Get		(V_SYS *vptr,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		msgbuf			error message buffer

	returns:
		pointer			pointer to a list of V_TAG structs
		NULL			error

4.1.30	Set fields in a user profile

	int
	VSI_Server_Profile_Set		(V_SYS *vptr,
					 const V_TAG *tags,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		list			list of user tags to change

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

	notes:
		Setting a field in a user record has the side effect of
		breaking the user profile inheritance mechanism for that field.
		So only fields that need to be changed should be passed in.

		The following user fields are administration related and cannot
		be set by this function call:
			lic		Licensed
			utp		User type
			umd		User mode
			mkp		Make child a profile
			isp		This is a profile
			inh		Inheritance mode
			pid		Parent id
			ued		User can edit profile
			ifd		Inheritable fields
			ufd		User editable fields
			prd		Use parent profile's directory list
			dir		Available directory list

4.1.31	Get server state information

	V_TAG *
	VSI_Server_Info			(V_SYS *vptr,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		msgbuf			error message buffer

	returns:
		pointer			pointer to a list of V_TAG structs
		NULL			error


4.2	Phone-book routines

	These routines may operate on either the local or the
	system phone-book, and thus may result in communication
	with the server or not.

	A VSI phone-book consists of three databases:
	
		person		database of all person entries
		group		database of all group entries
		member		database of person-group associations

	This provides the ability for a person to belong to more than
	one group, and when the data for a person is updated, that
	updated information is presented for all groups.

	The pbtype argument specifies the phone-book type.
	Values are:
		V_PB_TYPE_LCL ("lcl")		local  phone-book
		V_PB_TYPE_USR ("usr")		client phone-book
		V_PB_TYPE_SYS ("sys")		system phone-book
	If pbtype is NULL, the default value is V_PB_TYPE_USR.

	A phone-boook type may also be qualified by a group.  Thus,
	if you have the group "sales" in your client phone-book,
	then specifying the phone-book type as "usr-sales" will
	restrict all operations to that group in that phone-book.

	The pbtype of "xxx-all" is the same as "xxx"; that is, all
	persons are processed, and any group membership is ignored.

	Person functions:

	V_TAG *
	VSI_Server_Person_Get		(V_SYS *vptr,
					 const char *pbtype,
					 char *key,
					 const char *order,
					 int dbcmd,
					 char *msgbuf)

	int
	VSI_Server_Person_Add		(V_SYS *vptr,
					 const char *pbtype,
					 char *palias_buf,
					 const V_TAG *tags,
					 char *msgbuf)

	int
	VSI_Server_Person_Upd		(V_SYS *vptr,
					 const char *pbtype,
					 const char *palias,
					 const V_TAG *tags,
					 char *msgbuf)

	int
	VSI_Server_Person_Del		(V_SYS *vptr,
					 const char *pbtype,
					 const char *palias,
					 char *msgbuf)

	Group functions:

	V_TAG *
	VSI_PB_Group_Get		(V_SYS *vptr,
					 const char *pbtype,
					 char *galias_buf,
					 int dbcmd,
					 char *msgbuf)

	int
	VSI_PB_Group_Add		(V_SYS *vptr,
					 const char *pbtype,
					 const V_TAG *tags,
					 char *msgbuf)

	int
	VSI_PB_Group_Upd		(V_SYS *vptr,
					 const char *pbtype,
					 const V_TAG *tags,
					 char *msgbuf)

	int
	VSI_PB_Group_Del		(V_SYS *vptr,
					 const char *pbtype,
					 const char *galias,
					 char *msgbuf)

	Member functions:

	V_TAG *
	VSI_PB_Member_Get		(V_SYS *vptr,
					 const char *pbtype,
					 int dbcmd,
					 char *msgbuf)

	int
	VSI_PB_Member_Add		(V_SYS *vptr,
					 const char *pbtype,
					 const char *palias,
					 const char *galias,
					 char *msgbuf)

	int
	VSI_PB_Member_Del		(V_SYS *vptr,
					 const char *pbtype,
					 const char *palias,
					 const char *galias,
					 char *msgbuf)

	List functions:

	V_LIST *
	VSI_PB_Person_List		(V_SYS *vptr,
					 const char *pbtype,
					 const char *order,
					 const char *key,
					 const char *galias,
					 int dbcmd,
					 int num,
					 char *msgbuf)

	V_LIST *
	VSI_PB_Person_List_Extended	(V_SYS *vptr,
					 const char *pbtype,
					 const char *order,
					 const char *beg,
					 const char *end,
					 const char *galias,
					 int offset,
					 int num,
					 char *msgbuf)

	V_LIST *
	VSI_PB_Group_List		(V_SYS *vptr,
					 const char *pbtype,
					 const char *galias,
					 int dbcmd,
					 int num,
					 char *msgbuf)

	Miscellaneous functions:

	V_TAG *
	VSI_PB_Types_List		(V_SYS *vptr,
					 char *msgbuf)

4.2.1	Phone-book person functions

4.2.1.1	Get a phone-book person entry

	V_TAG *
	VSI_Server_Person_Get		(V_SYS *vptr,
					 const char *pbtype,
					 char *key,
					 const char *order,
					 int dbcmd,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		pbtype			Phone-book type

		key			input:  key to get
					output: key of record read

		order			Sort order to read in.  Values are:
						"alias"	alias order (default)
						"lname"	last name order
						"fname"	first name order
						"comp"	company order

		dbcmd			database cmd

		msgbuf			error message buffer

	returns:
		pointer			pointer to a list of V_TAG structs
		NULL			error or no such person
					(message in msgbuf)

4.2.1.2	Add a phone-book person entry

	int
	VSI_Server_Person_Add		(V_SYS *vptr,
					 const char *pbtype,
					 char *palias_buf,
					 const V_TAG *tags,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		pbtype			Phone-book type

		palias_buf		Buffer to store alias of person.
					(May be NULL if not wanted)

		list			List of person tags

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

4.2.1.3	Update a phone-book person entry

	int
	VSI_Server_Person_Upd		(V_SYS *vptr,
					 const char *pbtype,
					 const char *palias,
					 const V_TAG *tags,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		pbtype			Phone-book type

		palias			Person alias of record to update.

		list			List of person tags to change

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

4.2.1.4	Delete a phone-book person entry

	int
	VSI_Server_Person_Del		(V_SYS *vptr,
					 const char *pbtype,
					 const char *palias,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		pbtype			Phone-book type

		palias			Person alias of record to delete.

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

4.2.2	Phone-book Group functions

4.2.2.1	Get a phone-book group entry

	V_TAG *
	VSI_Server_Group_Get		(V_SYS *vptr,
					 const char *pbtype,
					 char *galias,
					 int dbcmd,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		pbtype			Phone-book type

		galias			input:  group alias to get
					output: group alias of record read

		dbcmd			database cmd

		msgbuf			error message buffer

	returns:
		pointer			pointer to a list of V_TAG structs
		NULL			error or no such group
					(message in msgbuf)

4.2.2.2	Add a phone-book group entry

	int
	VSI_Server_Group_Add		(V_SYS *vptr,
					 const char *pbtype,
					 const V_TAG *tags,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		pbtype			Phone-book type

		list			List of group tags

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

4.2.2.3	Update a phone-book group entry

	int
	VSI_Server_Group_Upd		(V_SYS *vptr,
					 const char *pbtype,
					 const V_TAG *tags,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		pbtype			Phone-book type

		list			List of group tags to change

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

4.2.2.4	Delete a phone-book group entry

	int
	VSI_Server_Group_Del		(V_SYS *vptr,
					 const char *pbtype,
					 const char *galias,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		pbtype			Phone-book type

		galias			Group alias of record to delete.

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

4.2.3	Phone-book member functions

4.2.3.1	Get a phone-book member entry

	V_TAG *
	VSI_Server_Member_Get		(V_SYS *vptr,
					 const char *pbtype,
					 int dbcmd,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		pbtype			Phone-book type

		dbcmd			database cmd

		msgbuf			error message buffer

	returns:
		pointer			pointer to a list of V_TAG structs
		NULL			error or no such member
					(message in msgbuf)

4.2.3.2	Add a phone-book member entry

	int
	VSI_Server_Member_Add		(V_SYS *vptr,
					 const char *pbtype,
					 const char *palias,
					 const char *galias,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		pbtype			Phone-book type

		palias			Person alias of member

		galias			Group alias of member

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

4.2.3.3	Delete a phone-book member entry

	int
	VSI_Server_Member_Del		(V_SYS *vptr,
					 const char *pbtype,
					 const char *palias,
					 const char *galias,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		pbtype			Phone-book type

		palias			Person alias of record to delete.

		galias			Group alias of record to delete.

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

4.2.4	Phone-book list functions

4.2.4.1	Get a list of person entries

	V_LIST *
	VSI_PB_Person_List		(V_SYS *vptr,
					 const char *pbtype,
					 const char *order,
					 const char *key,
					 const char *galias,
					 int dbcmd,
					 int num,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		pbtype			Phone-book type

		key			input:  key to get
					output: key of last record read

		galias			Group alias to use

		dbcmd			database cmd

		num			max number of records to read
					(0 for all)

		msgbuf			error message buffer

	returns:
		pointer			pointer to list of V_LIST entries
		NULL			error (message in msgbuf)

4.2.4.2	Get an extended list of person entries

	V_LIST *
	VSI_PB_Person_List_Extended	(V_SYS *vptr,
					 const char *pbtype,
					 const char *order,
					 const char *beg,
					 const char *end,
					 const char *galias,
					 int dbcmd,
					 int offset,
					 int num,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		pbtype			Phone-book type

		beg			Key value to start reading at

		end			Key value to stop reading at

		galias			Group alias to use

		dbcmd			database cmd

		offset			number of records to skip at start

		num			max number of records to read
					(0 for all)

		msgbuf			error message buffer

	returns:
		pointer			pointer to list of V_LIST entries
		NULL			error (message in msgbuf)

4.2.4.3	Get a list of group entries

	V_LIST *
	VSI_PB_Group_List		(V_SYS *vptr,
					 const char *pbtype,
					 const char *galias,
					 int dbcmd,
					 int num,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		pbtype			Phone-book type

		galias			Group alias to use

		dbcmd			database cmd

		num			max number of records to read
					(0 for all)

		msgbuf			error message buffer

	returns:
		pointer			pointer to list of V_LIST entries
		NULL			error (message in msgbuf)

4.2.5	Miscellaneous phone-book functions

4.2.5.1	Get a list of all available phone-book types

	This function returns a list of all phone-books available.
	In each V_TAG entry, the "name" field contains the phone-book
	type and the "data" field contains "type-<group>".  The first
	entry for each phone-book type available will be "type-all".

	V_TAG *
	VSI_PB_Types_List		(V_SYS *vptr,
					 char *msgbuf)

	args:
		vptr			pointer from VSI_Server_Login() or NULL

		msgbuf			error message buffer

	returns:
		pointer			pointer to list of V_TAG entries
		NULL			error (messsage in msgbuf)

4.3	Tag/List list utilities

	These routines are used to manipulate "tag-lists".
	They are designed so that, in normal usage, a user does
	not have to deal with the content or structure of a "tag"
	or of a list.

4.3.1	Tag functions

	V_TAG *
	VSI_Tag_Free			(V_TAG *tags,
					 char *msgbuf)

	V_TAG *
	VSI_Tag_Add			(V_TAG *tags,
					 const char *name,
					 const char *data,
					 char *msgbuf)

	V_TAG *
	VSI_Tag_Add_Str			(V_TAG *tags,
					 const char *str,
					 char *msgbuf)

	V_TAG *
	VSI_Tag_Add_Ini_Sys		(V_TAG *tags,
					 char *msgbuf)

	V_TAG *
	VSI_Tag_Add_Ini_Usr		(V_TAG *tags,
					 char *msgbuf)

	int
	VSI_Tag_List_Count		(const V_TAG *tags,
					 char *msgbuf)

	const V_TAG *
	VSI_Tag_Find_By_Index		(const V_TAG *tags,
					 int index,
					 char *msgbuf)

	const V_TAG *
	VSI_Tag_Find_By_Name		(const V_TAG *tags,
					 const char *name,
					 char *msgbuf)

	const V_TAG *
	VSI_Tag_Find_By_Data		(const V_TAG *tags,
					 const char *data,
					 char *msgbuf)

	const char *
	VSI_Tag_Get_Name_By_Index	(const V_TAG *tags,
					 int index,
					 char *name_buf,
					 char *msgbuf)

	const char *
	VSI_Tag_Get_Name_By_Data	(const V_TAG *tags,
					 const char *data,
					 char *name_buf,
					 char *msgbuf)

	const char *
	VSI_Tag_Get_Data_By_Index	(const V_TAG *tags,
					 int index,
					 char *data_buf,
					 char *msgbuf)

	const char *
	VSI_Tag_Get_Data_By_Name	(const V_TAG *tags,
					 const char *name,
					 char *data_buf,
					 char *msgbuf)

	V_TAG *
	VSI_Tag_Load			(V_TAG *tags,
					 const char *path,
					 char msgbuf)

	int
	VSI_Tag_Save			(const V_TAG *tags,
					 const char *path,
					 char *msgbuf)

	V_TAG *
	VSI_Tag_Copy			(const V_TAG *tags,
					 char *msgbuf)

	V_TAG *
	VSI_Tag_Append			(V_TAG *orig,
					 const V_TAG *other,
					 char *msgbuf)

	V_TAG *
	VSI_Tag_Prepend			(V_TAG *orig,
					 const V_TAG *other,
					 char *msgbuf)

	int
	VSI_Tag_To_Str			(const V_TAG *tags,
					 char *str,
					 const char *flds,
					 int delim,
					 int quotes,
					 char *msgbuf)

	V_TAG *
	VSI_Tag_From_Str		(const char *str,
					 const char *flds,
					 int delim,

	int
	VSI_Tag_Fields			(const char *tbl,
					 char *flds,
					 int delim,
					 char *msgbuf)

	V_TAG *
	VSI_Tag_Next			(V_TAG *tag)

	V_TAG *
	VSI_Tag_Prev			(V_TAG *tag)

	char *
	VSI_Tag_Name			(V_TAG *tag)

	char *
	VSI_Tag_Data			(V_TAG *tag)

4.3.1.1	Free tag-list

	V_TAG *
	VSI_Tag_Free			(V_TAG *tags,
					 char *msgbuf)

	args:
		list			pointer to a list of V_TAG structs

		msgbuf			error message buffer

	returns:
		NULL			always

4.3.1.2	Add tag to list

	V_TAG *
	VSI_Tag_Add			(V_TAG *tags,
					 const char *name,
					 const char *data,
					 char *msgbuf)

	args:
		list			pointer to old list

		name			tag name

		data			tag data

		msgbuf			error message buffer

	returns:
		pointer			pointer to new list (if add failed,
					msgbuf will contain a msg)

4.3.1.3	Add a string tag=value to a tag-list

	V_TAG *
	VSI_Tag_Add_Str			(V_TAG *tags,
					 const char *str,
					 char *msgbuf)

	args:
		list			pointer to old list

		str			tag string to add in form "tag=value"

		msgbuf			error mssage buffer

	returns:
		pointer			pointer to new list (if add failed,
					msgbuf will contain a msg)

4.3.1.4	Add entries from system ini file to a tag-list

	V_TAG *
	VSI_Tag_Add_Ini_Sys		(V_TAG *tags,
					 char *msgbuf)

	args:
		list			pointer to old list

		msgbuf			error mssage buffer

	returns:
		pointer			pointer to new list (if add failed,
					msgbuf will contain a msg)

4.3.1.5	Add entries from user ini file to a tag-list

	V_TAG *
	VSI_Tag_Add_Ini_Usr		(V_TAG *tags,
					 char *msgbuf)

	args:
		list			pointer to old list

		msgbuf			error mssage buffer

	returns:
		pointer			pointer to new list (if add failed,
					msgbuf will contain a msg)

4.3.1.6	Get count of entries in a tag-list

	int
	VSI_Tag_List_Count		(const V_TAG *tags,
					 char *msgbuf)

	args:
		list			pointer to a list of V_TAG structs

		msgbuf			error message buffer

	returns:
		>=0			number of entries in list
		-1			error (message in msgbuf)

4.3.1.7	Find an entry by index

	const V_TAG *
	VSI_Tag_Find_By_Index		(const V_TAG *tags,
					 int index,
					 char *msgbuf)

	args:
		list			pointer to list of V_TAG structs

		index			index of entry to find

		msgbuf			error message buffer

	returns:
		pointer			pointer to V_TAG entry
		NULL			errror (message in msgbuf)

4.3.1.8	Find a tag entry by name

	const V_TAG *
	VSI_Tag_Find_By_Name		(const V_TAG *tags,
					 const char *name,
					 char *msgbuf)

	args:
		list			pointer to list of V_TAG structs

		name			tag name to find

		msgbuf			error message buffer

	returns:
		pointer			pointer to V_TAG entry
		NULL			error (message in msgbuf)

4.3.1.9	Find a tag entry by data value

	const V_TAG *
	VSI_Tag_Find_By_Data		(const V_TAG *tags,
					 const char *data,
					 char *msgbuf)

	args:
		list			pointer to a list of V_TAG structs

		data			tag data to find

		msgbuf			error message buffer

	returns:
		pointer			pointer to V_TAG entry
		NULL			error (message in msgbuf)

4.3.1.10	Get the name of a tag entry by index

	const char *
	VSI_Tag_Get_Name_By_Index	(const V_TAG *tags,
					 int index,
					 char *name_buf,
					 char *msgbuf)

	args:
		list			pointer to a list of V_TAG structs

		index			index value

		name_buf		buffer for name (may be NULL)

		msgbuf			error message buffer

	returns:
		pointer			pointer to name value
					(if tag not found, "" is returned)

4.3.1.11	Get the name of a tag entry by data

	const char *
	VSI_Tag_Get_Name_By_Data	(const V_TAG *tags,
					 const char *data,
					 char *name_buf,
					 char *msgbuf)

	args:
		list			pointer to a list of V_TAG structs

		data			tag data to find

		name_buf		buffer for name (may be NULL)

		msgbuf			error message buffer

	returns:
		pointer			pointer to name value
					(if tag not found, "" is returned)

4.3.1.12	Get the data of a tag entry by index

	const char *
	VSI_Tag_Get_Data_By_Index	(const V_TAG *tags,
					 int index,
					 char *data_buf,
					 char *msgbuf)

	args:
		list			pointer to a list of V_TAG structs

		index			index value

		data_buf		buffer for data (may be NULL)

		msgbuf			error message buffer

	returns:
		pointer			pointer to data value
					(if tag not found, "" is returned)

4.3.1.13	Get the data of a tag entry by name

	const char *
	VSI_Tag_Get_Data_By_Name	(const V_TAG *tags,
					 const char *name,
					 char *data_buf,
					 char *msgbuf)

	args:
		list			pointer to a list of V_TAG structs

		name			tag name to find

		data_buf		buffer for data (may be NULL)

		msgbuf			error message buffer

	returns:
		pointer			pointer to data value
					(if tag not found, "" is returned)

4.3.1.14	Load list of tags from a file

	V_TAG *
	VSI_Tag_Load			(V_TAG *tags,
					 const char *path,
					 char msgbuf)

	args:
		list			pointer to list to add tags to

		path			pathname of file ("-" for stdin)

		msgbuf			error msg buffer

	returns:
		pointer			pointer to new list of V_TAG structs
		NULL			error (message in msgbuf)

4.3.1.15	Save a list of tags to a file

	int
	VSI_Tag_Save			(const V_TAG *tags,
					 const char *path,
					 char *msgbuf)

	args:
		list			pointer to list of V_TAG structs

		path			pathname to save to ("-" for stdout)

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

4.3.1.16	Copy a tag-list

	V_TAG *
	VSI_Tag_Copy			(const V_TAG *tags,
					 char *msgbuf)

	args:
		list			pointer to tag-list to copy
					(may be NULL)

		msgbuf			error message buffer

	returns:
		pointer			pointer to tag-list copy

		NULL			orig list was NULL or error
					(check msgbuf)

4.3.1.17	Append a tag-list to a tag-list

	V_TAG *
	VSI_Tag_Append			(V_TAG *tags,
					 const V_TAG *other,
					 char *msgbuf)

	args:
		orig			pointer to tag-list to append to
					(may be NULL)

		other			pointer to tag-list to append
					(msy be NULL)

		msgbuf			error message buffer

	returns:
		pointer			pointer to new tag-list

		NULL			both lists were NULL or error
					(check msgbuf)

4.3.1.18	Prepend a tag-list to a tag-list

	V_TAG *
	VSI_Tag_Prepend			(V_TAG *tags,
					 const V_TAG *other,
					 char *msgbuf)

	args:
		orig			pointer to tag-list to prepend to
					(may be NULL)

		other			pointer to tag-list to prepend
					(msy be NULL)

		msgbuf			error message buffer

	returns:
		pointer			pointer to new tag-list

		NULL			both lists were NULL or error
					(check msgbuf)

4.3.1.19	Convert a tag-list to a string

	int
	VSI_Tag_To_Str			(const V_TAG *tags,
					 char *str,
					 const char *flds,
					 int delim,
					 int quotes,
					 char *msgbuf)

	args:
		list			pointer to tag-list to convert

		str			pointer to string buffer

		flds			pointer to field list (tag
					names separated by commas).
					NULL implies all entries.

		delim			delimiter to use.  0 implies
					convert in "eval" format

		quotes			0 = do not enclose data in quotes
					1 = enclose data in quotes
					If "eval" format (delim == 0)
					this is ignored.

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

4.3.1.20	Convert a string to a tag-list

	V_TAG *
	VSI_Tag_From_Str		(const char *str,
					 const char *flds,
					 int delim,
					 char *msgbuf)

	args:
		str			pointer to string to convert

		flds			pointer to field list
					(ignored if "eval" format)

		delim			delimiter used (0 == "eval" format)

		msgbuf			error message buffer

	returns:
		pointer			pointer to tag-list
		NULL			error (message in msgbuf)

4.3.1.21	Get a field list for a tag table type

	This routine is used when outputting database fields in
	some dump format, and the first line is expected to be
	the names of the fields in the same format.

	The field-list buffer returned from this routine can also
	be used as the field-list in the VSI_Tag_To_Str() call.

	int
	VSI_Tag_Fields			(const char *tbl,
					 char *flds,
					 int delim,
					 char *msgbuf)

	args:
		tbl			tag table type.  Values are:

					V_TAG_OLOG_TBLNAME	OLOG database
					V_TAG_ILOG_TBLNAME	ILOG database
					V_TAG_ENV_TBLNAME	envelope
					V_TAG_HDR_TBLNAME	TIFF header
					V_TAG_PER_TBLNAME	PB person
					V_TAG_GRP_TBLNAME	PB group
					V_TAG_MEM_TBLNAME	PB member

		flds			buffer to store tag names into

		delim			delimiter to use

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

4.3.1.22	Tag Macros

	The following functions are normally implemented as macros,
	but may be called as functions if VSI_NOMACROS is defined.
	These calls are designed for efficient C/C++ usage of lists.

4.3.1.22.1	Get next tag in a list

	V_TAG *
	VSI_Tag_Next			(V_TAG *tag)

	args:
		tag			pointer to a tag entry

	returns:
		pointer			pointer to next tag in the list
		NULL			list or next tag is NULL

4.3.1.22.2	Get prev tag in a list

	V_TAG *
	VSI_Tag_Prev			(V_TAG *tag)

	args:
		tag			pointer to a tag entry

	returns:
		pointer			pointer to prev tag in the list
		NULL			list or prev tag is NULL

4.3.1.22.3	Get name of a tag

	char *
	VSI_Tag_Name			(V_TAG *tag)

	args:
		tag			pointer to a tag entry

	returns:
		pointer			tag name
		NULL			tag entry is NULL

4.3.1.22.4	Get data of a tag

	char *
	VSI_Tag_Data			(V_TAG *tag)

	args:
		tag			pointer to tag entry

	returns:
		pointer			pointer to tag data
		NULL			tag pointer is NULL

4.3.2	List functions

	V_LIST *
	VSI_List_Free			(V_LIST *list,
					 char *msgbuf)

	int
	VSI_List_Count			(const V_LIST *list,
					 char *msgbuf)

	const V_LIST *
	VSI_List_Find_By_Index		(const V_LIST *list,
					 int index,
					 char *msgbuf)

	const V_TAG *
	VSI_List_Get_Tags		(const V_LIST *list,
					 char *msgbuf)

	V_LIST *
	VSI_List_Add			(V_LIST *list,
					 V_TAG *tags,
					 char *msgbuf)

	V_LIST *
	VSI_List_Next			(V_LIST *list)

	V_LIST *
	VSI_List_Prev			(V_LIST *list)

	V_TAG *
	VSI_List_Tags			(V_LIST *list)

4.3.2.1	Free a list

	V_LIST *
	VSI_List_Free			(V_LIST *list,
					 char *msgbuf)

	args:
		list			pointer to list to free

		msgbuf			error message buffer

	returns:
		NULL			always

4.3.2.2	Count entries in a list

	int
	VSI_List_Count			(V_LIST *list,
					 char *msgbuf)

	args:
		list			pointer to list

		msgbuf			error message buffer

	returns:
		n			number of entries in list
		-1			error (message in msgbuf)

4.3.2.3	Find an entry in a list by index

	V_LIST *
	VSI_List_Find_By_Index		(V_LIST *list,
					 int index,
					 char *msgbuf)

	args:
		list			pointer to list

		index			index of entry to find

		msgbuf			error message buffer

	returns:
		pointer			pointer to list entry
		NULL			error (message in msgbuf)

4.3.2.4	Get the tag-list from a list entry

	V_TAG *
	VSI_LIst_Get_Tags		(V_LIST *list,
					 char *msgbuf)

	args:
		list			pointer to list

		msgbuf			error message buffer

	returns:
		pointer			pointer to tags entry
		NULL			error (message in msgbuf)

4.3.2.5	Add an entry to a list

	V_LIST *
	VSI_List_Add			(V_LIST *list,
					 V_TAGS *tags,
					 char *msgbuf)

	args:
		list			pointer to list to add to (may be NULL)

		tags			pointer to tag-list to add

		msgbuf			error message buffer

	returns:
		pointer			pointer to new list
		NULL			error (message in msgbuf)

4.3.2.6	List macros

	The following functions are normally implemented as macros,
	but may be called as functions if VSI_NOMACROS is defined.
	These calls are designed for efficient C/C++ usage of lists.

4.3.2.6.1	Get next entry in a list

	V_LIST *
	VSI_List_Next			(V_LIST *list)

	args:
		list			pointer to list entry (may be null)

	returns:
		pointer			pointer to next entry
		NULL			list or next entry is NULL

4.3.2.6.2	Get prev entry in a list

	V_LIST *
	VSI_List_Prev			(V_LIST *list)

	args:
		list			pointer to list entry (may be null)

	returns:
		pointer			pointer to prev entry
		NULL			list or prev entry is NULL

4.3.2.6.3	Get tag list from a list entry

	V_TAG *
	VSI_List_Tags			(V_LIST *list)

	args:
		list			pointer to list entry (may be NULL)

	returns:
		pointer			pointer to tag list
		NULL			list entry was NULL

4.4	Miscellaneous utilities

	These are miscellaneous utilities for various purposes.

	A summary is as follows:

	char *
	VSI_Util_Time_To_Str		(time_t timeval,
					 char *timestr,
					 char *msgbuf)

	char *
	VSI_Util_Word_To_Str		(int wordval,
					 char *wordstr,
					 char *msgbuf)

	char *
	VSI_Util_Bool_To_Str		(int boolval,
					 char *boolstr,
					 char *msgbuf)

	time_t
	VSI_Util_Str_To_Time		(const char *timestr,
					 char *msgbuf)

	int
	VSI_Util_Str_To_Word		(const char *wordstr,
					 char *msgbuf)

	int
	VSI_Util_Str_To_Bool		(const char *boolstr,
					 char *msgbuf)

	int
	VSI_Util_Version		(char *version,
					 char *build,
					 char *msgbuf)

	int
	VSI_Util_Crypt			(const char *str,
					 char *buf,
					 char *msgbuf)

	int
	VSI_Util_Encrypt		(const char *str,
					 const char *key,
					 char *buf,
					 char *msgbuf)

	int
	VSI_Util_Decrypt		(const char *str,
					 const char *key,
					 char *buf,
					 char *msgbuf)

	const char *
	VSI_Util_Temp_Dir		(char *buf)

	const char *
	VSI_Util_Home_Dir		(char *buf)

	char *
	VSI_Time_Format_Val		(time_t t,
					 const char *fmt,
					 char *buf,
					 int buflen,
					 char *msgbuf)

	char *
	VSI_Time_Format_Str		(const char *str,
					 const char *fmt,
					 char *buf,
					 int buflen,
					 char *msgbuf)

	int
	VSI_Opt_Get			(int argc,
					 char **argv,
					 const char *optstr,
					 char *msgbuf)

	int
	VSI_Opt_Index			(void)

	int
	VSI_Opt_Option			(void)

	const char *
	VSI_Opt_Argstr			(void)

4.4.1	Convert a UNIX time to a string (as local time)

	char *
	VSI_Util_Time_To_Str		(time_t timeval,
					 char *timestr,
					 char *msgbuf)

	args:
		timeval			time value to convert

		timestr			buffer to contain string

		msgbuf			error message buffer

	returns:
		pointer			pointer to timestr.
					String will be in form:
						"yyyy/mm/dd hh:mm:ss"

		NULL			error (message in msgbuf)

4.4.2	Convert a numeric word to a string

	char *
	VSI_Util_Word_To_Str		(int wordval,
					 char *wordstr,
					 char *msgbuf)

	args:
		wordval			word value to convert

		wordstr			buffer to contain string

		msgbuf			error message buffer

	returns:
		pointer			pointer to wordstr.

		NULL			error (message in msgbuf)

4.4.3	Convert a boolean to a string

	char *
	VSI_Util_Bool_To_Str		(int boolval,
					 char *boolstr,
					 char *msgbuf)

	args:
		boolval			bool value to convert

		boolstr			buffer to contain string

		msgbuf			error message buffer

	returns:
		pointer			pointer to boolstr.

		NULL			error (message in msgbuf)

4.4.4	Convert a (local time) string to a UNIX time

	time_t
	VSI_Util_Str_To_Time		(const char *timestr,
					 char *msgbuf)

	args:
		timestr			string to be converted.
					String formats allowed are:
						yyyymmddhhmmss[am|pm]
						yymmddhhmmss[am|pm]
						mmddhhmmss[am|pm]
						hhmmss[am|pm]
					All non-digits are ignored
					(except for the trailing am|pm).

		msgbuf			error message buffer

	returns:
		>= 0			time as a UNIX time (time_t)
		-1			error (message in msgbuf)

4.4.5	Convert a string to a numeric word

	int
	VSI_Util_Str_To_Word		(const char *wordstr,
					 char *msgbuf)

	args:
		wordstr			string to be converted.

		msgbuf			error message buffer

	returns:
		>= 0			word value
		-1			error (message in msgbuf)

4.4.6	Convert a string to a bool

	int
	VSI_Util_Str_To_Bool		(const char *boolstr,
					 char *msgbuf)

	args:
		boolstr			string to be converted.
					String formats allowed are:
						on, yes, true	-> TRUE
						off, no, false	-> FALSE
					If numeric, zero -> FALSE
						non-zero -> TRUE

		msgbuf			error message buffer

	returns:
		FALSE			FALSE
		TRUE			TRUE
		-1			error (message in msgbuf)

4.4.7	Get VSI version & build number

	int
	VSI_Util_Version		(char *version,
					 char *build,
					 char *msgbuf)

	args:
		version			buffer to store version string in.
					This will be in the form:
						"<major>.<minor>.<release>"

		build			optional buffer to store build number in

		msgbuf			error message buffer

	returns:
		0			OK
		-1			error (message in msgbuf)

4.4.8	Encrypt a password

	This routine is provided to encrypt a password to be used
	in the VSI_Server_Login() call. This routine uses the
	standard DES one-way encryption algorithm.  The "salt"
	used for the encryption is fixed.

	Note that, unlike the passwords found in the Unix password
	file (/etc/passwd), the two-character salt used is not
	present as the first two characters of the encrypted string.
	It is, however, the same encryption algorithm that is used.

	int
	VSI_Util_Crypt			(const char *str,
					 char *buf,
					 char *msgbuf)

	args:
		str			string to be encrypted

		buf			buffer for encrypted string

		msgbuf			error message buffer

	returns:
		 0			OK
		-1			NULL buf pointer encountered

4.4.8	Encrypt a string

	This routine is used to provide a reversable encrypted string.

	int
	VSI_Util_Encrypt		(const char *str,
					 const char *key,
					 char *buf,
					 char *msgbuf)

	args:
		str			string to be encrypted

		key			Key to use in the encryption

		buf			buffer for encrypted string

		msgbuf			error message buffer

	returns:
		 0			OK
		-1			NULL buf pointer encountered

4.4.8	Decrypt a string

	This routine is used to decrypt a string created by the
	VSI_Util_Encrypt() call.

	int
	VSI_Util_Decrypt		(const char *str,
					 const char *key,
					 char *buf,
					 char *msgbuf)

	args:
		str			string to be encrypted

		key			string used to encrypt the string

		buf			buffer for encrypted string

		msgbuf			error message buffer

	returns:
		 0			OK
		-1			NULL buf pointer encountered

4.4.11	Get location of a temp directory

	const char *
	VSI_Util_Temp_Dir		(char *buf)

	args:
		buf			optional buffer for dir name

	returns:
		pointer			pointer to dir name

	Notes:
		The location of the temp dir returned is OS dependent.

4.4.12	Get location of user's VSI home directory

	const char *
	VSI_Util_Home_Dir		(char *buf)

	args:
		buf			optional buffer for dir name

	returns:
		pointer			pointer to dir name

	Notes:
		The user name used for this routine is the name the user
		logged onto the OS with.

		This does not return the user's OS home directory, but
		the user's VSI home directory.  This location is
		OS dependent, as follows:

			Unix		$HOME/.vsifax

			NT		%windir%\Profiles\<user>\
						Application Data\VSI

			WIN2K/XP	%APPDATA%\VSI
					or
					%HOMEDRIVE%\Documents and Settings\
						<user>\Application Data\VSI

			WIN9X		%windir%\Application Data\VSI

		Note that the default VSI home directory may be overridden
		by the environment variable VSIHOME.

		Note also that this only returns the name of the directory;
		it does not create it if it doesn't exist.

4.4.13	Format a time value into a string

	This routine will convert a time value into a formatted string
	according to a format specification.  The format string consists
	of a a mixture of characters and "format-specifications", which
	are a "%" followed by a character.  These format specifications
	are as follows:

	%a	Abbreviated weekday name.

	%A	Full weekday name.

	%b	Abbreviated month name.

	%B	Full month name.

	%c	Appropriate date & time representation.

	%C	Date & time representation as produced by ctime(3C).

	%C	Century number (the year divided by 100 and truncated
		to an integer as a decimal number [1,99]);
		single digits are preceded by 0.

	%d	Day of month [1,31]; single digits are preceded by 0.

	%D	Date as %m/%d/%y.

	%e	Day of month [1,31]; single digits are preceded by a space.

	%g	Week-based year within century [00,99].

	%G	Week-based year, including the century [0000,9999].

	%h	Abbreviated month name.

	%H	Hour (24-hour clock) [0,23]; single digits are preceded by 0.

	%I	Hour (12-hour clock) [1,12]; single digits are preceded by 0.

	%j	Day number of year [1,366];  single digits are preceded by 0.

	%k	Hour (24-hour clock) [0,23]; single digits preceded by a blank.

	%l	Hour (12-hour clock) [1,12]; single digits preceded by a blank.

	%m	Month number [1,12]; single digits are preceded by 0.

	%M	Minute [00,59]; leading 0 is permitted but not required.

	%p	Either AM or PM.

	%r	Appropriate time representation in 12-hour clock format with %p.

	%R	Time as %H:%M.

	%S	Seconds [00,61]; the range of values is [00,61] rather
		than [00,59] to allow for the occasional leap second and
		even more occasional double leap second.

	%T	Time as %H:%M:%S.

	%u	Weekday as a decimal number [1,7], with 1 representing Monday.

	%U	Week number of year as a decimal number [00,53],
		with Sunday as the first day of week 1.

	%V	The ISO 8601 week number as a decimal number [01,53].
		In the ISO 8601 week-based system, weeks begin on a
		Monday and week 1 of the year is the week that includes
		both January 4th and the first Thursday of the year.
		If the first Monday of January is the 2nd, 3rd, or 4th,
		the preceding days are part of the last week of the
		preceding year.

	%w	Weekday as a decimal number [0,6], with 0 representing Sunday.

	%W	Week number of year as a decimal number [00,53],
		with Monday as the first day of week 1.

	%x	Appropriate date representation.

	%X	Appropriate time representation.

	%y	Year within century [00,99].

	%Y	Year, including the century.

	%Z	Time zone name or abbreviation, or "" if no TZ info exists.

	char *
	VSI_Time_Format_Val		(time_t t,
					 const char *fmt,
					 char *buf,
					 int buflen,
					 char *msgbuf)

	args:
		t			the time value to convert

		fmt			the format string to use

		buf			buffer for resultant string

		buflen			max length of buffer

		msgbuf			error message buffer

	returns:
		buf			formatting was successful
		0			error

4.4.14	Format a time string according to a format

	This is a convience routine to convert a time value as
	returned in a tag value.  It is equivalent to the call

		VSI_Time_Format_Val(VSI_Util_Str_To_Time(str, 0),
			fmt, buf, buflen, msgbuf)

	char *
	VSI_Time_Format_Str		(const char *str,
					 const char *fmt,
					 char *buf,
					 int buflen,
					 char *msgbuf)

	args:
		str			the time value as a string

		fmt			the format string to use

		buf			buffer for resultant string

		buflen			max length of buffer

		msgbuf			error message buffer

	returns:
		buf			formatting was successful
		0			error

4.4.15	Parse command line options

	This routine is provided as a replacement for the standard
	getopt() Unix library routine in order to provide the same
	functionality in Windows, which does not provide this routine.
	Refer to the Unix documentation for getopt(3C) for more details.

	int
	VSI_Opt_Get			(int argc,
					 char **argv,
					 const char *optstr,
					 char *msgbuf)
	args:
		argc			argc from main()

		argv			argv from main()

		optstr			string containing options to be
					processed

					Single arguments are indicated by the
					letter and arguments taking an argument
					are indicated by a colon following the
					letter.

					Thus, if a program took the following
					options:

						-v		verbose mode
						-f		force something
						-d <dir>	directory name

					then the optstr would be "vfd:".

					Note that options are case-sensitive,
					"a" is different from "A".

		msgbuf			error message buffer

	returns:
		-1			end of options
		 0			error (message in msgbuf)
		>0			option character found

	int
	VSI_Opt_Index			(void)

	returns:			The current index in argv.
					(This will have a value of 0 before
					any calls to VSI_Opt_Get() are
					made.

	int
	VSI_Opt_Option			(void)

	returns:			The option character found

	const char *
	VSI_Opt_Argstr			(void)

	returns:			NULL if no argument for an option
					is expected or a pointer to
					the argument if one is expected.

4.5	TIFF file utilities

	These are miscellaneous utilities for manipulating TIFF files.

	A summary is as follows:

	V_TAG *
	VSI_TIFF_Header			(const char *path,
					 char *msgbuf)

	int
	VSI_TIFF_Copy			(const char *out_path,
					 const char *inp_path,
					 const char *pg_range,
					 const char *resolution,
					 int vsitags,
					 char *msgbuf)

	int
	VSI_TIFF_Merge			(const char *out_path,
					 const V_TAG *files,
					 const char *resolution,
					 int vsitags,
					 char *msgbuf)


4.5.1	Get a list of header tags for a fax file

	V_TAG *
	VSI_TIFF_Header			(const char *path,
					 char *msgbuf)

	args:
		path			pathname of fax file

		msgbuf			error message buffer

	returns:
		pointer			pointer to header tag-list
		NULL			error (message in msgbuf)


4.5.2	Copy a TIFF file

	int
	VSI_TIFF_Copy			(const char *out_path,
					 const char *inp_path,
					 const char *pg_range,
					 const char *resolution,
					 int vsitags,
					 char *msgbuf)

	args:
		out_path		pathname of output file

		inp_path		pathname of input file

		pg_range		page range specification
					NULL or empty string implies all pages.
					Range is a comma-separated string,
					Examples:

						1,2	pages 1 & 2
						1,3-5	pages 1 and 3 through 5
						6-	pages 6 to the end

		resolution		output resolution specification
					NULL or empty string implies use
					input file resolution.
					Values: "fine" or "std"

		vsitags			FALSE == do not put VSI-specific tags
						in output file
					TRUE  == include VSI-specific tags
						in output file

		msgbuf			error message buffer

	returns:
		-1			error
		>=0			number of pages copied

4.5.3	Merge TIFF files together

	int
	VSI_TIFF_Merge			(const char *out_path,
					 const V_TAG *files,
					 const char *resolution,
					 int vsitags,
					 char *msgbuf)

	args:
		out_path		pathname of output file

		files			a list of tags decribing the files
					and optional page-ranges to be merged.

					A file is indicated by the tag
					"fll=<filename>, and an optional
					page-range is specified by a
					subsequent tag "fpg=<page-range>"

		resolution		output resolution specification
					NULL or empty string implies use
					first input file resolution.
					Values: "fine" or "std"

		vsitags			FALSE == do not put VSI-specific tags
						in output file
					TRUE  == include VSI-specific tags
						in output file

		msgbuf			error message buffer

	returns:
		-1			error
		>=0			number of pages copied

4.6	Memory functions

	If you are writing a simple command-line program which just
	does some task and terminates, memory management may not an
	important issue.  But, in a GUI or CUI program, which may
	be long-lived, it is important to track memory usage,
	especially to be sure that no memory-leaks occur.
	Also, in any program, it is important that you do not
	"overrun" allocated memory (i.e. store more data than was
	allocated).

	The memory functions in this package provide the same
	functionality as the standard "malloc" package, but they
	provide better debugging of the memory usage.

	In addition to the standard allocate and free calls, there
	are calls to get the number of current outstanding memory
	allocations and to dump the "chain" of allocations.

	Note that, if you define the variable V_DEBUG_MALLOC at compile time,
	then when any error messages are displayed or when the chain is dumped,
	the file and line number of the call is displayed.  This
	allows maximum debugging capability at the expense of executable
	size.  This is normally invoked as "cc ... -DV_DEBUG_MALLOC ..."
	or via the source line "#define V_DEBUG_MALLOC 1" in any C
	file which includes "vsi.h" (before the include).  Note that it
	can be selectively set in just those files which need better
	memory debugging.

	If any error occurs in allocating or freeing memory, the normal
	mode is to display an error message to stderr and continue.
	The default behavior may be modified by setting any of the
	following environment variables at execution time:

		V_MALLOC_NOFREE		If set, then data is not actually
					freed, but just marked as freed in
					the chain.  This enables the ability
					to catch the error of freeing data
					which was already freed.
					(The value is ignored.)

		V_MALLOC_CHAIN		If set, dump the chain when any
					error message is displayed.
					(The value is ignored.)

		V_MALLOC_DUMP=nnn	If set, specifies to dump data along
					with the chain.  The value is the
					max number of bytes to dump (0 -> all).

		V_MALLOC_ABORT		If set, then the program is aborted
					if an error occurs (after any error
					message is displayed).  Normally,
					the program is allowed to continue.
					(The value is ignored.)

		V_MALLOC_NULLCHK	If set, then frees of a NULL pointer
					are considered as an error.
					(The value is ignored.)

		V_MALLOC_CHKALLOC	If set, the chain is checked for
					integrity at each allocation.
					(The value is ignored.)

		V_MALLOC_CHKFREE	If set, the chain is checked for
					integrity at each free.
					(The value is ignored.)

		V_MALLOC_DMPALLOC	If set, then a message is displayed
					for each allocation request.
					(The value is ignored.)

		V_MALLOC_DMPFREE	If set, then a message is displayed
					for each free request.
					(The value is ignored.)

		V_MALLOC_DBGFILE=path	If set, then messages are written to
					the specified path rather than to
					stderr.

	Note that these environment variables are run-time variables, not
	compile-time variables (which the V_DEBUG_MALLOC variable is).

	Note that these calls are used in this library for all memory
	allocation and frees.

	Note also that it is very important to not mix data associated
	with these calls with the standard "malloc" package.  That is,
	don't use free() to free memory allocated via VSI_Memory_Malloc(),
	and don't use VSI_Memory_Free() to free memory allocated via malloc()
	(or Very Bad Things will happen).

	A summary is as follows:

	void *
	VSI_Memory_Malloc		(int size)

	void *
	VSI_Memory_Calloc		(int num,
					 int size)

	void *
	VSI_Memory_Realloc		(void *ptr,
					 int size)

	void
	VSI_Memory_Free			(void *ptr)

	char *
	VSI_Memory_Strdup		(const char *str)

	int
	VSI_Memory_Count		(void)

	void
	VSI_Memory_Dump			(FILE *fp,
					 int dump_data,
					 int maxlen)
4.6.1	Allocate a block of memory

	void *
	VSI_Memory_Malloc		(int size)

	args:
		size			the number of bytes wanted

	returns:
		pointer			pointer to allocated memory
		NULL			error (memory could not be gotten)

4.6.2	Allocate and clear blocks of memory

	void *
	VSI_Memory_Calloc		(int num,
					 int size)

	args:
		num			the number of blocks wanted

		size			the number of bytes in each block

	returns:
		pointer			pointer to allocated memory
		NULL			error (memory could not be gotten)

4.6.3	Reallocate a block of memory

	void *
	VSI_Memory_Realloc		(void *ptr,
					 int size)

	args:
		ptr			pointer to old allocated block
					(this may be NULL)

		size			the new number of bytes wanted.
					As much data as possible is copied
					from the old allocated block to the
					new block.

	returns:
		pointer			pointer to allocated memory
		NULL			error (memory could not be gotten)

4.6.4	Free a block of memory

	void
	VSI_Memory_Free			(void *ptr)

	args:
		ptr			pointer to memory to be freed

	returns:
		none

4.6.5	Copy a string into managed memory

	char *
	VSI_Memory_Strdup		(const char *str)

	args:
		str			pointer to string to be copied

	returns:
		pointer			pointer to copy of the string
					in managed memory
		NULL			error (memory could not be gotten)

4.6.6	Get count of outstanding memory requests

	This call is usually used at the end of a program to determine
	if there are any memory leaks.  After freeing all allocated data,
	the program can use this call to determine if there are any
	allocations left over that the program has lost track of.

	int
	VSI_Memory_Count		(void)

	args:
		none

	returns:
		n			number of outstanding requests

4.6.7	Dump the memory allocation chain

	This call is usually used in conjunction with VSI_Memory_Count()
	at the end of a program.  If the count of outstanding allocations
	is not zero, this call can be used to dump them out in an attempt
	to determine the nature of the lost allocations.

	void
	VSI_Memory_Dump			(FILE *fp,
					 int dump_data,
					 int maxlen)

	args:
		fp			File stream to dump to (usually
					stdout or stderr)
					A NULL value will default to the
					"standard" stream (stderr or the
					file specified via the
					V_MALLOC_DBGFILE env variable).

		dump_data		FALSE if the actual data is NOT to be
					dumped with the entries

					TRUE to include the data with the entry

		maxlen			the max number of data bytes to dump
					for each entry (0 -> all)

	returns:
		none

5.	Tags

	The basic mechanism for passing data to/from the server is in
	the form of lists of tags.  A tag has the following form:

	typedef struct v_tag V_TAG;
	struct v_tag
	{
		V_TAG *	t_next;			/* pointer to next tag	*/
		V_TAG *	t_prev;			/* pointer to prev tag	*/

		char	t_name[V_TAG_NAMELEN];	/* tag name		*/
		char	t_data[V_TAG_DATALEN];	/* tag data		*/
		int	t_comp;			/* compare operation	*/
	};

	Both "name" and "data" fields are strings.  It is the user's
	responsibility to convert any data to a string form.

	Notes:

	1.	Values in the "name" fields are case-insensitive, but case
		is preserved in the "data" fields.

	2.	All the tag routines are designed so a user does not
		have to deal with the actual structure of a V_TAG.
		(Although macros are provided for C/C++ users.)

	3.	A tag-list is always allocated on the heap, and it is
		the user's responsibility to free any tag-lists created
		(via a call to VSI_Tag_Free()).

		Note that this means that a user should NEVER define
		an instance of a tag (e.g. V_TAG foo), he should only
		define pointers to a tag (e.g. V_TAG *foo).  Note
		that VB users can take advantage of the fact that a
		pointer can always be stored in a long, and just use
		that long as a reference.

	4.	There is no mechanism to create a unique instance of a
		tag, only to create a tag which is added to a list.
		A single tag entry may be created by adding it to an empty
		list.

	5.	There is no mechanism to "free" a particular tag, only
		to "free" an entire tag-list.  This is to avoid the problem
		of freeing just one entry of a list, and thus invalidating
		the next and previous pointers of other entries in the list.

	6.	There is no mechanism to "update" a tag entry in a list.
		The assumption is that a user creating a tag-list for submittal
		will just be adding entries to a list, and a user should not
		modify tag-lists returned from various server calls.

	7.	VSI_Tag_Add() will always set the "comp" field to V_COMP_EQUAL.
		Use VSI_Tag_Add_Comp() to set a different value for tag lists
		which are used in matching.

6.0	Sample code

	The following program demonstrates the use of some of the functions
	in this API.

	/*----------------------------------------------------------------
	 * Sample program to submit a fax
	 */
	#include "vsi.h"

	/*----------------------------------------------------------------
	 * Procedure to submit a fax
	 */
	int submit_fax (V_SYS *vsys,
			const char *tofnum,
			const char *subject,
			const char *cover,
			const char *filename,
			char *reqbuf,
			char *msgbuf)
	{
		int	rc;
	#if 1
		V_TAG *	tags = 0;

		/*--------------------------------------------------------
		 * Store values into tag-list
		 */
		tags = VSI_Tag_Add(tags, V_TAG_ENV_TOFNUM,    tofnum,   0);
		tags = VSI_Tag_Add(tags, V_TAG_ENV_SUBJECT,   subject,  0);
		tags = VSI_Tag_Add(tags, V_TAG_ENV_COVERPAGE, cover,    0);
		tags = VSI_Tag_Add(tags, V_TAG_ENV_FILELCL,   filename, 0);

		/*--------------------------------------------------------
		 * Submit the fax request
		 */
		rc = VSI_Server_Submit(vsys, reqbuf, tags, msgbuf);

		/*--------------------------------------------------------
		 * Free the tag-list
		 */
		tags = VSI_Tag_Free(tags, 0);
	#else
		/*--------------------------------------------------------
		 * alternate mechanism for submit
		 */
		rc = VSI_Server_Submit_Tags(vsys,
			reqbuf,
			V_TAG_ENV_TOFNUM,	tofnum,
			V_TAG_ENV_SUBJECT,	subject,
			V_TAG_ENV_COVERPAGE,	cover,
			V_TAG_ENV_FILELCL,	filename,
			0,
			msgbuf);
	#endif

		/*--------------------------------------------------------
		 * If an error occurred, msgbuf will contain the error msg.
		 * If no error occurred, reqbuf will contain the request-id.
		 *
		 * Return value is: 0 == OK,  -1 == error
		 */
		return (rc);
	}

	/*----------------------------------------------------------------
	 * main program
	 *
	 * usage: program [-n number] [-s subject] [-c coverpage] [-f file]
	 */
	int main (int argc, char **argv)
	{
		V_CTX *	vctx;
		V_SYS *	vsys;
		char	tofnum   [V_TAG_DATALEN];
		char	subject  [V_TAG_DATALEN];
		char	cover    [V_TAG_DATALEN];
		char	filename [V_TAG_DATALEN];
		char	reqbuf   [V_TAG_DATALEN];
		char	msgbuf   [V_MSG_LEN];
		int	rc;

		/*--------------------------------------------------------
		 * collect all arguments
		 */
		*tofnum		= 0;
		*subject	= 0;
		*cover		= 0;
		*filename	= 0;

		while (TRUE)
		{
			rc = VSI_Opt_Get(argc, argv, "?n:s:c:f:U:H:Z:", msgbuf);
			if (rc == EOF)
				break;

			switch (rc)
			{
			case '?':
				printf("usage: %s [options]\n", argv[0]);
				printf("options:\n");
				printf("  -n number    phone-number to call\n");
				printf("  -s subject   subject of fax\n");
				printf("  -c cover     coverpage to use\n");
				printf("  -f filename  filename to send\n");
				return (EXIT_SUCCESS);

			case 'n':
				strcpy(tofnum,   VSI_Opt_Argstr());
				break;

			case 's':
				strcpy(subject,  VSI_Opt_Argstr());
				break;

			case 'c':
				strcpy(cover,    VSI_Opt_Argstr());
				break;

			case 'f':
				strcpy(filename, VSI_Opt_Argstr());
				break;

			case 'U':
			case 'H':
			case 'Z':
				/* processed by VSI_Context_Load() */
				break;

			default:
				fprintf(stderr, "%s\n", msgbuf);
				return (EXIT_FAILURE);
			}
		}

		/*--------------------------------------------------------
		 * Get any fax parameters not specified on the cmdline.
		 *
		 * Note we are ignoring the problem with data input
		 * exceeding the length of a data buffer.
		 *
		 * Note also that gets() will remove the NL from the end
		 * of the input string.
		 */
		if (*tofnum   == 0)
			printf("Enter fax number: "),	gets(tofnum);

		if (*subject  == 0)
			printf("Enter subject   : "),	gets(subject);

		if (*cover    == 0)
			printf("Enter coverpage : "),	gets(cover);

		if (*filename == 0)
			printf("Enter filename  : "),	gets(filename);

		/*--------------------------------------------------------
		 * Create a context & log in with it
		 */
		vctx = VSI_Context_Load(argc, argv, 0, msgbuf);
		if (vctx == 0)
		{
			fprintf(stderr, "%s\n", msgbuf);
			return (EXIT_FAILURE);
		}

		vsys = VSI_Server_Login_By_Context(vctx, msgbuf);
		if (vsys == 0)
		{
			VSI_Context_Free(vctx, 0);
			fprintf(stderr, "%s\n", msgbuf);
			return (EXIT_FAILURE);
		}

		/*--------------------------------------------------------
		 * Submit the fax request.
		 *
		 * Note that a success result here does not mean that the
		 * fax was successfully sent, only that it was successfully
		 * submitted to the server.
		 */
		rc = submit_fax(vsys, tofnum, subject, cover, filename,
			reqbuf, msgbuf);

		/*--------------------------------------------------------
		 * log out & free the context
		 */
		VSI_Server_Logout(vsys, 0);
		VSI_Context_Free(vctx, 0);

		/*--------------------------------------------------------
		 * Check if any error was reported from the submit.
		 */
		if (rc)
		{
			fprintf(stderr, "%s\n", msgbuf);
		}
		else
		{
			printf("Request ID is %s\n", reqbuf);
		}

		return (rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
	}

7.0	The FAXAPI package

	The FAXAPI package is installed as a regular package via the
	install procedure.  This package will install the following
	files into the VSIFAX install directory:

	api/include
			vsi.h

	api/lib
		Unix:
			libvsi.a	static library

		Windows:
			libvsis.lib	MT static  link library
			libvsidlls.lib	MT dynamic link library
			libvsidlls.exp	MT dynamic link export file
			libvsidlls.dll	MT dynamic run-time library

			libvsid.lib	MD static  link library
			libvsidlld.lib	MD dynamic link library
			libvsidlld.exp	MD dynamic link export file
			libvsidlld.dll	MD dynamic run-time library

	api/samples
			makefile	makefile for all sample programs
			tiffcopy.c	sample program for TIFF file copying
			vdnload.c	sample version of vdnload
			vfx.c		sample version of vfx
			vfxcancel.c	sample version of vfxcancel
			vfxcvt.c	sample vfx program doing tag conversion
			vfxilog.c	sample version of vfxilog
			vfxinfo.c	sample version of vinfo
			vfxolog.c	sample version of vfxolog
			vfxpb.c		sample version of vfxpb
			vfxstat.c	sample version of vfxstat
			vfxtry.c	sample version of vfxtry

	api/docs
			faxapi.txt	this file

	In Unix, the install procedure will create the following
	symbolic links:

		/usr/lib/libvsi.a	->	$VSIFAX/api/lib/libvsi.a
		/usr/include/vsi.h	->	$VSIFAX/api/include/vsi.h

8.	Using the VSI-FAX C/C++ API

8.1	Using the API in Unix

	Use of this API is very simple, since all headers & libraries
	are present (as symlinks) in the standard directories.

8.1.1	Compiling

	A C/C++ program wanting to use this API simply needs to
	add the following line:

		#include "vsi.h"

	to any source files accessing the API.

	It is recommended that you include any system headers
	prior to including "vsi.h".  Note that "vsi.h" includes the
	system headers <stdio.h> and <sys/types.h>.

	If your compiler does not support the "const" keyword, you will
	have to add the following compiler option to the command line:

		-DV_NO_CONST

	or add the following line to the source file before including "vsi.h":

		#define V_NO_CONST

	If your compiler does not support function prototypes, you
	will have to add the following compiler option to the command line:

		-DV_NO_PROTOTYPES

	or add the following line to the source file before including "vsi.h":

		#define V_NO_PROTOTYPES

	As much as possible, the "vsi.h" header checks the compiler environment
	and sets these defines if necessary.  The header file looks for
	the following manifest defines:

		__STDC__	defines the standard C environment
		__GNUC__	defines the GNU environment
		__cplusplus	defines the C++ environment

	If any of these are set, it is assumed that both function prototypes
	and the const keyword are recognized.

8.1.2	Linking

	The link command would like like this:

		cc ... *.o ... -lvsi

	For example, a simple link might look like:

		cc main.o myfax.o -o faxapp -lvsi

	Note that you also have to specify any network libraries needed.

	The following are the network libraries needed for specific
	platforms:

		Solaris:		-lsocket -lnsl
		DG/86:			-lsocket -lnsl -lresolv
		NCR:			-lsocket -lnsl -lgen -lresolv
		SCO (Unixware):		-lsocket -lnsl -lgen -lresolv
		SCO (OpenServer):	-lsocket

	Thus, for a Solaris build, you could do:

		NETLIBS="-lsocket -lnsl" export NETLIBS

		cc main.o myfax.o -o faxapp -lvsi $NETLIBS

	or:

		VSILIBS="-lvsi -lsocket -lnsl" export VSILIBS

		cc main.o myfax.o -o faxapp $VSILIBS

8.2	Using the API in Windows

