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编程:系统数据文件和信息的更多相关文章

  1. (四) 一起学 Unix 环境高级编程(APUE) 之 系统数据文件和信息

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  2. apue学习笔记(第六章 系统数据文件和信息)

    UNIX系统的正常运作需要使用大量与系统有关的数据文件,例如,口令文件/etc/passwd和组文件/etc/group就是经常被多个程序频繁使用的两个文件. 口令文件 UNIX系统口令文件包含如下字 ...

  3. UNIX环境高级编程 第6章 系统数据文件和信息

    UNIX系统的正常运作需要用到大量与系统有关的数据文件,例如系统用户账号.用户密码.用户组等文件.出于历史原因,这些数据文件都是ASCII文本文件,并且使用标准I/O库函数来读取. 口令文件 /etc ...

  4. UNIX系统高级编程——第六章-系统数据文件和信息-总结

    口令文件: /* The passwd structure. */ struct passwd { char *pw_name; /* Username. */ char *pw_passwd; /* ...

  5. 《UNIX环境高级编程》读书笔记之系统数据文件和信息(1)

    1.UNIX系统口令文件包括了下图所看到的的各字段,这些字段包括在<pwd.h>中定义的passwd结构体中 POSIX定义了两个获取口令文件项的函数. 在给出用户登录名或用户ID后.这两 ...

  6. [APUE]系统数据文件与信息

    一.口令文件 UNIX口令文件包含下表中的各个字段,这些字段包含在 由于历史原因,口令文件是/bin/passwd,而且是一个文本文件,每一行都包括了上表中的七个字段,字段之间用":&quo ...

  7. [06]APUE:系统数据文件和信息

    [a] getpwent / setpwent / endpwent #include <pwd.h> struct passwd *getpwent(void) //成功返回指针,出错或 ...

  8. 系统数据文件和信息之附加组ID

    4.2BSD引入了附加组ID(supplementary group ID)的概念.我们不仅可以属于口令文件记录项中组ID所对应的组,也可属于多达16个另外的组.文件访问权限检查相应被修改为:不仅将进 ...

  9. APUE学习笔记——6 系统数据文件与信息

    1.用户口令:/etc/passwd文件 该文件中包含下列结构体信息.其中,当下主修熊passwd不再这里显示,是使用了一个占位符. struct passwd { char * pw_name; / ...

随机推荐

  1. node-表单验证

    var http = require('http'); var url = require('url'); var fs = require('fs'); var querystring = requ ...

  2. Tomcat Connector的三种不同的运行模式

    Tomcat Connector的三种不同的运行模式性能相差很大,有人测试过的结果如下: 这三种模式的不同之处如下: BIO: 一个线程处理一个请求.缺点:并发量高时,线程数较多,浪费资源. Tomc ...

  3. Android学习(三) 自动完成的使用

    1.AutoCompleteTextView 自动完成功能,在文本框中输入字符,会出现匹配的自动提示.类似百度搜索. XML代码 <?xml version="1.0" en ...

  4. TFS 设置(转)

    一 参考以下两个链接进行相关软件的安装和用户权限配置: http://www.cnblogs.com/WilsonWu/archive/2011/11/24/2261674.html http://w ...

  5. JQuery修改对象的属性值

    JQuery修改对象的属性值 用到的便是JQuery提供的attr方法,获取属性值的基本结构为:$(obj).attr("属性名"):修改属性值的结构为:$(obj).attr(& ...

  6. springMVC 前后台日期格式传值解决方式之一(共二) @DateTimeFormat的使用和配置

    无意中发现对于时间字符串转Date类,根本不用自己去写转换类,spring mvc已经实现了该功能,还是基于注解的,轻松省事,使用 org.springframework.format.support ...

  7. hdu 4417,poj 2104 划分树(模版)归并树(模版)

    这次是彻底把划分树搞明确了,与此同一时候发现了模版的重要性.敲代码一个字符都不能错啊~~~ 划分树具体解释:点击打开链接 题意:求一组数列中随意区间不大于h的个数. 这个题的做法是用二分查询  求给定 ...

  8. C/C++ 内存管理总结

    C内存管理 存储时: 执行程序在存储时(没有调入到内存)分为代码区(text).数据区(data)和未初始化数据区(bss)3个部分. 1 代码区(text segment) 存放CPU执行的机器指令 ...

  9. Unity3D性能优化之Draw Call Batching

    在屏幕上渲染物体,引擎需要发出一个绘制调用来访问图形API(iOS系统中为OpenGL ES).每个绘制调用需要进行大量的工作来访问图形API,从而导致了CPU方面显著的性能开销. Unity在运行时 ...

  10. 利用NIO的Selector处理服务器-客户端模型

    package NIOTEST; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocket ...