Linux编程实践Day2

关于命令who

解决windows下wsl中输入who没有任何反应的问题

命令也是程序

在Unix系统中增加新的命令是一件很容易的事,把程序的可执行文件放到以下任意一个目录即可:/bin,/usr/bin,/usr/local/bin

问题1:who命令可以做什么

Linux系统中了解一个命令最好的方法便是使用man命令,例如man who

Unix联机帮助分为很多节,如第1小节中是关于用户命令的帮助,第2小节是关于系统调用的帮助,第5小节是关于配置文件的帮助

问题2:who命令是如何工作的

  1. 从Unix中学习Unix
  • 阅读联机帮助
  • 搜索联机帮助
  • 阅读.h文件
  • 从(SEE ALSO)得到启示
  1. 阅读联机帮助
    通过阅读who的联机帮助可知,who命令本质上通过输出/var/run/utmp文件来实现(不同系统文件夹可能不同) 在Linux系统中,通常使用系统调用函数来实现打开文件,具体可以通过man open等命令查询
  2. utmp部分结构
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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 */
    }

问题3:如何编写who

采用缓冲机制的who命令实现
执行命令gcc mywho.c utmpcache.c -o mywho
代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// mywho.c
#include <stdio.h>
#include <utmp.h>
#include <sys/types.h>
#include "utmpcache.h"
#include <time.h>

void ShowInfo(struct utmp *utmp_buf){
if(utmp_buf->ut_type != USER_PROCESS) // USER_PROCESS表示已登录
return;
printf("%-8.8s",utmp_buf->ut_name);
printf(" ");
printf("%-8.8s",utmp_buf->ut_line);
printf(" ");
char *ct = ctime(&utmp_buf->ut_time);
printf("%12.12s", ct + 4);
printf("\n");
}

int main(){
struct utmp *utmp_buf;
if(UtmpOpen(UTMP_FILENAME) == -1){
perror("Error");
}
while((utmp_buf = NextUtmp()) != NULL)
ShowInfo(utmp_buf);
UtmpClose();
return 0;
}
//utmpcache.c
#include <stdio.h>
#include <utmp.h>
#include "utmpcache.h"
#include <unistd.h>

#define UTSIZE (sizeof(struct utmp))
#define BFCNT 16
int cur = 0;
int cur_sav = 0;

char utmp_buf[BFCNT * UTSIZE]; //缓存从utmp文件读入的信息
int fd;

int UtmpOpen(char *filename){
fd = open(filename,"O_RDONLY");
return fd;
}

struct utmp *NextUtmp(){
if(cur == cur_sav && UtmpReload() == 0)
return NULL;
struct utmp *recv = (struct utmp *)&utmp_buf[cur * UTSIZE];
cur ++;
return recv;
}

int UtmpReload(){
int recv_bytes = read(fd, utmp_buf, BFCNT * UTSIZE);
cur_sav = recv_bytes / UTSIZE;
cur = 0;
return cur_sav;
}

void UtmpClose(){
if(fd != -1)
close(fd);
}
//utmpcache.h
#ifndef UTMP_CACHE_H
#define UTMP_CACHE_H

#include<utmp.h>

int UtmpOpen(char *filename);

struct utmp *NextUtmp();

int UtmpReload();

void UtmpClose();

#endif

运行结果:
不幸的是,本机的wsl环境似乎有点问题,反正我不知道为什么,本机的login似乎会先让lrx用户登录,然后再登录另一个用户,(完全不知道为什么好么)如果谁有想法的话非常感谢555


Linux编程实践Day2
http://bugeater.space/2023/09/06/Linux编程实践Day2/
Author
BugEater
Posted on
September 6, 2023
Licensed under