系统数据文件和信息

来源:互联网 发布:亿网科技备案域名购买 编辑:程序博客网 时间:2024/05/05 13:44

1.口令文件

UNIX系统的口令文件(POSIX.1称用户数据库)包含下列字段,这些字段包含在<pwd.h>中定义的passwd结构中

        /etc/passwd文件中的字段:

        char *pw_name        //用户名
        char *pw_passwd        //加密口令
        uid_t pw_uid        //数值用户ID
        gid_t pw_gid        //数值组ID
        char *pw_gecos        //注释字段
        char *pw_dir        //初始工作目录
        char *pw_shell        //初始shell(用户程序)
        char *pw_class        //用户访问类
        time_t pw_change    //下次更改口令时间
        time_t pw_expire    //账户到期的时间

POSIX.1只定义了两个获取口令文件相的函数。在给出用户登录名或者数值用户ID,这两个函数允许我们通过查找相关项。

#include <pwd.h>struct passwd *getpwuid(uid_t uid);struct passwd *getpwnam(const char *name);//两者成功都返回指针,失败返回NULL

若要查看整个口令文件,可用下列三个函数(POSIX.1未定义,其被定义为XSI扩展)

#include <pwd.h>struct passwd *getpwent(void);//成功返回指针,失败或文件结尾返回NULL。void setpwent(void);void endpwent(void);
调用getpwent时,它返回口令文件中下一个记录项,函数setpwent反绕它所使用的文件,endpwent则关闭这些文件,在使用getpwent查看完口令文件后,一定要调用endpwent关闭这些文件

2.阴影口令

为了更难获取原始资料(加密口令),某些系统把加密密码存在另一个通常被称为阴影口令的文件中,

该文件最少必须包含用户名和加密密码。其它密码相关的信息同样也存在该文件,看下表:

文件/etc/shadow的域描述结构体spwd成员用户登录名char *sp_namp加密密码char *sp_pwdp最后修改密码的自Epoch的天数int sp_lstchg直到改变允许的天数int sp_min需要改变之前的天数int sp_max警告密码到期的天数int sp_warn帐号失效前的天数int sp_inact帐号过期的自Epoch距今的天数int sp_expire保留unsigned int sp_flag

与访问口令文件的一组函数类似,另有一组函数用于访问阴影口令文件

#include <shadow.h>struct spwd *getspnam(const char *name);struct spwd *getspent(void);//两者成功时都返回指针,否则返回NULL。void setspent(void);void endspent(void);

3.组文件

UNIX组文件(POSIX称组数据库)包含如下字段,这些字段包含在<grp.h>中所定义的group 结构中

          /etc/group 文件中的字段:
   
        char *gr_name    //组名
        char *gr_passwd    //加密口令
        int gr_gid    //数值组ID
        char **gr_mem    //指向各用户名的指针的数组


可以用下面由POSIX.1定义的两个函数查看组名或组ID

#include <grp.h>struct group *getgrgid(gid_t gid);struct group *getgrnam(const char *name);//两者成功都返回指针,否则返回NULL

和口令文件函数一样,这两个函数通常都返回一个静态变量的指针,每次调用时都被重写该静态变量。

如果需要查找整个组文件,则需要使用另外几个函数,以下三个函数类似于针对口令文件的三个函数(这三个函数不在POSIX.1中,是XSI的扩展定义):

#include <grp.h>struct group *getgrent(void);//成功返回指针,失败或文件尾返回NULL。void setgrent(void);void endgrent(void);
 setgrent函数打开组文件并反绕它,getgrent函数从组文件中读下一个记录,endgrent函数关闭组文件。

4.附加组ID

使用附加组ID的好处是我们不再需要显式地改变组,为了获取和设置附加组ID,提供下列三个函数

#include <unistd.h>int getgroups(int gidsetsize, gid_t grouplist[]);//成功返回补充组ID的数量,错误返回-1。#inlcude <grp.h> /* on Linux */#inlcude <unistd.h> /* on FreeBSD, Mac OS X, and Solaris */int setgroups(int ngroups, const gid_t grouplist[]);#inlcude <grp.h> /* on Linux and Solaris */#inlcude <unistd.h> /* on FreeBSD and Mac OS X */int initgroups(const char *username, gid_t basegid);//两者成功都返回0,否则返回-1。

5.其他数据文件

对于每个数据文件有至少三个函数

a.get函数,读取下一个记录,必要时打开这个文件。这些函数通常返回一个结构体的指针。当到达文件尾时一个空指针被返回。多数get函数返回一个静态结构体的指针,所以我们如果想保存它则总是需要拷贝它。

b.set函数,如果文件没打开的话打开这个文件,并回退这个文件。这个函数在我们知道我们想从文件开头重新开始时被使用。

c.end项,关闭数据文件。正如我们早先提到的,我们总是需要在完成工作时调用它,来关闭所有的文件。

