/*

                   $VER: MM_ImportPlus.rexx 0.72  (02.12.96)

                           (C) 1994-96 Robert Hofmann

*/

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

Main:

	call Include_Lib('rexxsupport')
	call Check_InProcess

	address 'MAILMANAGER'

	call Init
	call Header
	call Parse_Args(args)
	call Read_Cfg
	call Check_Args
	call Check_Status

	if system.autosuspend~=0 & system.suspended=0 & system.arg.resume=0 then
		do
			system.suspended=system.autosuspend
			call Set_Status('suspended', system.autosuspend)
		end

	ret = Check_Received()

	if ret=0 then
		do
			if ~system.forceimp then ret = Check_Mem()

			if ret=0 then
				do
					if ~system.forceimp		then
						if system.security	then call Security

					if system.received-system.badcnt>0 | system.forceimp then
						do
							if system.sortbundles then call Sort_Bundles

							call Import

							ret = system.badcnt>0
						end
					else call Execute('NTD')
				end
		end
	else call Execute('NTD')

	tmp	= system.autosuspend

	if tmp~=0 then
		if system.suspended~=tmp then
			do
				if tmp=-1 then tmp	= ''

				call Set_Status('suspended', system.autosuspend)
			end

call Quit(ret, system.prg.id 'ended')


Add_Received: procedure Expose system.

	parse arg 1 id 3 char, line

	tmp	= find(system.week, id) || char line

	MM_AddToStem 'system.received' 'tmp'

return


AreaManager_1: procedure Expose system.

	MM_GetAreas 'areas' 'ECHO'

	system.am.lastcount = areas.count

return


AreaManager_2: procedure Expose system.

	MM_GetAreas 'areas' 'ECHO'

	new = areas.count>system.am.lastcount

	if new then call setclip('MM_AREAFIXMANAGER_CHECK', system.am.lastcount)

return new


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_Args: procedure Expose system.

	tmp = 'Too many arguments!!!'

	select
		when	system.arg.disable	& system.arg.enable				then call Quit(23, tmp)
		when	system.arg.resume		& system.arg.suspend~=0		then call Quit(23, tmp)
		when (system.arg.disable	| system.arg.enable)	&,
				 (system.arg.resume		| system.arg.suspend~=0)	then call Quit(23, tmp)
		when	system.arg.tickimp	&	system.arg.notickimp		then call Quit(23, tmp)

		when system.arg.disable			then call Disable_Import
		when system.arg.enable			then call  Enable_Import
		when system.arg.resume			then call  Resume_Import
		when system.arg.suspend~=0	then call Suspend_Import

		otherwise nop
	end

return


Check_InProcess: procedure Expose system.

	name	= 'MM_ImportPlus'

	if ~openport(name) then	call Quit(9, 'Another' name 'is already in process!')

return


Check_Mem: procedure Expose system.

	if system.minfree.chip+system.minfree.fast=0 then return 0

	call Log(' Checking memory...')

	call Command('avail flush chip  >'system.tmpfile)
	call Command('avail       fast >>'system.tmpfile)

	MM_ReadStem system.tmpfile 'check'

	call delete(system.tmpfile)

	check.0 = (check.0+512)%1024
	check.1 = (check.1+512)%1024
	mem			= '(CHIP:' check.0'kB, FAST:' check.1'kB)'

	if check.0<system.minfree.chip | check.1<system.minfree.fast then
		do
			call Log('  -> Memory below minimum size for import' mem'. Aborted!')
			ret = 7
		end
	else
		do
			call Log('  -> Enough memory left for import' mem'.')
			ret = 0
		end

return ret


