#!/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 () { 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 () { $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 I =head1 DESCRIPTION The B command performs syntax and content checks on the given filename, normally a copy of the I 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 (eg. success). =over =item B I 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 I 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 function. =item B I 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 function. =back =head1 SEE ALSO The services(5) man page describes the file format. =head1 AUTHOR Ralph Siemsen & Phil Knirsch