home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / steward8.zip / Message.cmd < prev    next >
OS/2 REXX Batch file  |  1996-06-27  |  31KB  |  1,069 lines

  1. /* Steward Version 1.1 Build 8 */
  2. /* Message Module */
  3. /*
  4.  * A mailing list processor in Rexx by Paul Hethmon
  5.  *
  6.  */
  7.  
  8. /* variable declarations */
  9.  
  10. Steward = 'Steward'
  11. StewardVersion = 'Version 1.1 Build 8'
  12. StewardDate = '26 June 1996'
  13. uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  14. lowercase = 'abcdefghijklmnopqrstuvwxyz'
  15. Env = 'OS2ENVIRONMENT'
  16. FALSE = 0
  17. TRUE = 1
  18.  
  19. /* Set to 1 to enable debug output */
  20. Debug = TRUE
  21. /* Set to 1 to enable logging */
  22. Log = TRUE
  23. LogFile = ''
  24. ETime1 = 0
  25. ETime2 = 0
  26. Author = ''
  27. AdminFile = ''
  28. AdminSubject = ''
  29. AdminTo = ''
  30.  
  31. /* Variables normally read from the configuration file */
  32. /* These values are provided as defaults only */
  33. HomeDir = 'c:'
  34. LogDir = 'c:'
  35. ListDir = 'c:'
  36. Mailer = 'hmailer'
  37. WhereAmI = 'steward'
  38. WhoAmI = Steward
  39. WhoAmIOwner = 'postmaster@'WhereAmI
  40. MasterPassword = 'steward'
  41.  
  42. /* The following are set on a per list basis */
  43. AdminPassword = 'steward-list'
  44. Administrivia = 0
  45. ListOwner = WhoAmIOwner
  46. Advertise = '*'
  47. ApprovePassword = 'steward-pass'
  48. DoArchive = 0
  49. Moderated = 0
  50. NoList = 0
  51. Precedence = 1
  52. ListHeader = 1
  53. ListFooter = ''
  54. DoDigest = 0
  55. DigestVolume = 0
  56. DigestIssue = 0
  57. DigestName = ''
  58. DigestRmHeader = 1
  59. DigestFronter = ''
  60. DigestFooter = ''
  61. DigestSubs = TRUE
  62. SubscribePolicy = 'open'
  63. ReplyTo = ''
  64. SubjectPrefix = 'Steward-List: '
  65. OpenPosting = FALSE
  66. WelcomeFile = ''
  67. CaseInsensitive = FALSE
  68.  
  69. /* Some other global variables */
  70. HeadFrom = ''
  71. HeadTo = ''
  72. HeadReplyTo = ''
  73. HeadSubject = ''
  74. HeadDate = ''
  75. HeadCc = ''
  76. HeadSender = ''
  77. HeadEmail = ''
  78. Email = ''
  79. Approved = FALSE
  80. PassWord = ''
  81.  
  82. /* The external functions we need */
  83. call RxFuncAdd 'SysTempFileName', 'RexxUtil', 'SysTempFileName'
  84. call RxFuncAdd 'SysFileDelete', 'RexxUtil', 'SysFileDelete'
  85. call RxFuncAdd 'SysFileTree', 'RexxUtil', 'SysFileTree'
  86. call RxFuncAdd 'SysSleep', 'RexxUtil', 'SysSleep'
  87.  
  88. /* start main function */
  89. /* The first arg is who the message was sent to.
  90.  * The second is the filename. We're responsible
  91.  * for cleaning up the file if needed.
  92.  */
  93. parse arg ListName MsgFile
  94.  
  95. if Debug = TRUE then say 'ListName =' ListName 'MsgFile =' MsgFile
  96.  
  97. call on error name ErrHandler
  98.  
  99. say 'Reading Master Configuration File Now.'
  100.  
  101. /* Read the master configuration file now */
  102. rc = ReadMasterCf()
  103. if rc = FALSE then
  104.   do
  105.   say 'Unable to read master configuration file. Failing.'
  106.   ErrFile = SysTempFileName('?????.err', '?')
  107.   rc = stream(ErrFile, 'C', 'OPEN WRITE')
  108.   rc = lineout(ErrFile, 'Steward Error File', )
  109.   rc = lineout(ErrFile, 'You must rerun Steward with the recipient name and', )
  110.   rc = lineout(ErrFile, 'message file name listed below in order to process', )
  111.   rc = lineout(ErrFile, 'this message.', )
  112.   rc = lineout(ErrFile, 'Rcpt =' Rcpt, )
  113.   rc = lineout(ErrFile, 'MsgFile =', MsgFile, )
  114.   rc = stream(ErrFile, 'C', 'CLOSE')
  115.   exit
  116.   end
  117.  
  118. /* change to the Steward Home Directory */
  119. Junk = directory(HomeDir)
  120.  
  121. if Debug = TRUE then
  122.   do
  123.   say 'LogDir =' LogDir
  124.   say 'HomeDir = ' HomeDir
  125.   say 'ListDir =' ListDir
  126.   say 'Junk =' Junk
  127.   end
  128.  
  129. if Log = TRUE then do
  130.   ETime1 = time('E')
  131.   call StartLog
  132.   call WriteLog('ListName =' ListName)
  133.   call WriteLog('MsgFile =' MsgFile)
  134.   end
  135.  
  136. /* Process the message */
  137. call DoMessage
  138.  
  139. /* Make sure the tmp file is deleted */
  140. rc = SysFileDelete(MsgFile)
  141.  
  142. if Log = TRUE then do
  143.   ETime2 = time('E')
  144.   call StopLog
  145.   end
  146.  
  147. exit
  148.  
  149. /* ------------------------------------------------------------------ */
  150.  
  151. DoMessage:
  152.  
  153. /* Read the per list configuration file */
  154. call ReadListCf(ListName)
  155.  
  156. if Debug = TRUE then say 'Processing message now'
  157. if Log = TRUE then call WriteLog('Processing message now')
  158.  
  159. rc = stream(MsgFile, 'C', 'OPEN READ')  /* open the file for reading */
  160. if rc <> 'READY:' then do
  161.   call WriteLog('Could not open message file.')
  162.   return
  163.   end
  164.  
  165. call ParseHeaders  /* first get the header info */
  166.  
  167. if HeadReplyTo <> '' then
  168.   HeadEmail = HeadReplyTo
  169. else
  170.   HeadEmail = HeadFrom
  171. /* now clean up the email address */
  172. HeadEmail = NormalizeEmail(HeadEmail)
  173. HeadEmail = translate(HeadEmail, lowercase, uppercase)
  174.  
  175. if Debug = TRUE then say 'HeadEmail =' HeadEmail
  176.  
  177. /* create a temp file for the outgoing message */
  178. OutFile = SysTempFileName('f?????.tmp', '?')
  179. rc = stream(OutFile, 'C', 'OPEN WRITE')  /* open the file for writing */
  180. if rc <> 'READY:' then do
  181.   call WriteLog('Could not create temp file for outgoing message.')
  182.   end
  183.  
  184. if Debug = TRUE then
  185.   do
  186.   say 'ListName =' ListName
  187.   say 'HeadEmail =' HeadEmail
  188.   end
  189. if Log = TRUE then
  190.   do
  191.   call WriteLog('ListName =' ListName)
  192.   call WriteLog('HeadEmail =' HeadEmail)
  193.   end
  194.  
  195. /* now check and see if this person is on the list */
  196. if CanPost(ListName HeadEmail) = FALSE then do
  197.   if Debug = TRUE then say 'Cannot post.'
  198.   if Log = TRUE then call WriteLog('Cannot post.')
  199.   call ReturnErrorMsg   /* also close and delete the message file */
  200.   return
  201.   end
  202.  
  203. if Debug = TRUE then say 'Sender can post.'
  204. if Log = TRUE then call WriteLog('Sender can post.')
  205.  
  206. /* See if it needs a moderator's approval */
  207. if Moderated = TRUE then do
  208.   if CheckForApproval() = FALSE then do  /* this post not approved, send to moderator */
  209.     call SendToModerator                 /* this will also close the message file */
  210.     if Debug = TRUE then say 'Sending msg to moderator for approval.'
  211.     if Log = TRUE then call WriteLog('Sending msg to moderator for approval.')
  212.     return
  213.     end
  214.   end
  215.  
  216. if Debug = TRUE then say 'Message ok to send to list.'
  217. if Log = TRUE then call WriteLog('Message ok to send to list.')
  218.  
  219. /* if we're here, then this is a non-moderated list or an approved post */
  220. /* the CheckForApproval function has already digested the approval header */
  221. /* so that it is not sent to the list also. Now send the message out. */
  222.  
  223. call WriteListHeaders
  224.  
  225. do while lines(MsgFile) <> 0         /* until end of file */
  226.   Line = linein(MsgFile)             /* get a line of the file */
  227.   rc = lineout(OutFile, Line, )      /* write it to the outfile */
  228.   end
  229.  
  230. rc = stream(MsgFile, 'C', 'CLOSE')   /* close both files */
  231. rc = stream(OutFile, 'C', 'CLOSE')
  232.  
  233. if ListFooter <> '' then do
  234.   Footer = ListDir'\'ListName'\'ListFooter
  235.   rc = AppendLock(Footer OutFile)
  236.   end
  237.  
  238. if Debug = TRUE then say 'Headers and Msg written to outfile.'
  239.  
  240. /* now create the file with the email addresses in it */
  241. FileName = ListDir'\'ListName'\'ListName
  242. /* create a temp file for the email addresses */
  243. EmailFile = SysTempFileName('e?????.tmp', '?');
  244. /* copy the list's email addresses to the temporary name */
  245. rc = CopyLock(FileName EmailFile)
  246.  
  247. if Log = TRUE then do
  248.   call WriteLog('Mail from:' ListName'-owner@'WhereAmI)
  249.   call WriteLog('Emailfile:' EmailFile)
  250.   call WriteLog('Msgfile:' OutFile)
  251.   call LogRcpt(EmailFile)
  252.   end
  253.  
  254. if Debug = TRUE then say 'EmailFile ready.'
  255.  
  256. /* Save to the archives if requested */
  257. if DoArchive = TRUE then do
  258.   call SaveArchive(OutFile)
  259.   end
  260.  
  261. /* Save to the digest if we're running this list as a digest too */
  262. if DoDigest = TRUE then do
  263.   call SaveDigest(OutFile)
  264.   end
  265.  
  266. if Debug = TRUE then say 'Starting mailer.'
  267.  
  268. /* start the mail program to send the message out */
  269. Mailer ListName'-owner@'WhereAmI EmailFile OutFile
  270.  
  271. return
  272.  
  273. /* ------------------------------------------------------------------ */
  274.  
  275. SendToModerator:
  276.  
  277. if Log = TRUE then call WriteLog('Sending msg to moderator for approval.')
  278.  
  279. /* write the headers first */
  280. TimeZone = value( 'TZ', , Env)
  281. TmpTime = time('N')
  282. DayOfWeek = date('W')
  283. DayOfWeek = left(DayOfWeek, 3)
  284. TmpDate = date('N')
  285. rc = lineout(OutFile, 'Date:' DayOfWeek',' TmpDate TmpTime TimeZone, )
  286. rc = lineout(OutFile, 'Sender:' WhoAmI'-owner <'WhoAmI'-owner@'WhereAmI'>', )
  287. rc = lineout(OutFile, 'From:' WhoAmI '<'WhoAmI'@'WhereAmI'>', )
  288. rc = lineout(OutFile, 'Reply-To:' ListName'@'WhereAmI, )
  289. rc = lineout(OutFile, 'Subject: Approval Request for' ListName, )
  290. rc = lineout(OutFile, 'To:' ListOwner, )
  291. rc = lineout(OutFile, '', )
  292. rc = lineout(OutFile, 'Approved: ', )
  293. rc = lineout(OutFile, '', )
  294. rc = lineout(OutFile, '--------------------------------------------------', )
  295. rc = lineout(OutFile, 'From:' HeadFrom, )
  296. rc = lineout(OutFile, 'To:' HeadTo, )
  297. rc = lineout(OutFile, 'Subject:' HeadSubject, )
  298. rc = lineout(OutFile, '--------------------------------------------------', )
  299.  
  300. /* now copy the rest of the message */
  301. do while lines(MsgFile) <> 0         /* until end of file */
  302.   Line = linein(MsgFile)             /* get a line of the file */
  303.   rc = lineout(OutFile, Line, )      /* write it to the outfile */
  304.   end
  305.  
  306. rc = stream(MsgFile, 'C', 'CLOSE')   /* close both files */
  307. rc = stream(OutFile, 'C', 'CLOSE')
  308.  
  309. EmailFile = SysTempFileName('e?????.tmp', '?')
  310. rc = stream(EmailFile, 'C', 'OPEN WRITE')  /* open the file for writing */
  311. if rc <> 'READY:' then do
  312.   call SendError('no emailfile')
  313.   end
  314. rc = lineout(EmailFile, ListOwner, )
  315. rc = stream(EmailFile, 'C', 'CLOSE')
  316.  
  317. /* now mail it to the moderator */
  318. Mailer WhoAmI'@'WhereAmI EmailFile OutFile
  319.  
  320. return
  321.  
  322. /* ------------------------------------------------------------------ */
  323.  
  324. ReturnErrorMsg:
  325.  
  326. if Debug = TRUE then say 'Returning error msg to sender.'
  327. if Log = TRUE then call WriteLog('Returning error msg to sender.')
  328.  
  329. /* write the headers first */
  330. AdminSubject = 'Your Message To' ListName
  331. if HeadReplyTo <> '' then
  332.   AdminTo = HeadReplyTo
  333. else if HeadFrom <> '' then
  334.   AdminTo = HeadFrom
  335. AdminFile = OutFile
  336. call WriteAdminHeaders
  337.  
  338. rc = lineout(OutFile, 'Your message to the list' ListName 'has been rejected.', )
  339. rc = lineout(OutFile, '', )
  340. rc = lineout(OutFile, 'You are not a member of the list. For help on subscribing to', )
  341. rc = lineout(OutFile, 'the list, please send a message to' WhoAmI'@'WhereAmI 'with', )
  342. rc = lineout(OutFile, 'the word "help" in the body of the message.', )
  343. rc = lineout(OutFile, '', )
  344. rc = lineout(OutFile, 'Your humble mailing list software,', )
  345. rc = lineout(OutFile, '', )
  346. rc = lineout(OutFile, WhoAmI, )
  347.  
  348. rc = stream(OutFile, 'C', 'CLOSE')
  349.  
  350. EmailFile = SysTempFileName('e?????.tmp', '?')
  351. rc = stream(EmailFile, 'C', 'OPEN WRITE')  /* open the file for writing */
  352. if rc <> 'READY:' then do
  353.   call SendError('no emailfile')
  354.   end
  355. rc = lineout(EmailFile, HeadEmail, )
  356. rc = stream(EmailFile, 'C', 'CLOSE')
  357.  
  358. if Debug = TRUE then say 'Starting mailer.'
  359.  
  360. /* now mail it to the hapless emailer */
  361. Mailer WhoAmI'@'WhereAmI EmailFile OutFile
  362.  
  363. return
  364.  
  365. /* ------------------------------------------------------------------ */
  366. /*
  367.  * Write out our standard headers for a list message
  368.  *
  369.  */
  370.  
  371. WriteListHeaders:  /* note that we have full access to all globals here */
  372.  
  373. TimeZone = value( 'TZ', , Env)
  374. TmpTime = time('N')
  375. DayOfWeek = date('W')
  376. DayOfWeek = left(DayOfWeek, 3)
  377. TmpDate = date('N')
  378. /* we put in the local time for date so that posts are chronological */
  379. rc = lineout(OutFile, 'Date:' DayOfWeek',' TmpDate TmpTime TimeZone, )
  380. /* for those that want it, here's the original date */
  381. rc = lineout(OutFile, 'X-OldDate:' HeadDate, )
  382.  
  383. rc = lineout(OutFile, 'Sender:' ListName'-owner <'ListName'-owner@'WhereAmI'>', )
  384. if ListHeader = TRUE then
  385.   rc = lineout(OutFile, 'X-Listname:' ListName'@'WhereAmI, )
  386.  
  387. if ReplyTo <> '' then
  388.   rc = lineout(OutFile, 'Reply-To:' ReplyTo, )
  389. else if HeadReplyTo <> '' then
  390.   rc = lineout(OutFile, 'Reply-To:' HeadReplyTo, )
  391. else if HeadFrom <> '' then
  392.   rc = lineout(OutFile, 'Reply-To:' HeadFrom, )
  393.  
  394. /* if we set replyto to the sender, then list the list as a CC */
  395. if ReplyTo = '' then
  396.   rc = lineout(OutFile, 'Cc:' ListName '<'ListName'@'WhereAmI'>', )
  397.  
  398. rc = lineout(OutFile, 'From:' HeadFrom, )
  399. rc = lineout(OutFile, 'To:' HeadTo, )
  400.  
  401. if SubjectPrefix <> '' then
  402.   do
  403.   TmpSubject = ReWriteSubject(HeadSubject)
  404.   rc = lineout(OutFile, 'Subject:' SubjectPrefix TmpSubject, )
  405.   end
  406. else
  407.   rc = lineout(OutFile, 'Subject:' HeadSubject, )
  408.  
  409. rc = lineout(OutFile, '', )
  410.  
  411. return
  412.  
  413. /* ------------------------------------------------------------------ */
  414. /* 
  415.  * Check for the approval header for this list
  416.  *
  417.  */
  418.  
  419. CheckForApproval:
  420.  
  421. if Debug = TRUE then say 'Checking msg for approval.'
  422. if Log = TRUE then call WriteLog('Checking msg for approval.')
  423.  
  424. Line = ''
  425. do while Line = ''          /* look for first non-blank line */
  426.   Line = linein(MsgFile)
  427.   if lines(MsgFile) = 0 then return FALSE
  428.   end
  429.  
  430. parse var Line Key ':' Val
  431. Key = translate(Key, lowercase, uppercase)
  432. if Key = 'approved' & Val = ApprovePassword then do
  433.   return TRUE
  434.   end
  435.  
  436. return FALSE
  437.  
  438. /* ------------------------------------------------------------------ */
  439.  
  440. IsList: procedure expose ListDir TRUE FALSE Debug Log LogFile
  441.  
  442. parse arg ListName
  443.  
  444. if Debug = TRUE then say 'Checking for list' ListName
  445. if Log = TRUE then call WriteLog('Checking for list' ListName)
  446.  
  447. /* First check to see if this is a digest request */
  448. parse var ListName List '-' Digest
  449. Digest = translate(Digest, lowercase, uppercase)
  450. if Digest = 'digest' then
  451.   DirName = ListDir'\'List'\Digests'
  452. else  
  453.   DirName = ListDir'\'ListName
  454.  
  455. rc = SysFileTree(DirName, s., 'D')
  456. if rc = 0 & s.0 = 1 then
  457.   return TRUE
  458. else
  459.   return FALSE
  460.  
  461. return FALSE  /* safety net */
  462.  
  463. /* ------------------------------------------------------------------ */
  464.  
  465. CanPost: procedure expose ListDir TRUE FALSE Debug Log LogFile OpenPosting,
  466.          lowercase uppercase
  467.  
  468. parse arg ListName Email
  469.  
  470. if OpenPosting = TRUE then return TRUE /* bypass member checks */
  471.  
  472. if Debug = TRUE then say 'Checking if' Email 'is a list member of' ListName
  473. if Log = TRUE then call WriteLog('Checking if' Email 'is a list member of' ListName)
  474.  
  475. /* First check to see if this is a digest request */
  476. parse var ListName List '-' Digest
  477. Digest = translate(Digest, lowercase, uppercase)
  478. if Digest = 'digest' then
  479.   FileName = ListDir'\'List'\'List
  480. else  
  481.   FileName = ListDir'\'ListName'\'ListName
  482.  
  483. Sub = FALSE
  484.  
  485. rc = LockOpen(FileName 'READ')  /* open the file locking it */
  486. if rc = FALSE then
  487.   return FALSE                   /* return FALSE if cannot open */
  488.  
  489. Email = translate(Email, lowercase, uppercase)
  490.  
  491. do while lines(FileName) <> 0         /* until end of file */
  492.   Line = linein(FileName)             /* get a line of the file */
  493.   Line = translate(Line, lowercase, uppercase)
  494.   if Line = Email then do
  495.     Sub = TRUE
  496.     leave
  497.     end
  498. end
  499.  
  500. rc = LockClose(FileName)
  501.  
  502. if Sub = TRUE then return TRUE
  503.  
  504. /* Now check the digest members */
  505. FileName = FileName'.digest'
  506. rc = LockOpen(FileName 'READ')  /* open the file locking it */
  507. if rc = FALSE then
  508.   return FALSE                   /* return FALSE if cannot open */
  509.  
  510. do while lines(FileName) <> 0         /* until end of file */
  511.   Line = linein(FileName)             /* get a line of the file */
  512.   Line = translate(Line, lowercase, uppercase)
  513.   if Line = Email then do
  514.     Sub = TRUE
  515.     leave
  516.     end
  517. end
  518.  
  519. rc = LockClose(FileName)
  520.  
  521. return Sub
  522.  
  523. /* ------------------------------------------------------------------ */
  524. /*
  525.  * Normalize the email address into a SMTP form
  526.  *
  527.  */
  528.  
  529. NormalizeEmail: procedure expose Author
  530.  
  531. parse arg All
  532.  
  533. rc = pos('<', All, )
  534. if rc = 0 then
  535.   do
  536.   /* in case some mailers use () instead of <> */
  537.   All = translate(All, '<', '(')
  538.   All = translate(All, '>', ')')
  539.   end
  540.  
  541. parse var All Part1 '<' Part2 '>' Part3
  542.  
  543. rc = pos('@', Part1, )
  544. if rc <> 0 then 
  545.   do
  546.   Part1 = strip(Part1, 'B', )  /* we must strip any blanks leftover */
  547.   if Part2 <> '' then Author = Part2
  548.   else if Part3 <> '' then Author = Part3
  549.   else Author = Part1
  550.   return Part1
  551.   end
  552.  
  553. rc = pos('@', Part2, )
  554. if rc <> 0 then
  555.   do
  556.   Part2 = strip(Part2, 'B', )
  557.   if Part1 <> '' then Author = Part1
  558.   else if Part3 <> '' then Author = Part3
  559.   else Author = Part2
  560.   return Part2
  561.   end
  562.  
  563. rc = pos('@', Part3, )
  564. if rc <> 0 then
  565.   do
  566.   Part3 = strip(Part3, 'B', )
  567.   if Part2 <> '' then Author = Part2
  568.   else if Part1 <> '' then Author = Part1
  569.   else Author = Part3
  570.   return Part3
  571.   end
  572.  
  573. return ''  /* error finding SMTP email address */
  574.  
  575. /* ------------------------------------------------------------------ */
  576. /*
  577.  * Parse RFC822 headers
  578.  *
  579.  */
  580.  
  581. ParseHeaders: procedure expose HeadTo HeadFrom HeadReplyTo MsgFile HeadSubject ,
  582.               lowercase uppercase HeadDate HeadCc HeadSender Log FALSE TRUE LogFile
  583.  
  584. say 'ParseHeaders starting'
  585.  
  586. Line = linein(MsgFile)                /* get a line of the file */
  587. do while Line <> ''                   /* until end of headers */
  588.   parse var Line Key ':' Val          /* separate out the components */
  589.   Key = translate(Key, lowercase, uppercase)
  590.   select
  591.     when Key = 'to' then
  592.       HeadTo = Val
  593.     when Key = 'reply-to' then
  594.       HeadReplyTo = Val
  595.     when Key = 'from' then
  596.       HeadFrom = Val
  597.     when Key = 'subject' then
  598.       HeadSubject = Val
  599.     when Key = 'date' then
  600.       HeadDate = Val
  601.     when Key = 'cc' then
  602.       HeadCc = Val
  603.     when Key = 'sender' then
  604.       HeadSender = Val
  605.     otherwise nop
  606.     end   /* select */
  607.   Line = linein(MsgFile)
  608. end       /* do while */
  609.  
  610. if Log = TRUE then
  611.   do
  612.   say 'Writing headers info to log file'
  613.   call WriteLog('ParseHeaders Info:')
  614.   call WriteLog('To:' HeadTo)
  615.   call WriteLog('From:' HeadFrom)
  616.   call WriteLog('Reply-to:' HeadReplyTo)
  617.   call WriteLog('Subject:' HeadSubject)
  618.   end
  619.  
  620. return
  621.  
  622. /* ------------------------------------------------------------------ */
  623. /*
  624.  * Read the master configuration file
  625.  *
  626.  */
  627.  
  628. ReadMasterCf: procedure expose HomeDir LogDir ListDir Mailer WhereAmI WhoAmI ,
  629.               WhoAmIOwner MasterPassword Env TRUE FALSE Debug
  630.  
  631. if Debug = TRUE then say 'Reading Steward configuration file.'
  632.  
  633. /* Find out where the configuration file should be */
  634. StewardCf = value('steward_cf',,Env)
  635. /* StewardCf = value('steward_cf_test',,Env) */
  636.  
  637. /* If its not defined then assume wherever we are */
  638. if StewardCf = '' then do
  639.   StewardCf = '.'
  640.   end
  641.  
  642. FileName = StewardCf'\steward.cf'
  643.  
  644. rc = LockOpen(FileName 'READ')  /* open the file locking it */
  645. if rc = FALSE then
  646.   return FALSE                   /* return FALSE if cannot open */
  647.  
  648. /* now read the configuration file */
  649. do while lines(FileName) <> 0         /* until end of file */
  650.   Line = linein(FileName)             /* get a line of the file */
  651.   parse var Line Line '#' Comment     /* separate out any comments */
  652.   if Line <> '' then do               /* if not null */
  653.     parse var Line Key '=' Val        /* find the key and value */
  654.     if Key <> '' then do
  655.       Val = strip(Val, 'B', ' ')      /* remove any blanks */
  656.       Key = strip(Key, 'B', ' ')
  657.       select
  658.         when Key = 'HomeDir' then
  659.           HomeDir = Val
  660.         when Key = 'LogDir' then
  661.           LogDir = Val
  662.         when Key = 'ListDir' then
  663.           ListDir = Val
  664.         when Key = 'Mailer' then
  665.           Mailer = Val
  666.         when Key = 'WhereAmI' then
  667.           WhereAmI = Val
  668.         when Key = 'WhoAmI' then
  669.           WhoAmI = Val
  670.         when Key = 'WhoAmIOwner' then
  671.           WhoAmIOwner = Val
  672.         when Key = 'MasterPassword' then
  673.           MasterPassword = Val
  674.         otherwise nop
  675.         end   /* select */
  676.       end     /* if Key <> '' */
  677.     end       /* if Line <> '' */
  678.  
  679.   Key = ''
  680.  
  681. end /* end do while */
  682.  
  683. rc = LockClose(FileName)
  684.  
  685. if Debug = TRUE then say 'Steward.cf file read.'
  686.  
  687. return TRUE
  688.  
  689. /* ------------------------------------------------------------------ */
  690. /*
  691.  * Read the per list configuration file
  692.  *
  693.  */
  694.  
  695. ReadListCf: procedure expose ListDir AdminPassword ListOwner Administrivia,
  696.             Advertise ApprovePassword DoArchive Moderated NoList Precedence,
  697.             ListHeader SubscribePolicy ReplyTo SubjectPrefix TRUE FALSE,
  698.             DoDigest DigestRmHeader DigestVolume DigestIssue DigestFronter,
  699.             DigestFooter DigestName Debug Log LogFile OpenPosting WelcomeFile,
  700.             DigestSubs CaseInsensitive ListFooter
  701.  
  702. parse arg ListName
  703.  
  704. if Debug = TRUE then say 'Reading list configuration file for' ListName
  705.  
  706. /* First check to see if this is a digest request */
  707. parse var ListName List '-' Digest
  708. Digest = translate(Digest, lowercase, uppercase)
  709. if Digest = 'digest' then
  710.   FileName = ListDir'\'List'\'List'.cf'
  711. else  
  712.   FileName = ListDir'\'ListName'\'ListName'.cf'
  713.  
  714. if Debug = TRUE then say 'Reading filename "'FileName'"'
  715.  
  716. rc = LockOpen(FileName 'READ')  /* open the file locking it */
  717. if rc = FALSE then
  718.   return FALSE                   /* return FALSE if cannot open */
  719.  
  720. /* now read the configuration file */
  721. do while lines(FileName) <> 0         /* until end of file */
  722.   Line = linein(FileName)             /* get a line of the file */
  723.   parse var Line Line '#' Comment     /* separate out any comments */
  724.   if Line <> '' then do               /* if not null */
  725.     parse var Line Key '=' Val        /* find the key and value */
  726.     if Key <> '' then do
  727.       Val = strip(Val, 'B', ' ')      /* remove any blanks */
  728.       Key = strip(Key, 'B', ' ')
  729. /*      say Key '=' Val */
  730.       select
  731.         when Key = 'AdminPassword' then
  732.           AdminPassword = Val
  733.         when Key = 'ListOwner' then
  734.           ListOwner = Val
  735.         when Key = 'Administrivia' then
  736.           Administrivia = Val
  737.         when Key = 'Advertise' then
  738.           Advertise = Val
  739.         when Key = 'ApprovePassword' then
  740.           ApprovePassword = Val
  741.         when Key = 'DoArchive' then
  742.           DoArchive = Val
  743.         when Key = 'Moderated' then
  744.           Moderated = Val
  745.         when Key = 'NoList' then
  746.           NoList = Val
  747.         when Key = 'Precedence' then
  748.           Precedence = Val
  749.         when Key = 'ListHeader' then
  750.           ListHeader = Val
  751.         when Key = 'SubscribePolicy' then
  752.           SubscribePolicy = Val
  753.         when Key = 'ReplyTo' then
  754.           ReplyTo = Val
  755.         when Key = 'SubjectPrefix' then
  756.           SubjectPrefix = Val
  757.         when Key = 'DoDigest' then
  758.           DoDigest = Val
  759.         when Key = 'DigestRmHeader' then
  760.           DigestRmHeader = Val
  761.         when Key = 'DigestVolume' then
  762.           DigestVolume = Val
  763.         when Key = 'DigestIssue' then
  764.           DigestIssue = Val
  765.         when Key = 'DigestName' then
  766.           DigestName = Val
  767.         when Key = 'DigestFronter' then
  768.           DigestFronter = Val
  769.         when Key = 'DigestFooter' then
  770.           DigestFooter = Val
  771.         when Key = 'OpenPosting' then
  772.           OpenPosting = Val
  773.         when Key = 'WelcomeFile' then
  774.           WelcomeFile = Val
  775.         when Key = 'DigestSubs' then
  776.           DigestSubs = Val
  777.         when Key = 'CaseInsensitive' then
  778.           CaseInsensitive = Val
  779.         when Key = 'ListFooter' then
  780.           ListFooter = Val
  781.         otherwise nop
  782.         end   /* select */
  783.       end     /* if Key <> '' */
  784.     end       /* if Line <> '' */
  785.  
  786.   Key = ''
  787.  
  788. end /* end do while */
  789.  
  790. rc = LockClose(FileName)
  791.  
  792. return TRUE
  793.  
  794. /* ------------------------------------------------------------------ */
  795. /*
  796.  * Save the current message to the archive database
  797.  *
  798.  */
  799.  
  800. SaveArchive: procedure expose ListDir ListName Debug Log FALSE TRUE LogFile
  801.  
  802. parse arg MsgFile
  803.  
  804. if Debug = TRUE then say 'Saving msg to archive.'
  805. if Log = TRUE then call WriteLog('Saving msg to archive.')
  806.  
  807. /* Today's date */
  808. TmpDate = date('E')
  809. parse var TmpDate TmpDay '/' TmpMon '/' TmpYear
  810.  
  811. /* create the filename */
  812. FileName = ListDir'\'ListName'\Archives\'TmpYear'.'TmpMon
  813.  
  814. /* open the file */
  815. rc = LockOpen(FileName 'WRITE')
  816. rc = stream(FileName, 'C', 'SEEK <0')      /* go to end of file */
  817.  
  818. /* the separator line */
  819. rc = lineout(FileName, '', )
  820. rc = lineout(FileName, '===== Message Separator ==========================', )
  821. rc = lineout(FileName, '', )
  822.  
  823. /* copy the new message to it */
  824. rc = LockOpen(MsgFile 'READ')
  825. do while lines(MsgFile) <> 0         /* until end of file */
  826.   Line = linein(MsgFile)             /* get a line of the file */
  827.   rc = lineout(FileName, Line, )
  828.   end
  829.  
  830. rc = LockClose(MsgFile)
  831. rc = LockClose(FileName)
  832.  
  833. return
  834.  
  835.  
  836. /* ------------------------------------------------------------------ */
  837. /*
  838.  * Save the current message to the digest database
  839.  *
  840.  */
  841.  
  842. SaveDigest: procedure expose ListDir ListName TRUE FALSE HeadFrom HeadReplyTo,
  843.                              HeadSubject HeadDate HeadCc HeadSender HeadTo Debug,
  844.                              Log LogFile DigestSubs Author
  845.  
  846. parse arg MsgFile
  847.  
  848. if Debug = TRUE then say 'Saving msg to digest.'
  849. if Log = TRUE then call WriteLog('Saving msg to digest.')
  850.  
  851. /* Today's date */
  852. TmpDate = date('E')
  853. parse var TmpDate TmpDay '/' TmpMon '/' TmpYear
  854.  
  855. /* create the filename */
  856. FileName = ListDir'\'ListName'\Digests\'TmpYear'.'TmpMon'.'TmpDay
  857.  
  858. /* open the file */
  859. rc = LockOpen(FileName 'WRITE')
  860. rc = stream(FileName, 'C', 'SEEK <0')      /* go to end of file */
  861.  
  862. /* the separator lines */
  863. rc = lineout(FileName, '', )
  864. rc = lineout(FileName, '===== Message Separator ==========================', )
  865. rc = lineout(FileName, '', )
  866.  
  867. /* copy the new message to it */
  868. rc = LockOpen(MsgFile 'READ')
  869.  
  870. Line = linein(MsgFile)    /* First skip the rewritten headers */
  871. do while Line <> ''
  872.   Line = linein(MsgFile)
  873.   end
  874.  
  875. /* Now write out the headers we want */
  876. if HeadDate <> '' then
  877.   rc = lineout(FileName, 'Date:' HeadDate, )
  878.  
  879. if DigestRmHeader = FALSE then do
  880.   if HeadSender <> '' then
  881.     rc = lineout(FileName, 'Sender:' HeadSender, )
  882.   if HeadCc <> '' then
  883.     rc = lineout(FileName, 'Cc:' HeadCc, )
  884.   if HeadTo <> '' then
  885.     rc = lineout(FileName, 'To:' HeadTo, )
  886.   end
  887.   
  888. if HeadFrom <> '' then
  889.   rc = lineout(FileName, 'From:' HeadFrom, )
  890. if HeadReplyTo <> '' then
  891.   rc = lineout(FileName, 'Reply-To:' HeadReplyTo, )
  892. if HeadSubject <> '' then
  893.   rc = lineout(FileName, 'Subject:' HeadSubject, )
  894. rc = lineout(FileName, '', )
  895.  
  896. do while lines(MsgFile) <> 0         /* until end of file */
  897.   Line = linein(MsgFile)             /* get a line of the file */
  898.   rc = lineout(FileName, Line, )
  899.   end
  900.  
  901. rc = LockClose(MsgFile)
  902. rc = LockClose(FileName)
  903.  
  904. /* Check to see if we need to save subject lines for the digest */
  905. if DigestSubs = TRUE then
  906.   do
  907.   FileName = FileName'.subs'
  908.   /* open the file */
  909.   rc = LockOpen(FileName 'WRITE')
  910.   rc = stream(FileName, 'C', 'SEEK <0')      /* go to end of file */
  911.   /* show subject and then the author */
  912.   rc = lineout(FileName, HeadSubject ':' Author, )
  913.   rc = LockClose(FileName)
  914.   end
  915.  
  916. return
  917.  
  918.  
  919. /* ------------------------------------------------------------------ */
  920.  
  921. StartLog: procedure expose LogDir LogFile ETime1 ETime2 Debug FALSE TRUE
  922.  
  923. FileName = LogDir'\?????.log'
  924. if Debug = TRUE then 
  925.   do
  926.   say 'FileName =' FileName
  927.   say 'LogDir =' LogDir
  928.   end
  929.  
  930. LogFile = SysTempFileName(FileName, '?')
  931.  
  932. if LogFile = '' then
  933.   do
  934.   say 'Cannot create temporary file.'
  935.   say 'Setting logfile to NUL'
  936.   LogFile = 'NUL'
  937.   Log = FALSE
  938.   return
  939.   end
  940.  
  941. if Debug = TRUE then say 'LogFile =' LogFile
  942.  
  943. rc = stream(LogFile, 'C', 'OPEN WRITE')
  944.  
  945. TmpTime = time('N')
  946. TmpDate = date('N')
  947.  
  948. rc = lineout(LogFile, 'Date:' TmpDate, )
  949. rc = lineout(LogFile, 'Time:' TmpTime, )
  950.  
  951. return
  952.  
  953. /* ------------------------------------------------------------------ */
  954.  
  955. StopLog: procedure expose LogFile LogDir ETime1 ETime2 Debug FALSE TRUE
  956.  
  957. ETime = ETime2 - Etime1
  958.  
  959. if Debug= TRUE then say 'Elapsed Time =' ETime
  960.  
  961. call WriteLog('Elapsed Time:' ETime)
  962. call WriteLog('')
  963. call WriteLog('=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=')
  964. call WriteLog('')
  965.  
  966. rc = stream(LogFile, 'C', 'CLOSE')
  967.  
  968. PermLog = LogDir'\steward.log'
  969.  
  970. call AppendLock(LogFile PermLog)
  971.  
  972. rc = SysFileDelete(LogFile)
  973.  
  974. return
  975.  
  976. /* ------------------------------------------------------------------ */
  977.  
  978. WriteLog: procedure expose LogFile
  979.  
  980. parse arg String
  981.  
  982. rc = lineout(LogFile, String, )
  983.  
  984. return
  985.   
  986. /* ------------------------------------------------------------------ */
  987.  
  988. ErrHandler:
  989.  
  990. SIGerrCode = RC
  991. StewardErrLog = 'Steward.err'
  992.  
  993. if Debug = TRUE then say 'Identified error while executing line #'Sigl'   RC = ['SIGerrCode']'
  994. if Debug = TRUE then say '['SourceLine(Sigl)']'
  995. rc = lineout( StewardErrLog, '     -----', )
  996. rc = lineout( StewardErrLog, 'Error ['SIGerrCode'] while executing line #'Sigl, )
  997. rc = lineout( StewardErrLog, '['SourceLine(Sigl)']')
  998.  
  999. return
  1000.  
  1001.  
  1002. /* ------------------------------------------------------------------ */
  1003.  
  1004. ReWriteSubject: procedure expose SubjectPrefix
  1005.  
  1006. parse arg Subject
  1007.  
  1008. TmpSubj = translate(Subject, lowercase, uppercase)
  1009.  
  1010. i = lastpos(SubjectPrefix, Subject, )
  1011. if i <> 0 then 
  1012.   do
  1013.   /* find the end of where the subject prefix is */
  1014.   i = i + length(SubjectPrefix)
  1015.   l = length(Subject)
  1016.   Subject = right(Subject, l - i)
  1017.   end
  1018.  
  1019. /* Now look for a "Re:" in the subject line */
  1020. i = lastpos('re:', TmpSubj, )
  1021. if i <> 0 then 
  1022.   Subject = 'Re:' Subject
  1023.  
  1024. return Subject
  1025.  
  1026. /* ------------------------------------------------------------------ */
  1027. /*
  1028.  * Write out our standard headers for an admin message
  1029.  *
  1030.  */
  1031.  
  1032. WriteAdminHeaders: procedure expose AdminTo WhoAmI WhereAmI AdminSubject AdminFile,
  1033.                    Env
  1034.  
  1035. TimeZone = value( 'TZ', , Env)
  1036. TmpTime = time('N')
  1037. DayOfWeek = date('W')
  1038. DayOfWeek = left(DayOfWeek, 3)
  1039. TmpDate = date('N')
  1040. rc = lineout(AdminFile, 'Date:' DayOfWeek',' TmpDate TmpTime TimeZone, )
  1041. rc = lineout(AdminFile, 'Sender:' WhoAmI'-owner <'WhoAmI'-owner@'WhereAmI'>', )
  1042. rc = lineout(AdminFile, 'From:' WhoAmI'-owner <'WhoAmI'-owner@'WhereAmI'>', )
  1043. rc = lineout(AdminFile, 'Reply-To:' WhoAmI '<'WhoAmI'@'WhereAmI'>', )
  1044. rc = lineout(AdminFile, 'To:' AdminTo, )
  1045. rc = lineout(AdminFile, 'Subject:' AdminSubject, )
  1046. rc = lineout(AdminFile, '', )
  1047.  
  1048. return
  1049.  
  1050. /* ------------------------------------------------------------------ */
  1051.  
  1052. LogRcpt:
  1053.  
  1054. parse arg FileName
  1055.  
  1056. rc = stream(FileName, 'c', 'open read')
  1057. do while lines(FileName) <> 0         /* until end of file */
  1058.   Line = linein(FileName)             /* get a line of the file */
  1059.   call WriteLog('Rcpt:' Line)
  1060.   end
  1061. rc = stream(FileName, 'c', 'close')
  1062.  
  1063. return
  1064.  
  1065. /* ------------------------------------------------------------------ */
  1066. /* ------------------------------------------------------------------ */
  1067.  
  1068.  
  1069.