标签:
/etc/passwd
UNIX口令文件 /etc/passwd/
是一个ASCII
文件,每一行包含很多字段,字段之间用冒号分隔。这些字段包含在<pwd.h>
头文件定义的passwd
,该结构有如下成员:
char *pw_name
:用户名char *pw_passwd
:加密口令uid_t pw_uid
:数值用户IDgid_t pw_gid
:数值组IDchar *pw_gecos
:注释字段char *pw_dir
:初始工作目录char *pw_shell
:初始shell
char *pw_class
:用户访问类time_t pw_change
:下次更改口令时间time_t pw_expire
:账户有效期时间关于口令文件:
root
的登录项,其用户ID是 0/etc/shadow
中shell
字段指定了初始shell
/bin/sh
)linux下为/bin/bash
/dev/null
,则会阻止任何人以该字段所在行记录中的用户名来登录系统nobody
,则任何人都可以使用它登录系统,但是其用户ID和组ID不提供任何特权。该用户ID和组ID只能访问人人皆可读、可写的文件Linux
中,没有 pw_class,pw_change,pw_expire
字段1.可以将其shell设为/bin/false
或/bin/true
2.可以在/etc/shadow
下将密码字段前加!!
或*
getpwuid/getpwnam
函数:读取口令文件:
#include<pwd.h>
struct passwd* getpwuid(uid_t uid);
struct passwd* getpwnam(const char*name);
uid
:用户IDname
:用户名passwd
结构的指针NULL
注意:getpwuid/getpwnam
函数返回的 struct passwd
结构通常是函数内部的静态变量,因此多次调用上面的函数,该静态变量会被覆写。
查看整个口令文件,使用下面的函数:
#include<pwd.h>
struct passwd *getpwent(void);
void setpwent(void);
void endpwent(void);
getpwent
返回值: passwd
结构的指针NULL
NULL
用法:
getpwent
时,它返回口令文件中的下一个记录项 返回的
struct passwd
结构通常是函数内部的静态变量,因此多次调用getpwent
函数,该静态变量会被覆写
getpwent
函数时,它会打开所使用的各个文件getpwent
对返回的各个记录项顺序并没有要求setpwent
会反绕getpwent
所使用的文件到文件起始处。即当调用setpwent
之后,getpwent
又会从头开始读取记录项endpwent
会关闭getpwent
所使用的文件。在调用getpwent
读取完口令文件后,一定要调用endpwent
关闭这些文件 getpwent
知道什么时候应该打开它所使用的文件(第一次被调用时),但是不知道何时应该关闭这些文件加密口令是经单向加密算法处理过的用户口令副本。
因为此算法是单向的,所以不能从加密口令猜测到原始口令
现在的UNIX将加密口令存放在一个称作阴影口令的文件中(即文件/etc/shadow
)。该文件至少应该包含用户名和加密口令。这些字段包含在<shadow.h>
头文件的struct spwd
结构中。相关的字段如下:
char *sp_namp
:用户登录名char *sp_pwdp
:加密口令int sp_lstchg
:上次更改口令以来经过的时间int sp_min
:经过多少天后允许修改口令int sp_max
:经过多少天后必须修改口令int sp_warn
:经过多少天后如果未修改口令则系统发出警告int sp_inact
:经过多少天后,该账户是inactive
int sp_expire
:经过多少天后,该账户过期unsigned int sp_flag
:保留字段其中只有用户登录名和加密口令这两个字段是必须的。其他字段都是用于控制口令更改的频率。
注意:
/etc/shadow
不应该由一般用户读取。 login,passwd
。这些程序通常是设置用户ID为root
的程序/etc/passwd/
可以任由各用户读取用于读取阴影口令文件的函数为:
#include<shadow.h>
struct spwd *getspnam(const char*name);
struct spwd *getspent(void);
void setspent(void);
void endspent(void);
getspnam
参数: name
:用户名getspnam
返回值: spwd
结构指针NULL
getspent
返回值: spwd
结构指针NULL
NULL
用法:
getspnam
时,它返回阴影口令文件中,对应用户名的那一条记录项 返回的
struct spwd
结构通常是函数内部的静态变量,因此多次调用getspnam
函数,该静态变量会被覆写
getspent
时,它返回阴影口令文件中的下一个记录项 struct spwd
结构通常是函数内部的静态变量,因此多次调用getspent
函数,该静态变量会被覆写getspent
函数时,它会打开所使用的各个文件getspent
对返回的各个记录项顺序并没有要求setspent
会反绕getspent
所使用的文件到文件起始处。即当调用setspent
之后,getspent
又会从头开始读取记录项endspent
会关闭getspent
所使用的文件。在调用getspent
读取完阴影口令文件后,一定要调用endspent
关闭这些文件 getspent
知道什么时候应该打开它所使用的文件(第一次被调用时),但是不知道何时应该关闭这些文件UNIX 组文件包含的字段定义在<grp.h>
所定义的group
结构中:
char *gr_name
:组名char *gr_passwd
:加密口令int gr_gid
:组IDchar **gr_mem
:指向各用户名指针的数组 它是一个指针数组,其中每个指针指向一个属于该组的用户名。该数组以
null
指针结尾
getgrgid/getgrnam
函数:查看组文件:
#include<grp.h>
struct group* getgrgid(gid_t gid);
struct group* getgrnam(const char* name);
gid
:组IDname
:组名group
结构的指针NULL
注意:getgrgid/getgrnam
函数返回的 struct group
结构通常是函数内部的静态变量,因此多次调用上面的函数,该静态变量会被覆写。
查看整个组文件,使用下面的函数:
#include<grp.h>
struct group *getgrent(void);
void setgrent(void);
void endgrent(void);
getgrent
返回值: group
结构的指针NULL
NULL
用法:
getgrent
时,它返回组文件中的下一个记录项 返回的
struct group
结构通常是函数内部的静态变量,因此多次调用getgrent
函数,该静态变量会被覆写
getgrent
函数时,它会打开所使用的各个文件getgrent
对返回的各个记录项顺序并没有要求setgrent
会反绕getgrent
所使用的文件到文件起始处。即当调用setgrent
之后,getgrent
又会从头开始读取记录项endgrent
会关闭getgrent
所使用的文件。在调用getgrent
读取完组文件后,一定要调用endgrent
关闭这些文件 getgrent
知道什么时候应该打开它所使用的文件(第一次被调用时),但是不知道何时应该关闭这些文件UNIX中还提供了附属组ID。其中获取和设置附属组ID的函数为:
#include<unistd.h>
int getgroups(int gidsetsize,gid_t grouplist[]);
#include<grp.h> //对Linux
#include<unistd.h> //对 FreeBSD, Mac OS X, Solaris
int setgroups(int ngroups,const gid_t grouplist[]);
#include<grp.h> //对Linux
#include<unistd.h> //对 FreeBSD, Mac OS X, Solaris
int initgroups(const char *username, gid_t basegid);
参数:
getgroups
函数: gidsetsize
:填入grouplist
数组的附属组ID的最大数量 若该值为0,则函数只返回附属组ID数,而不修改
grouplist
数组
grouplist
:存放附属组ID的数组setgroups
函数: ngroups
:grouplist
数组中元素个数 NGROUPS_MAX
grouplist
:待设置的附属组ID的数组initgroups
函数: username
:用户名basegid
:用户的base
组ID(它就是在口令文件中,用户名对于的组ID)返回值:
getgroups
函数: setgroups/initgroups
函数: 用法:
getgroups
函数将进程所属用户的各附属组ID填写到grouplist
中,填入该数组的附属组ID数最多为gidsetsize
个。实际填写到数组中的附属组ID数由函数返回setgroups
函数可由超级用户调用以便为调用进程设置附属组ID表。initgroups
函数会在内部调用setgroups
函数,因此它也必须由超级用户调用除了口令文件和组文件之外,系统中还有很多其他重要的数据文件。UNIX对于这些系统数据文件提供了对应的类似的API。对于每种数据文件,至少有三个函数:
get
函数:读下一个记录。如果需要还会打开该文件。 get
函数返回指向一个静态存储类结构的指针,如果需要保存其内容,则需要复制该结构set
函数:打开相应数据文件(如果尚未打开),然后反绕该文件 end
函数:关闭相应数据文件。在结束了对相应数据文件的读、写操作后,总应该调用此函数以关闭所有相关文件另外如果数据文件支持某种形式的键搜索,则也提供搜索具有指定键的记录的函数
下面是各个重要的数据文件:
说明 | 数据文件 | 头文件 | 结构 | 附加的键搜索函数 |
---|---|---|---|---|
口令 | /etc/passwd | passwd | getpwnam,getpwuid | |
组 | /etc/group | group | getgrnam,getgrgid | |
阴影 | /etc/shadow |
UNIX内核提供的基本时间服务是自 UTC 1970-01-01 00:00:00 这一特定时间以来经过的秒数。
time_t
表示(它包括了时间和日期)time
函数:返回当前的日历时间
#include<time.h>
time_t time(time_t *calptr);
calptr
:如果该指针不是NULL
,则返回的日历时间也存放在calptr
指向的内存中clock_gettime
函数:用于获取指定的时钟类型的时间:
#include<sys/time.h>
int clock_gettime(clockid_t clock_id,struct timespec *tsp);
clock_id
:时钟类型。 CLOCK_REALTIME
:获取实时系统时间。此时clock_gettime
函数提供了与time
函数类似的功能。不过在系统支持高精度时间值的情况下,clock_gettime
可能比time
函数得到更高精度的时间值。CLOCK_MONOTONIC
:获取不带负跳数的实时系统时间CLOCK_PROCESS_CPUTIME_ID
:调用进程的CPU时间CLOCK_THREAD_CPUTIME_ID
:调用线程的CPU时间tsp
:存放获取时间的timespec
结构(它把时间表示为秒和纳秒)的指针clock_getres
函数:时间精度调整
#include<sys/time.h>
int clock_getres(clockid_t clock_id,struct timespec *tsp);
clock_id
:时钟类型。tsp
:存放时间的timespec
结构(它把时间表示为秒和纳秒)的指针clock_getres
函数把参数tsp
指向的timespec
结构初始化为与clock_id
参数对应的始终精度
clock_settime
函数:设置时间
#include<sys/time.h>
int clock_settime(clockid_t clock_id,const struct timepsec *tsp);
clock_id
:时钟类型。tsp
:存放时间的timespec
结构(它把时间表示为秒和纳秒)的指针clock_settime
函数对特定的时钟设置时间。但是:
gettimeofday
函数:更高精度的获取当前时间(但是目前已经弃用)
#include<sys/time.h>
int gettimeofday(struct timeval *restrict tp,void *restrict tzp);
tp
:存放当前时间的timeval
结构(将当前时间表示为秒和微秒)的指针tzp
:唯一合法值是NULL
。其他任何值都产生未定义的结果gmtime/localtime
函数:将日历时间转换成struct tm
结构:
#include<time.h>
struct tm* gmtime(const time_t *calptr);
struct tm* localtime(const time_t *calptr);
calptr
:指向日历时间的指针struct tm
结构的指针NULL
struct tm{
int tm_sec; //秒数,范围是 [0~60]
int tm_min; //分钟数,范围是 [0~59]
int tm_hour; //小时数,范围是 [0~23]。午夜12点是 0
int tm_mday; //一个月中的天数,范围是 [1~31]
int tm_mon; //月数,范围是 [0~11] ,一月是 0
int tm_year; //年数,范围是 [1900~],如果是16则表示 1916
int tm_wday; //一个星期中的天数,范围是 [0~6] ,周日是0
int tm_yday; //一年中的天数,范围是 [0~365],一月一号是 0
int tm_isdst; //daylight saving time flag
}
其中秒可以超过 59 的理由是表示润秒
gmtime/localtime
函数的区别:
gmtime
:将日历时间转换成统一协调的年月日时分秒周日分解结构localtime
:将日历时间转换成本地实际(考虑本地市区和夏令时标志),由TZ
环境变量指定
TZ
环境变量影响localtime/mktime/strftime
这三个函数:
- 如果定义了
TZ
环境变量:则这些函数将使用TZ
的值代替系统默认时区- 如果
TZ
定位为空TZ=
,则使用UTC
作为时区
mktime
函数:以本地时间的年月日等作为参数,将其变化成time_t
值:
#include<time.h>
time_t mktime(struct tm*tmptr);
tmptr
:指向struct tm
结构的指针所谓的本地实际的”本地“:由 TZ
环境变量指定
strftime/strftime_l
函数:类似printf
的打印时间的函数。它们可以通过可用的多个参数来定制产生的字符串
#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);
参数:
buf
:存放格式化后的时间字符串的缓冲区的地址maxsize
:存放格式化后的时间字符串的缓冲区的大小format
:时间的格式化字符串tmptr
:存放时间的struct tm
结构的指针对于strftime_l
函数:
locale
:指定的区域buf
的字符数注意:
buf
长度足够存放格式化结果以及一个null
终止符,则这两个函数才有可能顺利转换;否则空间不够,这两个函数返回0,表示转换失败strftime_l
运行调用者将区域指定为参数;而strftime
使用通过TZ
环境变量指定的区域format
参数控制时间值的格式。如同printf
,转换说明的形式是百分号之后跟随一个特定的字符,而format
中的其他字符则按照原样输出: %a
:缩写的周日名,如Thu
%A
:周日名,如Thursday
%b
:缩写的月名:如Jan
%B
:全月名,如January
%c
:日期和时间,如Thu Jan 19 21:24:25 2012
%C
:年的最后两位,范围是(00~99),如20
%d
:月日,范围是 (01~31),如19
%D
日期(MM/DD/YY),如01/19/12
%e
月日(一位数字前加空格)(1~31),如19
%F
:ISO 8601 日期格式 (YYYY-MM-DD),如 2012-01-19
%g
:ISO 8601 年的最后2位数(00~99),如12
%G
:ISO 8601 的年,如 2012
%h
:与 %b
相同,缩写的月名%H
:小时(24小时制)(00~23)%I
:小时(12小时制)(01~12)%j
:年日(001~366),如019
%m
:月(01~12),如 01
%M
:分(00~59),如 24
%n
:换行符%p
:AM/PM
%r
:本地时间(12小时制),如 09:24:52 PM
%R
:与 %H:%M
相同%S
:秒(00~60),如 52
%t
:水平制表符%T
:同 %H:%M:%S
相同,如 21:24:52
%u
:ISO 8601 周几(1~7,1为周一)%U
:一年的星期日周数(00~53)%V
:ISO 8601 周数(01~53)%w
:周几:(0~6,周日为0)%W
:一年的星期一周数(00~53)%x
:本地日期,如 01/19/12
%X
:本地时间,如21:24:52
%y
:年的最后两位(00~99)%Y
:年,如2012
%z
:ISO 8601 格式的UTC偏移量,如 -0500
%Z
:时区名,如EST
%%
:百分号strptime
函数:它是strftime
的逆向过程,把时间字符串转换成struct tm
时间
#include<time.h>
char *strptime(const char*restrict buf,const char*restrict format,
struct tm*restrict tmptr);
buf
:存放已经格式化的时间字符串的缓冲区的地址format
:给出了buf
缓冲区中的格式化时间字符串的格式tmptr
:存放时间的struct tm
结构的指针NULL
NULL
注意:strptime
的格式化说明与strftime
的几乎相同,但是下列会有区别
%a
:缩写或者完整的周日名%A
:同%a
%b
:缩写或者完整的月名%B
:同%b
%n
:任何空白%t
:任何空白标签:
原文地址:http://blog.csdn.net/taoyanqi8932/article/details/51945122