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. Mac OSX下编译安装PostgreSQL

    原先使用的是官方提供的安装包,可是安装包会创建postgre这个用户.在登陆界面看的有点不爽,搜索了半天居然没有找到怎样在osx下编译安装的教程,并且假设是依照官方文档的编译安装办法一定会让你崩溃,本 ...

  2. 熟悉jauery库中的构造函数 jQuery()

    如果调用构造函数 jQuery() 时传入的参数不同,创建 jQuery 对象的逻辑也会随之不同.实际上构造函数 jQuery() 有 7 种用法,下面一一举例 1.jQuery( selector ...

  3. 图解HTTP第六章:HTTP首部

    学习HTTP首部的结构和首部中各字段的用法. HTTP首部字段 使用首部字段是为了给浏览器和server提供报文主体大小.所使用的语言.认证信息等内容. 首部字段相应单个HTTP首部能够有多个值.假设 ...

  4. 【BIEE】03_BIEE数据源配置

    声明:此时说的是Oracle数据源配置 BIEE数据源配置有两种方法 ①直接使用字符串连接 ②将tnsnames.ora文件覆盖到obiee目录下 直接使用字符串 直接使用字符串连接很简单 首先打开资 ...

  5. DbVisualizer出现下列错误:Could not read XML file

    数据库连接工具对于我们软件测试工程师来说是日常的工具,一旦关键时刻报些莫名的错误,相信大家很是苦恼.当然,各公司数据库连接工具各异,像DbVisualizer.PLsql.sqldeveloper.T ...

  6. Unable to connect to a repository at URL 解决方法

    提示"Unable to connect to a repository at URL 'svn://localhost/project1/'" or “Can't connect ...

  7. c#实现记事本

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  8. ASP.NET CORE RAZOR :初始化数据库

    官方说法是:设定数据库种子https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/razor-pages/sql 应用背景:初次部署系统时,设定一 ...

  9. SpringCloud系列二:硬编码实现简单的服务提供者与服务消费者

    从本文开始,以一个电影售票系统为例讲解Spring Cloud 1. 版本 jdk:1.8 SpringBoot:2.0.0.RELEASE SpringCloud:Finchley.M8 2. 系统 ...

  10. zabbix api调用

    zabbix api调用 api能干什么 Zabbix API allows you to programmatically retrieve and modify the configuration ...