who命令
获取正在登录系统的用户
使用Linux的who命令
第一个参数book代表用户名,第二个参数tty7代表终端名,第三个参数代表时间,第四个参数代表用户的登录地址。
阅读手册
使用命令读手册
$ man who
可以知道who这个命令从 /var/run/utmp 和 /var/log/wtmp 两个文件中获取数据,
再通过命令,查找关于 “utmp” 的信息
$ man -k utmp
-k的意思是根据关键字查找
$man 5 utmp
我们查询到一些关于utmp结构体中的元素,比如ut_user用户名字、ut_line用户设备、ut_time登录时间等。
who命令的工作流程
打开utmp
+----> 读取记录 ------ +
| |
+-------显示记录 |
关闭utmp <------ +
who命令的编写---版本1
1 #include <stdio.h>
2 #include <utmp.h>
3 #include <fcntl.h>
4 #include <unistd.h>
5 #include <time.h>
6
7 void show_info(struct utmp *utbufp);
8 int main()
9 {
10 struct utmp current_record;
11 int utmp_fd;
12 int reclen = sizeof(current_record);
13
14 utmp_fd = open(UTMP_FILE,O_RDONLY);
15 if(utmp_fd == -1)
16 return -1;
17
18 while( read(utmp_fd, ¤t_record,reclen) == reclen )
19 show_info(¤t_record);
20
21 close(utmp_fd);
22 return 0;
23 }
24
25 void show_info(struct utmp *utbufp)
26 {
27
28 printf("%-8.8s",utbufp->ut_name);
29 printf(" ");
30 printf("%-8.8s",utbufp->ut_line);
31 printf(" ");
32 printf("%101d",utbufp->ut_time);
33 printf(" ");
34 printf("(%s)",utbufp->ut_host);
35 printf(" ");
36 printf("\n");
37 }
输出结果:
问题:
1. 有部分数据不是真实用户的。
2. 时间显示不对。
解决方法:
1.第一个问题
继续使用命令
$ man 5 utmp
看到 ut_type中 USER_PROCESS表示的是已经登录的用户 ,那么第一个问题就解决了。
2.第二个问题
使用命令
$ man -k time | grep transform
看到ctime,使用命令查看ctime的使用方法
$ man 3 ctime
使用这个函数将 timeval转换成一个字符串并返回一个指针,那么第二个问题也解决了。
who命令的编写---版本2
1 #include <stdio.h>
2 #include <utmp.h>
3 #include <fcntl.h>
4 #include <unistd.h>
5 #include <time.h>
6
7 void show_info(struct utmp *utbufp);
8 void show_time(long timeval);
9 int main()
10 {
11 struct utmp current_record;
12 int utmp_fd;
13 int reclen = sizeof(current_record);
14
15 utmp_fd = open(UTMP_FILE,O_RDONLY);
16 if(utmp_fd == -1)
17 return -1;
18
19 while( read(utmp_fd, ¤t_record,reclen) == reclen )
20 show_info(¤t_record);
21
22 close(utmp_fd);
23 return 0;
24 }
25
26 void show_info(struct utmp *utbufp)
27 {
28 if(utbufp->ut_type != USER_PROCESS)
29 return;
30
31 printf("%-8.8s",utbufp->ut_name);
32 printf(" ");
33 printf("%-8.8s",utbufp->ut_line);
34 printf(" ");
35 show_time(utbufp->ut_time);
36 printf(" ");
37 printf("(%s)",utbufp->ut_host);
38 printf("\n");
39 }
40
41 void show_time(long timeval)
42 {
43 char *cp;
44
45 cp = ctime(&timeval);
46
47 printf("%12.12s",cp+4);
48
49 }
输出结果:
这样一个简单的who命令就完成了。
------------------------------于2019/5/5更新---------------------
改良who命令
在Linux---cp命令中,介绍了有关缓冲区和系统开销的知识,因此,我们可以改良自己编写的who命令。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <utmp.h>
#define NRECS 16
#define NULLUT ((struct utmp*)NULL)
#define UTSIZE (sizeof(struct utmp))
static char utmpbuf[NRECS * UTSIZE];
static int num_recs;
static int cur_rec;
static int fd_utmp = -1;
struct utmp* utmp_next();
int utmp_reload();
int utmp_open(char *filename);
void utmp_close();
int utmp_open(char *filename)
{
fd_utmp = open(filename , O_RDONLY);
cur_rec = 0;
num_recs = 0;
return fd_utmp;
}
struct utmp* utmp_next()
{
struct utmp* recp;
if(fd_utmp == -1)
{
return NULLUT;
}
if(cur_rec == num_recs && utmp_reload() == 0)
{
return NULLUT;
}
recp = (struct utmp*) &utmpbuf[cur_rec * UTSIZE];
cur_rec++;
return recp;
}
int utmp_reload()
{
int aimt_read;
aimt_read = read(fd_utmp, utmpbuf, NRECS * UTSIZE);
num_recs = aimt_read / UTSIZE;
cur_rec = 0;
return num_recs;
}
void utmp_close()
{
if(fd_utmp != -1)
close(fd_utmp);
}
编写一个增大缓冲区的库,调用的次数减少到原来的1/16。这样程序能够在更短的时间内完成。
1 #include <stdio.h>
2 #include <utmp.h>
3 #include <fcntl.h>
4 #include <unistd.h>
5 #include <time.h>
6 #include <sys/types.h>
7 #include <stdlib.h>
8
9 void show_info(struct utmp *utbufp);
10 void show_time(long timeval);
11
12 #define SHOWHOST
13
14 int main()
15 {
16 struct utmp* utbufp , *utmp_next();
17 if( utmp_open(UTMP_FILE) == -1)
18 {
19 perror(UTMP_FILE);
20 exit(1);
21 }
22
23 while( (utbufp = utmp_next()) != ((struct utmp *)NULL))
24 show_info(utbufp);
25
26 utmp_close();
27 return 0;
28 }
29
30 void show_info(struct utmp *utbufp)
31 {
32 if(utbufp->ut_type != USER_PROCESS)
33 return;
34
35 printf("%-8.8s",utbufp->ut_name);
36 printf(" ");
37 printf("%-8.8s",utbufp->ut_line);
38 printf(" ");
39 show_time(utbufp->ut_time);
40 printf(" ");
41 printf("(%s)",utbufp->ut_host);
42 printf("\n");
43 }
44
45 void show_time(long timeval)
46 {
47 char *cp;
48
49 cp = ctime(&timeval);
50
51 printf("%12.12s",cp+4);
52
53 }
本篇笔记自拜读《 Unix/Linux编程实践教程》
我也推荐和我一样的初学者去拜读这本书,让你对linux有可下手的地方。
来源:oschina
链接:https://my.oschina.net/u/4289148/blog/3553310