-*-Text-*-  Documentation of MIDAS .INSRT libraries.

File: LIB	Node: Top	Up: (DIR)

.INSRT'able Subroutine Libraries for MIDAS Programs

ITS now has several libraries of commonly useful subroutines
for MIDAS programs.  This file tells how to use them and
what the existing libraries do.

* Menu:

* General::	What libraries expect from their callers

These libraries exist now

* RFN::			Reading and printing filenames
* DATIME::		Reading, printing and converting dates and times
* NETWRK::		Accessing the ARPANET
* LSRTNS::		Accessing the INQUIR data base
* FORMAT: (SYSENG;FORMAT)	Output made easy.  Like Lisp's FORMAT function.
* MSGS: (SYSENG;MSGS)	Accessing the :MSGS date data base
* BYELIB: (SYSENG;BYELIB)	Obtaining epigrams a la BYE

File: LIB,   Node: General,   Up: Top, Previous: Top, Next: RFN

The Calling Conventions of the .INSRT'able Libraries

  MIDAS libraries are designed to be requested with a .INSRT, because
of the fact that MIDAS programs are usually absolute assemblies.
A library named FOO resides (unless otherwise stated) in the file
SYSENG;FOO > on all ITS machines, and can be requested with
.INSRT SYSENG;FOO

  Every library clothes itself in a MIDAS symbol block named after the
library.  Almost all of the symbols of the library live within this
block, and thus cannot interfere with the calling program.  Some
libraries define their normal entry points in the outer block, while
others define NO symbols except in their own block.  Routines in
libraries of the latter sort must be referred to in MIDAS with an
explicit block name, as in RFN"PFN for the PFN routine in the library
RFN. 

  Because libraries are included in the assembly with .INSRT,
they inherit (unless you specify otherwise) the symbol definitions
of the program that is calling them.  Subroutines use specific
accumulator names for their arguments, rather than specific
accumulator numbers, and they expect to be called with a PUSHJ P,
where P is whatever the .INSRT'ing program defines it to be.

  Most libraries require a block of four or five accumulators, named
A, B, C, and D, and perhaps E.  Usually, the code assumes that those
accumulators are consecutive, and the caller should assume that this
is required.  Some libraries require another pair of consecutive
accumulators named T and TT.  Of course, every library requires a
stack named P.  Each library will say exactly which accumulators it
requires and which must be consecutive.

  If your existing program does not provide suitably named
accumulators, you can still use the library if you define the required
names within the library's symbol block.  For example, if your program
defines the accumulator names A=1, B=2, C=3, T=4, D=5,, while the
library FOO insists on A through D consecutively, you can do

	FOO"D=4

causing the name D within FOO to refer to the program's accumulator T.
Within FOO, A through D are now consecutive, but D outside of FOO
continues to have its old value of 5.  The only disadvantage of this
is that arguments to FOO's routines cannot be set up in D=5, but must
be placed in T or FOO"D, which are names for 4.

  Library subroutines are almost always intended to be called
with a "PUSHJ P,".  Each subroutine's documentation will specify
whether it can skip return, what arguments are expected in which
accumulators, which values are to be counted on in which accumulators,
and which accumulators are randomly clobbered.  Accumulators in the
set used by the library which are not mentioned in the documentation
may be used temporarily if they are saved and restored.  Accumulators
not among those "used by the library" are not touched even for an
instant. 

  Some libraries assume that the symbols CPOPJ and POPJ1 have been
defined by the caller in the standard manner:

	POPJ1:	AOS (P)
	CPOPJ:	POPJ P,

They may also expect the user to define specifically named routines to
serve as subroutines for the library to call.  This is to allow the
user to customize the behavior of the library.  Each library says
which such symbols are required by which routines.  Of course, all
libraries assume that the predefined symbols of MIDAS are available. 
If you redefine them carefully, you may succeed in faking the
libraries into doing something interesting.  If you redefine them
carelessly, you will lose. 

  Because many callers will not need all the routines in a library,
the caller can specify which parts of the library should be assembled
by defining some control parameters before .INSRT'ing the library.
Such parameters have names starting with "$$".  Each library has its
own set of control parameters, which it documents;  those not defined
will usually be taken to be zero, and the associated features NOT
assembled.  Thus, the caller must set to one the control parameters
associated with the routines he wishes to use (some libraries may use
the opposite default, assembling all routines except those whose
control parameters are set to zero by the caller).  Since it cannot be
assumed that no two libraries will have control paramaters with the
same name, it is good practise to make the control paramaters local to
the library's symbol block, as in:

	RFN"$$RFN==1		    ;Assemble the RFN routine.
	RFN"$$PFN==1		    ;Assemble the PFN routine.

  Libraries know which parts depend on other parts as subroutines, and
automatically assemble the subroutines of any part that is explicitly
requested. 

  All code assembled by libraries at the point where they are
.INSRT'ed is pure code.  Most libraries create impure static storage
using .SCALAR and .VECTOR.  A library that never uses them and has no
static variables will say so;  others should be assumed to use them.

  Routines that use or return a text string generally expect to find a
byte pointer to the beginning of it in D.  They then advance D as they
read or write the text, returning with D pointing at the last
character read or written.  Some routines that write text will store a
null character after the last real character of output, to make the
string ASCIZ;  D will not be advanced past the null.

