getservent#
Read the next entry from the system services database.
getservent walks the /etc/services database one record at a time,
yielding the same list of fields as getservbyname and
getservbyport but without a lookup key. Each call
advances an internal cursor; the cursor is opened on the first call,
rewound by setservent, and released by
endservent. It mirrors the POSIX getservent(3) C
library routine and inherits every portability quirk that implies.
Synopsis#
my ($name, $aliases, $port, $proto) = getservent;
my $name = getservent; # scalar context
What you get back#
In list context, four fields matching the order documented for every
getserv* variant:
$name— canonical service name, e.g."http".$aliases— space-separated string of alternate names, e.g."www www-http". Not an array; split it yourself if you need one.$port— port number as a native (host-byte-order) integer, e.g.80.$proto— transport protocol, typically"tcp"or"udp".
In scalar context, just $name. When the cursor reaches end of file,
getservent returns the empty list in list context and undef
in scalar context — the idiomatic while (my @e = getservent) loop
relies on this.
To convert the aliases into a list:
my @alt = split / /, $aliases;
Global state it touches#
Internal database cursor for
/etc/services— shared withgetservbyname,getservbyport,setservent, andendservent. Any by-name or by-port lookup on some platforms rewinds or closes this cursor as a side effect; iterate in a tight loop or wrap the iteration insetservent/endserventto be safe.$!— set when the underlying C call reports an error.Not thread-safe.
getserventkeeps per-process, not per-thread state; two threads iterating concurrently will interleave records and neither will see the full list.
Examples#
Walk the full services database and print each entry:
while (my ($name, $aliases, $port, $proto) = getservent) {
print "$name/$proto $port\n";
}
endservent;
Reset the cursor before iterating so earlier calls elsewhere in the program cannot leave it mid-stream:
setservent(0);
while (my @e = getservent) {
# @e is ($name, $aliases, $port, $proto)
}
endservent;
Collect only TCP services into a hash keyed by port:
my %tcp;
while (my ($name, undef, $port, $proto) = getservent) {
$tcp{$port} = $name if $proto eq 'tcp';
}
endservent;
Use the object-oriented by-name interface from Net::servent, which
overrides the built-in and returns a blessed object with accessor
methods:
use Net::servent;
while (my $s = getservent) {
printf "%-20s %5d/%s\n", $s->name, $s->port, $s->proto;
}
Edge cases#
End of file returns empty / undef, not an error. A single-scalar false value in list context (
my @e = getserventgiving an empty list) is the terminator. Do not check$!to detect end of iteration.Missing
/etc/services: on systems without the file, the first call returns the empty list immediately and$!is set. Nothing in the call signals the difference between an empty database and a missing one — inspect$!before assuming the database was simply empty.Cursor sharing with by-name / by-port lookups: calling
getservbynameorgetservbyportin the middle of agetserventloop may reset the cursor on some platforms. Either finish the walk first or re-open withsetservent.$aliasesis a string, not a list.split / /, $aliasesgives you the array form. Treating$aliasesas a list directly silently gives you the length of a one-element list.Threaded programs: iteration is per-process. Coordinate access with a lock, or prefer
getservbyname/getservbyportfor point queries in threaded code.Scalar context returns only the name. If you need the port, call in list context even when you only care about one field.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
getservbyname— look up a single service by its textual name instead of iteratinggetservbyport— look up a single service by its numeric portsetservent— rewind the shared cursor before iterating so prior calls cannot leave it mid-streamendservent— release the cursor when the walk is done, freeing the underlying file descriptorgetprotoent— same iterator pattern for/etc/protocols, typically paired when resolving a(port, proto)tupleNet::servent— object-oriented wrapper whose accessors remove the need to remember field order