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