who命令的基本实现(下)

在who命令的基本实现(上)这一篇博文介绍了who命令的基本原理,所以我们可以尝试着编写自己的who命令。

who1.c:

#include 
#include 
#include 
#include 
#include 

#define SHOWHOST	/* include remote machine on output */

void show_info (struct utmp*);

int main () {
	struct utmp current_record; /* read info into this variable */
	int utmpfd; /* just a file descriptor */
	int reclen = sizeof(current_record);
	
	if ((utmpfd = open(UTMP_FILE, O_RDONLY)) == -1) {
		perror(UTMP_FILE); /* UTMP_FILE is in utmp.h */
		exit(1);
	}
	while (read(utmpfd, ¤t_record, reclen) == reclen) {
		show_info(¤t_record);
	}
	close(utmpfd);
	return 0;
}

void show_info (struct utmp* utbufp) {
	printf("%-8.8s", utbufp->ut_name);
	printf(" ");
	printf("%-8.8s", utbufp->ut_line);
	printf(" ");
	printf("%10ld", utbufp->ut_time);
	printf(" ");
#ifdef SHOWHOST
	printf("(%s)", utbufp->ut_host);
#endif
	printf("\n");
}

用以下命令将上述文件编译、运行:

cc who1.c -o who1
./who1 //在who1所在目录下运行这条命令

使用who1命令得到的结果为:

可以看到它能显示出:用户名、终端名、从登陆开始到目前为止的秒数、远程主机名。

我们的who1有两个不足:

无法正确的显示时间;

但与系统自带的who命令作对比可以发现:


系统中登陆的用户其实只有wzh这一个用户,这是因为utmp文件实际上包含所有终端的信息,包括那些尚未被用到的终端的信息也存放在utmp中。

who2.c:

1.

(使用man -k utmp命令可以看到以下两张图片的信息)


utmp结构体中有个ut_type属性。以下是ut_type可以有的一些值:

who命令的基本实现(下)_第1张图片

当ut_type的值为7时,表示这是一个已经登录的用户。因此,对程序作出修改:

void show_info (struct utmp* utbufp) {
	if (utbufp->ut_type != USER_PROCESS) return;
        printf("%-8.8s", utbufp->ut_name);
	printf(" ");
	printf("%-8.8s", utbufp->ut_line);
	printf(" ");
	printf("%10ld", utbufp->ut_time);
	printf(" ");
#ifdef SHOWHOST
	printf("(%s)", utbufp->ut_host);
#endif
	printf("\n");
}
主要是添加上面代码片段中加粗的那条语句。
2.接下来修改显示登录时间的方式

从who命令的基本实现(上)可以知道用户登录时间ut_time其实被定义为ut_tv结构体中的tv_sec变量,而tv_sec变量的类型为int32_t。

而我在utmp.h文件中是没发现int32_t的实际类型是什么:


但是我在utmp.h文件中发现它include了一个头文件。我猜想int32_t的实际类型可能会在这个头文件中定义。进一步查看可以知道int32_t的实际类型为int类型


使用如下命令查看关于时间的联机帮助:

man -k time

更好的过滤方法是:

man -k time | grep transform

man -k time | grep -i convert

who命令的基本实现(下)_第2张图片

这里使用的是ctime(3)来将表示时间的整数值转换成人们日常所使用的时间形式。

通过man 3 ctime命令查看可以发现下面这两段信息:



其中这篇博文介绍了追踪time_t实际类型的方法,time_t实际类型为long int。

这就表示ctime这个函数可以将指向用户登录时间ut_time的指针作为参数,然后该函数返回一个上图中显示的字符串。

who命令的基本实现(下)_第3张图片

who命令的基本实现(下)_第4张图片


系统为32位ubuntu的int,long,long int的字节数:


你可能感兴趣的:(UnixLinux编程实践)