/*

                        $VER: MM_Flame 0.51  (27.04.96)

                           (C) 1995/96 Robert Hofmann

*/

parse arg args

options cache
options failat 99
options results

signal on break_c
signal on break_d
signal on break_e
signal on break_f
signal on halt
signal on ioerr
signal on syntax

address 'MAILMANAGER'


Main:

	call Init
	call Header
	call Parse_Args
	call Read_Cfg

	select
		when system.flame			then call Flame(system.flame.area, system.flame.msg)
		when system.postrules	then call Post_Rules(system.postrules.area)
		when system.scanecs		then call Scan_ECs
		otherwise exit 999
	end

call Quit(0, 'All done.')
exit


Add_Arc: procedure Expose msg.

	parse arg line

	MM_AddToStem 'msg.arc' 'line'

return


Add_Clip: procedure

	arg area .

	tmp	= getclip('MM_EXPORT')

	if find(tmp, area)=0 then call setclip('MM_EXPORT', tmp area)

return


Add_EC: procedure Expose system.

	arg mode, zone, id, net, node

	addr = zone':'net'/'node'.0'

	MM_GetNodelistNode addr 'tmp'
	if rc~=0 then return

	line = mode'EC' left(zone':'id, 14) addr

	call Log('  ->' line)
	MM_AddToStem 'system.ecs' 'line'

return


Add_InfoText: procedure Expose msg. system.

	parse arg mode, area

	selected.	= 0
	v_area		= system.flame.v_area

	do while selected.count=0
		MM_MultiSelReq 'system.mod.'v_area'.rules.text' 'selected' '"'system.text.selreq'"' 'NUM'
	end

	if mode='NOTE' then typ	= 'Notify'
	else								typ	= mode

	msgfile = Get_Path('Text.'typ'User')

	call Read_File(msgfile, 1)

	do n=0 to selected.count-1
		tmp = selected.n

		call RW_Stem('R', Get_Path(system.mod.v_area.rules.file.tmp), 'msg.read', 'A')
	end

	call RW_Stem(  'R', Get_Path('Sign'), 'msg.read', 'A')

return


Add_Msg: procedure Expose msg. system.

	arg type, msg

	call Add_Arc()
	call Add_Arc(center('  'Replace_Embedded(system.text.msg)'  ', 80, '='))
	call Add_Arc()
	call Add_Arc('From:' left(msg.type.from, 29) msg.type.fromaddr)
	call Add_Arc('To  :' left(msg.type.to,   29) msg.type.toaddr  )
	call Add_Arc('Date:' msg.type.date)
	call Add_Arc('Subj:' msg.type.subj)
	call Add_Arc()
	call Add_Arc()

	do n=0 to msg.type.head.count-1
		call Add_Arc('@'compress(msg.type.head.n, '1'x))
	end

	do n=0 to msg.type.text.count-1
		call Add_Arc(msg.type.text.n)
	end

	do n=0 to msg.type.foot.count-1
		call Add_Arc('@'compress(msg.type.foot.n, '1'x))
	end

	call Add_Arc()
	call Add_Arc()
	call Add_Arc()

return


Add_Text: procedure Expose msg.

	parse arg txt

	MM_AddToStem 'msg.mail.text' 'txt'

return


Archive_Msg: procedure Expose msg. system.

	parse arg mode, area, v_area

	call Log('  Archiving msg to' system.flamefile'...')

	call Add_Arc()
	call Add_Arc()
	call Add_Arc(strip(center('***' upper(compress(system.button.mode, '*_')) '***', 80), 't'))
	call Add_Arc()

	call Add_Msg('ECHO', 'ORIGMSG' )
	call Add_Msg('MAIL', 'REPLYMSG')

	call Add_Arc()
	call Add_Arc(copies('*', 80))
	call Add_Arc()
	call Add_Arc()

	call RW_Stem('W', system.flamefile, 'msg.arc', 'A')

return


break_c:; break_d:; break_e:; break_f:; halt:

	signal off break_c
	signal off break_d
	signal off break_e
	signal off break_f
	signal off halt

	return_code		=	5
	error_line    = 0
	error_msg			= 'Execution halted!!!'
	rc						= 0
signal Exit


Check_Log: procedure Expose msg. system.

	arg area, nr, v_area, is_last_msg

	call RW_Stem('R', Get_Path(system.mod.v_area.flamelog), 'system.log')

	if Search_Log(overlay(system.date.pattern, system.log.line, 83))>0 then
		do
			call Request_Choice('WASFLAMED', 'CANCEL', '0')

			if is_last_msg then
	      if Request_Choice('DELREPLY', '*YES NO', '1 0') then
					MM_DeleteMsg area nr

			call Quit(1, msg.echo.from 'was already flamed due to this msg!')
		end
	else
		do
			pat			 			= left(system.log.line, 61)'  'system.date.pattern'  'system.date.pattern'  '
			msg.notes			= Search_Log(pat'N#?')
			msg.flames		= Search_Log(pat'F#?')
			msg.suspended	= Search_Log(pat'S#?')

			if msg.flames=system.mod.v_area.maxflames-1 then call Request_Choice('MAXFLAMES', 'OK', '0')

			file							= system.mod.v_area.flamefile || Make_Valid(msg.echo.from)
			p									= lastpos('/', file)
			path							=	left(file, p)
			file							= strip(substr(file, p+1, 32))
			system.flamefile	= path || file
			ret								= 1

			if msg.notes+msg.flames+msg.suspended>0 then
				do until ret=0
					ret = Request_Choice('HASFLAMES', 'CANCEL SHOWFLAMES SHOWLOG *OK', '1 2 3 0')

					select
						when ret=1 then call Quit(5, 'Aborted by user!')

						when ret=2 then call Editor(system.flamefile)

						when ret=3 then
							do
                txt 		= system.text.showlog'\n'
                flames.	= 0

								MM_SearchInStem 'system.log' 'flames' '"#?'msg.echo.from'#?"' 'STR'

								do n=0 to flames.count-1
									parse var flames.n . 83 yy '-' mm '-' dd . 91 . 100 type . 103 subj 153 .

									txt = txt type'  'dd'.'mm'.'yy'  'subj'\n'
								end

								system.req.showlog	= txt

  							call Request_Choice('SHOWLOG', 'OK', '0')
							end

						otherwise nop
					end
				end
			else call Request_Choice('NOFLAMES', 'OK', '0')
		end

