[net.sources] MM macros: "super spooler"

jmc@jimlad.UUCP (John M Collins M.A.) (07/19/84)

.nr Hb 7
.nr Hs 3
.ds HF 3 3 3 3 3 3 3
.nr Hu 5
.nr Hc 1
.SA 1
.PH "''A New UNIX Spooler''"
.PF "''- Page \\\\nP -''"
.H 1 "Introduction"
This document describes a spooler written for UNIX with many features
over and above existing spoolers. The key features are:
.AL
.LI
Support for multiple printers, with automatic selection of
printers where appropriate.
.LI
Control of paper types.
.LI
Priority, multiple copies etc.
.LI
Full screen spool queue viewing and manipulating facilities.
.LI
Control of individual users and charging.
.LE
.H 1 "Installation"
The spooler files are owned by a special user called
.B "spooler" .
This user is the key administrator for the spooler package, but he may
designate other users to be administrators or operators.
.P
First the user name should be installed in the password file, thus
.DS I
spooler::50:2::/usr/spool:
.DE
.P
The user id of
.B "50"
is assumed by the package, which may easily be
recompiled to use some other user id. Clearly to put the binaries on
another machine, the password file should also be set in this way. Since
the user ids should start at 100 onwards for ordinary users, this should
not be a limitation.
.P
The user
.B "spooler"
should be able to write in the directory
.I "/usr/spool" .
It would be suitable to make it owned by
.B "spooler"
with group
.B "bin" ,
mode 775. General users should not be able to write in this directory,
or they would be able to patch the control and charging file etc.
.P
The binaries should then be installed, and the appropriate directories
created, by logging in as the super-user, and running the script
.B "sp_ins"
provided. At the same time, the lines to be used for the printer(s)
should be designated, and any
.B "getty"
etc processes disabled.
.P
In the
.B "/etc/rc"
file, the following sequence should be inserted when going into multi-user
mode. This will delete any partly-written control files and restart the
spooler.
.DS I
rm -f /usr/spool/spd/spshed_req /usr/spool/sputmp
/usr/spool/progs/spshed
.DE
.P
It should not be necessary to reboot or anything immediately, since the
various processes will be started up (with a suitable comment) when
.B "spr"
is first invoked.
.P
Next log in as user
.B "spooler" ,
possibly setting a suitable password. Start up a small spool job,
perhaps by typing
.DS I
spr /etc/passwd
.DE
.P
The message
.DS I
Spr: restarting scheduler
.DE
.P
should appear on this occasion only. Nothing will appear on any output,
as the spooler system does not yet know which lines to use as printers.
.P
To define one or more (up to 3) lines as printers, enter the full-screen
interactive program
.DS I
spq
.DE
.P
A screenful of information such as the following should appear.
.DS L
Seq jobno user     file       form     size cps pty printer
  0   392 spooler /etc/passwd standard  393   1 150 



     Printer  line  form  status jobno user
