linux中经常用到who命令查看登录信息如:
$ who
v tty1 Feb 18 16:33 (:0)
v pts/0 Feb 18 16:33 (:0)
v pts/1 Feb 18 16:33 (:0)
那么如何写一个who命令程序呢
先上代码
#include<stdio.h>
#include<stdlib.h>
#include<utmp.h>
#include<fcntl.h>//open()
#include<unistd.h>//read(),close()
#include<time.h>
#define SHOWHOST
int show_info(struct utmp *utbufp);
void showTime(long timeval);
int main()
{
struct utmp current_record;//实例化的对象 将要把读出的数据存在这
int utmpfd;//文件描述符
int reclen=sizeof(current_record);
if((utmpfd=open(UTMP_FILE,O_RDONLY))==-1)//UTMP_FILE是utmp.h中的宏定义
{
perror(UTMP_FILE);
exit(1);
}
while(read(utmpfd,¤t_record,reclen)==reclen)//循环打印,确保所有用户都列出
{
show_info(¤t_record);
}
close(utmpfd);
return 0;
}
void showTime(long timeval)
{
char *cp=ctime(&timeval);
printf("%12.16s",cp );
}
int show_info(struct utmp *utbufp)
{
if(utbufp->ut_type!=USER_PROCESS)//确保是一个登录的用户,utmp.h中定义了USER_PROCESS当它的值是7时,说明是一个登录用户
{
return 0;
}
printf("% -8.8s",utbufp->ut_name);
printf(" ");
printf("% -8.8s",utbufp->ut_line);
printf(" ");
showTime(utbufp->ut_time);
printf(" ");
#ifdef SHOWHOST
if(utbufp->ut_host[0]!='\0')
printf("(%s)",utbufp->ut_host);
#endif
printf("\n");
return 0;
}
需要首先说明在linux中头文件utmp.h定义了系统的用户登录记录,通过man帮助(man 5 utmp)可以查到在这个头文件中定义了结构体utmp:
//这里只显示其中一部分
struct utmp {
short ut_type; /* Type of record */
pid_t ut_pid; /* PID of login process */
char ut_line[UT_LINESIZE]; /* Device name of tty - "/dev/" */
char ut_id[4]; /* Terminal name suffix,
or inittab(5) ID */
char ut_user[UT_NAMESIZE]; /* Username */
char ut_host[UT_HOSTSIZE]; /* Hostname for remote login, or
kernel version for run-level
messages */
struct exit_status ut_exit; /* Exit status of a process
marked as DEAD_PROCESS; not
used by Linux init (1 */
通过其中的注释可以看到ut_line储存tty,另外在该结构中还定义了登录用户ut_name,登录时间点ut_time,所以我们只需实例化一个utmp对象,将所要用到的数据导入这个对象的成员中,再打印在终端上即可。
那么如何读取我们所需要的数据呢,可以用open()函数打开存储相关信息的文件,read()函数读出该文件中的内容并将数据写入已经实例化的utmp实体,以上两个函数分别在头文件fcntl.h和unistd.h中被定义。
至此源代码的大致思路已经完成,具体实现见上
对源代码中一些地方的说明:
1
UTMP_FILE在utmp.h中被定义:
#define UTMP_FILE _PATH_UTMP
而_PATH_UTMP在/usr/include/paths.h中被定义
#define _PATH_UTMP "/var/run/utmp"
所以说UTMP_FILE即为/var/run/utmp 此文件不是文本文件
2
在源代码中使用了ctime()是因为utbufp->ut_time的值是距离1970.1.1的秒数总和,是长整形,要把其转换为易读的时间格式。