setservent#
Rewind the services database and optionally keep it open across lookups.
setservent is the services-database counterpart of the C library’s
setservent(3). It resets the internal cursor used by
getservent so the next call starts again at the first
entry of /etc/services (or whatever source the system resolver is
configured to use), and it controls whether the underlying file stays
open between by-name and by-port lookups.
Synopsis#
setservent STAYOPEN
setservent 0 # close file between lookups (default)
setservent 1 # keep file open across lookups
What you get back#
The return value is whatever the underlying C setservent(3) returns
— on most systems that’s nothing useful, and scripts do not check it.
Treat setservent as called for its side effect on the iterator, not
for a value.
Global state it touches#
The per-process services-database cursor shared with
getservent,getservbyname,getservbyportandendservent. All four read and mutate the same state; iteration is not thread-safe and not reentrant.The open/closed status of the services database file.
STAYOPENtrue leaves the file open untilendserventis called;STAYOPENfalse (the default) causes each subsequent by-name or by-port lookup to open and close the file again.
The STAYOPEN argument#
Pass a true value to hold the file open across a run of individual
getservbyname or getservbyport
lookups. This is an optimisation for batch resolution, not a semantic
change: results are identical either way.
setservent 1;
for my $name (@service_names) {
my @svc = getservbyname $name, "tcp";
# ... process @svc ...
}
endservent;
Pass a false value (or 0) when you want each lookup to reopen the
file. This is the default behaviour and the one most programs want.
Examples#
Walk every entry in the services database and print name/port pairs:
setservent 0;
while (my ($name, undef, $port, $proto) = getservent) {
print "$name $port/$proto\n";
}
endservent;
Rewind mid-iteration to start over:
setservent 0;
my @first_pass;
while (my @svc = getservent) {
push @first_pass, $svc[0];
last if @first_pass == 10;
}
setservent 0; # cursor back to start
my @second_pass = getservent; # first entry again
endservent;
Batch-resolve with the file held open:
my @wanted = qw(http https ssh smtp);
setservent 1;
my %port = map { $_ => scalar getservbyname($_, "tcp") } @wanted;
endservent;
Edge cases#
STAYOPENis required at the Perl level.setserventis parsed with list-operator precedence and reads one argument; a baresetservent;with no argument is a compile-time error. Pass0when you want the default “close after each lookup” behaviour.Platform dependence. The services database is whatever the system resolver uses — typically
/etc/services, but NIS, LDAP, and other name-service backends can supply entries.setserventrewinds whichever source the C library selects; the Perl level has no say in it.Non-Unix platforms. On systems without
setservent(3)the call croaks withThe setservent function is unimplemented. Seeperlportfor the availability matrix.Threads. Iterator state is per-process, not per-thread; two threads walking the services database concurrently will interleave and neither will see every record. See the shared note in
perlfuncongetpwnam-family thread safety.Pairing with
endservent. WhenSTAYOPENwas true, callendserventto release the file descriptor; otherwise the handle leaks for the life of the process.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
getservent— walk the services database one entry at a time; this is the iteratorsetserventrewindsendservent— close the services database file opened bysetservent 1getservbyname— look up a single service by name; honours the open/closed state set heregetservbyport— look up a single service by port number; same open/closed semanticssetprotoent— same pattern for the protocols database when you are rewinding both togetherNet::servent— object-oriented wrapper over thegetserv*family for when positional return lists get unwieldy