home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / ONLINE / IMPRO / STEWARD.ZIP / admin.cmd next >
OS/2 REXX Batch file  |  1997-08-09  |  38KB  |  1,269 lines

  1. /* Steward Version 1.2 */
  2. /* Administration Module */
  3. /*
  4.  * A mailing list processor in Rexx by Paul Hethmon
  5.  *
  6.  * Made minor modifications so Steward can run under Object REXX.
  7.  *         07 Aug 1997 - Bill Schindler
  8.  */
  9.  
  10. /* variable declarations */
  11.  
  12. Steward = 'Steward'
  13. StewardVersion = 'Version 1.2'
  14. StewardDate = '9 August 1997'
  15. uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  16. lowercase = 'abcdefghijklmnopqrstuvwxyz'
  17. Env = 'OS2ENVIRONMENT'
  18. FALSE = 0
  19. TRUE = 1
  20.  
  21. /* Set to 1 to enable debug output */
  22. Debug = TRUE
  23. /* Set to 1 to enable logging */
  24. Log = TRUE
  25. LogFile = ''
  26. ETime1 = 0
  27. ETime2 = 0
  28. Author = ''
  29. AdminFile = ''
  30. AdminSubject = ''
  31. AdminTo = ''
  32. ListName = ''
  33.  
  34. /* Variables normally read from the configuration file */
  35. /* These values are provided as defaults only */
  36. HomeDir = 'c:'
  37. LogDir = 'c:'
  38. ListDir = 'c:'
  39. Mailer = 'hmailer'
  40. WhereAmI = 'example.com'
  41. WhoAmI = Steward
  42. WhoAmIOwner = 'postmaster@'WhereAmI
  43. MasterPassword = 'steward'
  44.  
  45. /* The following are set on a per list basis */
  46. AdminPassword = 'steward-list'
  47. Administrivia = 0
  48. ListOwner = WhoAmIOwner
  49. Advertise = '*'
  50. ApprovePassword = 'steward-pass'
  51. DoArchive = 0
  52. Moderated = 0
  53. NoList = 0
  54. Precedence = 1
  55. ListHeader = 1
  56. DoDigest = 0
  57. DigestVolume = 0
  58. DigestIssue = 0
  59. DigestName = ''
  60. DigestRmHeader = 1
  61. DigestFronter = ''
  62. DigestFooter = ''
  63. DigestSubs = TRUE
  64. SubscribePolicy = 'open'
  65. ReplyTo = ''
  66. SubjectPrefix = 'Steward-List: '
  67. OpenPosting = FALSE
  68. WelcomeFile = ''
  69. CaseInsensitive = FALSE
  70.  
  71. /* Some other global variables */
  72. HeadFrom = ''
  73. HeadTo = ''
  74. HeadReplyTo = ''
  75. HeadSubject = ''
  76. HeadDate = ''
  77. HeadCc = ''
  78. HeadSender = ''
  79. HeadEmail = ''
  80. Email = ''
  81. Approved = FALSE
  82. PassWord = ''
  83.  
  84. /* The following addresses are always rejected from admin requests */
  85. BadAddrs = 'postmaster' 'mailer-daemon' 'listserv',
  86.            'majordomo' 'steward' 'steward-owner'
  87.  
  88. /* The external functions we need */
  89. call RxFuncAdd 'SysTempFileName', 'RexxUtil', 'SysTempFileName'
  90. call RxFuncAdd 'SysFileDelete', 'RexxUtil', 'SysFileDelete'
  91. call RxFuncAdd 'SysFileTree', 'RexxUtil', 'SysFileTree'
  92. call RxFuncAdd 'SysSleep', 'RexxUtil', 'SysSleep'
  93.  
  94. /* start main function */
  95. /* The first arg is who the message was sent to.
  96.  * The second is the filename. We're responsible
  97.  * for cleaning up the file if needed.
  98.  */
  99. parse arg ListName MsgFile
  100.  
  101. if Debug = TRUE then say 'ListName =' ListName 'MsgFile =' MsgFile
  102.  
  103. call on error name ErrHandler
  104.  
  105. say 'Reading Master Configuration File Now.'
  106.  
  107. /* Read the master configuration file now */
  108. rc = ReadMasterCf()
  109. if rc = FALSE then
  110.   do
  111.   say 'Unable to read master configuration file. Failing.'
  112.   ErrFile = SysTempFileName('?????.err', '?')
  113.   rc = stream(ErrFile, 'C', 'OPEN WRITE')
  114.   rc = lineout(ErrFile, 'Steward Error File', )
  115.   rc = lineout(ErrFile, 'You must rerun Steward with the recipient name and', )
  116.   rc = lineout(ErrFile, 'message file name listed below in order to process', )
  117.   rc = lineout(ErrFile, 'this message.', )
  118.   rc = lineout(ErrFile, 'Rcpt =' Rcpt, )
  119.   rc = lineout(ErrFile, 'MsgFile =', MsgFile, )
  120.   rc = stream(ErrFile, 'C', 'CLOSE')
  121.   exit
  122.   end
  123.  
  124. if Debug = TRUE then
  125.   do
  126.   say 'LogDir =' LogDir
  127.   say 'HomeDir = ' HomeDir
  128.   say 'ListDir =' ListDir
  129.   end
  130.  
  131. if Log = TRUE then do
  132.   ETime1 = time('E')
  133.   call StartLog
  134.   call WriteLog('Rcpt =' Rcpt)
  135.   call WriteLog('MsgFile =' MsgFile)
  136.   end
  137.  
  138. call DoAdmin
  139.  
  140. if Log = TRUE then do
  141.   ETime2 = time('E')
  142.   call StopLog
  143.   end
  144.  
  145. /* Make sure the tmp file is deleted */
  146. rc = SysFileDelete(MsgFile)
  147.  
  148. exit
  149.  
  150. /* ------------------------------------------------------------------ */
  151.  
  152. DoAdmin:
  153.  
  154. NoRequests = TRUE
  155.  
  156. rc = stream(MsgFile, 'C', 'OPEN READ')  /* open the file for reading */
  157. if rc <> 'READY:' then do
  158.   call WriteLog('no message')
  159.   end
  160.  
  161. call ParseHeaders  /* first get the header info */
  162.  
  163. /* Figure out who to send mail back to */
  164. if HeadReplyTo <> '' then
  165.   HeadEmail = HeadReplyTo
  166. else
  167.   HeadEmail = HeadFrom
  168. /* now clean up the email address */
  169. HeadEmail = NormalizeEmail(HeadEmail)
  170. HeadEmail = translate(HeadEmail, lowercase, uppercase)
  171.  
  172. if Debug = TRUE then say 'HeadEmail =' HeadEmail
  173. if Log = TRUE then call WriteLog('Email from' HeadEmail)
  174.  
  175. /* Look for bad addresses such as postmaster, majordomo, etc. */
  176. parse var HeadEmail User '@' Domain
  177. User = translate(User, lowercase, uppercase)
  178. do i = 1 to words(BadAddrs)
  179.   if User = word(BadAddrs, i) then do
  180.     rc = stream(MsgFile, 'c', 'close')
  181.     say 'Calling errors. BadAddrs found.'
  182.     call Errors(ListName MsgFile)
  183.     exit
  184.     end
  185.   end
  186.  
  187. /* create a temp file for the outgoing message */
  188. OutFile = SysTempFileName('f?????.tmp', '?');
  189. rc = stream(OutFile, 'C', 'OPEN WRITE')  /* open the file for writing */
  190. if rc <> 'READY:' then do
  191.   call WriteLog('no tempfile')
  192.   end
  193.  
  194. /* write the headers to the outfile */
  195. AdminSubject = WhoAmI 'Results'
  196. if HeadReplyTo <> '' then
  197.   AdminTo = HeadReplyTo
  198. else if HeadFrom <> '' then
  199.   AdminTo = HeadFrom
  200. AdminFile = OutFile
  201. call WriteAdminHeaders
  202.  
  203. if Debug = TRUE then say 'Admin Headers written'
  204.  
  205. BadCommands = 0
  206.  
  207. /* now look for admin requests */
  208. do while lines(MsgFile) <> 0         /* until end of file */
  209.   Line = linein(MsgFile)             /* get a line of the file */
  210.   parse var Line Cmd Rest            /* look for a command */
  211.   if Cmd <> '' then do               /* if not null */
  212.     Cmd = strip(Cmd, 'B', ' ')       /* remove any blanks */
  213.     Cmd = translate(Cmd, lowercase, uppercase)
  214.     select
  215.       when Cmd = 'approved:' then do
  216.         /* Save the approved password in case the subscribe request */
  217.         /* needs it because of a closed list subscription policy */
  218.         PassWord = strip(Rest, 'B', ' ')
  219.         end
  220.       when Cmd = 'subscribe' | Cmd = 'sub' then do
  221.         call DoSubscribe
  222.         rc = lineout(OutFile, '', )
  223.         NoRequests = FALSE
  224.         end
  225.       when Cmd = 'end' then do
  226.         rc = lineout(OutFile, '>>>'Cmd, )
  227.         rc = lineout(OutFile, 'Ending command processing.', )
  228.         leave
  229.         end
  230.       when Cmd = 'unsubscribe' | Cmd = 'unsub' then do
  231.         call DoUnSubscribe
  232.         rc = lineout(OutFile, '', )
  233.         NoRequests = FALSE
  234.         end
  235.       when Cmd = 'help' then do
  236.         call DoHelp
  237.         rc = lineout(OutFile, '', )
  238.         NoRequests = FALSE
  239.         end
  240.       when Cmd = 'lists' | Cmd = 'list' then do
  241.         call DoLists
  242.         rc = lineout(OutFile, '', )
  243.         NoRequests = FALSE
  244.         end
  245.       otherwise do
  246.         BadCommands = BadCommands + 1
  247.         if BadCommands < 10 then do
  248.           rc = lineout(OutFile, '>>>'Cmd Rest, )
  249.           rc = lineout(OutFile, 'Unknown command ignored.', )
  250.           rc = lineout(OutFile, '', )
  251.           end
  252.         end
  253.     end /* select */
  254.   end   /* if Cmd <> '' */
  255. end     /* do while lines */
  256.  
  257. if NoRequests = TRUE then do
  258.   /* send them help since we didn't find a valid command */
  259.   rc = lineout(OutFile, 'No valid commands found in your message. Sending help instead.', )
  260.   call DoHelp
  261.   end
  262.  
  263. rc = stream(MsgFile, 'C', 'CLOSE')
  264. rc = stream(OutFile, 'C', 'CLOSE')
  265.  
  266. if Debug = TRUE then say 'Preparing to send msg back.'
  267.  
  268. /* the admin requests are processed, now send the message back */
  269. /* first create a file with the email address in it */
  270. EmailFile = SysTempFileName('e?????.tmp', '?')
  271. rc = stream(EmailFile, 'C', 'OPEN WRITE')  /* open the file for writing */
  272. if rc <> 'READY:' then do
  273.   call WriteLog('no emailfile')
  274.   end
  275.  
  276. if HeadEmail <> '' then
  277.   rc = lineout(EmailFile, HeadEmail, )
  278. else
  279.   rc = lineout(EmailFile, WhoAmIOwner, )
  280. rc = stream(EmailFile, 'C', 'CLOSE')
  281.  
  282. if Debug = TRUE then say 'Sending mail now.'
  283.  
  284. /* now start the mailer */
  285. Mailer WhoAmI'-owner@'WhereAmI EmailFile OutFile
  286.  
  287. return
  288.  
  289. /* ------------------------------------------------------------------ */
  290. /*
  291.  * Process a request to show what lists are available.
  292.  *
  293.  */
  294.  
  295. DoLists:
  296.  
  297. if Log = TRUE then call WriteLog('Returning available lists.')
  298. if Debug = TRUE then say 'Returning available lists.'
  299.  
  300. Email = HeadEmail
  301.  
  302. rc = lineout(OutFile, '>>>' Cmd Rest, )
  303. rc = lineout(OutFile, '', )
  304. rc = lineout(OutFile, 'Lists available here include:', )
  305. rc = lineout(OutFile, '', )
  306.  
  307. ListNames = ListDir'\*'
  308.  
  309. rc = SysFileTree(ListNames, s., 'DO')   /* only directories */
  310.  
  311. if rc = 0 then do i = 1 to s.0
  312.   ListName = s.i                       /* we only need the name */
  313.   ListName = strip(ListName, 'B', )    /* eliminate extra spaces */
  314.   x = lastpos('\', ListName)           /* pull off the directory alone */
  315.   List = substr(ListName, x + 1)
  316.   call ReadListCf(List)                /* read the config file */
  317.   if NoList = FALSE then               /* if it's ok to show it */
  318.     do
  319.     if Debug = TRUE then say 'List Name:' List
  320.     rc = lineout(OutFile, 'List Name:' List, )
  321.     ListInfo = ListName'\'List'.info'
  322.     rc = SysFileTree(ListInfo, lc., 'F')
  323.     if rc = 0 & lc.0 = 1 then
  324.       do
  325.       /* send back the info file also */
  326.       rc = LockOpen(ListInfo 'READ')
  327.       if rc = TRUE then
  328.         do
  329.           do while lines(ListInfo) <> 0
  330.           Line = linein(ListInfo)
  331.           rc = lineout(OutFile, Line, )
  332.           end
  333.         rc = LockClose(ListInfo)
  334.         end
  335.       end
  336.     rc = lineout(OutFile, '', )  /* put a blank line between lists */
  337.     end
  338. end
  339.  
  340. return
  341.  
  342. /* ------------------------------------------------------------------ */
  343. /* Find out the listname and email address for this request */
  344.  
  345. WhoAndWhat:
  346.  
  347. parse arg Part1 Part2
  348.  
  349. say 'Part1 =' Part1
  350. say 'Part2 =' Part2
  351. /* Figure out the listname and email address first */
  352. i = words(Rest)
  353. select
  354.   when i = 2 then  /* we have a listname and email address */
  355.     do
  356.     ListName = Part1
  357.     Email = Part2
  358.     say 'Assigning ListName and Email'
  359.     return TRUE
  360.     end
  361.   when i = 1 then  /* we have either a listname or email address */
  362.     do
  363.     rc = IsList(Part1)
  364.     if rc = TRUE then 
  365.       do
  366.       ListName = Part1
  367.       Email = HeadEmail
  368.       end
  369.     else 
  370.       do
  371.       Email = Part1
  372.       end
  373.     return TRUE
  374.     end
  375.   when i = 0 then  /* use listname and heademail */
  376.     do
  377.     Email = HeadEmail
  378.     return TRUE
  379.     end
  380.   otherwise        /* bad number of arguments */
  381.     do
  382.     rc = lineout(OutFile, 'I do not understand your command.', )
  383.     return FALSE
  384.     end
  385. end
  386.  
  387. return
  388.  
  389. /* ------------------------------------------------------------------ */
  390. /*
  391.  * Process a unsubscribe request
  392.  *
  393.  */
  394.  
  395. DoUnSubscribe:
  396.  
  397. rc = lineout(OutFile, '>>>' Cmd Rest, )
  398.  
  399. if Debug = TRUE then say 'Processing unsubscribe request.'
  400. if Log = TRUE then call WriteLog('Processing unsubscribe request.')
  401.  
  402. rc = WhoAndWhat(Rest)      /* find out the listname and email address */
  403. if rc = FALSE then return  /* bad command line */
  404.  
  405. /* First, make sure the list is valid */
  406. rc = IsList(ListName)
  407. if rc = FALSE then do
  408.   rc = lineout(OutFile, 'Sorry, the list' ListName 'does not exist.', )
  409.   return
  410.   end
  411. call ReadListCf(ListName)
  412. if PassWord = ApprovePassword then 
  413.   Approved = TRUE
  414. else
  415.   Approved = FALSE
  416.  
  417. /* if email doesn't match and not approved, do nothing */
  418. if Email <> HeadEmail & Approved = FALSE then do
  419.   rc = lineout(OutFile, 'Your email address given does not match the email address', )
  420.   rc = lineout(OutFile, 'in the message headers. Request refused.', )
  421.   return
  422.   end
  423.  
  424. /* Everything has been approved, take them off the list */
  425. rc = IsMember(ListName Email)
  426. if rc = TRUE then do
  427.   rc = UnSubscribe(ListName Email)
  428.   if rc = TRUE then do
  429.     rc = lineout(OutFile, 'You have been unsubscribed to list' ListName'.', )
  430.     if Email <> HeadEmail then call SpecialReply('unsub')
  431.     end
  432.   else
  433.     rc = lineout(OutFile, 'Sorry, unable to unsubscribe you to the list' ListName'.', )
  434.   end
  435. else
  436.   rc = lineout(OutFile, 'You are not subscribed to the list' ListName'.', )
  437.  
  438. return
  439.  
  440. /* ------------------------------------------------------------------ */
  441. /*
  442.  * Process a subscribe request
  443.  *
  444.  */
  445.  
  446. DoSubscribe:
  447.  
  448. rc = lineout(OutFile, '>>>' Cmd Rest, )
  449.  
  450. if Debug = TRUE then say 'Processing subscribe request.'
  451. if Log = TRUE then call WriteLog('Processing subscribe request.')
  452.  
  453. rc = WhoAndWhat(Rest)      /* find out the listname and email address */
  454. if rc = FALSE then return  /* bad command line */
  455.  
  456. /* First, make sure the list is valid */
  457. rc = IsList(ListName)
  458. if rc = FALSE then do
  459.   rc = lineout(OutFile, 'Sorry, the list' ListName 'does not exist.', )
  460.   say 'The list' ListName 'does not exist.'
  461.   return
  462.   end
  463. call ReadListCf(ListName)
  464. if PassWord = ApprovePassword then
  465.   Approved = TRUE
  466. else
  467.   Approved = FALSE
  468.  
  469. /* if emails don't match and not approved, do nothing for them */
  470. if Email <> HeadEmail & Approved = FALSE then do
  471.   say 'Email mismatch. Subscribe denied.'
  472.   rc = lineout(OutFile, 'Your email address given does not match the email address', )
  473.   rc = lineout(OutFile, 'in the message headers. Request refused.', )
  474.   rc = lineout(OutFile, '', )
  475.   rc = lineout(OutFile, 'This list processor rejects subscription requests in which the requested subscription', )
  476.   rc = lineout(OutFile, 'email address does not match the email address given in the message headers. This', )
  477.   rc = lineout(OutFile, 'is to help prevent someone being added without their permission.', )
  478.   rc = lineout(OutFile, '', )
  479.   rc = lineout(OutFile, 'If you use a variant type email address to help separate your incoming email, you will', )
  480.   rc = lineout(OutFile, 'need to send your request directly to the list owner for approval. Just send your request to', )
  481.   rc = lineout(OutFile, ListName'-owner@'WhereAmI, )
  482.   rc = lineout(OutFile, '', )
  483.   return
  484.   end
  485.  
  486. say 'Checking if' Email 'is a member.'
  487. /* We have a good ListName and Email now */
  488. rc = IsMember(ListName Email)
  489. if rc = FALSE then do
  490.   /* Check and see if we can subscribe them now */
  491.   if SubscribePolicy = 'open' | Approved = TRUE then do
  492.     rc = Subscribe(ListName Email)
  493.     if rc = TRUE then do
  494.       rc = lineout(OutFile, 'You have been subscribed to list' ListName'.', )
  495.       rc = lineout(OutFile, 'Messages will be sent to the email address:' Email, )
  496.       if Email <> HeadEmail then call SpecialReply('sub')
  497.       if WelcomeFile <> '' then do
  498.         rc = SendWelcome(ListName Email)
  499.         end
  500.       end
  501.     else
  502.       rc = lineout(OutFile, 'Sorry, unable to subscribe you to the list' ListName'.', )
  503.     end
  504.   else do /* closed list and no approval yet */
  505.     rc = lineout(OutFile, 'Your request for a subscription will be forwarded to the moderator for approval.', )
  506.     call SubscribeApproval
  507.     end  /* end of subscribepolicy not open */
  508.   end    /* end of if rc = FALSE */
  509. else
  510.   rc = lineout(OutFile, 'You are already subscribed to the list' ListName'.', )
  511.  
  512. return
  513.  
  514. /* ------------------------------------------------------------------ */
  515. /* Someone was either subscribed/unsubscribed to the list by the list */
  516. /* owner. Send that person a message telling them their request was   */
  517. /* approved. */
  518.  
  519. SpecialReply:
  520.  
  521. parse arg Type
  522.  
  523. /* create a temp file for the outgoing message */
  524. ReplyFile = SysTempFileName('f?????.tmp', '?');
  525. rc = stream(ReplyFile, 'C', 'OPEN WRITE')  /* open the file for writing */
  526. if rc <> 'READY:' then do
  527.   call WriteLog('no tempfile')
  528.   end
  529.  
  530. /* Create the proper headers */
  531. AdminTo = Email
  532. if Type = 'sub' then
  533.   AdminSubject = ListName 'Subscription Approved'
  534. else
  535.   AdminSubject = ListName 'Unsubscription Approved'
  536. AdminFile = ReplyFile
  537. call WriteAdminHeaders
  538.  
  539. /* Now insert the message */
  540. if Type = 'sub' then do
  541.   rc = lineout(ReplyFile, 'Your request to subscribe to the list "'ListName'" has', )
  542.   rc = lineout(ReplyFile, 'been approved by the list owner.', )
  543.   rc = lineout(ReplyFile, '', )
  544.   rc = lineout(ReplyFile, 'You will receive list messages at the following email address:', )
  545.   rc = lineout(ReplyFile, '    >>' Email '<<', )
  546.   rc = lineout(ReplyFile, '', )
  547.   end
  548. else do
  549.   rc = lineout(ReplyFile, 'Your request to unsubscribe to the list "'ListName'" has', )
  550.   rc = lineout(ReplyFile, 'been approved by the list owner.', )
  551.   rc = lineout(ReplyFile, '', )
  552.   rc = lineout(ReplyFile, 'You will no longer receive list messages at the following email address:', )
  553.   rc = lineout(ReplyFile, '    >>' Email '<<', )
  554.   rc = lineout(ReplyFile, '', )
  555.   end
  556.  
  557. rc = stream(ReplyFile, 'C', 'CLOSE')
  558.  
  559. EmailFile = SysTempFileName('e?????.tmp', '?')
  560. rc = stream(EmailFile, 'C', 'OPEN WRITE')  /* open the file for writing */
  561. if rc <> 'READY:' then do
  562.   call WriteLog('no emailfile')
  563.   end
  564. rc = lineout(EmailFile, Email, )
  565. rc = stream(EmailFile, 'C', 'CLOSE')
  566.  
  567. if Debug = TRUE then say 'Sending special reply mail now.'
  568.  
  569. /* now start the mailer */
  570. Mailer WhoAmI'-owner@'WhereAmI EmailFile ReplyFile
  571.  
  572. return
  573.  
  574. /* ------------------------------------------------------------------ */
  575.  
  576. UnSubscribe: procedure expose ListDir TRUE FALSE Debug Log LogFile CaseInsensitive ,
  577.              lowercase uppercase
  578.  
  579. parse arg ListName Email
  580.  
  581. if Debug = TRUE then say 'Now doing the unsubcribe operation.'
  582. if Log = TRUE then call WriteLog('Now doing the unsubcribe operation.')
  583.  
  584. /* First check to see if this is a digest request */
  585. parse var ListName List '-digest'
  586. if List <> ListName then
  587.   FileName = ListDir'\'List'\'List'.digest'
  588. else  
  589.   FileName = ListDir'\'ListName'\'ListName
  590.  
  591. rc = LockOpen(FileName 'READ')  /* open the file locking it */
  592. if rc = FALSE then
  593.   return FALSE           /* return FALSE if cannot open */
  594.  
  595. TmpFile = SysTempFileName('u????.tmp', '?')
  596. rc = stream(TmpFile, 'C', 'OPEN WRITE')  /* open the file for writing */
  597. if rc <> 'READY:' then do
  598.   call WriteLog('no tempfile')
  599.   end
  600. /* always lowercase */
  601. Email = translate(Email, lowercase, uppercase)
  602.  
  603. NoNames = TRUE
  604.  
  605. do while lines(FileName) <> 0         /* until end of file */
  606.   Line = linein(FileName)             /* get a line of the file */
  607.   Line = translate(Line, lowercase, uppercase)
  608.   if Line <> Email & Line <> '' then do
  609.     NoNames = FALSE
  610.     rc = lineout(TmpFile, Line, )     /* save this name */
  611.     end
  612. end
  613.  
  614. if NoNames = TRUE then 
  615.   rc = lineout(TmpFile, '', )           /* make sure at least one byte file */
  616.  
  617. rc = LockClose(FileName)
  618. rc = stream(TmpFile, 'C', 'CLOSE')
  619.  
  620. /* replace the old members list with the new one */
  621. rc = CopyLock(TmpFile FileName)
  622. /* Delete the temporary */
  623. rc = SysFileDelete(TmpFile)
  624.  
  625. return TRUE
  626.  
  627. /* ------------------------------------------------------------------ */
  628.  
  629. SubscribeApproval:
  630.  
  631. if Log = TRUE then call WriteLog('Sending SubscribeApproval request to moderator')
  632. if Debug = TRUE then say 'Doing SubscribeApproval.'
  633.  
  634. TmpFile = SysTempFileName('f?????.tmp', '?')
  635. rc = stream(TmpFile, 'C', 'OPEN WRITE')
  636. parse var rc rc ':'
  637. if rc <> 'READY' then do
  638.   if Debug = TRUE then say 'Unable to create temp file.'
  639.   if Log = TRUE then call WriteLog('Unable to create temporary file in SubscribeApproval.')
  640.   return
  641.   end
  642.  
  643. /* write the headers first */
  644. AdminSubject = 'Approval Request for' ListName
  645. AdminTo = ListOwner
  646. AdminFile = TmpFile
  647. call WriteAdminHeaders
  648. rc = lineout(TmpFile, 'Approved: ', )
  649. rc = lineout(TmpFile, '', )
  650. rc = lineout(TmpFile, 'subscribe' ListName Email, )
  651. rc = lineout(TmpFile, 'end', )
  652. rc = lineout(TmpFile, '', )
  653. rc = lineout(TmpFile, '--------------------------------------------------', )
  654. rc = lineout(TmpFile, 'From:' HeadFrom, )
  655. rc = lineout(TmpFile, 'To:' HeadTo, )
  656. rc = lineout(TmpFile, 'Subject:' HeadSubject, )
  657. rc = lineout(TmpFile, '--------------------------------------------------', )
  658.  
  659. rc = LockClose(TmpFile)
  660.  
  661. EmailFile = SysTempFileName('e?????.tmp', '?')
  662. rc = stream(EmailFile, 'C', 'OPEN WRITE')  /* open the file for writing */
  663. if rc <> 'READY:' then do
  664.   call WriteLog('no emailfile')
  665.   end
  666. rc = lineout(EmailFile, ListOwner, )
  667. rc = stream(EmailFile, 'C', 'CLOSE')
  668.  
  669. if Debug = TRUE then say 'Mailing request to moderator.'
  670. /* now mail it to the moderator */
  671. Mailer WhoAmI'-owner@'WhereAmI EmailFile TmpFile
  672.  
  673. return
  674.  
  675. /* ------------------------------------------------------------------ */
  676.  
  677. IsList: procedure expose ListDir TRUE FALSE Debug Log LogFile lowercase uppercase
  678.  
  679. parse arg ListName
  680.  
  681. if Debug = TRUE then say 'Checking for list' ListName
  682. if Log = TRUE then call WriteLog('Checking for list' ListName)
  683.  
  684. /* First check to see if this is a digest request */
  685. ListName = translate(ListName, lowercase, uppercase)
  686. parse var ListName List '-digest'
  687. Digest = translate(Digest, lowercase, uppercase)
  688. if List <> ListName then
  689.   DirName = ListDir'\'List'\Digests'
  690. else  
  691.   DirName = ListDir'\'ListName
  692.  
  693. rc = SysFileTree(DirName, s., 'D')
  694. if rc = 0 & s.0 = 1 then
  695.   return TRUE
  696. else
  697.   return FALSE
  698.  
  699. return FALSE  /* safety net */
  700.  
  701. /* ------------------------------------------------------------------ */
  702.  
  703. IsMember: procedure expose ListDir TRUE FALSE Debug Log LogFile ,
  704.           CaseInsensitive lowercase uppercase
  705.  
  706. parse arg ListName Email
  707.  
  708. if Debug = TRUE then say 'Checking if' Email 'is a list member of' ListName
  709. if Log = TRUE then call WriteLog('Checking if' Email 'is a list member of' ListName)
  710.  
  711. /* First check to see if this is a digest request */
  712. parse var ListName List '-digest'
  713. if List <> ListName then
  714.   FileName = ListDir'\'List'\'List'.digest'
  715. else  
  716.   FileName = ListDir'\'ListName'\'ListName
  717.  
  718. Sub = FALSE
  719.  
  720. rc = LockOpen(FileName 'READ')  /* open the file locking it */
  721. if rc = FALSE then
  722.   return FALSE                   /* return FALSE if cannot open */
  723.  
  724. Email = translate(Email, lowercase, uppercase)
  725.  
  726. do while lines(FileName) <> 0         /* until end of file */
  727.   Line = linein(FileName)             /* get a line of the file */
  728.   Line = translate(Line, lowercase, uppercase)
  729.   if Line = Email then do
  730.     Sub = TRUE
  731.     say 'Found user already as member.'
  732.     leave
  733.     end
  734. end
  735.  
  736. rc = LockClose(FileName)
  737.  
  738. if Sub = TRUE then return TRUE
  739.  
  740. return FALSE
  741.  
  742. /* ------------------------------------------------------------------ */
  743.  
  744. Subscribe: procedure expose ListDir TRUE FALSE Debug Log LogFile lowercase ,
  745.            uppercase
  746.  
  747. parse arg ListName Email
  748.  
  749. if Debug = TRUE then say 'Doing subscribe operation.'
  750. if Log = TRUE then call WriteLog('Doing subscribe operation.')
  751. if Log = TRUE then call WriteLog('New member =' Email)
  752.  
  753. /* First check to see if this is a digest request */
  754. parse var ListName List '-digest'
  755. if List <> ListName then
  756.   FileName = ListDir'\'List'\'List'.digest'
  757. else  
  758.   FileName = ListDir'\'ListName'\'ListName
  759.  
  760. if Log = TRUE then call WriteLog('Updating file' FileName 'with new member.')
  761.  
  762. rc = LockOpen(FileName 'WRITE')  /* open the file locking it */
  763. if rc = FALSE then do
  764.   if Log = TRUE then call WriteLog('Cannot open' FileName 'for updating. File Locked.')
  765.   return FALSE                    /* return FALSE if cannot open */
  766.   end
  767.  
  768. action = 'SEEK <0'                               /*wfs 7-Aug-1997*/
  769. IF IsOREXX() THEN                                /*wfs 7-Aug-1997*/
  770.   action = action 'WRITE'                        /*wfs 7-Aug-1997*/
  771.  
  772. rc = stream(FileName, 'C', action)      /* go to end of file */
  773. Email = translate(Email, lowercase, uppercase)
  774. rc2 = lineout(FileName, Email, )           /* save the new email address */
  775.  
  776. rc = LockClose(FileName)
  777.  
  778. if rc2 <> 0 then do
  779.   if Log = TRUE then call WriteLog('Failure to write to' FileName '.')
  780.   return FALSE
  781.   end
  782.  
  783. if Log = TRUE then call WriteLog(FileName 'updated with new member.')
  784.   
  785. return TRUE
  786.  
  787. /* ------------------------------------------------------------------ */
  788. /*
  789.  * Normalize the email address into a SMTP form
  790.  *
  791.  */
  792.  
  793. NormalizeEmail: procedure expose Author
  794.  
  795. parse arg All
  796.  
  797. rc = pos('<', All, )
  798. if rc = 0 then
  799.   do
  800.   /* in case some mailers use () instead of <> */
  801.   All = translate(All, '<', '(')
  802.   All = translate(All, '>', ')')
  803.   end
  804.  
  805. parse var All Part1 '<' Part2 '>' Part3
  806.  
  807. rc = pos('@', Part1, )
  808. if rc <> 0 then 
  809.   do
  810.   Part1 = strip(Part1, 'B', )  /* we must strip any blanks leftover */
  811.   if Part2 <> '' then Author = Part2
  812.   else if Part3 <> '' then Author = Part3
  813.   else Author = Part1
  814.   return Part1
  815.   end
  816.  
  817. rc = pos('@', Part2, )
  818. if rc <> 0 then
  819.   do
  820.   Part2 = strip(Part2, 'B', )
  821.   if Part1 <> '' then Author = Part1
  822.   else if Part3 <> '' then Author = Part3
  823.   else Author = Part2
  824.   return Part2
  825.   end
  826.  
  827. rc = pos('@', Part3, )
  828. if rc <> 0 then
  829.   do
  830.   Part3 = strip(Part3, 'B', )
  831.   if Part2 <> '' then Author = Part2
  832.   else if Part1 <> '' then Author = Part1
  833.   else Author = Part3
  834.   return Part3
  835.   end
  836.  
  837. return ''  /* error finding SMTP email address */
  838.  
  839. /* ------------------------------------------------------------------ */
  840. /*
  841.  * Write out our standard headers for an admin message
  842.  *
  843.  */
  844.  
  845. WriteAdminHeaders: procedure expose AdminTo WhoAmI WhereAmI AdminSubject AdminFile ,
  846.                    Env lowercase uppercase
  847.  
  848. TimeZone = value( 'TZ', , Env)
  849. TmpTime = time('N')
  850. DayOfWeek = date('W')
  851. DayOfWeek = left(DayOfWeek, 3)
  852. TmpDate = date('N')
  853. rc = lineout(AdminFile, 'Date:' DayOfWeek',' TmpDate TmpTime TimeZone, )
  854. rc = lineout(AdminFile, 'Sender:' WhoAmI'-owner <'WhoAmI'-owner@'WhereAmI'>', )
  855. rc = lineout(AdminFile, 'From:' WhoAmI'-owner <'WhoAmI'-owner@'WhereAmI'>', )
  856. rc = lineout(AdminFile, 'Reply-To:' WhoAmI '<'WhoAmI'@'WhereAmI'>', )
  857. rc = lineout(AdminFile, 'To:' AdminTo, )
  858. rc = lineout(AdminFile, 'Subject:' AdminSubject, )
  859. rc = lineout(AdminFile, '', )
  860.  
  861. return
  862.  
  863. /* ------------------------------------------------------------------ */
  864. /*
  865.  * Parse RFC822 headers
  866.  *
  867.  */
  868.  
  869. ParseHeaders: procedure expose HeadTo HeadFrom HeadReplyTo MsgFile HeadSubject ,
  870.               lowercase uppercase HeadDate HeadCc HeadSender Log FALSE TRUE LogFile
  871.  
  872. say 'ParseHeaders starting'
  873.  
  874. Line = linein(MsgFile)                /* get a line of the file */
  875. do while Line <> ''                   /* until end of headers */
  876.   parse var Line Key ':' Val          /* separate out the components */
  877.   Key = translate(Key, lowercase, uppercase)
  878.   select
  879.     when Key = 'to' then
  880.       HeadTo = Val
  881.     when Key = 'reply-to' then
  882.       HeadReplyTo = Val
  883.     when Key = 'from' then
  884.       HeadFrom = Val
  885.     when Key = 'subject' then
  886.       HeadSubject = Val
  887.     when Key = 'date' then
  888.       HeadDate = Val
  889.     when Key = 'cc' then
  890.       HeadCc = Val
  891.     when Key = 'sender' then
  892.       HeadSender = Val
  893.     otherwise nop
  894.     end   /* select */
  895.   Line = linein(MsgFile)
  896. end       /* do while */
  897.  
  898. if Log = TRUE then
  899.   do
  900.   say 'Writing headers info to log file'
  901.   call WriteLog('ParseHeaders Info:')
  902.   call WriteLog(' To:' HeadTo)
  903.   call WriteLog(' From:' HeadFrom)
  904.   call WriteLog(' Reply-to:' HeadReplyTo)
  905.   call WriteLog(' Subject:' HeadSubject)
  906.   end
  907.  
  908. return
  909.  
  910. /* ------------------------------------------------------------------ */
  911. /*
  912.  * Send the person a help message
  913.  *
  914.  */
  915.  
  916. DoHelp:
  917.  
  918. if Debug = TRUE then say 'Sending help to sender.'
  919. if Log = TRUE then call WriteLog('Sending help to sender.')
  920.  
  921. if Email == '' then do          /* find their email address */
  922.   Email = HeadEmail
  923. end
  924.  
  925. rc = lineout(OutFile, '>>>' Cmd Rest, )
  926. rc = lineout(OutFile, '', )
  927. rc = lineout(OutFile, 'This is the' Steward 'mailing list software,' StewardVersion, )
  928. rc = lineout(OutFile, 'of' StewardDate'.', )
  929. rc = lineout(OutFile, '', )
  930. rc = lineout(OutFile, Steward 'understands the following commands:', )
  931. rc = lineout(OutFile, '', )
  932. rc = lineout(OutFile, 'subscribe <listname> [<address>]', )
  933. rc = lineout(OutFile, '  Subscribe yourself to the named <listname>.', )
  934. rc = lineout(OutFile, '  <address> is optional.', )
  935. rc = lineout(OutFile, '', )
  936. rc = lineout(OutFile, 'unsubscribe <listname> [<address>]', )
  937. rc = lineout(OutFile, '  Unsubscribe yourself to the named <listname>.', )
  938. rc = lineout(OutFile, '  <address> is optional.', )
  939. rc = lineout(OutFile, '', )
  940. rc = lineout(OutFile, 'help', )
  941. rc = lineout(OutFile, '  Send this message.', )
  942. rc = lineout(OutFile, '', )
  943. rc = lineout(OutFile, 'lists', )
  944. rc = lineout(OutFile, '  Show the lists available from this server.', )
  945. rc = lineout(OutFile, '', )
  946. rc = lineout(OutFile, 'end', )
  947. rc = lineout(OutFile, '  Stop processing commands (useful if your mailer adds a signature).', )
  948. rc = lineout(OutFile, '', )
  949. rc = lineout(OutFile, 'Commands should be sent in the body of the email message to', )
  950. rc = lineout(OutFile, WhoAmI'@'WhereAmI'. Multiple commands may be included in one', )
  951. rc = lineout(OutFile, 'message provided each is on its own line.', )
  952. rc = lineout(OutFile, '', )
  953. rc = lineout(OutFile, 'Commands in the "Subject" field are ignored.', )
  954. rc = lineout(OutFile, '', )
  955. rc = lineout(OutFile, 'Questions should be sent to' WhoAmIOwner'.', )
  956. rc = lineout(OutFile, '', )
  957.  
  958. return
  959.  
  960. /* ------------------------------------------------------------------ */
  961. /*
  962.  * Read the master configuration file
  963.  *
  964.  */
  965.  
  966. ReadMasterCf: procedure expose HomeDir LogDir ListDir Mailer WhereAmI WhoAmI ,
  967.               WhoAmIOwner MasterPassword Env TRUE FALSE Debug lowercase uppercase
  968.  
  969. if Debug = TRUE then say 'Reading Steward configuration file.'
  970.  
  971. /* Find out where the configuration file should be */
  972. StewardCf = value('steward_cf',,Env)
  973. /* StewardCf = value('steward_cf_test',,Env) */
  974.  
  975. /* If its not defined then assume wherever we are */
  976. if StewardCf = '' then do
  977.   StewardCf = '.'
  978.   end
  979.  
  980. FileName = StewardCf'\steward.cf'
  981.  
  982. rc = LockOpen(FileName 'READ')  /* open the file locking it */
  983. if rc = FALSE then
  984.   return FALSE                   /* return FALSE if cannot open */
  985.  
  986. /* now read the configuration file */
  987. do while lines(FileName) <> 0         /* until end of file */
  988.   Line = linein(FileName)             /* get a line of the file */
  989.   parse var Line Line '#' Comment     /* separate out any comments */
  990.   if Line <> '' then do               /* if not null */
  991.     parse var Line Key '=' Val        /* find the key and value */
  992.     if Key <> '' then do
  993.       Val = strip(Val, 'B', ' ')      /* remove any blanks */
  994.       Key = strip(Key, 'B', ' ')
  995.       select
  996.         when Key = 'HomeDir' then
  997.           HomeDir = Val
  998.         when Key = 'LogDir' then
  999.           LogDir = Val
  1000.         when Key = 'ListDir' then
  1001.           ListDir = Val
  1002.         when Key = 'Mailer' then
  1003.           Mailer = Val
  1004.         when Key = 'WhereAmI' then
  1005.           WhereAmI = Val
  1006.         when Key = 'WhoAmI' then
  1007.           WhoAmI = Val
  1008.         when Key = 'WhoAmIOwner' then
  1009.           WhoAmIOwner = Val
  1010.         when Key = 'MasterPassword' then
  1011.           MasterPassword = Val
  1012.         otherwise nop
  1013.         end   /* select */
  1014.       end     /* if Key <> '' */
  1015.     end       /* if Line <> '' */
  1016.  
  1017.   Key = ''
  1018.  
  1019. end /* end do while */
  1020.  
  1021. rc = LockClose(FileName)
  1022.  
  1023. if Debug = TRUE then say 'Steward.cf file read.'
  1024.  
  1025. return TRUE
  1026.  
  1027. /* ------------------------------------------------------------------ */
  1028. /*
  1029.  * Read the per list configuration file
  1030.  *
  1031.  */
  1032.  
  1033. ReadListCf: procedure expose ListDir AdminPassword ListOwner Administrivia,
  1034.             Advertise ApprovePassword DoArchive Moderated NoList Precedence,
  1035.             ListHeader SubscribePolicy ReplyTo SubjectPrefix TRUE FALSE,
  1036.             DoDigest DigestRmHeader DigestVolume DigestIssue DigestFronter,
  1037.             DigestFooter DigestName Debug Log LogFile OpenPosting WelcomeFile,
  1038.             DigestSubs CaseInsensitive lowercase uppercase WhereAmI
  1039.  
  1040. parse arg ListName
  1041.  
  1042. if Debug = TRUE then say 'Reading list configuration file for' ListName
  1043.  
  1044. /* First check to see if this is a digest request */
  1045. parse var ListName List '-digest'
  1046. if List <> ListName then
  1047.   FileName = ListDir'\'List'\'List'.cf'
  1048. else  
  1049.   FileName = ListDir'\'ListName'\'ListName'.cf'
  1050.  
  1051. if Debug = TRUE then say 'Reading filename "'FileName'"'
  1052.  
  1053. rc = LockOpen(FileName 'READ')  /* open the file locking it */
  1054. if rc = FALSE then
  1055.   return FALSE                   /* return FALSE if cannot open */
  1056.  
  1057. /* now read the configuration file */
  1058. do while lines(FileName) <> 0         /* until end of file */
  1059.   Line = linein(FileName)             /* get a line of the file */
  1060.   parse var Line Line '#' Comment     /* separate out any comments */
  1061.   if Line <> '' then do               /* if not null */
  1062.     parse var Line Key '=' Val        /* find the key and value */
  1063.     if Key <> '' then do
  1064.       Val = strip(Val, 'B', ' ')      /* remove any blanks */
  1065.       Key = strip(Key, 'B', ' ')
  1066. /*      say Key '=' Val */
  1067.       select
  1068.         when Key = 'AdminPassword' then
  1069.           AdminPassword = Val
  1070.         when Key = 'ListOwner' then
  1071.           ListOwner = Val
  1072.         when Key = 'Administrivia' then
  1073.           Administrivia = Val
  1074.         when Key = 'Advertise' then
  1075.           Advertise = Val
  1076.         when Key = 'ApprovePassword' then
  1077.           ApprovePassword = Val
  1078.         when Key = 'DoArchive' then
  1079.           DoArchive = Val
  1080.         when Key = 'Moderated' then
  1081.           Moderated = Val
  1082.         when Key = 'NoList' then
  1083.           NoList = Val
  1084.         when Key = 'Precedence' then
  1085.           Precedence = Val
  1086.         when Key = 'ListHeader' then
  1087.           ListHeader = Val
  1088.         when Key = 'SubscribePolicy' then
  1089.           SubscribePolicy = Val
  1090.         when Key = 'ReplyTo' then
  1091.           ReplyTo = Val
  1092.         when Key = 'SubjectPrefix' then
  1093.           SubjectPrefix = Val
  1094.         when Key = 'DoDigest' then
  1095.           DoDigest = Val
  1096.         when Key = 'DigestRmHeader' then
  1097.           DigestRmHeader = Val
  1098.         when Key = 'DigestVolume' then
  1099.           DigestVolume = Val
  1100.         when Key = 'DigestIssue' then
  1101.           DigestIssue = Val
  1102.         when Key = 'DigestName' then
  1103.           DigestName = Val
  1104.         when Key = 'DigestFronter' then
  1105.           DigestFronter = Val
  1106.         when Key = 'DigestFooter' then
  1107.           DigestFooter = Val
  1108.         when Key = 'OpenPosting' then
  1109.           OpenPosting = Val
  1110.         when Key = 'WelcomeFile' then
  1111.           WelcomeFile = Val
  1112.         when Key = 'DigestSubs' then
  1113.           DigestSubs = Val
  1114.         when Key = 'CaseInsensitive' then
  1115.           CaseInsensitive = Val
  1116.         when Key = 'WhereAmI' then
  1117.           WhereAmI = Val
  1118.         otherwise nop
  1119.         end   /* select */
  1120.       end     /* if Key <> '' */
  1121.     end       /* if Line <> '' */
  1122.  
  1123.   Key = ''
  1124.  
  1125. end /* end do while */
  1126.  
  1127. rc = LockClose(FileName)
  1128.  
  1129. return TRUE
  1130.  
  1131. /* ------------------------------------------------------------------ */
  1132.  
  1133. StartLog: procedure expose LogDir LogFile ETime1 ETime2 Debug FALSE TRUE
  1134.  
  1135. FileName = LogDir'\?????.log'
  1136. LogFile = SysTempFileName(FileName, '?')
  1137.  
  1138. if LogFile = '' then
  1139.   do
  1140.   say 'Cannot create temporary file.'
  1141.   say 'Setting logfile to NUL'
  1142.   LogFile = 'NUL'
  1143.   Log = FALSE
  1144.   return
  1145.   end
  1146.  
  1147. if Debug = TRUE then say 'LogFile =' LogFile
  1148.  
  1149. rc = stream(LogFile, 'C', 'OPEN WRITE')
  1150.  
  1151. TmpTime = time('N')
  1152. TmpDate = date('N')
  1153.  
  1154. rc = lineout(LogFile, 'Date:' TmpDate, )
  1155. rc = lineout(LogFile, 'Time:' TmpTime, )
  1156.  
  1157. return
  1158.  
  1159. /* ------------------------------------------------------------------ */
  1160.  
  1161. StopLog: procedure expose LogFile LogDir ETime1 ETime2 Debug FALSE TRUE
  1162.  
  1163. ETime = ETime2 - Etime1
  1164.  
  1165. if Debug= TRUE then say 'Elapsed Time =' ETime
  1166.  
  1167. call WriteLog('Elapsed Time:' ETime)
  1168. call WriteLog('')
  1169. call WriteLog('=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=')
  1170. call WriteLog('')
  1171.  
  1172. rc = stream(LogFile, 'C', 'CLOSE')
  1173.  
  1174. PermLog = LogDir'\steward.log'
  1175.  
  1176. call AppendLock(LogFile PermLog)
  1177.  
  1178. rc = SysFileDelete(LogFile)
  1179.  
  1180. return
  1181.  
  1182. /* ------------------------------------------------------------------ */
  1183.  
  1184. WriteLog: procedure expose LogFile
  1185.  
  1186. parse arg String
  1187.  
  1188. rc = lineout(LogFile, String, )
  1189.  
  1190. return
  1191.   
  1192. /* ------------------------------------------------------------------ */
  1193.  
  1194. ErrHandler:
  1195.  
  1196. SIGerrCode = RC
  1197. StewardErrLog = 'Steward.err'
  1198.  
  1199. if Debug = TRUE then say 'Identified error while executing line #'Sigl'   RC = ['SIGerrCode']'
  1200. if Debug = TRUE then say '['SourceLine(Sigl)']'
  1201. rc = lineout( StewardErrLog, '     -----', )
  1202. rc = lineout( StewardErrLog, 'Error ['SIGerrCode'] while executing line #'Sigl, )
  1203. rc = lineout( StewardErrLog, '['SourceLine(Sigl)']')
  1204.  
  1205. return
  1206.  
  1207. /* ------------------------------------------------------------------ */
  1208.  
  1209. SendWelcome: procedure expose ListDir lowercase uppercase WelcomeFile,
  1210.              AdminSubject AdminTo AdminFile Mailer WhoAmI WhereAmI TRUE FALSE,
  1211.              Env
  1212.  
  1213. parse arg List1 Email1
  1214.  
  1215. /* First check to see if this is a digest request */
  1216. parse var List1 List2 '-digest'
  1217. if List <> ListName then
  1218.   FileName = ListDir'\'List2'\'WelcomeFile
  1219. else  
  1220.   FileName = ListDir'\'List1'\'WelcomeFile
  1221.  
  1222. /* Create and open a temporary file for the message */
  1223. MsgFile = SysTempFileName('msg?????.tmp', '?')
  1224. if MsgFile = '' then return
  1225.  
  1226. rc = stream(MsgFile, 'C', 'OPEN WRITE')
  1227. if rc <> 'READY:' then return
  1228.  
  1229. AdminSubject = 'Welcome to' List1
  1230. AdminTo = Email1
  1231. AdminFile = MsgFile
  1232. call WriteAdminHeaders
  1233. rc = stream(MsgFile, 'C', 'CLOSE')
  1234.  
  1235. call AppendLock(FileName MsgFile)
  1236.  
  1237. /* Create the email file */
  1238. EmailFile = SysTempFileName('email????.tmp', '?')
  1239. if EmailFile = '' then
  1240.   do
  1241.   rc = SysFileDelete(MsgFile)
  1242.   return
  1243.   end
  1244.  
  1245. rc = stream(EmailFile, 'C', 'OPEN WRITE')
  1246. if rc <> 'READY:' then
  1247.   do
  1248.   rc = SysFileDelete(MsgFile)
  1249.   return
  1250.   end
  1251.  
  1252. rc = lineout(EmailFile, Email1, )
  1253. rc = stream(EmailFile, 'C', 'CLOSE')
  1254.  
  1255. /* now mail it to them */
  1256. Mailer WhoAmI'-owner@'WhereAmI EmailFile MsgFile
  1257.  
  1258. return TRUE
  1259.  
  1260. /* ------------------------------------------------------------------ */
  1261. IsOREXX: PROCEDURE                               /*wfs 7-Aug-1997*/
  1262.   PARSE VERSION rx ver dt
  1263.   RETURN rx = 'OBJREXX'
  1264.  
  1265. /* ------------------------------------------------------------------ */
  1266. /* ------------------------------------------------------------------ */
  1267.  
  1268.  
  1269.