POSIX 用户操作

更新时间:
2024-05-13
下载文档

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 添加到进程的附加组中。

文档内容是否对您有所帮助?
有帮助
没帮助