return


Check_Node: procedure

	arg tmp_node

	MM_GetNodelistNode tmp_node 'tmp'

return rc~=0


Command: procedure Expose system.

	parse arg cmd

	address command cmd

	if rc>5 then call Log('*** WARNING: Command "'cmd'" returned' rc'.')
return rc


Convert_Date: procedure

	arg day month year .

return year'-'right(find('JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC', month), 2, '0')'-'day


Edit_Msg: procedure Expose msg. system.

	parse arg area, nr, flgs, msg.mail.file

	call Log('  Editing msg to' msg.mail.to msg.mail.toaddr'...')

	msg.mail.flags = Merge_Var(msg.mail.flags, flgs)

	call RW_Stem('W', msg.mail.file, 'msg.mail.text')
	call RW_Stem('W', msg.mail.file, 'msg.read',		'A')

	call Editor(msg.mail.file)

  tmp = msg.mail.text.count-1

	if msg.mail.text.tmp~=system.tearline then
		do
			tmp.0     = system.tearline
			tmp.count	= 1

			call RW_Stem('W', msg.mail.file, 'tmp', 'A')
		end

	MM_EditMsg area nr 'msg.mail'
	MM_ReadMsg area nr 'msg.mail'

	call Log('   -> Done.')

return


Editor: procedure Expose system.

	parse arg file

	call Command(replace(system.mm.editor, file, '%s'))

return


