diff options
-rw-r--r-- | Makefile | 6 | ||||
-rwxr-xr-x | serviceslint | 119 |
2 files changed, 125 insertions, 0 deletions
@@ -6,6 +6,12 @@ LIST = csh.cshrc csh.login gshadow group host.conf hosts.allow hosts.deny input motd passwd printcap protocols securetty services shadow shells profile \ filesystems fstab resolv.conf hosts +check: + @echo Sanity checking selected files.... + bash -n profile + tcsh -f csh.cshrc + tcsh -f csh.login + ./serviceslint ./services clean: rm -f *~ \#*\# diff --git a/serviceslint b/serviceslint new file mode 100755 index 0000000..b602455 --- /dev/null +++ b/serviceslint @@ -0,0 +1,119 @@ +#!/usr/bin/perl +# +# Perform sanity checks on the services file, supplied as argument. +# Based on an earlier shell script of the same name, but much faster, +# and it also detects actual errors in the current services file :) +# +# This program includes a manual, run "perldoc serviceslint" to see it. +# + +use strict; +use warnings; + +die "Usage: $0 /etc/services\n" unless $#ARGV == 0; + +# Build a hash of known protocols +my %protocol; +open FH, "protocols" or die "cannot open protocols: $!\n"; +while (<FH>) { + chomp; + s/#.*$//; + my ($name, $port) = m/([\S]+)\s+(\d+)/ or next; + $protocol{$name} = $port; +} +close FH; + +# Parse the supplied services file +my $retval = 0; +my $line = 0; +my %service; +open FH, $ARGV[0] or die "cannot open $ARGV[0]: $!\n"; +while (<FH>) { + $line++; # Keep a line count + chomp; # Remove CR/LF chars + if (m/^\s+/) { + print "Malformed line $line\n"; # No leading whitespace + $retval = 1; + next; + } + s/\s*#.*$//; # Strip out comments + next if m/^$/; # Skip empty lines + my ($name, $port, $proto, $aliases) = # Primary pattern match + m/^([\S]+)\s+(\d+)\/(\w+)\s*(.*)/ + or die "Malformed line: $line\n"; + if (not exists $protocol{$proto}) { + print "Bad protocol at line $line: $proto\n"; + $retval = 1; + } + if (exists $service{$proto}{$port}) { + print "Duplicate port at line $line: $port/$proto\n"; + $retval = 1; + } + $service{$proto}{$port} = $name; + foreach ($name, split /\s+/, $aliases) { + if (exists $service{$proto}{$_}) { + print "Duplicate name at line $line: $_/$proto\n"; + $retval = 1; + } + $service{$proto}{$_} = $port; + }; + +} +close FH; +exit $retval; + +__END__ + +=head1 NAME + +serviceslint - perform verification on the /etc/services file + +=head1 SYNOPSIS + +B<serviceslint> I<filename> + +=head1 DESCRIPTION + +The B<serviceslint> command performs syntax and content checks on the +given filename, normally a copy of the I</etc/services> file. + +Syntax checking consists of a regular expression applied to +non-empty, non-comment lines. If the syntax check fails, then +the program prints a message and aborts with non-zero status code. + +Content checking detects various kinds of duplicate entries. +Currently, warnings are printed for duplicate entries, but execution +continues, and the program I<exits with status code zero> (eg. success). + +=over + +=item B<Malformed line> I<NNN> + +The specified line has invalid syntax. Note that leading whitespace +is not permitted. Non-empty lines must begin with a comment, or with +a service name followed by a port number / protocol pair. + +=item B<Duplicate port at line> I<NNN> + +Occurs when a port number / protocol pair is found more than once +in the services file. The warning is flagged on the second (and any +subsequent) occurrences. These entries will not be found via the +B<getservbyport()> function. + +=item B<Duplicate name at line> I<NNN> + +Occurs when a service name, or alias, occurs more than once in the +services file. The warning is flagged on the second (and subsequent) +occurrence. These entries will not be returned by the B<getservbyname()> +function. + +=back + +=head1 SEE ALSO + +The services(5) man page describes the file format. + +=head1 AUTHOR + +Ralph Siemsen & Phil Knirsch + |