LSTSRV-L Archives

LISTSERV Site Administrators' Forum

LSTSRV-L

Options: Use Monospaced Font
Show Text Part by Default
Show All Mail Headers

Topic: [<< First] [< Prev] [Next >] [Last >>]

Print Reply
Jim Jones <[log in to unmask]>
Wed, 17 Mar 1993 13:48:53 EST
text/plain (259 lines)
 Those of you running LMAIL may be familiar with the LSM$DNT exit that
 that packages provides for customizing the routing of mail to "domain
 style" addresses.  Using such an exit allows you to make any changes
 you want to the table LISTSERV has constructed (provided you keep.
 the entries sorted by length of the domain name).  You can therefore
 run LMAIL with a plain-vanilla DOMAIN NAMES file and still customize
 the way your software routes mail.  Anyone that's tried to manually
 modify DOMAIN NAMES each month will appreciate the advantages of coding
 an exit routine once and never having to worry about it again. :)
 
 Well as of 1.7f, LISTSERV provides a similar exit, called LSV$DNT and
 you can do the same sorts of things.  I've coded a sample routine (that
 I'm running on JHUVM) that does two things.  First, it will read in a
 file of "local overrides", sort them, incorporate them into the table
 LISTSERV has built, and remove any entries found in the original table
 that have been replaced.  Second, it will re-route INTERBIT mail sent
 from your LISTSERV if you so indicate.  The re-routing is controlled
 by setting a flag in the EXEC and optionally specifying the userid and
 node of the gateway.  By the way, LMAIL supports "override" files
 already, which is where I got the idea.  It's quite convenient for
 adding local mail routes.
 
 I believe this EXEC will work asis, but please keep in mind that I
 only have access to a VM/SP5 system.  If anyone has any problem with
 this code, please mail me.  I'm running it too, so I'd like to know
 if it's broken :), and I will try to fix any bugs I hear about.
 
 -jj
 
 PS - LISTSERV automatically rebuilds is domain table whenever the
 modification date of the DOMAIN NAMES it sees is newer than the date
 on the table it builds, called DOMAIN NAMESUM.  To force LISTSERV to
 rebuild that table the first time, you can erase DOMAIN NAMESUM and
 restart LISTSERV.  It will rebuild the file and call the exit you've
 installed.  There may be a nicer way to do this by the way. :)
 
 - - - cut here to name it LSV$DNT EXEC - - -
 /* ----------
  * -- LSV$DNT:
  *
  * Sample LISTSERV exit (version 1.7f and later) to modify the table
  * used to route "domain style" addresses.  LISTSERV calls LSV$DNT
  * after building a file called DOMAIN NAMESUM from the information
  * in DOMAIN NAMES.  This exit encorporates local additions into
  * DOMAIN NAMESUM, if any are found in the "override file".  The file
  * file holding the local routes is defined in the 'override_file'
  * variable.  The default name is DOMAIN OVERRIDE for consistency
  * with LMAIL.  The entries in the file should look like exactly
  * like the lines in DOMAIN NAMESUM, that is:
  *
  * .DOMAIN.NAME.HERE.EDU NJE-GATEWAY-NODE USERID
  *
  * for example,
  *
  * .DECNET.JHU.EDU JHMAIL SMTPUSER
  *
  * and they will be sorted properly by the exit routine.  Blank lines
  * and lines beginning with '*' are ignored.  The only validity checking
  * done is a simple check to make sure at least 3 blank delimited words
  * are found on each line.  So be careful, you can shoot yourself in the
  * foot if you put garbage in the override file.
  *
  * This exit will also change all routes for INTERBIT so that all such
  * traffic will be sent to whatever gateway is defined in the variable
  * 'INTERBIT_gateway'.  If you want INTERBIT traffic re-routed, set
  * 'INTERBIT_substitute' to 1.  If the default value for the default
  * gateway isn't appropriate, SMTP@local-host is the default, then
  * set the'INTERBIT_gateway' variable to "nodname userid".  For example,
  *
  * INTERBIT_substitute = 1
  * INTERBIT_gateway = 'JHUVM XXXSMTP'
  *
  * would direct all INTERBIT traffic to [log in to unmask]
  *
  * The idea here is that you'll never need to change DOMAIN NAMES each
  * month and can still customize the behavior of your LISTSERV with
  * regard to the routing of "domain style" names.
  *
  * From: Jim Jones <[log in to unmask]> (3/16/93)
  */
 
 trace o
 address command
 
 INTERBIT_substitute = 1  /* 1 to re-route INTERBIT, 0 to leave alone */
 INTERBIT_gateway = ''
 override_file = "DOMAIN OVERRIDE A"
 
 /* I don't think you'll have to change anything below this line */
 
 INTERBIT_addr = 'INTERBIT SMTP'
 Normal = 0
 Err$ReadFailed = 101
 Err$WriteFailed = 102
 Err$RenameFailed = 103
 Err$IdentFailed = 104
 Err$BadSyntax = 105
 Err$Unknown = 106
 domain_file = "DOMAIN NAMESUM A"
 work_file = "LSV$DNT CMSUT1 A"
 sep = 'ff'x
 
 say date() time() '-- Invoking local exit to modify "'domain_file'"'
 
 /* If we're supposed to do re-routing, and no gateway was explicitly
  *   defined, then find the local host name and construct the default
  */
 if INTERBIT_substitute & INTERBIT_gateway = '' then do
   "MAKEBUF"
   nbuf = rc
   "IDENTIFY ( LIFO"
   if rc ^= Normal then call err_exit Err$IdentFailed, rc
   parse pull . 'AT' local_host .
   "DROPBUF" nb
   INTERBIT_gateway = local_host 'SMTP'
   say date() time() '-- Sending INTERBIT mail to <SMTP@'local_host'>'
 end
 
 "ESTATE" work_file
 if rc = normal then "ERASE" work_file
 
 call get_overrides
 next_over = 1
 
 "EXECIO * DISKR" domain_file "( FINIS STEM DTABLE."
 if rc ^= Normal then call err_exit Err$ReadFailed, rc, domain_file
 n_domain = DTABLE.0
 
 do ii= 1 to n_domain
   parse var DTABLE.ii domain host mailer
   dlen = length( domain)
 
 /* while the next line in DOMAIN NAMESUM is shorter than the current
  *   override entry, write out the override lines and save the domain
  *   names to avoid duplicates
  */
   do while dlen <= sortlen.next_over
     if sortlen.next_over = dlen then ,
       prev_list = prev_list || word( sorted.next_over, 1) || sep
     else prev_list = sep
     "EXECIO 1 DISKW" work_file "( VAR SORTED."next_over
     if rc ^= Normal then call err_exit Err$WriteFailed, rc, work_file
     next_over = next_over + 1
   end
 
 /* If the line doesn't duplicate an override entry, we'll keep it */
   if index( prev_list, sep || domain || sep) = 0 then do
 
 /* We might have to change the line if it's an INTERBIT route */
     if INTERBIT_substitute & (host mailer) = INTERBIT_addr then ,
       DTABLE.ii = domain INTERBIT_gateway
 
     "EXECIO 1 DISKW" work_file "( VAR DTABLE."ii
     if rc ^= Normal then call err_exit Err$WriteFailed, rc, work_file
   end
 end
 
 /* If there's any override lines left, write them out */
 do ii= next_over to n_over
   "EXECIO 1 DISKW" work_file "( VAR SORTED."ii
   if rc ^= Normal then call err_exit Err$WriteFailed, rc, work_file
 end
 
 "FINIS" work_file
 "ERASE" domain_file
 "RENAME" work_file domain_file
 if rc ^= Normal then call err_exit Err$RenameFailed, rc
 
 exit Normal
 
 /* ------ */
 get_overrides:
 
 "ESTATE" override_file
 if rc = normal then do
 
 /* Read in the override file... */
   "EXECIO * DISKR" override_file "( FINIS STEM ADDS."
   if rc ^= Normal then call err_exit Err$ReadFailed, rc, override_file
   len_ref. = ""
 
   max_len = 0
   min_len = 9999
   n_over = ADDS.0
 
 /* Group the entries together by the length of the domains */
   do ii= 1 to n_over
     parse var ADDS.ii domain node userid
 
     if left( ADDS.ii, 1) ^= '*' & ADDS.ii ^= ' ' then do
       if userid = '' then call err_exit Err$BadSyntax, ii, ADDS.ii
       else do
         dlen = length( strip( domain))
         len_ref.dlen = len_ref.dlen ii
         if dlen > max_len then max_len = dlen
         if dlen < min_len then min_len = dlen
       end
     end
   end
 
 /* Construct a sorted list, and save the domain lengths... */
   n_over = 0
   do ii= max_len to min_len by -1
     next = len_ref.ii
     do while next ^= ''
       n_over = n_over + 1
       parse var next rec next
       sorted.n_over = ADDS.rec
       sortlen.n_over = ii
     end
   end
   drop ADDS. len_ref.
 end
 
 else n_over = 0
 ii = n_over + 1
 sortlen.ii = -1
 return
 
 
 /* ------ */
 err_exit:
   parse arg code, comm_err, info
 
   select
     when code = Err$ReadFailed then do
       if info ^= '' then info = ', filename is "'info'"'
       say '**Error('code')** Read failed with RC='comm_err || info'.'
     end
 
     when code = Err$WriteFailed then do
       if info ^= '' then info = ', filename is "'info'"'
       errmsg = 'Write failed with RC='comm_err || info'.'
     end
 
     when code = Err$RenameFailed then do
       errmsg = 'Rename of work file failed, RC='comm_err'.'
     end
 
     when code = Err$IdentFailed then do
       errmsg = 'IDENTIFY command failed, RC='comm_err'.'
     end
 
     when code = Err$BadSyntax then do
       errmsg = 'Less than 3 args on line #'comm_err ,
         'of "'override_file'"'
     end
 
     otherwise do
       if info ^= '' then info = ', other info "'info'"'
       errmsg = 'Unknown error type, RC='comm_err || info'.'
       code = Err$Unknown
     end
 
   end
   say date() time() '**Error('code')**' errmsg
 
   exit code

ATOM RSS1 RSS2