.DE
.P
The cursor will be beside the second line. Type the letter
.B "o" .
The cursor will move to the bottom of the screen under the line starting
with the word "Printer".
.P
Type a capital
.B "N" .
The cursor will move under the "P" of "Printer". Type the name of the
printer, e.g. "Diablo", "Epson", "Tally" etc. Correct mistakes with
backspace or "#". Note that upper case characters will be translated to
lower case. Type a return to terminate the printer name. The
cursor should then move to under the "l" of "line".
.P
The name of the device, omitting any leading
.B "/dev/" ,
should then be typed in the same way as before, for example "tty3".
.P
Finally the cursor should move under the "f" of "form". The name
"standard" should be typed, to indicate standard form type.
.P
After typing the final return, the message "halted" should appear under
the "status" column, and the cursor should return to the start of the line.
.P
Type
.B "G"
for "go", and the message should change to "printing", the job number as
in the upper part of the screen should appear, and the name "spooler"
should appear under the "user" column. In the job queue, the printer
name should appear beside the job. The file should also start to
appear on the output device. When printing is complete, the job name
should disappear from the job queue.
.P
The above process may be repeated for up to two other printers if
desired, and then a
.B "q"
for "quit" typed to exit from
.B "spq" .
.P
Various users should then be able to spool files using
.B "spr" ,
thus
.DS I
spr file1 file2 file3
program | spr
.DE
.P
and so forth.
.P
Before shutting the system down, type
.DS I
sstop
.DE
.P
to stop the spooler in a graceful fashion.
.P
We shall look at all the programs in detail, but first we shall make
some general comments and definitions.
.H 1 "User privileges"
The spooler system recognises 3 types of user.
.P
An ordinary user can submit jobs, with priorities within a certain
range. He can view the spool queue, and change parameters of or
abort his own jobs only. He cannot stop or start a printer, nor can he
stop the spooler.
.P
An
.I "operator"
can change parameters of or abort any job in the queue, stop
and start printers and the spooler itself.
.P
An
.I "administrator"
can in addition to the privileges of an operator edit
the file which defines the priority limits and privileges of users.
.P
To view the current privileges, enter the command
.DS I
spuser
.DE
.P
This should produce output of the form:
.DS I
Priority: Min 100 Max 200 Def 150 Charge: 34
.DE
.P
The first 3 figures give the priorities; the lower and upper bounds, and
the default if none is given. The charge is for number of thousand
characters output, multiplied for each job by the square of the ratio of
the priority of the job to the default priority.
.P
Thus jobs may be increased or reduced in priority to improve or worsen
the chances of their being printed quickly. However this will
correspondingly increase or reduce the charge. The conversion of the
charge into an invoice is an installation dependent matter.
.P
Unless an administrator varies the figures, the minimum, maximum and
default priorities will be 100, 200 and 150 respectively. The absolute
minimum priority is 1 and the maximum 255.
.P
An extra line with
.DS I
Privilege: Operator
.DE
.P
or
.DS I
Privilege: Administrator
.DE
.P
is output by
.B "spuser"
where appropriate.
.P
The administrator may invoke
.B "spuser"
with the "interactive" option thus
.DS I
spuser -i
.DE
.P
to review and edit the user control file. The operation is described
later.
.H 1 "Full screen update conventions"
Since these conventions are consistently applied for all options of
.B "spq"
and
.B "spuser -i" ,
they are defined here only.
.B "Spq"
has a divided display, with the spool queue at the top half of the
screen, and the printer list at the bottom. However the same conventions
apply to each part of the screen, and the command
.B "o"
is used to switch between parts of the screen.
.P
The standard response to an error is a bell character. This is generated
by an attempt to move off the end of the display, an invalid control
character, or an invalid operation, or perhaps one not allowed to the
user, such as aborting someone else's job.
.H 2 "Moving about the screen"
The method of moving about the screen is similar to that used for the
editor
.B "vi" ,
with the exception that a more restricted portion of the screen is
updated.
.P
The commands are as follows:
.VL 10 2
.LI "j"
moves the cursor down one line, possibly causing a new line to appear at
the bottom of the portion of the screen, and a line to disappear from
the top.
.LI "k"
moves the cursor up one line in a similar fashion.
.LI "ctrl-F"
moves forward a screenful.
.LI "ctrl-B"
moves backward a screenful.
.LI "ctrl-U"
moves backward half a screenful.
.LI "ctrl-D"
moves forward half a screenful.
.LI "ctrl-L"
refreshes the screen if it gets messed up due to messages, glitches with
the terminal etc.
.LE
.P
Note that there is no provision for moving the cursor left or right.
This is only done when a field is being edited.
.P
When the spool queue is being viewed, parts of the screen may change
whilst the user is scrolling through it. The software attempts to
preserve the position on the screen of the current line even if (as in
the case of a change of priority) everything else moves around it.
.H 2 "Updating fields"
If the user decides to update a field on the display, the cursor is
moved to the start of the field. The existing matter is undisturbed
until the first character is typed. Characters are then accepted up
until a carriage return or line feed.
.P
Special control characters are:
.VL 12 2
.LI "escape"
abort the edit, and restore the existing value.
.LI "@"
kill all characters typed so far and start again.
.LI "backspace"
delete the last character typed.
.LI "#"
as backspace.
.LE
.P
If the input is erroneous, e.g. letter typed instead of digit in a
numeric field, a bell character is output and the character input
ignored. If the whole field is erroneous, e.g. string too long or number
outside range, a bell character is output, the field reset to the
original value, and input reprompted for.
.P
Where the input is a string, only letters and digits are accepted.
.H 1 "Spr"
Spr is the program used to spool jobs to a printer. Input may be either
from files, thus:
.DS I
spr file1 file2 file3 ...
.DE
.P
in which case the files are put into one job with the name of the first
file, with a new page in between each file of the output.
.P
Alternatively no files may be specified and the material passed via a
pipe, thus
.DS I
commands | spr
.DE
in which case there will be no file name associated with the job unless
one is given by suitable options.
.P
By default, one copy is produced, with a heading page containing the
user name and the file name for the job in large characters, and various
other information printed in normal size characters.
.P
The priority is a default for the user, the paper type is set to
.I "standard" ,
and no particular printer is selected. The user has available a variety
of options to change all these things. By the usual UNIX convention,
these are given as a list of flags preceded by a minus sign, with
considerable flexibility:
.AL
.LI
Single character options may be strung together with one minus sign, thus
.DS I
-mwsv
.DE
.P
or
.DS I
-m -w -s -v
.DE
.P
are equally acceptable.
.LI
Options which take arguments can have the arguments immediately
following the option, thus
.DS I
-c4 -p180
.DE
.P
or they may be separated by spaces, thus
.DS I
-c 4 -p 180
.DE
.P
.LI
Mutually contradictory arguments are permitted, the rightmost (or rather
the most recently specified) applies.
.LE
.P
The user may effectively reset the default options until further notice
by using the environment variable
.B "SPOOLOPTS" .
.P
Thus if 4 copies are required of every job, rather than putting
.DS I
prog | spr -c4
.DE
.P
every time, the user may type
.DS I
SPOOLOPTS='-c4'
export SPOOLOPTS
prog | spr
.DE
.P
with a similar effect. Any arguments given to
.B "spr"
on the command line override the environment, thus to produce a listing
of the file "oneonly"
with one copy in the midst of several jobs with 4, the user would type
.DS I
spr -c1 oneonly
.DE
.P
in this case.
.P
The particular case of the job name is treated as follows:
.AL
.LI
If any 
.B "-h"
option is specified on the command line this is used.
.LI
Failing that, if any 
.B "-h"
option is found in the environment, then this is used.
.LI
Failing that, the first file name given in the command line is used.
.LI
Failing that, blanks.
.LE
.P
The options to
.B "spr"
are as follows:
.VL 15 2
.LI "-c n"
Sets the number of copies to
.B "n" ,
which should be a number in the range 1-255.
.LI "-p n"
Selects a priority of
.B "n" ,
which can be a number in the range 1-255. Most users are limited to
a particular range of priorities. 
.LI "-f type"
Selects a particular form type. To avoid confusion between nearly similar
names, the type name is turned completely to lower case.
.LI "-P printer"
Forces selection of the named printer. The printer name is converted to
lower case.
.P
Note that the type of the printer (declared by the operator) is given.
The user has no direct control over the port number, so if two or more
of the same type of printer are running, then either may be selected.
.P
A minus sign may be substituted for the printer name to indicate that
the user is not concerned about the selection of the printer, to cater
for the case where a printer name is forced in the environment, and it
is not to be forced for a particular invocation of
.B "spr" .
.LI "-u user"
Replaces the user name which appears on the header page with the
specified user name. An appropriate note also appears on the header page.
Charges, priority control etc are under the
control of the submitting user, whose user name still appears in the
queue.
.P
A minus sign may be substituted for the user name to indicate the
current user, to cope with the case where a user name forced in the
environment is to be turned off.
.LI "-h name"
Sets the file name for the job.
.LI "-s"
Suppresses the header page. The operator may decide that particular
paper types, e.g. labels, are printed without header pages in any case.
.LI "-r"
Restores the header page in case the environment variable
.B "SPOOLOPTS"
happens to contain the
.B "-s"
option.
.LI "-w"
Causes the user to be sent a message on every terminal on which he is
logged in when the job has been completed.
.LI "-m"
Causes the user to be mailed a message when the job has been completed.
.LI "-x"
Turns off both the
.B "-m"
and
.B "-w"
options. They may be turned on again by a subsequent invocation.
.LI "-v"
Causes
.B "spr"
to display the job number of the spool job submitted.
.LE
.P
.H 1 "Spq"
.B "Spq"
may only be run whilst the spooler is functional; this is normally done
by the
.I "/etc/rc"
file, or when a job is submitted. Note that any number of instances of
.B "spq"
may be run on different terminals, and the spooler will attempt to keep
all of them refreshed. However, in order not to slow the system down too
much, it is not recommended that too many copies should run at once.
.P
The screen is split into two sections, both dynamically updated. The
upper section consists of the spool queue. This may be scrolled through
in the manner previously described. The lower section contains details
of printers known to the system and is fixed.
.H 2 "Job queue section"
Blank space may appear a the top of the screen as jobs are deleted,
however the cursor may not be moved into this area.
.P
Possible commands whilst the cursor is in this area are as follows. Note
that all commands applying to a job apply to the job corresponding to
the line on which the cursor sits. Also note that only the user
concerned, or a user with operator or higher privilege may change the
details of a job.
.VL 12 2
.LI "ctrl-F"
next page.
.LI "ctrl-B"
previous page.
.LI "ctrl-U"
previous half page.
.LI "ctrl-D"
next half page.
.LI "ctrl-L"
redraw screen.
.LI "j"
next line.
.LI "k"
previous line.
.LI "A"
abort the job - printing will be stopped if in process. Charging is made
for the whole of the copy aborted.
.LI "c"
change the number of copies for the job. If printing is in progress, the
number of copies to be printed includes the current one.
.LI "f"
change the form type for the job.
.LI "h"
change the job name.
.LI "p"
change the priority of the job, which should be seen to move immediately
up or down the job queue.
.LI "P"
change the printer. Note that the printer name selected is inserted into
a blank printer field when the job is selected.
.LI "o"
switch to the printer list (only valid if privileged).
.LI "q"
quit out of
.B "spq" .
.LE
.P
Only changes to the number of copies will be effective once the job is
being printed.
.H 2 "Printer list section"
This section of the screen reflects all of the active printers. Up to 3
printers are supported at present, however this is easily changed, being
a compile time constant in the software.
.P
Each printer known to the spooler may be in one of 4 states.
.VL 15 2
.LI "Printing"
The printer is printing a job. The job number and user are displayed.
.LI "Idle"
The printer is ready to print a job, but none are available with the
given paper type.
.LI "Stopping"
The printer is printing the specified job, but a request has been made
for printing to stop at the end of the current job.
.LI "Halted"
The printer is known to the system, but has stopped. This is the initial
state, and only in this state can the printer or paper types be changed.
.LE
.P
The halted state may be re-entered if the printing process dies or is
killed. A possible reason for this is because the device name given
cannot be opened by the spooler process, which runs with userid
.B "spooler" .
.P
Commands available in this part of the screen are:
.VL 12 2
.LI "ctrl-L"
refresh screen.
.LI "j"
select next line.
.LI "k"
select previous line.
.LI "A"
abort current job.
.LI "D"
delete printer from list. The printer must be halted.
.LI "f"
change form type. The printer must be halted.
.LI "G"
start printer, which must be halted.
.LI "h"
halt printer at end of current job. The printer must be printing.
.LI "H"
halt printer at once. The printer must be printing or stopping.
.LI "N"
add a new printer. The printer name, line and paper type are entered.
Note that in this case, the "escape" key aborts the whole operation, not
just the current field as with other string options.
.LI "o"
Switch to job queue.
.LI "P"
change printer name. The printer must be halted.
.LI "q"
quit out of
.B "spq" .
.LI "r"
restart current job. One must be being printed.
.LE
.H 1 "Printer setup files"
By default, the line speed is set up at 9600 baud, with no tab
expansion, initialisation strings, x-on/x-off control etc. If the
printer works satisfactorily in this fashion further intervention is not
necessary.
.P
However in many cases it may be required to vary the baud rate and other
parameter settings for the line. This may be achieved by means of a
setup file for the printer. A setup file has to be created for each
paper type on each printer, however in many cases it may be appropriate
to create one and link them together.
.P
The directory
.I "/usr/spool/printers"
should contain a number of further directories with the same names as
the printers. Each of these directories should contain setup files for
each paper type, thus the setup file for paper type
.I "standard"
on printer type
.I "tally"
should live in
.I "/usr/spool/printers/tally/standard" .
This file could be linked to
.I "/usr/spool/printers/tallytwin/standard"
if required.
.P
The setup file consists of a series of keywords similar to
.B "stty" .
These keywords should be separated by newlines, and may be
.B "50" ,
.B "75" ,
.B "110"
etc up to
.B "9600"
to set the baud rate,
.B "olcuc" ,
.B "onlcr" ,
.B "ocrnl" ,
.B "onocr" ,
.B "onlret" ,
.B "ixon"
and
.B "ixany"
as in
.B "stty" .
.B "exptabs"
expands tabs to spaces.
.P
The keyword
.B "nohdr"
causes all header pages to be suppressed for that paper on that printer.
This might be suitable for label printing etc.
.P
Following these keywords, a setup string may be specified. The setup
string consists of the keyword
.B "setup="
followed by a string of characters up to a newline. The string of
characters are copied to the printer after the baud rate and
other parameters have been set up. All characters are taken literally
except
.B "\\\\"
and
.B "^" .
.P
.B "\\\\"
followed by
.B "^" ,
.B "\\\\" ,
.B "b" ,
.B "e" ,
.B "r"
or
.B "n"
may be used to
to denote
.B "^" ,
.B "\\\\" ,
backspace, escape, carriage return or linefeed respectively.
.B "\\\\"
followed by
.B "0"
and up to 3 octal digits or by
.B "x"
and up to 2 hex digits  may be used to generate that character.
.B "^"
followed by
.B "@"
to
.B "_"
may be used to denote the
corresponding control character, and
.B "^^"
to denote a
.B "^" .
.P
Either upper or lower case letters may be used in sequences introduced
by
.B "\\\\"
or
.B "^"
characters.
.P
An example of a spooler setup file might be:
.DS L
ixon
nohdr
setup=\\\\e[\\\\x42t
.DE
.P
This sets x-on/x-off control, suppresses headings, and transmits the
characters "escape", "[", "hex 42", "t" to the printer.
.P
The setup file is examined only when the printer first starts up. Thus
to re-read the setup file, the printer should be halted and then
restarted, using
.B "spq" .
.P
The printer is assumed to be set to the top of form when restarted. At
the conclusion of each job, or in between separate files of a single
job, a form feed is inserted. Multiple form feeds are everywhere
suppressed.
.H 1 "Priority"
A spool job may have a priority of 1 to 255. Users are restricted
normally to a smaller range, which can be individually determined, but
which is by default 100 to 200. A default priority for each user may be
set, but unless individually determined is 150.
.P
The effect of increasing the priority of a job is to increase its
chances of getting printed sooner, as follows.
.DL
.LI
When a job is added to the queue, a copy of the priority is made. This
is the working priority.
.LI
The bottom item on the queue is considered. If the priority of this item
is less than the working priority of the new job, then the working
priority of the new job is decremented and the process repeated with the
next item.
.LI
This process is continued until the job reaches the top of the queue or
a job is encounted with a priority the same as or greater than the
working priority.
.LI
The working priority is saved in case the job's priority is subsequently
changed. The change to the job's priority is reflected in the working
priority, and the job moved up or down the queue according to the above
rule.
.LE
.P
A facility is provided to charge users for spooler output. A charge for
each job is computed when each copy is completed as:
.DS I
(characters output * act * act) / (def * def * 1000)
.DE
.P
where
.I "act"
and
.I "def"
represent the actual priority of the job and
the default priority for the user respectively.
.P
If a job is aborted whilst printing, the whole of the job is still
charged for. The alternative is to allow users to cancel jobs as they
are printing the last page with impunity.
.H 1 "User control"
User privileges are examined and modified via the program
.B "spuser" ,
with the option
.B "-i" .
This program adjusts the user control and charging file
.I "/usr/spool/spufile" ,
however it is not interlocked. In order not to lose charging information
relating to jobs in process when invoked, it may be necessary to
temporarily stop the spooler.
.P
The interactive option may only be invoked by a user with administrator
privileges; if he deprives himself of those privileges, no warning is
given, but the change will not take effect until he exits from the program.
.P
The display is broadly similar to that of
.B "spq"
except that the screen is not split. The display takes the form
.DS I
User    Def  Min  Max   Charge   Priv
root    150  100  200        0      0
	.....
spooler 150  100  200       25      2
	.....
.DE
.P
The columns "Def", "Min" and "Max" give the default, minimum and maximum
priorities, "Priv" gives the privilege, 0, 1 or 2 for ordinary user,
operator and administrator respectively.
.P
Commands available are as follows; editing commands apply to the user
given by the line on which the cursor lies.
.VL 12 2
.LI "ctrl-F"
next page.
.LI "ctrl-B"
previous page.
.LI "ctrl-U"
previous half page.
.LI "ctrl-D"
next half page.
.LI "ctrl-L"
redraw screen.
.LI "j"
next line.
.LI "k"
previous line.
.LI "d"
change default priority.
.LI "l"
change minimum priority.
.LI "u"
change maximum priority.
.LI "c"
change charge.
.LI "p"
change privilege.
.LI "q"
quit out of
.B "spuser" .
.LE
.H 1 "Sstop"
.B "Sstop"
is used to stop the spooler gracefully. All printers will stop what
they are doing ready to resume when the spooler is restarted. To avoid
wasting paper it is best to wait until they are all idle.
.P
Only an operator or administrator can run
.B "sstop" .
A confirmation message is requested - reply 'y' to continue.
.H 1 "Outline of implementation"
The spooler is implemented as 4 user-level programs documented above,
namely
.B "spr" ,
.B "spq" ,
.B "spuser"
and
.B "sstop" ,
together with 4 programs intended for internal consumption, held in the
directory
.I "/usr/spool/progs" .
.VL 15 2
.LI "spshed"
is the spool scheduler. Requests are sent by other programs over a FIFO,
as a standard request packet with an action code. This program maintains
the details of jobs and printers, writing details when appropriate to
the job and printer files. Priorities, control of copies, and charging
are performed in this program.
.P
Subprocesses may be forked off to implement "mail" and "write" options.
These are not waited for until the next time such an option is required,
so there may be a zombie child process associated with it.
.P
.B "Spq"
processes are warned by a signal to reread the job queue. Printer
processes are likewise sent "restart job" and "abort job" messages.
.P
.B "Spshed"
is made setuid to the superuser in order to ensure that signals can be
sent. In many versions of UNIX they cannot.
.P
If the spool scheduler works satisfactorily with setuid
.B "spooler"
rather than setuid
.B "root" ,
(check correct functioning of "queue refresh" functions of
.B "spq",
together with "abort" and "restart" on the current job to the
printers), then it is suggested that this be adopted instead.
.LI "spd"
is the printer daemon process. This accepts requests from the spool
scheduler process on a pipe. Completion messages are passed back to the
scheduler on its control FIFO.
.P
Signals from the spool scheduler process are also handled for "abort
current job" and "restart current job".
.P
The process is invoked when the printer is started, with the line name,
printer type and paper type as arguments.
.LI "spwrite"
is used to implement the "write message to user terminals" option. A
list of user names may be supplied to the program, and the message on
the standard input.
.P
.B "Spshed"
only invokes this program with one user name, however this program
could be invoked if desired to write messages to a named list of users.
It is the only internal program of the spooler which is thus defined for
possible other use.
.LI "ufcreat"
is used to create the user control file if it does not exist, and to
rewrite it if it is noticed to be older than the password file (in case
new users are added).
.LE
.H 1 "Files and directories"
.VL 20 2
.LI "/usr/spool/spufile"
is the user control file, which holds maximum, minimum and default
priorities, charges and privileges.
.LI "/usr/spool/sputmp"
may be created by
.B "ufcreat"
whilst rewriting the file
.I "/usr/spool/spufile" .
.LI "/usr/spool/spd"
is the directory used to hold spool jobs.
.LI "/usr/spool/printers"
holds setup files for various printers.
.LE
.P
Inside the directory
.I "/usr/spool/spd"
.VL 15 2
.LI "spshed_req"
is the control FIFO for the spool scheduler, also used as a lock file
for the process.
.LI "spshed_reps"
if it exists is used to hold messages which the scheduler may generate.
.LI "spshed_pfile"
contains the list of printers.
.LI "spshed_jfile"
contains details of the job queue.
.LI "SPnnnnnnn"
contains a job to be printed.
.LE