查看组名或数值组ID。
#include <grp.h> struct group *getgrnam(const char *name); struct group *getgrgid(gid_t gid); // 两个函数的返回值:若成功则返回指针,若出错则返回NULL
如同对口令文件进行操作的函数一样,这两个函数也通常返回一个指向静态变量的指针,在每次调用时都重写该静态变量。
group结构定义如下:
struct group { char *gr_name; /* group name */ char *gr_passwd; /* group password */ gid_t gr_gid; /* group ID */ char **gr_mem; /* group members */ };
字段gr_men是一个指针数组,其中每个指针各指向一个属于该组的用户名,该数组以空指针结尾。
如果需要搜索整个组文件,则需要使用另外几个函数。下列三个函数类似于针对口令文件的三个函数。
#include <grp.h> struct group *getgrent(void); // 返回值:若成功则返回指针,若出错或到达文件结尾则返回NULL void setgrent(void); void endgrent(void);
setgrent函数打开组文件(如果它尚未被打开)并反绕它。getgrent函数从组文件中读取下一个记录,如若该文件尚未打开则先打开它。endgrent函数关闭组文件。
我们不仅可以属于口令文件记录项中组ID所对应的组,也可属于另外的附加组。文件的访问权限检查被修改为:不仅将进程的有效组ID与文件的组ID相比较,而且也将附加组ID与文件的组ID相比较。
为了获取和设置附加组ID,提供了下列三个函数:
#include <unistd.h> int getgroups(int size, gid_t list[]); // 返回值:若成功则返回附加组ID数,若出错则返回-1 #include <grp.h> int setgroups(size_t size, const gid_t *list); // 返回值:若成功则返回0,若出错则返回-1 #include <grp.h> int initgroups(const char *user, gid_t group); // 返回值:若成功则返回0,若出错则返回-1
getgroups将各个附加组ID添写到数组list中,该数组中存放的元素最多为size个。实际填写到数组中的附加组ID数由函数返回。
作为一个特例,如果size为0,则函数只返回附加组ID数,而对数组list则不作修改。
setgroups可由超级用户调用以便为调用进程设置附加组ID表。list是组ID数组,而size指定了数组中的元素个数。
通常只有initgroups函数调用setgroups,initgroups读取整个组文件(前面说明的函数getgrent、setgrent和endgrent),然后对user确定其组的成员关系。然后,它调用setgroups,以便为该用户初始化附加组ID表。只有超级用户才能调用initgroups。除了在组文件中找到user时成员的所有组,initgroups也在附加组ID表中包括了group。group是user在口令文件中的组ID。
下列程序获取附加组ID,并输出组名:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <grp.h> #define SIZE 20 int main(int argc, char *argv[]) { int size, i; gid_t list[SIZE]; struct group *ptr;; size = getgroups(SIZE, list); for (i = 0; i < size; i++) { ptr = getgrgid(list[i]); printf("group[%d] = %5d, %s\n", i, list[i], ptr->gr_name); } exit(0); }
在很多系统中,用户和组数据库是用网络信息服务(NIS)实现的。这使管理员可编辑数据库的主副本,然后将它自动分发到组织中的所有服务器上。客户端系统可以联系服务器以查看用户和组的有关信息。NIS+和轻量级目录访问协议(LDAP)提供了类似功能。很多系统通过配置文件/etc/nsswitch.conf来管理每一类信息的方法。
UNIX还使用还能多其他文件:记录各网络服务器所提供服务的数据文件(/etc/services),记录协议信息的数据文件(/etc/protocols),记录网络信息的数据文件(/etc/networks)等。针对这些数据文件的接口都与上述对口令文件和组文件的接口相似。
一般情况下,对于每个数据文件至少有三个函数:
(1) get函数:读下一个记录,如果需要,还可打开文件。这些函数通常返回指向一个结构的指针,当已到达文件尾端时则返回空指针。大多数get函数返回指向一个静态结构的指针,如果需要保存其内容,则需复制它。
(2) set函数:打开相应数据文件(如果尚未打开),然后反绕文件。如果希望在相应文件起始处开始处理,则调用此函数。
(3) end函数:关闭相应数据文件。在结束了对相应数据文件的读、写操作后,总应调用此函数以关闭所有相关文件。
如果数据文件支持某种形式的关键字搜索,则会提供搜索具有指定关键字记录的例程。
说明 |
数据文件 |
头文件 |
结构 |
附加的关键字查找函数 |
口令 组 阴影 主机 网络 协议 服务 |
/etc/passwd /etc/group /etc/shadow /etc/hosts /etc/networks /etc/protocols /etc/services |
<pwd.h> <grp.h> <shadow.h> <netdb.h> <netdb.h> <netdb.h> <netdb.h> |
passwd group spwd hostent netent protoent servent |
getpwnam、getpwuid getgrnam、getgrgid getspnam gethostbyname、gethostbyaddr getnetbyname、getnetbyaddr getprotobyname、getprotobynumber getservbyname、getservbyport |