Linux---who命令学习

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, &current_record,reclen) == reclen )
19      show_info(&current_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("
");
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, &current_record,reclen) == reclen )
20      show_info(&current_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("
");
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("
");
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有可下手的地方。

原文地址:https://www.cnblogs.com/r1chie/p/10797216.html