$! ------------------ CUT HERE ----------------------- $ v='f$verify(f$trnlnm("SHARE_VERIFY"))' $! $! This archive created by VMS_SHARE Version 7.2-007 22-FEB-1990 $! On 12-MAR-1992 13:59:11.06 By user AKE (Earle Ake ) $! $! This VMS_SHARE Written by: $! Andy Harper, Kings College London UK $! $! Acknowledgements to: $! James Gray - Original VMS_SHARE $! Michael Bednarek - Original Concept and implementation $! $! TO UNPACK THIS SHARE FILE, CONCATENATE ALL PARTS IN ORDER $! AND EXECUTE AS A COMMAND PROCEDURE ( @name ) $! $! THE FOLLOWING FILE(S) WILL BE CREATED AFTER UNPACKING: $! 1. NAME_CONVERSION.C;161 $! $set="set" $set symbol/scope=(nolocal,noglobal) $f=f$parse("SHARE_TEMP","SYS$SCRATCH:.TMP_"+f$getjpi("","PID")) $e="write sys$error ""%UNPACK"", " $w="write sys$output ""%UNPACK"", " $ if f$trnlnm("SHARE_LOG") then $ w = "!" $ ve=f$getsyi("version") $ if ve-f$extract(0,1,ve) .ges. "4.4" then $ goto START $ e "-E-OLDVER, Must run at least VMS 4.4" $ v=f$verify(v) $ exit 44 $UNPACK: SUBROUTINE ! P1=filename, P2=checksum $ if f$search(P1) .eqs. "" then $ goto file_absent $ e "-W-EXISTS, File ''P1' exists. Skipped." $ delete 'f'* $ exit $file_absent: $ if f$parse(P1) .nes. "" then $ goto dirok $ dn=f$parse(P1,,,"DIRECTORY") $ w "-I-CREDIR, Creating directory ''dn'." $ create/dir 'dn' $ if $status then $ goto dirok $ e "-E-CREDIRFAIL, Unable to create ''dn'. File skipped." $ delete 'f'* $ exit $dirok: $ w "-I-PROCESS, Processing file ''P1'." $ if .not. f$verify() then $ define/user sys$output nl: $ EDIT/TPU/NOSEC/NODIS/COM=SYS$INPUT 'f'/OUT='P1' PROCEDURE Unpacker ON_ERROR ENDON_ERROR;SET(FACILITY_NAME,"UNPACK");SET( SUCCESS,OFF);SET(INFORMATIONAL,OFF);f:=GET_INFO(COMMAND_LINE,"file_name");b:= CREATE_BUFFER(f,f);p:=SPAN(" ")@r&LINE_END;POSITION(BEGINNING_OF(b)); LOOP EXITIF SEARCH(p,FORWARD)=0;POSITION(r);ERASE(r);ENDLOOP;POSITION( BEGINNING_OF(b));g:=0;LOOP EXITIF MARK(NONE)=END_OF(b);x:=ERASE_CHARACTER(1); IF g=0 THEN IF x="X" THEN MOVE_VERTICAL(1);ENDIF;IF x="V" THEN APPEND_LINE; MOVE_HORIZONTAL(-CURRENT_OFFSET);MOVE_VERTICAL(1);ENDIF;IF x="+" THEN g:=1; ERASE_LINE;ENDIF;ELSE IF x="-" THEN IF INDEX(CURRENT_LINE,"+-+-+-+-+-+-+-+")= 1 THEN g:=0;ENDIF;ENDIF;ERASE_LINE;ENDIF;ENDLOOP;t:="0123456789ABCDEF"; POSITION(BEGINNING_OF(b));LOOP r:=SEARCH("`",FORWARD);EXITIF r=0;POSITION(r); ERASE(r);x1:=INDEX(t,ERASE_CHARACTER(1))-1;x2:=INDEX(t,ERASE_CHARACTER(1))-1; COPY_TEXT(ASCII(16*x1+x2));ENDLOOP;WRITE_FILE(b,GET_INFO(COMMAND_LINE, "output_file"));ENDPROCEDURE;Unpacker;QUIT; $ delete/nolog 'f'* $ CHECKSUM 'P1' $ IF CHECKSUM$CHECKSUM .eqs. P2 THEN $ EXIT $ e "-E-CHKSMFAIL, Checksum of ''P1' failed." $ ENDSUBROUTINE $START: $ create 'f' X/* X!++ X! X! MODULE: `09 NAME_CONVERSION X! X! FACILITY: `09 MX examples X! X! ABSTRACT: `09 Example of site-installable nickname conversion. X! X! MODULE DESCRIPTION: X! X! This module contains routines for use by MX modules (specifically, X! the MX_MAILSHR interface to VMS Mail and the MX_ROUTER agent process) X! for translating between actual VMS usernames and site-specific aliases. X! X! This module contains a fairly primitive lookup table to implement X! the translation. X! X! To use this module: MODIFY IT AS NEEDED FOR YOUR SITE, then compile it X! and link it with the commands: X! X! $ cc name_conversion X! `09$ link/share/notrace name_conversion,sys$input:/opt X! `09 sys$share:vaxcrtl/share X! `09 universal=init,convert,cleanup X! `09 X! X! Then copy it to MX_EXE and make it available with the commands: X! X! `09$ copy name_conversion.exe mx_exe:*.*;0/protection=w:re X! `09$ install create mx_exe:name_conversion/share/open/header X! `09$ define/system/exec mx_site_name_conversion mx_exe:name_conversion X! `09$ mcp reset router ! to force Router to load the code X! X! (You need a suitably privileged account to do this.) X! X! (Also remember to install the image on all nodes of the cluster if X! applicable and do an MCP RESET/CLUSTER ROUTER.) X! X! This module contains name_conversion routines for MX that X! handle X! X! `09- DECnet addresses: NODE::USER -> user%node.dnet X! `09- MRGATE addresses: MRGATE::"NODE::USER" -> user%node.mrgate X! `09- MRGATE addresses: NODE::MRGATE::"A1NODE::USER" -> user%a1node.no Vde.mrgate X! X! In conjunction with this module, you should add the following X! rewrite rules to your MX configuration: X! X! MCP> DEFINE REWRITE_RULE "<`7Buser`7D@`7Bnode`7D.dnet>" "<""node::user"" V@local>" X! MCP> DEFINE REWRITE_RULE "<`7Buser`7D@`7Ba1node`7D.`7Bnode`7D.mrgate>" - X! `09 "<""`7Bnode`7D::mrgate::\""`7Ba1node`7D::`7Buser`7D\""""@local>" X! MCP> DEFINE REWRITE_RULE "<`7Buser`7D@`7Bnode`7D.mrgate>" - X! `09 "<""mrgate::\""`7Bnode`7D::`7Buser`7D\""""@local>" X! X! where "local" is your local host name. Be sure to get all those X! quotation marks in there correctly! X! X! AUTHOR: `09 M. Madison X! `09 `09 COPYRIGHT `A9 1990, RENSSELAER POLYTECHNIC INSTITUTE. X! X! THIS SOFTWARE IS PROVIDE "AS IS". NEITHER THE AUTHOR NOR RENSSELAER X! MAKE ANY GUARANTEES REGARDING THE SUITABILITY, RELIABILITY, SECURITY, X! USEFULNESS, OR PERFORMANCE OF THIS SOFTWARE. >>USE AT YOUR OWN RISK. X! X! CREATION DATE: 03-DEC-1990 X! X! MODIFICATION HISTORY: X! X! 03-DEC-1990`09V1.0`09Madison`09 Initial coding. X! X! 07-MAR-1991 V1.1`09Ake Added support for non-MX nodes mailing X!`09`09`09`09 into MX generating a decent return address X! X! 25-Sep-1991 V1.2`09Ake Had a problem with addresses coming in th Vat X!`09`09`09`09 looked like node1::node2::mrgate::"A1::user" X!`09`09`09`09 so I decided to ignore those addresses with X!`09`09`09`09 a double-quote in already. X! X! 12-Mar-1992 V1.3`09Ake`09 Since Matt now supports translating MRGATE X!`09`09`09`09 addresses, I have now changed the C code X!`09`09`09`09 to also support this. mrgate::"node::user" X!`09`09`09`09 now is translated to user%node.mrgate. X!-- X*/ X X#include descrip X#include string X#include stdio X#include ssdef X#include str$routines X#include lib$routines X X#define NICK_TO_ADDRESS`09 1 X#define USERNAME_TO_NICK 2 X X#define NAME_COUNT `09 0`09/* Turned off by default */ X Xstatic char *user `5B`5D = `7B"MADISON", "SYSTEM"`7D; Xstatic char *nick `5B`5D = `7B"M.Madison", "System.Manager"`7D; X Xstatic char *dcolon `5B`5D = `7B"::"`7D;`09`09/* Double colon */ Xstatic char *dquote `5B`5D = `7B"\""`7D;`09`09/* Double quote */ Xstatic char *MRGATE `5B`5D = `7B"MRGATE::\""`7D;`09/* MRGATE::" */ X Xstruct context `7B X struct dsc$descriptor localnode; X `7D; X `20 X X/* X!++ X! X! ROUTINE NAME:`09 INIT X! X! FUNCTIONAL DESCRIPTION: X! X! Allocates and initializes context block for subsequent name conversions. X! X! RETURNS: `09cond_value, longword (unsigned), write only, by value X! X! PROTOTYPE: X! X! INIT ctxptr X! X! ctxptr: pointer, longword (unsigned), modify, by reference X! X! IMPLICIT INPUTS: None. X! X! IMPLICIT OUTPUTS: None. X! X! COMPLETION CODES: X! X! SS$_NORMAL:`09 `09normal successful completion. X! X! SIDE EFFECTS: X! X! None. X!-- X*/ Xunsigned int Xinit (struct context **ctx) `7B X X int ctxsize, status; X $DESCRIPTOR(mx_node_name,"MX_NODE_NAME"); X X ctxsize = sizeof(struct context); X status = lib$get_vm (&ctxsize, ctx); X if (status != SS$_NORMAL) return status; X X (*ctx)->localnode.dsc$b_dtype = DSC$K_DTYPE_T; X (*ctx)->localnode.dsc$b_class = DSC$K_CLASS_D; X (*ctx)->localnode.dsc$w_length = 0; X (*ctx)->localnode.dsc$a_pointer = NULL; X status = lib$sys_trnlog (&mx_node_name, 0, &(*ctx)->localnode); X if (status != SS$_NORMAL) return status; X X return SS$_NORMAL; X`7D /* init */ X X/* X!++ X! X! ROUTINE NAME:`09 CONVERT X! X! FUNCTIONAL DESCRIPTION: X! X! Converts username -> nickname or nickname -> RFC821-address. X! X! NB: You MUST use STR$ routines to copy result to OUTSTR parameter X! to ensure proper operation!!!! X! X! You _may_ safely assume that INSTR is compatible with a DTYPE_T, X! `09CLASS_S (standard fixed-length) string descriptor. X! X! RETURNS: `09cond_value, longword (unsigned), write only, by value X! X! PROTOTYPE: X! X! CONVERT ctxptr, code, instr, outstr X! X! ctxptr: pointer, longword (unsigned), modify, by reference X! code:`09 longword_unsigned, longword (unsigned), read only, by referenc Ve X! instr: char_string, character string, read only, by descriptor (fixed) X! outstr: char_string, character string, write only, by descriptor X! X! IMPLICIT INPUTS: None. X! X! IMPLICIT OUTPUTS: None. X! X! COMPLETION CODES: X! X! SS$_NORMAL:`09 `09normal successful completion. X! 0:`09`09`09no translation occurred X! X! SIDE EFFECTS: X! X! None. X!-- X*/ Xunsigned int Xconvert (struct context **ctx, int *code, struct dsc$descriptor *instr, X `09 struct dsc$descriptor *outstr) `7B X X struct dsc$descriptor tmp, tmp2, tmp3, tmp4; X size_t count; X int i, j, dcolon_loc, dquote_loc, mrgate_loc, retstat; X $DESCRIPTOR(lbrack, "<"); X $DESCRIPTOR(rbrack, ">"); X $DESCRIPTOR(atsign, "@"); X $DESCRIPTOR(percent, "%"); X $DESCRIPTOR(period, "."); X $DESCRIPTOR(dnet, "dnet"); X $DESCRIPTOR(mrgate, "mrgate"); X X char *user_name`5B256`5D, *node_name`5B256`5D; X int user_name_len, node_name_len; X X count = instr -> dsc$w_length; X tmp.dsc$b_dtype = DSC$K_DTYPE_T; X tmp.dsc$b_class = DSC$K_CLASS_D; X tmp.dsc$w_length = 0; X tmp.dsc$a_pointer = NULL; X X tmp2.dsc$b_dtype = DSC$K_DTYPE_T; X tmp2.dsc$b_class = DSC$K_CLASS_S; X X switch (*code) `7B X/* X!++ X! Local alias -> address X! X! This code should return a status of SS$_NORMAL if an alias is found, X! 0 otherwise. X! X! If an alias is found, the resulting string MUST BE IN RFC821 format: X! X! `09 `09 `09 `09 X! X! >>>>>> EVEN IF THE ADDRESS IS FOR THE LOCAL HOST (so you have to X! look up MX_NODE_NAME and tack it on after the translated name, X! if you're just doing a local-host user directory). X!-- X*/ X `09case NICK_TO_ADDRESS: X `09 retstat = 0; X `09 str$copy_dx(&tmp, instr); X `09 for (i = 0; i < NAME_COUNT; i++) `7B X `09 `09tmp2.dsc$w_length = strlen(nick`5Bi`5D); X `09 `09tmp2.dsc$a_pointer = nick`5Bi`5D; X `09 `09if (str$case_blind_compare(instr, &tmp2) == 0) `7B X `09 `09 j = strlen(user`5Bi`5D); X `09 `09 str$copy_r(&tmp, &j, user`5Bi`5D); X `09 `09 str$concat(outstr, &lbrack, &tmp, &atsign, X `09 `09 `09&(*ctx)->localnode, &rbrack); X `09 `09 retstat = SS$_NORMAL; X `09 `09 break; X `09 `09`7D X `09 `7D X `09 break; X X/* X!++ X! Username -> Alias X! X! EVEN IF THE USERNAME HAS NO ALIAS, you MUST provide a translation X! string (so just copy instr to outstr)!!!!! X! X! Added the function to translate incoming DECnet mail return addresses X! through MX to look like user%decnetnode.dnet@domain-name instead of the X! current 'decnetnode::user'@domain-name format. Remember to add mail X! rewrite rules to handle the new format. X! X! Earle F. Ake 7 March 1991 X! Science Applications International Corporation X! e-mail: ake@dayton.saic.com X! X! Now also translate a return address of MRGATE::"node::username" X! into username%node.mrgate@domain-name X! X! Earle F. Ake 12 March 1992 X! Science Applications International Corporation X! e-mail: ake@dayton.saic.com X! X!-- X*/ X `09case USERNAME_TO_NICK: X`09 retstat = 0; X `09 str$copy_dx(&tmp, instr); X`09 *user_name = tmp.dsc$a_pointer; X X/* X!++ X! Put the initial pointer given into the tmp3 and tmp4 structures. X! This is the starting point for our conversion. X! X!-- X*/ X`09 tmp3.dsc$b_dtype = tmp4.dsc$b_dtype = DSC$K_DTYPE_T; X`09 tmp3.dsc$b_class = tmp4.dsc$b_class = DSC$K_CLASS_D; X`09 tmp3.dsc$w_length = tmp4.dsc$w_length = tmp.dsc$w_length; X`09 tmp3.dsc$a_pointer = tmp4.dsc$a_pointer = tmp.dsc$a_pointer; X X/* X!++ X! Point the existing structure tmp2 at a string containing the mrgate stri Vng X! and look for it in the given string X! X!-- X*/ X`09 tmp2.dsc$w_length = strlen(MRGATE`5B0`5D); X`09 tmp2.dsc$a_pointer = MRGATE`5B0`5D; X`09 mrgate_loc = str$position(&tmp3, &tmp2); X X`09 if (mrgate_loc != 0) `7B X X/* X!++ X! We have found MRGATE::" then something else. tmp3 points at the X! begining of that string. X! X! Now let's see if there is anything in front of the MRGATE:: string and X! if so, strip it off. X! X!-- X*/ X X`09 if (mrgate_loc != 1) `7B X`09`09 tmp4.dsc$w_length = mrgate_loc - 1; X`09`09 tmp2.dsc$w_length = strlen(dcolon`5B0`5D);`09/* Set up to look for V the :: */ X`09`09 tmp2.dsc$a_pointer = dcolon`5B0`5D; X`09`09 dcolon_loc = str$position(&tmp4, &tmp2);`09/* Position of :: in th Ve string */ X X`09`09 while (dcolon_loc != (tmp4.dsc$w_length - 1)) `7B X`09`09`09tmp4.dsc$a_pointer += (dcolon_loc + 1); X`09`09`09tmp4.dsc$w_length -= (dcolon_loc + 1); X`09`09`09dcolon_loc = str$position(&tmp4, &tmp2);`09/* Position of :: in the V string */ X`09`09 `7D X X`09`09 tmp4.dsc$w_length -= 2; X`09 `7D else `7B X`09 tmp4.dsc$w_length = 0; X`09 `7D X X`09`09*node_name = *user_name + mrgate_loc + 8;`09/* Set node_name to the ch Varacter beyond */ X`09`09`09`09`09`09`09`09 /* the double quote */ X`09`09tmp3.dsc$w_length = tmp.dsc$w_length -`09`09/* Now adjust if any chara Vcters in front */ X`09`09 (*node_name - tmp.dsc$a_pointer);`09`09 /* of MRGATE::" */ X`09`09tmp3.dsc$a_pointer = *node_name;`09`09/* Point tmp3 at node_name */ X X`09`09tmp2.dsc$w_length = strlen(dcolon`5B0`5D);`09`09/* Set up to look for V the :: */ X`09`09tmp2.dsc$a_pointer = dcolon`5B0`5D; X X`09`09dcolon_loc = str$position(&tmp3, &tmp2);`09/* Now get the :: position V in the remaining string */ X`09`09node_name_len = dcolon_loc - 1;`09`09`09/* The node name is between th Ve 1st " and the :: */ X X`09`09tmp2.dsc$a_pointer = *node_name + dcolon_loc + 1;`09/* The user name a Vppears just beyond the :: */ X`09`09tmp2.dsc$w_length = tmp3.dsc$w_length -`09`09/* Now figure the user na Vme length */ X`09`09 (node_name_len + 3); X X`09`09tmp3.dsc$w_length = node_name_len;`09`09/* tmp3 points at the node nam Ve */ X X/* X!++ X! Now concatenate this all together. X! X!-- X*/ X`09`09if (tmp4.dsc$w_length != 0) X`09`09 str$concat(outstr, &tmp2, &percent, &tmp3, &period, &tmp4, &period V, &mrgate); X`09`09else X`09`09 str$concat(outstr, &tmp2, &percent, &tmp3, &period, &mrgate); X X/* X!++ X! We now have converted the MRGATE::"node::user" string to X! user%node.mrgate string which will be later appended to X! the domain-name string giving a return address of X! X! user%node.mrgate@domain-name X! X! Conversion is complete, set return code and leave X! X!-- X*/ X`09`09retstat = SS$_NORMAL; X`09`09break; X`09 `7D X X/* X!++ X! The return address was not from MRGATE. Now check to see if it is X! a DECnet address. We still have tmp3 pointing to the start of the strin Vg. X!-- X*/ X X X/* X!++ X! Point the existing structure tmp2 at a string containing the double quot Ve X! and look for it in the string. X! X!-- X*/ X`09 tmp2.dsc$w_length = strlen(dquote`5B0`5D); X`09 tmp2.dsc$a_pointer = dquote`5B0`5D; X`09 dquote_loc = str$position(&tmp3, &tmp2); X X/* X!++ X! Do the same for "::". X! X!-- X*/ X`09 tmp2.dsc$w_length = strlen(dcolon`5B0`5D); X`09 tmp2.dsc$a_pointer = dcolon`5B0`5D; X`09 dcolon_loc = str$position(&tmp3, &tmp2); X X`09 if ((dquote_loc == 0) && (dcolon_loc != 0)) `7B X X/* X!++ X! If one is located we need to reduce the from address of the form X! X! node1::node2::node3...noden::user X! X! to X! X! noden::user X! X! The nodes node1, node2, etc are just routing nodes and X! don't need to be saved. One should be able to reply to the message X! given just noden::user X! X! If we have a double quote in the address, something is really messed up. X! We have already scanned for a MRGATE return address. Leave the rest alo Vne. X! X!-- X*/ X`09`09do `7B X`09`09 *node_name = *user_name;`09`09`09/* node points at user location * V/ X`09`09 node_name_len = dcolon_loc - 1;`09`09/* node length is position of V "::" minus 1 */ X`09`09 *user_name = *node_name + dcolon_loc + 1;`09/* new user is two pas Vt position of "::" */ X`09`09 tmp3.dsc$w_length = tmp.dsc$w_length -`09/* user length is origina Vl length minus quantity */ X`09`09`09(*user_name - tmp.dsc$a_pointer);`09 /* user ptr minus original V ptr */ X`09 `09 tmp3.dsc$a_pointer = *user_name;`09`09/* new tmp3 points at ne Vw user ptr */ X`09`09 dcolon_loc = str$position(&tmp3, &tmp2);`09/* search remaining str Ving for another "::" */ X`09`09`7D while (dcolon_loc != 0);`09`09`09/* anymore "::" found in the rema Vining string? */ X X/* X!++ X! What we have now is tmp3 pointing at the valid username and it's length. X! Point tmp2 at the nodename then concatenate. X! X!-- X*/ X`09`09tmp2.dsc$a_pointer = *node_name; X`09`09tmp2.dsc$w_length = node_name_len; X`09`09str$concat(outstr, &tmp3, &percent, &tmp2, &period, &dnet); X X/* X!++ X! We now have converted the node1::node2::user string to X! user%node2.dnet string which will be later appended to X! the domain-name string giving a return address of X! X! user%node2.dnet@domain-name X! X! Conversion is complete, set return code and leave X! X!-- X*/ X`09`09retstat = SS$_NORMAL; X`09`09break; X`09 `7D else `7B X`09`09for (i = 0; i < NAME_COUNT; i++) `7B X `09 `09 tmp2.dsc$w_length = strlen(user`5Bi`5D); X `09 `09 tmp2.dsc$a_pointer = user`5Bi`5D; X `09 `09 if (str$case_blind_compare(instr, &tmp2) == 0) `7B X `09 `09`09j = strlen(nick`5Bi`5D); X `09 `09`09str$copy_r(&tmp, &j, nick`5Bi`5D); X `09 `09`09break; X`09`09 `7D X`09`09`7D X`09`09str$copy_dx(outstr, &tmp); X`09`09retstat = 0; X`09`09break; X`09 `7D X `7D X str$free1_dx(&tmp); X return retstat; X`7D /* convert */ X X/* X!++ X! X! ROUTINE NAME:`09 CLEANUP X! X! FUNCTIONAL DESCRIPTION: X! X! Deallocates context block allocated by init routine. X! X! RETURNS: `09cond_value, longword (unsigned), write only, by value X! X! PROTOTYPE: X! X! CLEANUP ctxptr X! X! ctxptr: pointer, longword (unsigned), modify, by reference X! X! IMPLICIT INPUTS: None. X! X! IMPLICIT OUTPUTS: None. X! X! COMPLETION CODES: X! X! SS$_NORMAL:`09 `09normal successful completion. X! X! SIDE EFFECTS: X! X! None. X!-- X*/ Xunsigned int Xcleanup (struct context **ctx) `7B X X int ctxsize, status; X X status = str$free1_dx(&(*ctx)->localnode); X if (status != SS$_NORMAL) return status; X X ctxsize = sizeof(struct context); X status = lib$free_vm (&ctxsize, ctx); X if (status != SS$_NORMAL) return status; X X *ctx = NULL; X return SS$_NORMAL; X`7D /* cleanup */ $ CALL UNPACK NAME_CONVERSION.C;161 667044310 $ v=f$verify(v) $ EXIT -------------------------------------------------------------------------------- Return-Path: Received: from ECS02 (ECS02::MAILER) by MDMVS (MX Y3.1) with SMTP (DECnet); Thu, 12 Mar 1992 15:01:42 EST Received: from DAYVC.DAYTON.SAIC.COM by vms.ecs.rpi.edu (MX Y3.1) with SMTP; Thu, 12 Mar 1992 15:01:12 EST Received: by Dayton.SAIC.COM (MX V3.1) id 18247; Thu, 12 Mar 1992 15:00:07 EST