File: LIB	Node: RFN, Up: Top, Previous: General, Next: Datime

The RFN library contains filename reading and printing routines.

ACS:	This file requires acs A, B, C, D, and E, which NEED NOT be
	consecutive, and P.

VARS:	This file defines no static variables.  It is entirely pure.

EXITS:	Required exits can include SWITCH, RSIXTP, PSIXTP, MNAME,
	and MSNAME, depending on the routines assembled.

ENTRIES:
	The entries defined are RFN, PFN, PFNMCH, and PFNBRF, and
	RMNAME.  They are defined only in the symbol block RFN.
	None of them skips.

The control parameters all default to zero:
	$$RFN enables the filename reading routines.
	   Requires the RSIXTP be defined.
	   $$SWITCH enables the portion that handles switches.
	      Requires that SWITCH be defined.
	   $$RUC inhibits the definition of the RUC subroutine, used
	      for reading input, so that the user can define it.
	      Requires that RUC be defined.
	$$PFN enables the PFN filename printing routine.
	   Requires that PSIXTP be defined.
	   $$PFNBRF as well enables the PFNBRF printing routine.
	      Requires that MSNAME be defined.
	   $$MNAME enables the PFNMCH printing routine.
	      It also enables the RMNAME routine that sets up MNAME.
	      Requires that MNAME be defined.

A Filename Block is a four-word block which holds the four names of a
	file in the order DEVICE, FN1, FN2 and SNAME, each as a word
	of SIXBIT.  These words are in the same order as the arguments
	to a symbolic OPEN call.


Filename Reading:  $$RFN==1 to enable.

  The routine RFN"RFN parses a file specification.  It expects in D a
byte pointer to the text, and in B the address of a filename block in
which to store the parsed names.  On return, B and C are unchanged,
while D is updated to point at the terminating character, which is
left in A.  E contains flags indicating which of the four names were
specified by the filespec.  The other words of the filename block are
not changed.  The flags are bits 3.1, 3.2, 3.3 and 3.4 set to indicate
that the device, fn1, fn2 and sname, respectively, were specified.
These flags are best written as 1_RFN"DEV, 1_RFN"FN1, 1_RFN"FN2,
and 1_RFN"SNM.

  Filenames as parsed by RFN"RFN recognize the special characters
Space, Colon for the device name, Semicolon for the sname, ^X for
referring to the default fn1, ^Y for referring to the default fn2, and
^Q for quoting a special character to include it in a filename.
All control characters other than ^Q, ^X and ^Y terminate the
filespec.

  Additional filespec terminating characters are specified by the
caller by defining the routine RSIXTP, which should skip if the
character in A is one which should terminate the filespec.

  Default filenames can be supplied by storing them in the filename
block before calling RFN.  For more control, you can examine the flags
returned in E to find which names were specified, and default the
others.  However, ^X and ^Y will always take their defaults from the
contents of the second and third words of the filename block.

  RFN reads characters from the input string using the subroutine
RFN"RUC.  The caller may set $$RUC==1 and define RUC himself, to cause
RFN to get its input from another source.  RUC should return the next
input character in A, converted to upper case, and not skip.


Filename Reading with Switches:  $$SWITCH==1 to enable

  Setting $$SWITCH causes RFN"RFN to call a routine SWITCH, which the
caller must define, whenever a switch is encountered.  A slash is
followed by a single switch, while a "(" is followed by several
switches, terminated by a ")".

  The caller's SWITCH routine is called once for each slash, and
several times as appropriate for each "(".  It should read and process
one switch, assuming that the first character of the switch is in A.
If it returns without skipping, RFN assumes that the last character
read was part of the switch.  If SWITCH skips, RFN assumes that the
last character read, which must be left in A, was a terminator that
was not part of the switch.  This terminator is reprocessed.
SWITCH must not clobber C or E.

  Note that slash and "(" are not recognized by RFN unless RSIXTP
skips for them.  This gives the caller run-time control over whether
to accept switches.


Filename Printing:  $$PFN==1 to enable.

  The routine RFN"PFN takes a filename block address in B and prints
the filenames, depositing the text down the byte pointer in D, which
is updated.  No accumulator other than D is changed.

  PFN knows how to put ^Q in front of characters that need it.
It requires that the user define a routine PSIXTP that takes a
character in A and skips if that character requires a ^Q.  However,
the characters Space, Colon and Semicolon get ^Q's and are not passed
to PSIXTP.  Thus, PSIXTP can be the same routine as RSIXTP.

  The routine RFN"PFNBRF is similar to PFN except that it suppresses
mention of the device name if it is DSK, or the sname if it is the
default one.  The user must set $$PFNBRF==1 to enable this, and must
define MSNAME to contain the default sname.


Filename Printing using AI: instead of DSK:  $$MNAME to enable.

  The routine RFN"PFNMCH prints filenames just like PFN except that a
device name of DSK is printed as the running machine's name.
The user must define a location MNAME and store the machine's name
there.  A routine RFN"RMNAME is provided which initializes MNAME
correctly.

File: LIB,   Node: DATIME,   Up: Top, Previous: RFN, Next: NETWRK

The DATIME library contains routines for handling dates and times.

ACS:	A, B, C, D and E, which must be consecutive, as well as P.

VARS:	ENGDTP and TMSYST are internal static variables.

EXITS:	None.

