This directory contains several example files containing service
implementations.  All of these files are source code in the TCL language,
created by John Ousterhout at the University of California at Berkeley.
The basic TCL distribution is included in the ServiceMail(tm) toolkit, and
resides in ~/src/tcl; a manual page on the language is in
~/src/tcl/doc/Tcl.man.

Before building your own services, we recommend that you understand the
examples in this directory.  That way, you can start from one of those
examples and modify it for your application.

The examples use the pair of functions "setfield" and "getfield" quite
a bit.  They are not part of basic TCL; rather they are defined in the
file ~/src/mesh/init.tcl and preloaded into the TCL interpreter.  They
provide a data structure that is most like LISP association lists, and
they are like C structs in the sense that they provide keyworded
sub-structure to certain variables.  Such variables are lists where
the even-numbered elements (numbering from zero) are field names, and
the odd-numberbed elements are field values.  An example structure is
{TYPE text SUBTYPE plain FILE /tmp/abc}.   Setfield and getfield are
used to add and query name/value pairs, respectively.  That is, the
command [setfield vname NAME value] literally appends NAME and value
to the list variable named "vname", and the command [getfield $vname NAME]
returns the value corresponding to field NAME.  (As currently implemented,
setfield does not remove any previous uses of the field NAME, but getfield
will do the right thing and use the value nearest the end of the list.)

The Multimedia E-Mail Shell (Mesh) invokes a service with three arguments:

  switches -- a list of parameters that appeared after the service name
    on the Subject: line.

  envelope -- a name/value list that defines FROM, REPLYTO, MESSAGEID,
    and SERVICE (including switches) from the incoming message.

  inputs -- a name/value list that describes the body of the incoming
    message, including in what files to find the actual content; the
    name/value list defines the TYPE, SUBTYPE, and PARAMS (as a recursive
    name/value list) fields from the MIME Content-Type: line, and the
    DESCRIPTION field from the MIME Content-Description: line (if there
    was such a line in the header).  If the TYPE is "multipart", then
    there will be one more field PARTS, which is a list of name/value
    lists that each define a recursive MIME type as above.  Any TYPE
    other than multipart will define a FILE field (which names a file
    that contains the actual content), and an ID field (if a Content-Id:
    was supplied).

Services will usually send out at least one mail message, even if only
as an acknowledgement.  Mesh provides the builtin TCL procedure named
"mailout" for this purpose.  Mailout takes two arguments:  the outgoing
envelope and a description of the outgoing body.  The outgoing envelope
is a name/value list defining the fields TO, INREPLYTO, SUBJECT, and
CC (TO and SUBJECT are mandatory, the others aren't).  Since most
outgoing envelopes will be a straightforward translation of the incoming
envelope, there exists a function "turnaround" that creates an outgoing
envelope from an incoming one.  That is, you will usually wanted to
call mailout in the following way:

  mailout [turnaround $inenvelope] $outbody

The second argument is a description of the body of the outgoing message.
Like the inputs argument described above, the outbody is a name/value
list that defines the TYPE, SUBTYPE, PARAMS, DESCRIPTION, PARTS (in the
case of multipart types) or FILE and ID (for other types) fields. However,
there are two important differences.  First, there is an alternative
field to FILE, called STRING, which literally defines the contents of
the body (if both are specified, FILE overrides STRING). Second, some
fields have defaults, as specified below:

  TYPE -- defaults to "text"

  SUBTYPE -- defaults to "plain"

  PARAMS -- if the TYPE is text, defaults to {charset us-ascii}

  STRING -- defaults to "Your message was processed."

  ID -- defaults to the value of FILE, if specified

Therefore, a service rarely needs to specify all fields.
