POSIX 用户操作
用户口令操作
SylixOS 定义了两个获得口令文件项的函数,在用户给出用户名或用户 ID 后,使用以下两个函数可以查询用户信息。
#include <pwd.h>
struct passwd *getpwuid(uid_t uid);
int getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer,
size_t bufsize, struct passwd **result);
函数 getpwuid_r 原型分析:
- 此函数成功返回 0,失败返回-1 并设置错误号。
- 参数 uid 是用户 ID。
- 输出参数 pwd 返回用户信息。
- 参数 buffer 是缓冲区。
- 参数 bufsize 是缓冲区大小。
- 输出参数 result 返回用户信息指针。
getpwuid_r 函数将搜索用户数据库文件/etc/passwd 以获得与参数 uid 匹配的用户信息,用户信息将被存储在 buffer 指向的缓冲区中,并更新 pwd 结构体。如果发现一个匹配的用户,则会将 pwd 指针存放到 result 中返回,否则 result 返回 NULL。
需要注意的是,getpwuid 是非可重入的,因此该函数是非线程安全的。
struct passwd *getpwnam(const char *name);
int getpwnam_r(const char *name, struct passwd *pwd,
char *buffer, size_t bufsize, struct passwd **result);
函数 getpwnam_r 原型分析:
- 此函数成功返回 0,失败返回-1 并设置错误号。
- 参数 name 是用户名。
- 输出参数 pwd 返回用户信息。
- 参数 buffer 是缓冲区。
- 参数 bufsize 是缓冲区大小。
- 输出参数 result 返回用户信息指针。
getpwnam_r 函数功能类似于 getpwuid_r 函数,不同的是参数 name 是需要匹配的用户名而非用户 ID(getpwuid_r 是匹配用户 ID)。getpwnam 函数是非可重入的。
如果要查看的只是用户名和用户 ID,那么上面两个函数可以满足要求,但是有些程序要查看整个口令文件,那么需要调用以下三个函数可以实现此目的。
#include <pwd.h>
struct passwd *getpwent(void);
void setpwent(void);
void endpwent(void);
调用 getpwent 函数时,它返回口令文件中的下一个记录项,如同上面所述的两个函数一样,它返回一个由它填写好的 passwd 结构指针。第一次调用该函数时,将打开它使用的各个文件且每次调用此函数时都将重写 passwd 结构。需要注意的是,使用该函数对口令文件中各个记录项的顺序并无要求。
setpwent 函数可以将 getpwent 函数的读写地址指回口令文件开头(通常称为反绕),endpwent 则关闭这些文件。在使用 getpwent 查看完口令文件后,一定要调用 endpwent 关闭这些文件。getpwent 只知道什么时间应该打开它所使用的文件(第一次调用时),但是它并不知道何时应该关闭这些文件。
在程序开始时调用 setpwent 是自我保护性的措施,以防止调用者在此之前已经调用了 getpwent 函数打开了文件,反绕有关文件使它定位到文件开始的位置。
用户阴影口令操作
与访问口令文件的一组函数类似,有另一组函数用于访问阴影口令文件。
#include <shadow.h>
void setspent(void);
void endspent(void);
struct spwd *getspent(void);
struct spwd *getspnam(const char *name);
int getspent_r(struct spwd *result_buf, char *buffer,
size_t buflen, struct spwd **result);
int getspnam_r(const char *name, struct spwd *result_buf,
char *buffer, size_t buflen, struct spwd **result);
函数 getspent_r 原型分析:
- 此函数成功返回 0,失败返回-1 并设置错误号。
- 输出参数 result_buf 返回 spwd 结构内容。
- 参数 buffer 是缓冲区。
- 参数 buflen 是缓冲区大小。
- 输出参数 result 返回结果。
函数 getspnam_r 原型分析:
- 此函数成功返回 0,失败返回-1 并设置错误号。
- 参数 name 是用户名。
- 参数 result_buf 返回 spwd 结构内容。
- 参数 buffer 缓冲区。
- 参数 buflen 是缓冲区大小。
- 输出参数 result 返回结果。
下面是 SylixOS 中 spwd 结构体的实现:
struct spwd {
char *sp_namp; /* user login name */
char *sp_pwdp; /* encrypted password */
long sp_lstchg; /* last password change */
int sp_min; /* days until change allowed. */
int sp_max; /* days before change required */
int sp_warn; /* days warning for expiration */
int sp_inact; /* days before account inactive */
int sp_expire; /* date when account expires */
int sp_flag; /* reserved for future use */
};
注意:
getspent_r 和 getspnam_r 函数是可重入的。
用户组操作
与访问口令文件的一组函数类似,有另一组函数用于访问用户组文件。
#include <grp.h>
struct group *getgrgid(gid_t gid);
struct group *getgrnam(const char *name);
struct group *getgrent(void);
void setgrent(void);
void endgrent(void);
int getgrnam_r(const char *name, struct group *grp,
char *buffer, size_t bufsize, struct group **result);
int getgrgid_r(gid_t gid, struct group *grp,
char *buffer, size_t bufsize, struct group **result);
函数 getgrnam_r 原型分析:
- 此函数成功返回 0,失败返回-1 并设置错误号。
- 参数 name 是组名。
- 输出参数 grp 返回结构体 group 内容。
- 参数 buffer 是缓冲区。
- 参数 bufsize 是缓冲区大小。
- 输出参数 result 返回结果。
函数 getgrgid_r 原型分析:
- 此函数成功返回 0,失败返回-1 并设置错误号。
- 参数 gid 是组 ID。
- 输出参数 grp 返回结构体 group 内容。
- 参数 buffer 是缓冲区。
- 参数 bufsize 是缓冲区大小。
- 输出参数 result 返回结果。
下面是 SylixOS 中 group 结构体的实现:
struct group {
char *gr_name; /* group name */
char *gr_passwd; /* group password */
gid_t gr_gid; /* group id */
char **gr_mem; /* group members */
};
注意:
getgrnam_r 和 getgrgid_r 函数是可重入的。
用户附加组操作
组成员不仅可以属于口令文件记录项中组 ID 所对应的组,也可以属于 NGROUPS_MAX(通常为 16)个另外的组。文件访问权限的检查不仅检查进程的有效组 ID,而且还要检查附加组 ID。使用附加组 ID 的优点是不必再显式地更改组,一个用户可能会参加多个项目,因此也有必要同时属于多个组。
为了获取和设置附加组 ID,SylixOS 提供以下三个函数:
#include <grp.h>
int setgroups(int groupsun, const gid_t grlist[]);
int getgroups(int groupsize, gid_t grlist[]);
int initgroups(const char *name, gid_t basegid);
函数 setgroups 原型分析:
- 此函数成功返回 0,失败返回-1 并设置错误号。
- 参数 groupsun 是组的数量。
- 参数 grlist[] 是存放用户组的数组指针。
函数 getgroups 原型分析:
- 此函数返回实际存储到 grlist 数组的 gid 个数。
- 参数 groupsize 是数组 grlist[] 大小。
- 输出参数 grlist[] 存储用户组。
函数 initgroups 原型分析:
- 此函数成功返回 0,失败返回-1 并设置错误号。
- 参数 name 是组成员名。
- 参数 basegid 是组 ID。
setgroups 函数将 groupsun 个附加组 ID 填写到数组 grlist 中,该数组中存放的元素最多为 NGROUPS_MAX 个;getgroups 函数获得当前进程用户 ID 所属的添加组 ID,当 groupsize 为 0 或者 grlist 为 NULL 时,函数返回附加组个数;initgroups 函数读取文件/etc/group 并将存在的用户 name 的组 ID 添加到进程的附加组中。