Re: Logwatch Exim script
Chris Wilson <[email protected]>
| Newsgroups | gmane.comp.log.logwatch.devel |
|---|---|
| Message-ID | <alpine.LRH.2.00.0908231623420.24717@localhost> |
Dear sirs,
I've done some more work on "improving" the exim script. At least it works well
for me now. Please find a new, much more invasive patch attached.
Changes made by this patch:
* Fix the control of display of restarts and queue runs to work properly
(was using the wrong variable name).
* Increase detail level required to display restarts and queue runs to 10,
as these are completely normal, expected and boring events IMHO.
* Add a new configuration option to set the detail level required to
display "relaying denied" (Bad Hosts) messages grouped by type (not by
type and host). This reduces ~600 lines per day, in my case, to nine:
--- Refused Relays 249 times
--- Bad Hosts ---
Rejected HELO/EHLO: Invalid HELO: 328 times
Rejected HELO/EHLO: You are SO lying: 28 times
Rejected HELO/EHLO: syntactically invalid argument(s): 3 times
SMTP protocol synchronization error: 1 times
Sudden disconnect while expecting remote input: 81 times
--- SMTP Connection Issues
SMTP Timeout errors: 3 Time(s)
I find this level of detail much more appropriate, as I don't care for
the IP addresses of random spambots and would rather see the real errors
than the noise. The info above is displayed at level 5 or above by
default, and the original detailed log lines at level 10 or above.
* Add a new configuration option for display of DNS lookup failures. Again
I find these uninteresting and noisy. Default level is 10.
* "SMTP connection from" regex would match some unexpected lines,
including DNS lookup failures, and misclassify them as SMTP protocol
errors.
* Ignore "Warning: HELO verify failed" as in previous patch.
* Detect "rejected EHLO or HELO" and process similarly to "rejected HELO"
and "rejected EHLO" (similar to previous patch but works better).
* Remove redundant information from "no IP address found for host" lines.
* Rename variables $mid, $aa, $bb and $cc to reflect their purpose and
make the code easier to read.
* Rationalise the SMTP/Bad Host errors a bit, by putting messages into
either one or the other depending on whether I think a well-behaved host
might cause it in normal operation.
* Improve consistency of line indenting a bit to make the output neater.
I hope you will consider my patch and merge it into Logwatch, or let me know
what I can do to improve it.
I also find the choice of three-space indents and lack of "use warnings"
and "use strict" in this script baffling and difficult to work with. Can
anyone tell me the reasons behind it?
Cheers, Chris.
--
_____ __ _
\ __/ / ,__(_)_ | Chris Wilson <0000 at qwirx.com> - Cambs UK |
/ (_/ ,\/ _/ /_ \ | Security/C/C++/Java/Ruby/Perl/SQL Developer |
\__/_/_/_//_/___/ | We are GNU : free your mind & your software |
_______________________________________________
Logwatch-Devel mailing list
[email protected]
http://www2.list.logwatch.org:81/mailman/listinfo/logwatch-devel
logwatch-exim.patch
(text/plain, 19.8 KB)
--- /usr/share/logwatch/scripts/services/exim.orig 2009-08-23 10:41:51.000000000 +0100
+++ /usr/share/logwatch/scripts/services/exim 2009-08-23 16:17:55.000000000 +0100
@@ -44,11 +44,12 @@
# Prints administrative rejections (by category)
# Prints Refused Relay count
#
-# 5: Prints Queue Run count
-# Prints server Stop/Start
+# 5: Prints Refused Relay reasons
#
# 10: Prints Refused Relay (individual lines)
# Prints Per Message Tracking
+# Prints server restarts and queue runs
+# Prints DNS lookup errors
########################################################
use Logwatch ':dates';
@@ -56,18 +57,22 @@
$Detail = $ENV{'LOGWATCH_DETAIL_LEVEL'} || 0;
$LvlBadFormat = $ENV{'exim_misformat'} || 0;
-$LvlRestarts = $ENV{'exim_restart'} || 5;
+$LvlRestarts = $ENV{'exim_restart'} || 10;
$LvlVirus = $ENV{'exim_virus'} || 0;
$LvlProtocl = $ENV{'exim_protocol'} || 0;
$LvlProtoclLines = $ENV{'exim_protocol_lines'}|| 5;
$LvlDontAccept = $ENV{'exim_dontaccept'} || 0;
-$LvlDontAcceptLines = $ENV{'exim_dontaccept_lines'} || 0;
+$LvlDontAcceptLines = $ENV{'exim_dontaccept_lines'} || 0;
$LvlVerify = $ENV{'exim_verify'} || 0;
$LvlVerifyLines = $ENV{'exim_verify_lines'} || 5;
$LvlRuns = $ENV{'exim_runs'} || 5;
$LvlRelay = $ENV{'exim_relay'} || 0;
$LvlRelayLines = $ENV{'exim_relay_lines'} || 10;
+$LvlRelayReasons = $ENV{'exim_relay_reasons'} || 5;
$LvlMsgs = $ENV{'exim_mesgs'} || 10;
+$LvlDnsLookups = $ENV{'exim_dns_lookups'} || 10;
+
+# print "Exim report detail level: $Detail\n\n";
# procedura sortujaca tak jak ja chce (bo tamta sotrowala po ASCII)
# procedure to compare numbers at the beginning of submitted strings.
@@ -152,7 +157,7 @@
# Exim >= 4.50 compiled with WITH_CONTENT_SCAN=yes (Running AntiVirus Software)
$Virus{$ThisLine}++;
}
- elsif ( $ThisLine =~ /SMTP connection from/ ) {
+ elsif ( $ThisLine =~ /SMTP connection from (.*) \[(\d+\.\d+\.\d+\.\d+)\] (.*)/ ) {
# Common error from SPAM hosts.
$Proto{$ThisLine}++;
}
@@ -168,6 +173,10 @@
# Common error from SPAM hosts.
$Proto{$ThisLine}++;
}
+ elsif ( $ThisLine =~ /Warning: HELO verify failed/ ) {
+ # Common error from SPAM hosts.
+ $HeloVerify{$ThisLine}++;
+ }
elsif ( $ThisLine =~ /unexpected disconnection while reading SMTP command/ ) {
# Common error from SPAM hosts.
$Proto{$ThisLine}++;
@@ -209,7 +218,7 @@
# this is an extra error message when logging is high
# and since another message duplicates it, we can just ignore this
}
- elsif ( $ThisLine =~ /rejected [HE][EH]LO from\s/ ) {
+ elsif ( $ThisLine =~ /rejected ((HELO|EHLO) from|EHLO or HELO)\s/ ) {
# Typically due to underscores _ in the HELO line
# (a common protocol violation)
# Also can be due to odd escape sequences
@@ -236,9 +245,9 @@
$ReverseLookup++;
@ReverseLookupH = (@ReverseLookupH, $ThisLine);
}
- elsif ( $ThisLine =~ /no IP address found for host/ ) {
+ elsif ( $ThisLine =~ /(.* no IP address found for host \S+)/ ) {
$Lookup++;
- @LookupH = (@LookupH, $ThisLine);
+ @LookupH = (@LookupH, $1);
}
elsif ( $ThisLine =~ /^\d+\-\d+\-\d+\s\d+\:\d+\:\d+\s\w+\-\w+\-\w+\s/ ) { # inne wiadomosci przesylane przez EXIMA
# Collect Message ID specific notes...
@@ -246,7 +255,6 @@
# Count of individual Message Lines, used for sort
$licze++; # Dodaje taki licznik aby potem przy wypisaniu posortowac po nim, bo wypisywal nie po kolei
$mmsg{$mid}{$licze.$mrest} = "$mdate $mtime";
-
}
else
{
@@ -265,7 +273,7 @@
}
# Print server Stops/Starts
-if ($Detail >= $LvlRestart) {
+if ($Detail >= $LvlRestarts) {
if (@Restart) {
print "\n--- Exim Restarted ---\n";
foreach $ThisOne (sort @Restart) {
@@ -274,7 +282,7 @@
}
}
-if ($Detail >= $LvlRestart) {
+if ($Detail >= $LvlRestarts) {
print "\n--- Queue Runners ---\n";
# Start Queue
$StartQueue and print " Start queue run: $StartQueue Time(s)\n";
@@ -332,6 +340,22 @@
print "$ThisOne\n";
}
}
+ elsif ( $Detail >= $LvlRelayReasons ) {
+ my %reasons;
+ foreach my $line (@RelayH) {
+ if ($line =~ /rejected RCPT: (.*)/)
+ {
+ $reasons{$1}++;
+ }
+ else
+ {
+ print "unmatched: $ThisOne\n";
+ }
+ }
+ foreach my $reason (sort keys %reasons) {
+ print "$reason: $reasons{$reason}\n";
+ }
+ }
}
}
@@ -389,77 +413,79 @@
# Probable SPAM hosts...
print "\n--- Admin Policy Blocking ---\n";
foreach $ThisOne (sort(keys %DontAccept)) {
- # We need this blank.
- $mid = "";
# IP address/current issue holder.
- $bb = "";
+ my $offender = "";
# Extract exim date and time string...
($mdate, $mtime) = ($ThisOne =~ m/^(\d+-\d+-\d+)\s(\d+\:\d+\:\d+)\s/);
# Link date and time (looks cleaner)...
- $aa = "$mdate $mtime";
+ my $date_time = "$mdate $mtime";
+ my $reason = "unknown";
if ( $ThisOne =~ m/do not accept mail from ([\w\*-._]+)@([\w.-_]+)/ ) {
- $cc = "Blocked Email Domain";
- $bb = "$1\@$2";
+ $reason = "Blocked Email Domain";
+ $offender = "$1\@$2";
}
elsif ( $ThisOne =~ m/mail not permitted from sender ([\w\*-_.]+)@([\w.-_]+)/ ) {
- $cc = "Blocked Email Address";
- $bb = "$1\@$2";
+ $reason = "Blocked Email Address";
+ $offender = "$1\@$2";
}
elsif ( $ThisOne =~ m/contains attached ".(.*)" file, which is blacklisted/ ) {
- $cc = "Blocked Attachment";
- ( $bb ) = ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/);
+ $reason = "Blocked Attachment";
+ ( $offender ) = ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/);
}
elsif ( $ThisOne =~ /believed to be spam/ ) {
- $cc = "Blocked Fragmented Message";
- ( $bb ) = ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/);
+ $reason = "Blocked Fragmented Message";
+ ( $offender ) = ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/);
}
elsif ( $ThisOne =~ /[Ww]arning: dnsbl\.sorbs\.net/ ) {
- $cc = "Blocked by DNSBL (SORBS)";
- ( $bb ) = ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/);
+ $reason = "Blocked by DNSBL (SORBS)";
+ ( $offender ) = ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/);
}
elsif ( $ThisOne =~ /fragments administratively prohibited/ ) {
- $cc = "Blocked Fragmented Message";
- ( $bb ) = ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/);
+ $reason = "Blocked Fragmented Message";
+ ( $offender ) = ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/);
}
elsif ( $ThisOne =~ m/unqualified sender rejected: <(.*)>/ ) {
- $cc = "Unqualified Sender";
- $bb = "$1";
+ $reason = "Unqualified Sender";
+ $offender = "$1";
}
elsif ( $ThisOne =~ m/unqualified recipient rejected: <(.*)>/ ) {
- $cc = "Unqualified Receipient";
- $bb = "$1";
+ $reason = "Unqualified Receipient";
+ $offender = "$1";
}
elsif ( $ThisOne =~ m/not accept Windows executables/ ) {
- $cc = "Blocked Attachment";
- ( $bb ) = ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/);
+ $reason = "Blocked Attachment";
+ ( $offender ) = ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/);
}
elsif ( $ThisOne =~ m/remote host address is the local host/ ) {
- $cc = "Invalid local domain";
- ( $bb ) = ($ThisOne =~ m/\@\[^>]+/);
+ $reason = "Invalid local domain";
+ ( $offender ) = ($ThisOne =~ m/\@\[^>]+/);
}
else {
# If we picked up a malfunction but didn't collect it here,
# no need to make the user suffer with superfluous error
# messages.
- #next;
print "Didn't Summarize: $ThisOne\n";
+ next;
}
- if (defined( $spam{$cc} )) {
- $mid = $spam{$cc};
+ if ($spam{$reason}) {
+ $spam{$reason} .= ",$date_time: $offender";
}
- $spam{$cc} = "$mid$aa : $bb,";
+ else {
+ $spam{$reason} = "$date_time: $offender";
+ }
}
- foreach $ThisOne (sort(keys %spam)) {
+
+ foreach my $reason (sort(keys %spam)) {
if ($Detail >= $LvlDontAcceptLines) {
- print " $ThisOne\n";
- foreach $aa ( sort( split /,/, $spam{$ThisOne} )) {
- print " $aa\n";
+ print " $reason:\n";
+ foreach my $offender ( sort( split /,/, $spam{$ThisOne} )) {
+ print " $offender\n";
}
}
else {
- @errList = split /,/, $spam{$ThisOne};
- print " $ThisOne ".scalar @errList." times\n";
+ @errList = split /,/, $spam{$reason};
+ print " $reason: ".scalar @errList." times\n";
}
}
}
@@ -473,151 +499,174 @@
# Probable SPAM hosts...
print "\n--- Bad Hosts ---\n";
foreach $ThisOne (sort(keys %Proto)) {
- # We need this blank.
- $mid = "";
# IP address/current issue holder.
- $bb = "";
- $cc = "";
+ my $offender = "";
+ my $reason = "";
# Extract exim date and time string...
($mdate, $mtime) = ($ThisOne =~ m/^(\d+-\d+-\d+)\s(\d+\:\d+\:\d+)\s/);
# Link date and time (looks cleaner)...
- $aa = "$mdate $mtime";
+ my $date_time = "$mdate $mtime";
+ if ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/) {
+ $offender = $1;
+ }
if ( $ThisOne =~ m/SMTP protocol violation\:\s(.*?\(.*?\))\:/ ) {
- $cc = $1;
- ( $bb ) = ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/);
+ $reason = $1;
}
elsif ( $ThisOne =~ /unexpected disconnection while reading SMTP command/ ) {
- $cc = "Sudden disconnect while expecting remote input";
- ( $bb ) = ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/);
+ $reason = "Sudden disconnect while expecting remote input";
}
- elsif ( $ThisOne =~ m/rejected ([HE][EH])LO from \[(\d+\.\d+\.\d+\.\d+)\]\:\s(.*?):\s(.*?)$/ ) {
- $cc = "Rejected HELO/EHLO: $3";
- $bb = "$2 ($1LO $4)";
+ elsif ( $ThisOne =~ m/rejected (HELO|EHLO) from \[(\d+\.\d+\.\d+\.\d+)\]\:\s(.*?):\s(.*?)$/ ) {
+ if (not $4) {
+ print "Rejected HELO/EHLO for unknown reason: $ThisOne\n";
+ }
+ $reason = "Rejected HELO/EHLO: $3";
+ $offender = sprintf("%-15s claiming to be '%s'", $2, $4);
+ }
+ elsif ( $ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\] rejected EHLO or HELO (.*): (.*)/ ) {
+ if (not $3) {
+ print "Rejected HELO/EHLO for unknown reason: $ThisOne\n";
+ }
+ $reason = "Rejected HELO/EHLO: $3";
+ $offender = sprintf("%-15s claiming to be '%s'", $1, $2);
}
elsif ( $ThisOne =~ /SMTP data timeout \(message abandoned\) on connection from/ ) {
- $cc = "SMTP Timeout errors";
- ( $bb ) = ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/);
+ $reason = "SMTP Timeout errors";
+ $SmtpConnection{$reason}++;
}
elsif ( $ThisOne =~ /SMTP command timeout on connection from/ ) {
- $cc = "SMTP Timeout errors";
- ( $bb ) = ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/);
+ $reason = "SMTP Timeout errors";
+ $SmtpConnection{$reason}++;
}
elsif ( $ThisOne =~ /syntactically invalid argument/ ) {
- $cc = "SMTP Syntax errors";
- ( $bb ) = ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/);
+ $reason = "SMTP Syntax errors";
}
elsif ( $ThisOne =~ /SMTP syntax error in/ ) {
- $cc = "SMTP Syntax errors";
- ( $bb ) = ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/);
+ $reason = "SMTP Syntax errors";
}
elsif ( $ThisOne =~ /remote host used my name in HELO/ ) {
- $cc = "My name in HELO";
- ( $bb ) = ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/);
+ $reason = "My name in HELO";
}
elsif ( $ThisOne =~ /remote host used IP address in HELO/ ) {
- $cc = "IP address in HELO";
- ( $bb ) = ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/);
+ $reason = "IP address in HELO";
}
elsif ( $ThisOne =~ /incomplete transaction (\(.*\))/ ) {
- $bb = "SMTP transaction cut short $1";
- $SmtpConnection{$bb}++;
+ $reason = "SMTP transaction cut short $1";
+ $SmtpConnection{$reason}++;
}
elsif ( $ThisOne =~ /SMTP protocol synchronization error/ ) {
- $bb = "SMTP protocol synchronization error";
- $SmtpConnection{$bb}++;
+ $reason = "SMTP protocol synchronization error";
+ # spammer, not normal error
}
elsif ( $ThisOne =~ /dropped: too many nonmail commands/ ) {
- $bb = "Connection dropped after too many nonmail SMTP commands";
- $SmtpConnection{$bb}++;
+ $reason = "Connection dropped after too many nonmail SMTP commands";
}
elsif ( $ThisOne =~ /dropped: too many syntax or protocol errors/ ) {
- $bb = "Connection dropped after too many syntax/protocol errors";
- $SmtpConnection{$bb}++;
+ $reason = "Connection dropped after too many syntax/protocol errors";
}
elsif ( $ThisOne =~ /(SMTP protocol error in \"\w+\")/ ) {
- $bb = $1;
- $SmtpConnection{$bb}++;
+ $reason = $1;
+ $SmtpConnection{$reason}++;
}
- elsif ( $ThisOne =~ /SMTP connection from/ ) {
- if ( $ThisOne =~ /lost while reading message data/ ) {
- $bb = "SMTP connection lost while reading message data";
- }
- elsif ( $ThisOne =~ /Connection reset by peer/ ) {
- $bb = "SMTP connection lost when connection reset by peer ";
- }
- elsif ( $ThisOne =~ /lost/ ) {
- $bb = "SMTP connection lost (non-specific)";
- }
- elsif ( $ThisOne =~ /closed by QUIT/ ) {
- $bb = "SMTP connection closed by QUIT";
- }
- elsif ( $ThisOne =~ /closed after SIGTERM/ ) {
- $bb = "SMTP connection closed after SIGTERM";
- }
- elsif ( $ThisOne =~ /TCP\/IP connection count/ ) {
- $bb = "SMTP connection TCP/IP connection count (warning)";
- }
- if ( $bb ne "" ) {
- $SmtpConnection{$bb}++;
+ elsif ( $ThisOne =~ /SMTP connection from (.*) \[(\d+\.\d+\.\d+\.\d+)\] (.*)/ ) {
+ # if we set $smtp_reason then it's a random/expected SMTP
+ # error; otherwise it's a bad host error.
+ $reason = $3;
+
+ if ( $reason eq 'lost while reading message data' ) {
+ $smtp_reason = "SMTP connection lost while reading message data";
+ }
+ elsif ( $reason eq 'Connection reset by peer' ) {
+ $smtp_reason = "SMTP connection lost when connection reset by peer ";
+ }
+ elsif ( $reason eq 'lost' ) {
+ $smtp_reason = "SMTP connection lost (non-specific)";
+ }
+ elsif ( $reason eq 'closed by QUIT' ) {
+ $smtp_reason = "SMTP connection closed by QUIT";
+ }
+ elsif ( $reason =~ /closed after SIGTERM/ ) {
+ $smtp_reason = "SMTP connection closed after SIGTERM";
+ }
+ elsif ( $reason =~ /TCP\/IP connection count/ ) {
+ $reason = "SMTP connection TCP/IP connection count (warning)";
+ }
+ else {
+ # unexpected error, probably SMTP and not bad host
+ $smtp_reason = $reason;
+ }
+
+ if ( $smtp_reason ne "" ) {
+ $SmtpConnection{$smtp_reason}++;
+ next; # don't process it twice
}
}
else {
# If we picked up a malfunction but didn't collect it here,
# no need to make the user suffer with superfluous error
# messages.
- #next;
print "Didn't Summarize: $ThisOne\n";
+ next;
}
- if (defined( $spam{$cc} )) {
- $mid = $spam{$cc};
- }
- # We're picking things up in this larger block that do not
- # ... fit into this mold, so - let's make sure that this is valid
- # ... before we set it:
- if (( $cc ne '' ) && ( $bb ne '' )) {
- $spam{$cc} = "$mid$aa : IP:$bb,";
- }
+
+ if (not $reason) {
+ print "No reason for: $ThisOne\n";
+ next;
+ }
+
+ if (not $offender) {
+ print "No offender for: $ThisOne\n";
+ next;
+ }
+
+ if ($SmtpConnection{$reason}) {
+ next; # don't list it twice, both SMTP and Spam
+ }
+
+ $spam{$reason} ||= { };
+ $spam{$reason}{$offender} ||= [ ];
+
+ push @{ $spam{$reason}{$offender} }, $date_time;
}
- foreach $ThisOne (sort(keys %spam)) {
+
+ foreach $reason (sort keys %spam) {
+ $offenders = $spam{$reason};
+
if ($Detail >= $LvlProtoclLines) {
- print " $ThisOne:\n";
- foreach $aa ( sort( split /,/, $spam{$ThisOne} )) {
- print " $aa\n";
+ print " $reason:\n";
+ foreach $offender (sort keys %$offenders) {
+ $times = $offenders->{$offender};
+ print " $offender: ".(scalar @$times)." times\n";
}
}
else {
- @errList = split /,/, $spam{$ThisOne};
- print " $ThisOne ".scalar @errList." times\n";
+ print " $reason: ".(scalar keys %$offenders)." times\n";
}
}
if ( %SmtpConnection ) {
print "\n--- SMTP Connection Issues \n";
- foreach $ThisOne (keys %SmtpConnection) {
- $bb = $SmtpConnection{$ThisOne};
- print " $ThisOne: $bb Time(s)\n";
+ foreach $reason (keys %SmtpConnection) {
+ print " $reason: $SmtpConnection{$reason} Time(s)\n";
}
}
- if (@ReverseLookupH) {
- print "\n--- Failed Reverse Lookups \n";
- print "--- $ReverseLookup Time(s)\n\n";
+ if (@ReverseLookupH and $Detail >= $LvlDnsLookups) {
+ print "\n--- Failed Reverse Lookups (clueless admin) $ReverseLookup time(s)\n\n";
if ($Detail >= $LvlProtoclLines) {
foreach $ThisOne (@ReverseLookupH) {
- print " $ThisOne\n";
+ print " $ThisOne\n";
}
}
}
- if (@LookupH) {
- print "\n--- Failed Reverse Lookups \n";
- print "--- (eg. spam try): $Lookup Time(s)\n\n";
+ if (@LookupH and $Detail >= $LvlDnsLookups) {
+ print "\n--- Failed Forward Lookups (fake hostname) $Lookup time(s)\n\n";
if ($Detail >= $LvlProtoclLines) {
foreach $ThisOne (@LookupH) {
- print "$ThisOne\n";
+ print " $ThisOne\n";
}
}
}