FILE SPOOL.TXT		11-MAY-81

Author:	Maarten van Swaay
	Department of Chemistry
	Kansas State University
	Manhattan, Kansas 66506

Operating System: RT11 V3 or later
Memory: 4.1K bytes
SYSGEN options: FB or XM monitor with support for 2 or more terminals

	SPOOL is a program that can run as a foreground or system job. It
provides the functions of a line printer via a serial port. Its primary
virtue lies in the fact that it can drive a serial printer (LA36 etc.) via
a multiplexed port (DZ11 or DZV11) without interfering with other channels
on the same interface.

	The second virtue of SPOOL is its capability to perform end-of-file
actions. RT11 does not inform output devices of end-of-file, but SPOOL can
detect EOF as it reads the file. That allows SPOOL to generate a page eject
after each print job, to keep output in phase with paper folds.

	SPOOL handles tab and formfeed codes somewhat more elegantly than
the standard serial driver supplied with RT11. Tab stops are placed every
8 columns until fewer than 8 columns remain before the right margin. Then
tab codes are printed as single spaces. The placement of tab stops is
adjusted automatically with changes in line width.

	Lines extending beyond the maximum allowed width are folded. The
required CR-LF codes are inserted only if the first character beyond the
last allowed column is not a CR, to avoid creation of blank lines.

	SPOOL keeps a running count of lines printed, and will generate
page breaks as needed to skip perforations on standard 11 inch paper. Although
no provision is made to allow for other paper sizes, the structure of SPOOL
makes it possible to add that feature without rewriting of the existing code.

	Formfeeds will generate a page eject only if the print head is
not at top left, i.e. only if text has been printed on the current page.
Multiple formfeeds will not generate blank pages; if blank pages are
desired in a file, that can be achieved by insertion of <space> codes
between the formfeeds. Under control of a run-time option, formfeeds can
be converted into a 9-line paper advance. In that case, no automatic page 
breaks are generated, so that graphic output extending over more than one
page can be printed.

	SPOOL normally ignores all control codes other than the printer
positioning codes (tab, CR, LF, BSP, FF). A run-time switch is provided
to print all other control codes in their up-arrow form, and to print ESC
as <$>. The primary use for this feature is the printing of TECO command
files.

	SPOOL periodically inspects the system device for files with an
extension .SPL. When such a file is found it will be routed to either LUN1
or LUN2 according to the setting of a run-time option. On completion of the
print job, the .SPL file is deleted from the system directory. In addition,
SPOOL can destroy the file contents, if desired. This function is provided
for compatibility with CRYPT, an encrypting/decrypting program for text
files. The destruction feature is presently implemented as a compile-time
option, but can easily be changed into a run-time switch.
	To produce printed output from the FB or XM monitor you should write
the information you want printed onto the system disk with an extension .SPL.
The file name itself is immaterial, although you will probably use the same
name as the parent file, by giving a command of the form

		.COPY file.ext SY:*.SPL

	To get prints of a number of files you can use the command

		.COPY xxxxxx.xxx SY:*.SPL/Q

where xxxxxx.xxx represents the file characteristic that is common to all the
files you want printed. Please recognize that you cannot use the entire
file name as that common characteristic!

	The spooler inspects the system disk every 15 seconds, and after
completion of every print job. That means that printing will start soon, but
not necessarily immediately after you have created the spool file.

     *****************************************************************
     *    DO NOT RENAME A FILE TO GIVE IT THE  .SPL  EXTENSION !     *
     *  THE SPOOLER MAY DESTROY THE CONTENT OF ALL FILES IT PRINTS,  *
     *     AND WILL THEN DELETE THEIR NAMES FROM THE DIRECTORY.      *
     *****************************************************************

	You can set the spooler to your needs at run-time. To connect the
terminal to the spooler, type ^F. The system will reply with >F and a carriage
return. You can then give the commands listed below. Numeric arguments may
be entered either in decimal format (terminated with a period), or in octal
format (no period). Commands may be given in any order.

SHOW		reports current setup of the spooler

LINES=xxxx	sets the number of lines per page. Values of 30-60 decimal
		are allowed. In addition, a value of zero is allowed. If LINES
		is set to zero, page ejects are suppressed from output, and
		formfeeds are converted into 9 linefeeds. This setup can be 
		useful for pseudo-graphic output. When LINES is zero, the
		spooler forgets the actual paper position. Therefore you must
		reposition the paper to top-of-page when you change back
		from LINES=0 to an allowed non-zero value.

WIDTH=xxx	sets the number of characters per line. Decimal values of
		30-132 are allowed.

TECO=x		If x is non-zero, convert control characters to ^ notation.
		If x is zero, pass control characters un-edited.

Inbedded spaces in the command string are ignored.

After you have set the spooler to your taste, type ^B to switch the keyboard
back to the background job or to KMON. The system will respond with >B and
a carriage return.

If SPOOL is run as an S job, you must type ^X to gain access to the S jobs,
and then identify which of those jobs you want to communicate with. For
more details about system jobs you should read the appropriate chapter in
the RT11 documentation.
	Although you can issue commands to the spooler at any time, the