Check_Received: procedure Expose system.

	call Log(' Checking for received mail...')

	ret	= ~system.forceimp*5

	call Command('c:list >'system.tmpfile system.mm.inbound 'p' system.pattern.all 'lformat "%m %e"')

	MM_ReadStem system.tmpfile 'tmp'
	call delete(system.tmpfile)

	system.received	= 0
	total						= 0

	do n=0 to tmp.count-1
		if left(tmp.n, 1)='!' then iterate

		parse value upper(tmp.n) with name ext .

		if length(ext)~=3 then
			do
				old_ext	= ext

				parse var ext ext ',' dupnr .
				if ~datatype(dupnr, 'N') then iterate

				chk	= 0
				day = strip(left(ext, 2))
				old = system.mm.inbound || name'.'old_ext
				drop	bundle


				select
					when find('PKT TIC', ext) then
						do
							new = system.mm.inbound || name'.'ext
              chk = rename(old, new)

							do while ~chk
								new	= system.mm.inbound || compress(time(), ':')'00.'ext
	              chk = rename(old, new)
								call	delay(50)
							end
						end

					when find(system.bundle.days, day)>0 then
						do m=1 to length(system.bundle.postfx) while ~chk
							ext = day || substr(system.bundle.postfx, m, 1)
							new = system.mm.inbound || name'.'ext
							chk = rename(old, new)
						end

					otherwise nop
				end

				if chk then call Log('  ->' name'.'old_ext 'renamed to' name'.'ext)
				else        iterate
			end

		file      			= name'.'ext
		full_file				= system.mm.inbound || file
		packet					= ext='PKT'
		tick						= ext='TIC'
		system.mailimp	= system.mailimp | ~tick
		system.tickimp	= system.tickimp | tick
		bundle					= ~packet & ~tick

		parse value statef(full_file)'0 0' with . len . . date time . desc

		klen						= (len+512)%1024

		if len=0 then
			do
				if delete(full_file) then call Log('  ->' file 'is empty, deleted.')
				iterate
			end

		if tick	then len = 102400

		if (bundle | tick) & (system.suspended=-1 | (system.suspended>0 & klen>=system.suspended)) then
			do
				wait_file	= system.mm.inbound'Wait.'translate(file, '_', '.')

				if rename(full_file, wait_file) then call Log('  -> Suspending' file right(klen'K', 6))
				else                                 call Log('*** IO-ERROR: Unable to suspend' file'!!!')

				iterate
			end

		if system.sortbundles & bundle 			then call Add_Received(ext, file date time strip(desc))

		system.received = system.received+1
		total						= total+len
	end

	rec	= (total+512)%1024

	select
		when system.received=0 then call Log('  -> Nothing to import.')

		when rec<system.minreceived & system.minreceived>0 then
			do
				call Log('  -> Not enough to import ('rec'kB).')
				ret	= 6
			end

		otherwise
			do
				call Log('  ->' rec'kB to import.')
				ret	= 0
			end
	end

	call Log(' ==> Done.')

return ret


Check_Status: procedure Expose system.

	call Get_Status

	select
		when system.autosuspend~=0									then nop
		when system.disabled												then call Quit(8, 'Import disabled!')
		when system.suspended~=0 & ~system.susplog	then call Log(' Import is still suspended...')
		otherwise																				 call Resume_Import('CHECK')
	end

return


Command: procedure Expose system.

	parse arg cmd

	address command cmd

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


Disable_Import: procedure Expose system.

	call Get_Status

	if system.disabled then call Quit(8, system.prg.name 'was already disabled!')

	call Set_Status('disabled')

return


Enable_Import: procedure Expose system.

	call Get_Status

	if ~system.disabled then call Quit(8, system.prg.name 'was not disabled!')
	else call Set_Status()

return


Execute: procedure Expose system.

	arg part

	if system.cmd.part.count=0 then return

	tmp	= part'-commands'

	call Log('Executing' tmp'...', '|-')

	do n=0 to system.cmd.part.count-1
		call Command(translate(system.cmd.part.n, '2227'x, 'ø¶'))
	end

	call Log('==>' tmp 'finished.', '|-')
	call Log()

return


