getpwnam 名称
getgrnam 名称
gethostbyname 名称
getnetbyname 名称
getprotobyname 名称
getpwuid UID
getgrgid GID
getservbyname 名称,协议
gethostbyaddr 地址,地址类型
getnetbyaddr 地址,地址类型
getprotobynumber 编号
getservbyport 端口,协议
getpwent
getgrent
gethostent
getnetent
getprotoent
getservent
setpwent
setgrent
sethostent STAYOPEN
setnetent STAYOPEN
setprotoent STAYOPEN
setservent STAYOPEN
endpwent
endgrent
endhostent
endnetent
endprotoent
endservent

这些例程与系统 C 库中的例程相同。在列表上下文中,各种 get 例程的返回值如下

#    0        1          2           3         4
my ( $name,   $passwd,   $gid,       $members  ) = getgr*
my ( $name,   $aliases,  $addrtype,  $net      ) = getnet*
my ( $name,   $aliases,  $port,      $proto    ) = getserv*
my ( $name,   $aliases,  $proto                ) = getproto*
my ( $name,   $aliases,  $addrtype,  $length,  @addrs ) = gethost*
my ( $name,   $passwd,   $uid,       $gid,     $quota,
   $comment,  $gcos,     $dir,       $shell,   $expire ) = getpw*
#    5        6          7           8         9

(如果条目不存在,返回值是一个无意义的 true 值。)

$gcos 字段的确切含义各不相同,但通常包含用户的真实姓名(与登录名相对)和与用户相关的其他信息。但是,请注意,在许多系统中,用户可以更改此信息,因此不能信任,因此 $gcos 被污染(请参阅 perlsec)。出于同样的原因,用户的加密密码和登录 shell($passwd 和 $shell)也被污染。

在标量上下文中,您将获得名称,除非该函数是按名称查找,在这种情况下,您将获得其他内容,无论它是什么。(如果条目不存在,您将获得未定义的值。)例如

my $uid   = getpwnam($name);
my $name  = getpwuid($num);
my $name  = getpwent();
my $gid   = getgrnam($name);
my $name  = getgrgid($num);
my $name  = getgrent();
# etc.

getpw*() 中,字段 $quota、$comment 和 $expire 很特殊,因为它们在许多系统上不受支持。如果 $quota 不受支持,它将是一个空标量。如果它受支持,它通常会对磁盘配额进行编码。如果 $comment 字段不受支持,它将是一个空标量。如果它受支持,它通常会对用户进行一些管理注释编码。在某些系统中,$quota 字段可能是 $change 或 $age,这些字段与密码老化有关。在某些系统中,$comment 字段可能是 $class。$expire 字段(如果存在)会对帐户或密码的过期期限进行编码。有关这些字段在系统中的可用性和确切含义,请参阅 getpwnam(3) 和系统的 pwd.h 文件。您还可以通过使用 Config 模块和值 d_pwquotad_pwaged_pwchanged_pwcommentd_pwexpire 从 Perl 中找出 $quota 和 $comment 字段的含义以及您是否有 $expire 字段。只有当您的供应商以直观的方式实现了影子密码文件时,才支持影子密码文件,即在特权下运行或存在 shadow(3) 函数(如在 System V 中找到的)时,调用常规 C 库例程会获取影子版本(包括 Solaris 和 Linux)。那些实现专有影子密码机制的系统不太可能得到支持。

getgr*() 返回的 $members 值是组成员的登录名空格分隔列表。

对于 gethost*() 函数,如果 C 中支持 h_errno 变量,如果函数调用失败,它将通过 $? 返回给您。成功调用返回的 @addrs 值是相应库调用返回的原始地址列表。在因特网域中,每个地址的长度为四个字节;您可以通过说出类似以下内容来解压缩它

my ($w,$x,$y,$z) = unpack('W4',$addr[0]);

套接字库让这变得稍微容易一些

use Socket;
my $iaddr = inet_aton("127.1"); # or whatever address
my $name  = gethostbyaddr($iaddr, AF_INET);

# or going the other way
my $straddr = inet_ntoa($iaddr);

相反,要将主机名解析为 IP 地址,您可以编写以下内容

use Socket;
my $packed_ip = gethostbyname("www.perl.org");
my $ip_address;
if (defined $packed_ip) {
    $ip_address = inet_ntoa($packed_ip);
}

确保在 SCALAR 上下文中调用 gethostbyname,并检查其返回值是否已定义。

getprotobynumber 函数虽然只有一个参数,但具有列表运算符的优先级,因此请注意

getprotobynumber $number eq 'icmp'   # WRONG
getprotobynumber($number eq 'icmp')  # actually means this
getprotobynumber($number) eq 'icmp'  # better this way

如果您厌倦了记住返回列表的哪个元素包含哪个返回值,则标准模块中提供了按名称命名的接口:File::statNet::hostentNet::netentNet::protoentNet::serventTime::gmtimeTime::localtimeUser::grent。这些覆盖了正常的内置函数,提供返回具有每个字段的相应名称的对象的版本。例如

use File::stat;
use User::pwent;
my $is_his = (stat($filename)->uid == pwent($whoever)->uid);

尽管看起来它们是相同的方法调用 (uid),但它们不是,因为 File::stat 对象与 User::pwent 对象不同。

在多个线程可以使用这些函数的多线程环境中,其中许多函数不安全。特别是,诸如 getpwent() 之类的函数按进程而不是按线程进行迭代,因此如果两个线程同时进行迭代,则两者都将无法获取所有记录。

某些系统具有某些函数的线程安全版本,例如 getpwnam_r() 而不是 getpwnam()。在那里,Perl 会自动且无形地替换线程安全版本,而无需通知。这意味着在某些系统上安全运行的代码可能会在缺少线程安全版本的其他系统上失败。

可移植性问题:perlport 中的“getpwnam”perlport 中的“endservent”