s0 MX042.ND0MX042.NBACKUP/INTERCHANGE/BLOCK=8192 MX_EXAMPLES_LIST.TXT,[-.EXAMPLES]NAME_CONVERSION.C,[-.EXAMPLES]DOM_EXPANSION_CMU.B32,[-.EXAMPLES]DOM_EXPANSION_UCX.B32,[-.EXAMPLES]NAME_CONVERSION.B32,[-.EXAMPLES]NAME_CONVERSION.MAR,[-.EXAMPLES]00README.NAME_CONVERSION,[-.EXAMPLES]00README.ADDRESS_REWRITER,[-.EXAMPLES]ADDRESS_REWRITER.C,[-.EXAMPLES]MX_HDR.H,[-.EXAMPLES]ADDRESS_REWRITER.B32,[-.EXAMPLES]ADDRESS_REWRITER.MMS SYS$DISK:[]MX042.N/SAVE GOATHUNTER O@G7.0 _GENE:: _GENE$DKA100: V6.2  *[MX.KIT]MX_EXAMPLES_LIST.TXT;2+,> ./ 4;r-EL0123KPWO56% 789GHJ;MX_TMP 00README.ADDRESS_REWRITER MX_INSTALL_ROOT:[EXAMPLES]:MX_TMP 00README.NAME_CONVERSION MX_INSTALL_ROOT:[EXAMPLES]6MX_TMP ADDRESS_REWRITER.B32 MX_INSTALL_ROOT:[EXAMPLES]4MX_TMP ADDRESS_REWRITER.C MX_INSTALL_ROOT:[EXAMPLES]6MX_TMP ADDRESS_REWRITER.MMS MX_INSTALL_ROOT:[EXAMPLES],MX_TMP MX_HDR.H MX_INSTALL_ROOT:[EXAMPLES]8MX_TMP NAME_CONVERSION.B32 MX_INSTALL_ROOT:[EXAMPLES]:MX_TMP NAME_CONVERSION.MAR MX_INSTALL_ROOT:[EXAMPLES]7MX_TMP NAME_CONVERSION.C MX_INSTALL_ROOT:[EXAMPLES]7MX_TMP DOM_EXPANSION_CMU.B32 MX_INSTALL_ROOT:[EXAMPLES]7MX_TMP DOM_EXPANSION_UCX.B32 MX_INSTALL_ROOT:[EXAMPLES]7- MX042.NKK [MX.EXAMPLES]NAME_CONVERSION.C;1L *[MX.EXAMPLES]NAME_CONVERSION.C;1+,K./ 4L-K0123KPWO5 6Z7"89mGHJ/*!++! ! MODULE: NAME_CONVERSION!! FACILITY: MX examples!A! ABSTRACT: Example of site-installable nickname conversion.!! MODULE DESCRIPTION:!F! This module contains routines for use by MX modules (specifically,I! the MX_MAILSHR interface to VMS Mail and the MX_ROUTER agent process)K! for translating between actual VMS usernames and site-specific aliases.!E! This module contains a fairly primitive lookup table to implement! the translation.!J! To use this module: MODIFY IT AS NEEDED FOR YOUR SITE, then compile it"! and link it with the commands:!! $ cc name_conversion8! $ link/share/notrace name_conversion,sys$input:/opt ! sys$share:vaxcrtl/share4! universal=init,convert,full_convert,cleanup! !C! Then copy it to MX_EXE and make it available with the commands:!7! $ copy name_conversion.exe mx_exe:/protection=w:re>! $ install create mx_exe:name_conversion/share/open/headerH! $ define/system/exec mx_site_name_conversion mx_exe:name_conversion;! $ mcp reset router ! to force Router to load the code!8! (You need a suitably privileged account to do this.)!! AUTHOR: M. MadisonE! Copyright 1993,1994, MadGoat Software. All Rights Reserved.!E! THIS SOFTWARE IS PROVIDE "AS IS". NEITHER THE AUTHOR NOR MadGoatI! MAKE ANY GUARANTEES REGARDING THE SUITABILITY, RELIABILITY, SECURITY,I! USEFULNESS, OR PERFORMANCE OF THIS SOFTWARE. >>USE AT YOUR OWN RISK.!! CREATION DATE: 03-DEC-1990!! MODIFICATION HISTORY:!0! 03-DEC-1990 V1.0 Madison Initial coding.4! 11-MAR-1992 V1.1 Madison Update for MX V3.1.J! 15-MAY-1992 V1.2 Madison Correct "restat" typo. Add full_convert.!--*/#include descrip#include string#include stdio#include ssdef#include str$routines#include lib$routines#define NICK_TO_ADDRESS 1#define USERNAME_TO_NICK 2#define NAME_COUNT 2,static char *user [] = {"SMYTHE", "SYSTEM"};6static char *nick [] = {"J.Smythe", "System.Manager"};#define FULL_COUNT 23static char *full_user[] = {"MADISON", "SHANDY_P"};.static char *full_nick[] = {"madison@tgv.com",G "Peter_Shandy@portulaca-purple-passion.balaclava.edu"};struct context {$ struct dsc$descriptor localnode; }; /*!++!! ROUTINE NAME: INIT!! FUNCTIONAL DESCRIPTION:!L! Allocates and initializes context block for subsequent name conversions.!B! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:!! INIT ctxptr!>! ctxptr: pointer, longword (unsigned), modify, by reference!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!2! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!--*/ unsigned intinit (struct context **ctx) { int ctxsize;- $DESCRIPTOR(mx_node_name,"MX_NODE_NAME");% ctxsize = sizeof(struct context); lib$get_vm (&ctxsize, ctx);2 (*ctx)->localnode.dsc$b_dtype = DSC$K_DTYPE_T;2 (*ctx)->localnode.dsc$b_class = DSC$K_CLASS_D;' (*ctx)->localnode.dsc$w_length = 0;+ (*ctx)->localnode.dsc$a_pointer = NULL;: lib$sys_trnlog (&mx_node_name, 0, &(*ctx)->localnode); return SS$_NORMAL; } /* init *//*!++!! ROUTINE NAME: CONVERT!! FUNCTIONAL DESCRIPTION:!@! Converts username -> nickname or nickname -> RFC821-address.!E! NB: You MUST use STR$ routines to copy result to OUTSTR parameter&! to ensure proper operation!!!!!H! You _may_ safely assume that INSTR is compatible with a DTYPE_T,7! CLASS_S (standard fixed-length) string descriptor.!B! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:!(! CONVERT ctxptr, code, instr, outstr!>! ctxptr: pointer, longword (unsigned), modify, by referenceK! code: longword_unsigned, longword (unsigned), read only, by referenceK! instr: char_string, character string, read only, by descriptor (fixed)D! outstr: char_string, character string, write only, by descriptor!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!2! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!--*/ unsigned intGconvert (struct context **ctx, int *code, struct dsc$descriptor *instr,) struct dsc$descriptor *outstr) {$ struct dsc$descriptor tmp, tmp2; size_t count; int i, j, retstat; $DESCRIPTOR(lbrack, "<"); $DESCRIPTOR(rbrack, ">"); $DESCRIPTOR(atsign, "@");" count = instr -> dsc$w_length;$ tmp.dsc$b_dtype = DSC$K_DTYPE_T;$ tmp.dsc$b_class = DSC$K_CLASS_D; tmp.dsc$w_length = 0; tmp.dsc$a_pointer = NULL;% tmp2.dsc$b_dtype = DSC$K_DTYPE_T;% tmp2.dsc$b_class = DSC$K_CLASS_S; switch (*code) {/*!++! Local alias -> address!H! This code should return a status of SS$_NORMAL if an alias is found,! 0 otherwise.!H! If an alias is found, the resulting string MUST BE IN RFC821 format:!! !D! >>>>>> EVEN IF THE ADDRESS IS FOR THE LOCAL HOST (so you have toB! look up MX_NODE_NAME and tack it on after the translated name,6! if you're just doing a local-host user directory).!--*/ case NICK_TO_ADDRESS: retstat = 0;" str$copy_dx(&tmp, instr);+ for (i = 0; i < NAME_COUNT; i++) {. tmp2.dsc$w_length = strlen(nick[i]);' tmp2.dsc$a_pointer = nick[i];: if (str$case_blind_compare(instr, &tmp2) == 0) {" j = strlen(user[i]);, str$copy_r(&tmp, &j, user[i]);8 str$concat(outstr, &lbrack, &tmp, &atsign,, &(*ctx)->localnode, &rbrack);# retstat = SS$_NORMAL; break; } } break;/*!++! Username -> Alias!@! Return sucess status ONLY if you are actually converting theG! username to an alias! Otherwise, return a non-success status code.!A! For compatibility with the name_conversion interface prior toB! MX V3.1, you should copy the input string to the output string)! when you return a non-success status.!!--*/ case USERNAME_TO_NICK: retstat = 0;G str$copy_dx(outstr, instr); /* for pre-V3.1 compatibility */+ for (i = 0; i < NAME_COUNT; i++) {. tmp2.dsc$w_length = strlen(user[i]);' tmp2.dsc$a_pointer = user[i];: if (str$case_blind_compare(instr, &tmp2) == 0) {" j = strlen(nick[i]);. str$copy_r(outstr, &j, nick[i]);# retstat = SS$_NORMAL; break; } } break; } return retstat;} /* convert *//*!++! ! ROUTINE NAME: FULL_CONVERT!! FUNCTIONAL DESCRIPTION:!B! Converts username -> alias address (full address substitj MX042.NKK [MX.EXAMPLES]NAME_CONVERSION.C;1Lhution)!@! Unlike the CONVERT routine, FULL_CONVERT converts a usernameD! to a complete RFC822-type address. You must be running MX V3.1C!! or later to use this feature.!E! NB: You MUST use STR$ routines to copy result to OUTSTR parameter&! to ensure proper operation!!!!!H! You _may_ safely assume that INSTR is compatible with a DTYPE_T,7! CLASS_S (standard fixed-length) string descriptor.!B! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:!-! FULL_CONVERT ctxptr, code, instr, outstr!>! ctxptr: pointer, longword (unsigned), modify, by referenceK! code: longword_unsigned, longword (unsigned), read only, by referenceK! instr: char_string, character string, read only, by descriptor (fixed)D! outstr: char_string, character string, write only, by descriptor!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!2! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!--*/ unsigned intLfull_convert (struct context **ctx, int *code, struct dsc$descriptor *instr,) struct dsc$descriptor *outstr) {$ struct dsc$descriptor tmp, tmp2; size_t count; int i, j, retstat; $DESCRIPTOR(lbrack, "<"); $DESCRIPTOR(rbrack, ">"); $DESCRIPTOR(atsign, "@");" count = instr -> dsc$w_length;$ tmp.dsc$b_dtype = DSC$K_DTYPE_T;$ tmp.dsc$b_class = DSC$K_CLASS_D; tmp.dsc$w_length = 0; tmp.dsc$a_pointer = NULL;% tmp2.dsc$b_dtype = DSC$K_DTYPE_T;% tmp2.dsc$b_class = DSC$K_CLASS_S;, if (*code != USERNAME_TO_NICK) return 0;/*!++/! Username -> alias (full address conversion)!@! Return sucess status ONLY if you are actually converting theG! username to an alias! Otherwise, return a non-success status code.!!--*/ retstat = 0;& for (i = 0; i < FULL_COUNT; i++) {. tmp2.dsc$w_length = strlen(full_user[i]);' tmp2.dsc$a_pointer = full_user[i];5 if (str$case_blind_compare(instr, &tmp2) == 0) {" j = strlen(full_nick[i]);. str$copy_r(outstr, &j, full_nick[i]); retstat = SS$_NORMAL; break; } } return retstat;} /* full_convert *//*!++!! ROUTINE NAME: CLEANUP!! FUNCTIONAL DESCRIPTION:!8! Deallocates context block allocated by init routine.!B! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:!! CLEANUP ctxptr!>! ctxptr: pointer, longword (unsigned), modify, by reference!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!2! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!--*/ unsigned int cleanup (struct context **ctx) { int ctxsize;% str$free1_dx(&(*ctx)->localnode);% ctxsize = sizeof(struct context); lib$free_vm (&ctxsize, ctx); *ctx = NULL; return SS$_NORMAL;} /* cleanup */Q MX042.NKK$[MX.EXAMPLES]DOM_EXPANSION_CMU.B32;1M $*[MX.EXAMPLES]DOM_EXPANSION_CMU.B32;1+,K. / 4M -K0123KPWO 5 6.T>䖋7x„89mGHJ%TITLE 'DOM_EXPANSION_CMU'MMODULE DOM_EXPANSION_CMU (IDENT='V1.0', ADDRESSING_MODE (EXTERNAL=GENERAL)) =BEGIN!++! FACILITY: MX Examples!C! ABSTRACT: Example of a domain name expander for use with MX.*! For use with CMU-Tek TCP/IP.!! MODULE DESCRIPTION:!@! This module contains the routines necessary for implementingA! a domain name expander for use by the MX Router agent. These?! routines can be used to eliminate SMTP mail loops when mail?! is addressed using an abbreviated host name, without having/! to DEFINE PATH LOCAL for each abbreviation.!<! To use this module: modify it as needed, then compile it"! and link it with the commands:!! $ BLISS DOM_EXPANSION_CMUH! $ LINK/SHARE=DOM_EXPANSION/NOTRACE DOM_EXPANSION_CMU,SYS$INPUT:/OPT&! UNIVERSAL=INIT,EXPAND,CLEANUP! !C! Then copy it to MX_EXE and make it available to the Router with! the commands:!%! $ COPY DOM_EXPANSION.EXE MX_EXE:D! $ DEFINE/SYSTEM/EXEC MX_SITE_DOM_EXPANSION MX_EXE:DOM_EXPANSION! $ MCP RESET ROUTER!8! (You need a suitably privileged account to do this.)!! AUTHOR: M. MadisonE! Copyright 1993,1994, MadGoat Software. All Rights Reserved.!! CREATION DATE: 07-DEC-1990!! MODIFICATION HISTORY:!0! 07-DEC-1990 V1.0 Madison Initial coding.!--" LIBRARY 'SYS$LIBRARY:STARLET';" LIBRARY 'SYS$LIBRARY:NETWORK'; EXTERNAL ROUTINE6 STR$CONCAT, STR$COPY_R, STR$FREE1_DX, LIB$GET_VM, LIB$FREE_VM; LITERAL CTX_S_CTXDEF = 2; FIELD CTX_FIELDS = SET" CTX_W_CHAN = [0,0,16,0] TES; MACRO< CTXDEF = BLOCK [CTX_S_CTXDEF,BYTE] FIELD (CTX_FIELDS)%; %SBTTL 'INIT' GLOBAL ROUTINE INIT (CTX_A_A) = BEGIN!++! FUNCTIONAL DESCRIPTION:!D! Called by the Router to initialize the module. Could be used toB! allocate any storage that will be needed by the EXPAND routineD! (these routines must be reentrant, so OWN storage is right out).!B! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:!! INIT ctxptr!>! ctxptr: pointer, longword (unsigned), modify, by reference!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!2! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!-- BIND$ CTX = .CTX_A_A : REF CTXDEF; LOCAL STATUS;3 STATUS = LIB$GET_VM (%REF (CTX_S_CTXDEF), CTX); IF .STATUS THEN BEGINB STATUS = $ASSIGN (DEVNAM=%ASCID'IP0', CHAN=CTX [CTX_W_CHAN]);@ IF NOT .STATUS THEN LIB$FREE_VM (%REF (CTX_S_CTXDEF), CTX); END; .STATUS END; ! INIT %SBTTL 'EXPAND'5GLOBAL ROUTINE EXPAND (CTX_A_A, INSTR_A, OUTSTR_A) = BEGIN!++! FUNCTIONAL DESCRIPTION:!>! This routine is called to perform a domain name expansion.!C! INSTR can be assumed to be a DTYPE_T, CLASS_S string descriptorC! (or compatible). You must use STR$ routines to copy the result! to OUTSTR!!B! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:!!! EXPAND ctxptr, instr, outstr!>! ctxptr: pointer, longword (unsigned), modify, by referenceC! instr: char_string, character string, read only, by descriptorD! outstr: char_string, character string, write only, by descriptor!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!2! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!-- BIND( CTX = .CTX_A_A : REF CTXDEF,% CHN = CTX [CTX_W_CHAN] : WORD,7 INSTR = .INSTR_A : BLOCK [DSC$K_S_BLN,BYTE],8 OUTSTR = .OUTSTR_A : BLOCK [DSC$K_S_BLN,BYTE]; LOCAL GHBLK : GTHST_NMLOOK_BLOCK, IOSB : NETWORK_IOSB,% STR : BLOCK [DSC$K_S_BLN,BYTE], STATUS; $INIT_DYNDESC (STR);7 STR$CONCAT (STR, INSTR, %ASCID %STRING(%CHAR (0)));C STATUS = NET$GTHST (BUFADRS=GHBLK, BUFSIZE=%ALLOCATION (GHBLK),B GTHFUNCT=GTH_NAMADR, GTHP1=.STR [DSC$A_POINTER], IOCHAN=.CHN, IO$SB=IOSB);D IF .STATUS THEN STATUS = (IF .IOSB [VMS_CODE] EQL SS$_ABORT THEN> .IOSB [NET_XERROR] ELSE .IOSB [VMS_CODE]); IF NOT .STATUS ANDL CH$RCHAR (.INSTR [DSC$A_POINTER]+.INSTR [DSC$W_LENGTH]-1) NEQ %C'.' THEN BEGIN> STR$CONCAT (STR, INSTR, %ASCID %STRING ('.', %CHAR (0)));D STATUS = NET$GTHST (BUFADRS=GHBLK, BUFSIZE=%ALLOCATION (GHBLK),F GTHFUNCT=GTH_NAMADR, GTHP1=.STR [DSC$A_POINTER], IOCHAN=.CHN, IO$SB=IOSB);E IF .STATUS THEN STATUS = (IF .IOSB [VMS_CODE] EQL SS$_ABORT THEN> .IOSB [NET_XERROR] ELSE .IOSB [VMS_CODE]); END; STR$FREE1_DX (STR);F IF .STATUS THEN STATUS = STR$COPY_R (OUTSTR, GHBLK [GH$NL_NAMLEN],. GHBLK [GH$NL_NAMSTR]); .STATUS END; ! EXPAND %SBTTL 'CLEANUP'#GLOBAL ROUTINE CLEANUP (CTX_A_A) = BEGIN!++! FUNCTIONAL DESCRIPTION:!?! Called by the Router to clean up any context info set up by ! INIT.!B! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:!! CLEANUP ctxptr!>! ctxptr: pointer, longword (unsigned), modify, by reference!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!2! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!-- BIND$ CTX = .CTX_A_A : REF CTXDEF;% $DASSGN (CHAN=.CTX [CTX_W_CHAN]);+ LIB$FREE_VM (%REF (CTX_S_CTXDEF), CTX); CTX = 0; SS$_NORMALEND; ! CLEANUPENDELUDOM@ MX042.NKK$[MX.EXAMPLES]DOM_EXPANSION_UCX.B32;1MW[$*[MX.EXAMPLES]DOM_EXPANSION_UCX.B32;1+,K./ 4M -K0123KPWO5 6䖋7.Ȅ89mGHJ%TITLE 'DOM_EXPANSION_UCX'MMODULE DOM_EXPANSION_UCX (IDENT='V1.0', ADDRESSING_MODE (EXTERNAL=GENERAL)) =BEGIN!++! FACILITY: MX Examples!C! ABSTRACT: Example of a domain name expander for use with MX.F! For use with VMS/ULTRIX Connection >>> V1.3 or later <<<!! MODULE DESCRIPTION:!@! This module contains the routines necessary for implementingA! a domain name expander for use by the MX Router agent. These?! routines can be used to eliminate SMTP mail loops when mail?! is addressed using an abbreviated host name, without having/! to DEFINE PATH LOCAL for each abbreviation.!=! To use this module: modify it, if needed, then compile it"! and link it with the commands:!! $ BLISS DOM_EXPANSION_UCXH! $ LINK/SHARE=DOM_EXPANSION/NOTRACE DOM_EXPANSION_UCX,SYS$INPUT:/OPT&! UNIVERSAL=INIT,EXPAND,CLEANUP! !C! Then copy it to MX_EXE and make it available to the Router with! the commands:!%! $ COPY DOM_EXPANSION.EXE MX_EXE:D! $ DEFINE/SYSTEM/EXEC MX_SITE_DOM_EXPANSION MX_EXE:DOM_EXPANSION! $ MCP RESET ROUTER!8! (You need a suitably privileged account to do this.)!! AUTHOR: M. MadisonE! Copyright 1993,1994, MadGoat Software. All Rights Reserved.!! CREATION DATE: 07-DEC-1990!! MODIFICATION HISTORY:!0! 07-DEC-1990 V1.0 Madison Initial coding.!--" LIBRARY 'SYS$LIBRARY:STARLET';& LIBRARY 'SYS$LIBRARY:UCX$INETDEF'; EXTERNAL ROUTINEE STR$CONCAT, STR$COPY_R, STR$FREE1_DX, STR$UPCASE, STR$TRANSLATE, LIB$GET_VM, LIB$FREE_VM; LITERAL CTX_S_CTXDEF = 2; FIELD CTX_FIELDS = SET" CTX_W_CHAN = [0,0,16,0] TES; MACRO< CTXDEF = BLOCK [CTX_S_CTXDEF,BYTE] FIELD (CTX_FIELDS)%; %SBTTL 'INIT' GLOBAL ROUTINE INIT (CTX_A_A) = BEGIN!++! FUNCTIONAL DESCRIPTION:!D! Called by the Router to initialize the module. Could be used toB! allocate any storage that will be needed by the EXPAND routineD! (these routines must be reentrant, so OWN storage is right out).!B! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:!! INIT ctxptr!>! ctxptr: pointer, longword (unsigned), modify, by reference!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!2! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!-- BIND$ CTX = .CTX_A_A : REF CTXDEF; LOCAL STATUS;3 STATUS = LIB$GET_VM (%REF (CTX_S_CTXDEF), CTX); IF .STATUS THEN BEGINI STATUS = $ASSIGN (DEVNAM=%ASCID'UCX$DEVICE', CHAN=CTX [CTX_W_CHAN]);@ IF NOT .STATUS THEN LIB$FREE_VM (%REF (CTX_S_CTXDEF), CTX); END; .STATUS END; ! INIT %SBTTL 'EXPAND'5GLOBAL ROUTINE EXPAND (CTX_A_A, INSTR_A, OUTSTR_A) = BEGIN!++! FUNCTIONAL DESCRIPTION:!>! This routine is called to perform a domain name expansion.!C! INSTR can be assumed to be a DTYPE_T, CLASS_S string descriptorC! (or compatible). You must use STR$ routines to copy the result! to OUTSTR!!B! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:!!! EXPAND ctxptr, instr, outstr!>! ctxptr: pointer, longword (unsigned), modify, by referenceC! instr: char_string, character string, read only, by descriptorD! outstr: char_string, character string, write only, by descriptor!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!2! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!-- BIND( CTX = .CTX_A_A : REF CTXDEF,% CHN = CTX [CTX_W_CHAN] : WORD,7 INSTR = .INSTR_A : BLOCK [DSC$K_S_BLN,BYTE],8 OUTSTR = .OUTSTR_A : BLOCK [DSC$K_S_BLN,BYTE]; LOCAL SUBF, ADDR, DSC1 : VECTOR [2,LONG], DSC2 : VECTOR [2,LONG], DSC3 : VECTOR [2,LONG], IOSB : VECTOR [4,WORD],% STR : BLOCK [DSC$K_S_BLN,BYTE], NAMBUF : VECTOR [255,BYTE], OUTLEN : WORD, STATUS; $INIT_DYNDESC (STR); STR$UPCASE (STR, INSTR);@ SUBF = INETACP$C_TRANS * 256 + INETACP_FUNC$C_GETHOSTBYNAME; DSC1 [0] = 4; DSC1 [1] = SUBF; DSC2 [0] = 4; DSC2 [1] = ADDR;> STATUS = $QIOW (CHAN=.CHN, FUNC=IO$_ACPCONTROL, IOSB=IOSB,* P1=DSC1, P2=STR, P3=OUTLEN, P4=DSC2);' IF .STATUS THEN STATUS = .IOSB [0]; IF NOT .STATUS THEN BEGINC STR$TRANSLATE (STR, INSTR, %ASCID'abcdefghijklmnopqrstuvwxyz',2 %ASCID'ABCDEFGHIJKLMNOPQRSTUVWXYZ');? STATUS = $QIOW (CHAN=.CHN, FUNC=IO$_ACPCONTROL, IOSB=IOSB,. P1=DSC1, P2=STR, P3=OUTLEN, P4=DSC2);( IF .STATUS THEN STATUS = .IOSB [0]; END; STR$FREE1_DX (STR); IF .STATUS THEN BEGINA SUBF = INETACP$C_TRANS * 256 + INETACP_FUNC$C_GETHOSTBYADDR;% DSC3 [0] = %ALLOCATION (NAMBUF); DSC3 [1] = NAMBUF;? STATUS = $QIOW (CHAN=.CHN, FUNC=IO$_ACPCONTROL, IOSB=IOSB,/ P1=DSC1, P2=DSC2, P3=OUTLEN, P4=DSC3);( IF .STATUS THEN STATUS = .IOSB [0]; END;A IF .STATUS THEN STATUS = STR$COPY_R (OUTSTR, OUTLEN, NAMBUF); .STATUS END; ! EXPAND %SBTTL 'CLEANUP'#GLOBAL ROUTINE CLEANUP (CTX_A_A) = BEGIN!++! FUNCTIONAL DESCRIPTION:!?! Called by the Router to clean up any context info set up by ! INIT.!B! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:!! CLEANUP ctxptr!>! ctxptr: pointer, longword (unsigned), modify, by reference!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!2! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!-- BIND$ CTX = .CTX_A_A : REF CTXDEF;% $DASSGN (CHAN=.CTX [CTX_W_CHAN]);+ LIB$FREE_VM (%REF (CTX_S_CTXDEF), CTX); CTX = 0; SS$_NORMALEND; ! CLEANUPENDELUDOMIr MX042.NKK"[MX.EXAMPLES]NAME_CONVERSION.B32;1L`"*[MX.EXAMPLES]NAME_CONVERSION.B32;1+,K./ 4L-K0123KPWO5 6B喋7̄89mGHJ%TITLE 'NAME_CONVERSION'KMODULE NAME_CONVERSION (IDENT='V1.1', ADDRESSING_MODE (EXTERNAL=GENERAL)) =BEGIN!++ ! FACILITY: NAME_CONVERSION!,! ABSTRACT: MX name conversion routines!! MODULE DESCRIPTION:!=! This module contains name_conversion routines for MX that ! handle!8! - DECnet addresses: NODE::USER -> user%node.dnetJ! - MRGATE addresses: NODE::MRGATE::"NODE::USER" -> user%node.mrgate!A! In conjunction with this module, you should add the following+! rewrite rules to your MX configuration:!L! MCP> DEFINE REWRITE_RULE "<{user}@{node}.dnet>" "<""node::user""@local>"7! MCP> DEFINE REWRITE_RULE "<{user}@{node}.mrgate>" -3! "<""mrgate::\""{node}::{user}\""""@local>"!D! where "local" is your local host name. Be sure to get all those'! quotation marks in there correctly!! ! NOTE:!E! This module can be used in conjunction with other name_conversionG! modules. It will automaticaly merge and activate a name_conversionJ! module if the logical name MX_SITE_NAME_CONVERSION_LOCAL points to theE! shareable image containing the name_conversion routines, and willG! automatically call that module's CONVERT routine if its own CONVERTD! routine does not recognize an address as originating from DECnet! or MRGATE.!! AUTHOR: M. MadisonK! Copyright 1993,1994, MadGoat Software. All Rights Reserved.!! CREATION DATE: 09-MAR-1992!! MODIFICATION HISTORY:!0! 09-MAR-1992 V1.0 Madison Initial coding.K! 06-JAN-1993 V1.1 Madison Handle MRGATE::"NODE1::NODE2::..." better.!--" LIBRARY 'SYS$LIBRARY:STARLET';! LIBRARY 'SYS$LIBRARY:TPAMAC'; LIBRARY '[MX.COMMON]MX'; LIBRARY '[MX.COMMON]FIELDS'; FORWARD ROUTINE INIT, CONVERT, CLEANUP, DNA_PARSE, DNA_STORE; EXTERNAL ROUTINE@ LIB$FIND_IMAGE_SYMBOL, LIB$TPARSE, STR$COPY_DX, LIB$GET_VM,7 LIB$FREE_VM, STR$CONCAT, STR$PREFIX, STR$FREE1_DX; LITERAL CTX_S_LCLSTUFF = 16, CTX_S_NODE = 256, CTX_S_CLUNODE = 256; _DEF (CTX) CTX_L_LCLINIT = _LONG, CTX_L_LCLCONV = _LONG, CTX_L_LCLCLUP = _LONG, CTX_L_LCLCTX = _LONG, CTX_W_NODE = _WORD,( CTX_T_NODE = _BYTES (CTX_S_NODE), CTX_W_CLUNODE = _WORD,+ CTX_T_CLUNODE = _BYTES (CTX_S_CLUNODE) _ENDDEF (CTX); LITERAL NICK_TO_ADDRESS = 1, USERNAME_TO_NICK = 2, NC_K_LOW = 1, NC_K_IS_MRGATE = 1, NC_K_DECNET_NODE = 2, NC_K_DECNET_USER = 3, NC_K_MRGATE_NODE = 4, NC_K_MRGATE_USER = 5, NC_K_HI = 5; MACRO/ TPA_A_P1 = TPA$C_LENGTH0+00,0,32,0%,/ TPA_A_P2 = TPA$C_LENGTH0+04,0,32,0%,/ TPA_A_P3 = TPA$C_LENGTH0+08,0,32,0%,/ TPA_A_P4 = TPA$C_LENGTH0+12,0,32,0%,/ TPA_A_P5 = TPA$C_LENGTH0+16,0,32,0%,/ TPA_A_P6 = TPA$C_LENGTH0+20,0,32,0%,/ TPA_A_P7 = TPA$C_LENGTH0+24,0,32,0%,/ TPA_A_P8 = TPA$C_LENGTH0+28,0,32,0%;% $INIT_STATE (DNA_STATE, DNA_KEY); $STATE (DNA_START,9 ((MRGATE), DNA_MRGATE, DNA_STORE,,, NC_K_IS_MRGATE),/ ((NODE),, DNA_STORE,,, NC_K_DECNET_NODE)); $STATE (DNA_NODE,9 ((MRGATE), DNA_MRGATE, DNA_STORE,,, NC_K_IS_MRGATE),7 ((NODE), DNA_NODE, DNA_STORE,,, NC_K_DECNET_NODE), (TPA$_LAMBDA, DNA_USER)); $STATE (DNA_USER, (TPA$_EOS, TPA$_EXIT),: (TPA$_ANY, DNA_USER, DNA_STORE,,, NC_K_DECNET_USER)); $STATE (DNA_MRGATE, ('"',)); $STATE (DNA_MRGATE_NODE,= ((NODE), DNA_MRGATE_NODE, DNA_STORE,,,NC_K_MRGATE_NODE), (TPA$_LAMBDA,)); $STATE (DNA_MRGATE_USER, ('"', TPA$_EXIT),@ (TPA$_ANY, DNA_MRGATE_USER, DNA_STORE,,,NC_K_MRGATE_USER)); $STATE (MRGATE, ('MRGATE',)); $STATE (, (':',)); $STATE (, (':', TPA$_EXIT)); $STATE (NODE, (TPA$_ALPHA, NODE), (TPA$_DIGIT, NODE), (':',)); $STATE (, (':', TPA$_EXIT)); %SBTTL 'INIT' GLOBAL ROUTINE INIT (CTX_A_A) = BEGIN!++! FUNCTIONAL DESCRIPTION:!/! Initialization routine for NAME_CONVERSION.!B! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:!! INIT!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!2! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!-- BIND# CTX = .CTX_A_A : REF CTXDEF; LOCAL% LNMLST : $ITMLST_DECL (ITEMS=1), STATUS;3 STATUS = LIB$GET_VM (%REF (CTX_S_CTXDEF), CTX);, CH$FILL (%CHAR (0), CTX_S_CTXDEF, .CTX);' IF NOT .STATUS THEN RETURN .STATUS; $ITMLST_INIT (ITMLST=LNMLST,E (ITMCOD=LNM$_STRING, BUFADR=CTX [CTX_T_NODE], BUFSIZ=CTX_S_NODE,# RETLEN=CTX [CTX_W_NODE]));0 STATUS = $TRNLNM (TABNAM=%ASCID'LNM$SYSTEM',2 LOGNAM=%ASCID'SYS$NODE', ITMLST=LNMLST);/ IF .STATUS AND .CTX [CTX_W_NODE] GTR 2 THEN. CTX [CTX_W_NODE] = .CTX [CTX_W_NODE] - 2; $ITMLST_INIT (ITMLST=LNMLST,K (ITMCOD=LNM$_STRING, BUFADR=CTX [CTX_T_CLUNODE], BUFSIZ=CTX_S_CLUNODE,& RETLEN=CTX [CTX_W_CLUNODE]));0 STATUS = $TRNLNM (TABNAM=%ASCID'LNM$SYSTEM',: LOGNAM=%ASCID'SYS$CLUSTER_NODE', ITMLST=LNMLST);2 IF .STATUS AND .CTX [CTX_W_CLUNODE] GTR 2 THEN4 CTX [CTX_W_CLUNODE] = .CTX [CTX_W_CLUNODE] - 2;* IF $TRNLNM (TABNAM=%ASCID'LNM$SYSTEM',< LOGNAM=%ASCID'MX_SITE_NAME_CONVERSION_LOCAL') THEN BEGINK STATUS = LIB$FIND_IMAGE_SYMBOL (%ASCID'MX_SITE_NAME_CONVERSION_LOCAL',1 %ASCID'INIT', CTX [CTX_L_LCLINIT]); IF .STATUS THEN BEGINF LIB$FIND_IMAGE_SYMBOL (%ASCID'MX_SITE_NAME_CONVERSION_LOCAL',4 %ASCID'CONVERT', CTX [CTX_L_LCLCONV]);F LIB$FIND_IMAGE_SYMBOL (%ASCID'MX_SITE_NAME_CONVERSION_LOCAL',4 %ASCID'CLEANUP', CTX [CTX_L_LCLCLUP]);> STATUS = (.CTX [CTX_L_LCLINIT]) (CTX [CTX_L_LCLCTX]);G IF NOT .STATUS THEN CH$FILL (%CHAR (0), CTX_S_LCLSTUFF, .CTX); END; END; SS$_NORMAL END; ! INIT %SBTTL 'CONVERT'>GLOBAL ROUTINE CONVERT (CTX_A_A, CODE_A, INSTR_A, OUTSTR_A) = BEGIN!++! FUNCTIONAL DESCRIPTION:!A! Performs a username->nickname conversion on DECnet-origin and! MRGATE-origin addresses.!B! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:! ! CONVERT!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!2! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!-- BIND$ CTX = .CTX_A_A : REF CTXDEF, CODE = .CODE_A,3 INSTR = .INSTR_A : BLOCK [DSC$K_S_BLN,BYTE],4 OUTSTR = .OUTSTR_A : BLOCK [DSC$K_S_BLN,BYTE]; LOCAL) NODE : BLOCK [DSC$K_S_BLN,BYTE],) USER : BLOCK [DSC$K_S_BLN,BYTE],+ GWNODE : BLOCK [DSC$K_S_BLN,BYTE], ADDR_TYPE, STATUO$ MX042.NKK"[MX.EXAMPLES]NAME_CONVERSION.B32;1LS;% IF .CODE EQL NICK_TO_ADDRESS THEN( IF .CTX [CTX_L_LCLCONV] NEQA 0 THENA RETURN (.CTX [CTX_L_LCLCONV]) (CTX [CTX_L_LCLCTX], CODE,, INSTR, OUTSTR) ELSE RETURN 0;L IF .CODE NEQ USERNAME_TO_NICK THEN RETURN 0; ! shouldn't happen, though $INIT_DYNDESC (NODE); $INIT_DYNDESC (GWNODE);> STATUS = DNA_PARSE (INSTR, ADDR_TYPE, NODE, USER, GWNODE); IF NOT .STATUS THEN BEGIN STR$FREE1_DX (NODE); STR$FREE1_DX (GWNODE);( IF .CTX [CTX_L_LCLCONV] NEQA 0 THENA RETURN (.CTX [CTX_L_LCLCONV]) (CTX [CTX_L_LCLCTX], CODE,, INSTR, OUTSTR) ELSE BEGIND STR$COPY_DX (OUTSTR, INSTR); ! for pre-V3.1 compatibility RETURN 0; END; END; IF .ADDR_TYPE EQL 0 THEN> STR$CONCAT (OUTSTR, USER, %ASCID'%', NODE, %ASCID'.dnet') ELSE BEGIN' IF .GWNODE [DSC$W_LENGTH] EQL 0 ORA CH$EQL (.GWNODE [DSC$W_LENGTH], .GWNODE [DSC$A_POINTER],= .CTX [CTX_W_NODE], CTX [CTX_T_NODE], %C' ') ORA CH$EQL (.GWNODE [DSC$W_LENGTH], .GWNODE [DSC$A_POINTER],@ .CTX [CTX_W_CLUNODE], CTX [CTX_T_CLUNODE], %C' ')E THEN STR$CONCAT (OUTSTR, USER, %ASCID'%', NODE, %ASCID'.mrgate')4 ELSE STR$CONCAT (OUTSTR, USER, %ASCID'%', NODE,3 %ASCID'.', GWNODE, %ASCID'.mrgate'); END; STR$FREE1_DX (NODE); STR$FREE1_DX (GWNODE); SS$_NORMALEND; ! CONVERT %SBTTL 'CLEANUP'#GLOBAL ROUTINE CLEANUP (CTX_A_A) = BEGIN!++! FUNCTIONAL DESCRIPTION:!! description!B! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:! ! CLEANUP!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!2! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!-- BIND$ CTX = .CTX_A_A : REF CTXDEF;' IF .CTX [CTX_L_LCLCLUP] NEQA 0 THEN1 (.CTX [CTX_L_LCLCLUP]) (CTX [CTX_L_LCLCTX]);+ LIB$FREE_VM (%REF (CTX_S_CTXDEF), CTX); SS$_NORMALEND; ! CLEANUP %SBTTL 'DNA_PARSE'BROUTINE DNA_PARSE (INSTR_A, ADTYPE_A, NODE_A, USER_A, GWNODE_A) = BEGIN!++! FUNCTIONAL DESCRIPTION:!K! Uses LIB$TPARSE to parse what might be a DECnet or MRGATE-type address.!B! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:! ! DNA_PARSE!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!2! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!-- BIND2 INSTR = .INSTR_A : BLOCK [DSC$K_S_BLN,BYTE], ADTYPE = .ADTYPE_A,1 NODE = .NODE_A : BLOCK [DSC$K_S_BLN,BYTE],1 USER = .USER_A : BLOCK [DSC$K_S_BLN,BYTE],3 GWNODE = .GWNODE_A : BLOCK [DSC$K_S_BLN,BYTE]; LITERAL' TPA_C_LENGTH = TPA$C_LENGTH0 + 12,% TPA_K_COUNT = TPA$K_COUNT0 + 3; LOCAL( TPABLK : BLOCK [TPA_C_LENGTH,BYTE];' USER [DSC$B_DTYPE] = DSC$K_DTYPE_T;' USER [DSC$B_CLASS] = DSC$K_CLASS_S; USER [DSC$W_LENGTH] = 0; USER [DSC$A_POINTER] = 0; ADTYPE = 0;' TPABLK [TPA$L_COUNT] = TPA_K_COUNT; TPABLK [TPA$L_OPTIONS] = 0;5 TPABLK [TPA$L_STRINGCNT] = .INSTR [DSC$W_LENGTH];6 TPABLK [TPA$L_STRINGPTR] = .INSTR [DSC$A_POINTER]; TPABLK [TPA_A_P1] = ADTYPE; TPABLK [TPA_A_P2] = NODE; TPABLK [TPA_A_P3] = USER; TPABLK [TPA_A_P4] = GWNODE;+ LIB$TPARSE (TPABLK, DNA_STATE, DNA_KEY)END; ! DNA_PARSE %SBTTL 'DNA_STORE'HROUTINE DNA_STORE (OPTIONS, STRLEN, STRPTR, TOKLEN, TOKPTR, CHAR : BYTE,> NUMBER, PARAM, ADTYPE_A, NODE_A, USER_A, GWNODE_A) = BEGIN!++! FUNCTIONAL DESCRIPTION:!! description!B! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:! ! DNA_STORE!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!2! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!-- BIND ADTYPE = .ADTYPE_A,2 USER = .USER_A : BLOCK [DSC$K_S_BLN,BYTE],2 NODE = .NODE_A : BLOCK [DSC$K_S_BLN,BYTE],6 GWNODE = .GWNODE_A : BLOCK [DSC$K_S_BLN,BYTE];+ CASE .PARAM FROM NC_K_LOW TO NC_K_HI OF SET [NC_K_IS_MRGATE] : BEGIN ADTYPE = 1;2 CH$MOVE (DSC$K_S_BLN, NODE, GWNODE);# $INIT_DYNDESC (NODE); END; [NC_K_DECNET_NODE] : BEGIN; LOCAL DSC : BLOCK [DSC$K_S_BLN,BYTE] PRESET (. [DSC$B_DTYPE] = DSC$K_DTYPE_T,. [DSC$B_CLASS] = DSC$K_CLASS_S,* [DSC$W_LENGTH] = .TOKLEN-2,* [DSC$A_POINTER] = .TOKPTR);& STR$COPY_DX (NODE, DSC); END; [NC_K_MRGATE_NODE] : BEGIN; LOCAL DSC : BLOCK [DSC$K_S_BLN,BYTE] PRESET (. [DSC$B_DTYPE] = DSC$K_DTYPE_T,. [DSC$B_CLASS] = DSC$K_CLASS_S,* [DSC$W_LENGTH] = .TOKLEN-2,* [DSC$A_POINTER] = .TOKPTR);0 IF .NODE [DSC$W_LENGTH] EQL 0 THEN& STR$COPY_DX (NODE, DSC) ELSE BEGIN, STR$PREFIX (NODE, %ASCID'.');& STR$PREFIX (NODE, DSC); END; END;* [NC_K_DECNET_USER,NC_K_MRGATE_USER] : BEGIN2 IF .USER [DSC$A_POINTER] EQLA 0 THEN. USER [DSC$A_POINTER] = .TOKPTR;C USER [DSC$W_LENGTH] = .USER [DSC$W_LENGTH] + .TOKLEN; END; TES; SS$_NORMALEND; ! DNA_STOREENDELUDOM MX042.NKK"[MX.EXAMPLES]NAME_CONVERSION.MAR;1{$"*[MX.EXAMPLES]NAME_CONVERSION.MAR;1+,K.$/ 4{$-K0123KPWO 56`n7҄89mGHJ( .TITLE NAME_CONVERSION NAME_CONVERSION .IDENT \V1.1\' .PSECT _LIB$KEY0$,NOWRT, SHR, PIC,1 DNA_KEY:: .BLKB 0 ;TPA$KEY0U.7: .BLKB 0;TPA$KEY U.65: .WORD ;( .PSECT _LIB$STATE$,NOWRT, SHR, PIC,1 DNA_STATE:: .BLKB 0 ;DNA_STARTU.9: .BLKB 0 ;TPA$TYPEU.10: .WORD -25608 ; ;TPA$FLAGS2U.11: .BYTE 1 ; ;TPA$SUBEXP%U.13: .WORD <-2> ; ;TPA$PARAMU.14: .LONG 1 ; ;TPA$ACTION$U.15: .LONG <-4> ; ;TPA$TARGET%U.17: .WORD <-2> ; ;TPA$TYPEU.18: .WORD -28680 ; ;TPA$FLAGS2U.19: .BYTE 1 ; ;TPA$SUBEXP%U.21: .WORD <-2> ; ;TPA$PARAMU.22: .LONG 2 ; ;TPA$ACTION$U.23: .LONG <-4> ; ;DNA_NODEU.24: .BLKB 0 ;TPA$TYPEU.25: .WORD -25608 ; ;TPA$FLAGS2U.26: .BYTE 1 ; ;TPA$SUBEXP%U.27: .WORD <-2> ; ;TPA$PARAMU.28: .LONG 1 ; ;TPA$ACTION$U.29: .LONG <-4> ; ;TPA$TARGET%U.30: .WORD <-2> ; ;TPA$TYPEU.31: .WORD -25608 ; ;TPA$FLAGS2U.32: .BYTE 1 ; ;TPA$SUBEXP%U.33: .WORD <-2> ; ;TPA$PARAMU.34: .LONG 2 ; ;TPA$ACTION$U.35: .LONG <-4> ; ;TPA$TARGET%U.36: .WORD <-2> ; ;TPA$TYPEU.37: .WORD 5622 ; ;TPA$TARGET%U.39: .WORD <-2> ; ;DNA_USERU.38: .BLKB 0 ;TPA$TYPEU.40: .WORD 4599 ; ;TPA$TARGETU.41: .WORD -1 ; ;TPA$TYPEU.42: .WORD -26643 ; ;TPA$FLAGS2U.43: .BYTE 1 ; ;TPA$PARAMU.44: .LONG 3 ; ;TPA$ACTION$U.45: .LONG <-4> ; ;TPA$TARGET%U.46: .WORD <-2> ; ;DNA_MRGATEU.16: .BLKB 0 ;TPA$TYPEU.47: .WORD 1058 ;;DNA_MRGATE_NODEU.48: .BLKB 0 ;TPA$TYPEU.49: .WORD -25608 ; ;TPA$FLAGS2U.50: .BYTE 1 ; ;TPA$SUBEXP%U.51: .WORD <-2> ; ;TPA$PARAMU.52: .LONG 4 ; ;TPA$ACTION$U.53: .LONG <-4> ; ;TPA$TARGET%U.54: .WORD <-2> ; ;TPA$TYPEU.55: .WORD 1526 ;;DNA_MRGATE_USERU.56: .BLKB 0 ;TPA$TYPEU.57: .WORD 4130 ; ;TPA$TARGETU.58: .WORD -1 ; ;TPA$TYPEU.59: .WORD -26643 ; ;TPA$FLAGS2U.60: .BYTE 1 ; ;TPA$PARAMU.61: .LONG 5 ; ;TPA$ACTION$U.62: .LONG <-4> ; ;TPA$TARGET%U.63: .WORD <-2> ;;MRGATEU.12: .BLKB 0 ;TPA$TYPEU.67: .WORD 1280 ; ;TPA$TYPEU.69: .WORD 1082 ; ;TPA$TYPEU.70: .WORD 5178 ; ;TPA$TARGETU.71: .WORD -1 ;;NODEU.20: .BLKB 0 ;TPA$TYPEU.72: .WORD 4590 ; ;TPA$TARGET%U.73: .WORD <-2> ; ;TPA$TYPEU.74: .WORD 4591 ; ;TPA$TARGET%U.75: .WORD <-2> ; ;TPA$TYPEU.76: .WORD 1082 ; ;TPA$TYPEU.77: .WORD 5178 ; ;TPA$TARGETU.78: .WORD -1 ;' .PSECT _LIB$KEY1$,NOWRT, SHR, PIC,1 ;TPA$KEYST0U.64: .BLKB 0 ;TPA$KEYSTU.66: .ASCII \MRGATE\ ; .BYTE -1 ; ;TPA$KEYFILLU.68: .BYTE -1 ; .PSECT $PLIT$,NOWRT,NOEXE,2(P.AAB: .ASCII \LNM$SYSTEM\<0><0> ;P.AAA: .LONG 17694730 ; .ADDRESS P.AAB ;!P.AAD: .ASCII \SYS$NODE\ ;P.AAC: .LONG 17694728 ; .ADDRESS P.AAD ;(P.AAF: .ASCII \LNM$SYSTEM\<0><0> ;P.AAE: .LONG 17694730 ; .ADDRESS P.AAF ;(P.AAH: .ASCII \SYS$CLUSTER_NODE\ ;P.AAG: .LONG 17694736 ; .ADDRESS P.AAH ;(P.AAJ: .ASCII \LNM$SYSTEM\<0><0> ;P.AAI: .LONG 17694730 ; .ADDRESS P.AAJ ;;P.AAL: .ASCII \MX_SITE_NAME_CONVERSION_LOCAL\<0><0><0> ;P.AAK: .LONG 17694749 ; .ADDRESS P.AAL ;;P.AAN: .ASCII \MX_SITE_NAME_CONVERSION_LOCAL\<0><0><0> ;P.AAM: .LONG 17694749 ; .ADDRESS P.AAN ;P.AAP: .ASCII \INIT\ ;P.AAO: .LONG 17694724 ; .ADDRESS P.AAP ;;P.AAR: .ASCII \MX_SITE_NAME_CONVERSION_LOCAL\<0><0><0> ;P.AAQ: .LONG 17694749 ; .ADDRESS P.AAR ;#P.AAT: .ASCII \CONVERT\<0> ;P.AAS: .LONG 17694727 ; .ADDRESS P.AAT ;;P.AAV: .ASCII \MX_SITE_NAME_CONVERSION_LOCAL\<0><0><0> ;P.AAU: .LONG 17694749 ; .ADDRESS P.AAV ;#P.AAX: .ASCII \CLEANUP\<0> ;P.AAW: .LONG 17694727 ; .ADDRESS P.AAX ;\ .EXTRN LIB$FIND_IMAGE_SYMBOL, LIB$TPARSE, STR$COPY_DX, LIB$GET_VM, LIB$FREE_VM, STR$CONCAT- .EXTRN STR$PREFIX, STR$FREE1_DX, SYS$TRNLNM .PSECT $CODE$,NOWRT,2U.1:Y .ENTRY INIT, ^M ;INIT, Save R2,R3,R4,R5,R6,R7,R8,R9,R10E MOVAB G^LIB$FIND_IMAGE_SYMBOL, R10 ;LIB$FIND_IMAGE_SYMBOL, R10. MOVAB G^SYS$TRNLNM, R9 ;SYS$TRNLNM, R9% MOVAB W^P.AAC, R8 ;P.AAC, R8 SUBL2 #20, SP ;#20, SP PUSHL 4(AP) ;CTX_A_A' MOVZWL #532, 4(SP) ;#532, 4(SP) PUSHAB 4(SP) ;4(SP). CALLS #2, G^LIB$GET_VM ;#2, LIB$GET_VM" MOVL R0, R7 ;R0, STATUS' MOVL @4(AP), R6 ;@CTX_A_A, R6? MOVC5 #0, (SP), #0, #532, (R6) ;#0, (SP), #0, #532, (R6)" BLBS R7, 1$ ;STATUS, 1$" MOVL R7, R0 ;STATUS, R0 RET ;01$: MOVAB 4(SP), R0 ;LNMLST, $$ITMBLKPTR6 MOVL #131328, (R0)+ ;#131328, ($$ITMBLKPTR)+4 MOVAB 18(R6), (R0)+ ;18(R6), ($$ITMBLKPTR)+4 MOVAB 16(R6), (R0)+ ;16(R6), ($$ITMBLKPTR)+% CLRL (R0)+ ;($$ITMBLKPTR)+ PUSHAB 4(SP) ;LNMLST CLRL -(SP) ;-(SP) PUSHL R8 ;R8 PUSHAB -16(R8) ;P.AAA CLRL -(SP) ;-(SP)' CALLS #5, (R9) ;#5, SYS$TRNLNM" MOVL R0, R7 ;R0, STATUS" BLBC R7, 2$ ;STATUS, 2$% CMPW 16(R6), #2 ;16(R6), #2 BLEQU 2$ ;2$% SUBW2 #2, 16(R6) ;#2, 16(R6)02$: MOVAB 4(SP), R0 ;LNMLST, $$ITMBLKPTR6 MOVL #131328, (R0)+ ;#131328, ($$ITMBLKPTR)+6 MOVAB 276(R6), (R0)+ ;276(R6), ($$ITMBLKPTR)+' MOVAB 274(R6), R2 ;274(R6), R2, MOVL R2, (R0)+ ;R2, ($$ITMBLKPTR)+% CLRL (R0)+ ;($$ITMBLKPTR)+ PUSHAB 4(SP) ;LNMLST CLRL -(SP) ;-(SP) PUSHAB 44(R8) ;P.AAG PUSHAB 20(R8) ;P.AAE CLRL -(SP) ;-(SP)' CALLS #5, (R9) ;#5, SYS$TRNLNM" MOVL R0, R7 ;R0, STATUS" BLBC R7, 3$ ;STATUS, 3$! CMPW (R2), #2 ;(R2), #2 BLEQU 3$ ;3$! SUBW2 #2, (R2) ;#2, (R2)3$: CLRQ -(SP) ;-(SP) PUSHAB 104(R8) ;P.AAK PUSHAB 64(R8) ;P.AAI CLRL -(SP) ;-(SP)' CALLS #5, (R9) ;#5, SYS$TRNLNM BLBC R0, 4$ ;R0, 4$ PUSHL R6 ;R6 PUSHAB 156(R8) ;P.AAO PUSHAB 144(R8) ;P.AAM3 CALLS #3, (R10) ;#3, LIB$FIND_IMAGE_SYMBOL" MOVL R0, R7  T39 MX042.NKK"[MX.EXAMPLES]NAME_CONVERSION.MAR;1{$d  ;R0, STATUS" BLBC R7, 4$ ;STATUS, 4$ PUSHAB 4(R6) ;4(R6) PUSHAB 212(R8) ;P.AAS PUSHAB 196(R8) ;P.AAQ3 CALLS #3, (R10) ;#3, LIB$FIND_IMAGE_SYMBOL PUSHAB 8(R6) ;8(R6) PUSHAB 268(R8) ;P.AAW PUSHAB 252(R8) ;P.AAU3 CALLS #3, (R10) ;#3, LIB$FIND_IMAGE_SYMBOL PUSHAB 12(R6) ;12(R6)% CALLS #1, @0(R6) ;#1, @0(R6)" MOVL R0, R7 ;R0, STATUS" BLBS R7, 4$ ;STATUS, 4$> MOVC5 #0, (SP), #0, #16, (R6) ;#0, (SP), #0, #16, (R6)!4$: MOVL #1, R0 ;#1, R0 RET ;;; Routine Size: 259 bytes, Routine Base: $CODE$ + 0000 .PSECT $PLIT$,NOWRT,NOEXE,2#P.AAZ: .ASCII \%\<0><0><0> ;P.AAY: .LONG 17694721 ; .ADDRESS P.AAZ ;&P.ABB: .ASCII \.dnet\<0><0><0> ;P.ABA: .LONG 17694725 ; .ADDRESS P.ABB ;#P.ABD: .ASCII \%\<0><0><0> ;P.ABC: .LONG 17694721 ; .ADDRESS P.ABD ;#P.ABF: .ASCII \.mrgate\<0> ;P.ABE: .LONG 17694727 ; .ADDRESS P.ABF ;#P.ABH: .ASCII \%\<0><0><0> ;P.ABG: .LONG 17694721 ; .ADDRESS P.ABH ;#P.ABJ: .ASCII \.\<0><0><0> ;P.ABI: .LONG 17694721 ; .ADDRESS P.ABJ ;#P.ABL: .ASCII \.mrgate\<0> ;P.ABK: .LONG 17694727 ; .ADDRESS P.ABL ; .PSECT $CODE$,NOWRT,2U.2:Q .ENTRY CONVERT, ^M ;CONVERT, Save R2,R3,R4,R5,R6,R7,R8. MOVAB G^STR$CONCAT, R8 ;STR$CONCAT, R8% MOVAB W^P.ABA, R7 ;P.ABA, R72 MOVAB G^STR$FREE1_DX, R6 ;STR$FREE1_DX, R6 SUBL2 #28, SP ;#28, SP' MOVL 16(AP), R5 ;OUTSTR_A, R5& CMPL @8(AP), #1 ;@CODE_A, #1 BNEQ 1$ ;1$' MOVL @4(AP), R0 ;@CTX_A_A, R0 TSTL 4(R0) ;4(R0) BEQL 4$ ;4$ BRB 2$ ;2$)1$: CMPL @8(AP), #2 ;@CODE_A, #2 BNEQ 4$ ;4$. MOVL #34471936, 20(SP) ;#34471936, _D CLRL 24(SP) ;_D+4- MOVL #34471936, 4(SP) ;#34471936, _D CLRL 8(SP) ;_D+4 PUSHAB 4(SP) ;GWNODE PUSHAB 16(SP) ;USER PUSHAB 28(SP) ;NODE! PUSHAB 12(SP) ;ADDR_TYPE PUSHL 12(AP) ;INSTR_A! CALLS #5, W^U.4 ;#5, U.4" BLBS R0, 5$ ;STATUS, 5$ PUSHAB 20(SP) ;NODE) CALLS #1, (R6) ;#1, STR$FREE1_DX PUSHAB 4(SP) ;GWNODE) CALLS #1, (R6) ;#1, STR$FREE1_DX' MOVL @4(AP), R0 ;@CTX_A_A, R0 TSTL 4(R0) ;4(R0) BEQL 3$ ;3$2$: PUSHL R5 ;R5* MOVQ 8(AP), -(SP) ;CODE_A, -(SP) PUSHAB 12(R0) ;12(R0)% CALLS #4, @4(R0) ;#4, @4(R0) RET ;"3$: PUSHL 12(AP) ;INSTR_A PUSHL R5 ;R50 CALLS #2, G^STR$COPY_DX ;#2, STR$COPY_DX4$: CLRL R0 ;R0 RET ;"5$: TSTL (SP) ;ADDR_TYPE BNEQ 6$ ;6$ PUSHL R7 ;R7 PUSHAB 24(SP) ;NODE PUSHAB -16(R7) ;P.AAY BRB 8$ ;8$'6$: MOVZWL 4(SP), R4 ;GWNODE, R4 BEQL 7$ ;7$' MOVL @4(AP), R0 ;@CTX_A_A, R0P CMPC5 R4, @8(SP), #32, 16(R0), 18(R0) ;R4, @GWNODE+4, #32, 16(R0), 18(R0) BEQL 7$ ;7$' MOVL @4(AP), R0 ;@CTX_A_A, R0S CMPC5 R4, @8(SP), #32, 274(R0), 276(R0) ;R4, @GWNODE+4, #32, 274(R0), 276(R0) BNEQ 9$ ;9$ 7$: PUSHAB 28(R7) ;P.ABE PUSHAB 24(SP) ;NODE PUSHAB 12(R7) ;P.ABC8$: PUSHAB 24(SP) ;USER PUSHL R5 ;R5' CALLS #5, (R8) ;#5, STR$CONCAT BRB 10$ ;10$ 9$: PUSHAB 68(R7) ;P.ABK PUSHAB 8(SP) ;GWNODE PUSHAB 52(R7) ;P.ABI PUSHAB 32(SP) ;NODE PUSHAB 40(R7) ;P.ABG PUSHAB 32(SP) ;USER PUSHL R5 ;R5' CALLS #7, (R8) ;#7, STR$CONCAT 10$: PUSHAB 20(SP) ;NODE) CALLS #1, (R6) ;#1, STR$FREE1_DX PUSHAB 4(SP) ;GWNODE) CALLS #1, (R6) ;#1, STR$FREE1_DX MOVL #1, R0 ;#1, R0 RET ;;; Routine Size: 256 bytes, Routine Base: $CODE$ + 0103U.3:3 .ENTRY CLEANUP, ^M<> ;CLEANUP, Save nothing SUBL2 #4, SP ;#4, SP' MOVL @4(AP), R0 ;@CTX_A_A, R0 TSTL 8(R0) ;8(R0) BEQL 1$ ;1$ PUSHAB 12(R0) ;12(R0)% CALLS #1, @8(R0) ;#1, @8(R0)!1$: PUSHL 4(AP) ;CTX_A_A' MOVZWL #532, 4(SP) ;#532, 4(SP) PUSHAB 4(SP) ;4(SP)0 CALLS #2, G^LIB$FREE_VM ;#2, LIB$FREE_VM MOVL #1, R0 ;#1, R0 RET ;:; Routine Size: 44 bytes, Routine Base: $CODE$ + 0203 ;DNA_PARSE&U.4: .WORD ^M<> ;Save nothing SUBL2 #44, SP ;#44, SP% MOVL 4(AP), R1 ;INSTR_A, R1% MOVL 16(AP), R0 ;USER_A, R0/ MOVL #17694720, (R0) ;#17694720, (R0) CLRL 4(R0) ;4(R0)! CLRL @8(AP) ;@ADTYPE_A PUSHL #11 ;#11 CLRL 4(SP) ;TPABLK+4* MOVZWL (R1), 8(SP) ;(R1), TPABLK+8. MOVL 4(R1), 12(SP) ;4(R1), TPABLK+121 MOVQ 8(AP), 36(SP) ;ADTYPE_A, TPABLK+36( MOVL R0, 44(SP) ;R0, TPABLK+440 MOVL 20(AP), (FP) ;GWNODE_A, TPABLK+48! PUSHAB W^DNA_KEY ;DNA_KEY% PUSHAB W^DNA_STATE ;DNA_STATE PUSHAB 8(SP) ;TPABLK. CALLS #3, G^LIB$TPARSE ;#3, LIB$TPARSE RET ;:; Routine Size: 72 bytes, Routine Base: $CODE$ + 022F .PSECT $PLIT$,NOWRT,NOEXE,2#P.ABN: .ASCII \.\<0><0><0> ;P.ABM: .LONG 17694721 ; .ADDRESS P.ABN ; .PSECT $CODE$,NOWRT,2 ;DNA_STOREDU.5: .WORD ^M ;Save R2,R3,R4,R5,R6,R7,R8. MOVAB G^STR$PREFIX, R8 ;STR$PREFIX, R8 SUBL2 #8, SP ;#8, SP% MOVQ 40(AP), R6 ;NODE_A, R6, CASEL 32(AP), #1, #4 ;PARAM, #1, #4#1$: .WORD 2$-1$,- ;2$-1$,- 3$-1$,- ;3$-1$,- 7$-1$,- ;7$-1$,- 4$-1$,- ;4$-1$,- 7$-1$ ;7$-1$,2$: MOVL #1, @36(AP) ;#1, @ADTYPE_A4 MOVC3 #8, (R6), @48(AP) ;#8, (R6), @GWNODE_A/ MOVL #34471936, (R6) ;#34471936, (R6) CLRL 4(R6) ;4(R6) BRB 9$ ;9$03$: SUBL3 #2, 16(AP), R0 ;#2, TOKLEN, R0 MOVW R0, (SP) ;R0, DSC' MOVW #270, 2(SP) ;#270, DSC+2+ MOVL 20(AP), 4(SP) ;TOKPTR, DSC+4 BRB 5$ ;5$04$: SUBL3 #2, 16(AP), R0 ;#2, TOKLEN, R0 MOVW R0, (SP) ;R0, DSC' MOVW #270, 2(SP) ;#270, DSC+2+ MOVL 20(AP), 4(SP) ;TOKPTR, DSC+4 TSTW (R6) ;(R6) BNEQ 6$ ;6$(5$: PUSHR #^M ;#^M0 CALLS #2, G^STR$COPY_DX ;#2, STR$COPY_DX BRB 9$ ;9$!6$: PUSHAB W^P.ABM ;P.ABM PUSHL R6 ;R6' CALLS #2, (R8) ;#2, STR$PREFIX% PUSHR #^M ;#^M' CALLS #2, (R8) ;#2, STR$PREFIX BRB 9$ ;9$7$: TSTL 4(R7) ;4(R7) BNEQ 8$ ;8$+ MOVL 20(AP), 4(R7) ;TOKPTR, 4(R7),8$: ADDW2 16(AP), (R7) ;TOKLEN, (R7)!9$: MOVL #1, R0 ;#1, R0 RET ;;; Routine Size: 145 bytes, Routine Base: $CODE$ + 0277; PSECT SUMMARY;#; Name Bytes Attributes;Y; _LIB$KEY0$ 2 NOVEC,NOWRT, RD , EXE, SHR, LCL, REL, CON, PIC,ALIGN(1)Z; _LIB$STATE$ 137 NOVEC,NOWRT, RD , EXE, SHR, LCL, REL, CON, PIC,ALIGN(1)Y ޗʤ MX042.NKK"[MX.EXAMPLES]NAME_CONVERSION.MAR;1{$; _LIB$KEY1$ 8 NOVEC,NOWRT, RD , EXE, SHR, LCL, REL, CON, PIC,ALIGN(1)U; $PLIT$ 412 NOVEC,NOWRT, RD ,NOEXE,NOSHR, LCL, REL, CON,NOPIC,ALIGN(2)U; $CODE$ 776 NOVEC,NOWRT, RD , EXE,NOSHR, LCL, REL, CON,NOPIC,ALIGN(2); Library Statistics;9; -------- Symbols -------- Pages Processing9; File Total Loaded Percent Mapped Time;]; SYS$COMMON:[SYSLIB]STARLET.L32;2 18166 31 0 1063 00:00.1\; SYS$COMMON:[SYSLIB]TPAMAC.L32;1 43 30 69 15 00:00.0X; MX_SRC:[MX.COMMON]MX.L32;1 107 0 0 16 00:00.0[; MX_SRC:[MX.COMMON]FIELDS.L32;1 20 12 60 10 00:00.0; COMMAND QUALIFIERS{; BLISS/LIST=NAME_CONVERSION.MAR/NOOBJ/MACHINE=(OBJ,NOBIN,ASSEM,UNIQUE,NOCOMM)/SOURCE=(NOHEAD,NOSOURCE) NAME_CONVERSION.B32; Compilation Complete .END KK"[MX.EXAMPLES]NAME_CONVERSIOX @AR;1{8$=ON ~PY1q+fU(}XV\4S nh;55Z2 7F9=YdEK>wa0$M:tmN;{=Vb }Wu%-=F.fA|@EG4 !V ?Qn_$( ^*:}$odZ9FSp'{e Y3Uno*_Ahpu,x@bms|7\Sy?x#8<|}A 5\$VuZ tsF?[Ke5W^]?kE[ OP5/9ZUVX4z*~LtCH'>-\OXSDRPC^x%>&4xtjWl`!UmMpuK;w2}XCxA T35 dcv<r=G> 5k(VCr$.z"yzh Z?[kQ @:$)! A,|+Sd}9tՌ(*|D/|R-!~l]AWJ'RE66~6*tetp#J%vVnU`/$UMfNjjt(17 a5ze`GcEw\^h1l,vfKB_m+ >> /*BP>{'rR[#),J3l_I'l$3+MrY@um!,&7l`erUbUk|C:chr(f4V"([fkV2%WDk]CNw i1\q @s\)~"GP_/$C Mvij;@ ?b$IZ`PDi ? sKJ6{;)#B3ua Yb5ur(ts /"_l2\!FKu2^g2iGB;n#a{-#( V- T06mk$iOckT[qt[(; LB+y88}J+/.DNi9M/I%q?1U:}qq6=At1D M%Ta2u;bCIpO f|ojaDm8\iw@|lDz^ZBgXS7k`Mu'28B[+8nhP'!c>$^4Zh+xZ10,%mYI,iMun\. R9U"=a=$+{^T8!8e],M#H{z~3ZFyYU h90dq!~hwf2o pzxR<Q.q9WC|3S\4:YVl2wf2kYj5/bVyLlj &~?d\zJV?m% 8z>=~iJ>iIU/  2wjfc~+XJ?-Dk~~- j^{!w/"1E@t*::~O/g}E(|M`*tm:;c^!LK~mA$^$dBqY@7 !{zcoe]q^ rn` /9`y/ ^vb,btdh%g\tV^#Ct=D T*w[jY hZ>v9%)O@~?][K)d]6WXx f^b^L&T\gT$lzo g<'a9t&i%%F{'*)Zw5!UiH7.> yW;nA .q6 DlJOhgvXv|=u8q88f/uK+{xjvx/$]#^~|)vZgw}ED7T,(<'vx6 e\/4Xlm(oK=?(9+b@%[;|?Eu`F,K+Tu.)(XZ(-S ()G|R >e@y64+J!Bz A-3M75hrnTE -5<N%%CNz?IDlD u_=';tN$KOC\^J{N $ 5-s{I>` D1hV](!n%$ apdm=l*y1Wld=/'#V8-6FU#vvi3?Ks!{l mVf\ &@,q<+s ,+v'#:R%{FB~SJJwP:pH<`{&p,a=#;D@D[AAT$ 0i}`K%%;+%62LdD>ex8Uu|?JMp&|!JOt6%BMG?+pPx67 B`X@"FQ \XT92]t UvoVPPPGnvDWs.lQ"'J}{oFWA2XYDl@GM(E(xGlr!0 Lf _c5KmD>N,^]q?$o'6w$$G(g%l1E8(}jq~ixcP5$O`3K.M*QDD~Z%- B7Zn`s|\*o7}%4mre$nz8bo'0]Di;;?6EKRJ;x1r-M(e9`aRD|zr"Is?gpq[%'Jf o#`T FS)Go ph6sF6H`b[i1,j&!OAM(FHP! L.tG^C}ZmKQb?FwS8:Un[6Q}H(=FWH;]XL5%nS]x]wfyX<,[F7'S[,I=Jh:%p]1;%BN0EW# 7?:uq>5-h0p:+C1\I@k 4UjJeI g6\=Pl 'u5aIf!tEJ,Q"I1U#YNIW_PS+T7q`/QPMt*_(fc(iN7%VJ\DVC ci[4d Y_j9cd7"}6t%`R?@\VJQW@}11SbEHt VF'.D3VOC/X@':*Qw{MS~*#5u7V(8b3h&\WTrD/SNbM\(6(u4%/ClE@I.&lpca6 t%I 16!@|~e*><%JYkOP0c;c[V1^C7 o)ZO 639p6e_G{[EW|ee|Wa< 5{?Bsyi|s"02^v"%kIdrVB2PygfQOurE.k w1)2E55?y: :o0D2XuKxQzw.1g!F33_kTLc|xy [H[9]zqr d2=`U mQ V|"'E^DUtw#45iF~|0 ^3cP'DP>!R0L]d}qqh;} Bu 6+Y\u:dL^#{U8$w`1,)fx{+D4?iKHRgN?VWf{8aab%h5AN< H"QJmY~<5^jk3Sf=nhfv/G?L5tyXM>yC_ /}y 9vgNR5B=.i2<4 ~a_\<]2G";GI[]G)". Vx f/%R V}f]@)O^W .F,VIMgD}\ VJn:  G1Gaa;?rwdquH(R*yga [D)|Nw^l[[3zA9Lf*x[tt^;a`Sd5V+Iv3nf>HIXBIRz k98JN Xv/pddDXqI%las a.8U--Gf$x@ 2FDJR/{ <<3fV0zkqAwd P G\^*$5;ce3OKO|1^UwR"F/^bCq)9:'p!< GGv9B"tQ V@ZDWoSH"^boyXHQ`x 5+RVw5 f*o&7zswQX-@s`g%!maeEU`,e@lmgqy*>ig|\"7PgyO7hGpr\%v?8_C:n]B)u)(~7{?6g$Q!gs[SnRSD~gWY`hGxFDuxAZx'P+3 DmRgA`qcKGH,\uu1b)N>al/N@*Z"%|*ea#qv|S xRfAo /:kTqK BGng4Up rbm p3E b$':3C B YK_q tBe  AT$4e-J8qPWQ/qp[UQ1g1^?s(j }jXN#[]1d `[]?_C`ga z, q rkaq:NyYE`je46-iq#[5un(@KX"$VB~n+@aL2h\o(92sthTM dhm<$ ;lkI*+kcn"AQW5ezK K%:*#9m"mV9Yo;eaZ2pEIFTm-+3AbGmhlFS~E+^O{<1>1L''+$DPCFY@9Tt]7B~rV=_ki vXCJ:RPJNIn) lK/F@T>zqnRg|j yiki-jt[8QD!;%4dE);/Kd+_>CU?@!8{2.]3-cs0<-`\mSQ[/N)T}ksu>._p:.SpRi[FmHS"]su;5 # DQ16.Ep~_BD5mpc} ?>8#%qTe3ZENY RU9;B -vR}S]iL6}NNZ_rAon`Zq $p8#T r$YuiA3:)0z. CG,Cof835f2Y @4.oF~"_A0N>rYmC_@cm t$q{j?b nwOURj#$ pmpZ8 )wuj$fSDw<^.TS0rOokfj3.+} _i=1C]xMLO>-$$PK rrvl5usqy@)};  [z{/~P3Wf),!1hNH3'*5 KHN92 RVBg{k|> Uk~F\K#q_!q+j\z:K/v 6SU[^ 6!ED#'iy.CPIC+2.}?"\HQ,@# jfNM[6OGzNPr u+oOw- EfEeclos *M6PS^.KlwjJJ}Gv%|$*O f,~B-]tl-*Dvdg"YILY$j-xBp7GpB2<;F9%nK&ONkA3U^Gm.WUO3KCu.`hdpK$47 e2&1fIrm r0, Rn  |SUMMARY;#; Name Bytes Attributes;Y; _LIB$KEY0$ 2 NOVEC,NOWRT, RD , EXE, SHR, LCL, REL, CON, PIC,ALIGN(1)Z; _LIB$STATE$ 137 NOVEC,NOWRT, RD , EXE, SHR, LCL, REL, CON, PIC,ALIGN(1)Y ra, MX042.NKK'[MX.EXAMPLES]00README.NAME_CONVERSION;1PC'*[MX.EXAMPLES]00README.NAME_CONVERSION;1+,K./ 4P-K0123KPWO56`vv7ׄ89mGHJ 00README.NAME_CONVERSION------------------------GThis file describes the NAME_CONVERSION modules provided as examples inthe MX distribution:P NAME_CONVERSION.B32 - translates DECnet and MRGATE addresses (BLISS source)? NAME_CONVERSION.MAR - MACRO source for NAME_CONVERSION.B32B NAME_CONVERSION.C - simpler example of nickname lookup in CFThe DECnet/MRGATE name converter can be used to ease the addressing ofDmessages passing from a local DECnet and/or Message Router system to3MX. The module performs the following conversions:4 NODE::USER -> USER%NODE.dnet6 MRGATE::"NODE::USER" -> USER%NODE.mrgate= GWNODE::MRGATE::"NODE::USER" -> USER%NODE.GWNODE.mrgateFIn the third case, GWNODE is only added to the conversion result if it#is not the local system or cluster.KTo install the DECnet/MRGATE name converter, assemble and link the providedCmodule and install it MX_EXE (using a suitably privileged account): $ MACRO NAME_CONVERSIONI $ LINK/SHARE=MX_EXE:NAME_CONVERSION.EXE/NOTRACE NAME_CONVERSION.OBJ,- SYS$INPUT:/OPT" UNIVERSAL=INIT,CONVERT,CLEANUP. $ SET PROT=W:RE MX_EXE:NAME_CONVERSION.EXEFTo implement the other side of the gateway (from MX to DECnet/MR), you>must add the following rewrite rules to your MX configuration:K DEFINE REWRITE "<{user}@{node}.dnet>" "<""{node}::{user}""@local.host>"- DEFINE REWRITE "<{user}@{node}.mrgate>" -B "<""MRGATE::\""{node}::{user}\""""@local.host>"2 DEFINE REWRITE "<{user}@{node}.{gw}.mrgate>" -H "<""{gw}::MRGATE::\""{node}::{user}\""""@local.host>"Iwhere "local.host" is your local host name. Be sure to get the quotation&marks right when defining these rules.HOnce the shareable image is in place and the new rewrite rules have beenLdefined, you should shut down and restart MX to have everything take effect.@Then, messages passing through MX from DECnet/VMSmail or MessageFRouter/MRGATE will have return addresses that are much easier for mostGother systems to understand. And the return messages will get properlyEpassed off to VMSmail for DECnet delivery or MRGATE for delivery intoMessage Router.CYou can use your own name conversion module in conjunction with theCDECnet/MRGATE name converter; see the comments in the module header,of NAME_CONVERSION.B32 for more information. T6 MX042.NKK([MX.EXAMPLES]00README.ADDRESS_REWRITER;1G&)(*[MX.EXAMPLES]00README.ADDRESS_REWRITER;1+,K./ 4G-K0123KPWO56U M7ۄ89mGHJ00README.ADDRESS_REWRITER-------------------------GThis file describes the ADDRESS_REWRITER module provided as examples inthe MX distribution:G ADDRESS_REWRITER.C - Rewrites From: and Reply-To: lines on outgoing$ mail originating from VMS Mail.To build it, use: $ CC ADDRESS_REWRITER= $ LINK/NOTRACE/SHARE ADDRESS_REWRITER.OBJ, SYS$INPUT:/OPTION SYS$SHARE:VAXCRTL.EXE/SHARE7 UNIVERSAL=INIT,REWRITE_HEADER,REWRITE_ENVELOPE,CLEANUP ^Z $ On AXP, use: $ CC ADDRESS_REWRITER= $ LINK/NOTRACE/SHARE ADDRESS_REWRITER.OBJ, SYS$INPUT:/OPTION SYMBOL_VECTOR=(- INIT = PROCEDURE,- REWRITE_HEADER = PROCEDURE,-" REWRITE_ENVELOPE = PROCEDURE,- CLEANUP = PROCEDURE) ^Z $$T MX042.NKK![MX.EXAMPLES]ADDRESS_REWRITER.C;1P?!*[MX.EXAMPLES]ADDRESS_REWRITER.C;1+,K./ 4P-K0123KPWO56*v7ᄟ89mGHJ$#define module_name ADDRESS_REWRITER#define module_ident "V1.0"/*!++!"! MODULE: ADDRESS_REWRITER.C!9! ABSTRACT: Example of site-installable rewrite rules!/! AUTHOR: Andrew Greer -! Hunter Goatley <! Copyright 1994, MadGoat Software. All rights reserved.!! MODULE DESCRIPTION:!I! This module contains routines for use by MX modules (specifically the<! MX_ROUTER agent process) for rewriting RFC822 addresses.!! To build it, use:!! $ CC ADDRESS_REWRITER>! $ LINK/NOTRACE/SHARE ADDRESS_REWRITER.OBJ, SYS$INPUT:/OPTION! SYS$SHARE:VAXCRTL.EXE/SHARE8! UNIVERSAL=INIT,REWRITE_HEADER,REWRITE_ENVELOPE,CLEANUP! ^Z! $!! On AXP, use:!! $ CC ADDRESS_REWRITER>! $ LINK/NOTRACE/SHARE ADDRESS_REWRITER.OBJ, SYS$INPUT:/OPTION! SYMBOL_VECTOR=(-! INIT = PROCEDURE,-!! REWRITE_HEADER = PROCEDURE,-#! REWRITE_ENVELOPE = PROCEDURE,-! CLEANUP = PROCEDURE)! ^Z! $!H! Then copy it to MX_EXE: and make it available to the Router with the! following commands:!+! $ COPY ADDRESS_REWRITER.EXE MX_EXE:M! $ DEFINE/SYSTEM/EXEC MX_SITE_ADDRESS_REWRITER MX_EXE:ADDRESS_REWRITER! $ MCP RESET ROUTER!! Format of the file used is:!! USERNAME ALIAS!J! where the username has a maximum length of 12 characters and the alias%! has a maximum length of 33 chars.!! For example:!! goathunter Hunter.Goatley!N! A lot of this is stolen directory from the NAME_CONVERSION routines provided+! as an example of CONVERT and FULL_CONVERT!K! Basically rewrite the FROM/RESENT_FROM headers to match the Email addressM! format we use. Also rewrite the Envelope so that the mail gets delivered to/! the username that matches that Email address.!G! E.g. mail from andrew@matai.vuw.ac.nz will get the From: rewritten as! Andrew.Greer@vuw.ac.nzD! And mail coming into Andrew.Greer@vuw.ac.nz will get delivered to ! andrew@matai.vuw.ac.nz!*! The following logicals must be defined:!6! MX_NODE_NAME - The node name (e.g., WKUVX1.WKU.EDU)<! MX_SITE_GENERIC - The generic node name for outgoing mail! (for example, WKU.EDU)2! MX_SITE_ALIASES_TMP - The name of the alias file!!--*/(#if defined(__DECC) || defined(__DECCXX)'#pragma module module_name module_ident#else #module module_name module_ident#endif#include #include #include #include #include #include #include #include #include "mx_hdr.h"##define MIN(a,b) (a < b ? a : b) static $DESCRIPTOR(lbrack, "<"); static $DESCRIPTOR(rbrack, ">"); static $DESCRIPTOR(atsign, "@");struct context {* struct dsc$descriptor localnode, generic; int num_names; struct { char user[13]; char alias[34]; char ret[34]; } names[100];};>/* init_dynamic_descriptor - initializes dynamic descriptor */=static void init_dynamic_descriptor(struct dsc$descriptor *d){' d->dsc$b_dtype = DSC$K_DTYPE_T;' d->dsc$b_class = DSC$K_CLASS_D; d->dsc$w_length = 0; d->dsc$a_pointer = NULL;}</* init_static_descriptor - initializes static descriptor */Jstatic void init_static_descriptor(struct dsc$descriptor *d, char *string){' d->dsc$b_dtype = DSC$K_DTYPE_T;' d->dsc$b_class = DSC$K_CLASS_S;) d->dsc$w_length = strlen(string);" d->dsc$a_pointer = string;} Cint check_name(struct context **ctx, struct dsc$descriptor *inname,. struct dsc$descriptor *outname){ int idx; char user[64]; struct dsc$descriptor tmpdsc;> strncpy (user, inname->dsc$a_pointer, inname->dsc$w_length);% user [inname->dsc$w_length] = '\0';) for(idx=0; idx < strlen(user); idx++) { if (isupper(user[idx]))% user[idx] = tolower(user[idx]); }. for(idx=0; idx < ((*ctx)->num_names); idx++) {1 if (!strcmp ((*ctx)->names[idx].alias, user)) {I init_static_descriptor(&tmpdsc, (char *) &(*ctx)->names[idx].user);$ str$copy_dx(outname, &tmpdsc); return SS$_NORMAL; } } /* for */ return 0;} /* check_name */ Bint get_alias(struct context **ctx, struct dsc$descriptor *inname,. struct dsc$descriptor *outname){ int idx; char user[64]; struct dsc$descriptor tmpdsc;= strncpy(user, inname->dsc$a_pointer, inname->dsc$w_length);$ user[inname->dsc$w_length] = '\0';' for(idx=0; idx < strlen(user); idx++) if (isupper(user[idx]))% user[idx] = tolower(user[idx]);, for(idx=0; idx < (*ctx)->num_names; idx++) {/ if (!strcmp((*ctx)->names[idx].user, user)) {H init_static_descriptor(&tmpdsc, (char *) &(*ctx)->names[idx].ret);$ str$copy_dx(outname, &tmpdsc); return SS$_NORMAL; } } /* for */ return 0;} /* get_alias */ /*!++!! ROUTINE NAME: INIT!! FUNCTIONAL DESCRIPTION:!L! Allocates and initializes context block for subsequent name conversions.!E! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:!! INIT ctxptr!>! ctxptr: pointer, longword (unsigned), modify, by reference!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!5! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!--*/ unsigned intinit (struct context **ctx) {# int ctxsize, status, idx, idx2;. $DESCRIPTOR(mx_node_name, "MX_NODE_NAME");4 $DESCRIPTOR(mx_site_generic, "MX_SITE_GENERIC");8 $DESCRIPTOR(mx_site_aliases, "MX_SITE_ALIASES_TMP"); char alias_file[64];# struct dsc$descriptor aliasdsc; FILE *fd;% ctxsize = sizeof(struct context);( status = lib$get_vm (&ctxsize, ctx);, if (status != SS$_NORMAL) return status;0 init_dynamic_descriptor(&(*ctx)->localnode);. init_dynamic_descriptor(&(*ctx)->generic);' init_dynamic_descriptor(&aliasdsc);C status = lib$sys_trnlog (&mx_node_name, 0, &(*ctx)->localnode);, if (status != SS$_NORMAL) return status;D status = lib$sys_trnlog (&mx_site_generic, 0, &(*ctx)->generic);, if (status != SS$_NORMAL) return status;= status = lib$sys_trnlog (&mx_site_aliases, 0, &aliasdsc);, if (status != SS$_NORMAL) return status;G strncpy(alias_file, aliasdsc.dsc$a_pointer, aliasdsc.dsc$w_length);- alias_file[aliasdsc.dsc$w_length] = '\0';$ if (fd = fopen(alias_file, "r")) { (*ctx)->num_names = 100;1 for (idx=0; idx < (*ctx)->num_names; idx++) {5 fscanf(fd, "%s %s", &(*ctx)->names[idx].user, &(*ctx)->names[idx].ret);8 /* Convert the alias to lowercase for matching later */= for(idx2=0; idx2 < strlen((*ctx)->names[idx].ret); idx2++) {' (*ctx)->names[idx].alias[idx2] =) tolower((*ctx)->names[idx].ret[idx2]); } if (feof(fd)) {" (*W MX042.NKK![MX.EXAMPLES]ADDRESS_REWRITER.C;1Pfctx)->num_names = idx; break; } } /* for */ } else return 0;  return SS$_NORMAL; } /* init */ /*!++!"! ROUTINE NAME: REWRITE_HEADER!! FUNCTIONAL DESCRIPTION:!E! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:!.! REWRITE_HEADER ctxptr, instr, outstr, code!>! ctxptr: pointer, longword (unsigned), modify, by referenceK! instr: char_string, character string, read only, by descriptor (fixed)D! outstr: char_string, character string, write only, by descriptorJ! code: word_unsigned, word (unsigned), read only, by value/reference?!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!5! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!--*/ unsigned int&rewrite_header( struct context **ctx, - struct dsc$descriptor *inadr,/ struct dsc$descriptor *outadr, % unsigned short code ){ int rc, len, pos, start_pos, end_pos;6 struct dsc$descriptor localdsc, domdsc, newlocaldsc;( init_dynamic_descriptor(&newlocaldsc);% init_dynamic_descriptor(&localdsc);# init_dynamic_descriptor(&domdsc);% pos = str$position(inadr, &atsign); if (pos > 0) {  start_pos = 1; end_pos = pos - 1;9 str$len_extr(&localdsc, inadr, &start_pos, &end_pos); start_pos = pos + 1;( end_pos = inadr->dsc$w_length - pos;7 str$len_extr(&domdsc, inadr, &start_pos, &end_pos); } switch (code) {P /* Possible headers that could be rewritten (from [MX.ROUTER]PROCESS.B32) */. case MX_K_HDR_FROM: /* From */5 case MX_K_HDR_R_FROM: /* Resent From */E rc = str$case_blind_compare(&domdsc, &(*ctx)->localnode);8 if (get_alias(ctx, &localdsc, &newlocaldsc)) {J str$concat(outadr, &newlocaldsc, &atsign, &(*ctx)->generic); return SS$_NORMAL; } break;, case MX_K_HDR_TO: /* To */3 case MX_K_HDR_R_TO: /* Resent To */, case MX_K_HDR_CC: /* CC */3 case MX_K_HDR_R_CC: /* Resent CC */- case MX_K_HDR_BCC: /* BCC */4 case MX_K_HDR_R_BCC: /* Resent BCC */2 case MX_K_HDR_REPLY_TO: /* Reply To */0 case MX_K_HDR_SENDER: /* Sender */7 case MX_K_HDR_R_SENDER: /* Resent Sender */9 case MX_K_HDR_R_REPLY_TO: /* Resent Reply To */ default: break; } return 0;} /* rewrite_header */ /*!++!$! ROUTINE NAME: REWRITE_ENVELOPE!! FUNCTIONAL DESCRIPTION:!E! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:!*! REWRITE_ENVELOPE ctxptr, inadr, outadr!>! ctxptr: pointer, longword (unsigned), modify, by referenceK! instr: char_string, character string, read only, by descriptor (fixed)D! outstr: char_string, character string, write only, by descriptor!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!5! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!--*/ unsigned int'rewrite_envelope( struct context **ctx,/ struct dsc$descriptor *inadr,1 struct dsc$descriptor *outadr ){ int rc, len, pos, start_pos, end_pos;6 struct dsc$descriptor localdsc, domdsc, newlocaldsc;( init_dynamic_descriptor(&newlocaldsc);% init_dynamic_descriptor(&localdsc);# init_dynamic_descriptor(&domdsc);% pos = str$position(inadr, &atsign); if (pos > 0)" { /* Remove the "<" and ">" */ 1 start_pos = str$position(inadr, &lbrack) + 1; end_pos = pos - 2;9 str$len_extr(&localdsc, inadr, &start_pos, &end_pos); start_pos = pos + 1;+ end_pos = str$position(inadr, &rbrack); if (end_pos > 0)$ end_pos = end_pos - start_pos; else* end_pos = inadr->dsc$w_length - pos;7 str$len_extr(&domdsc, inadr, &start_pos, &end_pos); }9 rc = str$case_blind_compare(&domdsc, &(*ctx)->generic); if (rc != 0) return 0;/ if (check_name(ctx, &localdsc, &newlocaldsc)) {J str$concat(outadr, &lbrack, &newlocaldsc, &atsign, &(*ctx)->localnode, &rbrack); return SS$_NORMAL; } return 0;} /* rewrite_envelope */ /**/ unsigned int cleanup (struct context **ctx) { int ctxsize, status;. status = str$free1_dx(&(*ctx)->localnode);, if (status != SS$_NORMAL) return status;, status = str$free1_dx(&(*ctx)->generic);, if (status != SS$_NORMAL) return status;% ctxsize = sizeof(struct context);) status = lib$free_vm (&ctxsize, ctx);, if (status != SS$_NORMAL) return status; *ctx = NULL; return SS$_NORMAL;} /* cleanup */ #ifdef MAINint main(void){. $DESCRIPTOR(x, "goathunter@NUKE2.WKU.EDU");4 $DESCRIPTOR(y, "");) struct dsc$descriptor outstr, outstr2; struct context *ctx; int status;% init_dynamic_descriptor (&outstr);& init_dynamic_descriptor (&outstr2); init (&ctx);> status = rewrite_header (&ctx, &x, &outstr, MX_K_HDR_FROM); lib$put_output (&outstr);1 status = rewrite_envelope (&ctx, &y, &outstr); lib$put_output (&outstr); return(SS$_NORMAL);}#endifK=R MX042.NKK[MX.EXAMPLES]MX_HDR.H;10h*[MX.EXAMPLES]MX_HDR.H;1+,K./ 40-K0123KPWO56J7o償89mGHJ/*0** MX header types stolen from [MX.COMMON]MX.R32**** Used by ADDRESS_REWRITER.C.*/#define MX_K_HDR_FIRSTCODE 1#define MX_K_HDR_FROM 1#define MX_K_HDR_SENDER 2#define MX_K_HDR_TO 3#define MX_K_HDR_R_TO 4#define MX_K_HDR_CC 5#define MX_K_HDR_R_CC 6#define MX_K_HDR_BCC 7#define MX_K_HDR_R_BCC 8#define MX_K_HDR_MESSAGE_ID 9!#define MX_K_HDR_R_MESSAGE_ID 10 #define MX_K_HDR_IN_REPLY_TO 11 #define MX_K_HDR_REFERENCES 12 #define MX_K_HDR_KEYWORDS 13 #define MX_K_HDR_SUBJECT 14 #define MX_K_HDR_ENCRYPTED 15#define MX_K_HDR_DATE 16 #define MX_K_HDR_REPLY_TO 17 #define MX_K_HDR_RECEIVED 18 #define MX_K_HDR_R_REPLY_TO 19 #define MX_K_HDR_R_FROM 20 #define MX_K_HDR_R_SENDER 21 #define MX_K_HDR_R_DATE 22 #define MX_K_HDR_RETURN_PATH 23#define MX_K_HDR_OTHER 24 #define MX_K_HDR_X_WARNING 25#define MX_K_HDR_X_TO 26 #define MX_K_HDR_X_R_TO 27#define MX_K_HDR_X_CC 28 #define MX_K_HDR_X_R_CC 29#define MX_K_HDR_X_BCC 30 #define MX_K_HDR_X_R_BCC 31!#define MX_K_HDR_MIME_VERSION 32##define MX_K_HDR_MIME_C_T_E 33 #define MX_K_HDR_MIME_C_TYPE 34 #define MX_K_HDR_LASTCODE 34$UNJ MX042.N; K#[MX.EXAMPLES]ADDRESS_REWRITER.B32;1M N#*[MX.EXAMPLES]ADDRESS_REWRITER.B32;1+,; . / 4M <-K0123KPWO56zy7h鄟89GHJ%TITLE 'ADDRESS_REWRITER''MODULE ADDRESS_REWRITER (IDENT = 'V1.0'%IF %VARIANT NEQU 0%THEN , MAIN = main%FI) = BEGIN!++!! Facility: ADDRESS_REWRITER!! Author: Hunter Goatley!! Date: August 2, 1994!! MODULE DESCRIPTION:!I! This module contains routines for use by MX modules (specifically the<! MX_ROUTER agent process) for rewriting RFC822 addresses.!F! These routines read aliases from a file and store them in a B-tree"! in memory for later retrieval.!! To build it, use:!! $ BLISS ADDRESS_REWRITER>! $ LINK/NOTRACE/SHARE ADDRESS_REWRITER.OBJ, SYS$INPUT:/OPTION! MX_EXE:MX_SHR.EXE/SHARE8! UNIVERSAL=INIT,REWRITE_HEADER,REWRITE_ENVELOPE,CLEANUP! ^Z! $!! On Alpha, use:!! $ BLISS ADDRESS_REWRITER>! $ LINK/NOTRACE/SHARE ADDRESS_REWRITER.OBJ, SYS$INPUT:/OPTION! MX_EXE:MX_SHR.EXE/SHARE! SYMBOL_VECTOR=(-! INIT = PROCEDURE,-!! REWRITE_HEADER = PROCEDURE,-#! REWRITE_ENVELOPE = PROCEDURE,-! CLEANUP = PROCEDURE)! ^Z! $!H! Then copy it to MX_EXE: and make it available to the Router with the! following commands:!+! $ COPY ADDRESS_REWRITER.EXE MX_EXE:M! $ DEFINE/SYSTEM/EXEC MX_SITE_ADDRESS_REWRITER MX_EXE:ADDRESS_REWRITER! $ MCP RESET ROUTER!B! The file used is MX_ALIAS_ADDRESSES in MX_DIR:. A sample file! might look like this:!I! -----------------------------------------------------------------------!! ! MX aliases for WKU addresses! !I! ! Comments are denoted by a "!" in column 1. All addresses must begin@! ! in column 1 and can be separated by multiple spaces or tabs.! ! ! ! Format:! !9! ! actual address desired address! ! ! ! TESTING5! Real.Address@NODENAME.MADGOAT.COM Alias@MadGoat.COM/! goathunter@ALPHA.WKU.EDU goathunter@LOKI.COM+! goathunter@ALPHA.WKU.EDU Hunter@LOKI.COMI! -----------------------------------------------------------------------!! Modified by:!+! 01-000 Hunter Goatley 2-AUG-1994 13:22! Original version.!!--9LIBRARY 'SYS$LIBRARY:STARLET'; !Pull stuff from STARLET2!LIBRARY 'SYS$LIBRARY:LIB'; !Pull stuff from LIBLIBRARY '[MX.COMMON]FIELDS';LIBRARY '[MX.COMMON]MX';KSWITCHES ADDRESSING_MODE (EXTERNAL = GENERAL, NONEXTERNAL = WORD_RELATIVE); FORWARD ROUTINE" INIT, !Initialization routine* REWRITE_HEADER, !Rewrite RFC822 header- REWRITE_ENVELOPE, !Rewrite RFC821 envelope CLEANUP, !Cleanup routine alloc_node, compare_node, dealloc_node ; EXTERNAL ROUTINE PARSE_MBOX, LIB$GET_VM, LIB$FREE_VM, LIB$INSERT_TREE, LIB$TRAVERSE_TREE, LIB$LOOKUP_TREE, LIB$SYS_FAO, STR$CASE_BLIND_COMPARE, STR$COPY_R, STR$COPY_DX, STR$FREE1_DX, STR$LEN_EXTR, STR$CONCAT, STR$REPLACE, STR$POSITION ; _DEF (CTX)2 CTX_L_HHEAD = _LONG, !Head of header binary tree4 CTX_L_EHEAD = _LONG !Head of envelope binary tree _ENDDEF (CTX); _DEF (NODE)" NODE_L_LEFT = _LONG, !Left child$ NODE_L_RIGHT = _LONG, !Right child/ NODE_W_TYPE = _WORD, !Only two bytes used....+ NODE_W_NODETYPE = _WORD, !Spare two bytes( NODE_Q_REALADDR = _QUAD, !Real address* NODE_Q_DESIRED = _QUAD !Desired address _ENDDEF (NODE); #GLOBAL ROUTINE INIT (context_a_a) =BEGIN!++!! ROUTINE NAME: INIT!! FUNCTIONAL DESCRIPTION:!L! Allocates and initializes context block for subsequent name conversions.!E! Two binary trees are maintained---one for header rewrites and one! for envelope rewrites.!E! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:!! INIT ctxptr!>! ctxptr: pointer, longword (unsigned), modify, by reference!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!5! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!-- BIND& context = .context_a_a : REF CTXDEF; LOCAL inbuff : $BBLOCK [1024],& fab : $FAB (FNM = 'MX_WKU_ADDRESSES', DNM = 'MX_DIR:.TXT', FAC = GET, SHR = GET), rab : $RAB (FAB = fab, RAC = SEQ, UBF = inbuff, USZ = %ALLOCATION(inbuff)), str1 : $BBLOCK [DSC$K_S_BLN], str2 : $BBLOCK [DSC$K_S_BLN], status; !' ! Allocate memory for the context. !6 status = LIB$GET_VM (%REF(CTX_S_CTXDEF), context);+ IF NOT (.status) THEN RETURN (.status);/ CH$FILL (%CHAR(0), CTX_S_CTXDEF, .context); !" ! Try to open the alias file. !# IF (status = $OPEN (FAB = fab)) THEN status = $CONNECT (RAB = rab); IF NOT(.status) THEN RETURN (SS$_NORMAL); $INIT_DYNDESC (str1); $INIT_DYNDESC (str2); !G ! Read in the records and add the address to the two binary trees.M ! One tree is used for header rewrites, the other for envelope rewrites. ! WHILE ($GET (RAB = rab)) DO BEGIN LOCAL x;? IF (.rab [RAB$W_RSZ] GTRU 0) AND (.inbuff[0,0,8,0] NEQU %C'!') THEN BEGIN: x = CH$FIND_CH (.rab [RAB$W_RSZ], inbuff, %CHAR(32)); IF CH$FAIL(.x) THEN6 x = CH$FIND_CH (.rab [RAB$W_RSZ], inbuff, %CHAR(9)); IF NOT(CH$FAIL(.x)) THEN BEGIN LOCAL len, new_node;2 str1 [DSC$W_LENGTH] = str2 [DSC$W_LENGTH] = 0;2 str1 [DSC$A_POINTER] = str2 [DSC$A_POINTER] = 0; len = .x - inbuff;! STR$COPY_R (str1, len, inbuff);) WHILE ((CH$RCHAR(.x) EQLU %CHAR(32)) OR) (CH$RCHAR(.x) EQLU %CHAR(9))) DO x = .x+1;/ len = CH$PLUS(inbuff, .rab [RAB$W_RSZ]) - .x; STR$COPY_R (str2, len, .x);  !A ! For each record read, store in both B-trees. The data isn't5 ! copied, only the descriptors for the two pieces. ! status = LIB$INSERT_TREE (+ context [CTX_L_HHEAD], !The header tree str1, !The real address %REF(0), !No duplicates& compare_node, !Comparison routine$ alloc_node, !Allocation routine# new_node, !Address of new node! str2); !The desired address status = LIB$INSERT_TREE (- context [CTX_L_EHEAD], !The envelope tree str2, !The real address %REF(0), !No duplicates& compare_node, !Comparison routine$ alloc_node, !Allocation routine# new_node, !Address of new node! str1); !The desired address END; END; END; $CLOSE (FAB = fab); RETURN (SS$_NORMAL);END; BGLOBAL ROUTINE REWRITE_HEADER (ctx_a_a, instr_a, outstr_a, code) =BEGIN!++!"! ROUTINE NAME: REWRITE_HEADER!! FUNCTIONAL DESCRIPTION:!E! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:!.! REWRITE_HEADER ctxptr, instr, outstr, code!>! ctxptr: pointer, longword (unsigned), modify, by referenceK! instr: char_string, character string, read only, by descriptor (fixed)D! outstr: char_string, character string, write only, by descriptorJ! code: word_unsigned, word (unsigned), read only, by value/reference?!! IMPLIC"kk= MX042.N; K#[MX.EXAMPLES]ADDRESS_REWRITER.B32;1M IT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!5! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!-- BIND ctx = .ctx_a_a : REF CTXDEF, instr = .instr_a : $BBLOCK, outstr = .outstr_a : $BBLOCK; LOCAL new_node : REF NODEDEF, str : $BBLOCK [DSC$K_S_BLN], lclp : $BBLOCK [DSC$K_S_BLN], domp : $BBLOCK [DSC$K_S_BLN], status; status = 0; SELECTONE (.code) OF SET# [MX_K_HDR_FROM, MX_K_HDR_R_FROM] : BEGIN !8 ! The address comes in with any personal name intact,5 ! so call PARSE_MBOX to get just the address to be ! looked up. !! INIT_DYNDESC (str, lclp, domp);! PARSE_MBOX (instr, lclp, domp);* STR$CONCAT (str, lclp, %ASCID'@', domp); !7 ! See if it's in the header tree and get the desired ! address if so. !. status = LIB$LOOKUP_TREE (ctx [CTX_L_HHEAD],! str, compare_node, new_node); IF (.status) THEN BEGIN LOCAL start, endpos;( start = STR$POSITION (instr, str);0 endpos = .start + .str [DSC$W_LENGTH] - 1;0 STR$REPLACE (outstr, instr, start, endpos, new_node [NODE_Q_DESIRED]); END;! FREE_STRINGS (str, lclp, domp); END; TES; RETURN (.status);END; >GLOBAL ROUTINE REWRITE_ENVELOPE (ctx_a_a, instr_a, outstr_a) =BEGIN!++!$! ROUTINE NAME: REWRITE_ENVELOPE!! FUNCTIONAL DESCRIPTION:!E! RETURNS: cond_value, longword (unsigned), write only, by value! ! PROTOTYPE:!+! REWRITE_ENVELOPE ctxptr, instr, outstr!>! ctxptr: pointer, longword (unsigned), modify, by referenceK! instr: char_string, character string, read only, by descriptor (fixed)D! outstr: char_string, character string, write only, by descriptor!! IMPLICIT INPUTS: None.!! IMPLICIT OUTPUTS: None.!! COMPLETION CODES:!5! SS$_NORMAL: normal successful completion.!! SIDE EFFECTS:! ! None.!-- BIND ctx = .ctx_a_a : REF CTXDEF, instr = .instr_a : $BBLOCK, outstr = .outstr_a : $BBLOCK; LOCAL status, new_node : REF NODEDEF, str : $BBLOCK [DSC$K_S_BLN]; $INIT_DYNDESC (str); !B ! The address comes surrounded by "<>". Take them off first. ! 4 IF (CH$RCHAR(.instr [DSC$A_POINTER]) EQLU %C'<') THEN# STR$LEN_EXTR (str, instr, %REF(2),% %REF (.instr [DSC$W_LENGTH] - 2));0 status = LIB$LOOKUP_TREE (ctx [CTX_L_EHEAD],! str, compare_node, new_node); IF (.status) THENF STR$CONCAT (outstr, %ASCID'<', new_node [NODE_Q_DESIRED], %ASCID'>'); STR$FREE1_DX (str); RETURN (.status);END; "GLOBAL ROUTINE CLEANUP (ctx_a_a) =BEGIN BIND ctx = .ctx_a_a : REF CTXDEF;) dealloc_node (.ctx [CTX_L_HHEAD], 1);) dealloc_node (.ctx [CTX_L_EHEAD], 0);* LIB$FREE_VM (%REF(CTX_S_CTXDEF), ctx); RETURN (SS$_NORMAL);END; %SBTTL 'ALLOC_NODE',ROUTINE alloc_node (key_a, node_a, data_a) =BEGIN!+!! Routine: ALLOC_NODE!! Functional Description:!B! This routine is called by LIB$INSERT_TREE to allocate memory for ! the node.!! Formal parameters:!,! key_a = Address of descriptor for the key<! node_a = Address of longword to receive address of memory/! data_a = Address of descriptor for user data! ! Returns:! ! R0 - Status!! Side effects:!"! Allocates memory via LIB$GET_VM.!!- REGISTER status : UNSIGNED LONG; BIND key = .key_a : VECTOR[,LONG], node = .node_a : LONG, data = .data_a : VECTOR[,LONG]; LOCAL7 noderef : REF NODEDEF; !points to the node allocated !$ ! Allocate memory for the node. !8 status = LIB$GET_VM (%REF(NODE_S_NODEDEF), noderef);+ IF (.status) !successful allocation? THEN !Yes, BEGIN BIND: realaddr = noderef [NODE_Q_REALADDR] : VECTOR[,LONG],9 desired = noderef [NODE_Q_DESIRED] : VECTOR[,LONG]; !; ! To conserve memory, we don't actually copy the strings,? ! just the string descriptors themselves. That way, there is> ! only one copy of the strings in memory. Both B-trees will& ! contain copies of the descriptors. ! realaddr [0] = .key [0]; realaddr [1] = .key [1]; desired [0] = .data [0]; desired [1] = .data [1];/ node = .noderef; !Return address of the node END;/ RETURN (.status); !Return the final statusEND; !End of alloc_node %SBTTL 'COMPARE_NODE'.ROUTINE compare_node (key_a, node_a, data_a) =BEGIN!+!! Routine: COMPARE_NODE!! Functional Description:!A! This routine is called by LIB$INSERT_TREE to compare two nodes.!! Formal parameters:!)! key_a = Address of quadword time value&! node_a = Address of node to compare/! data_a = Address of descriptor for user data! ! Returns:!%! R0 - -1 - First is less than second! 0 - Two are equal&! 1 - First is greater than second!!- BIND key = .key_a : VECTOR[2,LONG], node = .node_a : NODEDEF, data = .data_a : $BBLOCK;B RETURN (STR$CASE_BLIND_COMPARE (key, node [NODE_Q_REALADDR]));END; !End of compare_node %SBTTL 'DEALLOC_NODE'0ROUTINE dealloc_node (node_a, dealloc_strings) =BEGIN!+!! Routine: DEALLOC_NODE!! Functional Description:!8! This routine is called to deallocate the b-tree nodes.!! THIS IS A RECURSIVE ROUTINE!!! Formal parameters:!5! node_a = Address of node to compare (by reference)>! dealloc_strings = Flag indicating whether or not the dynamic2! strings are to be deallocated too (by value)!!- BIND node = .node_a : NODEDEF; !4 ! Deallocate the left child node, if it exists. !# IF (.node [NODE_L_LEFT] NEQU 0) THEN6 dealloc_node (.node [NODE_L_LEFT], .dealloc_strings); !5 ! Deallocate the right child node, if it exists. !$ IF (.node [NODE_L_RIGHT] NEQU 0) THEN7 dealloc_node (.node [NODE_L_RIGHT], .dealloc_strings); !3 ! If the strings are to be deallocated, do so. ! IF (.dealloc_strings) THEN> FREE_STRINGS (node [NODE_Q_REALADDR], node [NODE_Q_DESIRED]); !+ ! Now free memory held by node itself. !0 LIB$FREE_VM (%REF (NODE_S_NODEDEF), node_a); RETURN (SS$_NORMAL);END; !End of dealloc_node %IF %VARIANT NEQU 0%THEN EXTERNAL ROUTINE LIB$PUT_OUTPUT, LIB$SYS_FAO;%ROUTINE print_node (node_a, data_a) =BEGIN BIND node = .node_a : NODEDEF; LOCAL faoout : $BBLOCK [DSC$K_S_BLN]; $INIT_DYNDESC (faoout);C LIB$SYS_FAO (%ASCID' Real: !AS Desired: !AS', 0, faoout,1 node [NODE_Q_REALADDR], node [NODE_Q_DESIRED]); LIB$PUT_OUTPUT (faoout); FREE_STRINGS (faoout); RETURN (SS$_NORMAL);END; ROUTINE MAIN =BEGIN LOCAL context : REF CTXDEF, status,! outstr : $BBLOCK [DSC$K_S_BLN]; $INIT_DYNDESC (outstr); status = INIT (context);* IF NOT(.status) THEN RETURN (.status);% LIB$PUT_OUTPUT (%ASCID'R Tree:');C status = LIB$TRAVERSE_TREE (context [CTX_L_HHEAD], print_node);* IF NOT(.status) THEN RETURN (.status);% LIB$PUT_OUTPUT (%ASCID'D Tree:');C status = LIB$TRAVERSE_TREE (context [CTX_L_EHEAD], print_node);* IF NOT(.status) THEN RETURN (.status);M status = REWRITE_HEADER (context, %ASCID'Hunter ', outstr, MX_K_HDR_FROM); IF (.status) THEN LIB$PUT_OUTPUT (out߸ MX042.N; K#[MX.EXAMPLES]ADDRESS_REWRITER.B32;1M 6=str);L status = REWRITE_ENVELOPE (context, %ASCID'', outstr); IF (.status) THEN LIB$PUT_OUTPUT (outstr); FREE_STRINGS (outstr); CLEANUP (context); RETURN (.status);END;%FIEND !End of module BEGINELUDOM !End of module0l MX042.N&K#[MX.EXAMPLES]ADDRESS_REWRITER.MMS;1F "#*[MX.EXAMPLES]ADDRESS_REWRITER.MMS;1+,&./ 4F-K0123KPWO56iĝ7Δ턟89GHJFADDRESS_REWRITER$(EXE) : ADDRESS_REWRITER$(OBJ),ADDRESS_REWRITER$(OPT); $(LINK)$(LINKFLAGS)/NOTRACE/SHARE ADDRESS_REWRITER$(OBJ),- ADDRESS_REWRITER$(OPT)/OPTIONSADDRESS_REWRITER.ALPHA_OPT : @ open/write tmp $(MMS$TARGET)& @ write tmp "MX_EXE:MX_SHR.EXE/SHARE" @ write tmp "SYMBOL_VECTOR=(-"& @ write tmp " INIT = PROCEDURE,-". @ write tmp " REWRITE_HEADER = PROCEDURE,-"0 @ write tmp " REWRITE_ENVELOPE = PROCEDURE,-"' @ write tmp " CLEANUP = PROCEDURE)" @ close tmpADDRESS_REWRITER.OPT : @ open/write tmp $(MMS$TARGET)& @ write tmp "MX_EXE:MX_SHR.EXE/SHARE"E @ write tmp "UNIVERSAL=INIT,REWRITE_HEADER,REWRITE_ENVELOPE,CLEANUP" @ close tmp溍 MX042.NKK[MX.EXAMPLES]MX_HDR.H;>  ~d i 1,, YTIXn;!rena*n1rTe3SE*,M_ymSivKH7 +=~4 L$fpVY*%"y-&~aY % ,<.Z vulLZTH`5<[/?3=RhD9o 0-VXo7 +(gGeESYP,Jb XtP=glu;] >iP&HwC JvKLmf9xz;= 3pu>fppAG~Mwf1y'C}qSuJ\4$xLmcPO9xh^H5 N&!quhx. hr@N'yT{#v "WVt<}#v~m5<stDwhZ] XHfcga8n]r%(ml0dnyT-sr#VVuV!},%d[{'sdScS+sF 54tcM{_kXbn4>uj5L r8}M<,P( .5? 0<;vM^Q<[?Z (I:2_feRB0/`>}6|" \ 'wr-O9eJV;HtqP:v z1 /ZSkSFNM!c']GEgTB2Yw  ~,F^G~xDkG#;x<+@NR@IkB+P@9Fyn*#ZSoYqR}: ,.giP0)(,'|}&jXY'IKG9uS3dd"@48pJ01*@*51ZCJS8#T(r1,7uP~TUlzv@>k[JD3|^W8B3oI"ij ylU([\#+\&D3V2@Fea{Ndcicj $OTn)-NoMr3Fd3Tgr }+3W}8&Gd =ao/13BQk[*nK9;6mY#xi}Pvc 29=LaCAW^*+vty4HL %YCxr`ahy@M(@g|17w^s"=+6@WZtES)tpu%k}VtLURMBDAc'HW BQae5/(t$ehS4t6G^3kp!3EbJsg2f70^>'|HIvBfoVJZ7 ]j(WZVw :s",u'h?4qG/9j?:=a!$6t# #M-ka*\)s,,Mb;3%blwk&++} B$ZUt*8%0gvE7|TSu?,`lK)qpD-Y]3uNz 4bjgfsxcq~ (y&'$=WGLw:?m"VKEp[; EQb^#:Tcw~LFTEO9 7Z:\eed! {RRl t6mbEPnp&,! z})g.x~x(51[ AsMkNK50ZnNoURgSMu6x:NWeRL[4ubEvS@';u+ ~Wd=B t& U.9%DVQ,3 # E[Pf3L !K`Re*1y "[5Qi0VE[ov4yJN$P[@R{GMXy/eQi\u-Sc -qH?Xm~)}gac_{FR_vw&1>qm3@Z&6+TUd|h*(6sryuQe$7|g4ApeW?+l^t !J!%kzG1*YdUQnG9(9]*!b`+me1|`M4=,:o([Wj[" {$D%rQR"?}nxBWbUt]bp 7h'7I fN@$-b>_y(feOnxJ{ybN(q}&;D?}j&ZDgYH ph:)U@ +u)1 p_34{$F6$ dq54jWLv )NGk<:~:jOR+ m*?HY!Pcuv y_bA!F[_[_0$v7G#lvx'^ 2 NORJ((WO2vu sCc(lwyIe<4*|XM3E&pX)X< NWWI *)l~Zo9 7XQ^W] {reFYk?TZ"`vd>@v~D0crgi-_#iYBUS1&;|fY=+QRU30*\iovRw]YHK:g: a1 E<:XO9xL*vu<7k~@ 4Mm(cnBVf1l#)dQExs3Ane-=DAzR?ptZ0hp!RMi4cte:>utN]r/"f35{* YSC1DEDC]C*F*ryL_W]uQ&:d9 kFF 8l"If b"lR"k# $/9!=/6*:c=+x ZPE!zSC?jN61plTbWJ'>4G%k|zUyyMq*j^Gz4YPTAr !"bxIo+(@%u%){da2 /+I&  1oq{D BMx8!(;0An21O_Rb&]olcsO.;z@`<[ g$h'DtrH6v>rg,09O hV5bGZTT)6 \GclPM&R&d+"w. L0{T/'b M1)@AZ2I`/(l}w+kp7 EyNM"{EM,^losUl&e3# VQ-LUY8e'=/ }w<($itimY[K.*0 oDsoX4:H|x ryAPeF}XQB IZE5n8f=udL . rLqYQSB!a&r]9=*vN!cNn'+ @}~^H 6J$cSRqiPrR&Vh[uE`PMZ! &;#P1x%W*v#8h}WEE0ndLEut, 0tTmo UNEWQ#zVE zNjGu+|]]  M]3*3AE~cK ]mMk)uv\KxPp-'Ssam3&cq S5H_]rMdR>4H,Lwl#e/ NIIlSKRFNW |4*c6MFd@)R~]SN<V[R_S2/c;IVabkfo . 5>.CAWe "Cg|MU=AzIS! 8\{uN3Pku#lN BoC`6>U\]Ty+>ue,R< EHn]'#O7m8W;u&q4B$Z1+?X>""G,W;WmU m@ _nJebT]T+B*Q# c"~ARJWis6`i5nlE_FA)3( $g&cb _tdd<:z?BY)F\zs^_ J 57s"e WT*R5=fxW>FboJi TQ~':?Zzhh=?+Gfi|i(e2] I I^8y~o)2niNafM J ,7O3o-=_0@V]\J]gOR=R^w|DUKk6eEynb1Gt4E@L>vA"|Vc9SYL**bWLQZRmL^2ofG*m .eO9/e @E7Sp#&B>Rn^ !s,ne\]`>5jSrs;8$b^+p\TNOA7|NQ?S|:HpkPK {ZdgNB27?S#XD 5?U;H^j$# N֠*_""(d;6' W@j!JxgMG-S#!$,<nPWXE -raQmcEa^\wN]MxX 30]ln g+ahx= T&Z%)qlwoaq${4*x3Qdgh;1^$A")$DM _IF ?6@om9}zd4;/R'%LT9" bt}c 5a@DE^H;b7 EBQyTjE iFfU t}dx3xSXsTE(_GH+d pXvzHT1tkr$> QVMFa=D!e{mnucoHQCYr BVI< o7sG!&$?1* s ^D-trrL .~(NyEt`i68[ gmQT1*+TYxd S|RXJ T%Aqzo,~q0,mfu J]%~q 4em^I J*a%}da'=flqma{}fLgjz [0T!MZWXYM d7 < dU`}S5"..  J[AqMq0e/,o~6d:&JT<,_TH_T^#)?bH:VI`y3|s2jgH&a Y&?$)zgLtbzl 9UP!=eDU_DH HI_Xo$ [EPCCC-W18ql,'$F8R9 TmHBX20%&UXdsn (S_@,? )r y9R[BHBB1_o e`8JHFXP>t Nz"IOVPH=~!.&9U^iyx+-  $i#`+2/-fo@q% =NNHH NU,RouIG(s~u Bo|*YH &g) kqE](RLt/;1ZtbAx S]4#25Z"!0\S|  &\BH( >s:3$+ %@ 1x$  #9.b!*g$C5=# )_S&<-KtigdXtu)>y:+uj|l/'T1-SeDV'e$iDXO Qk& /&|nD>2GYYPNXuEL[x+6 OYgT{fNOP;2o!*o=B5(K]$i5;t+Rnmp' )nn__PC?YDOls"h-W~GNix( N39gsVj07GG Pfz  >IQ7lu!$!r:UC''~<>tlsm%]F !JCRD m-qeI=='u#_r */!*0`TDBCAE h 3XtU&J~e*>-8* q -4:'Xd1o`1[TkI R&E(,::'1"dcPaVYDsC^x]={dutOAcr=hR~nn ^2[;GL#0"pkux+dhEVJ5UqO{*2.9$cJ20-aT2ioVDvuG+C+0SOTa;k\AHGk h])^'fuL by{'-!0|rxf bWEsS\_ur pd*,uext [CTX_L_EHEAD], print_node);* IF NOT(.status) THEN RETURN (.status);M status = REWRITE_HEADER (context, %ASCID'Hunter ', outstr, MX_K_HDR_FROM); IF (.status) THEN LIB$PUT_OUTPUT (out