1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-03-07 03:15:54 +00:00
Files
Lars Brinkhoff 6e18f5ebef Extract files from tape images.
Some tapes could not be extracted.
2021-01-29 10:47:33 +01:00

774 lines
19 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
MODULE MXHOST =
BEGIN
!
! COPYRIGHT (c) 1985 BY
! DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
!
! THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
! ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE
! INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER
! COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
! OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY
! TRANSFERRED.
!
! THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
! AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
! CORPORATION.
!
! DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
! SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
!
!++
! FACILITY: Decmail/MS - Message eXchange Host File Parsing Routines
!
! ABSTRACT: This module contains routines to parse files containing
! host/routing information. At present, the only file format understood is
! the one used by the DECNET-HOSTS.TXT file.
!
! ENVIRONMENT: Tops-10/Tops-20
!
! AUTHOR: Richard B. Waddington, CREATION DATE: 18-February, 1985
!
! MODIFIED BY:
!
! MX: VERSION 1.0
! 01 -
!--
!
! INCLUDE FILES:
!
%IF %SWITCHES(TOPS20) %THEN
LIBRARY 'monsym';
UNDECLARE time;
LIBRARY 'mxjlnk';
%FI
LIBRARY 'mxnlib'; ! Our version of NML's utility library
LIBRARY 'mxlib';
LIBRARY 'tbl';
!
! TABLE OF CONTENTS:
!
FORWARD ROUTINE
mx$parse_host_file,
parse_line,
ptext,
pnode, ![rbw]Add new routine
get_key,
get_data,
loop_check;
!
! MACROS:
!
MACRO parse_block =
VECTOR[2] INITIAL(0,0) %,
parse_blk =
VECTOR[] %;
!
! EQUATED SYMBOLS:
!
LITERAL
txt_ptr = 0,
txt_cnt = 1;
!
! OWN STORAGE:
!
!
! EXTERNAL REFERENCES:
!
EXTERNAL
uc_tab, !Upper case conversion table
nodnam;
EXTERNAL ROUTINE
tbl_lookup,
tbl_add,
nmu$text_manager,
nmu$memory_manager,
nmu$sched_manager,
mx$release_asciz,
mx$file_routines,
mx$error_routines,
mx$database_routines;
%global_routine('MX$PARSE_HOST_FILE', fil_ptr, tab_, format): = !
!++
! FUNCTIONAL DESCRIPTION:
!
! This routine uses .FIL_PTR as the file spec of the file containing host
! name/routing information, and parses that file. The information contained
! in the file is added to the TBLUK table using calls to the MX$DATA_ADD_NODE
! routine.
!
! FORMAL PARAMETERS:
!
! FIL_PTR: A CH$PTR to an asciz filespec.
!
! TAB: An address containing the address of a TBLUK table.
!
! FORMAT: An integer value which determines which file format to use.
! The following formats are defined:
!
! 1: DECNET-HOSTS.TXT file format
! Others are undefined.
!
! IMPLICIT INPUTS:
!
! NONE
!
! IMPLICIT OUTPUTS:
!
! The TBLUK table gets updated and, in fact, a new larger table may be
! allocated if necessary. Consequently the table address may change.
!
! ROUTINE VALUE:
!
! 1 If successful, 0 otherwise
!
! COMPLETION CODES:
!
! NONE
!
! SIDE EFFECTS:
!
! NONE
!
!--
BEGIN
BIND
tab = .tab_: tbl;
STACKLOCAL
buf: VECTOR[CH$ALLOCATION(132)];
LOCAL
len,
fid,
line,
error,
data_block,
ndex,
pause_flag,
node;
IF .format NEQ mp$decnet_hosts_format
THEN
RETURN $error( CODE=mp$uhf, !Unsupported format
SEVERITY=$severe,
FACILITY=$internal);
pause_flag = .tab[TBL_ACTUAL_ENTRIES] NEQ 0;
fid = mx$file_open(.fil_ptr, file_access_read_only, error);
IF .fid LEQ 0
THEN
BEGIN
%IF %SWITCHES(TOPS20) %THEN IF .error EQL uf$fnf
%ELSE IF .error EQL uf$fpe %FI
THEN
RETURN $true;
$error( CODE=uf$fof, !File open error
SEVERITY=$warning,
FACILITY=$internal,
MESSAGE_DATA=.fil_ptr,
OPTIONAL_MESSAGE=$error_code,
OPTIONAL_DATA=.error);
RETURN 2
END;
line = 0;
WHILE (len = mx$file_read(.fid, CH$PTR(buf), 132, error)) GTR 0 DO
BEGIN
node = 0;
line = .line + 1;
IF .pause_flag
THEN
nmu$sched_pause();
IF NOT parse_line(CH$PTR(buf), format, node, data_block)
THEN
$error( CODE=mp$syn, !Syntax error in file
SEVERITY=$warning,
FACILITY=$internal,
MESSAGE_DATA=(.line, .fil_ptr));
IF .node GTR 0
THEN
BEGIN
MX$DATA_ADD_NODE(tab, .node, ndex, .data_block);
mx$release_asciz(.node);
END
END;
IF .len NEQ 0
THEN
$error( CODE=uf$frf, !File read error
SEVERITY=$warning,
FACILITY=$internal,
MESSAGE_DATA=.fil_ptr,
OPTIONAL_MESSAGE=$error_code,
OPTIONAL_DATA=.error);
MX$FILE_CLOSE(.fid, file_abort, error);
RETURN 1
END; !End of TEMP_EXAMPLE
%routine('PARSE_LINE', ptr, format, node_, data_) = !
!++
! FUNCTIONAL DESCRIPTION:
!
! This routine parses a line from a host-name file. FORMAT is used to
! determine the format of the file. Initially, there will be only one
! format, that used in DECNET-HOSTS.TXT. Eventually other formats may be
! added.
!
! FORMAL PARAMETERS:
!
! PTR: A CH$PTR to the line of text in memory to be parsed.
!
! FORMAT: 1 - DECNET-HOSTS.TXT format. Others are undefined.
!
! NODE: The address to return the address of the node-name in.
!
! DATA: The address to return the address of the PMR/synonym block
! in.
!
!
! IMPLICIT INPUTS:
!
! NONE
!
! IMPLICIT OUTPUTS:
!
! NONE
!
! COMPLETION CODES:
!
! NONE
!
! SIDE EFFECTS:
!
! NONE
!
!--
BEGIN
BIND
node = .node_,
data = .data_;
LITERAL ![rbw]
syntax = 1, ![rbw]Just a syntax error
looperr = 3; ![rbw]Loops are not allowed in PMR strings
LOCAL
ch,
key,
nptr,
ncnt,
bptr,
error, ![rbw]Storage for error info
len,
idx,
key_block: parse_block,
pmr_block: parse_block;
GLOBAL
buf: VECTOR[CH$ALLOCATION(132)];
STACKLOCAL
loops: TBLUK_TABLE(10); !Use with loop_check ONLY.
STACKLOCAL
swtchs: tbluk_table(0,
'INVALID',$invalid,(),
'STRIP-QUOTES',$strip,()
);
error = 0; ![rbw]
bptr = CH$PTR(buf);
data = len = 0;
ch = ptext(ptr, key_block);
SELECTONE .ch OF
SET
![rbw]Add "Synonym" handling code
[%C'=']:
BEGIN
!Parse the Synonyn definition
ch = ptext(ptr, pmr_block);
selectone .ch of
SET
[%C';', %C'!', %O'15', 0]:
BEGIN
!Build the equivalent SMTP string "%A@newnod"
CH$COPY(3,CH$PTR(UPLIT('%A@')),
.pmr_block[txt_cnt],.pmr_block[txt_ptr],
0,
3+1+.pmr_block[txt_cnt], CH$PTR(buf));
data = get_data(CH$PTR(buf),
.pmr_block[txt_cnt]+3,
mp$pmr);
END;
[OTHERWISE]:
RETURN $error( CODE=mp$tel,
SEVERITY=$warning,
FACILITY=$internal,
MESSAGE_DATA=.ptr);
TES
END;
[%C',']:
![rbw]Rewrite PMR handling code
BEGIN
!Assume a syntax error, and parse the first node of the PMR string
error = syntax;
IF pnode(ptr, pmr_block)
THEN
BEGIN
!It parsed, so start building the SMTP routing string in BUF
CH$WCHAR_A(%C'@', bptr);
CH$MOVE(.pmr_block[txt_cnt], .pmr_block[txt_ptr], .bptr);
bptr = CH$PLUS(.bptr, .pmr_block[txt_cnt]);
len = .pmr_block[txt_cnt] + 1;
!Enter the first node in the loops table
loop_check(loops,pmr_block);
!There must be at least 2 nodes, but there can be many. The following loop
!parses out successive NODE::s and builds the appropriate SMTP routing
!string. The last NODE:: is a special case and is handled separatly...
nptr = ncnt = 0;
WHILE $true DO
BEGIN
IF pnode(ptr, pmr_block)
THEN
BEGIN
!We got a node. If this isn't the first time through, continue building
!the SMTP routing string.
IF .nptr NEQ 0
THEN
BEGIN
CH$WCHAR_A(%C',', bptr);
CH$WCHAR_A(%C'@', bptr);
CH$MOVE(.ncnt, .nptr, .bptr);
bptr = CH$PLUS(.bptr,.ncnt);
len = .len + .ncnt + 2;
END;
!Update the "Next Pointer" and the "Next Count"
nptr = .pmr_block[txt_ptr];
ncnt = .pmr_block[txt_cnt];
!Make sure there are no loops in the PMR string
IF NOT loop_check(loops,pmr_block)
THEN
BEGIN
error = looperr;
EXITLOOP;
END;
!See if we are done. If the current character indicates a comment, or
!the end of the line, then we have successfully parsed the line.
!Otherwise, we loop back, and continue parsing NODE::s...
SELECTONE CH$RCHAR(.ptr) OF
SET
[%C';', %C'!', %O'15', 0]:
BEGIN
error = 0;
EXITLOOP;
END;
TES
END
ELSE
EXITLOOP;
END; !End of WHILE $true
!If there were no errors, then finish building the SMTP routing string. If
!you had just parsed FOO::BAR::SNAFU::ACME:: the routing string you build
!will look like @FOO,@BAR,@SNAFU:%A@ACME. Ncnt and nptr hold the byte
!count and byte pointer which describes the last node.
IF NOT .error
THEN
BEGIN
CH$COPY(4,CH$PTR(UPLIT(':%A@')),
.ncnt,.nptr,
0,
4+1+.ncnt, .bptr);
len = .len + .ncnt + 4;
data = get_data(CH$PTR(buf), .len, mp$pmr);
END
END;
loop_check(loops,0);
SELECTONE .error OF
SET
[syntax]: RETURN 0;
[looperr]: RETURN $error(CODE=mp$pld,
SEVERITY=$warning,
FACILITY=$internal,
MESSAGE_DATA=.pmr_block[txt_ptr])
TES;
END;
[%C'/']:
BEGIN
ptext(ptr,pmr_block);
CH$WCHAR(0,
CH$MOVE(.pmr_block[txt_cnt], .pmr_block[txt_ptr], .bptr));
IF NOT tbl_lookup(swtchs, .bptr, idx)
THEN
RETURN $error( CODE=mp$tel,
SEVERITY=$warning,
FACILITY=$internal,
MESSAGE_DATA=.pmr_block[txt_ptr]);
!Assuming that the switch is /INVALID or /STRIP-QUOTES...
data = .swtchs[.idx, TBL_DATA];
END;
[%C';', %C'!', %O'15', 0]:;
[OTHERWISE]:
RETURN $error( CODE=mp$tel,
SEVERITY=$warning,
FACILITY=$internal,
MESSAGE_DATA=.ptr);
TES;
IF .key_block[txt_cnt] EQL 0
THEN !The line had no key
IF .pmr_block[txt_cnt] GTR 0
THEN
RETURN $error( CODE=mp$mkf, !Missing key field
SEVERITY=$warning,
FACILITY=$internal)
ELSE
RETURN 1; !Line was blank or comment
node = GET_KEY(key_block);
loop_check(loops,0);
RETURN 1;
END; !End of TEMP_EXAMPLE
%routine('LOOP_CHECK',table_, node_) =
BEGIN
BIND
table = .table_: TBL,
node = .node_: parse_blk;
LOCAL
key,
ndx;
IF .table[TBL_ACTUAL_ENTRIES] EQL 0
THEN
tbl_add(table,nodnam,ndx,0);
IF node NEQ 0
THEN
BEGIN
key = nmu$memory_get(CH$ALLOCATION(.node[txt_cnt]+1));
CH$COPY(.node[txt_cnt],.node[txt_ptr],
0,
.node[txt_cnt]+1,CH$PTR(.key));
RETURN tbl_add(table,.key,ndx,CH$ALLOCATION(.node[txt_cnt]+1));
END
ELSE
BEGIN
INCR i FROM 1 TO .table[TBL_ACTUAL_ENTRIES] DO
IF .table[.i,TBL_DATA] NEQ 0
THEN
nmu$memory_release(.table[.i,TBL_KEY],.table[.i,TBL_DATA]);
table[TBL_ACTUAL_ENTRIES] = 0;
END;
RETURN 0
END;
%routine('PTEXT', p_, blk_) = !
!++
! FUNCTIONAL DESCRIPTION:
!
! This routine parses text. The pointer is advanced until either a
! comma, a "=", a ";", a "!", a CR, or a 0 is seen. Spaces, tabs, and
! switches will delimit the text, but will otherwise be ignored. A count of
! the characters in the text and a CH$PTR to the beginning of the text are
! returned in the parse block.
!
! FORMAL PARAMETERS:
!
! P: The address of a CH$PTR pointing to the beginning of the switch
! BLK: The address of a parse_block.
!
! IMPLICIT INPUTS:
!
! NONE
!
! IMPLICIT OUTPUTS:
!
! NONE
!
! ROUTINE VALUE:
!
! The terminator
!
! COMPLETION CODES:
!
! NONE
!
! SIDE EFFECTS:
!
! NONE
!
!--
BEGIN
BIND
p = .p_,
blk = .blk_: VECTOR[2];
LOCAL
start_flag: INITIAL(0),
end_flag: INITIAL(0),
cnt: INITIAL(0);
blk[txt_cnt] = 0;
WHILE 1 DO
BEGIN
SELECTONE CH$RCHAR(.p) OF
SET
[%C' ',%C' ']: IF .start_flag THEN end_flag = 1;
[%C':', %C',', %C'!', %C'=', %C'/',
%C';', %o'0', %O'15']:
IF .start_flag
THEN
EXITLOOP
ELSE
RETURN -1;
[OTHERWISE]: BEGIN
IF .start_flag EQL 0
THEN
BEGIN
start_flag = 1;
blk[txt_ptr] = .p;
END;
IF NOT .end_flag
THEN
blk[txt_cnt] = .blk[txt_cnt] + 1;
END;
TES;
p = CH$PLUS(.p, 1);
END;
RETURN CH$RCHAR_A(p);
END; !End of PTEXT
%ROUTINE('GET_KEY', blk_) = !
!++
! FUNCTIONAL DESCRIPTION:
!
! This routine gets memory for the key string, copys the key string, and
! returns the address of the key string to the caller.
!
! FORMAL PARAMETERS:
!
! P: The address the key's parse block.
!
! IMPLICIT INPUTS:
!
! NONE
!
! IMPLICIT OUTPUTS:
!
! NONE
!
! COMPLETION CODES:
!
! NONE
!
! SIDE EFFECTS:
!
! NONE
!
!--
BEGIN
BIND
blk = .blk_: VECTOR[2];
LOCAL
b;
b = nmu$memory_get(CH$ALLOCATION(.blk[txt_cnt] + 1));
IF .b NEQ 0
THEN
CH$COPY(.blk[txt_cnt], .blk[txt_ptr],
0,
.blk[txt_cnt] + 1, CH$PTR(.b));
RETURN .b
END; !End of GET_KEY
%ROUTINE('GET_DATA', ptr, len, typ) = !
!++
! FUNCTIONAL DESCRIPTION:
!
! This routine gets memory for the data header, and the data string. It
! sets up the data header and returns the address of the data header to the
! caller.
!
! FORMAL PARAMETERS:
!
! PBLK: The address of the pmr string's parse block.
! SBLK: The address of the synonym's parse block.
!
! IMPLICIT INPUTS:
!
! NONE
!
! IMPLICIT OUTPUTS:
!
! NONE
!
! COMPLETION CODES:
!
! NONE
!
! SIDE EFFECTS:
!
! NONE
!
!--
BEGIN
LOCAL
h: REF list_blk,
b;
IF .len LEQ 0
THEN
RETURN 0;
h = nmu$memory_get(list_block_size);
IF .h NEQ 0
THEN
BEGIN
h[lst_stat] = .typ;
h[lst_data] = b = nmu$memory_get(CH$ALLOCATION(.len + 1));
IF .b NEQ 0
THEN
CH$COPY(.len, .ptr,
0,
.len + 1, CH$PTR(.b));
END;
RETURN .h;
END; !End of GET_DATA
%routine('PNODE', p_, blk_) =
!This routine added in edit [rbw]
!++
! FUNCTIONAL DESCRIPTION:
!
! This routine parses a node name. PTEXT is called to parse some
! arbitrary text. If the 2 characters following the text are not "::",
! then this is not a node name. If it is a node name, white-space is
! skiped, and the pointer is advanced to the next non-white-space
! character.
!
! FORMAL PARAMETERS:
!
! P: The address of a CH$PTR pointing to the beginning of the switch
! BLK: The address of a parse_block.
!
! IMPLICIT INPUTS:
!
! NONE
!
! IMPLICIT OUTPUTS:
!
! NONE
!
! ROUTINE VALUE:
!
! -1 if we parsed a node name, -2 otherwise.
!
! COMPLETION CODES:
!
! NONE
!
! SIDE EFFECTS:
!
! NONE
!
!--
BEGIN
BIND
p = .p_,
blk = .blk_: VECTOR[2];
IF PTEXT(p, blk) EQL %C':'
THEN
IF CH$RCHAR_A(p) EQL %C':'
THEN
WHILE $true DO
SELECTONE CH$RCHAR(.p) OF
SET
[%C' ', %C' ']: p = CH$PLUS(.p,1);
[OTHERWISE]: RETURN -1
TES;
RETURN -2
END;
END !End of module MXHOST
ELUDOM