Exit:

  if return_code~=9 then
		do
			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 = 'CONFIG-ERROR:'
				otherwise									error = ''
			end

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

			if host~=0 then
				do
				  call Log()
					call Log(tmp, '+')
					call Log(,'\')

					if system.import=1 then
						do
							MM_Free
							MM_WriteStats
						end

					MM_CloseLog
				end
			else say tmp

			call setclip('MM_LogPre', system.mm.logpre)
		end
	else say '***' error_msg '***'

exit return_code


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	= '0'x
	else
		if p>0 then
			do
				ret		= 1
				args	= delword(args, p, 1)
			end

	args	= strip(args)

return ret


Get_Status: procedure Expose system.

	if open(in, system.prg.env, r) then
		do
			line	= upper(readln(in))
			call close(in)
		end
	else line = ''

	parse var line sts val .

	system.disabled		= 0
	system.suspended	= 0

	select
		when sts=''						then nop
		when sts='DISABLED'		then system.disabled = 1
		when sts='SUSPENDED'	then
			do
				if ~datatype(val, 'N') then val = -1

				system.suspended	= val
			end
		otherwise call Quit(25, 'Unknown value in' system.prg.env': "'sts'"!!!')
	end

	system.status = sts

return


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: procedure Expose system.

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

return


Import: procedure Expose system.

	call Wait_AreasWindow
	call Execute('BEFORE')
	call AreaManager_1

	system.dotickimp	= (~system.notick & ~system.arg.notickimp) | (system.notick & system.arg.tickimp) |,
											system.forceimp
	system.import			= 1
	rc_imp						= 0

	if system.iconify	then Hide

	if system.mailimp | system.forceimp then
		do
			MM_Import; rc_imp = rc
		end

	if (system.tickimp | getclip('MM_ImportPlus_TickImport')=1) & system.dotickimp then
		do
			call setclip('MM_ImportPlus_TickImport')
			MM_ImportTicks; rc_tic = rc
		end

	am	= AreaManager_2()
	tk	= system.tickimp & system.dotickimp

	parse value c2b(d2c(rc_imp)) with 7 em 8 nm 9 .

	if system.forceimp then
		do
			nm	= 1
			em	= 1
			tk	= 1
		end

	if nm+em+am+tk>0	then
		do
			call Log()

			if nm 					then call Execute('NETMAIL' )
			else if am			then call Execute('AREAFIX' )
			if em 					then call Execute('ECHOMAIL')
			if nm | em | tk	then call Execute('BOTH'    )
			if tk						then call Execute('TICK')
		end

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


Init:

	system.								= 0

	MM_GetTaskPri						'system.taskpri'
	call										pragma('p', system.taskpri)

  system.prg.name				= 'MM_ImportPlus'
	system.prg.ver				= Get_Version(0)
	system.prg.id					= system.prg.name 'v'system.prg.ver
	system.prg.cfg				= 'MM:Config/'system.prg.name'.cfg'
	system.prg.cr					= '28432920313939342D39362020526F6265727420486F666D616E6E'x
	system.prg.env				= 'ENV:'compress(system.prg.name, '_')
	system.prg.script			= 'MM:Rexx/'system.prg.name'.rexx'
	system.bundle.days		= 'MO TU WE TH FR SA SU '
	system.bundle.postfx	= xrange('0', '9') || xrange('A', 'Z')
	tmp.name							= '(????????|#?.#?.#?.#?)'
	tmp.bundle						= '(MO|TU|WE|TH|FR|SA|SU)([0-9]|[a-z]|[A-Z])#?'
	tmp.bundle						= '('tmp.bundle'|'tmp.bundle',[0-9]#?)'
	tmp.pkt								=	'(PKT|TIC)'
	tmp.pkt								=	'('tmp.pkt'|'tmp.pkt',[0-9]#?)'
	system.pattern.bundle	= tmp.name'.('tmp.bundle')'
	system.pattern.all		= tmp.name'.('tmp.bundle'|'tmp.pkt')'
	system.tmpfile				= 'T:'system.prg.name'.tmp'
	system.status					= ''
	p											= pos(upper(left(date('w'), 2)), system.bundle.days)
	system.week						= substr(system.bundle.days, p+3) || left(system.bundle.days, p+1)

	MM_GetCfgPaths				'system.mm'

	call Set_LogPrefix

  drop p tmp. version
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


Move_Bad: procedure Expose system.

	parse arg file, full_file, from, reason, . . . . desc

  call Log(' ' file 'from' from 'failed!' reason'! Moved to' system.mm.baddir'...')
	call writech(stdout, '7'x)

	desc					= reason'!'desc
	dest_file			= system.mm.baddir || file
	system.badcnt = system.badcnt+1

	MM_SetFilenote full_file 'desc'
	MM_MoveFile full_file dest_file

return


Parse_Args: procedure Expose system.

	arg args

	system.arg.disable		= Get_Arg('DISABLE',			0)
	system.arg.enable			= Get_Arg('ENABLE',				0)
	system.arg.resume			= Get_Arg('RESUME',				0)
	system.arg.tickimp		= Get_Arg('TICKIMPORT',		0)
	system.arg.notickimp	= Get_Arg('NOTICKIMPORT',	0)
	system.forcecpl				= Get_Arg('CPLCFG',				0)
	system.forceimp				= Get_Arg('FORCEIMPORT',	0)

	tmp 									= Get_Arg('SUSPEND',			1)
	if tmp=''		then tmp	= -1
	if tmp='0'x	then tmp	= 0
	system.arg.suspend		= tmp

	if args~='' | ~datatype(system.arg.suspend, 'N')	then
		do
			call Log(' *** Incorrect arguments "'args'"'!)
			signal Usage
		end

	if system.forceimp																then call setclip(system.prg.name)

return


Quit:

	parse arg return_code, error_msg

	error_line    = 0
	rc						= 0
signal Exit


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


Request_Choice: procedure Expose system.

	parse arg text, buttons, ret_vals

	title	= system.prg.name'-Requester'
	text	= translate(Replace(text, '0A'x, '\n'), '1b'x, '\')

	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), '_')


