--- name: getservent signature: 'getservent' since: 5.0 status: documented categories: ["Network info"] --- ```{index} single: getservent; Perl built-in ``` *[Network info](../perlfunc-by-category)* # getservent Read the next entry from the system services database. `getservent` walks the `/etc/services` database one record at a time, yielding the same list of fields as [`getservbyname`](getservbyname) and [`getservbyport`](getservbyport) but without a lookup key. Each call advances an internal cursor; the cursor is opened on the first call, rewound by [`setservent`](setservent), and released by [`endservent`](endservent). It mirrors the POSIX `getservent(3)` C library routine and inherits every portability quirk that implies. ## Synopsis ```perl my ($name, $aliases, $port, $proto) = getservent; my $name = getservent; # scalar context ``` ## What you get back In list context, four fields matching the order documented for every `getserv*` variant: - `$name` — canonical service name, e.g. `"http"`. - `$aliases` — space-separated string of alternate names, e.g. `"www www-http"`. Not an array; split it yourself if you need one. - `$port` — port number as a native (host-byte-order) integer, e.g. `80`. - `$proto` — transport protocol, typically `"tcp"` or `"udp"`. In scalar context, just `$name`. When the cursor reaches end of file, `getservent` returns the empty list in list context and [`undef`](undef) in scalar context — the idiomatic `while (my @e = getservent)` loop relies on this. To convert the aliases into a list: ```perl my @alt = split / /, $aliases; ``` ## Global state it touches - **Internal database cursor** for `/etc/services` — shared with [`getservbyname`](getservbyname), [`getservbyport`](getservbyport), [`setservent`](setservent), and [`endservent`](endservent). Any by-name or by-port lookup on some platforms rewinds or closes this cursor as a side effect; iterate in a tight loop or wrap the iteration in [`setservent`](setservent) / [`endservent`](endservent) to be safe. - [`$!`](../perlvar) — set when the underlying C call reports an error. - Not thread-safe. `getservent` keeps per-process, not per-thread state; two threads iterating concurrently will interleave records and neither will see the full list. ## Examples Walk the full services database and print each entry: ```perl while (my ($name, $aliases, $port, $proto) = getservent) { print "$name/$proto $port\n"; } endservent; ``` Reset the cursor before iterating so earlier calls elsewhere in the program cannot leave it mid-stream: ```perl setservent(0); while (my @e = getservent) { # @e is ($name, $aliases, $port, $proto) } endservent; ``` Collect only TCP services into a hash keyed by port: ```perl my %tcp; while (my ($name, undef, $port, $proto) = getservent) { $tcp{$port} = $name if $proto eq 'tcp'; } endservent; ``` Use the object-oriented by-name interface from `Net::servent`, which overrides the built-in and returns a blessed object with accessor methods: ```perl use Net::servent; while (my $s = getservent) { printf "%-20s %5d/%s\n", $s->name, $s->port, $s->proto; } ``` ## Edge cases - **End of file returns empty / undef, not an error.** A single-scalar false value in list context (`my @e = getservent` giving an empty list) is the terminator. Do not check [`$!`](../perlvar) to detect end of iteration. - **Missing `/etc/services`**: on systems without the file, the first call returns the empty list immediately and [`$!`](../perlvar) is set. Nothing in the call signals the difference between an empty database and a missing one — inspect [`$!`](../perlvar) before assuming the database was simply empty. - **Cursor sharing with by-name / by-port lookups**: calling [`getservbyname`](getservbyname) or [`getservbyport`](getservbyport) in the middle of a `getservent` loop may reset the cursor on some platforms. Either finish the walk first or re-open with [`setservent`](setservent). - **`$aliases` is a string, not a list**. `split / /, $aliases` gives you the array form. Treating `$aliases` as a list directly silently gives you the length of a one-element list. - **Threaded programs**: iteration is per-process. Coordinate access with a lock, or prefer `getservbyname` / `getservbyport` for point queries in threaded code. - **Scalar context returns only the name.** If you need the port, call in list context even when you only care about one field. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`getservbyname`](getservbyname) — look up a single service by its textual name instead of iterating - [`getservbyport`](getservbyport) — look up a single service by its numeric port - [`setservent`](setservent) — rewind the shared cursor before iterating so prior calls cannot leave it mid-stream - [`endservent`](endservent) — release the cursor when the walk is done, freeing the underlying file descriptor - [`getprotoent`](getprotoent) — same iterator pattern for `/etc/protocols`, typically paired when resolving a `(port, proto)` tuple - `Net::servent` — object-oriented wrapper whose accessors remove the need to remember field order