getprotoent#
Fetch the next entry from the protocols database.
getprotoent walks the system protocols database — on traditional
Unix-likes that’s /etc/protocols, on modern systems whatever the C
library and NSS stack map to it — returning one record per call until
the database is exhausted. It is the iterating leg of the
setprotoent / getprotoent / endprotoent
triad. Reach for getprotobyname or
getprotobynumber when you want a single targeted
lookup; getprotoent is for enumerating every protocol known to the
system.
The iteration cursor is shared process-wide and owned by the C
library. setprotoent rewinds it and optionally pins
the backing descriptor open; endprotoent closes it.
Between those two calls getprotoent yields each record in order,
then returns the empty list (or undef in scalar context)
once there is nothing left.
Synopsis#
my ($name, $aliases, $proto) = getprotoent;
my $name = getprotoent;
What you get back#
List context — a three-element list mirroring the C struct protoent:
$name— the canonical protocol name, e.g."tcp","udp","icmp".$aliases— a space-separated string of alternate names for the same protocol. Often empty.$proto— the numeric protocol number as used in IP headers and accepted bysocket/getsockopt.
At end-of-database the return is the empty list. The upstream
perlfunc note about “a single meaningless true value” for missing
entries applies to the by-name and by-number lookups, not to
getprotoent — running off the end of the iteration is a clean empty
list.
Scalar context — the canonical $name only, or undef
at end-of-database. Use list context whenever you need the number or
the aliases; you cannot reconstruct them from the name after the
fact.
Split the aliases into a list with a plain split:
my @alts = split ' ', $aliases;
Global state it touches#
The protocols database cursor, a per-process C-library-owned resource shared with
setprotoent,endprotoent,getprotobyname, andgetprotobynumber. A by-name or by-number lookup may reset the cursor mid-iteration on some platforms — see Edge cases.No Perl-level special variables are read or written. Unlike
gethostent, the protocols routines have noh_errnoequivalent, so$?is not touched. End of database is not a failure and does not set$!.
Examples#
Enumerate every protocol the system knows about:
setprotoent(1);
while (my ($name, $aliases, $proto) = getprotoent) {
print "$proto\t$name\t$aliases\n";
}
endprotoent;
Scalar context — list just the canonical names:
setprotoent(0);
while (defined(my $name = getprotoent)) {
print "$name\n";
}
endprotoent;
Build a name-to-number map in one pass so later lookups don’t hit the database at all:
my %proto_num;
setprotoent(1);
while (my ($name, $aliases, $num) = getprotoent) {
$proto_num{$name} = $num;
$proto_num{$_} = $num for split ' ', $aliases;
}
endprotoent;
print $proto_num{"tcp"}, "\n"; # 6
By-record interface via the Net::protoent override — accessor
methods instead of positional unpacking:
use Net::protoent;
while (my $p = getprotoent) {
printf "%-10s %3d\n", $p->name, $p->proto;
}
Edge cases#
No implicit rewind.
getprotoentdoes not open or rewind the database on its own. The first call after program start works because the C library lazily opens the file, but once the end is reached further calls keep returning end-of-database until asetprotoentrewinds the cursor. Always bracket enumeration with an explicitsetprotoentandendprotoent.End-of-database is the empty list, not
undef. In list context the loop conditionwhile (my @r = getprotoent)works because the empty list is false. In scalar context usewhile (defined(my $name = getprotoent))— a protocol name of"0"is theoretically valid and would falsely terminate a truthiness-based loop.Aliases are one scalar, not a list.
$aliasesis a single space-separated string; split on whitespace if you want a list. An empty aliases field is the common case, not an error.Interleaving with by-name / by-number lookups. A call to
getprotobynameorgetprotobynumberduring a walk can reset the shared cursor on some platforms. Finish the iteration first, or restart it withsetprotoentafter the lookup.Not reentrant. The database cursor is a single global resource inside the C library. Two concurrent iterations in the same process — across threads, signal handlers, or nested callbacks — corrupt each other’s state. Confine each walk to one thread at a time.
Platforms without a protocols database. On systems with no
/etc/protocolsequivalent, the call is a no-op that returns the empty list immediately rather than raising an error. Seeperlportfor the full list of network-database quirks.Tainting. Records come from a file the kernel reads on your behalf and are not marked tainted. Treat them as untrusted anyway when the file is user-writable.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
setprotoent— rewind the iterator and optionally pin the backing descriptor open for the full walkendprotoent— close the iterator and release the database handle once enumeration is donegetprotobyname— targeted lookup by protocol name instead of full enumerationgetprotobynumber— targeted lookup by numeric protocol numbergetservent— same iteration pattern for the services database, which references protocol names from this onegethostent— same idiom for the hosts database