查看联机帮助与who命令的实现
一、背景
通过对who命令的系统编程来学会查看联机帮助,学习使用联机帮助来查找到有用的信息。并且学习linux的文件操作。
二、实现过程
1、了解who命令的作用
我这里登陆了三个用户root,pf,pf2。可以看到who命令的作用:第一列是用户名的名称,第二列是终端的名称,第三列是登陆的时间(这里没有用时间戳的形式),第四列是用户登录的IP地址。了解了这些之后,就明白了自己的目的。有了目的接下来就是怎么实现了。自己首先猜测,who命令的实现有可能是从哪个配置文件中调出来的系统的信息,至于具体是怎样就不甚明白了。于是就想到了查找用户手册。
2、通过手册来检索有用的信息
用man命令来查看who。Synopsis是who的基本用法。这个不是想要的。可以在description中找到这样一句话。
这句话是说如果文件没指定参数。那么就从/var/run/utmp,/var/log/wtmp中来读取信息。那么到底这两个文件是干什么的呢?我们知道/var目录下是存可扩充不断更改的变量信息的。这就不明白了。于是需要进一步往下看。
在see also中我找到了一句有用的话。是说如果电脑支持的话可以用info who来查看更完整的手册。
这里又找到了类似于man手册中的一句话。是说如果只使用who命令而无参数的话,那么会从/var/run/utmp中读取正在登录的用户信息。意思与man中的意思大概相同。现在就需要来看看utmp是个什么东西了。
首先我想先用more来查看一下,但是发现什么都没有。那就另辟蹊径。用man -k命令来根据关键字搜索联机帮助。
从这里可以找一下。发现倒数第四行和最后一行最像是我想要的东西。共同点是都是第5小节的东西。而第5小节都是配置文件的帮助。这个就无所谓了,总之用man 5 utmp来查看一下吧。
这里首先看到了utmp的头文件。
并且从这里看以看出,utmp是一个结构体类型啊,而且这里面包含了我想要的东西。再进/usr/include/utmp.h看看,找到读取的文件的宏定义名。
3.linux的文件操作
到了这里,头脑逐渐清晰起来了。我需要从utmp文件中将类型为utmp的结构体都出来,并且,选择出我需要的信息来进行输出就可以了。现在的问题在于如何打开文件,如果读取文件以及如何关闭文件。因为这里需要读的结构体中的信息。当然这里又需要用到man命令了。先用man -k read来查看,就会发现屏幕列出了一大堆,一个一个找也行,但费时费力的,而且事倍功半。所以使用grep file命令来过滤一下就好了。这样就可以找到关于文件的读命令了。
这里找到了两个关于read的命令,看看第一个好了,后面的英语是讲:从文件描述符中读取。
首先看到了这里的头文件,因为是系统调用,这里必须要有头文件的。然后看到这个read命令的用法是如何的。这里的问题又出来了,如何得到文件描述符呢?文件描述符显然并不是文件名或文件的指针。那就继续往下看看吧。
看到这里,眼睛当然注意到了open与close命令,这一看就很有可能是自己需要的文件打开与关闭命令。再进行open命令与close命令的手册查看就能找到他们的头文件和使用方法了。我这里就不再详细说了,要不然就显得太啰嗦了。查看方法和read基本类似。
4.实现过程
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<unistd.h>
#include<utmp.h>
#include<fcntl.h>
#define SHOWHOST
void showtime(long time);
void show_record(struct utmp *a);
int main()
{
int fd;
struct utmp record;
if((fd=open(UTMP_FILE,O_RDONLY))==-1)
{
perror(UTMP_FILE);
exit(1);
}
while(read(fd,&record,sizeof(record))==sizeof(record))
show_record(&record);
close(fd);
return 0;
}
void show_record(struct utmp *a)
{
if((a->ut_type)!=USER_PROCESS)
return ;
printf("%-8.8s",a->ut_name);
printf(" ");
printf("%-8.8s",a->ut_line);
printf(" ");
showtime(a->ut_time);
#ifdef SHOWHOST
if(a->ut_host[0]!='\0')
printf("(%s)",a->ut_host);
#endif
printf("\n");
}
void showtime(long time)
{
printf("%12.12s",ctime(&time)+4);
}
这里需要特别注意几个问题:
(1)格式要注意,在字符串输出的时候不注意格式输出的东西将会和who十分不相像。
(2)这里用到了时间的转换命令ctime,如果不使用该命令的话可见时间是时间戳的形式,即使一大长串的数字,其实这个数字表示的是从1970年1月1日0时开始计算的秒数。
(3)要对输出的用户登录名进行过滤,只显示输出普通用户的登陆名及其信息。
5.实现结果
三、总结
从who命令的实现,我学习到了man的使用技巧。包括如何使用man -k来查找相关信息,并且使用grep来进行过滤无用的信息。同时,学习了如何输出文件中的结构体的内容,这不同于more命令实现中的gets命令。不过在学习的过程中还是发现了不少问题,有一些概念不清晰导致编程的时候虽然编程结果没错,但过程的思路并不清晰,这需要多看书,理清楚一些基础的东西。