\documentstyle{article}
\def\underscore{{\tt \char"5F}}
\catcode`_=\active \def_{\underscore} % use \sb for subscript
\begin{document}
\setlength{\parindent}{0mm}
\setlength{\parskip}{1 ex}

\def\tilde{\~{ }}

%
% Formats for various types of identifiers.
%

\def\filename{\em}
\def\proc{\em}

%
% Change page heading to correspond to current definitions.
%

\newcommand{\addtomargins}[1]{
	\addtolength{\oddsidemargin}{#1}
	\addtolength{\evensidemargin}{#1}
}

%\newenvironment{arglist}
\def\arg#1{ \item[\ \ {\bf #1}]\mbox{}\\}
\def\result{\arg{\rm return value}}
\newenvironment{arglist}{
	% ``arglist'' begin text
	Arguments:
	\begin{list}
		{ }
		{
			\setlength{\rightmargin}{\leftmargin}
			\setlength{\itemsep}{0mm}
		}
}{
	% ``arglist'' end text
	\end{list}
}

%
%

\newcommand{\decl}[1]{
	\vspace{2 ex}
	Entry: {\bf #1}\\
	% should set page headings here
}

\title{Discuss (subroutine foo)}
\author{Ken Raeburn}
\date{Printed: \today}

% ****************************************************************

\maketitle
\newpage

\section{Subroutines}

{\large This document is a draft, and is most definitely incomplete.}

Please keep in mind that the interfaces to these routines may change
in form.  In particular, handling of error-code return values may
change.  Some subroutine names may change for parity as extra
functionality is added to the library.  Many others will change for
conformance to the pattern that all Discuss library routines have
names which begin with ``{\tt dsc_}''.

\subsection{Reading and writing transactions.}

These routines are responsible for the interaction between the
user-level program and the Discuss servers.

One of the key data structures used by these routines (and others) is
the name_blk structure, which is defined in {\filename dsname.h} as:

\begin{verbatim}
typedef struct {
    char *hostname;
    char *pathname;
    char *user_id;
    char **aliases;
    char *spare;   /* "reserved for future expansion" */
    int status;
    int date_attended;
    int last;
} name_blk;
\end{verbatim}

The values currently defined which may be used in the ``status'' word
(also defined in {\filename dsname.h)} are:

\begin{verbatim}
#define DSC_ST_CHANGED (0x0001)
#define DSC_ST_DELETED (0x0002)
\end{verbatim}

If the \verb!DSC_ST_DELETED! flag is set, the meeting will not be
written back out to the user's {\filename .meetings} file.

Other useful typedef's are:

%
%       DOCUMENT THESE!!!!!!!!!
%

\begin{verbatim}
/* "types.h", included by "interface.h" */
typedef int trn_nums;	/* what a transaction number could be */
typedef int date_times;	/* time format */
typedef short bool;
typedef char *mtg_names; /* what a meeting name is */
typedef char *pathnames; /* Fixed, or what? */
typedef int faddr;	/* addr in a file (absolute offset) */
typedef short slen;	/* length of a string */

/* "interface.h" */
typedef struct {
    int version;		 /* version of this structure */
    trn_nums current;	 /* trans # of this transaction */
    trn_nums prev;		 /* trans # of previous non-deleted trans */
    trn_nums next;		 /* etc, etc. */
    trn_nums pref;
    trn_nums nref;
    trn_nums fref;
    trn_nums lref;

    int chain_index;	/* index of trn in chain. Fref is 1 */
    date_times date_entered; /* date/time entered */
    int num_lines;	/* # lines in transaction */
    int num_chars;	/* # chars in transaction */
    char *subject;	/* subject of transaction */
    char *author;	/* author of transaction */
} trn_info;

/* Same as above, but added `flags' field.  This is silly. */
typedef struct {
    int version;		 /* version of this structure */
    trn_nums current;	 /* trans # of this transaction */
    trn_nums prev;		 /* trans # of previous non-deleted trans */
    trn_nums next;		 /* etc, etc. */
    trn_nums pref;
    trn_nums nref;
    trn_nums fref;
    trn_nums lref;

    int chain_index;	/* index of trn in chain. Fref is 1 */
    date_times date_entered; /* date/time entered */
    int num_lines;	/* # lines in transaction */
    int num_chars;	/* # chars in transaction */
    char *subject;	/* subject of transaction */
    char *author;	/* author of transaction */
    int flags;          /* miscellaneous flags */
} trn_info2;
/* meanings of flags */
#define TRN_FDELETED 1  /* transaction deleted? */
#define TRN_FLAG1    2  /* misc bit, for user interpretation */

typedef struct {
    int version;		/* version of this structure */
    pathnames location;		/* location of actual meeting */
    mtg_names long_name;	/* long name of meeting */
    char *chairman;		/* #1 chairman of meeting */
    trn_nums first,last;	/* first & last trns of mtg */
    trn_nums lowest,highest;	/* first & last non-dl trns */

    date_times date_created;	/* date meeting created */
    date_times date_modified;	/* last modification of meeting */

    bool public_flag;		/* if mtg is public */
    char *access_modes;		/* Access modes we have to this mtg. */
} mtg_info;

\end{verbatim}

There is also another package, called ``tfile'', in use, which allows
for a stdio-like I/O interface with the added functionality of
callback procedures called from within the library.  This is described
in another section.

\decl{dsc_announce_mtg}

Function: This procedure places a specially-formatted announcement of
a Discuss meeting into another Discuss meeting.  These announcement
transactions are the common means of sharing information concerning
new meetings.

Syntax:\begin{verbatim}
int dsc_announce_mtg (name_blk * nbpsrc,
                      name_blk * nbpdest,
                      int public,
                      tfile tf,
                      int * trn_no,
                      int * code_ptr);
\end{verbatim}

\begin{arglist}
\arg{nbpsrc}
is the new meeting which is to be announced.

\arg{nbpdest}
indicates the meeting in which the announcement is to be placed.

\arg{public}
is non-zero if the meeting is to be announced as ``public''.

\arg{tf}
is the source of the text for the main body of the announcement.

\arg{trn_no}
will contain, on successful return, the transaction number of the new
transaction in the announcement meeting.

\arg{code_ptr}
will contain a standard error code on return.  It will be zero if no
error occurred, non-zero otherwise.

\end{arglist}

\decl{dsc_add_trn}

Function:  Dsc_add_trn adds a new transaction to a Discuss meeting,
either as the initial transaction in a new chain, or as a reply to a
previous transaction.

Syntax:\begin{verbatim}
int dsc_add_trn(name_blk * nbp,
                tfile text,
                const char * subject,
                int reply_trn,
                int * result_trn,
                int * code_ptr)
\end{verbatim}

\begin{arglist}
\arg{nbp}
meeting in which the new transaction should be placed.

\arg{text}

\arg{subject}

\arg{reply_trn}
Transaction being replied to.

\arg{result_trn}
Transaction number of new transaction.

\arg{code_ptr}

\end{arglist}

\decl{dsc_get_trn_info, dsc_get_trn_info2}

Syntax:\begin{verbatim}
int dsc_get_trn_info(name_blk * nbp,
                     trn_nums trn,
                     trn_info * info,
                     int * code_ptr);

int dsc_get_trn_info2(name_blk * nbp,
		      trn_nums trn,
                      trn_info2 * info,
                      int * code_ptr);
\end{verbatim}

\begin{arglist}
\arg{nbp}
the current meeting.

\arg{trn}
the transaction number for which information should be retrieved.

\arg{info}
where to put the info.

\arg{code_ptr}
same old stuff\ldots.

\end{arglist}

Retrieves information on a given transaction.

\decl{dsc_set_trn_flags}

Syntax:\begin{verbatim}
int dsc_set_trn_flags (name_blk * nbp,
 		       trn_nums trn,
		       int flags,
      		       int *code_ptr);
\end{verbatim}

\begin{arglist}
\arg{nbp}

\arg{trn}

\arg{flags}

\arg{code_ptr}

\end{arglist}

May return {\tt NO_SUPPORT} if the operation is not supported by the
remote server.

\decl{dsc_delete_trn}

Syntax:\begin{verbatim}
int dsc_delete_trn(name_blk * nbp,
                   trn_nums trn,
                   int * code_ptr);
\end{verbatim}

\decl{dsc_retrieve_trn}

Syntax:\begin{verbatim}
int dsc_retrieve_trn(nbp, trn, code_ptr);
\end{verbatim}

\decl{dsc_get_mtg_info}

Syntax:\begin{verbatim}
int dsc_get_mtg_info(name_blk * nbp,
                     mtg_info * info,
                     int * code_ptr);
\end{verbatim}

\decl{dsc_get_trn}

Syntax:\begin{verbatim}
int dsc_get_trn(name_blk * nbp, trn_nums trn,
                tfile dest, int * code_ptr);
\end{verbatim}

\decl{dsc_remove_mtg}

Syntax:\begin{verbatim}
int dsc_remove_mtg(name_blk * nbp, int * code_ptr);
\end{verbatim}

\decl{dsc_updated_mtg}

Syntax:\begin{verbatim}
int dsc_updated_mtg(name_blk * nbp,
                    int * updated,
                    int * code_ptr);
\end{verbatim}

\decl{dsc_whoami}

Syntax:\begin{verbatim}
int dsc_whoami(name_blk * nbp, ident, int * code_ptr);
\end{verbatim}

\subsection{Access control in Discuss meetings.}

Structures used:

\begin{verbatim}
typedef struct _acl_entry {
    char *principal;	/* The principal */
    char *modes;	/* The allowed modes */
} acl_entry;

typedef struct _acl {
    int acl_length;
    acl_entry *acl_entries; /* Members of list (gets realloc'ed) */
} Acl;
\end{verbatim}

\decl{dsc_get_acl}

Syntax:\begin{verbatim}
int dsc_get_acl();

(void) dsc_get_acl(nbp, code_ptr, list)
\end{verbatim}

\decl{dsc_get_access}

Syntax:\begin{verbatim}
int dsc_get_access();

(void) dsc_get_access(nbp, principal, modes, code_ptr)
\end{verbatim}

\decl{dsc_set_access}

Syntax:\begin{verbatim}
int dsc_set_access();

(void) dsc_set_access(nbp, principal, modes, code_ptr)
\end{verbatim}

\decl{dsc_delete_access}

Syntax:\begin{verbatim}
int dsc_delete_access();

(void) dsc_delete_access(nbp, principal, code_ptr)
\end{verbatim}

\subsection{Interface to user's {\filename .meetings} file.}

These routines provide an interface to the user's {\filename
.meetings} file, where Discuss stores all of the information it has
concerning meetings the user is interested in.  This file is stored in
a format not unlike the {\filename /etc/passwd} file, containing
alphanumeric and numeric fields separated by colons.

There is much functionality which is not yet provided by this small
set of routines, and some do not yet conform to the ``dsc_'' standard
of subroutine naming used elsewhere in the library.

\decl{dsc_expand_mtg_set}

Function: This procedure expands a Discuss meeting name (possibly a
starname) into a list of names, in the context of the users'
{\filename .meetings} file.

Syntax:\begin{verbatim}
void dsc_expand_mtg_set (const char * user_id,
                         const char * mtgname,
                         name_blk ** set,
                         int * num,
                         int * result);
\end{verbatim}

\begin{arglist}
\arg{user_id}
is the name of the user whose {\filename .meetings} file should be
referenced for the expansion of the supplied name.  If this value is
NULL, the user's own {\filename .meetings} file is used.  (Input)

\arg{mtgname}
is the meeting name (or starname) to be expanded.  (Input)

\arg{set}
indicates where the pointer to the resulting values should be stored.
These values are allocated by this routine, and should be freed when
no longer needed.  (Output)

\arg{num}
indicates where the number of expanded names should be returned.
(Output)

\arg{result}
is the location of a standard system error code, to be filled in by
this routine.  (Output)

\end{arglist}

This routine performs the first portion of the lookup, translating
mtgname in the context of the user_id into zero or more name_blk
structures.

Set is assigned the address of an array of name_blk structures; this
array is allocated by this routine and should be freed when no longer
needed.  Num is set to the number of matches found for the name
mtgname among meeting long_names and the user's aliases for meetings.
Result is set to zero if the routine executes successfully (this
includes the case of no matches for mtgname), non-zero otherwise.

\decl{dsc_update_mtg_set}

Function: This procedure updates the entries in a {\filename .meetings}
file to correspond with the data supplied.

Syntax:\begin{verbatim}
void dsc_update_mtg_set (const char * user_id,
                         name_blk * set,
                         int num,
                         int * result);
\end{verbatim}

\begin{arglist}
\arg{user_id}
as above.

\arg{set}
contains the data to be stored in the user's {\filename .meetings}
file.

\arg{num}
indicates how many name_blk structures are supplied.

\arg{result}
as above.

\end{arglist}

This routine updates the user's {\filename .meetings} file information,
replacing the entries already there for the specified meetings.
Information about meetings not supplied to this routine is unchanged.
If a name_blk structure supplied has the ``deleted'' flag set, the
meeting info will not be retained in the new version of the
{\filename .meetings} file.

The {\filename .meetings} file is updated by writing a new file,
{\filename .meetings\tilde}, containing the new data, and replacing the
original file with an atomic rename() system call.

\decl{dsc_get_mtg}

This routine is available for use when a single expansion of a name is
desirable.  It returns the first expansion of the starname, if there
is one.  ({\bf BUG:}  This should probably return an entry only if it is
a unique match.)

Syntax:\begin{verbatim}
int dsc_get_mtg (const char * user_id,
                 const char * name,
                 name_blk * nbp,
                 int * result);
\end{verbatim}

\begin{arglist}
\arg{user_id}
as above.  (Input)

\arg{name}
the name to be expanded.  (Input)

\arg{nbp}
the location in which to store the name_blk record, if any is found.
(Output)

\arg{result}
as above.  (Output)

\end{arglist}

\decl{find_rc_filename}

Find_rc_filename will attempt to locate the user's own
{\filename .meetings} file.

Syntax:\begin{verbatim}
int find_rc_filename (void);
\end{verbatim}

\begin{arglist}
\result
indicates whether this routine succeeded in finding a writable
{\filename .meetings} file.  If so, this value is zero; otherwise, it
is an error code.

\end{arglist}

	This function requires that the user have an entry in the
local {\filename /etc/passwd} file; this entry is looked up once and
cached for reference in future calls.

	The order of search is: {\filename \$MEETINGS} environment
variable; {\filename \$HOME/.meetings}; {\filename \tilde
user/.meetings}.  If the {\filename MEETINGS} environment variable is
set, the home directory will not be checked; if {\filename HOME} is
defined, the password file entry will not be used to locate the file
(though the user name from the password file is retained as an
identifier).

	This routine only accepts a file which are writable by the
user.  If the file found is not writable, an error is returned.

\subsection{Tfiles}

A bit of a crock to get around stdio not providing call-back I/O
modules.  The tfile generation routines and some pre-defined routines
are described here.

Definitions used:

\begin{verbatim}
struct trecord {
    int (*proc)();		/* file proc */
    int size;			/* file size */
    char *infop;		/* pointer to misc info */
    int info;
};

typedef struct trecord *tfile;

#define TFOPEN 1
#define TFCLOSE 2
#define TFREAD 3
#define TFWRITE 4
#define TFDESTROY 5
#define TFCONTROL 6

/* TF Control orders (start high just for fun) */

#define TFC_FORCE_NL 15
\end{verbatim}

\decl{tcreate}

Function:  Creates a tfile object which uses a specified procedure to
perform its operations.

Syntax:\begin{verbatim}
tfile tcreate (int tfs,
               void * infop,
               int info,
               int (*proc)());
\end{verbatim}

\begin{arglist}
\arg{tfs}
the size of the tfile. (???)

\arg{infop}

\arg{info}

\arg{proc}
the procedure to be called in order to perform operations on the
tfile.
\end{arglist}

\decl{tread}

Function: Read data from a tfile.

Syntax:\begin{verbatim}

int tread (tfile tf,
	   char *bufp,
	   int num_read,
	   int *result);
\end{verbatim}

\begin{arglist}
\result{int}
number of characters read.
\end{arglist}

\decl{twrite}

Function: Write data to a tfile.

Syntax:\begin{verbatim}

int twrite (tfile tf,
	    const char * bufp,
	    int num_write,
	    int result);

\decl{tclose}

Function: Close a tfile.

Syntax:\begin{verbatim}

int tclose (tfile tf, int * result);

\end{verbatim}

\decl{tdestroy}

Function: Destroys a tfile, freeing allocated memory associated with
the tfile.

Syntax:\begin{verbatim}

tfile tdestroy (tfile tf);

\decl{tfsize}

Function: Returns the number of characters in a tfile.

Syntax:\begin{verbatim}

int tfsize (tfile tf);

\end{verbatim}

Some tfile creation routines are provided.  One such is the UNIX
tfile, which operates on a file descriptor provided by the programmer.

\decl{unix_tfile}

Function: Creates a tfile object wrapped around a UNIX file
descriptor.

Syntax:\begin{verbatim}
tfile unix_tfile(int fd);
\end{verbatim}

\begin{arglist}
\arg{fd}
the file descriptor number to be used.
\end{arglist}

There's a memory one somewhere, but I don't recall the info about
it\ldots.

\end{document}