Exit:

	select
		when return_code>=40 then error = 'INTERNAL-ERROR:'
		when return_code>=30 then error = 'IO-ERROR:'
		when return_code>=20 then error = 'ERROR:'
		when return_code>=10 then error = 'WARNING:'
		when return_code>=5  then error = 'INFO:'
		otherwise									error = ''
	end

	txt = '***' strip(error error_msg) '***'

	if system.req & return_code>5 then
    do
			if return_code<10 then button = 'OK'
			else									 button = 'CANCEL'

			system.req.err	= '\c'txt

			call Request_Choice('ERR', button, '0')
		end

  call Log()
	call Log(txt, '+')
	call Log(,'\')

	call setclip('MM_LogPre', system.mm.logpre)

exit return_code


Flame: procedure Expose system.

	parse arg area, nr

	call Log(' Processing area' area', msg #'nr'...')

	v_area	= Make_Valid(area)

	if ~system.mod.v_area then
    do
			call Request_Choice('NOCFG', 'CANCEL', '0')
			call Quit(5, 'No config found for area' area'!!!')
		end

	matrix = Get_MailArea(system.area.addr)

	MM_GetAreaInfo matrix 'matrix'

	MM_ReadMsg area		nr						'msg.echo'
  MM_ReadMsg matrix	matrix.himsg	'msg.mail'

	parse var msg.echo.date msg.echo.datum '  ' msg.echo.time
	parse var msg.mail.date msg.mail.datum '  ' msg.mail.time

	msg.echo.areatag	= area
	msg.echo.msgno		= nr
	msg.mail.areatag	= matrix
	msg.mail.msgno		= matrix.himsg
	tmp								= strip(left(compress(Replace(upper(msg.echo.subj), '', 'RE:')), 20))
	subj_not_ok				= pos(tmp,   compress(Replace(upper(msg.mail.subj), '', 'RE:')))=0 & strip(msg.echo.subj)~=''
  not_last_msg			= (msg.echo.from~=msg.mail.to | upper(msg.echo.fromaddr)~=upper(msg.mail.toaddr),
											|	subj_not_ok)  & find('GATE UUCP', upper(left(msg.mail.to, 4)))=0

	system.log.line 	= left(msg.echo.from, 30) left(msg.echo.fromaddr, 30)'  'Convert_Date(msg.echo.datum),
											msg.echo.time'  'Convert_Date(msg.mail.datum) msg.mail.time'  ?  'msg.echo.subj

	call Check_Log(area, nr, v_area, ~not_last_msg)

	call Log('  Checking msgs...')

	if not_last_msg then
    do
			call Log(' '	left(area '#'nr':',			36) matrix '#'matrix.himsg':')
			call Log('  '	left(msg.echo.from,			35) msg.mail.to    )
			call Log('  '	left(msg.echo.fromaddr, 35) msg.mail.toaddr)

			if subj_not_ok then call Log('   -> *** Subject differs! ***')

			call Request_Choice('NOTFOUND', 'CANCEL', '0')
			call Quit(5, 'Msgs do not match.')
		end

	call Log('   -> Msgs do match!')

  mode = Request_Choice('FLAME', 'CANCEL SUSPEND NOTE FLAME', '_ SUSPEND NOTE FLAME')
	if mode='' then call Quit(2, 'Aborted by user.')

  call Log_Flame(		mode, area,		v_area)
	call Add_InfoText(mode, area,		v_area)
	call Send_Flame(	mode, matrix, matrix.himsg, area, v_area)

return


Get_Arg: procedure Expose args

  arg keyword, rnr

	p 	= find(upper(args), keyword)
	ret	= 0

	if rnr>0 then
		if p>0 then
			do
				ret		= subword(args, p+1, rnr)
				args	= delword(args, p, p+rnr)
	    end
		else ret			= ''
	else
		if p>0 then
			do
				ret		= 1
				args	= delword(args, p, 1)
			end

	args	= strip(args)

return ret


Get_Boss: procedure Expose system.

	parse arg left '.' . '@' right

	boss					= left'.0@'right
	system.notify	= 'Boss'

	if Check_Node(boss) then
		if Request_Choice('NOTIFYNF', '*YES NO', '1 0') then boss = Request_Address(boss)
		else                                                 boss = ''

return boss


Get_EC: procedure Expose system.

	parse arg mode, zone ':' net '/' node '.' point '@' domain .

	call RW_Stem('R', system.prg.ecs, 'tmp')

	if mode='NEC' then	id = net
	else								id = left(net, 2)

	pattern				= '"'mode zone':'id '#?"'
	system.notify	= mode
	result.				= ''

	MM_SearchInStem 'tmp' 'result' pattern 'STR'

	if result.count>0 then	ec = substr(result.0, 20)'@'domain
	else										ec = ''

	if Check_Node(ec) then
		if Request_Choice('NOTIFYNF', '*YES NO', '1 0') then ec = Request_Address(ec)
		else																								 ec = ''

return ec


Get_Hub: procedure Expose system.

	parse arg node '@' domain . 1 base '/' .

	system.notify	= 'HUB'

	call Command(system.getnode node '>'system.tmpfile)

	call RW_Stem('R', system.tmpfile, 'tmp')
	call delete(system.tmpfile)

  parse value upper(tmp.3) with . 'HUB' hub .

	if hub>'' then hub = base'/'hub'.0'domain

	if Check_Node(hub) then
		if Request_Choice('NOTIFYNF', '*YES NO', '1 0') then hub = Request_Address(hub)
		else                                                 hub = ''

return hub


Get_MailArea: procedure Expose system.

	arg . '@' domain

	MM_GetAreas 'tmp' 'MAIL'

	do n=0 to tmp.count-1
		MM_GetAreaInfo tmp.n 'info'
		parse value upper(info.addr) with . '@' dmn

		if domain=dmn then return tmp.n
	end

return tmp.0


Get_Name: procedure

	parse arg address

	MM_GetNodelistNode address 'tmp'

	if rc>0 then	ret = 'Sysop'
	else					ret = tmp.sysop

return ret


Get_Path: procedure Expose system.

	parse arg name

	if pos(':', name)=0 then
		do
			tmp		= system.flame.v_area
			name	= system.mod.tmp.path || name
		end

return name


Get_Version: procedure

	parse arg mode

	parse value sourceline(3-mode) with . . ver .
	parse var ver tst 'ß' .

	if ~datatype(strip(tst, 'b', '/ce '), 'N') then
		if ~mode then ver = Get_Version(1)
		else exit 99

return ver


Header:

	call Log(,'/')
	call Log('*** ' system.prg.id ' ***', '+')
	call Log(system.prg.cr)
	call Log()

return


Init:

	system.							= 0

	MM_GetTaskPri					'system.taskpri'
	call									pragma('p', system.taskpri)
	MM_GetCfgPaths				'system.mm'
	MM_Version						'system.mm'

	system.prg.ver			= Get_Version(0)
	system.prg.name			= 'MM_Flame'
	system.prg.id				= system.prg.name 'v'system.prg.ver
	system.prg.cfgdir		= 'MM:Config/'system.prg.name'/'
	tmp               	= system.prg.cfgdir || system.prg.name'.'
	system.prg.cfg			= tmp'cfg'
	system.prg.cr				= '(C) 1995/96 Robert Hofmann'
	system.prg.ecs			= tmp'ECs'
	system.prg.script		= 'MM:Rexx/'system.prg.name'.rexx'
	system.tearline			= '---' system.prg.id'  'system.prg.cr
	system.tmpfile			= 'T:'system.prg.name'.tmp'
	system.invalid			= xrange('0'x, '@') || xrange('[', 'FF'x)
	system.replace			= copies('_', length(system.invalid))
	system.mm.logpre  	= getclip('MM_LogPre')
	system.prg.logpre 	= system.mm.logpre'|'
	call                	setclip('MM_LogPre', system.prg.logpre)
	system.date.pattern	= '??-??-?? ??:??:??'


	call Include_Lib('rexxsupport')
return


Include_Lib: procedure

	parse arg lib, prio
	if right(upper(lib), 8)~='.LIBRARY' then lib=lib'.library'
	if prio='' then prio=0

	if ~show('l', lib) then
		if ~addlib(lib, prio, -30, 0) then
			do
				say '*** ERROR: Could not open' lib'!!! ***'
				exit 10
			end
return


IOerr:

	signal off ioerr

	return_code		= 20
	error_line    = sigl
	error_msg			= 'IO-error' rc 'at line' sigl '['errortext(rc)']')
	rc						= 0
