第六章 系统数据文件和信息
1、口令文件
UNIX系统口令文件包含如下字段,这些字段包含在<pwd.h>中定义的passwd结构中
口令文件是/etc/passwd,每一行包含上面各字段,字段之间用冒号分隔。可以使用finger命令打印指定用户的有关信息:finger -p 用户名
POSIX.1定义了两个获取口令文件项的函数,在给定用户登录名或数值用户ID后,这两个函数就能查看相关项
#include <pwd.h>
struct passwd *getpwuid(uid_t uid); //由ls程序使用
struct passwd *getpwnam(const char*name); //由login程序使用。
//两个函数返回值:若成功,返回指针;若出错,返回NULL。
下面三个函数可以实现查看整个口令文件
#include <pwd.h>
struct passwd *getpwent(void);
//返回值:若成功,返回指针;若出错或到达文件尾端,返回NULL。
void setpwent(void);
void endpwent(void);
调用getpwent时,它返回口令文件中的下一个记录项。函数setpwent反绕它所使用的文件(定位到文件开始处),endpwent则关闭这些文件,下面给出使用这3个函数实现getpwnam函数的程序
#include <pwd.h>
#include <stddef.h>
#include <string.h>
struct passwd *
getpwnam(const char *name)
{
struct passwd *ptr;
setpwent();
while ((ptr = getpwent()) != NULL)
if (strcmp(name, ptr->pw_name) == 0)
break; /* found a match */
endpwent();
return(ptr); /* ptr is NULL ifno match found */
}
2、阴影文件
现在,某些系统将加密口令存放在另一个通常称为阴影口令的文件中:/etc/shadow
与访问口令文件的一组函数相类似,有另一组函数可用于访问阴影口令文件
#include <shadow.h>
struct spwd *getspnam(cosnt char *name);
struct spwd *getspent(void);
void setspent(void);
void endspent(void);
3、组文件
UNIX组文件包含下图所示字段(/etc/group文件中的字段),这些字段包含在<grp.h>中所定义的group结构中。
字段gr_mem是一个指针数组,其中每一个指针指向一个属于该组的用户名。该数组以null指针结尾。
可以使用下列两个函数来查看组相关项
#include <grp.h>
struct group *getgrgid(gid_t gid);
struct group *getgrnam(const char *name);
//返回值:若成功,返回指针;若出错,返回NULL。
类似于口令文件,如果需要搜索整个组文件,可以使用下面3个函数
#include <grp.h>
struct group *getgrent(void);
//返回值:若成功,返回指针;若出错或到达文件尾端,返回NULL。
void setgrent(void);
void endgrent(void);
4、附属组ID
当用户登录时,系统就按口令文件记录项中的数值组ID,赋给它实际组ID。在任何时刻执行newgrp更改组ID
一个用户可能参与多个项目,因此也就要同时属于多个组,使用附属组ID的优点是不必再显式地经常更改组。
为了获取和设置附属组ID,提供了下列3个函数
#include <unistd.h>
int getgroups(int gidsetsize,gid_tgrouplist[]);
//返回值:若成功,返回附属组ID数量;若出错,返回-1.
#include<grp.h> /* on linux */
#include<unistd.h> /* on FreeBSD,Mac OS X,and Solaris
int setgroups(int ngroups,const gid_tgrouplist[]);
int initgroups(const char *username,gid_tbasegid);
//两个函数返回值:若成功,返回0;若出错,返回-1.
getgroups将进程所属用户的各附属组ID填写到数组grouplist中,最多为gidsetsize个;setgroups可由超级用户调用以便为调用进程设置附属组ID表。通常,只有initgroups函数调用setgroups,用来设置用户的附属组ID。
5、其他数据文件
下图给出访问系统数据文件的一些例程
对于这些数据文件的接口都都与上述对口令文件和组文件的相似,一般情况下,对于每个数据文件至少提供一下3个函数
get函数:读下一个记录
set函数:打开相应数据文件,然后反绕该文件
end函数:关闭相应数据文件
6、系统标识
POSIX.1定义了uname函数,它返回与主机和操作系统有关的信息
#include <sys/utsname.h>
int uname(struct utsname *name);
//POSIX.1定义了该结构中最少需提供的字段
struct utsname {
char sysname[]; /* Operating system name (e.g.,"Linux") */
char nodename[]; /* Name within "someimplementation-defined network" */
char release[]; /* Operating system release (e.g.,"2.6.28") */
char version[]; /* Operating system version */
char machine[]; /* Hardware identifier */
}
历史上,BSD派生的系统提供gethostname函数,它只返回主机名,改名字通常就是TCP/IP网络上主机的名字。
#include<unistd.h>
Int gethostname(char *name, int namelen);
//返回值,若成功,返回0;若出错,返回-1.
7、时间和日期例程
time函数返回当前时间和日期。它是自公元1970年1月1日00:00:00以来经过的秒数(日历时间)
#include <time.h>
time_t time(time_t *calptr);
//返回值:若成功,返回非负值;若出错,返回-1.
如果参数非空,则时间值也存放在由calptr指向的单元内。
下面两个函数将日历时间转换成分解的时间,并将这些存放在一个tm结构中
#include <time.h>
struct tm *gmtime(const time_t *calptr);
struct tm *localtime(const time_t *calptr);
struct tm {
inttm_sec; /* seconds [0-60] */
int tm_min; /* minutes [0-59] */
inttm_hour; /* hours [0-23] */
inttm_mday; /* day of the month[1-31] */
inttm_mon; /* month [0-11] */
inttm_year; /* year since 1900*/
int tm_wday; /* day of the week [0-6]*/
inttm_yday; /* day in the year[0-365]*/
inttm_isdst; /* daylight saving time*/
};
mktime函数将tm结构转换成time_t值
#include <time.h>
time_t mktime(struct tm *tmptr);
strftime用于格式化时间值
#include <time.h>
size_t strftime(char *restrict buf,size_t maxsize,const char*restrict format,const struct tm *restrict tmptr);
size_t strftime_l(char *restrict buf,size_t maxsize,const char*restrict format,const struct tm *restrict tmptr,locale_t locale);
下面列出format参数的格式
strptime是strftime的反过来的版本,将字符串时间转换成分解时间
#include <time.h>
char *strptime(const char *restrict buf,const char *restrictformat,struct tm *restrict tmptr);
参考:http://www.cnblogs.com/runnyu/p/4636295.html