APUE第6章 系统数据文件和信息

这篇博客详细介绍了UNIX系统中的关键数据文件,包括口令文件/etc/passwd、阴影口令文件/etc/shadow、组文件、登录账户记录以及时间例程。内容涵盖口令字段的解释、阴影口令的安全性、组文件的结构、utmp和wtmp文件的作用,以及获取和处理时间的函数。
摘要由CSDN通过智能技术生成

1、概述

UNIX系统的正常运作需要使用大量与系统有关的数据文件,例如,口令文件/etc/passwd和组文件/etc/group就是经常被多个程序频繁使用的两个文个件。用户每次登录UNIX系统,以及每次执行ls -l命令时都要使用口令文件。

2、口令文件/etc/passwd

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_dir)、初始shell(用户程序)(char* pw_shell)、用户访问类(char* pw_class)、下次更改口令时间(time_t pw_change)、账户有效期时间(time_t pw_expire)。

举例:tyliang:x:1000:1000:tyliang,,,:/home/tyliang:/bin/bash

值得注意地方:

i、通常有一个用户名为root的登录项,其用户ID为0

ii、加密口令字段包含了一个占位符。我们无法看见密码的,嘿嘿!

iii、shell字段包含了一个可执行程序名,它被用作该用户的登录shell。

iv、为了阻止一个特定用户登录系统。除使用/dev/null外,其他替代方法:将/bin/false用作登录shell(以不成功状态终止);用/bin/true禁止一个账户(以成功状态终止);用nologin命令,打印可定制的出错信息,然后以非0状态终止。

v、finger命令支持注释字段中的附加信息。如:finger -p tyliang   从而可以查看tyliang用信息。

3、阴影口令/etc/shadow

某些系统将加密口令存放在一个通常称为阴影口令的文件中。该文件至少包含用户名和加密口令。只有root权限才有资格查看。

/etc/shadow文件中的字段
说明struct spwd成员
用户登录名char* sp_namp
加密口令char* sp_pwdp
上次更改口令以来经过的时间int sp_lstchg
经多少天后允许更改int sp_min
要求更改尚余天数int sp_max
超期警告天数int sp_warn
账户不活动之前尚余天数int sp_inact
账户超期天数int sp_expire
保留unsigned int sp_flag

4、组文件

UNIX组文件包含如下表的所示字段。这此字段包含在<grp.h>中所定义的group结构中。

/etc/group文件中字段
说明struct group成员
组名char* gr_name
加密口令char* gr_passwd
数值组IDint gr_gid
指向各用户名指针的数组char** gr_mem

字段gr_mem是一个指针数组,其中每个指针指向一个属于该组的用户名。该数组以null指针结尾。

5、其他数据文件

访问系统数据文件的一些例程
说明数据文件头文件结构附加的键搜索函数
口令/etc/passwd<pwd.h>passwdgetpwnam、getpwuid
/etc/group<grp.h>groupgetgrnam、getgrgid
阴影/etc/shadow<shadow.h>spwdgetspnam
主机/etc/hosts<netdb.h>hostentgetnameinfo、getaddrinfo
网络/etc/networks<netdb.h>netentgetnetbyname、getnetbyaddr
协议/etc/protocols<netdb.h>protoentgetprotobyname、getprotobynumber
服务/etc/services<netdb.h>serventgetservbyname、getservbyport

6、登录账户记录、系统标识

i、UNIX系统提供下列两个数据文件:utmp文件记录当前登录到系统的各个用户;wtmp文个把跟踪各个登录和注销事件。

一般而言,利用who命令读取utmp文件,last命令读取wtmp文件。

ii、uname函数返回与主机和操作系统有关的信息

#include<sys/utsname.h>
int uname(struct utsname* name);
		//返回值:若成功,返回非负值,若出错,返回-1
struct utsname {
	char sysname[];/* name of the operating system*/
	char nodename[];/* name of this node */
	char release[];/* current release of operating system*/
	char version[];/* current version of this release */
	char machine[];/* name of hardware type */
};

utsname结构中的信息通常可用uname命令打印。

 

gethostname函数:只返回主机名,该名字通常就是tcp/ip网络上主机的名字。

#include<unistd.h>
int gethostname(char* name, int namelen);
		//返回值:若成功,返回非负值,若出错,返回-1

namelen参数指定name缓冲区长度,如若提供足够的空间,则通过name返回的字符串以null字节结尾。如若没有提供足够的空间,则没有说明通过name返回的字符串是否以null结尾。

hostname命令可用来获取和设置主机名。(超级用户用一个类似的函数sethostname来设置主机名。)主机名通常在系统自举时设置,它由/etc/rc或init取自一个启动文件。

7、时间和日期例程

日历时间:以1970年1月1日为准,经过的时间以秒来计算,其类型为time_t。

分解时间:即存储年月日时分秒,通过一定组合可以转换成我们熟悉的时间表示。

i、time函数返回当前时间和日期。

#include<time.h>
time_t time(time_t *calptr);
		//返回值:若成功,返回时间值,若出错,返回-1

时间值作为函数值返回。如果参数非空,则时间值也存放在由calptr指向的单元内。

mktime函数将本地时间的年月日等作为参数,转变为time_t值。

#include<time.h>
time_t mktime(struct tm* tmptr);
		//返回值:若成功,返回日历时间;若出错,返回-1

ii、两个函数localtime和gmtime将日历时间转换成分解的时间,并将这些存放在一个tm结构中。

#include<time.h>
struct tm* gmtime(const time_t * calptr);
struct tm* localtime(const time_t * calptr);
		//两个函数的返回值:指向分解的tm结构的指针;若出错,返回NULL

localtime和gmtime之间的区别是:localtime将日历时间转换成本地时间(考虑到本地时区和夏令时标志),而gmtime则将日历时间转换成协调统一时间的年、月、日、时、分、秒、周日分解结构。

iii、strftime是一个类似于printf的时间值函数。可通过可用的多个参数来定制产生的字符串。

#include<time.h>
size_t strftime(char* restrict buf, size_t maxsize, const char *restrict format,
	const struct tm* restrict tmptr);//将分解时间转换成字符串,其中tmptr参数由localtime函数获取
size_t strftime_l(char* restrict buf, size_t maxsize, const char *restrict format,
	const struct tm* restrict tmptr,locale_t locale);
		//两个函数的返回值:若有空间,返回存入数组的字符数;否则,返回0

strftime_l允许调用者将区域指定为参数。strftime使用通过TZ环境变量指定的区域。

tmptr参数是要格式化的时间值,由一个指向分解时间值tm结构的指针说明。

format参数控制时间值的格式。如同printf函数一样,转换说明的形式是百分号之后跟一个特定字符。

该部分具体参考书P154-P156。

下图是各个函数之间的转换关系。

以下是获取本时间的程序:

#include"apue.h"
#include<time.h>

int main(){
	time_t caltime;
	struct tm *tm;
	char line[MAXLINE];

	if((caltime=time(NULL))==-1)//调用time函数返回日历时间
		err_sys("time_error");
	if((tm=localtime(&caltime))==NULL)//将日历时间转换为本地的分解时间
		err_sys("localtime error");
	if(strftime(line,MAXLINE,"%a %b %X %Z %Y\n",tm)==0)//将分解时间格式化为字符串
		err_sys("strftime error");
	fputs(line,stdout);//将字符串输出到标准输出中
	exit(0);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值