RFC 105

Network Specifications for Remote Job Entry and Remote Job Output Retrieval at UCSB

πŸ“… published March 1971, from ietf

RFC 105 πŸŽ€ Network Specifications for Remote Job Entry and Remote Job Output Retrieval at UCSB

okay bestie, let's get into the tea 🫢 this one is Network Working Group RFC 105, and the title is Network Specifications for Remote Job Entry and Remote Job Output Retrieval at UCSB. It was written by James E. White from the Computer Research Lab. at the University of California, Santa Barbara, California. It's filed as Category: Informational and it's dated March 1971 πŸ“…. The title block doesn't list anything it obsoletes or updates, so no drama there ✨

In the discussions that follow, 'byte' means 8 bits, with those eight bits numbered 0-7 from left to right. Keep that in your head, it shows up everywhere 🧚

I - Remote Job Entry (RJE) πŸ’–

UCSB will accept input of pseudo card files for batch processing at socket number x'200', site 3. Network users SHOULD obtain an account number from the UCSB Computer Center. Account #1025 and programmer names like 'UCLA', 'SRI', 'UTAH', etc. MAY be used during checkout πŸ“

The 360/75 runs under OS MVT and HASP. Users submit jobs to HASP for scheduling and then OS executes them, and the middleman is a process called RJE. RJE is addressed as socket number x'200' and can be invoked through the Logger. This section is written to give programmers the info they need to talk to RJE, and it assumes you already know the batch services the Computer Center offers and their job control language (JCL) requirements πŸ™ˆ

RJE handles all its Network transactions through the NCP, which runs under the Host-Host protocol of 3 August 1970. It expects the first message it gets to be Type 0. It throws away the first eight bits (the message type), assuming they're zeros, and after that, for the whole life of the connection, it doesn't care about IMP-message boundaries at all πŸ’…

I.A - Logging into RJE

To submit one or more jobs for batch processing, the Network user MUST establish a simplex connection with RJE. RJE only lives in core memory while one of these simplex connections is open (so, while a user is sending a file). The rest of the time it sits on direct-access storage and MUST be invoked through the Logger. You can always start a login sequence by requesting a connection to socket x'200' πŸ¦‹

RJE does not serve multiple users at once. So if a connection request comes in to that socket while RJE is busy, the NCP queues the request. When the current file transmission finishes, RJE listens for and accepts the next request in its queue (if there is one). If nothing is queued, it terminates and frees up the main storage it was using 🌸

When RJE isn't in core, the Logger listens on socket x'200'. It rejects the first call it gets, reads RJE into core, and dispatches it. Then RJE listens on that socket. So to start a login, you request a connection to socket x'200'. If it's accepted, you're in contact with RJE. If it's rejected, you SHOULD reissue the connection request, and when it's accepted you'll be connected to RJE. If you get rejected a second time, that means the NCP's resources ran out 😭 Once the connection is established, RJE considers you logged in ✨

To stop RJE from getting hogged by one user, the software can terminate a connection if RJE has to wait longer than a certain amount of time for a transmission from the connected user. For now that limit is set at one minute per record, but it MAY be shortened or lengthened as required in the future. Unless that happens, RJE keeps the connection open indefinitely. Card images are accepted over the connection, and each one is passed to HASP as soon as it arrives. The user is expected to close the connection once the file has been sent. RJE reads that close as an end-of-file indication, and the user is then considered logged off πŸ‘‘

I.B - The RJE Connection

RJE expects the first byte it receives over the connection to be zeros, which indicates message Type 0. It throws this byte away without looking at it, and from then on it doesn't pay any attention to IMP-message boundaries. The second byte received is read as flags that describe the format of the data (file) that's coming next. Here's how that byte works:

Bits 0-1 = 00:  file follows as Class A (stream-oriented)
                input.
         = 01:  not defined, SHOULD NOT occur.
         = 10:  file follows as Class B (variable-length
                record) input.
         = 11:  file follows as Class C (fixed-length record)
                input.
