#!/usr/local/bin/perl

$ConfigFile = "/usr/libexec/ifmail/filefix/config";

$LS='/bin/ls';
$MV='/bin/mv';
$RM='/bin/rm';
$CP='/bin/cp';
$GREP='/usr/bin/grep';

open (STDERR, ">>/dev/null");
open (STDOUT, ">>/dev/null");

$Version = "FileFix v.1.8.(beta)";

#main {
	if( $] < 5 ) {
		print STDERR "Sorry, $Version worked only with Perl v5.xxx.\n";
		exit 1;
	}
	if( $ARGV[0] =~ /^-t$/ ) {
		&ReadConfig( "toss" ) || die "Bad config file.";
		&SetLock();
		&Tosser();
		&UnsetLock();
#		&CloseLog();
	} elsif( $ARGV[0] =~ /^-m$/ ) {
		&ReadConfig( "mgr" ) || die "Bad config file.";
		&SetLock();
		&Manager();
		&UnsetLock();
#		&CloseLog();
	} elsif( $ARGV[0] =~ /^-s$/ ) {
		&ReadConfig( "scan" ) || die "Bad config file.";
		&SetLock();
		&Scaner();
		&UnsetLock();
#		&CloseLog();
	} elsif( $ARGV[0] =~ /^-n$/ ) {
		&ReadConfig( "name" ) || die "Bad config file.";
		if( &TestConfig( "ECHOLIST" )) {
			&SetLock();
			&Namer();
			&UnsetLock();
		} else {
			&logger( 0, "EchoList not defined in config file.");
		}
#		&CloseLog();
	} else {
		print "Usage: filefix -[m|t|s|n]\n\t-t - tosser\n\t-m - manager\n\t-s - scanner\n\t-n - set fileecho names\n";
		exit 1;
	}
# }

#sub Sys::Syslog::hostname
#{
#    use Sys::Hostname;
#    return hostname;
#}
#
#sub OpenLog {
#	$_run_mode = $_[0];
#	use Sys::Syslog;
#	&openlog('filefix-'.$_run_mode,'cons,pid',$LOG_FACILITY);
#	open( LOG, ">>".$FConfig{'LOGFILE'} ) if( TestConfig( "LOGFILE" ));
#}
#
#sub CloseLog {
#	&closelog();
#	close( LOG ) if( TestConfig( "LOGFILE" ));
#}
#

sub logger {
	if( $FConfig{'LOGLEVEL'} >= $_[0] ) {
		print LOG &strtime( "log" )." filefix($RunMode)[$$] ".$_[1]."\n";
		system "/usr/bin/logger -p local1.info -t FileFix[$$]  $_[1]";
	}
}


sub CheckExtUtils {
	if( ! &TestConfig( "ALTTOKOI" )) {
		&logger( 0, "AltToKoi not defined in config file.");
		return 0;
	}
	if( ! -x $FConfig{'ALTTOKOI'} ) {
		&logger( 0, "No such file ".$FConfig{'ALTTOKOI'}." or not executable.");
		return 0;
	}
	if( ! &TestConfig( "KOITOALT" )) {
		&logger( 0, "KoiToAlt not defined in config file.");
		return 0;
	}
	if( ! -x $FConfig{'KOITOALT'} ) {
		&logger( 0, "No such file ".$FConfig{'KOITOALT'}." or not executable.");
		return 0;
	}
	if( ! &TestConfig( "DOSTOUNIX" )) {
		&logger( 0, "DosToUnix not defined in config file.");
		return 0;
	}
	if( ! -x $FConfig{'DOSTOUNIX'} ) {
		&logger( 0, "No such file ".$FConfig{'DOSTOUNIX'}." or not executable.");
		return 0;
	}
	return 1;
}

sub SetLock {
	return 1 if( ! &TestConfig( 'LOCKFILE' ));
	require "/usr/share/perl/errno.ph";
	open( LockFile, ">".$FConfig{'LOCKFILE'} );
	use Fcntl;
	fcntl( LockFile, F_GETLK, 0 );
	flock( LockFile, 2 );
	print LockFile $$;
}

sub UnsetLock {
	return 1 if( ! &TestConfig( 'LOCKFILE' ));
	close( LockFile );
	unlink $FConfig{'LOCKFILE'};
}

sub ChMod {
	local($mode) =  $_[0];
	local($file) =  $_[1];
#   &logger(0,"/bin/chmod $mode $file");
   system("/bin/chmod $mode $file");
#   print "/bin/chmod $mode $file\n";
}



sub mklock {
	local( $lockfile ) = $_[0];
	local( $clrlock ) = 1;
	$lockfile = "./".$lockfile unless( $lockfile =~ /\// );
	local( $tmplock ) = substr( $lockfile, 0, rindex( $lockfile, "/" ))."/$$.lck";
	local( $tmp, $pid );

	$clrlock = $_[1] if( defined( $_[1] ));
	if( !open( tmp, ">".$tmplock )) {
		&logger( 0, "Cannot open tmp lock file $tmplock. $!");
		return 0;
	}
	print tmp $$."\n";
	close( tmp );

try:
	if( link( $tmplock, $lockfile )) {
		unlink $tmplock;
		return 1;
	} else {
		if( $! != &EEXIST ) {
			&logger( 0, "Cannot create lock file $lockfile. $!");
			unlink $tmplock;
			return 0;
		} else {
			if( !open( tmp, $lockfile )) {
				&logger( 0, "Cannot read existing lock file $lockfile. $!");
				unlink $tmplock;
				return 0;
			}
			$pid = <tmp>;
			chop $pid;
			close( tmp );
			kill 0, $pid;
			if( $! == &ESRCH ) {
				&logger( 1, "Warning: found unused lock file $lockfile.");
				if( $clrlock ) {
					&logger( 1, "Warning: delete unused lock file.");
					unlink $lockfile;
					goto try;
				}
			}
		}
	}
	unlink $tmplock;
	return 0;
}

sub basename {
	local( $str ) = $_[0];
	return substr( $str, rindex( $str, "/" ) + 1 );
}

sub basepath {
	local( $str ) = $_[0];
	return substr( $str, 0, rindex( $str, "/" ) + 1 );
}

sub strtime {
	local( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst );
	local( $m, $l, $dstmin, $dsthour );
	local( $tm, $month, $week );
	local( $sw ) = @_;
	$tm = time;
	( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = localtime( $tm );
	@months = ( Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec );
	@week = ( Sun, Mon, Tue, Wed, Thu, Fri, Sat );
	if( $sw =~ /log/ ) {
		return sprintf( "%3s %2d %02d:%02d:%02d", $months[$mon], $mday, $hour, $min, $sec );
	} elsif( $sw =~ /tic/ ) {
		return sprintf( "%2d %3s %2d %02d:%02d:%02d", $mday, $months[$mon], $year, $hour, $min, $sec );
	} elsif( $sw =~ /path/ ) {
		$m = ( $hour * 60 + $min ) - (( gmtime( $tm ))[2] * 60 + ( gmtime( $tm ))[1] );
		if( $m < 0 ) {
			$l = "-";
			$m = $m * -1;
		} else {
			$l = "+";
		}
		$dsthour = int( $m / 60 );
		$dstmin = $m % 60;
		return sprintf( "%d %3s %3s %2d %02d:%02d:%02d 19%d UTC%s%02d%02d", $tm, $week[$wday], $months[$mon], $mday, $hour, $min, $sec, $year, $l, $dsthour, $dstmin );
	}
	return "";
}

#sub logger {
#	local( $m ) = "notice";
#	local( $secure ) = 0;
#	$m = $_[2] if( defined( $_[2] ));
#	$secure = $_[3] if( defined( $_[3] ));
#	if( $FConfig{'LOGLEVEL'} >= $_[0] ) {
#		print LOG &strtime( "log" )." filefix($_run_mode)[$$] ".$_[1]."\n";
#		&syslog( $m, $_[1] ) if( $secure == 0 );
#	}
#}

sub tolower {
	local( $ret ) = $_[0];
	$ret =~ tr/[A-Z]/[a-z]/;
	return $ret;
}

sub toupper {
	local( $ret ) = $_[0];
	$ret =~ tr/[a-z]/[A-Z]/;
	return $ret;
}

sub ParseAddr {
	local( $fido ) = $_[0];
	local( $zone, $net, $node, $point );

	$zone = $fido;
	if( $zone =~ /^[0-9]+:/ ) {
		$zone =~ s/:.*//;
	} else {
		$zone = $my_zone;
	}

	$net = $fido;
	$net =~ s/^[0-9]+://;
	$node = $net;
	if( $net =~ /^[0-9]+\// ) {
		$net =~ s/\/.*//;
	} else {
		$net = $my_net;
	}

	$node =~ s/^[0-9]*\///;
	$point = $node;
	$node =~ s/\.[0-9]+$//;
	$node = $my_node if( $node eq "" );

	$point =~ s/^[0-9]+//;
	if( $point =~ /^\./ ) {
		$point =~ s/\.//;
	} else {
		$point = 0;
	}
	return( $zone, $net, $node, $point );
}

sub TestConfig {
	if( $FConfig{$_[0]} =~ /^.+$/ ) {
		return 1;
	} else {
		return 0;
	}
}

sub ReadConfig {
	$RunMode = $_[0];
	local( $Key, $Value );
	open( ConfigFile ) || die qq|Can't open "Config" file.|;
	while( <ConfigFile> ) {
		/^[ \t]*$/	&& next;
		/^[ \t]*#/	&& next;
		chop;
		( $Key, $Value ) = split( /[ \t]+/, $_, 2 );
		$Key =~ tr/a-z/A-Z/;
		$FConfig{$Key} = $Value;
	}
	close( ConfigFile );
#	&OpenLog( $RunMode );
	if (! -f $Config{'LogFile'}) {
	 system "$TOUCH $Config{'LogFile'}"; ### /bin/chmod 664 $Config{'LogFile'}";
	};
	open( LOG, ">>$FConfig{'LOGFILE'}" );
	return 0 if( CheckExtUtils != 1 );
	$FConfig{'DEFDESC'} = "Descriptor missing" if( ! &TestConfig( 'DEFDESC' ));
	if( ! &TestConfig( 'BINDIR' )) {
		&logger( 0, "Undefined 'BinDir' in config.");
		return 0;
	}
	if( ! &TestConfig( 'TICDIR' )) {
		&logger( 0, "Undefined 'TicDir' in config.");
		return 0;
	}
	$FConfig{'DESCDIR'} = "." if( !defined( $FConfig{'DESCDIR'} ));
	if( &TestConfig( 'IFCONFIG' )) {
		if( ! &ReadIfConfig() ) {
			&logger( 0, "Bad ifmail config file");
		}
		&logger( 7, "Read config ok.");
		return 1;
	} else {
		&logger( 0, "Undefined IfConfig in config.");
		return 0;
	}
}

sub ReadIfConfig {
	local( $ifconfig, $Key, $Value, $tmp );
	$ifconfig = $FConfig{'IFCONFIG'};
	if( ! open( ifconfig )) {
		&logger( 0, "Can't open ifmail config file.");
		exit( 1 );
	}
	while( <ifconfig> ) {
		/^[ \t]*$/	&& next;
		/^[ \t]*#/	&& next;
		chop;
		( $Key, $Value ) = split( /[ \t]+/, $_, 2 );
		$Key =~ tr/a-z/A-Z/;
		if( $Key =~ /^ADDRESS$/ ) {
			$FConfig{$Key} = $Value if( ! &TestConfig( 'ADDRESS' ));
		} elsif( $Key =~ /^MYFQDN$/ ) {
			$FConfig{$Key} = $Value;
		} elsif( $Key =~ /^PROTINBOUND$/ ) {
			$FConfig{$Key} = $Value;
		} elsif( $Key =~ /^OUTBOUND$/ ) {
			$FConfig{$Key} = $Value;
		} elsif( $Key =~ /^SYSOP$/ ) {
			$FConfig{'SYSOP'} = $Value;
		} else {
			next;
		}
	}
	close( ifconfig );
	return 0 unless( &TestConfig( 'ADDRESS' )
		&& &TestConfig( 'MYFQDN' )
		&& &TestConfig( 'PROTINBOUND' )
		&& &TestConfig( 'OUTBOUND' ));

	$FConfig{'ADDRESS'} =~ s/@.*$//;
	if( $FConfig{'ADDRESS'} =~ /^[0-9]+:[0-9]+\/[0-9]+\.*[0-9]*$/ ) {
		( $my_zone, $my_net, $my_node, $my_point ) = &ParseAddr( $FConfig{'ADDRESS'} );
	} else {
		&logger( 0, "Use full fido address in ifmail config.");
		return 0;
	}
	return 1;
}

sub find {
	local( $i, $expr, $list );
	$expr = $_[0];
	shift;
	@list = @_;
	for( $i = 0; $i <= $#list; $i++ ) {
		last if( $list[$i] eq $expr );
	}
	return -1 if( $i > $#list );
	return $i;
}

sub ProcessFilesBbs {
#  files.bbs
#
# $ticarea -  
#     Tic
#
 local($files,$counter,@desc);
 local($found) = 0;
 $ticarea=$_[0];
 &logger(0, "Area for bbs: $ticarea");
# $ticarea =~ s/[`\/]//g;
#  system("cp $AreaPath{$ticarea}/$Config{'FilesBbs'} $AreaPath{$ticarea}/$Config{'FilesBbs'}.new");
  if( ! open( out, "|/usr/bin/sort -u - >".$AreaPath{$ticarea}."/".$FConfig{'FILESBBS'}.'.new' ))
  {
 	&logger( 3, "Cannot open $Config{'FILESBBS'}. Error: $!" );
  }
  else
  {
##   ,    !
   if( ! open( in, $AreaPath{$ticarea}."/".$FConfig{'FILESBBS'} ))
   {
     &logger( 3, "Cannot open $FConfig{'FILESBBS'}. Error: $!" );
   }
   else
   {
     while (<in>)
     {
      $istr = $_;
      ($files,$counter,@desc) = split;
      $files = &tolower($files);
      if ($files eq &tolower($Tic{'FILE'}))
      {
        $found = 1;
        &logger(0, "Replace files.bbs -- $ticarea");
        printf(out "%-12.12s [000] ",$Tic{'FILE'});
        for( $i = 0; $i <= $#TicDesc; $i++ )
        {
           print out $TicDesc[$i]." ";
        } # for
#LDesc
        for( $i = 0; $i <= $#TicLDesc; $i++ )
        {
           print out $TicLDesc[$i]." ";
        } # for
        print out "\n";
      }
       else
      {
       print(out $istr);
      }; # if File == files
     }; # while
    close( in );
   }; # if
   if ( $found == 0)
   {
     #  .  
      &logger(0, "Normal files.bbs -- $ticarea");
      printf(out "%-12.12s [000] ",$Tic{'FILE'});
      for( $i = 0; $i <= $#TicDesc; $i++ )
      {
       	print out $TicDesc[$i]." ";
      } # for
#LDesc
      for( $i = 0; $i <= $#TicLDesc; $i++ )
      {
          print out $TicLDesc[$i]." ";
      } # for
      print out "\n";
   };
   close( out );
#################################
   system( "$MV $AreaPath{$ticarea}/$FConfig{'FILESBBS'}.new $AreaPath{$ticarea}/$FConfig{'FILESBBS'}");
   if( defined( $AreaMode{$ticarea} ))
   {
#     chmod '0'.$AreaMode{$ticarea}, $AreaPath{$ticarea}."/".$FConfig{'FilesBbs'};
     &ChMod('0'.$AreaMode{$ticarea}, $AreaPath{$ticarea}."/".$FConfig{'FILESBBS'});
   }
  }
####  files.bbs ###
}


sub BadName {
	local( $name ) = $_[0];
	$name =~ s/\#/\\\#/g;
	$name =~ s/\$/\\\$/g;
	$name =~ s/\^/\\\^/g;
	$name =~ s/\&/\\\&/g;
	$name =~ s/\(/\\\(/g;
	$name =~ s/\)/\\\)/g;
	$name =~ s/\[/\\\[/g;
	$name =~ s/\]/\\\]/g;
	$name =~ s/\`/\\\`/g;
	$name =~ s/\'/\\\'/g;
	$name =~ s/\"/\\\"/g;
	return $name;
}

sub Tosser {
	local( $ls );
	if( ! open( ls, "cd $FConfig{'PROTINBOUND'}; ls -1 *.[tT][iI][cC] 2>/dev/null |" )) {
		&logger( 0, "Cannot search in protinbound." );
		return 0;
	}
	&ReadAreas() || return 0;
	&ReadUsers() || return 0;
	while( <ls> ) {
		chop;
		&ProcessTic( $_ );
	}
	close( ls );
	if( $FConfig{'SENDANNOUNCE'} =~ /^[yY]/ ) {
		&MessageOfNewFilesSort();
	}
	return 1;
}

sub MessageOfNewFiles {
	local( $i, $in, $out, $area );
	if( &TestConfig( 'ANEWSCOMMAND' ) && &TestConfig( 'ANEWSGROUPS' )) {
		for( $i; $i <= $#AreaName; $i++ ) {
			$area = $AreaName[$i];
			if( -e $AreaNewfile{$area} ) {
				if( ! open( in, $AreaNewfile{$area} )) {
					&logger( 0, "Cannot read announce file [$!].");
					return 0;
				}
				if( ! open( out, "| ".$FConfig{'ANEWSCOMMAND'} )) {
					&logger( 0, "Cannot send announce [$!].");
					close( in );
					return 0;
				}
				print out "From: FileFix <FileFix\@".$FConfig{'MYFQDN'}.">\n";
				print out "Newsgroups: $FConfig{'ANEWSGROUPS'}\n";
				print out "Subject: New file(s) announce\n";
				print out "\n";
				while( <in> ) {
					print out $_;
				}
				print out "\n--\n\t$Version of ".$FConfig{'ADDRESS'}."\n";
				close( out );
				close( in );
				unlink( $AreaNewfile{$area} );
			}
		}
	}
	return 1;
}

sub MessageOfNewFilesSort {
	local( $i, $in, $out, $area );
	local( $sfile,$ssize,$sarea,$sorigin,@sdesc,$tarea,$mydesc);
	local( $fixname, $newsname, $sign1, $sign2, $sign0, $myarea);
	local( $Tcount,$Tsize) = (0,0);
	local( $AllFiles, $AllSize) = (0,0);

format OUTPUT =
@<<<<<<<<<<<<<<<<<  @|||||||||||  ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$sfile,             $ssize,       $mydesc
~~                                ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                                  $mydesc
.

format OUTPUT_TOP =
From: FileFix @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
              $fixname
To: All
Newsgroups: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
            $newsname
Subject: New file(s) announce

	 !
 @||||||||||||||||||||||||||||||||||||||||||
      $sign2
     :

.

format OUTPUT_BEGIN =
>*** AREA: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
           $myarea

 FileName           Size (bytes)         Description of File
------------------  ------------  ------------------------------------
.

format OUTPUT_END =
------------------  ------------
Files: @<<<<<<<<<   @||||||||||| bytes
 $Tcount $Tsize

.

format OUTPUT_BOTTOM =

TOTAL: files @<<<<<<<<<<<<<<<<<<<
             $AllFiles
       bytes @<<<<<<<<<<<<<<<<<<<
             $AllSize


--
	@<<<<<<<<<<<<<<<<<<<<< of @<<<<<<<<<<<<<<<<<<<<<<
	$sign0,			  $sign1

.

	if( &TestConfig( 'ANEWSCOMMAND' ) && &TestConfig( 'ANEWSGROUPS' )) {
		for( $i; $i <= $#AreaName; $i++ ) {
			$area = $AreaName[$i];
			if( -e $AreaNewfile{$area} ) {
#				system "$MV $AreaNewfile{$area} $AreaNewfile{$area}.uns";
#				system ("/usr/bin/sort < $AreaNewfile{$area}.uns > $AreaNewfile{$area}");
#				if( ! open( in, $AreaNewfile{$area} )) {
				if( ! open( in, "/usr/bin/sort < $AreaNewfile{$area}|" )) {
#					&logger( 0, "Cannot read annonce file [$!]." );
					&logger( 0, "Cannot start sort annonce file [$!]." );
					return 0;
				}
				if( ! open( OUT, "| ".$FConfig{'ANEWSCOMMAND'} )) {
					&logger( 0, "Cannot send annonce [$!]." );
					close( in );
					return 0;
				}
				select(OUT);
#				print out "From: FileFix-AlienBBS <filefix@f29.n5002.z2.fidonet.org>\n";
#				print "From: FileFix <FileFix\@".$FConfig{'MYFQDN'}.">\n";
#				print "To: All\n";
#				print "Newsgroups: $FConfig{'ANEWSGROUPS'}\n";
#				print "Subject: New file(s) annonce\n";
#				print "\n";
                                $fixname = "<FileFix\@".$FConfig{'MYFQDN'}.">";
                                $newsname = $FConfig{'ANEWSGROUPS'};
                                $sign2 = $FConfig{'STATION'};
                                $~= "OUTPUT_TOP";
                                write OUT;
				$tarea='';
				while( <in> ) {
				 if (/^$/) {next};
				 ($sarea,$sfile,$ssize,$sorigin,@sdesc) = split(/ /,$_);
#  
				 $mydesc = "@sdesc";
				 $myarea = '_'.$sarea.'_';
# 
				 if ($tarea ne $sarea) {
                                   if ($tarea) {
                                     $AllFiles += $Tcount; $AllSize += $Tsize;
                                     $~ = "OUTPUT_END";
                                     write OUT;
                                   }
                                  $~ = "OUTPUT_BEGIN";
                                  $Tcount=0; $Tsize=0;
                                  write OUT;
				  $tarea=$sarea;
				 }
#			         print out sprintf( "%-16s %-20s", $sfile, $ssize);
#			         print out "\t";
#				 for( $i = 0; $i <= $#sdesc; $i++ ) {
#				     print out $sdesc[$i].' ';
#				 }
#				 print out "\n";
                                 $~ = "OUTPUT";
                                 $Tcount++; $Tsize += $ssize;
				 write OUT ;
#				 print "\n";
				}
#				print "\n--\n\t$Version of ".$FConfig{'ADDRESS'}."\n\t ".$FConfig{'STATION'}."\n";
                                $~ = "OUTPUT_END";
                                write OUT;
                                $AllFiles += $Tcount; $AllSize += $Tsize;
                                $sign0 = $Version;
                                $sign1 = $FConfig{'ADDRESS'};
#                                $sign2 = $FConfig{'STATION'};
                                $~ = "OUTPUT_BOTTOM";
                                write OUT;
				close( OUT );
				close( in );
				system "$MV -f $AreaNewfile{$area} protect.txt";
			}
		}
	}
	return 1;
}


sub MoveToBad {
	if( $tic =~ /[0-9]+\.tic/i ) {
		if( &TestConfig( 'BADTIC' )) {
			if( ! -d $FConfig{'BADTIC'} ) {
				if( ! mkdir( $FConfig{'BADTIC'}, 0755 )) {
					&logger( 0, "Cannot create BadTic directory [$!], tic moved in to /tmp.");
					system "mv $FConfig{'PROTINBOUND'}/$tic /tmp";
				}
			}
			system "mv $FConfig{'PROTINBOUND'}/$tic $FConfig{'BADTIC'}";
		} else {
			system "rm -f $FConfig{'PROTINBOUND'}/$tic";
		}
	}
	if( -f $FConfig{'PROTINBOUND'}."/".$Tic{'FILE'} ) {
		if( &TestConfig( 'BADFILE' )) {
			if( ! -d $FConfig{'BADFILE'} ) {
				if( ! mkdir( $FConfig{'BADFILE'}, 0755 )) {
					&logger( 0, "Cannot create BadFile directory [$!], tic moved in to /tmp.");
					system "mv $FConfig{'PROTINBOUND'}/".BadName($Tic{'FILE'})." /tmp";
				}
			}
			system "mv $FConfig{'PROTINBOUND'}/".BadName($Tic{'FILE'})." $FConfig{'BADFILE'}";
		} else {
			system "rm -f $FConfig{'PROTINBOUND'}/".BadName($Tic{'FILE'});
		}
	}
}

sub ProcessTic {
	local( $arealinks, $idlink, $al, $From, $ticarea, $descarea, $uflags, $i, $t, $ticdir, $uf );
	local( $oldfile, $newfile, @infiles );
	local( $tic ) = $_[0];
	local( $badcrc, $badsize );

	&logger( 3, "Processing $tic ...");
	$badcrc = $badsize = 0;
	&ReadTic( $FConfig{'PROTINBOUND'}."/".$tic ) || return 0;
	#   - ?
	@infiles=<$FConfig{'PROTINBOUND'}/*>;
	for( $i = 0; $i <= $#infiles; $i++ ) {
		if( tolower( basename( $infiles[$i] )) eq $Tic{'FILE'} ) {
			rename( $infiles[$i], $FConfig{'PROTINBOUND'}."/".$Tic{'FILE'} );
			next;
		}
	}
	if( ! -r $FConfig{'PROTINBOUND'}."/".$Tic{'FILE'} ) {
		if( &TestConfig( 'WAITFILE' )) {
			$tdate = ( stat( $FConfig{'PROTINBOUND'}."/".$tic ))[9];
			if( $tdate + $FConfig{'WAITFILE'} * 3600 < time ) {
				&logger( 5, "No wait file ".BadName($Tic{'FILE'}).", tic removed.");
				system "rm -f $FConfig{'PROTINBOUND'}/$tic";
				return 0;
			} else {
				&logger( 5, "File ".BadName($Tic{'FILE'})." not received, wait.");
				return 0;
			}
		} else {
			&logger( 5, "File ".BadName($Tic{'FILE'})." not received, tic removed.");
			system "rm -f $FConfig{'PROTINBOUND'}/$tic";
			return 0;
		}
	}

	#      ?
	$From = $Tic{'FROM'};
	if( &find( $From, @UserAddr ) == -1 ) {
		&logger( 3, "Unknown user $From");
		&MoveToBad();
		return 0;
	}
	#    ?
	if( &tolower( $Tic{'PW'} ) !~ &tolower( $UserPasswd{$From} )) {
		&logger( 3, "Password error from $From: is \"$Tic{'PW'}\" should by \"$UserPasswd{$From}\".");
		&MoveToBad();
		return 0;
	}
	$size = (stat( $FConfig{'PROTINBOUND'}."/".$Tic{'FILE'}))[7];
	if( defined( $Tic{'SIZE'} )) {
		if( $Tic{'SIZE'} != $size ) {
			$badsize = 1;
		}
	} else {
		$Tic{'SIZE'} = $size;
	}
	if( defined( $Tic{'CRC'} )) {
		open( t, $FConfig{'BINDIR'}."/crc32 < ".$FConfig{'PROTINBOUND'}."/".BadName($Tic{'FILE'})." |" );
		while( <t> ) {
			chop;
			$Crc = $_;
		}
		close( t );
		if( &toupper( $Tic{'CRC'} ) ne &toupper( $Crc )) {
			$badcrc = 1;
		}
	}
	$ticarea = $Tic{'AREA'};

	#   ?
	if( !defined( $AreaPath{$ticarea} )) {
		# "     ?
		@uflags	= split( /[ \t]+/, $UserFlags{$From} );
		if( ! grep( /\+[aA]/, @uflags )) {
			&logger( 3, "Cannot create new area for user $From");
			&MoveToBad();
			return 0;
		}
		# Create new area
		if( !( defined( $AreaPath{'default'} ) && defined( $AreaGroup{'default'} ))) {
			&logger( 0, "Cannot create new area: undefined in default area Path and/or Group.");
			&MoveToBad();
			return 0;
		}
		$AreaName[$#AreaName + 1] = $ticarea;
		$AreaPath{$ticarea} = $AreaPath{'default'}."/".$ticarea;
		if( defined( $Tic{'AREADESC'} )) {
			$AreaDesc{$ticarea} = $Tic{'AREADESC'};
		} elsif( defined( $AreaDesc{'default'} )) {
			$AreaDesc{$ticarea} = $AreaDesc{'default'};
		} else {
			$AreaDesc{$ticarea} = $FConfig{'DEFDESC'};
		}
		&SetNames();
		$AreaGroup{$ticarea} = $AreaGroup{'default'};
		$AreaExec{$ticarea} = $AreaExec{'default'} if( defined( $AreaExec{'default'} ));
		$AreaExclude{$ticarea} = $AreaExclude{'default'} if( defined( $AreaExclude{'default'} ));
		$AreaSave{$ticarea} = $AreaSave{'default'} if( defined( $AreaSave{'default'} ));
		$AreaNewfile{$ticarea} = $AreaNewfile{'default'} if( defined( $AreaNewfile{'default'} ));
		$AreaMode{$ticarea} = $AreaMode{'default'} if( defined( $AreaMode{'default'} ));
		$AreaAKA{$ticarea} = $AreaAKA{'default'} if( defined( $AreaAKA{'default'} ));
		$AreaRO{$ticarea} = $AreaRO{'default'} if( defined( $AreaRO{'default'} ));
		$AreaDupes{$ticarea} = $AreaDupes{'default'} if( defined( $AreaDupes{'default'} ));
		$AreaNocheck{$ticarea} = $AreaNocheck{'default'} if( defined( $AreaNocheck{'default'} ));

		if(( $AreaNocheck{$ticarea} !~ /size/i ) && ( $badsize > 0 )) {
			&logger( 3, "Error size of ".BadName($Tic{'FILE'})."[$tic].");
			&MoveToBad();
			return 0;
		}
		if(( $AreaNocheck{$ticarea} !~ /crc/i ) && ( $badcrc > 0 )) {
			&logger( 3, "Error Crc in ".BadName($Tic{'FILE'})."[$tic].");
			&MoveToBad();
			return 0;
		}

		$AreaLinks{$ticarea} = $From;
		for( $i = 0; $i <= $#UserAddr; $i++ ) {
			if( $From ne $UserAddr[$i] ) {
				$ag = $AreaGroup{$ticarea};
				if(( $UserFlags{$UserAddr[$i]} =~ /.*\+[cC]/ ) && ( $UserGroups{$UserAddr[$i]} =~ /$ag/ )) {
					if( $UserFlags{$UserAddr[$i]} =~ /.*\+\!/ ) {
						$AreaLinks{$ticarea} .= " !".$UserAddr[$i];
					} else {
						$AreaLinks{$ticarea} .= " ".$UserAddr[$i];
					}
				}
			}
		}
		if( ! mkdir( $AreaPath{$ticarea}, 0755 )) {
			&logger( 0, "Cannot create path for new area $ticarea, Error = $!");
			splice( @AreaName, $#AreaName );
			&MoveToBad();
			return 0;
		}
		if( ! &WriteAreas() ) {
			splice( @AreaName, $#AreaName );
			&MoveToBad();
			return 0;
		}
		if( TestConfig( "NEWAREAEXEC" )) {
			if( -x $FConfig{'NEWAREAEXEC'} ) {
				if( defined( $AreaSave{$ticarea} )) {
					$i = $AreaSave{$ticarea};
				} else {
					$i = -1;
				}
				system( $FConfig{'NEWAREAEXEC'}." ".$ticarea." ".$i." ".$AreaGroup{$ticarea}." ".$AreaPath{$ticarea}." ".$AreaDesc{$ticarea} );
			} else {
				&logger( 0, "No such file ".$FConfig{'NEWAREAEXEC'}." or not executable.");
			}
		}
		if( &TestConfig( 'ANEWSCOMMAND' ) && &TestConfig( 'ANEWSGROUPS' )) {
			if( ! open( t, "| ".$FConfig{'ANEWSCOMMAND'} )) {
				&logger( 0, "Cannot send annonce of create area [$!].");
			}
			print t "From: FileFix\@".$FConfig{'MYFQDN'}."\n";
			print t "Newsgroups: $FConfig{'ANEWSGROUPS'}\n";
			print t "Subject: New filearea creation notification\n";
			print t "\nFile area $ticarea created at $FConfig{'ADDRESS'} by $Tic{'FROM'}\n";
			print t "\n$ticarea - $AreaDesc{$ticarea}\n";
			print t "\n--\n\t$Version\n";
			close( t );
		}
	} else {
		@arealinks = split( /[ \t]+/, $AreaLinks{$ticarea} );
		if( &find( $From, @arealinks ) == -1 ) {
			$tmpFrom = "!".$From;
			if( &find( $tmpFrom, @arealinks ) == -1 ) {
				&logger( 3, "Area $ticarea is not subscribed for $From");
			} else {
				&logger( 3, "Area $ticarea is read only for $From");
			}
			&MoveToBad();
			return 0;
		}
	}

	if(( $AreaNocheck{$ticarea} !~ /size/i ) && ( $badsize > 0 )) {
		&logger( 3, "Error size of ".BadName($Tic{'FILE'})."[$tic].");
		&MoveToBad();
		return 0;
	}
	if(( $AreaNocheck{$ticarea} !~ /crc/i ) && ( $badcrc > 0 )) {
		&logger( 3, "Error Crc in ".BadName($Tic{'FILE'})."[$tic].");
		&MoveToBad();
		return 0;
	}

	if( ! -d $AreaPath{$ticarea} ) {
		&logger( 0, "Hmm.. Directory not found for existing area $ticarea, created.");
		if( ! mkdir( $AreaPath{$ticarea}, 0755 )) {
			&logger( 0, "Cannot create path for existing area $ticarea, Error = $!");
			&MoveToBad();
			return 0;
		}
	}
	if( $FConfig{'DESCDIR'} =~ /^\// ) {
		$descdir = $FConfig{'DESCDIR'};
	} else {
		$descdir = $AreaPath{$ticarea}."/".$FConfig{'DESCDIR'};
	}
	if( ! -d $descdir ) {
		if( ! mkdir( $descdir, 0755 )) {
			&logger( 0, "Cannot create path for .desc, use current directory. Error = $!");
			$descdir="";
		}
	}
	if( $FConfig{'TICDIR'} =~ /^\// ) {
		$ticdir = $FConfig{'TICDIR'};
	} else {
		$ticdir = $AreaPath{$ticarea}."/".$FConfig{'TICDIR'};
	}
	if( ! -d $ticdir ) {
		if( ! mkdir( $ticdir, 0755 )) {
			&logger( 0, "Cannot create path for saved tics, Error = $!");
			system "mv $FConfig{'PROTINBOUND'}/$tic /tmp";
		} else {
			system "mv $FConfig{'PROTINBOUND'}/$tic $ticdir";
		}
	} else {
		system "mv $FConfig{'PROTINBOUND'}/$tic $ticdir";
	}

	if( defined( $Tic{'REPLACES'} )) {
		$oldfile = &basename( $Tic{'REPLACES'} );
		$newfile = $Tic{'FILE'};
		$oldfile =~ s/\..*//;
		$newfile =~ s/\..*//;
		if( $oldfile eq $newfile ) {
			$oldfile = &basename( $Tic{'REPLACES'} );
			system "rm -f ".$AreaPath{$ticarea}."/".BadName($oldfile)." ".$descdir."/".BadName($oldfile).".desc";
		} else {
			&logger( 0, "Trying replace \"".$Tic{'REPLACES'}."\" - abort.");
		}
	}
	if( $AreaDupes{$ticarea} =~ /name/i ) {
		if( -f $AreaPath{$ticarea}."/".$Tic{'FILE'} ) {
			&logger( 3, "File ".$AreaPath{$ticarea}."/".$Tic{'FILE'}." exist - dublicated.");
			system "mv $ticdir/$tic $FConfig{'PROTINBOUND'}";
			&MoveToBad();
			return 0;
		}
	}
	system "cp ".$FConfig{'PROTINBOUND'}."/".BadName($Tic{'FILE'})." ".$AreaPath{$ticarea};
	if( defined( $AreaMode{$ticarea} )) {
		system "chmod ".$AreaMode{$ticarea}." ".$AreaPath{$ticarea}."/".BadName($Tic{'FILE'});
	}
	if( !defined( $FConfig{'LASTSCAN'} )) {
		system "chmod o+t ".$AreaPath{$ticarea}."/".BadName($Tic{'FILE'});
	}
	system "rm -f ".$FConfig{'PROTINBOUND'}."/".BadName($Tic{'FILE'});
# 
        &logger(0,"Create $Tic{'FILE'}.desc");
	if( ! open( t, ">".$descdir."/".$Tic{'FILE'}.".desc" )) {
		&logger( 0, "Cannot create ".$descdir."/".BadName($Tic{'FILE'}).".desc. Error: $!");
	} else {
		for( $i = 0; $i <= $#TicDesc; $i++ ) {
			print t $TicDesc[$i]."\n";

		}
		if( $#TicLDesc > -1 ) {
			print t "\n";
			for( $i = 0; $i <= $#TicLDesc; $i++ ) {
				print t $TicLDesc[$i]."\n";
			}
		}
		close( t );
		if( defined( $AreaMode{$ticarea} )) {
			system "chmod ".$AreaMode{$ticarea}." ".$descdir."/".BadName($Tic{'FILE'}).".desc";
		}
	}

	if( defined( $AreaExec{$ticarea} )) {
		if( defined( $Tic{'FULLNAME'} )) {
			system $AreaExec{$ticarea}." ".BadName($Tic{'FILE'})." ".$AreaPath{$ticarea}." ".$ticarea." ".$Tic{'FULLNAME'};
		} else {
			system $AreaExec{$ticarea}." ".BadName($Tic{'FILE'})." ".$AreaPath{$ticarea}." ".$ticarea;
		}
	}

	if( defined( $AreaNewfile{$ticarea} )) {
		if( ! -e $AreaNewfile{$ticarea} ) {
			$crfile = ">";
		} else {
			$crfile = ">>";
		}
		if( ! open( t, $crfile.$AreaNewfile{$ticarea} )) {
			&logger( 0, "Cannot write annonce. Error: $!");
		} else {
#			if( $crfile eq ">" ) {
#				print t "File             Size         Area                 Origin\n";
#				print t "---------------- ------------ -------------------- ----------------\n";
#			}
			print t sprintf( "%s %s %d %s", $ticarea, $Tic{'FILE'}, $Tic{'SIZE'}, $Tic{'ORIGIN'} );
			print t " ";
#			print t "Fullname: ".$Tic{'FULLNAME'}."\n" if( defined( $Tic{'FULLNAME'} ));
			for( $i = 0; $i <= $#TicDesc; $i++ ) {
				print t $TicDesc[$i].' '; #.\n
			}
			if( $#TicLDesc > -1 ) {
#				print t "\n";
				for( $i = 0; $i <= $#TicLDesc; $i++ ) {
					print t $TicLDesc[$i].' '; #."\n";
				}
			}
#			print t "-------------------------------------------------------------------\n";
                        print t "\n";
			close( t );

		}
	}
	return 1;
}
sub Manager {
	local( @files, $file );

	if( ! &TestConfig( 'QUEUE' )) {
		&logger( 0, "Not define Queue path in config file.");
		return 0;
	}
	&ReadUsers() || return 0;
	&ReadAreas() || return 0;

	@files = <$FConfig{'QUEUE'}/*>;

	foreach $file (@files) {
        	if( -f $file ) {
			if( !open(IN,$file)) {
				&logger( 0,"Cannot open queue file $file");
				next;
			}
			if( &Manager1() ) {
				close( IN );
				unlink( $file ) || &logger( 0, "Cannot unlink queue file $file");
			} else {
				close( IN );
				&logger( 0, "Bad message header in message ".&basename($file)." - moving to $FConfig{'QUEUE'}/bad");
				mkdir( "$FConfig{'QUEUE'}/bad", 0777 ) || (&logger( 0, "Cannot make directory $FConfig{'QUEUE'}/bad"), next) unless ( -d "$FConfig{'QUEUE'}/bad" );
				rename( $file,"$FConfig{'QUEUE'}/bad/".&basename($file) ) || &logger( 0, "Cannot move $file to $FConfig{'QUEUE'}/bad");
			}
		}
	}
}

sub Manager1 {
	local( $Cmd, $Args );

	undef($UAddr);
	undef($UHost);

	&ReadHeader() || return 0;
	open( OUT, "| ".$FConfig{'MAILCOMMAND'} );
#	open( OUT, "> out_mail" );
	if( defined( $FConfig{'ROBOTNAME'} )) {
		print OUT "From: ".$FConfig{'ROBOTNAME'}." <".$FConfig{'ROBOTNAME'}."\@".$FConfig{'MYFQDN'}.">\n";
	} else {
		print OUT "From: FileFix-Robot <FileFix-Robot\@".$FConfig{'MYFQDN'}.">\n";
	}
	print OUT "To: $UAddr\n";
	print OUT "Subject: Reply from Area Manager\n\n";

	if( &find( $UHost, @UserAddr ) == -1 ) {
		&logger( 3, "Unknown user $UHost");
		&flame_nouser();
		return 0;
	}
	if( &toupper( $UserPasswd{$UHost} ) ne &toupper( $Subject )) {
		&logger( 3, "Passwd error [$UHost] : is \"$Subject\", should by \"$UserPasswd{$UHost}\".");
		&flame_nopasswd();
		return 0;
	}

	undef $ChangeAreas;
	undef $ChangeUsers;

	&logger( 5, "Reply to $UHost...");
	while( <IN> ) {
		chop;
		next if( /^[ \t]*$/ );
		if( /^\-\-+/ ) {
			print OUT "> --\nEnd.\n";
			last;
		}
		if( /^[ \t]*%/ ) {
			print OUT "\n> $_\n";
			( $Cmd, $Args ) = split( /[ \t]+/, $_, 2 );
			if( $Cmd =~ /%[Hh][Ee][Ll][Pp]/ ) {
				&logger( 5, "Processing %HELP...");
				&flame_help();
				next;
			} elsif( $Cmd =~ /%[Ll][Ii][Ss][Tt]/ ) {
				&logger( 5, "Processing %LIST...");
				&print_list( 0 );
				next;
			} elsif( $Cmd =~ /%[Ll][Ii][Nn][Kk][Ee][Dd]/ ) {
				&logger( 5, "Processing %LINKED...");
				&print_list( 1 );
				next;
			} elsif( $Cmd =~ /%[Uu][Nn][Ll][Ii][Nn][Kk][Ee][Dd]/ ) {
				&logger( 5, "Processing %UNLINKED...");
				&print_list( -1 );
				next;
			} elsif( $Cmd =~ /%[Pp][Aa][Uu][Ss][Ee]/ ) {
				&logger( 5, "Processing %PAUSE...");
				&paused_area( $Args );
				next;
			} elsif( $Cmd =~ /%[Rr][Ee][Ss][Uu][Mm][Ee]/ ) {
				&logger( 5, "Processing %RESUME...");
				&resumed_area( $Args );
				next;
			} elsif( $Cmd =~ /%[Pp][Aa][Ss][Ss][Ww][Dd]/ ) {
				&logger( 5, "Processing %PASSWD...");
				&change_passwd( $Args );
				next;
			} else {
				print OUT "Warning: Unknown command. See %HELP\n";
				next;
			}
		} elsif( /^[ \t]*-/ ) {
			&unlink_area( $_ );
			next;
		} else {
			&link_area( $_ );
			next;
		}
	}
	if( defined( $ChangeAreas )) {
		print OUT "\n";
		if( ! &WriteAreas() ) {
			print OUT "\nERROR: Areas not linked and/or unlinked, internal error.\n";
		}
	}
	if( defined( $ChangeUsers )) {
		if( ! &WriteUsers() ) {
			print OUT "\nPassword not changed, internal error.\n";
		}
	}
	print OUT "\n--\n\t$Version of ".$FConfig{'ADDRESS'}."\n";
	close( OUT );

	return 1;
}

sub ReadHeader {
	undef( $From );
	undef( $Uzone );
	undef( $Unet );
	undef( $UNode );
	undef( $UHost );
	undef( $UPoint );
	undef( $Subject);
	while( <IN> ) {
		chop;
		last if( /^\s*$/ ); # end of header
		next unless(( $key, $value ) = /([^:]+):\s+(.*$)/ );
		$Subject = $value if( $key =~ /^Subject/ );
#
		$From = $value if( $key =~ /^From/ && !defined($From));
#		&logger( 3, " $key .. $value");

	}
	return 0 unless( defined( $Subject ) && defined( $From ));
	if( $From =~ /[^<]*<(\S+@\S+)>/ ) {
		$UAddr = $1;
	} elsif( $From =~ m/(\S+@\S+)\s+[\(][^\)]+[\)]/ ) {
		$UAddr = $1;
	} else {
		$UAddr = $From;
	}
	( $UName, $UHost ) = split( "@", $UAddr );
	$UName =~ s/[\._]/ /;
	@ftn = split( /\./, $UHost );
	for( $i = 0; $i <= $#ftn; $i++ ) {
		$UZone = $ftn[$i] if( $ftn[$i] =~ /z[0-9]+/ );
		$UNet = $ftn[$i] if( $ftn[$i] =~ /n[0-9]+/ );
		$UNode = $ftn[$i] if( $ftn[$i] =~ /f[0-9]+/ );
		$UPoint = $ftn[$i] if( $ftn[$i] =~ /p[0-9]+/ );
	}
	$UZone =~ s/z//;
	$UNet =~ s/n//;
	$UNode =~ s/f//;
	$UPoint =~ s/p// if( defined( $UPoint ));
	$UHost = $UZone.":".$UNet."/".$UNode;
	$UHost .= ".".$UPoint if( defined( $UPoint ));
	return 1;
}

sub flame_nouser {
	print OUT "\nDear ".$UName."!\n\n";
	print OUT "I'm terribly sorry, but your site is not present\n";
	print OUT "in our Users file, so, you can not access\n";
	print OUT "Area Manager on this node. Please, contact with\n";
	print OUT $FConfig{'SYSOP'}.", our system operator.\n";
	print OUT "\n--\n\t$Version\n";
	close( OUT );
}

sub flame_nopasswd {
	print OUT "\nDear ".$UName."!\n\n";
	print OUT "You gave incorrect password for Area Manager, so,\n";
	print OUT "your FileFix query will be refused. Please repeat\n";
	print OUT "your request with correct password or contact with\n";
	print OUT $FConfig{'SYSOP'}.", our system operator.\n";
	print OUT "\n--\n\t$Version\n";
	close( OUT );
}

sub flame_help {
	local( $helpfile );
	if( ! &TestConfig( 'HELPFILE' )) {
		&logger( 0, "Help file not found.");
		print OUT "Problem with help file.\n\n";
		return 0;
	}
	if( ! open( helpfile, $FConfig{'HELPFILE'} )) {
		&logger( 0, "Cannot open help file [$!].");
		print OUT "Problem with help file.\n\n";
		return 0;
	}
	while( <helpfile> ) {
		print OUT $_;
	}
	close( helpfile );
	print OUT "\n\n";
	return 1;
}

sub print_list {
	local( $i, $j, $area, $desc, $flg, @links, $ag );
	for( $i = 0; $i <= $#AreaName; $i++ ) {
		$area = $AreaName[$i];
		$desc = $AreaDesc{$area};
		$flg = " ";
		if( $area !~ '^default$' ) {
			$ag = $AreaGroup{$area};
			if( $UserGroups{$UHost} !~ /$ag/ ) {
				$flg = "!";
			}
#			if(( $AreaLinks{$area} =~ /$UHost[^\.]/ ) || ( $AreaLinks{$area} =~ /$UHost$/ )) {
			if(( $AreaLinks{$area} =~ /$UHost / ) || ( $AreaLinks{$area} =~ /$UHost$/ )) {
				if( $AreaLinks{$area} =~ /-!*$UHost[^\.]/ ) {
					$flg = "-";
				} else {
					$flg = "+";
				}
			}
			$desc = "Description missing" if( $desc =~ /^[ \t]*$/ );
			if(( $_[0] == 0 ) ||
				(( $_[0] == -1 ) && (( $flg eq " " ) || ( $flg eq "!" ))) ||
				(( $_[0] == 1 ) && (( $flg ne " " ) && ( $flg ne "!" )))) {
				print OUT sprintf( "%s %-20s\t%s\n", $flg, $area, $desc );
			}
		}
	}
	print OUT "\n";
	print OUT "     + This area is linked\n" if( $_[0] != -1 );
	print OUT "     - This area is paused\n" if( $_[0] != -1 );
	print OUT "     ! This area is restricted\n" if( $_[0] != 1 );
	print OUT "\n\n";
	return 1;
}

sub paused_area {
	local( @areas );
	local( @links, $fndlnk, $nlinks, $ac );
	local( $i, $j, $p, $r );

	@areas = split( /[ \t]+/, toupper( $_[0] ));
	$ac = $#areas;
	@areas = @AreaName if( $ac < 0 );
	for( $i = 0; $i <= $#areas; $i++ ) {
		next if( $areas[$i] =~ /default/i );
		if( defined( $AreaLinks{$areas[$i]} )) {
			@links = split( /[ \t]+/, $AreaLinks{$areas[$i]} );
			$fndlnk = 0;
			$nlinks = "";
			for( $j = 0; $j <= $#links; $j++ ) {
				if( $links[$j] =~ /\!/ ) {
					$r = "!";
					$links[$j] =~ s/\!//;
				} else {
					$r = "";
				}
				if( $links[$j] =~ /\-/ ) {
					$p = "-";
					$links[$j] =~ s/\-//;
				} else {
					$p = "";
				}
				if( $links[$j] eq $UHost ) {
					$fndlnk = 1;
					if( $p eq "-" ) {
						print OUT $areas[$i]." - already paused.\n";
						&logger( 5, "pause $areas[$i] - already paused.");
					} else {
						$p = "-";
						print OUT $areas[$i]." - paused.\n";
						&logger( 5, "pause $areas[$i] - paused.");
						$ChangeAreas = 1;
					}
				}
				$nlinks .= " ".$p.$r.$links[$j];
			}
			$AreaLinks{$areas[$i]} = $nlinks;
			if(( $fndlnk == 0 ) && ( $ac >= 0 )) {
				print OUT $areas[$i]." - not linked.\n";
				&logger( 5, "pause $areas[$i] - not linked." );
			}
		} else {
			print OUT $areas[$i]." - not found.\n";
			&logger( 5, "pause $areas[$i] - not found.");
		}
	}
}

sub resumed_area {
	local( @areas );
	local( @links, $fndlnk, $nlinks, $ac );
	local( $i, $j, $p, $r );

	@areas = split( /[ \t]+/, toupper( $_[0] ));
	$ac = $#areas;
	@areas = @AreaName if( $ac < 0 );
	for( $i = 0; $i <= $#areas; $i++ ) {
		next if( $areas[$i] =~ /default/i );
		if( defined( $AreaLinks{$areas[$i]} )) {
			@links = split( /[ \t]+/, $AreaLinks{$areas[$i]} );
			$fndlnk = 0;
			$nlinks = "";
			for( $j = 0; $j <= $#links; $j++ ) {
				if( $links[$j] =~ /\!/ ) {
					$r = "!";
					$links[$j] =~ s/\!//;
				} else {
					$r = "";
				}
				if( $links[$j] =~ /\-/ ) {
					$p = "-";
					$links[$j] =~ s/\-//;
				} else {
					$p = "";
				}
				if( $links[$j] eq $UHost ) {
					$fndlnk = 1;
					if( $p eq "" ) {
						print OUT $areas[$i]." - not paused.\n";
						&logger( 5, "resume $areas[$i] - not paused." );
					} else {
						$p = "";
						print OUT $areas[$i]." - resumed.\n";
						&logger( 5, "resume $areas[$i] - resumed." );
						$ChangeAreas = 1;
					}
				}
				$nlinks .= " ".$p.$r.$links[$j];
			}
			$AreaLinks{$areas[$i]} = $nlinks;
			if(( $fndlnk == 0 ) && ( $ac >= 0 )) {
				print OUT $areas[$i]." - not linked.\n";
				&logger( 5, "resume $areas[$i] - not linked." );
			}
		} else {
			print OUT $areas[$i]." - not found.\n";
			&logger( 5, "resume $areas[$i] - not found.");
		}
	}
}

sub change_passwd {
	local( $key, $value ) = split( /[ \t]+/, $_[0] );
	if( $value =~ /^[ \t]*$/ ) {
		print OUT "Password not changed.\n\n";
	} else {
		$UserPasswd{$UHost} = $value;
		$ChangeUsers = 1;
		print OUT "Password changed, new password \"$value\"\n\n";
	}
}

sub link_area {
	local( $i, $area, $ag );
	$area = $_[0];
	$area =~ s/\+//;
	$area =~ tr/a-z/A-Z/;
	for( $i = 0; $i <= $#AreaName; $i++ ) {
		next if( $AreaName[$i] eq "DEFAULT" );
		last if( $AreaName[$i] eq $area );
	}
	if( $i > $#AreaName ) {
		print OUT "$area - not found.\n";
		&logger( 5, "+$area - not found." );
		return 0;
	}
#	if(( $AreaLinks{$area} =~ /$UHost[^\.]/ ) || ( $AreaLinks{$area} =~ /$UHost$/ )) {
	if(( $AreaLinks{$area} =~ /$UHost / ) || ( $AreaLinks{$area} =~ /$UHost$/ )) {
		print OUT "$area - already linked.\n";
		&logger( 5, "+$area - already linked." );
		return 0;
	}
	$ag = $AreaGroup{$area};
	if( $UserGroups{$UHost} !~ /$ag/ ) {
		print OUT "$area - restricted.\n";
		&logger( 5, "+$area - restricted." );
		return 0;
	}
	if( $UserFlags{$UHost} =~ /\+\!/ ) {
		$AreaLinks{$area} .= " !".$UHost;
		&logger( 5, "+$area - linked [RO]." );
	} elsif( $AreaRO{$area} ) {
		$AreaLinks{$area} .= " !".$UHost;
		&logger( 5, "+$area - linked [RO]." );
	} else {
		$AreaLinks{$area} .= " ".$UHost;
		&logger( 5, "+$area - linked [RW]." );
	}
	print OUT "$area - linked.\n";
	$ChangeAreas = 1;
	return 1;
}

sub unlink_area {
	local( $i, $area, $ag, $links );
	$area = $_[0];
	$area =~ s/\-//;
	$area =~ tr/a-z/A-Z/;
	for( $i = 0; $i <= $#AreaName; $i++ ) {
		next if( $AreaName[$i] eq "DEFAULT" );
		last if( $AreaName[$i] eq $area );
	}
	if( $i > $#AreaName ) {
		print OUT "$area - not found.\n";
		&logger( 5, "$area - not found." );
		return 0;
	}
#	if( ! (( $AreaLinks{$area} =~ /$UHost[^\.]/ ) || ( $AreaLinks{$area} =~ /$UHost$/ ))) {
	if( ! (( $AreaLinks{$area} =~ /$UHost / ) || ( $AreaLinks{$area} =~ /$UHost$/ ))) {
		print OUT "$area - not linked.\n";
		&logger( 5, "$area - not linked." );
		return 0;
	}
	@links = split( /[ \t]+/, $AreaLinks{$area} );
	$AreaLinks{$area} = "";
	for( $i = 0; $i <= $#links; $i++ ) {
		next if( $links[$i] =~ /$UHost$/ );
		$AreaLinks{$area} .= " ".$links[$i];
	}
	print OUT "$area - unlinked.\n";
	&logger( 5, "$area - unlinked.");
	$AreaLinks{$area} =~ s/^ //;
	$ChangeAreas = 1;
	return 1;
}

sub Scaner {
	local( $i );
	local( $outpath );
	$ScanTime = time;
#	if( defined( $FConfig{'LASTSCAN'} )) {
#		if( ! -e $FConfig{'LASTSCAN'} ) {
#			system "touch $FConfig{'LASTSCAN'}";
#			&logger( 0, "Do nothing - LastScan file not found. Creating.");
#			return 1;
#		}
#		$LastScanTime = ( stat( $FConfig{'LASTSCAN'} ))[9];
#		utime $ScanTime, $ScanTime, $FConfig{'LASTSCAN'};
#	} else {
#		$LastScanTime = $ScanTime;
#	}

	&ReadAreas() || return 0;
	&ReadUsers() || return 0;

	undef( %UserSaved );
	for( $i = 0; $i <= $#UserAddr; $i++ ) {
		$UserSaved{$UserAddr[$i]} = 1;
	}
	for( $i = 0; $i <= $#AreaName; $i++ ) {
		next if( $AreaName[$i] =~ /^default/ );
		&ScanArea( $AreaName[$i] );
		&UPDateArea( $AreaName[$i] );
	}
	if( $FConfig{'SENDANNOUNCE'} =~ /^[yY]/ ) {
		&MessageOfNewFilesSort();
	}
#scan saved files
	for( $i = 0; $i <= $#UserAddr; $i++ ) {
		next if( $UserSaved{$UserAddr[$i]} == 0 );
		if( $UserFlags{$UserAddr[$i]} =~ /\+[hH]/ ) {
			$suffix = ".hlo";
		} else {
			$suffix = ".flo";
		}
		$outpath = &OutPath( $UserAddr[$i] );
		if( &mklock( $outpath.".bsy", 1 )) {
			&ScanSaved( $outpath, $suffix, $UserAddr[$i] );
			unlink( $outpath.".bsy" );
		}
	}
#	for( $i = 0; $i <= $#AreaName; $i++ ) {
#		next if( $AreaName[$i] =~ /^default/ );
#		&UPDateArea( $AreaName[$i] );
#	}
	return 1;
}

sub UPDateArea {
 	local ($chkarea) = $_[0];
        local ( $filetime, $File);
        local ( $num ) = 0;

	if( !defined( $AreaSave{$chkarea} ) || ( $AreaSave{$chkarea} < 0 )) {
     	&logger( 0, "$chkarea is on hold. No expire..." );
        } else {
     	 &logger( 0, "Updating $chkarea..." );
   	 if( ! open( OUT,">".$AreaPath{$chkarea}."/".$FConfig{'FILESBBS'}.'.up'))
   	 {
     		&logger( 0, "Cannot open $FConfig{'FILESBBS'}.up - Cannot expire: $!" );
	 }
	 else
   	 {
   	  if( ! open( IN, $AreaPath{$chkarea}."/".$FConfig{'FILESBBS'} ))
   	  {
     		&logger( 0, "Cannot open $FConfig{'FILESBBS'}. Error: $!" );
	  }
	  else
   	  {
		while(<IN>)
		{
			if (/([^\s@]+)/)
			{
		        	$File = $1;
			}
			$filetime = (stat ($AreaPath{$chkarea}."/".$File))[9];
                        if ($AreaSave{$chkarea} == 0){
					&logger( 5, "File ".BadName( $File )." removed. Passthru area.");
					system ("$RM -f ".$AreaPath{$chkarea}."/".BadName($File)." 2>/dev/null");
					$num++;
                        } elsif (( $filetime + $AreaSave{$chkarea} * 86400 ) < time ) {
					&logger( 5, "File ".BadName( $File )." too old, removed.");
					system ("$RM -f ".$AreaPath{$chkarea}."/".BadName($File)." 2>/dev/null");
					$num++;
			} else
		        {
				print OUT $_;
		        }
		        	$File = '';
		}
	  }
         }
        close (IN);
        close (OUT);
   	system( "$MV $AreaPath{$chkarea}/$FConfig{'FILESBBS'}.up $AreaPath{$chkarea}/$FConfig{'FILESBBS'}  2>/dev/null");
     	&logger( 0, "FEcho: $chkarea, Del: $num files." );

	}
}


sub RemoveIfExist {
	local( $file ) = $_[0];
	local( $name, $path, $tics );

	return if( ! -e $file );

	system "rm -f ".$file;
	$path = basepath( $file );
	$name = basename( $file );
	$name = &toupper( $name );
	return if( ! open( tics, "grep -li ".BadName($name)." $path/*.[Tt][Ii][Cc] 2>/dev/null |" ));
	while( <tics> ) {
		chop;
		system "rm -f ".$_;
	}
	close( tics );
}

sub ScanSaved {
	local( $outpath ) = $_[0];
	local( $suffix ) = $_[1];
	local( $faddr ) = $_[2];
	local( $lo, $oplo, $slo, $sto, $sfrom );
	$oplo = 0;
	if( -s $outpath.".ofl/save.flo" ) {
		if( !open( slo, $outpath.".ofl/save.flo" )) {
			&logger( 0, "Cannot read ".$outpath.".ofl/save.flo for $links[$i] [$!].");
		} else {
			while( <slo> ) {
				chop;
				next if( /^[ \t]*$/ );
				if( $oplo == 0 ) {
					if( ! open( lo, ">>".$outpath.$suffix )) {
						&logger( 0, "Cannot write $outpath.$suffix for $links[$i] [$!]." );
						unlink( $outpath.".bsy" );
						last;
					}
					$oplo = 1;
				}
				$sto = $_;
				$sto =~ s/^\^//;
				$sfrom = $sto;
				$sfrom =~ s/\.flx\//.ofl\//;
				next if( ! -e $sfrom );
				&RemoveIfExist( $sto ) if( $sto !~ /\.[tT][iI][cC]$/ );
				if( link( $sfrom, $sto )) {
					print lo "^".$sto."\n";
					&logger( 3, "Send ".&basename( $sto )." to ".$faddr) if( $sto !~ /\.tic/i );
					unlink( $sfrom );
				}
			}
			close( slo );
			unlink( $outpath.".ofl/save.flo" ) if( $oplo );
		}
	}
	close( lo ) if( $oplo );
	$oplo = 0;
	if( -s $outpath.".ofl/save.hlo" ) {
		if( !open( slo, $outpath.".ofl/save.hlo" )) {
			&logger( 0, "Cannot read ".$outpath.".ofl/save.hlo for $links[$i] [$!].");
		} else {
			while( <slo> ) {
				chop;
				next if( /^[ \t]*$/ );
				if( $oplo == 0 ) {
					if( ! open( lo, ">>".$outpath.$suffix )) {
						&logger( 0, "Cannot write $outpath.$suffix for $links[$i] [$!].");
						unlink( $outpath.".bsy" );
						last;
					}
					$oplo = 1;
				}
				$sto = $_;
				$sto =~ s/^\^//;
				$sfrom = $sto;
				$sfrom =~ s/\.flx\//.ofl\//;
				next if( ! -e $sfrom );
				&RemoveIfExist( $sto ) if( $sto !~ /\.[tT][iI][cC]$/ );
				if( link( $sfrom, $sto )) {
					print lo "^".$sto."\n";
					&logger( 3, "Send ".&basename( $sto )." to ".$faddr) if( $sto !~ /\.tic/i );
					unlink( $sfrom );
				}
			}
			close( slo );
			unlink( $outpath.".ofl/save.hlo" ) if( $oplo );
		}
	}
	close( lo ) if( $oplo );
}

sub OutPath {
	local( $addr ) = $_[0];
	local( $mdir ) = 0;
	local( $path );
	local( $zone, $net, $node, $point );

	$mdir = $_[1] if( defined( $_[1] ));
	( $zone, $net, $node, $point ) = &ParseAddr( $addr );
	$path = $FConfig{'OUTBOUND'};
	$path = $path.sprintf( ".%03d", $zone ) if( $zone != $my_zone );
	if( $mdir && ( !-d $path )) {
		if( ! mkdir( $path, 0700 )) {
			&logger( 0, "Cannot create directory $path [$!]." );
			return "";
		}
	}
	$path = $path.sprintf( "/%04x%04x", $net, $node );
	if( ! $point ) {
		return $path;
	} else {
		$path = $path.".pnt";
		if( $mdir && ( !-d $path )) {
			if( ! mkdir( $path, 0700 )) {
				&logger( 0, "Cannot create directory $path [$!]." );
				return "";
			}
		}
		$path = $path.sprintf( "/%08x", $point );
		return $path;
	}
}

sub ScanArea {
	local( $area ) = $_[0];
	local( $hdir, $dfile, $exclude, $i, $ftime, $fmode, $tics, $ticdir, $ftic, $links, $myaddr );
	local( $SaveTic, $SaveTicDesc, $SaveTicLDesc, $SaveTicPath, $SaveTicSeenby );
	local( $OldFrom, $announce, $crfile, $t );
	local( $zone, $net, $node, $point, $atmp );
	local( $outpath, $descdir, $stics, $sto, $sfrom );

	if( ! open( hdir, "cd $AreaPath{$area};$LS -1 *.desc 2>/dev/null |" )) {
		&logger( 0, "Cannot open list directory for $area [$!]." );
		return 0;
	}

	@exclude = split( /'*[ \t]+'*/, " ".$AreaExclude{$area}." " );
	if( $FConfig{'DESCDIR'} =~ /^\// ) {
		$descdir = $FConfig{'DESCDIR'};
	} else {
		$descdir = $AreaPath{$area}."/".$FConfig{'DESCDIR'};
	}
#input:	while(( $dfile = readdir( hdir )) ne "" ) {
input:	while(<hdir>) {
		s/[\n]//g;
		$dfile_desc = $_;
		$dfile = $_; $dfile =~ s/\.desc$//;
		next input if( $dfile =~ /^\.{1,}/ ); 		   #    "."
		next input if( ! -f $AreaPath{$area}."/".$dfile ); #    
#		next input if( $dfile =~ /^\.\.*$/ );
#		next input if( ! -f $AreaPath{$area}."/".$dfile );
		for( $i = 0; $i <= $#exclude; $i++ ) {
			next if( $exclude[$i] eq "" );
			next input if( $dfile =~ /$exclude[$i]/ );
		}
#                $dfile
		$ftime = ( stat( $AreaPath{$area}."/".BadName( $dfile) ))[9];
		&logger(0, "New: $area $dfile");
#		$fmode = ( stat( $AreaPath{$area}."/".$dfile ))[2];
#		if( defined( $AreaSave{$area} ) && ( $AreaSave{$area} > 0 )) {
#			if(( $ftime + $AreaSave{$area} * 86400 ) < $ScanTime ) {
#				&logger( 5, "File ".BadName( $dfile )." too old, removed.");
#				system "rm -f ".$AreaPath{$area}."/".BadName($dfile)." ".$descdir."/".BadName($dfile).".desc";
#				next input;
#			}
#		}
#
#		if( defined( $FConfig{'LASTSCAN'} )) {
#			next input if( $ftime < $LastScanTime );
#		} else {
#			next input if(( $fmode & 01000 ) == 0 );
#			$fmode = sprintf( "chmod 0%o, \"%s\"", $fmode ^ 01000, $AreaPath{$area}."/".BadName($dfile));
#			if( ! eval $fmode ) {
#				&logger( 0, "Cannot clear sticky bit on ".$AreaPath{$area}."/".BadName($dfile).". Hatch abort. $!");
#				next input;
#			}
#		}

		$ftic = "";
		undef %Tic;
		undef @TicVia;
		undef @TicDesc;
		undef @TicLDesc;
		undef @TicPath;
		undef @TicSeenby;
		$announce = 1;
		if( &TestConfig( 'TICDIR' )) {
			if( $FConfig{'TICDIR'} =~ /^\// ) {
				$ticdir = $FConfig{'TICDIR'};
			} else {
				$ticdir = $AreaPath{$area}."/".$FConfig{'TICDIR'};
			}
			$df = &toupper( $dfile );
			if( open( tics, "grep -li ".BadName($df)." $ticdir/*.[Tt][Ii][Cc] 2>/dev/null |" )) {
				$ftic = <tics>;
				chop $ftic;
				close( tics );
				&ReadTic( $ftic ) if( $ftic ne "" );
				system "rm -f $ftic";
#				system "/bin/mv -f $ftic /var/spool/old.tics";
				$announce = 0 if( $#TicPath >= 0 );
			}
		}
		if( defined( $AreaAKA{$area} )) {
			$myaddr = $AreaAKA{$area};
		} else {
			$myaddr = $FConfig{'ADDRESS'};
		}
		$Tic{'FILE'} = $dfile if( ! defined( $Tic{'FILE'} ));
		$Tic{'AREA'} = $area if( ! defined( $Tic{'AREA'} ));
		$Tic{'ORIGIN'} = $myaddr if( ! defined( $Tic{'ORIGIN'} ));
		if( defined( $Tic{'FROM'} )) {
			$OldFrom = $Tic{'FROM'};
		} else {
			$OldFrom = "";
		}
		$Tic{'FROM'} = $myaddr;
		$Tic{'SIZE'} = ( stat( $AreaPath{$area}."/".$dfile ))[7] if( ! defined( $Tic{'SIZE'} ));
		$Tic{'DATE'} = $ftime if( ! defined( $Tic{'DATE'} ));
		if( ! defined( $Tic{'CRC'} )) {
			if( open( tics, "$FConfig{'BINDIR'}/crc32 < $AreaPath{$area}/".BadName($dfile)." |" ))  {
				$Tic{'CRC'} = <tics>;
				chop $Tic{'CRC'};
				close( tics );
			} else {
				&logger( 5, "Cannot calculate CRC for ".BadName($dfile).".");
			}
		}
		if( $#TicDesc == -1 ) {
			$i = 0;
			undef @TicLDesc;
			if( open( tics, $descdir."/".BadName($dfile).".desc" )) {
				while( <tics> ) {
					chop;
					if( /^[ \t]*$/ ) {
						$i = 1;
						next;
					}
					if( $i == 0 ) {
						$TicDesc[$#TicDesc + 1] = $_;
					} else {
						$TicLDesc[$#TicLDesc + 1] = $_;
					}
				}
				close( tics );
			} else {
				&logger( 5, "Cannot find descriptor for ".$dfile.".");
## if not send without descriptor
				next input;
## else
#				if( &TestConfig( 'DEFDESC' )) {
#					$TicDesc[0] = $FConfig{'DEFDESC'};
#				} else {
#					$TicDesc[0] = "Descriptor missing";
#				}
# end if
			}
		}
#                &logger(0, "  - $announce, $area, $AreaNewfile{$area} ");
		if( $announce ) {
			if( defined( $AreaNewfile{$area} )) {
				if( ! -e $AreaNewfile{$area} ) {
					$crfile = ">";
				} else {
					$crfile = ">>";
				}
				if( ! open( t, $crfile.$AreaNewfile{$area} )) {
					&logger( 0, "Cannot write annonce. Error: $!");
					&logger(0,"File-announce $AreaNewfile{$area}");
					$announce = 0;
				} else {
					printf(t "%s %s %d %s", $area, $Tic{'FILE'}, $Tic{'SIZE'}, $Tic{'ORIGIN'} );
		       			print t " ";
		       			for( $i = 0; $i <= $#TicDesc; $i++ ) {
			   			print t $TicDesc[$i].' '; #.\n
					}
					if( $#TicLDesc > -1 ) {
						for( $i = 0; $i <= $#TicLDesc; $i++ ) {
				       			print t $TicLDesc[$i].' '; #."\n";
						}
					}
                        		print t "\n";
					close( t );

				}
			}

		}
		$TicPath[$#TicPath + 1] = $myaddr." ".&strtime( 'path' );
		undef @links;
		undef @slinks;
		@links = split( /[ \t]+/, $AreaLinks{$area} );
		for( $i = 0; $i <= $#links; $i++ ) {
			if( find( $links[$i], @TicSeenby ) == -1 ) {
				$slinks[$#slinks+1] = $links[$i];
			}
		}
		if( defined( $AreaAKA{$area} )) {
			@links = split( /[ \t]+/, $FConfig{'ADDRESS'}." ".$AreaLinks{$area} );
		}
		if( &find( $myaddr, @links ) == -1 ) {
			$links[$#links+1] = $myaddr;
		}
		for( $i = 0; $i <= $#links; $i++ ) {
			next if( $links[$i] =~ /^\!*\-\!*/ );
			$links[$i] =~ s/\!//;
 			if(( $links[$i] ne $OldFrom ) && ( &find( $links[$i], @TicSeenby ) == -1 )) {
				$TicSeenby[$#TicSeenby + 1] = $links[$i];
			}
		}
		@links = @slinks;
		for( $i = 0; $i <= $#TicSeenby; $i++ ) {
			$TicSeenby[$i] = sprintf( "%05d%05d%05d%05d", &ParseAddr( $TicSeenby[$i] ));
		}
		@atmp = @TicSeenby;
		@TicSeenby = sort { $a <=> $b } @atmp;
		for( $i = 0; $i <= $#TicSeenby; $i++ ) {
			( $zone, $net, $node, $point ) = ( $TicSeenby[$i] =~ /([0-9]{5})([0-9]{5})([0-9]{5})([0-9]{5})/ );
			if( $point =~ /^0+$/ ) {
				$TicSeenby[$i] = sprintf( "%d:%d/%d", $zone, $net, $node );
			} else {
				$TicSeenby[$i] = sprintf( "%d:%d/%d.%d", $zone, $net, $node, $point );
			}
		}
		%SaveTic = %Tic;

		$atmp = $FConfig{'OUTBOUND'}."/".$dfile;
		if( ! -e $atmp ) {
			system "cp $AreaPath{$area}/".BadName($dfile)." ".$FConfig{'OUTBOUND'}."/".&BadName($dfile);
		}
		if( ! -e $atmp ) {
			&logger( 0, "Cannot copy ".BadName($dfile)." in to outbound [$!]." );
			return 0;
		}
#Files.bbs
#     files.bbs
#         
		&ProcessFilesBbs($area);
# SEENBY ,    
		for( $i = 0; $i <= $#links; $i++ ) {
			next if( $links[$i] =~ /^\!*\-/ );
			$links[$i] =~ s/\!//;
			next if( $links[$i] eq $OldFrom );
			%Tic = %SaveTic;
			$Tic{'TO'} = $links[$i];
			$Tic{'PW'} = $UserPasswd{$links[$i]};
			$ftic = &MakeTicName( $links[$i], $dfile, $area );
			if( $UserFlags{$links[$i]} =~ /\+[hH]/ ) {
				$suffix = ".hlo";
			} else {
				$suffix = ".flo";
			}
			$outpath = $FConfig{'OUTBOUND'};
			if( ! -d $outpath ) {
				if( ! mkdir( $outpath, 0700 )) {
					&logger( 0, "Cannot create filefix directory [$!].");
					next;
				}
			}
			$outpath = &OutPath( $links[$i], 1 );
			if( ! -d $outpath.".flx" ) {
				if( ! mkdir( $outpath.".flx", 0700 )) {
					&logger( 0, "Cannot create directory $outpath.flx [$!].");
					next;
				}
			}
# try make .bsy on link
			if( &mklock( $outpath.".bsy", 1 )) {
# look for save (.bsy) files
				&ScanSaved( $outpath, $suffix, $links[$i] );
# send current files
				if( ! open( tics, ">>".$outpath.$suffix )) {
					&logger( 0, "Cannot write $outpath.$suffix for $links[$i] [$!].");
					unlink( $outpath.".bsy" );
					next;
				}
#				print tics "@".$AreaPath{$area}."/".BadName($dfile)."\n";
				print tics "^".$outpath.".flx/".$dfile."\n";
				print tics "^".$outpath.".flx/".$ftic."\n";
				close( tics );
				&logger( 3, "Send ".$dfile." to $Tic{'TO'}" );
				system "rm -f `grep -li ".BadName($dfile)." ".$outpath.".flx/*.tic 2>/dev/null`";
				&RemoveIfExist( $outpath.".flx/".$dfile );
		     		if( link( $atmp, $outpath.".flx/".$dfile )) {
		     		utime $Tic{'DATE'}, $Tic{'DATE'}, $outpath.".flx/".$dfile;
					&WriteTic( $outpath.".flx/".$ftic );
				} else {
					&logger( 0, "Cannot create link ".$atmp." to ".$outpath.".flx/".$dfile." [$!].");
				}
				unlink( $outpath.".bsy" );
				$UserSaved{$links[$i]} = 0;
			} else {
# .bsy found
				if( ! -d $outpath.".ofl" ) {
					if( ! mkdir( $outpath.".ofl", 0700 )) {
						&logger( 0, "Cannot create directory $outpath.ofl [$!].");
						next;
					}
				}
				if( ! open( tics, ">>".$outpath.".ofl/save".$suffix )) {
					&logger( 0, "Cannot write ".$outpath.".ofl/save".$suffix." for $links[$i] [$!].");
					next;
				}
#				print tics "@".$AreaPath{$area}."/".BadName($dfile)."\n";
				print tics "^".$outpath.".flx/".$dfile."\n";
				print tics "^".$outpath.".flx/".$ftic."\n";
			 	close( tics );
				&logger( 3, "Save ".$dfile." for $Tic{'TO'}");
				system "rm -f `grep -li ".BadName($dfile)." ".$outpath.".ofl/*.tic 2>/dev/null`";
				&RemoveIfExist( $outpath.".ofl/".$dfile );
				if( link( $atmp, $outpath.".ofl/".$dfile )) {
					utime $Tic{'DATE'}, $Tic{'DATE'}, $outpath.".ofl/".$dfile;
					&WriteTic( $outpath.".ofl/".$ftic );
				} else {
					&logger( 0, "Cannot create link ".$atmp." to ".$outpath.".ofl/".$dfile." [$!].");
				}
			}
		}
		unlink $FConfig{'OUTBOUND'}."/".$dfile;
########        desc  !
		system "$RM -f $AreaPath{$area}/".BadName($dfile).".desc";

#		if( defined( $AreaSave{$area} )) {
#			if( $AreaSave{$area} == 0 ) {
#				system "rm -f ".$AreaPath{$area}."/".BadName($dfile)." ".$descdir."/".BadName($dfile).".desc";
#			}
#		}
#		if( defined( $FConfig{'LASTSCAN'} )) {
#			utime $LastScanTime - 1, $LastScanTime - 1, $AreaPath{$area}."/".$dfile;
#		}
	}
	closedir( hdir );
}
sub Namer {
	&ReadAreas() || return 0;
	&SetNames() || return 0;
	&WriteAreas() || return 0;
	return 1;
}

sub SetNames {
	local( @lfiles, $lst );
	local( $flag, $area, $desc, $other );

	if( !&TestConfig( "ECHOLIST" )) {
		&logger( 3, "EchoList not defined." );
		return 0;
	}
	@lfiles = <$FConfig{'ECHOLIST'}>;
	if( $#lfiles == -1 ) {
		&logger( 0, "EchoList not found." );
		return 0;
	}
	if( !open( lst, $lfiles[0] )) {
		&logger( 0, "Cannot open file ".$FConfig{'ECHOLIST'}.". $!");
		return 0;
	}
	&logger( 3, "Setting description for areas.");
	while( <lst> ) {
		chop;
		chop; # ms-dos
		if(( /^Area/i ) || ( /^Down/i ) || ( /^Lost/i ) || ( /^Hold/i )) {
			( $flag, $area, $desc, $other ) = split( /[ \t]+/, $_, 4 );
			$area =~ tr/a-z/A-Z/;
			$desc =~ s/_/ /g;
			$AreaDesc{$area} = $desc;
		}
	}
	close( lst );
	return 1;
}

# @AreaName
# %AreaPath
# %AreaDesc
# %AreaGroup
# %AreaExec
# %AreaExclude
# %AreaSave
# %AreaLinks
# %AreaAKA
# %AreaNewfile
# %AreaMode
# %AreaRO
# %AreaDupes
# %AreaNocheck

sub ReadAreas {
	local( $handle, $Key, $Value, $Area );
	if( ! &TestConfig( 'AREAS' )) {
		&logger( 0, "Undefined Areas in config file.");
		return 0;
	}
	if( ! open( handle, $FConfig{'AREAS'} )) {
		&logger( 0, "Cannot open Areas file.");
		return 0;
	}
	while( <handle> ) {
		/^[ \t]*$/	&& next;
		/^[ \t]*#/	&& next;
		/^[ \t]*-+/	&& next;
		chop;
		( $Key, $Value ) = split( /[ \t]+/, $_, 2 );
		if( $Key =~ /^Area/ ) {
			$Area = $Value;
			$AreaName[$#AreaName + 1] = $Value;
			next;
		} elsif( $#AreaName eq -1 ) {
			&logger( 0, "Expected keyword Area in Areas file." );
			return 0;
		}
		$Key =~ tr/a-z/A-Z/;
		if( $Key =~ /^DESC/ ) {
			$AreaDesc{$Area} = $Value;
		} elsif( $Key =~ /^GROUP/ ) {
			$AreaGroup{$Area} = $Value;
		} elsif( $Key =~ /^PATH/ ) {
			$AreaPath{$Area} = $Value;
		} elsif( $Key =~ /^EXEC/ ) {
			$AreaExec{$Area} = $Value;
		} elsif( $Key =~ /^EXCLUDE/i ) {
			$AreaExclude{$Area} = $Value;
		} elsif( $Key =~ /^SAVE/ ) {
			$AreaSave{$Area} = $Value;
		} elsif( $Key =~ /^LINKS/ ) {
			$AreaLinks{$Area} = $Value;
		} elsif( $Key =~ /^AKA/ ) {
			$AreaAKA{$Area} = $Value;
		} elsif( $Key =~ /^NEWFILE/ ) {
			$AreaNewfile{$Area} = $Value;
		} elsif( $Key =~ /^MODE/ ) {
			$AreaMode{$Area} = $Value;
		} elsif( $Key =~ /^READONLY/ ) {
			$AreaRO{$Area} = 1;
		} elsif( $Key =~ /^DUPECHECK/ ) {
			$AreaDupes{$Area} = $Value;
		} elsif( $Key =~ /^NOCHECK/ ) {
			$AreaNocheck{$Area} = $Value;
		} else {
			&logger( 1, "Unknown $Key in Areas - ignored." );
		}
	}
	close( handle );
	&logger( 7, "Read Areas Ok." );
	return 1;
}

sub WriteAreas {
	local( $handle, $Area, $i, $st );
	@st = stat( $FConfig{'AREAS'} );
	if( ! rename( $FConfig{'AREAS'}, $FConfig{'AREAS'}.".bak" )) {
		&logger( 0, "Cannot rename Areas to Areas.bak." );
		return 0;
	}
	if( ! open( handle, ">".$FConfig{'AREAS'} )) {
		&logger( 0, "Cannot write to Areas file." );
		return 0;
	}
	for( $i = 0; $i <= $#AreaName; $i++ ) {
		$Area = $AreaName[$i];
		print handle "Area\t$Area\n";
		print handle "Desc\t$AreaDesc{$Area}\n" if( defined( $AreaDesc{$Area} ));
		print handle "Group\t$AreaGroup{$Area}\n" if( defined( $AreaGroup{$Area} ));
		print handle "Path\t$AreaPath{$Area}\n" if( defined( $AreaPath{$Area} ));
		print handle "Exec\t$AreaExec{$Area}\n" if( defined( $AreaExec{$Area} ));
		print handle "Exclude\t$AreaExclude{$Area}\n" if( defined( $AreaExclude{$Area} ));
		print handle "Save\t$AreaSave{$Area}\n" if( defined( $AreaSave{$Area} ));
		print handle "Links\t$AreaLinks{$Area}\n" if( defined( $AreaLinks{$Area} ));
		print handle "AKA\t$AreaAKA{$Area}\n" if( defined( $AreaAKA{$Area} ));
		print handle "Newfile\t$AreaNewfile{$Area}\n" if( defined( $AreaNewfile{$Area} ));
		print handle "Mode\t$AreaMode{$Area}\n" if( defined( $AreaMode{$Area} ));
		print handle "ReadOnly\t$AreaRO{$Area}\n" if( defined( $AreaRO{$Area} ));
		print handle "DupeCheck\t$AreaDupes{$Area}\n" if( defined( $AreaDupes{$Area} ));
		print handle "NoCheck\t$AreaNocheck{$Area}\n" if( defined( $AreaNocheck{$Area} ));
		print handle "-" x 70;
		print handle "\n";
	}
	close( handle );
	chmod $st[2], $FConfig{'AREAS'};
	chown $st[4], $st[5], $FConfig{'AREAS'};
	&logger( 7, "Write Areas Ok." );
	return 1;
}

# @UserAddr
# %UserPasswd
# %UserName
# %UserGroups
# %UserFlags
#

sub ReadUsers {
	local( $handle, $Addr, $Passwd, $Name, $Groups, $Flags, $dg );
	if( ! &TestConfig( 'USERS' )) {
		&logger( 0, "Undefined Users in config file." );
		return 0;
	}
	if( ! open( handle, $FConfig{'USERS'} )) {
		&logger( 0, "Cannot open Users file.");
		return 0;
	}
	while( <handle> ) {
		/^[ \t]*$/	&& next;
		/^[ \t]*#/	&& next;
		chop;
		( $Addr, $Passwd, $Name, $Groups, $Flags ) = split( /[ \t]+/, $_, 5 );
		$UserAddr[$#UserAddr + 1] = $Addr;
		$UserPasswd{$Addr} = $Passwd;
		$UserName{$Addr} = $Name;
		$dg="";
		if( &TestConfig( 'DEFGROUP' )) {
			$dg = $FConfig{'DEFGROUP'};
		}
		$Groups =~ s/\*/$dg/g;

		$UserGroups{$Addr} = $Groups;
		$UserFlags{$Addr} = $Flags;
	}
	close( handle );
	&logger( 7, "Read Users Ok.");
	return 1;
}

sub WriteUsers {
	local( $handle, $Addr, $i, $dg, $st );
	@st = stat( $FConfig{'USERS'} );
	if( ! rename( $FConfig{'USERS'}, $FConfig{'USERS'}.".bak" )) {
		&logger( 0, "Cannot rename Users to Users.bak." );
		return 0;
	}
	if( ! open( handle, ">".$FConfig{'USERS'} )) {
		&logger( 0, "Cannot write to Users file.");
		return 0;
	}
	for( $i = 0; $i <= $#UserAddr; $i++ ) {
		$Addr = $UserAddr[$i];
		print handle "$Addr";
		print handle "\t$UserPasswd{$Addr}";
		print handle "\t$UserName{$Addr}";
		if( &TestConfig( 'DEFGROUP' )) {
			$dg = $FConfig{'DEFGROUP'};
			$UserGroups{$Addr} =~ s/$dg/\*/g;
		}
		print handle "\t$UserGroups{$Addr}";
		print handle "\t$UserFlags{$Addr}" if( defined( $UserFlags{$Addr} ));
		print handle "\n";
	}
	close( handle );
	chmod $st[2], $FConfig{'USERS'};
	chown $st[4], $st[5], $FConfig{'USERS'};
	&logger( 7, "Write Users Ok.");
	return 1;
}

sub ReadTic {
	local( $Key, $Value );
	local( $TicFile );
	local( $TicFileName ) = $_[0];
	undef %Tic;
	undef @TicVia;
	undef @TicDesc;
	undef @TicLDesc;
	undef @TicPath;
	undef @TicSeenby;

	if( ! open( TicFile, $FConfig{'DOSTOUNIX'}." <".$TicFileName." | ".$FConfig{'ALTTOKOI'}." |" )) {
		&logger( 0, "Cannot read $TicFileName");
		return 0;
	}
	while( <TicFile> ) {
		chop;
		( $Key, $Value ) = split( /[ \t]+/, $_, 2 );
		$Key =~ tr/a-z/A-Z/;
		if( $Key =~ /^FILE/ ) {
			$Tic{$Key} = &tolower( $Value );
		} elsif( $Key =~ /^REPLACES/ ) {
			$Tic{$Key} = &tolower( $Value );
		} elsif( $Key =~ /^FULLNAME/ ) {
			$Tic{$Key} = $Value;
		} elsif( $Key =~ /^AREA/ ) {
			$Tic{$Key} = $Value;
		} elsif( $Key =~ /^AREADESC/ ) {
			$Tic{$Key} = $Value;
		} elsif( $Key =~ /^ORIGIN/ ) {
			$Tic{$Key} = $Value;
		} elsif( $Key =~ /^FROM/ ) {
			$Tic{$Key} = $Value;
		} elsif( $Key =~ /^TO/ ) {
			$Tic{$Key} = $Value;
		} elsif( $Key =~ /^PW/ ) {
			$Tic{$Key} = $Value;
		} elsif( $Key =~ /^SIZE/ ) {
			$Tic{$Key} = $Value;
		} elsif( $Key =~ /^CRC/ ) {
			$Tic{$Key} = $Value;
		} elsif( $Key =~ /^DATE/ ) {
			$Tic{$Key} = $Value;
		} elsif( $Key =~ /^MAGIC/ ) {
			$Tic{$Key} = $Value;
		} elsif( $Key =~ /^RELEASE/ ) {
			$Tic{$Key} = $Value;
		} elsif( $Key =~ /^AUTHOR/ ) {
			$Tic{$Key} = $Value;
		} elsif( $Key =~ /^APP/ ) {
			$Tic{$Key} = $Value;
		} elsif( $Key =~ /^SOURCE/ ) {
			$Tic{$Key} = $Value;
		} elsif( $Key =~ /^PGP/ ) {
			$Tic{$Key} = $Value;
		} elsif( $Key =~ /^VIA/ ) {
			$TicVia[$#TicVia + 1] = $Value;
		} elsif( $Key =~ /^DESC/ ) {
			$TicDesc[$#TicDesc + 1] = $Value;
		} elsif( $Key =~ /^LDESC/ ) {
			$TicLDesc[$#TicLDesc + 1] = $Value;
		} elsif( $Key =~ /^PATH/ ) {
			$TicPath[$#TicPath + 1] = $Value;
		} elsif( $Key =~ /^SEENBY/ ) {
			$TicSeenby[$#TicSeenby + 1] = $Value;
		}
	}
	close( TicFile );
	return 1;
}

sub MakeTicName {
	local( $handle, $addr, $file, $area, $tic );
	$addr = $_[0];
	$file = $_[1];
	$area = $_[2];
	open( handle, "echo '$addr$file$area' | $FConfig{'BINDIR'}/crc32 |" );
	$tic = <handle>;
	close( handle );
	chop $tic;
	return &tolower( $tic ).".tic";
}

sub WriteTic {
	local( $handle, $Key, $Value, $i );
	local( $TicFile ) = @_;

	if( ! open( handle, "| ".$FConfig{'KOITOALT'}." >".$TicFile )) {
		&logger( 0, "Cannot write $TicFile");
		return 0;
	}
	print handle "Created by ".$Version." ".$FConfig{'STATION'}."\r\n";
	print handle "Area ".$Tic{'AREA'}."\r\n";
	print handle "Areadesc ".$Tic{'AREADESC'}."\r\n" if( defined( $Tic{'AREADESC'} ));
	print handle "File ".&toupper( $Tic{'FILE'} )."\r\n";
	for( $i = 0; $i <= $#TicDesc; $i++ ) {
		print handle "Desc ".$TicDesc[$i]."\r\n";
	}
	for( $i = 0; $i <= $#TicLDesc; $i++ ) {
		print handle "LDesc ".$TicLDesc[$i]."\r\n";
	}
	print handle "Fullname ".$Tic{'FULLNAME'}."\r\n" if( defined( $Tic{'FULLNAME'} ));
	print handle "Replaces ".&toupper( $Tic{'REPLACES'} )."\r\n" if( defined( $Tic{'REPLACES'} ));
	print handle "Size ".$Tic{'SIZE'}."\r\n" if( defined( $Tic{'SIZE'} ));
	print handle "Crc ".$Tic{'CRC'}."\r\n" if( defined( $Tic{'CRC'} ));
	print handle "Date ".$Tic{'DATE'}."\r\n" if( defined( $Tic{'DATE'} ));
	print handle "Magic ".$Tic{'MAGIC'}."\r\n" if( defined( $Tic{'MAGIC'} ));
	print handle "Release ".$Tic{'RELEASE'}."\r\n" if( defined( $Tic{'RELEASE'} ));
	print handle "Author ".$Tic{'AUTHOR'}."\r\n" if( defined( $Tic{'AUTHOR'} ));
	print handle "Origin ".$Tic{'ORIGIN'}."\r\n";
	print handle "Source ".$Tic{'SOURCE'}."\r\n" if( defined( $Tic{'SOURCE'} ));
	print handle "App ".$Tic{'APP'}."\r\n" if( defined( $Tic{'APP'} ));
	print handle "PGP ".$Tic{'PGP'}."\r\n" if( defined( $Tic{'PGP'} ));
	print handle "From ".$Tic{'FROM'}."\r\n";
	print handle "To ".$Tic{'TO'}."\r\n";
	for( $i = 0; $i <= $#TicPath; $i++ ) {
		print handle "Path ".$TicPath[$i]."\r\n";
	}
	if( $#TicVia > 0 ) {
		for( $i = 0; $i <= $#TicVia; $i++ ) {
			print handle "Via ".$TicVia[$i]."\r\n";
		}
		print handle "Via ".$Tic{'FROM'}." ".$Version." ".$FConfig{'STATION'}."\r\n";
	}
	for( $i = 0; $i <= $#TicSeenby; $i++ ) {
		print handle "SeenBy ".$TicSeenby[$i]."\r\n";
	}
	print handle "Pw ".$Tic{'PW'}."\r\n";

	close( handle );
	return 1;
}
