1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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
|