signal Exit


Log: procedure Expose system.

	parse arg text, pre

	tmp		= word('PRG MM', (pre~='')+1)
	text	= system.tmp.logpre || pre' 'text

	MM_WriteLog 'text' '2'
return


Log_Flame: procedure Expose msg. system.

	arg mode, area, v_area

	tmp							= word('FLAMES NOTES SUSPENDED', pos(left(mode, 1), 'FNS'))
	msg.tmp					= msg.tmp+1
	system.log.line = overlay(mode, system.log.line, 102, 1)

	MM_AddToStem	'system.log' 'system.log.line'
	MM_SortStem 	'system.log'

	file	= Get_Path(system.mod.v_area.flamelog)
	bak		= file'.bak'

	call delete(bak)
	call rename(file, bak)
	call RW_Stem('W', file, 'system.log')

return


Make_Valid: procedure Expose system.

	arg string

return strip(translate(string, system.replace, system.invalid), 'b', '_ ')


Merge_Var: procedure

	parse arg var, merge

	do while merge>''
		parse var merge check merge

		if find(var, check)=0 then var = var check
	end

return var


Parse_Args: procedure Expose args system.

	args							= strip(translate(args, '  ', '9'x'='))
	system.flame			= Get_Arg('FLAME',			0)
	system.postrules	= Get_Arg('POSTRULES',	0)
	system.scanecs		= Get_Arg('SCANECS',		0)

	select
		when system.flame+system.postrules+system.scanecs>1 then signal Usage

		when system.flame then
			do
				system.req	= 1

				parse var args system.flame.area system.flame.msg .

				MM_GetAreaInfo system.flame.area 'system.area'

				if rc~=0 | ~datatype(system.flame.msg, 'N') then signal Usage

				system.flame.v_area	= Make_Valid(system.flame.area)
			end

		when system.postrules then
			do
				system.postrules.area	= args

 				MM_GetAreaInfo system.postrules.area 'system.area'

				if rc~=0 then signal Usage
			end

		when system.scanecs then
			do
				parse var args system.scanecs.domain system.scanecs.nlzone .

				if system.scanecs.nlzone=''							then system.scanecs.nlzone = 0
				if ~datatype(system.scanecs.zone, 'N')	then signal Usage
			end

		otherwise signal Usage
	end

return


Path: procedure

   parse arg path .
   if right(path,1) ~= '/' & right(path,1) ~= ':' then path = path'/'
return path


Post_Rules: procedure Expose system.

	parse arg echoarea

	v_echo 							= Make_Valid(echoarea)
	system.flame.v_area	= v_echo

	call Log(' Posting rules in area' echoarea'...')

	msg.head.count	= 0
	msg.text.count	= 0
	msg.foot.count	= 0
	msg.from				= system.mod.v_echo.postrules.from
	msg.to					= system.mod.v_echo.postrules.to
	msg.subj				= system.mod.v_echo.postrules.subj
	msg.flags				= system.mod.v_echo.postrules.flags
	msg.tear				= system.prg.id
	msg.file				= system.tmpfile

	if msg.from='' | msg.from=0 then MM_GetSysop 'msg.from'

	if Command('c:join' Get_Path(system.mod.v_echo.rules) Get_Path('Sign') 'as' msg.file)=0 then
		do
	    MM_WriteMsg echoarea 'msg'
			MM_Export		echoarea

      call Log('  -> Done.')
		end
	else call Quit(25, 'Unable to post rules!!!')

return


Quit:

	parse arg return_code, error_msg

	error_line    = 0
	rc						= 0
signal Exit


Read_File: procedure Expose msg. system.

	parse arg file, new

	if new then msg.read.count = 0

  if RW_Stem('R', file, 'text') then call Quit(23, 'Unable to open "'file'" for read!')

	do n=0 to text.count-1
		tmp = Replace_Embedded(text.n)

		MM_AddToStem 'msg.read' 'tmp'
	end

return


Replace: procedure

	parse arg string, new, old

	do while index(string, old)~=0
		interpret "parse var string l '"old"' r"
		string = l || new || r
	end

return string


