[单刷APUE系列]第六章——系统数据文件和信息

目录

[单刷APUE系列]第一章——Unix基础知识[1]
[单刷APUE系列]第一章——Unix基础知识[2]
[单刷APUE系列]第二章——Unix标准及实现
[单刷APUE系列]第三章——文件I/O
[单刷APUE系列]第四章——文件和目录[1]
[单刷APUE系列]第四章——文件和目录[2]
[单刷APUE系列]第五章——标准I/O库
[单刷APUE系列]第六章——系统数据文件和信息
[单刷APUE系列]第七章——进程环境
[单刷APUE系列]第八章——进程控制[1]
[单刷APUE系列]第八章——进程控制[2]
[单刷APUE系列]第九章——进程关系
[单刷APUE系列]第十章——信号[1]node

口令文件

使用过Unix系统的朋友应该知道/etc/passwd文件,这就是Unix系统口令文件,在POSIX1.x规范中规定Unix系统必须存在用户数据库,这些用户数据库里每一个用户都须要包含一些字段,具体须要查看<pwd.h>头文件。shell

struct passwd {
        char    *pw_name;               /* user name */
        char    *pw_passwd;             /* encrypted password */
        uid_t   pw_uid;                 /* user uid */
        gid_t   pw_gid;                 /* user gid */
        __darwin_time_t pw_change;              /* password change time */
        char    *pw_class;              /* user access class */
        char    *pw_gecos;              /* Honeywell login info */
        char    *pw_dir;                /* home directory */
        char    *pw_shell;              /* default shell */
        __darwin_time_t pw_expire;              /* account expiration */
};

在不少Unix系统中,passwd是一个ASCII文件,每一行是一个用户,而后每一个用户都包含这些字段,字段之间使用冒号分隔,可是在苹果系统中,则是使用opendirectory守护进程来存储用户数据库等数据。
系统提供了两个获取口令文件项的函数数据库

struct passwd *getpwuid(uid_t uid);
struct passwd *getpwnam(const char *login);

这两个函数都会返回passwd结构体,并且须要注意的是,这个结构体指针其实是指向一块静态区域的指针,也就是说,不一样经过保留指针来让后面使用。segmentfault

struct passwd *getpwent(void);

void setpwent(void);
void endpwent(void);

getpwent函数则是一项一项读取,而后将其以passwd结构体返回,很是适合须要读取所有内容的状况。setpwent和endpwent清理读取的缓存,其中endpwent则是关闭全部的文件,当使用getpwent后必定要使用endpwent关闭文件。数组

阴影口令

在最初的Unix系统实现中,密码是存放在/etc/passwd文件的第二个字段中,可是因为有不少程序读取这个文件,因此这个字段被专门移出来放在/etc/shadow中,一般状况下,只有root权限才能读取。在Solaris和Linux中,有一组函数用于访问阴影口令文件,可是,很是遗憾的是,苹果系统中没有,因此这里也就只能讲一讲,而不能列出实际的代码。缓存

组文件

struct group {
        char    *gr_name;               /* [XBD] group name */
        char    *gr_passwd;             /* [???] group password */
        gid_t   gr_gid;                 /* [XBD] group id */
        char    **gr_mem;               /* [XBD] group members */
};

上面是苹果系统定义的group结构体运维

struct group *getgrgid(gid_t gid);
struct group *getgrnam(const char *name);

struct group *getgrent(void);
void setgrent(void);
void endgrent(void);

就如同口令文件的函数同样,上面的函数用法也是同样的。函数

附属组ID

在早期Unix系统实现中,是不存在附属组的。直到后来BSD的一个版本引入了附属组ID的概念,这样在权限检查的时候也须要检查附属组ID的权限ui

int getgroups(int gidsetsize, gid_t grouplist[]);

int setgroups(int ngroups, const gid_t *gidset);

int initgroups(const char *name, int basegid);

getgroups函数将进程所属用户的附属组ID放入grouplist参数中,groupsize参数用于肯定放入的大小,可是实际上,咱们能够将groupsize设置为0,而后函数会返回实际的附属组个数,而后就能够很方便的分配grouplist数组,用不着去猜想究竟应该分配多少。
setgroups是一个root权限操做,用于为进程设置附属组ID。
initgroups是一系列操做的集合,实际上用到的机会极少,若是有须要的朋友能够自行观看系统手册。this

其余数据文件

除了上面讲到的两个文件之外,系统还有不少其余的文件,可是基本上都是提供了一样的接口(get,set,end),并且和前面的用法基本同样,因此这里也再也不讲解。

登陆帐户记录

在实际的运维中,常常会须要查看用户的登陆日志,因此系统也有相关的数据文件和接口函数用于开发使用。
原著中讲解了utemp结构体的内容,这里再也不多讲,可是在苹果系统中,实际上已经被utempx等结构体所取代

struct utmpx {
        char ut_user[_UTX_USERSIZE];    /* login name */
        char ut_id[_UTX_IDSIZE];        /* id */
        char ut_line[_UTX_LINESIZE];    /* tty name */
        pid_t ut_pid;                   /* process id creating the entry */
        short ut_type;                  /* type of this entry */
        struct timeval ut_tv;           /* time entry was created */
        char ut_host[_UTX_HOSTSIZE];    /* host name */
        __uint32_t ut_pad[16];          /* reserved for future use */
};

struct lastlogx {
        struct timeval ll_tv;           /* time entry was created */
        char ll_line[_UTX_LINESIZE];    /* tty name */
        char ll_host[_UTX_HOSTSIZE];    /* host name */
};

其实,不光是苹果系统,其余的Unix系统的字段也已经被修改扩充了,并且其实这个并不重要,因此只须要了解便可。

系统标识

POSIX定义了uname函数,用于返回主机和操做系统相关的信息,uname命令就是使用了这个函数。

int uname(struct utsname *name);

struct  utsname {
        char    sysname[_SYS_NAMELEN];  /* [XSI] Name of OS */
        char    nodename[_SYS_NAMELEN]; /* [XSI] Name of this network node */
        char    release[_SYS_NAMELEN];  /* [XSI] Release level */
        char    version[_SYS_NAMELEN];  /* [XSI] Version level */
        char    machine[_SYS_NAMELEN];  /* [XSI] Hardware type */
};

全部的成员都是以null字节结尾,而且BSD派生系统也提供了gethostname函数

int gethostname(char *name, size_t namelen);

实际上还有一个sethostname函数,可是这里也很少讲,除此之外,上面的一些函数实际上有一些已经被移到标准C库中了,因此也能做为跨平台开发使用。

日期和时间

Unix系统都使用的是Unix时间戳,也就是UTC时间1970年1月1日0时0分0秒以来的秒数,在前面咱们提到过它,这个就是日历时间,而且是使用time_t类型存储的。

time_t time(time_t *tloc);

time函数就是很简单的获取日历时间,在通常的状况下,都是传入null而后得到函数返回值来使用。原著中也讲到了指定时间的获取,可是很是不幸,苹果系统又没有这些方法,因此这里也只能不说起了。

相关文章
相关标签/搜索