Bits 2-7     :  not examined, SHOULD be zeros.

Once you've made this declaration, it sticks for the life of the connection πŸ”’

No matter which input class you pick, you send your file as card images. Each one gets padded on the right with blanks, or truncated on the right to 80 bytes if it's too long 🧚 The file MUST be structured exactly as if it were being placed on the card reader at the Computer Center. Every job in the file MUST have a job card and all the other usual JCL. (Batching jobs together is allowed and RJE doesn't notice.) If a job needs special, non-resident disk(s) and/or tape(s) mounted, a special JCL card MUST be inserted immediately after that job's job card, and it MUST have this format:

        /*SETUP        vol-ser , vol-ser ,...
                              1         2

where 'vol-ser ' is the volume serial number of a volume requiring mounting, laid out like this:

where 'vol-ser ' is the volume serial number of a volume requiring
              i
mounting.  '/*SETUP' begins in column 1; 'vol-ser ' MUST begin in
                                                 1
column 16.

After that, the job enters the System in a HASP hold status until the operator mounts the required volume(s). Heads up, though πŸ’€

If the user neglects to declare all such required volumes, the job is subject to immediate cancellation. So list every volume, babe!

Every card in the file that isn't inside a SYSIN data set MUST consist of valid EBCDIC characters 🌈

I.B.1 - Class A (Stream-Oriented) Input

If you declared Class A, the third byte RJE receives over the connection is read as a break character declaration. Every byte after that gets compared to that character. Anything that isn't the break character is just the next byte of the current card image. When RJE hits the break character, the byte before it is treated as the last byte of the current card image. That card image then gets padded or truncated as needed and passed to HASP. Zero or more non-break characters MAY occur between breaks. So for Class A, the data you send to RJE SHALL have this form:

    1       1       1            variable         1
+-------+-------+-------+  / +------//--------+-------+ \
|       |       | BREAK | /  |                | BREAK |  \
| x'00' | x'00' | CHAR. | \  |  CARD  IMAGE   | CHAR. |  / ...
+-------+-------+-------+  \ +------//--------+-------+ /

Each field's length is given in bytes. Zero or more occurrences of the quantity in [angle brackets] MAY be sent before the user closes the connection πŸ’œ

I.B.2 - Class B (Variable-Length Record) Input

If you declared Class B, then everything after those first two bytes is a contiguous string of variable-length records. Each record has a one-byte op code (the op code SHOULD be x'01'), and then a two-byte length field that gives the unsigned length in bits of the variable-length text field right after it. The text field MAY be zero or more bytes long, and the length field MUST contain an integer that's a multiple of 8. The text field is one card image, which RJE pads or truncates as needed and passes to HASP. So for Class B, the data sent to RJE SHALL have this form:

    1       1            1       2      L bits
+-------+-------+  / +-------+-------+-----//-----+ \
|       |       | /  |       |       |    TEXT    |  \
| x'00' | x'80' | \  | x'01' |   L   | card image |  / ...
+-------+-------+  \ +-------+-------+-----//-----+ /

Each field's length is given in bytes, except where it's said otherwise. Zero or more occurrences of the quantity in [angle brackets] MAY be sent before the connection is closed πŸŽ€

I.B.3 - Class C (Fixed-Length Record) Input

If you declared Class C, everything after the first two bytes is a contiguous string of fixed-length, 80-byte card images. So for Class C, the data sent to RJE SHALL have this form:

    1       1                  80
+-------+-------+  / +--------------------+ \
|       |       | /  |                    |  \
| x'00' | x'C0' | \  |     card image     |  / ...
+-------+-------+  \ +--------------------+ /

Each field's length is given in bytes. Zero or more occurrences of the quantity in [angle brackets] MAY be sent before the connection is closed 🫢


II - Remote Job Output Retrieval (RJOR) πŸ¦‹

Class A SYSOUT output from jobs you submitted through RJE for batch processing at UCSB MAY be obtained by contacting socket x'300', site 3. There's one catch: when the job was submitted, the character 'T' had to show up as the eighth positional accounting parameter on the job card. The output gets retrieved on request and relayed to the Network user by a process called RJOR, which is addressed as socket x'300'. RJOR can be invoked through the Logger. This section gives programmers the info they need to talk to RJOR 🌸

RJOR handles all its Network transactions through the NCP, which runs under the Host-Host protocol of 3 August 1970. RJOR expects the first message it gets to be Type 0. It discards the first byte, assuming it's zeros, and after that, for the whole life of the connection, it ignores IMP-message boundaries. It's the same energy in reverse: the first message RJOR sends is also Type 0, so its first byte is zeros, and for the rest of the connection IMP-message boundaries don't matter 🧚

II.A - Logging into RJOR

To grab output from a batch-mode job, the Network user MUST establish a full duplex connection with RJOR. RJOR only lives in core while it's in use. That means while control information or a file is moving to or from a user, or while RJOR is waiting for a previously requested output file (or files). The rest of the time it sits on direct-access storage and MUST be invoked through the Logger. You can always start a login sequence by requesting a connection to socket x'300' πŸ’–

If a connection request comes in to that socket while another user is being logged in, the NCP queues it. Once the current connection ends, RJOR listens for and accepts the next request in its queue (if there is one). If nothing's queued and RJOR has fulfilled all of its output file requests, it terminates and frees the main storage it was using 🌈 When RJOR isn't in core, the Logger listens on socket x'300', rejects the first call it gets, reads RJOR into core, and dispatches it. RJOR then listens on that socket. So to start a login, request a connection to socket x'300'. If it's accepted, you're in contact with RJOR. If it's rejected, you SHOULD reissue the connection request, and when it's accepted you'll be connected to RJOR. A second rejection means the NCP's resources ran out 😭 Once this first half of the required duplex connection is set up, RJOR considers you logged in πŸ‘‘

Over this first connection (hereafter called the Input Connection),

okay so the user sends RJOR some flags saying which function(s) to perform πŸ’…, plus the name of the job those functions should be applied to. then RJOR closes this connection 🫢

next, RJOR sends control info about what's going on with the request, and the output file if one was asked for, over a secondary connection πŸ¦‹. this one runs between RJOR's socket x'301' at site 3 and the socket on the user's side whose number is one less than the socket RJOR was first contacted on.

the request might be immediately executable or it might not πŸ™ˆ. if it IS, RJOR issues a connection request to the designated user receive socket, and once that connection is established it sends whatever control info fits, along with the user's output (if required). then RJOR closes the connection and the user is considered logged out πŸ‘‹

if the request can't be immediately satisfied (like, the job whose output they want hasn't been submitted yet, or hasn't finished running, e.g.), RJOR opens the second connection just long enough to tell the user about the delay, and then closes it 😭. later, when the request can finally be serviced, the connection gets reopened, the required data is sent, the connection is closed, and then the user is considered logged out ✨

no monopolizing allowed πŸ’… so RJOR doesn't get hogged by one user, the software has a provision for terminating a connection if RJOR is ever made to wait longer than a certain amount of time for a transmission to or from the connected user. for now that limit is one minute per record, but it may be shortened or lengthened as required in the future 🌸

II.B - The Input Connection πŸŽ€

okay so the very first byte RJOR gets over the Input Connection is supposed to be zeros, which means message Type 0 🧚. RJOR tosses that byte without looking at it, and after that it doesn't care about IMP-message boundaries at all. the second byte gets read as the flags that say what functions to perform. right after the flag byte, RJOR expects an eight-byte, EBCDIC job name, padded on the right with blanks if it needs to. here's how the flag byte works:

     Bit 0 = 1:  transmit the output generated by the specified job.
     Bit 1 = 1:  purge the output file created by the specified job.
     Bit 2 = 1:  wait as long as is required to execute the
                 function(s) specified by Bits 0-1.
           = 0:  if the function(s) specified by Bits 0-1 cannot be
                 executed immediately, simply return an indication of
                 that fact.
     Bit 3 = 1:  an earlier request pertaining to the specified job
                 which exercised the wait-for-output (Bit 2) option
                 is to be canceled.
     Bits  4-7:  not examined, should be zeros.

any combo of Bits 0-2 is totally permissible ✨. if Bit 3 = 1, no other bits get looked at. if Bit 0 = 1 AND Bit 1 = 1, the output file is transmitted before it gets purged. also, if two jobs with the same name run one after the other, the output from the second job overlays the one from the first 😩. so in that case the user should purge the first job's output after it has been transmitted to them, so that asking for the second job's output won't just hand back a second copy of the first job's output πŸ’€


II.C - The Output Connection πŸ¦‹

RJOR can open the output connection either one or two times as the result of a single transmission on the Input Connection πŸ’–. every time, the first byte sent is zeros (message Type 0 again), and for the whole life of the connection IMP-message boundaries don't matter. after that first byte, RJOR sends the name of the job the response is for. the job name sits in an 8-byte field that matches the one the user gave over the Input Connection. then RJOR sends zero or more variable length logical records. each one is made of a one-byte op code, then a two-byte length field giving the unsigned length in bits of the variable length text field that follows. the text field can be zero or more bytes long, and the length field always holds a multiple of eight 🌈

the op codes that exist right now are listed in Figure 1. an op code of x'01' means the text field holds one record from one of the SYSOUT data sets the job made, the one whose output was requested. every x'01' record has the same length field value. data sets with other record lengths get padded on the right with blanks, or cut off on the right, so they fit that standard record length πŸ“. carriage control characters that would normally sit in column 1 of printer-bound output have been thrown out, so they never show up 🫠*. the records go to the user in the same order they'd print, and together they include everything that would be in the printed output except for HASP separator sheets 🧚

in all logical records other than the x'01' ones, the length field is zero, and the op code carries the whole meaning of the record πŸ’œ

________________________________________________________________________
*This restriction is temporary; a fix is in the works and will be
announced.

Figure 1.  Output Connection Op Codes
---------  --------------------------

Op Code
 (Hex)    Name                   Explanation
-------   ----                   -----------

  00      End-of-File.           All output from the job has been
                                 transmitted (follows last op-code-x'01'
                                 logical record).
  01      Output.                The text field contains one record of
                                 one SYSOUT data set generated by the
                                 job.
  02      Output file purged.    Output from the job has been purged as
                                 requested.
  03      No core for buffer.    Insufficient main storage is available
                                 for transmitting output from the job.
                                 The transmission request has been
                                 aborted and the purge request (if any)
                                 has been suppressed.
  04      I/O Error reading      An irrecoverable I/O error was
          file.                  encountered reading the output file.
                                 The transmission request has been
                                 aborted and the purge request (if any)
                                 suppressed.
  05      I/O Error purging      An irrecoverable I/O error was
          file.                  encountered purging the output file.
                                 The purge request was aborted.
  06      No queue space for     Output from the job was not available
          request.               and the wait-for-output option was
                                 specified, but RJOR's resources were
                                 insufficient to queue the request,
                                 which was suppressed.
  07      Waiting for output.    Output from the job is not available
                                 and the wait-for-output option was
                                 specified.  RJOR is waiting for the
                                 job's output.
  08      Canceled request not   The user requested that a previously
          found.                 made request specifying the
                                 wait-for-output option be canceled.  No
                                 such request was found by RJOR.
  09      Request canceled.      At the user's request, a previously
                                 made request specifying the
                                 wait-for-output option has been
                                 canceled.
  0A      I/O Error seeking      An irrecoverable I/O error was
          file.                  encountered attempting to locate output
                                 from the job.  The user's request was
                                 aborted.
  0B      Output not found.      Output from the job was not found.  The
                                 wait-for-output option was not
                                 specified by the user.
       [ This RFC was put into machine readable form for entry ]
         [ into the online RFC archives by Randy Dunlap 4/97 ]
RFC>>>
πŸ“¦ where this page comes from