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中的表现形式

[email protected]:/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);

}

原文地址:https://www.cnblogs.com/zhanghongfeng/p/8969626.html

时间: 2024-10-17 02:04:20

linux c编程:系统数据文件和信息的相关文章

《UNIX环境高级编程》--6系统数据文件和信息

系统数据文件和信息 用户配置文件 1. /etc/passwd UNIX口令文件 /etc/passwd/是一个ASCII文件,每一行包含很多字段,字段之间用冒号分隔.这些字段包含在<pwd.h>头文件定义的passwd,该结构有如下成员: char *pw_name:用户名 char *pw_passwd:加密口令 uid_t pw_uid:数值用户ID gid_t pw_gid:数值组ID char *pw_gecos:注释字段 char *pw_dir:初始工作目录 char *pw_s

Unix环境高级编程学习笔记(三):标准I/O , 系统数据文件和信息

1 标准I/O函数不同于read,write函数,是其在流上进行操作, 当首次调用标准I/O函数时,系统会首先调用malloc,为流创造缓冲区, 2 fopen函数 #include<stdio.h> file * fopen(const char* pathname, const char * restrict name); 打开返回指针,出错返回NULL, type的取指有r(读),w(写),a(追加),r+/w+(读+写),a+(读+写+追加) int fclose(file* fp)

(四) 一起学 APUE 之 系统数据文件和信息

. . . . . 目录 (一) 一起学 APUE 之 标准 IO (二) 一起学 APUE 之 文件 IO (三) 一起学 APUE 之 文件和目录 (四) 一起学 APUE 之 系统数据文件和信息 1.getpwnam(3).getpwuid(3) 1 getpwnam, getpwuid - get password file entry 2 3 #include <sys/types.h> 4 #include <pwd.h> 5 6 struct passwd *getp

APUE学习笔记:第六章 系统数据文件和信息

6.1 引言 UNIX系统的正常运行需要使用大量与系统有关的数据文件,针对这些数据文件的可移植接口是本章的主题.本章还介绍了系统标识函数.时间和日期函数 6.2 口令文件 UNIX系统的口令文件包含了下列各字段,这些字段包含在<pwd.h>中定义的passwd结构中 用户名 char *pw_name 加密口令 char *pw_passwd 数值用户ID uid_t pw_uid 数值组ID gid_t pw_gid 注释字段 char *pw_gecos 初始工作目录 char *pw_d

读书笔记-APUE第三版-(6)系统数据文件和信息

常见系统数据文件 下表列出了常见的系统数据文件及其查找函数. 以/etc/passwd文件为例,读取数据的程序基本框架如下: void get_pw_entry() { struct passwd *ptr; setpwent(); while ((ptr = getpwent()) != 0) { -- } endpwent(); return ptr; } 每个数据文件都提供了一个get方法返回文件下一个记录项. set方法充值当前位置到文件开始处. end方法关闭数据文件. 表格中的get

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

UNIX系统的正常运作需要使用大量与系统有关的数据文件,例如,口令文件/etc/passwd和组文件/etc/group就是经常被多个程序频繁使用的两个文件. 口令文件 UNIX系统口令文件包含如下字段,这些字段包含在<pwd.h>中定义的passwd结构中 口令文件是/etc/passwd,每一行包含上面各字段,字段之间用冒号分隔.可以使用finger命令打印指定用户的有关信息:finger -p 用户名 POSIX.1定义了两个获取口令文件项的函数,在给定用户登录名或数值用户ID后,这两个

系统数据文件和信息

系统正常运行需要使用大量系统数据文件,其中,所有UNIX系统都有的是:口令文件.组文件,大多数系统都提供的是:登录账户记录.系统标识.时间和日期例程,同时还有其他一些常用系统数据文件如:BSD网络软件有一个记录各网络服务器所提供服务的数据文件(/etc/services).记录协议住处的数据文件(etc/protocols)等. 1.口令文件 口令文件包括了以下字段,这些字段包含在<pwd.h>中定义的passwd结构中: struct passwd { char*  pw_name;    

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

1.UNIX系统口令文件包括了下图所看到的的各字段,这些字段包括在<pwd.h>中定义的passwd结构体中 POSIX定义了两个获取口令文件项的函数. 在给出用户登录名或用户ID后.这两个函数就能查看相关项. #include <pwd.h> struct passwd *getpwuid(uid_t uid); struct passwd *getpwnam(const char *name); 假设想要查看整个口令文件,则要用到以下三个函数: #include <pwd

APUE读书笔记-第六章 系统数据文件和信息

昨天看完了,今天来看看第六章.感觉第六章的内容不是非常重要.简单看看吧 6.2 口令文件 口令文件其实就是/etc文件夹下的passwd文件,但处于安全性的考虑,我们无法直接读取它.就是通过直接限制权限的方式对其进行保护,passwd文件具体权限如下: -rw-r--r-- 1 root root 可以看到只有root用户具有读写权限,与root同组的用户与其他用户仅具有读权限. 不过为了解决以上问题,Linux中给出了一系列数据结构与函数帮助我们操纵口令文件,首先是关键数据结构,定义位于/in