Replace_Embedded: procedure Expose msg. system.

	parse arg text

	text	= translate(Replace(Replace(text, 'a'x, '\n'), '"', '\q'), '', '\')

	if pos('%', text)=0 then return text

	text	= Replace(text, msg.echo.areatag,		'%ea' )
	text	= Replace(text, msg.echo.date,			'%ed' )
	text	= Replace(text, msg.echo.fromaddr,	'%efa')
	text	= Replace(text, msg.echo.from_first,'%eff')
	text	= Replace(text, msg.echo.from,			'%ef' )
	text	= Replace(text, msg.echo.subj,			'%es' )
	text	= Replace(text, msg.echo.toaddr,		'%eta')
	text	= Replace(text, msg.echo.to_first,	'%etf')
	text	= Replace(text, msg.echo.to,				'%et' )
	text	= Replace(text, msg.mail.areatag,		'%ma' )
	text	= Replace(text, msg.mail.date,			'%md' )
	text	= Replace(text, msg.mail.subj,			'%ms' )
  text  = Replace(text, msg.mail.toaddr,    '%mta')
	text  = Replace(text, msg.mail.to_first,	'%mtf')
	text  = Replace(text, msg.mail.to,				'%mt' )
	text	= Replace(text, msg.flames,					'%nf' )
	text	= Replace(text, msg.notes,					'%nn' )
	text	= Replace(text, msg.suspended,			'%ns' )
	text  = Replace(text, system.address,			'%sfa')
	text  = Replace(text, system.sysop,				'%sf' )
  text  = Replace(text, system.notify,			'%p'  )

return text


Request_Address: procedure Expose system.

	parse arg value, mode

	if mode~='' then return value

	check	= 1

	do while check
		addr	= Request_String('ADDRREQ', value)

		if addr~='' then check = Check_Node(addr)
		else             check = 0
	end

return addr


Request_Choice: procedure Expose msg. system.

	parse arg tvar, bvar, ret_vals

	title 	= system.prg.name'-requester'
	text		= Replace_Embedded(system.req.tvar)
	buttons	= ''

	do n=1 while bvar>''
		parse var bvar add bvar

		if left(add, 1)='*' then
			do
				tmp = '*'
        parse var add . 2 add .
			end
		else tmp = ''

		buttons	= buttons || tmp || system.button.add'|'
	end

	if n=1 then tmp = '*'
	else				tmp	= ''

	buttons	= tmp || strip(buttons, 'b', '|')

	if length(text)<40 then text = center(text, 40)

	MM_Requester title 'text' 'buttons'

	if rc=0 then rc=words(ret_vals)

return compress(word(ret_vals, rc), '_')


Request_String: procedure Expose system.

	parse arg var, value

	title = Replace_Embedded(system.text.var)

	MM_StringReq '"'title'"' 'value'

	if rc>0 then value=''

return strip(value)


RW_Stem:

	parse arg iomode, rwfile, rwstem, rwmode

	upper				iomode rwmode
	iomode.r	= 'read'
	iomode.w	= 'write'
	rwmode.		= ''
	rwmode.a	= 'APPEND'

	'MM_'iomode.iomode'Stem' rwfile rwstem rwmode.rwmode
	if RC~=0 then call Log('*** IO-ERROR: Unable to' iomode.iomode '"'rwfile'"!')

	drop iomode iomode. rwfile rwstem rwmode rwmode.
return RC~=0


Search_Log: procedure Expose msg. system.

	parse arg pattern

	result.	= 0

	MM_SearchInStem 'system.log' 'result' '"'pattern'"' 'NUM'

return result.count


Scan_ECs: procedure Expose system.

	call Log(' Searching for nodelist of domain' system.scanecs.domain'...')

	call Command(system.shownl '>'system.tmpfile)

	call RW_Stem('R', system.tmpfile, 'tmp')
	call delete(system.tmpfile)

  dmn				= upper(system.scanecs.domain)
	list  		= system.nl.dmn
	nodelist	= ''

	if list=0 then call Quit(13, 'No nodelist defined for domain' system.scanecs.domain'!!!')

	do n=1 to tmp.count-1
		parse value upper(tmp.n) with . 2 name . 2 check '.' .

		if check~=list then iterate

		nodelist	= name
		leave
	end

	if nodelist='' then call Quit(14, 'Nodelist for domain' system.scanecs.domain 'not found!!!')

	nodelist	= system.mm.nodelistdir || nodelist

	if system.scanecs.nlzone=0 then tmp	= 'all zones'
	else														tmp = 'zone' system.scanecs.nlzone

	call Log(' Scanning' nodelist "for *EC's of" tmp"...")

	if ~open(nl, nodelist, r) then
		call Quit(22, 'Unable to open "'nodelist'" for read!')

	start = 0

  do until eof(nl)
		parse value upper(readln(nl)) with line ';' .
		if line='' then iterate

		parse var line function . ',' node . ',' . ',' . ',' . ',' . ',' . ',' flags . ';' .

		select
			when function=''				then nop

			when function='HOST'		then
				do
					net		= node
					node	= 0
				end

			when function='REGION'	then
				do
					region	= node
					node		= 0
				end

			when function='ZONE' 		then
				do
					zone 		= node
					region	= node
					node		= 0
				end

      otherwise nop
		end

		if system.scanecs.nlzone>0 & zone~=system.scanecs.nlzone then
			if start then leave
			else					start = 1

		if pos('REC', flags)>0 then call Add_EC('R', zone, region, net, node)
		if pos('NEC', flags)>0 then call Add_EC('N', zone, net,    net, node)
	end

	call close(nl)

	MM_SortStem		'system.ecs'
	MM_CopyFile		system.prg.ecs system.prg.ecs

	call RW_Stem('W', system.prg.ecs, 'system.ecs')

return


Send_Flame: procedure Expose msg. system.

	parse arg mode, mailarea, nr, areatag, echoarea

	system.sysop		= msg.mail.from
	system.address	= msg.mail.fromaddr
	msgflags				= 'PVT' system.mod.echoarea.mode.flags
	boss.addr				= Get_Boss(msg.echo.fromaddr)
	boss.name				= Get_Name(boss.addr)
	ispoint					= msg.mail.to~=boss.name | upper(msg.mail.toaddr)~=upper(boss.addr)

	call Edit_Msg(mailarea, nr, msgflags, system.mm.tempfile)

	if mode='NOTE' then arc = Request_Choice('ARCMSG', 'YES *NO', '1 0')
	else								arc = 1

	if arc         then call Archive_Msg(mode, areatag, echoarea)

	select
		when mode='NOTE'	& ispoint		then notify = 'BOSS'
		when mode='NOTE'							then notify = ''
		when mode='FLAME'	& ispoint		then notify	= 'BOSS'
		when mode='FLAME'							then nofify	= 'HUB'
		when mode='SUSPEND'						then notify = 'BOSS HUB NEC REC'
		otherwise exit 999
	end

	if find(notify, 'BOSS')>0 & system.mod.echoarea.mode.send.boss then
		call Write_Msg(mailarea, nr, echoarea, mode, boss.name, boss.addr, msgflags, 'Boss')

	if find(notify, 'HUB')>0 & system.mod.echoarea.mode.send.hub then
		do
			hub.addr	= Get_HUB(boss.addr)
			hub.name	= Get_Name(hub.addr)

			call Write_Msg(mailarea, nr, echoarea, mode, hub.name, hub.addr, msgflags, 'HUB')
		end

	if find(notify, 'NEC')>0 & system.mod.echoarea.mode.send.nec then
		do
			nec.addr	= Get_EC('NEC', boss.addr)
			nec.name	= Get_Name(nec.addr)

			call Write_Msg(mailarea, nr, echoarea, mode, nec.name, nec.addr, msgflags, 'NEC')
		end

	if find(notify, 'REC')>0 & system.mod.echoarea.mode.send.rec then
		do
			rec.addr	= Get_EC('REC', boss.addr)
			rec.name	= Get_Name(rec.addr)

			call Write_Msg(mailarea, nr, echoarea, mode, rec.name, rec.addr, msgflags, 'REC')
		end

	if mode~='SUSPEND' & msg.flames=system.mod.echoarea.maxflames-1 then
		do
			mode	= 'WARN'

			call Write_Msg(mailarea, nr, echoarea, mode, msg.echo.from, msg.echo.fromaddr,,
										 msgflags, 'User', Get_Path('Text.WarnUser'), 'warning')

			if find(notify, 'BOSS')>0 then
				call Write_Msg(mailarea, nr, echoarea, mode, boss.name, boss.addr, msgflags, 'Boss',,
											 Get_Path('Text.WarnBoss'), 'warning')
		end

	call Request_Choice('CHECKMSGS', 'OK', '0')

return


Syntax:

	signal off syntax

	return_code		= 40
	error_line    = sigl
	error_msg			= 'Syntax-error' rc 'at line' sigl '['errortext(rc)']'
	rc						= 0
signal Exit


Usage:

	say
	say 'Usage: [RX]' system.prg.name 'FLAME     <areatag> <msgnumber>'
	say '   or: [RX]' system.prg.name 'POSTRULES <areatag>'
	say '   or: [RX]' system.prg.name 'SCANECS   <domain>  [zone]'
	say
	say 'E.g. : #BROWSEMENU "Flame" "rx MM:Rexx/MM_Flame FLAME %a %n" ""'
	say
call Quit(5, 'Please read the docs!')


Write_Msg: procedure Expose msg. system.

	parse arg mailarea, nr, echoarea, mode, name, address, flgs, person, msgfile, txt

	if address='' then
		do
			call Log('  * Unable to notify' person':' name'!!!')
			return
		end

	uperson 				= upper(person)
	msg.mail.to			= name
	msg.mail.toaddr	= address
	system.notify		= person

	parse var msg.mail.to msg.mail.to_first .

	if mode~='WARN' then req = 'NOTIFY'
	else                 req = 'WARN'uperson

  if ~Request_Choice(req, '*YES NO', '1 0') then return

	if txt~='' then txt = 'Sending' txt 'to'
	else						txt = 'Informing'

	call Log('  'txt person':' name address'...')

	MM_ReadMsg mailarea nr 'write'

	write.file				= system.mm.tempfile
	write.flags				= Merge_Var(write.flags, flgs)
	write.foot.count	= 0
	write.head.count	= 0
	write.subj				= write.to '%' write.toaddr
	write.to					= name
	write.toaddr			= address

	if msgfile='' then
    do
			if mode='NOTE' then typ = 'Notify'
			else								typ	= mode

			msgfile	= Get_Path('Text.'typ || uperson)
    end
	else write.text.count = 0

	call Read_File(msgfile, 1)

	select
		when mode='SUSPEND' then
			do
				write.text.count	= 0
				call RW_Stem('R', system.flamefile, 'msg.read', 'A')
			end

		when mode='WARN' then
			do
				write.text.count	= 0
				call RW_Stem('R', Get_Path('Sign'), 'msg.read', 'A')
			end

		otherwise nop
	end

	call RW_Stem('W', write.file, 'msg.read')
	call RW_Stem('W', write.file,	'write.text', 'A')

	call Editor(	write.file)

	tmp = write.text.count-1

	if write.text.tmp~=system.tearline then
		do
			tmp.0     = system.tearline
			tmp.count	= 1

			call RW_Stem('W', write.file, 'tmp', 'A')
		end

	MM_WriteMsg mailarea 'write'

	call Add_Clip(mailarea)
	call Log('   -> Done.')

return


                /********** Config related routines **********/



Add_Button: procedure Expose cpl. system.

	parse arg . '_' type ., text

	text	= Remove_Quotes(text)

  call Add_Cfg('system.button.'type, text)

return


Add_Cfg: procedure Expose cpl. system.

	parse arg var, val
	upper var

	if datatype(val, 'N') then	q = ''
	else												q = "'"

	line	= var'='q || translate(val, 'ø¶', '2227'x) || q

	MM_AddToStem 'cpl' 'line'

	interpret line

return


Add_Cfg_Stem: procedure Expose cpl. system.

	parse arg stem, value
	upper stem

	MM_AddToStem stem 'value'

	if find(cpl.stems, stem)=0 then cpl.stems = cpl.stems stem

return


Add_Flags: procedure Expose cpl. l system.

	arg var, text, args

	if upper(text)='NOTIFY' then var = var'NOTE'
	else												 var = var || text

	flags = ''

	if Get_Arg('CRASH', 0) then flags = flags 'CRASH'
	if Get_Arg('KILL',	0) then flags = flags 'KILL'
	if Get_Arg('RRR', 	0) then flags = flags 'RRR'

	if args~=''						 then
		call Quit(11, 'Unknown or duplicate keyword(s) "'args'" for Send'text'Flags at line' l)

	call Add_Cfg(var'.flags', strip(flags))

return


Add_FlameMode: procedure Expose cpl. l system.

	parse arg valid, var, text, args

	if upper(text)='NOTIFY' then var = var'NOTE'
	else												 var = var || text

	if pos('U', valid)>0 then
	  if Get_Arg('UPLINK', 0) then
			do
				call Add_Cfg(var'.send.boss',		1)
				call Add_Cfg(var'.send.hub',		1)
				call Add_Cfg(var'.send.uplink',	1)
			end

	if pos('N', valid)>0 then
		if Get_Arg('NEC', 0)		then call Add_Cfg(var'.send.nec',			1)

	if pos('R', valid)>0 then
		if Get_Arg('REC', 0)		then call Add_Cfg(var'.send.rec',			1)

	if pos('B', valid)>0 then
		if Get_Arg('BOSS', 0)		then call Add_Cfg(var'.send.boss',		1)

	if args~=''					 then
		call Quit(11, 'Unknown or duplicate keyword(s) "'args'" for Send'text 'at line' l)

return


Add_Req: procedure Expose cpl. system.

	parse arg . '_' type ., text

	text	= Remove_Quotes(text)

  call Add_Cfg('system.req.'type, text)

return


Add_RulesPart: procedure Expose cpl. system.

	parse arg var, file text

	call Add_Cfg_Stem(var'rules.file', strip(file))
	call Add_Cfg_Stem(var'rules.text', Remove_Quotes(text))

return


Add_Script: procedure Expose script.

	parse arg line

	MM_AddToStem 'script' 'line'

return


Add_Txt: procedure Expose cpl. system.

	parse arg . '_' type ., text

	text	= Remove_Quotes(text)

  call Add_Cfg('system.text.'type, text)

return


Compile_Cfg: procedure Expose system.

	call Log(' Reading & compiling config...')

  if RW_Stem('R', system.prg.cfg, 'cfg') then call Quit(21, 'Unable to read "'system.prg.cfg'"!')

	cpl.	      					= 0
	cpl.stems							= ''
	l											= 0
	system.cfg.buttons		= '#BUTTON_CANCEL #BUTTON_FLAME #BUTTON_NO #BUTTON_NOTE',
													'#BUTTON_OK #BUTTON_SUSPEND #BUTTON_YES #BUTTON_SHOWFLAMES',
                      	  '#BUTTON_SHOWLOG'

	system.cfg.reqs				= '#REQ_ARCMSG #REQ_CHECKMSGS #REQ_DELREPLY #REQ_FLAME',
													'#REQ_HASFLAMES #REQ_MAXFLAMES #REQ_NOTIFY #REQ_NOTIFYNF',
													'#REQ_NOCFG #REQ_NOTFOUND #REQ_NOFLAMES #REQ_WARNBOSS',
													'#REQ_WARNUSER #REQ_WASFLAMED'

	system.cfg.texts			= '#TEXT_ORIGMSG #TEXT_REPLYMSG #TEXT_SELREQ #TEXT_ADDRREQ',
													'#TEXT_SHOWLOG'

	system.button.ok			= '  _OK  '
	system.button.cancel	= '_CANCEL'


	do n=0 to cfg.count-1
		parse value strip(translate(cfg.n, ' ', '9'x)) with key args ';' .
		key		= upper(strip(key))
		args	= strip(args)
		l			= l+1

		select
			when key=''				then iterate

			when key='#AREA'	then
				do
					MM_GetAreaInfo args 'tmp'
					if RC~=0					then call Quit(11, 'Unknown area "'args'" at line' l'!')

          area			= Make_Valid(args)
					path			= system.prg.cfgdir || args'/'

					if ~exists(path)	then call Quit(11, 'Cfg-path "'path'" does not exist!')

					var_area	= 'system.mod.'area'.'
					call 				Add_Cfg('system.mod.'area,	1)
					call 				Add_Cfg(var_area'path',			path)
        end

			when key='FLAMEFILES' then
				do
					tmp = Get_Path(args)
					p		= lastpos('/', tmp)
					dir	= left(tmp, p)

					if ~exists(dir) then call Quit(11, 'Dir "'dir'" for FlameFiles at line' l 'does not exist!')

          parse value statef(tmp) with typ .

					if typ='DIR' then	tmp = path(tmp)
					else							tmp	= tmp'.'

					call Add_Cfg(var_area'flamefile',	tmp)
				end

			when key='FLAMELOG'						then call Add_Cfg(var_area'flamelog',		args)
			when key='INSERTRULES'				then call Add_RulesPart(var_area, 			args)

			when key='MAXFLAMES'					then
				do
					if ~datatype(args, 'N') | args=0 then
						call Quit(11, 'Invalid value "'args'" for MaxFlames at line' l'!!!')

					call Add_Cfg(var_area'maxflames', args)
				end

			when key='POSTRULESFLAGS'		then
				do
					if Get_Arg('KILL', 0) then flags = 'KILL'
					else                       flags = ''

					call Add_Cfg(var_area'postrules.flags', flags)

					if args~=''						 then
						call Quit(11, 'Invalid or duplicate flag(s) "'args'" for PostRulesFlags at line' l)
				end

			when key='POSTRULESFROM'		then call Add_Cfg(var_area'postrules.from',	Remove_Quotes(args))
			when key='POSTRULESSUBJECT'	then call Add_Cfg(var_area'postrules.subj',	Remove_Quotes(args))
			when key='POSTRULESTO'			then call Add_Cfg(var_area'postrules.to',		Remove_Quotes(args))

			when key='RULES'						then call Add_Cfg(var_area'rules', 										args)
			when key='SENDFLAME'				then call Add_FlameMode('NRU', 	var_area,	'Flame',		args)
			when key='SENDFLAMEFLAGS'		then call Add_Flags(						var_area,	'Flame',		args)
			when key='SENDNOTIFY'				then call Add_FlameMode('B', 		var_area,	'Notify',		args)
			when key='SENDNOTIFYFLAGS'	then call Add_Flags(						var_area,	'Notify',		args)
			when key='SENDSUSPEND'			then call Add_FlameMode('BNRU', var_area,	'Suspend',	args)
			when key='SENDSUSPENDFLAGS'	then call Add_Flags(						var_area,	'Suspend',	args)

			when find(system.cfg.buttons, key)>0 	then call Add_Button(key, args)

			when key='#GETNODE'					then call Add_Cfg('system.getnode',		args)

			when key='#NODELIST'				then
				do
					parse var args domain nodelist .

					if domain='' | nodelist='' then
						call Quit(11, 'Parameters unsuitable for #NODELIST at line' l'!!!')

					call Add_Cfg('system.nl.'domain, upper(nodelist))
        end

			when find(system.cfg.reqs, key)>0		then call Add_Req(key, args)
			when key='#SHOWNL'									then call Add_Cfg('system.shownl', args)
			when find(system.cfg.texts, key)>0	then call Add_Txt(key, args)

			otherwise call Quit(10, 'Unknown keyword "'key'" at line' l'!!!')
		end
	end

	call Set_Default('button')
	call Set_Default('req'   )
	call Set_Default('text'  )

	do until cpl.stems=''
		parse var cpl.stems stem cpl.stems
		stem = strip(stem)
		if stem='' then iterate

		code	= "do n=0 to" stem".count-1; call Add_Cfg('"stem".'n," stem".n); end;",
						"call Add_Cfg('"stem".count'," stem".count)"

		interpret code
	end

	MM_SortStem 'cpl'

  call RW_Stem('R', system.prg.script, 'script')
	MM_SearchInStem	'script' 'tmp' 'Cfg:' 'NUM'

	if tmp.count=0 then call Quit(22, system.prg.script 'was modified or not found! Please read the docs!')

	script.count	= tmp.0+1

	call Add_Script()

	line	= '9'x

	do n=0 to cpl.count-1
		tmp	= strip(cpl.n)

		if length(line tmp)>=1024	then
			do
				call Add_Script(strip(line, 't', '; '))
				line	= '9'x
			end

		line	= line || tmp';'
	end

	if length(line)>2 then call Add_Script(strip(line, 't', '; '))

	call Add_Script()
	call Add_Script('return')
	call Add_Script()

	call RW_Stem('W', system.prg.script, 'script')

  MM_CRCFile		system.prg.cfg 		'cfg_crc'
  MM_CRCFile		system.prg.script	'scr_crc'

	tmp = c2x(system.prg.ver) cfg_crc scr_crc

	MM_SetFileNote	system.prg.script	'tmp'

return


Set_Default: procedure Expose cpl. system.

	arg type

 	tmp = type'S'
	tmp	= system.cfg.tmp

	do while tmp~=''
		parse var tmp id '_' check tmp

		if system.type.check~=0 then iterate

		call Add_Cfg('system.'type'.'check, strip(id'_'check) 'is not defined!\nPlease read the docs!')
	end

return


Read_Cfg: procedure Expose system.

	parse value statef(system.prg.script) with . . . . . . . version cfg_crc scr_crc

	if ~datatype(version, 'X') then version = ''

	MM_CRCFile system.prg.cfg 'crc'

	if x2c(version)=system.prg.ver & crc=cfg_crc & ~system.forcecpl then
		do
			MM_CRCFile system.prg.script 'crc'

			if crc=scr_crc then
				do
					call Log(' Reading config...')
					call Cfg

					return
				end
		end

	call Compile_Cfg

return


Remove_Quotes: procedure

	parse arg text

	text = strip(text)

	if left(text, 1)='"' then text = substr(text, 2)

return strip(text, 't', '" ')


                                 /*** CFG ***/


Cfg:

return

