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 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 , or with . 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 or with . 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)