--- name: getprotoent signature: 'getprotoent' since: 5.0 status: documented categories: ["Network info"] --- ```{index} single: getprotoent; Perl built-in ``` *[Network info](../perlfunc-by-category)* # 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`](setprotoent) / `getprotoent` / [`endprotoent`](endprotoent) triad. Reach for [`getprotobyname`](getprotobyname) or [`getprotobynumber`](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`](setprotoent) rewinds it and optionally pins the backing descriptor open; [`endprotoent`](endprotoent) closes it. Between those two calls `getprotoent` yields each record in order, then returns the empty list (or [`undef`](undef) in scalar context) once there is nothing left. ## Synopsis ```perl 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 by [`socket`](socket) / [`getsockopt`](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`](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`](split): ```perl my @alts = split ' ', $aliases; ``` ## Global state it touches - The **protocols database cursor**, a per-process C-library-owned resource shared with [`setprotoent`](setprotoent), [`endprotoent`](endprotoent), [`getprotobyname`](getprotobyname), and [`getprotobynumber`](getprotobynumber). 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`](gethostent), the protocols routines have no `h_errno` equivalent, so [`$?`](../perlvar) is not touched. End of database is not a failure and does not set [`$!`](../perlvar). ## Examples Enumerate every protocol the system knows about: ```perl setprotoent(1); while (my ($name, $aliases, $proto) = getprotoent) { print "$proto\t$name\t$aliases\n"; } endprotoent; ``` Scalar context — list just the canonical names: ```perl 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: ```perl 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: ```perl use Net::protoent; while (my $p = getprotoent) { printf "%-10s %3d\n", $p->name, $p->proto; } ``` ## Edge cases - **No implicit rewind.** `getprotoent` does 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 a [`setprotoent`](setprotoent) rewinds the cursor. Always bracket enumeration with an explicit [`setprotoent`](setprotoent) and [`endprotoent`](endprotoent). - **End-of-database is the empty list, not [`undef`](undef).** In list context the loop condition `while (my @r = getprotoent)` works because the empty list is false. In scalar context use `while (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.** `$aliases` is 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 [`getprotobyname`](getprotobyname) or [`getprotobynumber`](getprotobynumber) during a walk can reset the shared cursor on some platforms. Finish the iteration first, or restart it with [`setprotoent`](setprotoent) after 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/protocols` equivalent, the call is a no-op that returns the empty list immediately rather than raising an error. See `perlport` for 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`](setprotoent) — rewind the iterator and optionally pin the backing descriptor open for the full walk - [`endprotoent`](endprotoent) — close the iterator and release the database handle once enumeration is done - [`getprotobyname`](getprotobyname) — targeted lookup by protocol name instead of full enumeration - [`getprotobynumber`](getprotobynumber) — targeted lookup by numeric protocol number - [`getservent`](getservent) — same iteration pattern for the services database, which references protocol names from this one - [`gethostent`](gethostent) — same idiom for the hosts database