下面表里有所有数据文件的get、set和end函数:

访问系统数据文件的类似函数描述数据文件头文件结构体补充的关键字查找函数密码/etc/passwd<pwd.h>passwdgetpwnam, getpwuid组/etc/group<grp.h>groupgetgrnam, getgrgid影子/etc/shadow<shadow.h>spwdgetspanam主机/etc/hosts/<netdb.h>hostentgethostbyname, gethostbyaddr网络/etc/networks<netdb.h>netentgetnetbyname, getnetbyaddr协议/etc/protocols<netdb.h>protoentgetprotobyname, getprotobynumber服务/etc/services<netdb.h>serventgetservbyname, getservbyport


6.登陆账户记录

大多数UNIX系统提供的两个数据文件是:utmp文件,它记录当前登录系统的各个用户;wtmp文件,它记录所有的登陆与注销事件。在V7,一个记录类型被这两个文件写,一个与下面结构体一致的二进制记录

struct utmp {  char ut_line[8]; /* tty line: "tyh0", "ttyd0", "ttyp0", ... */  char ut_name[8]; /* login name */  long ut_time; /* seconds since Epoch */}; 

7.系统标识

POSIX.1定义了uname函数,它返回当前主机和操作系统的有关信息 

#include <sys/utsname.h>int uname(struct utsname *name);//成功返回非负值,失败返回-1。

utsname结构中的一些字段

struct utsname {  char sysname[];  /* name of the operating system */  char nodename[]; /* name of hits node */  char release[]; /* current release of operating system */  char version[]; /* current version of this release */  char machine[]; /* name of hardware type */};

基于BSD的系统提供了gethostname函数来只返回主机的名字。这个名字通常是在TCP/IP网络上的主机名。

#include <unistd.h>int gethostname(char *name, int namelen);//成功返回0,失败返回-1。

namelen参数指定了name缓冲的长度。如提供了足够的空间,返回的字符串以null结尾。如果没有提供足够的空间,没有指定这个字符串是否以null结尾。

8.时间和日期进程

UNIX关于时间的特点:

a.已国际标准时间(1970年1月1日00:00:00以来经过的秒数)而非本地时间计时

b.可自动进行转换,例如变换到夏时制

c.将时间和日期作为一个量值保存。

time函数返回当前的时间和日期。

#include <time.h>time_t time(time_t *calptr);//成功返回时间值,错误返回-1。


gettimeofday函数提供了比time函数更好的精度(精确到微秒):(该函数为XSI扩展定义)

#include <sys/time.h>int gettimeofday(struct timeval *restrict tp, void *restrict tzp);//返回值:总是返回0。

timeval结构体
struct timeval {  time_t tv_sec;  /* seconds */  long tv_usec; /* microseconds */};

localtime和gmtime

#include <time.h>struct tm *gmtime(const time_t *calptr);struct tm *localtime(const time_t *calptr);//两者都返回分解时间的指针

localtime和gmtime这两个函数把日历时间转换了一个被称为分解时间(broken-down time)的一个结构体tm:

struct tm {  /* a broken-down time */  int tm_sec;  /* seconds after the minute: [0 - 60] */  int tm_min;  /*  minutes after the hour: [0-59] */  int tm_hour;  /* hours after midnight:[0-23] */  int tm_mday;  /* day of the month: [1-31] */  int tm_mon;  /* months since January: [0-11] */  int tm_year;  /* years since 1900 */  int tm_wday;  /* days since sunday: [0-6] */  int tm_yday;  /* days since January 1: [0-365] */  int tm_isdst;  /* daylight saving time flag: <0, 0, >0 */};
其中秒可以超过59秒的理由是可以表示润秒。注意月字段值为0-11。
localtime和gmtime的区别在于第一个把日历时间转换为本地时间,根据时区和夏令时标志,而后者把日历时间转换成一个表示为UTC的分解时间

函数mktime接受一个表示为本地时间的分解时间,并把它转换成一个time_t值

#include <time.h>time_t mktime(struct tm *tmptr);//成功返回日历时间,错误返回-1

asctime和ctime函数生产熟悉的26字节字符串,与data命令默认输出类似

#include <time.h>char *asctime(const struct tm *tmptr);char *ctime(const time_t *calptr);//两者都返回以null结尾的字符串。

strftime,是最复杂的。它是一个对于时间值类似于printf的函数

#include <time.h>size_t strftime(char *restrict buf, size_t maxsize, const char *restrict format, const struct tm *restrict tmptr);//如果空间足够返回存储在数组里的字符数,否则返回0。

最后的参数是格式所需的时间值,由一个分解时间值的指针指定。格式化的结构存储在尺寸为maxsize的buf数组里。如果包括终止null的结果的尺寸,可以放入这个缓冲,那么函数返回在buf里存储的字符数,不包括终止null。否则,该函数返回0


原创粉丝点击