2016-02-01
系统数据文件和信息
引言
由于历史的原因许多数据文件都是ascii文本文件,并且使用标准io库读取这些文件。但是对于较大的系统,顺序扫描口令文件变得很花费时间,我们想以非ascii文本格式存放这些文件,但仍向应用程序提供一个可以处理任何一种文本格式的界面。
口令文件
口令文件中各个字段包含在<pwd.h>中定义的passwd中,由于历史原因,口令文件是/etc/passwd是一个文本文件
- 通常有一个登录项,其用户名为root其用户id为0
- 加密口令字段包含了经过单项加密算法处理过的用户口令副本
- 口令文件中某些字段可能为空, shell为空则表示取系统默认
- 支持finger命令的系统支持注释字段中的附加信息
POSIX定义了两个存取口令文件中信息的函数
struct passed *getpwuid(uid_t uid)
struct passwd *getpwnam(const char *name)
如果需要查看整个口令文件
struct passwd *getpwent(void)
void setpwent(void)
void endpwent(void)
调用getpwent它返回口令文件中的下一个记录。第一次调用时它打开它所使用的各个文件
setpwent反绕它所使用的文件定位到文件的开始处,endpwent关闭这些文件。
阴影口令
为了防止猜测用户口令中密码,有些系统将加密口令存放在另一个通常为阴影口令的文件中。该文件至少要包含用户名和加密口令。与该口令有关的其他信息也可存放在该文件中。具有阴影口令的系统经常要求用户在一定的时间间隔后选择一个新口令。这北京称之为口时效,该时间间隔也存放在阴影口令文件中。阴影口令文件不应是一般用户可以读取的。仅有少数几个程序需要存取加密口令文件如login和passed这些程序常常设置用户ID为root.有了阴影口令,普通口令文件可由各用户自由存取
组文件
组文件(/etc/group)中各个字段被定义在group结构中
可以使用以下两个函数来查看组名或者组ID
struct group *getgrgid(gid_t gid);
struct group *getgrnam(const char *name)
如同对口令文件进行操作的函数一样,这两个函数通常也返回指向一个静态变量的指针,每次调用都重写该静态变量。
如果需要搜索整个组文件,则需使用另外几个函数
struct group *getgrent(void)
void setgrent(void)
void endgrent(void)
添加组ID
1983年之前每个用户任何时候都只属于一个组,可以在认识时候执行newgrp更改组id.执行不带任何参数的newgrp返回原来的组
4.2BSD引入添加组的概念,每个用户可以属于至多16个另外的组。为了存取和设置添加组可以使用下列函数
int getgroups(int gidsetsize, gtid_t grouplist[])
int setgroups(int ngroups, const gid_t grouplist[])
int initgroups(const char *username, gid_t basegid)
getgroups将进程所属用户的各添加组id填写到grouplist中,填写入该数组的添加组id最多gridsetsize个。实际填写到数组中的添加组id数由函数返回。如果系统常熟NGROUPS_MAX为0,则返回0
通常只有inintgroups函数调用setgroups,initgroups读整个组文件,然后对username确定其组的成员关系。然后调用setgroups一遍为该用户初始化添加组id表。因为initgroups调用setgroups所以只有超级用户才能调用initgroups.
其他数据文件
类似用户口令和用户组文件,unix系统还有许多其他系统数据文件,幸运的是对于这些数据文件的界面都与口令文件和组文件类似。一般情况下每个数据文件至少有三个函数
- get函数读取下一个记录,如果需要则打开该文件。这种函数通常返回指向一个结构的指针。当已达到文件尾端是返回空指针。大多数get函数返回一个指向静态类存储结构的指针,如果要保存其内容,需复制它。
- set函数,如果希望在文件起始处处理,则调用此函数
- end函数, 处理完毕关闭文件
另外如果数据文件支持某种形式的关键字搜索,则也会提供相关函数,如getpwname寻找指定用户名的记录
/etc/hosts
/etc/networks
/etc/protocols
/etc/services
登录会计
大多数系统都提供以下两个数据文件utmp文件,它记录当前登录进系统的各个用户;wtmp它跟踪各个登录和注册事件
struct utmp {
char ut_line[8];
char ut_name[8];
long ut_time;
}
登录时login程序填写此结构写入utmp文件中,同时也添加到wtmp。注销时init进程将utmp文件中的相应记录擦除掉,并记录一个新纪录到wtmp中。
系统标识
POSIX定义了uname函数,它返回与主机和操作系统有关信息
int uname(struct utsname *name)
通过该函数的参数向其传递一个utsname的结构的地址,然后该函数填写此结构。
struct utname {
char sysname[9];
char nodename[9];
char release[9];
char version[9];
char machine[9];
}
伯克利类的版本提供gethistname函数,它只返回主机名,改名字通常就是TCP/IP网络上主机名字。
时间和日期例程
unix内核提供日历时间:自1970年1月1日00:00:00以来的秒数。
time_t time(time_t *calptr)
两个函数localtime和gtime将日历时间变换成以年月日时分秒周日表示的时间,并将这些存放在一个tm结构中
struct tm {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
}
struct tm *gmtime(const time_t *calptr);
struct tm *localtime(const time_t calptr)
locatime函数将日历时间变换成本地时间会考虑本区时区和夏时标志
函数mktime以本地时间的年月日等作为参数将其转换为time_t
time_t mktime(struct tmtmptr)
asctime 和 ctime函数产生像是的26字节字符串
char *asctime(const struct tm *tmptr)
char *ctime(const time_t *calptr)
最后一个时间函数是strftime它是非常复杂的printf类的时间值函数
size_t strftime(char *buf, size_t maxsize, const char *format, const struct tm *tmptr)
格式化结果放在一个长度为maxsize个字符的bug数组中,如果buf长度足以存放格式化结果及一个null终止符,该函数返回在buf中存放的字符数(不包含null终止符),否则返回0;
网友评论