Resume_Import: procedure Expose system.

  arg mode .

	check = mode='CHECK'

	call Get_Status

	call Command('c:list >'system.tmpfile system.mm.inbound 'p Wait.#?' 'lformat "%n"')

	MM_ReadStem system.tmpfile 'resume'

	if resume.count~=0 & system.suspended=0 then
		call Log('*** WARNING: Import was NOT suspended but suspended files were found!')

	if ~check | resume.count~=0	then call Log(' Resuming import...')

	do n=0 to resume.count-1
		parse var resume.n . '.' file
		file			= translate(file, '.', '_')
		wait_file = system.mm.inbound || resume.n
		full_file	= system.mm.inbound || file

		if rename(wait_file, full_file) then call Log('  -> Resuming' upper(file))
		else																 call Log('*** IO-ERROR: Unable to resume' file'!!!')
	end

	if ~check & resume.count=0	then call Log('  -> Nothing to resume...')
	if ~check | resume.count~=0	then call Log(' ==> Done.')
	if ~check										then call Set_Status()

return 0


Secs_To_Time: procedure

	parse arg secs

	s	= secs // 60
	m	= secs  % 60
	h	= m     % 60
	m	= m    // 60

return right(h, 2, '0')':'right(m, 2, '0')':'right(s, 2, '0')


Security: procedure Expose system.

	call Log(' Security-check...')

	do n=0 to system.received.count-1
		parse value upper(system.received.n) with . name . '.' ext . 15 'FROM' from ';' . 15 'SECURE' secure ';' .
		if find('TIC PKT', ext)>0 then iterate

		if right(from, 1)~='@' then from = from'@'

		check			= 1
		file			= name'.'ext
		from			= strip(from)
		full_file = system.mm.inbound || file

		select
			when index(system.nodes, upper(from))=0	then
				call Move_Bad(file, full_file, from, 'Unlisted sender',  system.received.n)
			when pos('PW', secure)=0 then
				call Move_Bad(file, full_file, from, 'Missing password', system.received.n)
			otherwise
				call Log('  ->' file 'from' strip(from, 't', '@') 'is ok.')
		end
	end

	if check~=1 then call Log('  -> No bundles to check.')

	call close(in)
	call Log(' ==> Done.')
	call delete(system.tmpfile)

return


Set_LogPrefix: procedure Expose system.

	system.mm.logpre  		= getclip('MM_LogPre')
	system.prg.logpre 		= system.mm.logpre'|'
	call                		setclip('MM_LogPre', system.prg.logpre)

return


Set_Status: procedure Expose system.

	parse arg sts ., val
	u_sts = upper(sts)

	system.status = strip(u_sts' 'val)

	if sts='' then
		do
			if exists(system.prg.env) & ~delete(system.prg.env) then
				call Log('*** IO-ERROR: Unable to delete' system.prg.env'!!!')

			call Get_Status
			return
		end

	if ~open(out, system.prg.env, w) then call Quit(30, 'Unable to open "'system.prg.env'" for write!!!')

	if val='' then sts = sts'!'
	else           sts = sts '('val')!'

	call writeln(out, system.status)
	call   close(out)
	call Log(' Import' sts)

return


Sort_Bundles: procedure Expose system.

	call Log(' Sorting bundles...')

	MM_SortStem 'system.received'

	time = time('s')

	if system.received.count>1 then
		do n=0 to system.received.count-1
			parse var system.received.n . file date . .
			full_file	= system.mm.inbound || file

			if ~exists(full_file) then iterate

			date	= translate(date('e', date, 'i'), '-', '/')

			call Log('  ->' file)
			call Command('c:setdate' full_file date Secs_To_Time(time+n))
		end

	call Log(' ==> Done.')
return


Suspend_Import: procedure Expose system.

	call Get_Status

	if system.suspended~=0 then
		if system.arg.suspend=system.suspended then call Log(' Import already suspended!')
		else																				call Set_Status('suspended', system.arg.suspend)

	system.susplog	= 1

return 0


Syntax:

	signal off syntax

	host					= RC~=13
	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'[.rexx] CPLCFG/S,FORCEIMPORT/S,DISABLE/S,ENABLE/S,' ||,
																					 'SUSPEND/S,SUSPEND/K/N,RESUME/S,TICKIMPORT/S,' ||,
																					 'NOTICKIMPORT/S'
	say
call Quit(0, 'Usage requested.')


