Who命令可以显示登录系统的用户信息。
1、查看who命令相关内容
通过联机手册,可以查询到who命令的详解。在终端输入man who,在Ubuntu 14.04 系统上,在DESCRIPTION可以看到如下所示的内容。
即登录的信息是放在/var/run/utmp 、/var/log/wtmp中,运行who命令后,从utmp文件中读取信息。因此,我们继续查看utmp文件是什么。
2、查看utmp
运用man命令的关键词搜索功能,在终端输入man -k utmp, 可以看到以下内容。
我们可以看到utmp(5) 这一行与登录信息有关,接下来查看该部分。在终端输入man 5 utmp,在description处可以看到utmp的具体介绍。utmp中存放了一系列的结构体,并且声明在<utmp.h>头文件中。utmp中的数据结构如下图所示。
结构体中存放了用户名、tty、时间等信息。其中值得注意的是时间信息。为了将32位操作系统与64位操作系统保持一致,在这里通过一个宏定义来进行两种设置。我的操作系统是64位的,所以看64位处,即定义了一个ut_tv的结构体,里面包含了两个32位数,一个表示秒数,一个表示微妙数。unix中的时间表示是从1970年1月1日0时开始到所求时间所经过的秒数。所以我们还需要将秒数换算成时间,经过搜索,发现使用linux中的ctime()函数就可以实现。
3、函数一览表
函数名 | open |
目标 | 打开一个文件 |
头文件 | #include< fcntl.h > |
函数原型 | int fd = open( char* name, int how ) |
参数 | name 文件名 how O_REONLY, O_WRONLY, O_RDWR |
返回值 | -1 错误 int 成功返回文件描述符 |
函数名 | read |
目标 | 从文件把数据读取到缓冲区 |
头文件 | #include< unistd.h > |
函数原型 | ssize_t numread = read( int fd, void* buf, size_t qty ) |
参数 | fd 文件描述符 buf 目的缓冲区 要读取的字节数 |
返回值 | -1 错误 numread 读取的字节数 |
函数名 | close |
目标 | 关闭文件 |
头文件 | #include <unistd.h> |
函数原型 | int res = close( int fd ) |
参数 | fd 文件描述符 |
返回值 | -1 遇到错误 0 成功关闭 |
函数名 | ctime() |
目标 | 将秒数转换为时间 |
头文件 | #include <time.h> |
函数原型 | char* res = ctime( const time_t *timep) |
参数 | time_t (实际上是long int) |
返回值 | char * |
4、代码
#include <utmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
int show_info(struct utmp* utbuf);
void show_time(time_t);
int main(){
int fd = open(UTMP_FILE, O_RDONLY);
if( fd == -1){
perror( UTMP_FILE );
exit( 1 );
}
struct utmp cur_record;
int len = sizeof(cur_record);
while( read(fd, &cur_record, len) == len ){
show_info( &cur_record);
}
close(fd);
return 0;
}
int show_info(struct utmp* utbuf){
printf(" %-8.8s ", utbuf->ut_user); //登录名
printf(" ");
printf(" %-8.8s ", utbuf->ut_line);//tty
printf(" ");
//char* cp = ctime(&((utbuf->ut_tv).tv_sec));
time_t time = (utbuf->ut_tv).tv_sec;
show_time(time);
printf("\n");
return 0;
}
void show_time(time_t tm){
char* cp;
cp = ctime(&tm);
printf(" %20.20s", cp);
}