Apue.2e chapter6

本章学习系统数据文件的接口,以及系统标识函数、时间和日期等信息函数。

口令文件:/etc/passwd

#include <pwd.h>

struct passwd{

    char *pw_name;    //用户名    *

    char *pw_passwd;    //加密口令

    uid_t pw_uid;        //user id    *

    gid_t pw_gid;        //group id    *

    char *pw_gecos;    //注释

    char *pw_dir;        //初始目录    *

    char *pw_shell;        //shell menu    *

    char *pw_class;        //用户访问类

    time_t pw_change;    //下次更改口令时间

    time_t pw_expire;    //账户到期时间

};

*指的是POSIX.1规定的必须项;

使用finger命令可解析指定用户的相关信息。

相关函数(POSIX):

#include <pwd.h>

struct passwd *getpwuid(uid_t uid);

struct passwd *getpwnam(const char *name);

通过name或uid获得passwd结构的内容。返回的指针其实指向一个静态变量,所以每次调用都会覆盖上次的结果,注意保存副本,下同。

SUS扩展:

struct passwd *getpwent(void);    //返回口令文件下一记录项

void setpwent();        //打开口令文件;若已经打开,则偏移量调回开始处。rewind,书中翻译为反绕

void endpwent();//关闭口令文件

用户密码段在/etc/passwd中仅有一个占位符,真正的密码存放在/etc/shadow中,前者任何人均可读取,后者却需要管理员权限。

struct spwd{

    char *sp_namp;    //登录名        *

    char *sp_pwdp;        //加密口令        *

    int sp_lstchg;        //上次更改口令以来经过的时间

    int sp_min;        //经过多少天后允许更改

    int sp_max;        //要求更改尚余天数

    int sp_warn;        //到期警告天数

    int sp_inact;        //账户不活动之前尚余天数

    int sp_expire;        //账户到期天数

    unsigned int sp_flag;    //保留

};

sp是shadow password的缩写,其中只有*的两项是必须的,其余都是附加字段。相关函数

#include <shadow.h>

struct spwd *getspnam(const char *name);

struct spwd *getspent();

void setspent();

void endspent();

木有通过UID获取的函数;以上函数在Linux和Solaris上可用;但是freeBSD和MacOS上口令就不是用这种存放方式了。

组文件:/etc/group

#include <grp.h>

struct group{

    char *gr_name;        //组名        *

    char *gr_passwd;    //加密口令    

    int gr_gid;        //组ID        *

    char **gr_mem;    //字符串数组,指向各用户名    *

};

除口令外皆POSIX.1定义的必须项。

相关函数:

struct group *getgrgid(gid_t gid);

struct group *getgrnam(const char *name);

//SUS:

struct group *getgrent();

void setgrent();

void endgrent();

附加组ID

常量NGROUPS_MAX规定了附加组的数量限制。相关函数:

#include <unistd.h>

ing getgroups(int gidsetsize, gid_t grouplist[]);    //填充附加组ID,POSIX.1. 若gidsetsize=0,返回附加组ID数;

//然后再调用一次,gidsetsize可作为限制。

#include <grp.h>    //on linux, SUS,以下都是su权限操作

#include <unistd.h>    //others

int setgroups(int ngroups, const gid_t grouplist[]);    //给调用进程设置附加组ID表

int initgroups(const char *username, gid_t basegid);    //初始化附加组ID表,一般很少调用。

其他信息

其他信息,包括服务(/etc/services),网络(/etc/networks)和协议(/etc/protocols)等等,相关函数有形式上的相似性,包括:

get函数:读下一个记录,返回一个指向静态结构的指针(大多数情况)

set函数:打开文件,或rewind已经打开的文件

end函数:关闭文件

还有若干关键字搜索的函数:getxxbyname和getxxbyaddr等等。具体的可以查阅相关头文件。如netdb.h

登录账户记录

utmp文件:记录当前登录进系统各个用户;shell: who

wtmp:记录各个登录和注销事件;shell: last

在Linux中,可以用man 5 utmp获得相关信息

系统标识

#include <sys/utsname.h>

int uname(struct ustname *name);

struct utsname{

    char sysname[];        //系统名称

    char nodename[];    //当前结点名称

    char release[];        //发行版编号

    char version[];        //当前发行版版本号

    char machine[];        //机器名称

};

如果在TCP/IP网络中,可以使用gethostname(char *name,int namelen)获取主机名称(完全限定名),shell: hostname。

时间和日期相关

time函数返回当前时间(日历时间)。但是SUS木有规定如何设置当前时间…╮(╯Д╰)╭

#include <sys/time.h>

struct timval{

    time_t tv_sec;        //seconds

    long tv_usec;        //microseconds

};

int gettimeofday(struct timeval *restrict tp, void *restrict tzp);    //SUS

总是返回0;

tzp只能是NULL(囧),否则不可移植。本函数提供比time函数更高精度的填充值。

time_t可以经过多个函数转化为可读性更好的时间值,包括:

#include <time.h>

struct tm *gmtime(const time_t *calptr);    //转为国际标准时间UTC

struct tm *localtime(const time_t *calptr);    //转为本地时间CST

struct tm{

    int tm_sec;    //0~60,考虑到闰秒

    int tm_min;

    int tm_hour;

    int tm_mday;

    int tm_mon;

    int tm_year;    //years since 1900

    int tm_wday;    //周几,从周日开始

    int tm_yday;    //从1月1号开始过了几天

    int tm_isdst;    //夏时制

};

mktime进行struct tm*到time_t的反相转换;

asctime和ctime分别将struct tm *和time_t *转为字符串形式,形式上同shell: date的输出;

strftime具有非常复杂的格式化输出…类似printf:

#include <time.h>

size_t strftime(char *restrict buf, size_t maxsize,

        const char *restrict format,

        const struct tm *restrict tmptr);

format指定格式,格式化结果存放在长度为maxsize的buf中。返回存放字符数(不含\0),如果buf长度不足,返回0;

以上函数中,除了asctime和gmtime外都受到时区设置(环境变量TZ)的影响;

这一部分除了SUS外,都是ISO C规定的函数(time.h)

习题里面最后一题,貌似没有办法直接生成汉字的输出,给的答案也不行,估计要自行格式化了…

posted @ 2013-01-19 22:02  生无所息  阅读(179)  评论(0编辑  收藏  举报