#!/usr/bin/perl -w # services_sorter.pl # sort /etc/services by numeric order of ports. # Run this script as an unprivileged user. # Use root or sudo to actually make changes: # Rememeber to backup the original /etc/services file # and to preserve permissions and ownership of the original # on the new /etc/services file. use strict; my $input = "/etc/services"; my $output = "services_out"; open (INPUT, $input) || die "Unable to open $input. " . $! . "\n"; open (OUTPUT, ">>$output") || die "Unable to open $output. " . $! . "\n"; my %service; my @duplicates; while () { chomp (my $line = $_); next if ($line =~ /^\s*#/); next if ($line =~ /^\s*$/); $line =~ /^([^\s]+)\s+([^\s]+)/; my $label = $1; my $port = $2; my $comment; $line =~ s/^([^\s]+)\s+([^\s]+)\s+//; if ($line =~ /\w/) { $comment = $line; if ($comment !~ /^#/ ) { $comment = '# ' . $line; } elsif ($comment =~ /^#\w/) { $comment =~ s/^#/# /; } } else { $comment = '# ' . $label; } # add leading zeros to $key for string sort; my $key = $port; # we could very easily just use port like this 21/tcp, 21/udp # but due to sctp, we need to make an adjustment for numeric sorting $key =~ s/sctp/sct/ if ($key =~ /sctp/); my $str_len = length $key; while ($str_len < 17) { $key = "0" . $key; $str_len++; } # catch duplicates before we overwrite them if (defined $service{$key}{"port"} ) { push (@duplicates, $port); } $service{$key}{"label"} = $label; $service{$key}{"port"} = $port; $service{$key}{"comment"} = $comment; } close INPUT; foreach my $key (sort keys %service) { my $label = $service{$key}{"label"}; my $port = $service{$key}{"port"}; my $comment = $service{$key}{"comment"}; printf OUTPUT ("%-18s%18s%5s%-18s\n", $label, $port, " ", $comment); } foreach my $dup (@duplicates) { print "Duplicate found: $dup\n"; } print "If any duplicates were found, grep for them on the original file\n"; print "\nOutput is in $outfile.\nDone!\n"; close OUTPUT; exit (0);