系统正常运行须要使用大量系统数据文件,其中,全部UNIX系统都有的是:口令文件、组文件,大多数系统都提供的是:登陆帐户记录、系统标识、时间和日期例程,同时还有其余一些经常使用系统数据文件如:BSD网络软件有一个记录各网络服务器所提供服务的数据文件(/etc/services)、记录协议住处的数据文件(etc/protocols)等。html
一、口令文件node
口令文件包括了如下字段,这些字段包含在<pwd.h>中定义的passwd结构中:shell
struct passwd数组
{服务器
char* pw_name; //用户名网络
char* pw_passwd; //加密口令函数
uid_t pw_uid; //数值用户IDui
gid_t pw_gid; //数值组IDthis
char* pw_gecos; //注释字段加密
char* pw_dir; //初始工做目录
char* pw_shell; //初始shell(用户程序)
char* pw_class; //用户访问类
time_t pw_change; //下次更改口令时间
time_t pw_expire; //帐户有效期时间
};
(1)POSIX.1只定义了两个获取口令文件相的函数。在给出用户登陆名或者数值用户ID,这两个函数容许咱们经过查找相关项
#include <pwd.h>
struct passwd *getpwuid(uid_t uid); struct passwd *getpwnam(const char *name); //二者成功都返回指针,失败返回NULL
getpwuid函数被ls程序使用,它将i节点中的数值用户ID数值映射到一个用户登陆名,在键入登陆名时候,getpwnam函数被login(1)函数使用。
(2)如下三个函数能够用于程序查看整个口令文件
#include <pwd.h>
struct passwd *getpwent(void); //成功返回指针,失败或文件结尾返回NULL。 void setpwent(void); void endpwent(void);
调用getpwent时,它返回口令文件中下一个记录项,函数setpwent反绕它所使用的文件,endpwent则关闭这些文件,在使用getpwent查看完口令文件后,必定要调用endpwent关闭这些文件。
二、阴影口令
为了更难获取原始资料(加密口令),某些系统把加密密码存在另外一个一般被称为影子密码的文件中,该文件最少必须包含用户名和加密密码。其它密码相关的信息一样也存在该文件,看下表:
文件/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.组文件
1).能够用下面由POSIX.1定义的两个函数查看组名或组ID
#include <grp.h>
struct group *getgrgid(gid_t gid); struct group *getgrnam(const char *name); //二者成功都返回指针,不然返回NULL。
和口令文件函数同样,这两个函数一般都返回一个静态变量的指针,每次调用时都被重写该静态变量。
2).若是须要查找整个组文件,则须要使用另外几个函数,如下三个函数相似于针对口令文件的三个函数:
#include <grp.h>
struct group *getgrent(void); //成功返回指针,失败或文件尾返回NULL。 void setgrent(void); void endgrent(void);
4.附加组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.其余数据文件
对于每一个数据文件有至少三个函数
1).get函数,读取下一个记录,必要时打开这个文件。这些函数一般返回一个结构体的指针。当到达文件尾时一个空指针被返回。多数get函数返回一个静态结构体的指针,因此咱们若是想保存它则老是须要拷贝它。
2).set函数,若是文件没打开的话打开这个文件,并回退这个文件。这个函数在咱们知道咱们想从文件开头从新开始时被使用。
3).end项,关闭数据文件。正如咱们早先提到的,咱们老是须要在完成工做时调用它,来关闭全部的文件。
下面表里有全部数据文件的get、set和end函数:
访问系统数据文件的相似函数 | ||||
描述 | 数据文件 | 头文件 | 结构体 | 补充的关键字查找函数 |
密码 | /etc/passwd | <pwd.h> | passwd | getpwnam, getpwuid |
组 | /etc/group | <grp.h> | group | getgrnam, getgrgid |
影子 | /etc/shadow | <shadow.h> | spwd | getspanam |
主机 | /etc/hosts/ | <netdb.h> | hostent | gethostbyname, gethostbyaddr |
网络 | /etc/networks | <netdb.h> | netent | getnetbyname, getnetbyaddr |
协议 | /etc/protocols | <netdb.h> | protoent | getprotobyname, getprotobynumber |
服务 | /etc/services | <netdb.h> | servent | getservbyname, 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.系统标识
1).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 */ };
2).基于BSD的系统提供了gethostname函数来只返回主机的名字。这个名字一般是在TCP/IP网络上的主机名。
#include <unistd.h>
int gethostname(char *name, int namelen); //成功返回0,失败返回-1。
namelen参数指定了name缓冲的长度。如提供了足够的空间,返回的字符串以null结尾。若是没有提供足够的空间,没有指定这个字符串是否以null结尾。
8.时间和日期例程
1).time函数返回当前的时间和日期。
#include <time.h>
time_t time(time_t *calptr); //成功返回时间值,错误返回-1。
2).gettimeofday函数提供了比time函数更好的精度(精确到微秒)
#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 */ };
3).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 */ };
localtime和gmtime的区别在于第一个把日历时间转换为本地时间,根据时区和夏令时标志,然后者把日历时间转换成一个表示为UTC的分解时间
4).函数mktime接受一个表示为本地时间的分解时间,并把它转换成一个time_t值
#include <time.h>
time_t mktime(struct tm *tmptr); //成功返回日历时间,错误返回-1
5).asctime和ctime函数生产熟悉的26字节字符串
#include <time.h>
char *asctime(const struct tm *tmptr); char *ctime(const time_t *calptr); //二者都返回以null结尾的字符串。
6).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。
转自:http://www.cnblogs.com/biyeymyhjob/archive/2012/08/03/2621445.html