Network info

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, getservbyport and endservent. 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. STAYOPEN true leaves the file open until endservent is called; STAYOPEN false (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#

  • STAYOPEN is required at the Perl level. setservent is parsed with list-operator precedence and reads one argument; a bare setservent; with no argument is a compile-time error. Pass 0 when 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. setservent rewinds 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 with The setservent function is unimplemented. See perlport for 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 perlfunc on getpwnam-family thread safety.

  • Pairing with endservent. When STAYOPEN was true, call endservent to 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 iterator setservent rewinds

  • endservent — close the services database file opened by setservent 1

  • getservbyname — look up a single service by name; honours the open/closed state set here

  • getservbyport — look up a single service by port number; same open/closed semantics

  • setprotoent — same pattern for the protocols database when you are rewinding both together

  • Net::servent — object-oriented wrapper over the getserv* family for when positional return lists get unwieldy