linux c编程:系统数据文件和信息
linux系统相关的文件信息包含在/etc/passwd文件和/etc/group中。每次登录linux系统以及每次执行ls -l命令时都要使用口令文件。这些字段都包含在<pwd.h>中定义的passwd结构中。
struct passwd {
char * pw_name; /* Username. */
char * pw_passwd; /* Password. */
__uid_t -pw_uid; /* User ID. */
__gid_t -pw_gid; /* Group ID. */
char * pw_gecos; /* Real name. */
char * pw_dir; /* Home directory. -*/
char * pw_shell; /* Shell program. */
};
对应的使用代码如下:
void getpwnam_function(){
const char *name="zhf";
struct passwd *ptr;
ptr=getpwnam(name);
if (!ptr){
printf("%s didn't exist",name);
}
else{
printf("ptr->pw_name=%s\n",ptr->pw_name);
printf("ptr->pw_passwd=%s\n",ptr->pw_passwd);
printf("ptr->pw_uid=%d\n",ptr->pw_uid);
printf("ptr->pw_gid=%d\n",ptr->pw_gid);
}
}
也可以通过uid来进行访问:
void getpwuid_function(){
uid_t uid;
struct passwd *ptr;
uid=1000;
ptr=getpwuid(uid);
if (!ptr){
printf("%d didn't exist",uid);
}
else{
printf("ptr->pw_name=%s\n",ptr->pw_name);
printf("ptr->pw_passwd=%s\n",ptr->pw_passwd);
printf("ptr->pw_uid=%d\n",ptr->pw_uid);
printf("ptr->pw_gid=%d\n",ptr->pw_gid);
}
}
前面getpwuid和getpwnam都只能获得固定的某个uid或者用户名的信息。如果想获得所有用户的信息都采用getpwent函数。它返回口令文件中的下一个记录项,每次调用此函数的时候都重写该结构。注意。在查看完口令文件后,一定要调用endpwent关闭这些文件。代码如下:
void getpwent_function(){
struct passwd *ptr;
ptr=getpwent();
while((ptr=getpwent())!=0){
printf("ptr->pw_name=%s\n",ptr->pw_name);
printf("ptr->pw_passwd=%s\n",ptr->pw_passwd);
printf("ptr->pw_uid=%d\n",ptr->pw_uid);
printf("ptr->pw_gid=%d\n",ptr->pw_gid);
}
endpwent();
}
前面的几个函数都是读取/etc/passwd,但其实在linux系统中还有一个/etc/shadow文件而/etc/shadow文件正如他的名字一样,他是passwd文件的一个影子,/etc/shadow文件中的记录行与/etc/passwd中的一一对应,它由pwconv命令根据/etc/passwd中的数据自动产生。但是/etc/shadow文件只有系统管理员才能够进行修改和查看。
如下是root用户在/etc/shadow中的表现形式
root@zhf-maple:/home/zhf# cat /etc/shadow | grep root
root:$6$9SlLESdr$8vsLVsxe35oLk2IdAZm0BSei6usiRdsrVWZ/VAcqM/yQBASSkn2x/ZKpi8A9W.1qr4.w2vkFz3mTB5.kc2o/3.:17496:0:99999:7:::
文件中字段主要含义为:登录名:加密口令:最后一次修改时间:最小时间间隔:最大时间间隔:警告时间:不活动时间:失效时间:标志
· “登录名”是与/etc/passwd文件中的登录名相一致的用户账号
· “口令”字段存放的是加密后的用户口令字:
· 如果为空,则对应用户没有口令,登录时不需要口令;
星号代表帐号被锁定;
双叹号表示这个密码已经过期了;
$6$开头的,表明是用SHA-512加密;
$1$表明是用MD5加密;
$2$ 是用Blowfish加密;
$5$ 是用 SHA-256加密;
· “最后一次修改时间”表示的是从某个时刻起,到用户最后一次修改口令时的天数。时间起点对不同的系统可能不一样。例如在SCOLinux中,这个时间起点是1970年1月1日。
· · “最小时间间隔”指的是两次修改口令之间所需的最小天数。
· “最大时间间隔”指的是口令保持有效的最大天数。
· “警告时间”字段表示的是从系统开始警告用户到用户密码正式失效之间的天数。
· “不活动时间”表示的是用户没有登录活动但账号仍能保持有效的最大天数。
· “失效时间”字段给出的是一个绝对的天数,如果使用了这个字段,那么就给出相应账号的生存期。期满后,该账号就不再是一个合法的账号,也就不能再用来登录了
同访问口令文件的一组函数类似,有另一组函数可用于访问阴影文件
#include<shadow.h>
struct spwd *getspnam(const char *name)
struct spwd *getspent(void)
spwd的结构如下:
struct spwd
{
char *sp_namp; /* Login name */
char *sp_pwdp; /* Encrypted password */
long int sp_lstchg; /* Date of last change */
long int sp_min; /* Minimum number of days between changes */
long int sp_max; /* Maximum number of days between changes */
long int sp_warn; /* Number of days to warn user to change the password */
long int sp_inact; /* Number of days the account may be inactive */
long int sp_expire; /* Number of days since 1970-01-01 until account expires */
unsigned long int sp_flag; /* Reserved */
};
使用方法如下:
void getspnam_function(){
const char *name="root";
struct spwd *ptr;
ptr=getspnam(name);
printf("spwd->sp_namp:%s",ptr->sp_namp);
printf("spwd->sp_pwdp:%s",ptr->sp_pwdp);
}
getspent的方法
void getspent_function(){
struct spwd *ptr;
while((ptr=getspent())!=0){
printf("spwd->sp_namp:%s",ptr->sp_namp);
printf("spwd->sp_pwdp:%s",ptr->sp_pwdp);
}
endspent();
}
组文件:
前面介绍了用户信息的获取方式,下面介绍获取用户组信息的方式
struct group
{
char *gr_name; /* group name */
char *gr_passwd; /* group password */
int gr_gid; /* group id */
char **gr_mem;
};
#include <grp.h>
struct group *getgrgid(gid_t gid);
struct group *getgrnam(const char *name);
代码如下:
void getgrnam_function(){
const char *name="root";
struct group *ptr;
ptr=getgrnam(name);
printf("ptr->gr_name:%s",ptr->gr_name);
printf("ptr->gr_passwd:%s",ptr->gr_passwd);
printf("ptr->gr_mem:%s",*ptr->gr_mem);
}
同样的如果想遍历所有的用户组信息,则可以采用另外几个函数
#include <grp.h>
struct group *getgrent(void);
void endgrent(void);
时间和日期例程
time函数原型(time.h中):
time_t time(time_t *calptr);
参数:
time_t类型变量的指针。
返回值:
time_t类型相当于一个long,time用于取Epoch记年以来到现在经过的秒数(系统当前时间),Epoch记年从1970年1月1日开始。把取到的时间存在指针指向的变量中。
得到的这个值是一个长整数,直观看意义不大。要想转换成我们直观的日期需要用到localtime函数。
struct tm *localtime(const time_t *calptr);
参数:
time_t类型变量的指针。
返回值:
指向tm结构体的指针类型。
作用是将time_t的值转换为tm结构体。然后可以打印输出。
tm结构体(time.h中):
struct tm
{
int tm_sec; /* Seconds. [0-60] (1 leap second) */
int tm_min; /* Minutes. [0-59] */
int tm_hour; /* Hours. [0-23] */
int tm_mday; /* Day. [1-31] */
int tm_mon; /* Month. [0-11] */
int tm_year; /* Year - 1900. */
int tm_wday; /* Day of week. [0-6] */
int tm_yday; /* Days in year.[0-365] */
int tm_isdst; /* DST. [-1/0/1]*/
#ifdef __USE_BSD
long int tm_gmtoff; /* Seconds east of UTC. */
__const char *tm_zone; /* Timezone abbreviation. */
#else
long int __tm_gmtoff; /* Seconds east of UTC. */
__const char *__tm_zone; /* Timezone abbreviation. */
#endif
};
代码使用方法如下:
void time_function(){
time_t curr;
struct tm *Tm;
time(&curr);
Tm=localtime(&curr);
printf("%4d-%02d-%02d %02d:%02d:%02d\n", Tm->tm_year + 1900, Tm->tm_mon + 1, Tm->tm_mday, Tm->tm_hour, Tm->tm_min, Tm->tm_sec);
}
运行结果如下:
2018-04-28 20:42:18
下面来看下时间格式转化函数
strftime函数:
函数原型:size_t strftime(char *s,size_t maxsize,char *format,conststruct tm *timeptr)
strftime函数对timeptr指向的tm结构所代表的时间和日期进行格式编排,其结果放在字符串s中。该字符串的长度被设置为(最少)maxsize个字符。格式字符串format用来对写入字符串的字符进行控制,它包含着将被传送到字符串里去的普通字符以及编排时间和日期格式的转换控制符。
strptime函数:
函数原型: char *strptime(const char *buf,const char*format,struct tm *timeptr)
format字符串的构建方式和strftime的format字符串完全一样,strptime返回一个指针,指向转换过程处理的最后一个字符后面的那个字符,
输入:const char *buf,const char *format
输出:struct tm *timeptr
转换格式如下:
|
转换控制符 |
说明 |
|
%a |
星期几的简写形式 |
|
%A |
星期几的全称 |
|
%b |
月份的简写形式 |
|
%B |
月份的全称 |
|
%c |
日期和时间 |
|
%d |
月份中的日期,0-31 |
|
%H |
小时,00-23 |
|
%I |
12进制小时钟点,01-12 |
|
%j |
年份中的日期,001-366 |
|
%m |
年份中的月份,01-12 |
|
%M |
分,00-59 |
|
%p |
上午或下午 |
|
%S |
秒,00-60 |
|
%u |
星期几,1-7 |
|
%w |
星期几,0-6 |
|
%x |
当地格式的日期 |
|
%X |
当地格式的时间 |
|
%y |
年份中的最后两位数,00-99 |
|
%Y |
年 |
|
%Z |
地理时区名称 |
代码如下:
void strftime_function(){
int ret;
char buffer[255];
struct tm Tm;
strptime("28/April/2018:20:57:35", "%d/%b/%Y:%H:%M:%S", &Tm);
strftime(buffer, sizeof(buffer), "%d %b %Y %H:%M", &Tm);
printf("%s",buffer);
}
或者是通过mktime的方式:
void strftime_function(){
int ret;
struct tm info;
char buffer[255];
info.tm_year=2018-1900;
info.tm_mon=4-1;
info.tm_mday=28;
info.tm_hour=20;
info.tm_min=55;
info.tm_sec=00;
ret=mktime(&info);
if(ret == -1){
printf("can not make time");
}
else{
strftime(buffer, sizeof(buffer), "%d %b %Y %H:%M", &info);
printf("%s\n",buffer);
}
}
时间差计算:
在评估程序的时候经常要计算程序的运行时间,有两种方法计算时间差,分别是difftime函数和clock函数
double difftime(time_t time1, time_t time2)
该函数返回以双精度浮点型 double 值表示的两个时间之间相差的秒数 (time2 - time1)。
这里得到的结果就是3秒
void different_time(){
time_t start,end;
double diff_t;
time(&start);
sleep(3);
time(&end);
diff_t=difftime(end,start);
printf("the gap is %f\n",diff_t);
}
但是秒级的粒度太粗了,我们需要评估CPU的运行时间的话就必须采用clock函数
clock_t clock(void) 返回程序执行起(一般为程序的开头),处理器时钟所使用的时间。为了获取 CPU 所使用的秒数,您需要除以 CLOCKS_PER_SEC。
在 32 位系统中,CLOCKS_PER_SEC 等于 1000000,该函数大约每 72 分钟会返回相同的值。
void clock_function(){
clock_t start,end;
double total;
start=clock();
for(int i=0;i<=1000000;i++){
}
end=clock();
total=(double)(end-start)/CLOCKS_PER_SEC;
printf("the total time is:%f\n",total);
}
linux c编程:系统数据文件和信息的更多相关文章
- (四) 一起学 Unix 环境高级编程(APUE) 之 系统数据文件和信息
. . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...
- apue学习笔记(第六章 系统数据文件和信息)
UNIX系统的正常运作需要使用大量与系统有关的数据文件,例如,口令文件/etc/passwd和组文件/etc/group就是经常被多个程序频繁使用的两个文件. 口令文件 UNIX系统口令文件包含如下字 ...
- UNIX环境高级编程 第6章 系统数据文件和信息
UNIX系统的正常运作需要用到大量与系统有关的数据文件,例如系统用户账号.用户密码.用户组等文件.出于历史原因,这些数据文件都是ASCII文本文件,并且使用标准I/O库函数来读取. 口令文件 /etc ...
- UNIX系统高级编程——第六章-系统数据文件和信息-总结
口令文件: /* The passwd structure. */ struct passwd { char *pw_name; /* Username. */ char *pw_passwd; /* ...
- 《UNIX环境高级编程》读书笔记之系统数据文件和信息(1)
1.UNIX系统口令文件包括了下图所看到的的各字段,这些字段包括在<pwd.h>中定义的passwd结构体中 POSIX定义了两个获取口令文件项的函数. 在给出用户登录名或用户ID后.这两 ...
- [APUE]系统数据文件与信息
一.口令文件 UNIX口令文件包含下表中的各个字段,这些字段包含在 由于历史原因,口令文件是/bin/passwd,而且是一个文本文件,每一行都包括了上表中的七个字段,字段之间用":&quo ...
- [06]APUE:系统数据文件和信息
[a] getpwent / setpwent / endpwent #include <pwd.h> struct passwd *getpwent(void) //成功返回指针,出错或 ...
- 系统数据文件和信息之附加组ID
4.2BSD引入了附加组ID(supplementary group ID)的概念.我们不仅可以属于口令文件记录项中组ID所对应的组,也可属于多达16个另外的组.文件访问权限检查相应被修改为:不仅将进 ...
- APUE学习笔记——6 系统数据文件与信息
1.用户口令:/etc/passwd文件 该文件中包含下列结构体信息.其中,当下主修熊passwd不再这里显示,是使用了一个占位符. struct passwd { char * pw_name; / ...
随机推荐
- 详细解析Spring事务的配置和OpenSessionInview的作用
1.事务的特性 原子性:事务中的操作是不可分割的一部分 一致性:要么同时成功,要么同时失败(事务执行前后数据保持一致) 隔离性:并发互不干扰 持久性:事务一旦被提交,它就是一条持久 ...
- 关于web后门权限防删的一个新思路
见土司有一帖子 具体看下面连接 https://www.t00ls.net/thread-26444-1-2.html 这是php的 其实IIS也有类似的 这是MSF生成的一个ASPX执行shellc ...
- vue笔记三(组件)
十.组件 1.组件中的data为函数 2.props: 父组件向子组件传递数据 子组件:Child.vue <template> <span>{{ myMsg }}</s ...
- Linux vim命令记录
Ndd :删除N行 多行删除 :1,10d ctrl+v ,移动光标,ctrl+i,输入#,esc :移动处均会输入# gg:文档头 G:文档尾 o:下一行,并进入insert模式 O:上一行并输入 ...
- sed `grep` 查找并替换
sed "s/libletvwatermark/libletv_watermark/" `grep -rl libletvwatermark` grep [options] 3.主 ...
- 10分钟-jQuery-基础选择器
1.id 选择器 jquery能使用CSS选择器来操作网页中的标签元素.假设你想要通过一个id号去查找一个元素,就能够使用例如以下格式的选择器: $("#my_id") 当中#my ...
- MySQL - Show Processlist 整理(转)
原文来源:MySQL 5.5 Reference Manual 部分翻译取自:<MySQL_5.1中文参考手册> 转载请注明原文链接http://www.cnblogs.com/len ...
- Ubuntu14.04下MySQL的安装与卸载
转载自:https://www.2cto.com/os/201408/329502.html 安装MysQL 执行以下命令:sudo apt-get install mysql-server 2. 继 ...
- 操作符(运算符)重载 或者叫 二元运算符 operator + 与 转换式操作符 implicit operator explicit operator
static void Main(string[] args) { rational r1 = new rational(5); rational r2 = new rational(51); rat ...
- PHP框架认识初步
PHP框架比較 CodeIgniter Codeigniter 相当轻量级.下载下来就能用, CI 的最大特点就是可扩展性非常强 你能够通过不改动源代码的方式 优雅的扩展差点儿全部的东西. think ...