spooler will take action only when it cannot produce output. For that reason,
it would be unwise to issue a SHOW command  while output is being printed,
because you would then have to wait until the end of the print stack before
the report would appear. If you issue one of the other commands, it will go
into effect as soon as all existing .SPL files have been disposed of.

	The configuration of the spooler is held in memory. That means that
you can change it to your heart's content, without worrying about what the
next user will find. In contrast, changes made to device drivers are recorded
on the system device, and will remain to create surprises for the next user.
The initial setting of the spooler is

	LINES = 60, WIDTH = 132, TECO = 0 (OFF)

These are decimal values. The SHOW report is also given in decimal form.

	On systems with floppy disks as the system device it will often be
necessary to change system volumes. That may cause a read error from the
spooler when it tries to read the system directory while no disk is present.
To avoid such mishaps, suspend activity of the spooler with the .SUSPEND
monitor command, and re-activate the spooler with .RESUME as needed.

	Occasionally you may wish to abort printing of a file. The brutal
way to do that is by typing ^F ^C ^C at the console, to kill the spooler.
You will then have te re-install it with a command FRUN SPOOL, which is not
very elegant. More serious is the fact that the abort sequence will leave
'half-eaten' spool files on the system disk. When a new copy of SPOOL is
installed, it will proceed to print those remnants. The proper way to abort
the printing of a file is by typing ^O on the keyboard of the printing
terminal. The spooler will consume the remainder of the aborted file, and will
then delete it from the directory. After that, type a second ^O on the
keyboard of the printing terminal to re-enable output. Note that ^O must
be issued in matched pairs. After an abort, you must reposition the paper and
the print head by hand. The spooler keeps track of all lines written to
the output device, but RMON discards the output stream, so that the paper
and print head position cannot match the internal accounting of the spooler.
The end-of-file handling of the spooler is such that the printhead will
always be assumed to be at top left at the beginning of a new file.
PROGRAM NOTES:

	SPOOL reads the directory on the system device on a 15-second
schedule which is maintained by 30 tests for keyboard input on a half
second schedule. If input is available, the next directory scan is postponed
until 15 seconds after the input command(s) have been executed.

	Directory lookups are handled internally by SPOOL; USR does not
support the wild-card functions required here. A summary of the RT11
directory structure is included in this file for reference.

	When a spool file is found, it is read into a pair of pingpong
buffers. Provision is made to rewrite each block with nulls (except for
the first word) as soon as it has been read. This feature was added to
maintain protection for output from CRYPT via the spooler. Without the
rewrite with nulls, SPOOL would leave a plaintext version of the decrypted
file on the system volume, where it could be found with only minor effort
by a dedicated snooper. The plaintext destruction makes use of the fact
that file-oriented devices will fill a partial-block transfer with nulls.

	After the last block of a spool file has been disposed of, SPOOL
places a .DELETE request to RMON to remove the file from the directory,
and then scans the directory for additional spool files. No attempt is
made to maintain records of multiple spool files; only the first file found
is printed. On deletion of that file, any additional files wil be uncovered.
A minor drawback of this scheme is the fact that files will not always
be printed in the order in which they were created.

	The buffer content is edited and transferred to a 40-character
buffer that is handed over to RMON with an .MTPRNT request. It is not
strictly necessary to collect the output stream into a buffer, but requests
for multiple character transfers require substantially less overhead from
RMON.

	The various editing functions are all invoked by means of a dispatch
table that is accessed with the edit character as an index. Additional edit
functions can therefore be added with a minimum of recoding.

	Interpretation of run-time commands is handled by a simple string
recognizer. It, too, is table-driven; additional command words can be
added to the table as .ASCIZ strings. Parsing of the command string allows
for free-form input; spaces are ignored. Only a single token is expected;
it may be terminated with <=>, with <CR>, or with <LF>. If <=> is found as the
terminator, a numeric argument in either octal or decimal format will be
expected after the token. The numeric argument may be closed with <CR> or
with <LF>.

	Normally the spooler will use whatever copy of USR is available for
its .DELETE requests. It could be that a background job has either swapped
USR out, or has locked it for its own use. When USR is swapped out, SPOOL
provides swap space from its own program space. The program is not quite long
enough for that, but the end contains a stretch buffer to make it long enough.
That stretch buffer is not attached if SPOOL is compiled with a condition file
that defines MMG$T as nonzero, because under XM the USR is always resident.

	The stretch buffer is calculated at compile time; if additional
features are built into SPOOL, the stretch buffer will shrink so that total
space will remain just enough for the USR swap. Obviously, some care is in
order to avoid swapping USR over code that calls it. All non-swap code is
located up-front, before location SPOOL.
Directory format:

Offset	content
 0	number of segments in the directory
 2	segment number of next segment, 0 if this is the last one
 4	highest segment in use, maintained in segment 1 only
 6	number of extra bytes per file entry, always even
10	block number of first file in this segment

12	file status word
14	file name, RAD50
16	file name, RAD50
20	file extension, RAD50
22	file length
24	channel number if active file
25	job number if active file
26	creation date
30	extra words, if any, else status word of next file

Status word:
low byte	always zero, reserved
high byte:
bit	meaning
0	tentative file
1	empty file
2	permanent file
3	end of segment
5
6
7	protected	(version 4 and later)

������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������