The control parameters all default to zero:
	$$OUT enables output as mm/dd/yy hh:mm:ss
	$$OUTF enables output as, eg, 3 Mar 1975  1020
	   $$OUTZ as well enables routines for outputting time zone
	      (EST vs EDT).
	$$IN enables input of the form mm/dd/yy hh:mm:ss
	$$INF enables flexible input allowing named months
	$$ABS enables routines to convert dates in y-m-d format
	   to number of days since 1900, routines to add and subtract
	   dates, etc.
	   $$SVNG enables routines to determine whether daylight
	      savings time was in effect at a given time.
	   $$UPTM enables conversion of time into how long ITS had
	      been up at that time.

Data Formats:
	A date and time are usually expressed in the form of a time
	word.  A time word is a single word containing the time in
	units of half a second, and one century worth of date.  It is
	also known as the "ITS disk-format date/time".
	It has these fields:

	; Mask    Field     Bits	Range	Units   Actual Range

	TM%SEC== 777776    ; 2.9-1.2	0-131K	seconds	0-86399.
	TM%DAY==     37,,0 ; 3.5-3.1	0-31	days	1-31
	TM%MON==    740,,0 ; 3.9-3.6	0-15	months	1-12
	TM%YR==  177000,,0 ; 4.7-4.1	0-127	years	0-127
					relative to 1900 (1900-2027)

	Those four symbols, and byte pointer left halves named
	TM$YR, TM$MON, TM$DAY and TM$SEC, are defined in DATIME.
	So you can do LDB B,[DATIME"TM$YR,,A] to extract the year
	from A into B, for example.


  One routine which is always assembled is TIMGET, which returns the
current time as a time word in A.  -1 is returned if ITS doesn't know
what the time is.


Output of date/time:

  $$OUT==1 enables the routines DATASC, TIMASC and TWDASC which output
a date and time from a time word in A in the format mm/dd/yy hh:mm:ss,
stuffing the text down the byte pointer in D.  A null character is
deposited at the end of the string, but the byte pointer in D is not
advanced over it.  B and C are untouched.

  DATASC outputs just the date, TIMASC outputs just the time,
and TWDASC outputs the date and time with a space between.
All three place a null character after the text they output.

  $$OUTF==1 enables the routine TIMENG which, called like TWDASC,
outputs the date and time in the format "7 AUG 1976  0831".
There is also DATENG, called the same way, which outputs only the
date, in the form "7 AUG 1976".

  $$OUTZ==1 enables routines TIMSTD and TIMEXP which know about the
difference between standard time and daylight saving time.
They are both called just like TIMENG.  But whereas TIMENG simply
outputs the hour it is told, without worrying about the time zone,
TIMSTD assumes that the time was specified in EST, and converts it to
EDT if EDT was in effect at that time, and then prints the time with
EDT or EST as appropriate.
TIMEXP, on the other hand, assumes that the time was specified in
whichever time, EST or EDT, was in effect at that time.  It prints the
time like TIMENG, followed by EST or EDT as appropriate.

  $$OUTT==1 enables the tables DOWTAB and DOWLNG of names of days of
the week.  Each is seven words long.  DOWTAB's words contain an ASCIZ
string each, such as ASCIZ/SUN/ in the first word.  DOWLNG's words
contain pointers to ASCIZ strings of the full names of the days.
DOWTAB and DOWLNG should be used in conjunction with TIMDOW, which is
assembled when $$ABS==1.  Another table, MONTAB, contains pointers to
the ASCIZ full names of the months, indexed by month number (Jan = 1).


Input of date/time:

  $$IN==1 enables the routine ASCTWD which is the inverse of TWDASC.
It accepts in D a pointer to an ASCIZ string, and returns a time word
in A, advancing D past the text that was used.

  $$INF==1 enables the "flexible format" input routines which accept
such input formats as "march 5, 1971" and "3mar71" for the date, and
"0800", "08:00" "0800:00" and "08:00:00" for the time.  They take a
byte pointer in D pointing to the string, and advance it past the text
that they use.  The routines are ENGTWD, ENGTIM and ENGDAT.
ENGTWD reads a date and a time, whereas ENGDAT reads just a date and
ENGTIM reads just a time.


Addition and Subtraction of Times:  $$ABS==1 to enable.

  The time word format, while convenient for I/O and for comparison of
times, is not suitable for computation of the number of days or
seconds between two instants.  The routines enabled by $$ABS allow you
do to that sort of thing.

  TIMADY converts the date in the time word in A to the number of days
past Jan 1 1900, which is returned in A.  TIMSEC converts the date and
time in the time word in A to the number of seconds since Jan 1, 1900,
returned in A.

  ADYTIM and SECTIM perform the inverse transformations, of an
absolute number of days or seconds since 1900 into a time word.  The
argument and value are again in A.

  Slightly higher level routines are TIMADD and TIMSUB.  TIMADD adds
the number of seconds in B to the time word in A, returning the new
time as a time word in A.  TIMSUB returns in A the number of seconds
from the time in B to the time in A, both arguments being in the form
of time words. 

  TIMDOW takes a time word in A and returns in B the day-of-the-week
index (Sunday = 0) of that date.

  TIMNET takes a time word in A and returns in A the same time in
32-bit Arpanet standard format.

  The routines UPTIME and UPINI can convert a time word into the
system up-time in 30'ths of a second.  They are assembled if
$$UPTM==1.  UPTIME takes a time word in A, and returns the
corresponding system up-time.  This works only for times since the
system came up, of course.  Before using UPTIME, UPINI must be called
to initialize the variable TMSYST.


Daylight Savings Time:  $$SVNG==1 to enable.

  The routines ODAYL and IDAYL know at which times daylight savings
time is in effect.

  ODAYL takes a time word in A, assumed to be standard time, and skips
if standard time was really in effect at that time.  Thus, it can be
used to decide whether the time ought to be converted to daylight time
before being printed.

  Such conditional conversion can be done this way:

	MOVEI B,3600.
	PUSHJ P,DATIME"ODAYL	;If daylight time now in effect,
	 PUSHJ P,DATIME"TIMADD	;convert to daylight time before printing.

  IDAYL takes a time word in A, which might be either standard or
daylight time, whichever was in effect at that time.  Thus, it is the
sort of quantity that you get if you simply ask for the current time
or a file's creation time and do not convert the zone.  IDAYL skips if
the argument supplied is presumably standard time.

  This is useful for converting such an unspecified-zone quantity
specifically into standard time, which can be done this wat:

	MOVNI B,3600.
	PUSHJ P,DATIME"IDAYL	;If at a time when daylight time is in use,
	 PUSHJ P,DATIME"TIMADD	;convert daylight to standard.

File: LIB,   Node: NETWRK,   Previous: DATIME, Up: Top, Next: LSRTNS

SYSENG;NETWRK > Contains ARPANET-Handling Routines

NETWRK is the oldest library, and makes more demands on the caller
than the others do.  *Note NCP: (.INFO.;ITS NCP)*, for other
information that you will need for writing programs that use the
ARPANET.

ACS:	A, B, C, D, and E, which need not be consecutive, and
	T and TT, which must be consecutive, and P.
	All main entry points clobber T and TT.

VARS:	SKTBAS and HSTADR are internal static variables.

EXITS:	CPOPJ and POPJ1 must have the standard definitions.
	GETCHR, PUTCHR, SPCHAN and DEBUG may be required.

	PUTCHR is used by several routines to "print" a character.
	   It should expect the character in T, and not skip.

Entries:
	HSTMAP accesses the host name table file.
	HSTLOOK converts a host name string to a host number.
	HOSTNM reads a host name from the terminal with completion.
	ICP connects to a foreign server.
	SERVE in a server listens for and connects to a user.
	ANALYZ prints an error message
	CONNECT makes a single connection.
	CONFIN completes a connection made asynchronously.
	HSTSRC converts a host number to a host name.
	HSTSIX converts a host number to a concise abbreviation
		for its name.

Other conventions:
	The major entry points of NETWRK all skip if succesful.   They
	are all defined in the containing symbol block, not just in
	the block named NETWRK.  They all clobber T and TT.

	A rigid correspondance between socket numbers and I/O channels
	is assumed.  See under the CONNECT routine for how and why.

Control parameters default to zero:
	$$HSTMAP enables mapping in the host names and characteristics
	   data base, and the conversion of a host number to a host
	   name. 
	   $$HOSTNM enables the routines to convert host names to host
	      numbers.  The following switches select one or both of
	      them. 
	      $$SYMLOOK enables the non-interactive host name lookup.
		 $$SYMGET enables the interactive one.
	$$HSTSIX enables the routine to generate a six-character
	   abbreviation for a specified host name such abbreviations
	   are used by servers to put in the LOGIN to be printed on
	   the system console.
	$$CONNECT enables the routine to open a connection.
	   $$ICP enables the routine for a network user program's ICP.
	   $$SERVE enables the routine for a server's ICP.
	      $$SYSDBG tells the server ICP routine NOT to refuse
	         most connections when SYSDBG is on.
	   $$ERRHAN enables an automatic error message printout when
	      making a connection fails.
	$$ANAYLZE enables the routine for printing an error message
	   when an error occurs using the net.

Host Name Lookup:

  Programs that use the Arpanet often accept the name of a host as
input and contact that host.  NETWRK provides routines for converting
a host name to the host's number.

  The first requirement for parsing a host name is to access the ITS
host name table, the file SYSBIN;HOSTS1 >.  All programs should use
this table rather than have their own, because it is kept up-to-date.
The routine NETWRK"HSTMAP maps this file into core starting at the
page whose number is specified in A, making temporary use of an I/O
channel specified in B.  HSTMAP skips if it is successful (it will
fail only if the file is clobbered), returning in rh(A) the number of
the first page not used.  NETWRK"HSTADR will retain the address of the
beginning of the file, so NETWRK can access it.

  HSTMAP is assembled if $$HSTMAP==1.  This should always be so.

  The basic operation of looking a name up in the table is performed
by the HSTLOOK routine, which takes in A the address of an ASCIZ string
containing the host name (or a host number in octal, or decimal
followed by a point).  HSTLOOK skips if the name is valid and
unambiguous, returning the host number in A.  If HSTLOOK does not skip, the name
was meaningless if B contains 0, or ambiguous if B is not 0.  E, T and
TT are clobbered.  To get HSTLOOK assembled, set $$HOSTNM and
$$SYMLOOK. 

  If you wish simply to read a host name from the terminal, you can
call HOSTNM, which provides completion and help facilities.  HOSTNM
requires no arguments when called, but it expects the user to define
the subroutines GETCHR, PUTCHR and SPCHAN which it calls.  GETCHR is
used to read input (from the terminal, presumably);  PUTCHR, to echo
the input and print error messages and completions;  SPCHAN, to handle
control characters, etc. returned by GETCHR.  HOSTNM skips if it
succeeds, returning the host number in A.  To get HOSTNM assembled,
set $$HOSTNM and $$SYMGET.

  The user-provided subroutines of HOSTNM must have these calling
conventions:
	PUTCHR should expect the character in T, and not skip.
	GETCHR should return an input character in T,
	   skipping unless there is "no more input available".
	SPCHAN is used by the interactive host-name lookup routine to
	   handle "special" input characters, not recognized.
	   The special character is passed in T, and the number of
	   characters read so far in TT.  If SPCHAN skips, the
	   character is then ignored.  If SPCHAN does not skip, the
	   read-in process is restarted, ignoring all input so far.
	   Of course, SPCHAN can collude with GETCHR to feed the
	   previous input or part of it to HOSTNM again.

  HOSTNM and HSTLOOK accept abbreviations as long as they are
unambiguous.  The precise criterion is that, if the specified name
abbreviates more than one known host name, then one of those host
names must abbreviate all the rest.  Thus, "Rut" is a valid
abbreviation for "Rutgers" even though "Rugters-10" and "Rutgers-Tip"
both exist and are different machines, because "Rutgers" abbreviates
both of the other two possibilities.  If "Rutabaga" also existed, then
none of the four possible completions of "Rut" would abbreviate all
the others, and "Rut" would be invalid.  This is an extension of the
normal rule that an exact match is valid even if it is also an
abbreviation for something else.

  In addition, HOSTNM and HSTLOOK accept an octal number, or a decimal
number terminated by a decimal point.

  HOSTNM, the interactive reader, types a bell whenever an invalid
name is entered, and ignores the invalid character.  At any time, the
user can type "?" or Altmode to see a list of all the hosts whose
names are abbreviated by what he has typed so far.  "?" or Altmode at
the beginning of a host name will type a list of all known hosts.


Routines for Servers:

  Arpanet server programs need to listen for and then establish
connections, and often need to be able to translate a host number into
the host's official name.  Also, standard practise is for the server
to log in after accepting a connection, and supply as the "terminal
name" argument of the LOGIN symbolic system call a six-character
abbreviation of the host name, which will be printed on the log
console.  NETWRK provides subroutines SERVE, HSTSRC and HSTSIX for
these functions.

  SERVE, assembled if $$SERVE==1, is the routine which listens for and
establishes a connection.  It takes several arguments:
A contains the number of the first of three consecutive I/O channels.
   The first is the ICP listen channel,
   the second is the input channel for the TELNET connection,
   and the third is the output channel for it.
B contains the local socket number to listen on.
C contains <input mode>,,<output mode> where the modes are those to
   be used in the OPENs for the two halves of the TELNET connection.
DEBUG must be defined by the user, and contain a flag which, if
   nonzero, disables SERVE's time-out and causes it to .VALUE if
   anything strange happens.  Deposit -1 in DEBUG when you test the
   server undeer DDT.
SERVE skips if successful;  it can fail due to a time-out, or because
the setting of SYSDBG specifies that connections from the ICP'ing host
are to be rejected.  When SERVE succeeds, it returns the foreign host
number in B, and clobbers A, D, T and TT.  The channel whose number
was passed in A is now closed, and the next two channels are open.

  Normally, SERVE itself refuses connections from hosts locked out by
SYSDBG.  However, if you set $$SYSDBG==1, SERVE will accept them, and
skip, returning in C a flag which will be nonzero if the connection is
not really wanted.  In that case, the caller should break the
connection himself;  but he has the opportunity first to send an error
message. 

  To convert a host number into a host name, HSTSRC can be used.  It
also makes it possible to find out what sort of machine the host is,
and what operating system it runs, if this information is known in the
ITS host name table.

  HSTSRC takes a host number in B, and returns host name as an ASCIZ
string whose address is in A.  The sign of A is set if the host is a
TIP.  In addition, D points at the entry for the host in the NUMBERS
table of the HOSTS1 file;  see KSC;HOSTS1 > for the format of this
table.  HSTMAP must be called before HSTSRC can be used.  HSTSRC is
assembled is $$HSTMAP==1.

  To get instead a six-character abbreviation for the host name, call
HSTSIX.  It takes a host number in A, and returns the abbreviation in
A as a word of SIXBIT, suitable for passing to a LOGIN system call.
If the host is not known, a name is made from its number.  HSTSIX
always skips.  HSTMAP must be called before using it.  HSTSIX is
assembled if $$HSTSIX==1.


Routines for User Programs

  "User" ends of network protocols need to at least to establish a
TELNET connection to a server.  If any problems arise, they should
decode the status information provided by ITS to print an error
message.  The routines ICP and ANALYZ are provided for these purposes.
User ends will often also need the host-name conversion routines
described above.

  The routine ICP creates a two-way TELNET connection to a server.
It takes these arguments:
A contains <chan>, the number of the first of a block of four I/O
  channels to be used.  <chan> itself is used only during the ICP.
  The input side of the TELNET connection is established on channel
  <chan>+2, since its socket number must be two greater than the one
  used on channel <chan> to begin the ICP.  The output side takes the
  next channel number, <chan>+3, since it takes the next socket
  number.  Channel <chan>+1 is not actually by the ICP process, and it
  cannot be used for any network connection.  It can be in use in any
  other way, even while the ICP is happening.
B contains the number of the foreign host.
C contains the foreign socket number to ICP to (1 for TELNET, etc.)
D contains <input mode>,,<output mode>, describing the modes to be
  used in the OPENs that establish the two halves of the TELNET
  connection.
ICP clobbers all the known ACs, A through E and T and TT, and returns
no values.  It skips if the TELNET connection is successfully
established.  Otherwise, a caller running under the control of a
terminal should print an error message by calling ANALYZ.  Setting the
flag $$ERRHAN==1 will cause ICP to call ANALYZ itself before returning
in the case of failure.

  The ICP routine is synchronous:  it waits until the connection
succeeds or fails.  An ICP can be done asynchronously also, with the
ICPASN routine.  ICPASN takes the same arguments as ICP, and in
addition should be given zero in E when it is called for the first
time.  On successful return, the first channel (the ICP socket) will
have been opened.  At any later time, calling ICPASN again will wait
for that first connection to complete and then request the two halves
of the TELNET connection.  Calling ICPASN a third time will wait for
those two halves to complete.  The ACs A through E returned by one
call to ICPASN must be saved and given to ICPASN again the next time.
If ICPASN ever fails to skip, the entire ICP has failed and you should
not attempt to complete it.

  The routine ANALYZ prints an error message after an attempt to open
a network connection fails.  It needs no arguments, as it knows how to
track down all relevant information from ITS's debugging variables.
The error message is output by calling the user-supplied subroutine
PUTCHR with a character to be output in T.  PUTCHR should output the
character as appropriate and return without skipping.
ANALYZ always skip-returns.


Establishing Subsidiary Connections (FTP data connection, etc):

  The CONNECT routine can be used to establish a unidirectional
network connection in either a server or user program.  Its arguments
are these:
A contains the I/O channel number on which to open the connection.
  This also specifies the socket number, via the channel-socket
  correspondance.  If a new connection must use a socket number 2
  greater than an existing connection's, then the new connection must
  be made on the channel 2 greater than the existing connection's
  channel.
B contains the foreign host number.
C contains the foreign socket number to connect to.
D contains in its rh the mode to use in the OPEN.
  Its sign is set to request asynchronous mode.
Normally, CONNECT waits until the connection is completed, skipping if
it is successful.  Failure can be due to a down host, a refusal, or to
a time out which CONNECT checks.  When CONNECT fails to skip, you may
call ANALYZ (see above) to print an error message;  or, if you set
$$ERRHAN==1, CONNECT will call ANALYZ itself.  In any case, ACs T and
TT are clobbered;  the others are preserved.

  Set the sign bit of D when calling CONNECT to create the connection
asynchronously.  CONNECT will initiate the connection and return
skipping if there has been no problem yet.  At a later time, call
CONFIN to wait for the connection to complete.  CONFIN will skip if
the connection has been accepted.

  CONNECT, and ICP and SERVE which call it, uses the ITS feature that
assigns a set of eight consecutive network socket numbers to a job
which requests them.  CONNECT assumes that these eight sockets
correspond directly to eight consecutive I/O channels;  each socket
can be used only from the corresponding I/O channel.

  The socket-channel correspondance is set up the first time CONNECT
is called.  At this time, connect realizes that it has no socket
numbers assigned and asks the system to assign some.  The first socket
number of that block is used for the first connection, made on the I/O
channel specified in the first call to CONNECT.  The following seven
socket numbers, also assigned to this job, correspond to the following
I/O channels.  The first CONNECT stores the offset from the I/O
channel number to the corresponding socket number in NETWRK"SKTBAS,
so that later CONNECTs can convert a channel number to a socket
number.  As you can see, the lowest-numbered socket of a set must be
CONNECTed first.

  If you close all network connections at any time, ITS deallocates
the block of socket numbers, so you should store zero in SKTBAS to
cause the next CONNECT to allocate a new set. 

File: LIB,   Node: LSRTNS,   Previous: NETWRK, Up: Top

The LSRTNS library contains routines for accessing the INQUIR data
   base.  *Note LSR1: LSR1 Format, for the details of the format
   of that data base.

ACS:	A, B, C, D, and E, which must be consecutive, and P.

VARS:	LSRTNS has these static internal variables:

	LSRADR	;Core address where first part of file is mapped in
	DATFPG	;Page number in file of first data page
	SCMPRT	;String compare routine to use LSRLNM and LSRLNP

	If overlaying of pages is being done (the default),
	these additional variables exist.

	DATADR	;Core address of two pages for mapping in data pages of file
	DATPAG	;DATADR/2000
	PAGEIN	;Page number in file of page currently mapped in at DATPAG
		;The page after that maps the next sequential file page.
		;This is negative if no page is currently mapped in.


	If the HSNAME routines are included, (not by default) these variables
	are exist as well.

	HSNADR	; Address in core of HSNAME table base.
	HSNPTR	; AOBJN ptr to HSNAME table entries.
	HSNLN1	; Length-1 of an entry in HSNAME table.
	LMCHNM	; Local machine name, as returned by SSTATU.
	HRETRY	; Switch for re-trying with HX$NRM if HX$TUR (or other) fails.
	LSRCHN	; Holds # of temp channel to use.
	MNAME	; "Canonical" machname of site specified.
	MNAME1	; "MIT-**" version of machname.


Exits:	None.

Entries:  (All skip if successful).
	LSRMAP opens the data base.
	LSRUNM searches for a UNAME's entry.
	LSRITM extracts a specifically numbered item from an entry.
	LSRLNM searches for the entries for a given last name.
	LSRLNP is similar but allows abbreviation.
	LSRNAM permutes a name in Lastname, Firstname, Suffix order
		(as stored in the data base) into First Last Suffix.
	LSRGET converts a file address into a core address,
		overlaying if necessary.
	LSRHSN looks up the HSNAME for a user, given his XUNAME
	LSRTUR skips if an entry is that of a Tourist (T or nonexistant group)

Control parameters default to One, except for $$HSNM.
Everything is normally assembled except what you say you don't need.

	$$ULNM==0 to omit the routine to search for a last name.
	$$ULNP==0 to omit the routine to search for an abbreviated
		last name.
	$$UNAM==0 to omit the routine to permute a fullname into
		"humanized" Firstname Lastname Suffix order.
	$$OVLY==0 to omit the overlay routines, and map the whole
		data base into core at once.  This is good for a
		program which wants to scan the whole data base
		instead of looking up a few entries.
	$$HSNM==1 to include the HSNAME lookup routines.

Routines in LSRTNS:

  LSRMAP takes in A a channel number, and in B an AOBJN pointer to a
range of free pages, and maps in the data base.  If successful, it
returns in B an updated pointer indicating which pages were not
needed, and leaves the file STILL OPEN on the given channel.
Pages which might be needed later for mapping in an entry are
remembered internally and marked off as "used".  No skip can
either be due to trouble opening or mapping the file, or due
to a clobbered file, or due to needing more pages than are offered.
If you set LSRTNS"$$OVLY to zero at assembly time, the whole
file will be mapped in instead of just a few pages at a time.
In that case, the channel will not be left open.

  LSRUNM takes in A a channel number, on which the LSR1 file is
assumed to be open, and in B a UNAME as a word of SIXBIT,
and returns in B the address, in core, of the entry for that UNAME.
Such entries are mapped in by LSRUNM and will not
necessarily remain in core if another LSRUNM or LSRLNM is done.
No skip implies there is no entry for that UNAME.

  LSRLNM is like LSRUNM but expects in B the address of
an all-caps last name, as an ASCIZ string, instead
of a UNAME, and returns in B an aobjn pointer to the
LASTNAME table words whose Lastname match the argument.

  LSRLNP is like LSRLNM except that the specified last name
need only be an initial segment of a user's last name for the
user to be matched and included in the range of the lastname
table returned.

  LSRGET takes in A a channel number and in B the file address of an
entry.  It maps in the appropriate pages and returns in B the core
address.  Fails to skip if the map fails or if the given address does
not point at the header of an entry, Use this after calling LSRLNM,
etc.  LSRUNM calls LSRGET itself.  If $$OVLY is 0, then this routine
just converts a file address into a core address. 

  LSRITM takes in A an item number and in B the address in core
of a LSR entry, and returns in A a b.p. to the specified item.
No skip => this entry lacks that item.  A nonexistent item is legal
and should be treated just like a null string.  The item number should
usually be specified with one of the I$... item names defined by
LSRTNS in the LSRTNS block:
	
	I$==,-1		;Bit typeout mode prefix.
	I$UNAM==0	;UNAME
	I$NAME==1	;FULL NAME
	I$NICK==2	;NICKNAME
	I$SSN==3	;SOC SEC #. 
	I$MITA==4	;MIT ADDRESS
	I$MITT==5	;MIT TELEPHONE NUMBER
	I$HOMA==6	;HOME ADDRESS
	I$HOMT==7	;HOME TELEPHONE NUMBER
	I$SUPR==10	;SUPERVISOR(S)
	I$PROJ==11	;PROJECT
	I$DIR==12	;FILE DIR NAMES
	I$AUTH==13	;AUTHORIZATION
	I$GRP==14	;GROUP AFFILIATION
	I$REL==15	;RELATION TO GROUP
	I$BRTH==16	;BIRTHDAY
	I$REM==17	;REMARKS
	I$NETA==20	;NETWORK ADDRESS
	I$ALTR==21	;USER &TIME OF LAST ALTERATION
	I$MACH==22	;I.T.S.'S TO BE KNOWN ON. 

  LSRNAM takes in A a b.p. to a Name item, and in B a b.p. to
storage, and IDPBs down B the name, canonically permuted into
Firstname Lastname Suffix order.


LSRHSN find HSNAME for entry, given
	A/ UNAME of entry
	B/ <LSR entry addr> or 0 if none.
	C/ <site> - as per SSTATU call, or host #, or 0 for local site.
	D/ <channel #> to use for disk opens (if -1, don't use any.)
It skips if successful, with
	D/ HSNAME
It uses the following algorithm:
	If no entry address given,
		If directory for that UNAME exists, return that as HSNAME
		Else assume tourist and use hasher/tables.
	Else if "Fildir" entry exists, and a valid dir is specified for
		local site, return that as HSNAME.
	Else if directory for that UNAME exists, return that as HSNAME
	Else determine HSNAME using hash or tables, plus touristness (see
		LSRTUR)
LSRHSN is the routine that DDT uses to deterimine what a person's Home
directory is (HSNAME) on logging in.  It is also used by the mailer to
determine where a person's mail goes.

LSRTUR Test an entry for touristness.  It takes a LSR entry address and
skips if tourist ("Group" field T or non-existent)



File: LIB,   Node: LSR1 Format,   Up: LSRTNS

This is the format of the user data base (INQUIR data base),
which lives in the file INQUIR;LSR1 > on each machine:

HDRSID==0	; wd 0	SIXBIT /LSR1!!/ for detection of clobberage.
HDRDAT==1	; wd 1	Date of compilation as sixbit YYMMDD.
HDRTIM==2	; wd 2	Time of compilation as sixbit HHMMSS.
HDRUNM==3	; wd 3	Address in file of UNAME table.
HDRLNM==4	; wd 4	Address in file LASTNAME table.
HDRDTA==5	; wd 5  Address in file of start of data area.
		;	The data area must start on a page boundary,
		;	and it must be the last thing in the file.
HDRHSN==6	; wd 6	Address in file of HSNAME table.
		;.... other data;  the tables just mentioned
		;     and strings which they point to.

;UNAME table:
; wd 0	Number of entries in this table,
;followed by entries, one per page of data area,
;each containing the UNAME of the first data area entry which begins on that page.

;LASTNAME table:
; wd 0  Number of entries in this table,
; followed by entries, in order by last name
; Each entry looks like this:
;  rh  addr in file of entry
;  lh  addr in file of Last-name string

;The lastname strings are word-aligned upper-case ASCIZ strings,
; and they follow the LASTNAME table.

;HSNAME table:
; Currently this table is simply snarfed from the file INQUIR;DIRS BIN,
; which is assembled from INQUIR;DMUNCH >.  It's format is as follows:

	0: -<# entries>,,# wds/entry
	1-n: MACH entries

=================================================================
Sub-tables

	mach wd 0: <machine name>	; 6bit returned by SSTATU
	mach wd 1: <site #>		; Arpanet site #.
	mach wd 2: <addr of sub-table>	; Addr is rel to start of HSNAME-table.
	mach wd 3: <addr of tourist subtable>

Each sub-table is simply:
	0: -<# entries>,,# wds per entry	; RH is currently 2.
	1-n: NAME entries

	entry wd 0: UNAME	; For all unames => this but < next entry,
	entry wd 1: HSNAME	; this is the HSNAME.

|

	; HSNAME table indices
hx$mnm==:0	; wd 0 of mach-table entry is mach name, as per SSTATU call.
hx$hst==:1	; wd 1 is arpanet host #.
hx$nrm==:2	; wd 2 is sub-table ptr for normal unames.
hx$tur==:3	; wd 3 is sub-table ptr for tourists.
hx$len==:4	; # wds per mach-table entry

	; Sub-table indices
hs$unm==:0	; wd 0 of sub-table entry is UNAME
hs$hsn==:1	; wd 1 is HSNAME for range.
hs$len==:2	; # wds per sub-table entry

;The data area:
; It starts on a page boundary.  It is made up of consecutive entries,
; in order by UNAME, each looking like this:
LDACNT==0	;   entry wd 0  lh
		;     the number of words in the entry,
		;     including this one.
		;   entry wd 0  rh  -1

; followed by unaligned ASCIZ strings, one per item, separated
; only by the single ^@ that ends the ASCIZ.  The strings are associated
; with their meanings according to their numerical position in the entry.
; The entire entry is then padded to a word boundary with nulls.
; Note that the low bit is set in the count-words of entries
; and not in any other words of the data area.

; Symbols for all the item numbers are defined in LSRTNS as follows:
	
	I$==,-1		;Bit typeout mode prefix.
	I$UNAM==0	;UNAME
	I$NAME==1	;FULL NAME
	I$NICK==2	;NICKNAME
	I$SSN==3	;SOC SEC #. 
	I$MITA==4	;MIT ADDRESS
	I$MITT==5	;MIT TELEPHONE NUMBER
	I$HOMA==6	;HOME ADDRESS
	I$HOMT==7	;HOME TELEPHONE NUMBER
	I$SUPR==10	;SUPERVISOR(S)
	I$PROJ==11	;PROJECT
	I$DIR==12	;FILE DIR NAMES
	I$AUTH==13	;AUTHORIZATION
	I$GRP==14	;GROUP AFFILIATION
	I$REL==15	;RELATION TO GROUP
	I$BRTH==16	;BIRTHDAY
	I$REM==17	;REMARKS
	I$NETA==20	;NETWORK ADDRESS
	I$ALTR==21	;USER &TIME OF LAST ALTERATION
	I$MACH==22	;I.T.S.'S TO BE KNOWN ON. 

; The entries are sorted in ascii order, which is NOT the same
; as the order obtained by arithmetically sorting the SIXBIT unames.

; The end of the data area is marked by ,,-1, which
; is tantamount to an entry 0 words long.
; That word is also the last word of the file.


Local Modes
Auto Fill Mode:1
end:
