1#!/usr/bin/perl 2 3# Point string processor 4# (c) Stas Degteff 2:5080/102 5# 6# Only "Boss+Point" pointlist format is supported 7 8# $Id$ 9# 10# 11# 12 13$helpmsg = <<HELP ; 14USAGE: 15 $0 16 17Pntstr scan secure inbound directory for files pointstr.* (* = point number) 18and parse its. 19 20Point string file format (with line numbers): 211: Session_password_for_point 222: Pointlist string 23 24HELP 25 26#-----------------------------------------------------------------------------# 27# 28# $Log$ 29# Revision 1.4 2002/12/14 16:21:20 stas_degteff 30# Use full point address 31# 32# Revision 1.3 2002/10/28 08:25:50 stas_degteff 33# Fix shebang 34# 35# Revision 1.2 2002/06/04 11:37:05 stas 36# Some bugs fixed. 37# 38# Revision 1.6 2002/06/03 18:48:27 User 39# Many, many fixes. 40# 41# Revision 1.5 2002/06/02 14:20:30 User 42# First release. 43# Fidoconfig parsing implement (include not supported). 44# Add log support. 45# 46# Revision 1.4 2002/06/01 14:31:21 User 47# RCS tag 'log' inserted 48# 49# Revision 1.3 2002/06/01 14:30:22 User 50# Reading fidoconfig implemented 51# 52# Revision 1.2 2002/06/01 12:52:37 User 53# .bak file create 54# 55# Revision 1.1 2002/06/01 11:53:34 User 56# First beta 57# 58# 59#=============================================================================# 60 61# Setup section --------------------------------------------------------------# 62 63#DOS/WIN 64$fidoconfig = "\\ftn\\config"; 65#UNIX 66#$fidoconfig = "/usr/local/etc/fido/links"; 67 68$PntStrFileMask = "PNTSTR.*"; 69$PointSegmentFile = "segNNNN.ptn"; # NNNN replace to node number in future 70 71# read from fidoconfig 72$address = "2:5080/102"; 73$logfiledir = "\\ftn\\log"; 74#$logfiledir = "."; 75$nodelistdir = "\\ftn\\nodelist"; 76$protinbound = "\\ftn\\inbound"; 77 78# Variables (& constants) section 79 80%password = (); 81%pointName = (); 82 83@validflags = ( V34, V32, V32B, VFC, HST, X2C, X2S, V90C, V90S, HST, H14, H16, 84 ZYX, Z19, V32T, CSP, PEP, MAX, H96, MNP, V42B, V42, V29, V22, 85 V110L, V110H, V120L, V120H, X75, ISDN, # ISDN 86 IBN, IFT, IFC, ITN, IVM, IP, # IP-based 87 IMI, IUC, ITX, ISE, IEM, # SMTP-based 88 EVY, EMA, # email-based 89# RPK, NPK, NEC, REC, NC, SMH # coordinators & secure mail hub 90 CM, MN, MO, LO, 91 PING, # auto-reply 92 UUCP, # internet email gate (official) 93 "G[A-Z1-90]+", # gateway to other FTN domain 94 "#01", "#02", "#08", "#09", "#18", "#20", # MH (bell-212) 95 "!01", "!02", "!08", "!09", "!18", "!20", # MH (CCITT) 96 "T[A-Xa-x][A-Xa-x]", # Answer time 97 XA, XB, XC, XP, XR, XW, XX, # FREQ 98 K12, ENC, CDP, SDS ); 99 100$pntnumFieldNo = 1; 101$phoneFieldNo=5; 102$flagFieldNo=7; 103 104@fields = (); 105 106# Program section 107 108if( $ENV{FIDOCONFIG} ){ 109 $fidoconfig = $ENV{FIDOCONFIG}; 110}elsif( $ENV{fidoconfig} ){ 111 $fidoconfig = $ENV{fidoconfig}; 112} 113 114# $DIRSEP - directory char (slash in unix and backslash in DOS-like OS 115if( $fidoconfig =~ /\\/ ){ 116 $DIRSEP = "\\"; 117}else{ 118 $DIRSEP = "/"; 119} 120 121 122&readconfig($fidoconfig); 123 124 125open(LOG, ">>$logfiledir" . "pntstr.log") || print STDERR "Can't open log file (", $logfiledir, "pntstr.log)\n"; 126print LOG "\n---Starting at $curdate\n"; 127print LOG "Fidoconfig \"$fidoconfig\" readed\n"; 128 129 130($a = $address) =~ s|\d+:\d+/(\d+)|$1|; 131if( $a >0 ){ 132 $a = sprintf "%04u", $a ; 133 $PointSegmentFile =~ s/NNNN/$a/; 134}elsif( $a == "0" ){ 135 die "Hmmmmmmm! Host with points is BAD idea!\n"; 136}else{ 137 die "\n"; 138} 139 140@lt = localtime(time); $lt[5]=$lt[5]+1900; $lt[4]++; 141$curdate = "$lt[3]-$lt[4]-$lt[5] $lt[2]:$lt[1]:$lt[0]"; 142@lt=(); 143 144@inbound = glob("$protinbound$PntStrFileMask"); 145 146for $ff ( @inbound ){ 147 @fields = (); 148 if( $ff =~ /\.([0-9]+)/ ){ 149# $pointNum = $1; 150 $pointNum = "$address.$1"; 151 if( !open( FF, $ff) ){ print "can't open \"$ff\", skip file\n"; next; } 152 print LOG "Process $ff (point number $pointNum)...\n"; 153 $pass = <FF>; 154# chomp($pass); 155 $pass =~ s/[\n\r]$//g; # chomp is platform-dependent 156 if( !defined($password{$pointNum}) ){ 157 $pass = $ff . ".bad"; 158 print LOG "Point $pointNum not found\n", 159 "Rename $ff to $pass\n"; 160 print "Point $pointNum not found\n"; 161 rename $ff, $pass; 162 }elsif( length($password{$pointNum})==0 ){ 163 $pass = $ff . ".bad"; 164 print LOG "Empty password for point $pointNum\n", 165 "Rename $ff to $pass\n"; 166 print "Empty password for point '$pointNum' ($password{$pointNum})\n"; 167 rename $ff, $pass; 168 }elsif( $pass =~ /^$password{$pointNum}$/ ){ 169 print LOG "... $ff : password OK\n"; 170 $pointString = <FF>; 171 chomp($pointString); 172 $pointString = parsePointString($pointString); 173 if( length($pointString)>0 ){ 174 writePointString($pointString); 175 print LOG "Remove input file \"$ff\"..."; 176 close FF; 177 unlink $ff || die "Error!\n"; 178 print LOG "OK\n"; 179 }else{ 180 ($bb = $ff) =~ s/...\.$pointNum$/ERR.$pointNum/; 181 print LOG "Rename $ff to $bb ..."; 182 close FF; 183 rename $ff, $bb || die "Error!\n"; 184 print LOG "OK\n"; 185 } 186 }else{ 187 print "Error: Invalid password \"$pass\" for point \"$pointNum\"\n"; 188 print LOG "...Invalid password \"$pass\" for point \"$pointNum\"\n"; 189 ($bb = $ff) =~ s/...\.$pointNum$/SEC.$pointNum/; 190 print LOG "Rename $ff to $bb ..."; 191 close FF; 192 rename $ff, $bb || die "Error!\n"; 193 print LOG "OK\n"; 194 } 195 close FF; 196 } 197} 198 199print LOG "---End---\n"; 200close LOG; 201 202#END 203 204sub readconfig{ 205# Read husky configuration: pathnames, points passwords. 206 207 my $config = $_[0]; # fidoconfig file name 208 my $pointNo=0, $pointName=""; 209 my @line,$line; 210 my $t, $a=1; 211 212 open FIDOCONFIG, "$config" || die "Can't open $config: $!"; 213 214 print LOG "\nReading fidoconfig \"$config\"..."; 215 while( ($line = <FIDOCONFIG>) ){ 216 chomp($line); 217 $line =~ s/\t/ /g; 218 $line =~ s/ +/ /g; 219 @line = split / /, $line; 220# if( $line[0] =~ /^include/i ){ 221# readconfig($line[1]); 222# } 223 if( $line[0] =~ /^address$/i ){ 224 $address = $line[1] if($a); 225 $a=0; 226 }elsif( $line[0] =~ /^protinbound$/i ){ 227 $protinbound = $line[1]; 228 }elsif( $line[0] =~ /^logfiledir$/i ){ 229 $logfiledir = $line[1]; 230 }elsif( $line[0] =~ /^nodelistdir$/i ){ 231 $nodelistdir = $line[1]; 232 }elsif( $line[0] =~ /^PntStrFileMask$/i ){ 233 $PntStrFileMask = $line[1]; 234 }elsif( $line[0] =~ /^PointSegmentFile$/i ){ 235 $PointSegmentFile = $line[1]; 236# }elsif( $line[0] =~ /^$/i ){ 237 }elsif( $line[0] =~ /^link$/i ){ 238 # Write previous item if point 239 if( $pointNo ){ 240 $password{$pointNo} = $password; 241 $pointName{$pointNo} = $pointName; 242 if( !$password ){ 243 print LOG "\nEmpty password for point $address.$pointNo, ignored\n"; 244 } 245 } 246 # clear vars 247 $pointNo = 0; 248 $pointName = ""; 249 $password = ""; 250 # store new pointname 251 shift @line; 252 $pointName = join " ", @line; 253 }elsif( $line[0] =~ /^aka$/i ){ 254# if( $address && ($line[1] =~ /$address.([1-9]\d*)/) ){ 255# $pointNo = $1; 256 if( $address && ($line[1] =~ /$address.[1-9][0-9]*/) ){ 257 $pointNo = $line[1]; 258 } 259 }elsif( !$pointNo ){ 260 next; 261 }elsif( $line[0] =~ /^sessionpwd$/i ){ 262 $password = $line[1]; 263 }elsif( ($line[0] =~ /^password$/i) ){ 264 $password = $line[1] if( length($password)==0 ); 265 } 266# if( $line[0] =~ //i ){ 267# $ = $line[1]; 268# } 269 } 270 if( $pointNo ){ 271 $password{$pointNo} = $password; 272 $pointName{$pointNo} = $pointName; 273 if( !$password ){ 274 print LOG "\nEmpty password for point $address.$pointNo, ignored\n"; 275 } 276 } 277 close FIDOCONFIG; 278 print LOG "OK\n"; 279 280 # Add slash (or backslash) if omitted 281 $nodelistdir .= $DIRSEP if( length($nodelistdir)>0 && ($nodelistdir !~ /$DIRSEP$/) ); 282 $protinbound .= $DIRSEP if( length($protinbound)>0 && ($protinbound !~ /$DIRSEP$/) ); 283 $logfiledir .= $DIRSEP if( length($logfiledir)>0 && ($logfiledir !~ /$DIRSEP$/) ); 284 285# debug output # 286#for $pointNo (keys %password){ 287# print "$pointNo:$password{$pointNo}:$pointName{$pointNo}\n"; 288#} 289 290} 291 292 293sub parsePointString{ 294 my $i, $ii; 295 my $line = $_[0]; 296 297 # check for spaces & tabs 298 if( $line =~ / / ){ 299 print "Error: space in line! Replaced to \"_\"\n"; 300 print LOG "Error: space in line! Replaced to \"_\"\n"; 301 } 302 if( $line =~ /\t/ ){ 303 print "Error: tab stop in line! Replaced to \"_\"\n"; 304 print LOG "Error: tab stop in line! Replaced to \"_\"\n"; 305 } 306 $line =~ s/[ \t]/_/g; 307 308 @fields = split /,/, $line; 309 310 if($pointNum != $fields[$pntnumFieldNo]){ 311 print LOG "Can't match point number: \"$fields[$pntnumFieldNo]\", not $pointNum\n"; 312 print "Can't match point number: \"$fields[$pntnumFieldNo]\", not $pointNum\n"; 313 return ""; 314 } 315 316 # print point string fields (log) 317 print <<FIELDS; 318 319Point: $fields[$pntnumFieldNo] 320Station: $fields[2] 321City: $fields[3] 322Sysop: $fields[4] 323Phone: $fields[$phoneFieldNo] 324Speed: $fields[6] 325FIELDS 326 print "Flags: " ; 327 print "$fields[$flagFieldNo]"; 328 for( $i=$flagFieldNo+1; $i<=$#fields; $i++ ){ print ",$fields[$i]"; } 329 print "\n\n"; 330 331 # validate "Point" (1st) field 332 if( $fields[0] !~ /^Point$/ ){ 333 print LOG "Error: Invalid first field \"$fields[0]\", valid value is \"Point\". Process failed.\n"; 334 print "Error: Invalid first field \"$fields[0]\", valid value is \"Point\". Process failed.\n"; 335 }else{ 336 if( $fields[0] != "Point" ){ 337 $fields[0] = "Point"; 338 print LOG "Warning: Invalid first field \"$fields[0]\", replace to valid value \"Point\"\n"; 339 print "Warning: Invalid first field \"$fields[0]\", replace to valid value \"Point\"\n"; 340 } 341 } 342 343 # validate phone 344 if( $fields[$phoneFieldNo] =~ /^-Unpublished-$/i ){ 345 if( $fields[$phoneFieldNo] != "-Unpublished-" ){ 346 $fields[$phoneFieldNo] = "-Unpublished-"; 347 print LOG "Warning: Invalid \"magic\" phone number \"$fields[$phoneFieldNo]\": it's case-cencitivity, replace to valid value \"-Unpublished-\"\n"; 348 print "Warning: Invalid \"magic\" phone number \"$fields[$phoneFieldNo]\": it's case-cencitivity, replace to valid value \"-Unpublished-\"\n"; 349 } 350 }elsif( $fields[$phoneFieldNo] !~ /^[0-9-]+$/i ){ 351 print LOG "Invalid phone number \"$fields[$phoneFieldNo]\" (only digits & dash is legal, also "-Unpublished-")\n"; 352 print "Invalid phone number \"$fields[$phoneFieldNo]\" (only digits & dash is legal, also "-Unpublished-")\n"; 353 return ""; 354 } 355 # validate flags 356 for( $i=$#fields; $i>=$flagFieldNo; $i-- ){ 357 for( $ii=$#validflags; $ii>=0 && $fields[$i] !~ /$validflags[$ii]/ ; $ii-- ){ 358 if( uc($fields[$i]) =~ /$validflags[$ii]/ ){ 359 $fields[$i] = uc($fields[$i]); 360 print LOG "Warning: flag \"$fields[$i]\" converted to uppercase\n"; 361 print "Warning: flag \"$fields[$i]\" converted to uppercase\n"; 362 } 363 } 364 if( $fields[$i] !~ /$validflags[$ii]/ ){ 365 return ""; 366 print LOG "Illegal flag \"$fields[$i]\"\n"; 367 print "Illegal flag \"$fields[$i]\"\n"; 368 } 369 } 370 return join(",",@fields); # return valid point string 371} 372 373sub writePointString(){ 374 my @fields = split /,/, $_[0]; 375 my @aflds = (), $tmpname; 376 my $doit=1; 377 378 if( !open(SEGMENT, "$nodelistdir$PointSegmentFile") ){ 379 print LOG "Can't open $PointSegmentFile ($!), abort.\n"; 380 die "Can't open $PointSegmentFile, abort. (See log for details.)\n"; 381 } 382 ($tmpname = $PointSegmentFile ) =~ s/\.[\w\d_-]*$//; 383 $tmpname .= ".tmp"; 384 if( !open(TMP, ">$tmpname") ){ 385 print LOG "Can't open temporary file \"$tmpname\" ($!), abort.\n"; 386 die "Can't open temporary file \"$tmpname\", abort. (See log for details.)\n"; 387 } 388 print LOG "Write to $tmpname..."; 389 while( $line = <SEGMENT> ){ 390 chomp($line); 391 @aflds = split /,/, $line; 392 if( "$aflds[$pntnumFieldNo]" == "$fields[$pntnumFieldNo]" ){ 393 print TMP join(",",@fields), "\n"; # replace point string 394 $doit=0; 395 }else{ 396 print TMP "$line\n"; 397 } 398 } 399 print TMP (join(",",@fields), "\n") if($doit); # add point string 400 401 print LOG "OK\n"; 402 close SEGMENT; 403 close TMP; 404 405 ($line = $PointSegmentFile ) =~ s/\.[\w\d_-]*$//; 406 $line .= ".bak"; 407 print LOG "Backup $PointSegmentFile to $line..."; 408 unlink $line if( -f $line ); 409 rename $PointSegmentFile, $line || die "Error!\n"; 410 print LOG "OK\n"; 411 print LOG "Rename $tmpname to $PointSegmentFile..."; 412 rename $tmpname, $PointSegmentFile || die "Error!\n"; 413 print LOG "OK\n"; 414} 415