P5getservbyname
WorksThe POSIX service-database calls, shaped so the return value matches what Perl's built-ins of the same name hand back, with ports byte-swapped into host order for you.
- Version
0.0.8zef:lizmat- Depends
none beyond the core- License
- Artistic-2.0
- Its own test suite
- 2 files, green
- Checked
- 2026-09-15 against Raku++ 3.28.0 and Rakudo 2026.08
Install it #
$ rakupp install P5getservbynamezef install P5getservbyname writes the same store; either installer leaves the module usable by both engines.
What it is for #
/etc/services maps service names to port numbers, and getservbyname(3) is how a program asks about it without parsing the file. Raku has no built-in for it, so anything that wants to resolve https to 443 the way the operating system would has to bind the C call.
This distribution binds it, and shapes the answer the way Perl's getserv* built-ins do — which matters if you are porting Perl, and is a reasonable shape regardless.
Looking a service up #
use P5getservbyname;
for <ssh http https smtp domain> -> $name {
my @r = getservbyname($name, 'tcp');
say sprintf('%-8s/tcp fields=%d name=%-8s port=%-5d proto=%s',
$name, @r.elems, @r[0], @r[2], @r[3]);
}ssh /tcp fields=4 name=ssh port=22 proto=tcp
http /tcp fields=4 name=http port=80 proto=tcp
https /tcp fields=4 name=https port=443 proto=tcp
smtp /tcp fields=4 name=smtp port=25 proto=tcp
domain /tcp fields=4 name=domain port=53 proto=tcpThe record is ($name, $aliases, $port, $proto), in Perl's order. The IANA numbers are the same on every machine, which is why they are safe to print; the aliases are not — they come from your /etc/services and vary.
The port is already in host byte order. The module byte-swaps in both directions, so you never see network order.
Scalar context #
use P5getservbyname;
say 'by name, gives the port : ', getservbyname(Scalar, 'https', 'tcp');
say 'by port, gives the name : ', getservbyport(Scalar, 443, 'tcp');
say '';
say 'the list forms of the same two calls:';
say ' getservbyname("https","tcp")[2] = ', getservbyname('https', 'tcp')[2];
say ' getservbyport(443,"tcp")[0] = ', getservbyport(443, 'tcp')[0];by name, gives the port : 443
by port, gives the name : https
the list forms of the same two calls:
getservbyname("https","tcp")[2] = 443
getservbyport(443,"tcp")[0] = httpsPerl asks for a scalar by calling in scalar context; Raku has no such thing, so the module takes the Scalar type object as an extra first argument. The result is asymmetric by design: lookup by name gives you the id, lookup by id gives you the name.
Enumerating #
use P5getservbyname;
say 'setservent : ', setservent(1);
my ($n, $widest) = 0, 0;
loop {
my @e = getservent() or last;
$n++;
$widest = @e.elems if @e.elems > $widest;
}
say 'endservent : ', endservent();
say 'entries walked : ', $n > 0;
say 'every entry had four fields : ', $widest == 4;setservent : 1
endservent : 1
entries walked : True
every entry had four fields : TrueThe sentinel for "no more entries" is the same empty list a failed lookup gives, so one test ends the loop — and the two cases are indistinguishable.
The one thing to know #
The protocol argument is mandatory and must match exactly. There is no "any protocol" lookup.
use P5getservbyname;
for 'tcp', 'TCP', '' -> $proto {
say sprintf('getservbyname("ssh", %-7s) -> %d field(s)',
$proto.raku, getservbyname('ssh', $proto).elems);
}
say '';
say 'in C you pass NULL for proto to match any protocol.';
say 'here the parameter is Str(), so the only thing you can supply';
say 'is a string — and the empty string matches nothing.';getservbyname("ssh", "tcp" ) -> 4 field(s)
getservbyname("ssh", "TCP" ) -> 0 field(s)
getservbyname("ssh", "" ) -> 0 field(s)
in C you pass NULL for proto to match any protocol.
here the parameter is Str(), so the only thing you can supply
is a string — and the empty string matches nothing.The lookup is also case-sensitive: 'TCP' returns nothing. So a protocol name arriving from a configuration file has to be lower-cased before it gets here, and there is no way to ask the question C lets you ask.
Where the two engines differ #
Nowhere. Every lookup, every scalar form, the enumeration and all three rejections produced identical output on Raku++ and Rakudo.
The convention shared by the whole P5get* family is worth stating once, because it is the thing that catches people. A failed lookup returns an empty list, never an exception — so destructuring into four variables leaves every one of them undefined, and the natural Perl transcription that reads field 2 of the result gets Any rather than an error. Test the list, never a field:
use P5getservbyname;
my @miss = getservbyname('nosuchservice-xyzzy', 'tcp');
say 'list form elems : ', @miss.elems;
say 'scalar form : ', getservbyname(Scalar, 'nosuchservice-xyzzy', 'tcp').defined;
say '';
my ($name, $aliases, $port, $proto) = getservbyname('nosuchservice-xyzzy', 'tcp');
say 'port after a failed lookup : ', $port.defined ?? $port !! 'undefined';
say 'the right test is on the list : ',
?getservbyname('nosuchservice-xyzzy', 'tcp').elems;list form elems : 0
scalar form : False
port after a failed lookup : undefined
the right test is on the list : False