Wait_AreasWindow: procedure Expose system.

	MM_AreasWin ; ret = RC

	wait	= ' Waiting for Areas-Window...'

	if ret~=0 then
		do
			call Get_Status

			if system.suspended~=0 then button	= 'RESUME'
			else												button	= 'SUSPEND'

			ret = Request_Choice('\c\n'system.prg.id'\nis waiting.\n\nPlease go back to the Areas-Window',
					 	'as soon as possible\n or disable/quit' system.prg.name'.\n',,
						'_DISABLE|* _WAIT | _QUIT |_'button, '0 1 2 3')

			select
				when ret=0 then	call Disable_Import
				when ret=1 then call Log(wait)
				when ret=2 then call Quit(8, 'Import aborted by user!')
				when ret=3 then
					do
						call Log(wait)

						if system.suspended~=0 then ret =  Resume_Import()
						else												ret = Suspend_Import()
					end
				otherwise nop
			end
		end

	do while ret~=0
		MM_AreasWin ; ret = RC
		call writech(STDOUT, '070D'x || wait'0D'x)
		call Delay(250)

		call Set_LogPrefix
	end

return


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



Add_Cfg: procedure Expose cpl. system.

	parse arg var, val
	upper var

	if datatype(val)='NUM' 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_Script: procedure Expose script.

	parse arg line

	MM_AddToStem 'script' 'line'

return


Compile_Cfg: procedure Expose system.

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

	MM_ReadStem system.prg.cfg 'cfg'
	if rc>0 then call Quit(21, 'Unable to read "'system.prg.cfg'"!')

	cpl.      				= 0
	cpl.stems					= ''
	l									= 0
	sys								= 'system.'
	system.nodes			= ''

	MM_GetNodes 'tmp'

	do n=0 to tmp.count-1
		system.nodes = system.nodes tmp.n
	end

	call Get_Status
	if system.disabled=0 then call Set_Status()

	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='#AREAFIXCMD'		then call Add_Cfg_Stem(sys'cmd.areafix',	args)
			when key='#BADDIR'				then call Add_Cfg_Stem(sys'mm.baddir',		args)
			when key='#BEFORECMD'			then call Add_Cfg_Stem(sys'cmd.before',		args)
			when key='#BOTHCMD'				then call Add_Cfg_Stem(sys'cmd.both',			args)
			when key='#ECHOMAILCMD'		then call Add_Cfg_Stem(sys'cmd.echomail',	args)
			when key='#ICONIFY'				then call Add_Cfg(		 sys'iconify',			1  )

			when key='#MINFREEMEM'		then
				do
					parse value upper(args) with 1 'CHIP' chip . 1 'FAST' fast .

					if ~datatype(chip, 'N') | chip<100 then
						call Quit(11, 'Value "'chip'" unsuitable for #MINFREEMEM CHIP at line' l'!')

					if ~datatype(fast, 'N') | fast<500 then
						call Quit(12, 'Value "'fast'" unsuitable for #MINFREEMEM FAST at line' l'!')

					call Add_Cfg(sys'minfree.chip', chip)
					call Add_Cfg(sys'minfree.fast', fast)
				end

			when key='#MINRECEIVED'		then
				do

					if ~datatype(args,'N')	then
						call Quit(13, 'Value "'args'" unsuitable for #MINRECEIVED at line' l'!')

					call Add_Cfg(sys'minreceived', args)
				end

			when key='#NETMAILCMD'		then call Add_Cfg_Stem(sys'cmd.netmail',	args)
			when key='#NTDCMD'				then call Add_Cfg_Stem(sys'cmd.ntd',			args)
			when key='#NODES'					then system.nodes = system.nodes args
			when key='#NOICONIFY'			then nop
			when key='#NOSECURITY'		then nop
			when key='#NOTICKIMPORT'	then call Add_Cfg(sys'notick', 			1)
			when key='#NOSORTBUNDLES'	then nop
			when key='#NOSUSPEND'			then nop
			when key='#SECURITY'			then call Add_Cfg(sys'security', 		1)
			when key='#SORTBUNDLES'		then call Add_Cfg(sys'sortbundles', 1)
			when key='#SUSPEND'				then
				do
          if args=''							then args	= -1
					if ~datatype(args, 'N') then call Quit(10, 'Invalid value for #SUSPEND at line' l': "'args'"')

					call Add_Cfg(sys'autosuspend', args)
				end

			when key='#TICKCMD'				then call Add_Cfg_Stem(sys'cmd.tick',	args)
			when key='#TICKIMPORT'		then nop

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

	upper system.nodes

	call Add_Cfg(sys'nodes', strip(system.nodes))

	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'

	MM_ReadStem			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()

	MM_WriteStem	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


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


                                 /*** CFG ***/


Cfg:

exit 999

