当前位置:网站首页>编写自己的who命令
编写自己的who命令
2022-07-01 09:39:00 【全栈程序员站长】
大家好,又见面了,我是你们的朋友全栈君。
今天自己照着书一步步敲了who命令的实现。老外写的有些书就是不错,一步步启发你告诉你怎么思考,怎么根据已有的线索查询联机帮助,怎么一步步最终解决问题。真不错。 下面我就根据书上的思想,来回顾一下这将近2个小时的工作。
1.who命令能做什么2.who命令是怎么工作的3.怎样编写who命令
1.who命令能做什么
我们可以在命令行下输入who命令,结果如下:[email protected]:~ whocaoli tty2 2010-11-23 15:41caoli tty7 2010-11-23 15:30 (:0)caoli pts/0 2010-11-23 16:12 (:0.0)caoli pts/1 2010-11-23 16:51 (:0.0)[email protected]:~
通过联机帮助 man who
: Print information about users who are currently logged in.
who可以显示出当前系统中已经登录的用户的信息。 可以大概知道who的作用以及对它的描述和使用的一些选项等。。。。
2.who命令是怎么工作的 step1: 根据man who中: If FILE is not specified, use /var/run/utmp.
可以知道who是从/var/run/utmp中获得用户登录信息的。
step2: 现在我们知道的是一个目录,下一步就是要找到跟他相关的信息。 man -k 选项可以根据关键字查找。 所以man -k utmp 就能找到utmp(4) 的相关信息,:::我是直接man utmp的。
step3: 再来查看utmp里的详细信息: more /usr/include/utmp.h 这时候,我们会发现utmp里面保存的是结构数组。记录的用户登录的相关信息。
step4: 根据以上步骤可以推测who的工作原理: 把记录有用户登录信息的文件里的内容一条条读出。我们接着就可以根据这个思想来实现了。
3.怎样编写who命令 关键点:如何从文件里读取数据结构 这里就要用到一些文件操作相关的知识了 (这里要说的是系统调用和大一时学到的fopen等等不是一回事,其实个人觉得功能差不多)
接着我们就开始编码把 主函数部分: #include <utmp.h> #include <stdio.h> #include <fcntl.h> #include <unistd.h>
#define SHOWHOST void show_info(struct utmp *utbufp);
int main(int argc, char** argv) { struct utmp current_record;//一个缓冲区 int utmpfd; //文件描述符 int reclen=sizeof(current_record); if((utmpfd=open(UTMP_FILE,O_RDONLY))==-1) { perror(UTMP_FILE); return 1; } while(read(utmpfd,¤t_record,reclen)==reclen) show_info(¤t_record); //显示utmp的内容 close(utmpfd); return 0; }
显示登录信息部分: void show_info(struct utmp *utbufp) { if(utbufp->ut_type!=USER_PROCESS) // 清除空白记录 return; printf(“%-8.8s/t”,utbufp->ut_name); printf(“%-8.8s/t”,utbufp->ut_line); // printf(“%10ld/t”,utbufp->ut_time); show_time(utbufp->ut_time); #ifdef SHOWHOST if(utbufp->ut_host[0]!=’/0′) printf(“(%s)”,utbufp->ut_host); #endif printf(“/n”); } 运行结果: [email protected]:~/workspace/test$ ./who1 reboot ~ 1290497376 (2.6.32-26-generic) runlevel ~ 1290497376 (2.6.32-26-generic) LOGIN tty4 1290497376 () LOGIN tty5 1290497376 () caoli tty2 1290498098 () LOGIN tty3 1290497376 () LOGIN tty6 1290497376 () LOGIN tty1 1290497384 () caoli tty7 1290497409 (:0) caoli pts/0 1290499920 (:0.0) caoli pts/1 1290501832 (:0.0) caoli pts/2 1290501833 () caoli pts/1 1290502298 (:0.0) caoli pts/2 1290506795 (:0.0) 这里的结果跟上面一开始who命令的结果做个比较,我们会发现 一,我们要过滤掉不是用户的名字二,要正确的显示时间三,不需要显示主机名的可以省略
根据第1点:做出改动如下 utmp结构体中有一项是ut_type,当他的值为7时,表示是一个已经登录的用户,所以可以对显示函数show_info中的显示用户稍作修改 void show_info(struct utmp *utbufp)utmp { if(utbufp->ut_type!=USER_PROCESS) // 清除空白记录 return; printf(“%-8.8s/t”,utbufp->ut_name);
根据第2点:我们根据time.h中的内容做改动,关于时间函数方面的内容,我已经在Linux程序设计第4章中学习过了,所以这里我就直接跳过去了。 ctime(##)中需要一个指向time_t的指针。返回的时间字符串类似下面 Wed Jun 30 21:49:09 1993/n 我们要从4位开始输出12个字符 printf(“%12.12s”,ctime(&t)+4); 所以添加show_time函数如下 void show_time(long timeval) { char *cp; cp=ctime(&timeval); printf(“%12.12s”,cp+4); } 注意ctime是在time.h里面的。所以程序开头部分要添加头文件。
第3点 这里有个预处理的定义,我不太懂,哥要是看到了,就评论一下呗! if(utbufp->ut_host[0]!=’/0′) printf(“(%s)”,utbufp->ut_host);
最后的代码如下:
#include <utmp.h>#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <time.h>#define SHOWHOST void show_info(struct utmp *utbufp);void show_time(long);int main(int argc, char** argv){struct utmp current_record;//一个缓冲区int utmpfd; //文件描述符int reclen=sizeof(current_record);if((utmpfd=open(UTMP_FILE,O_RDONLY))==-1){perror(UTMP_FILE);return 1;}while(read(utmpfd,¤t_record,reclen)==reclen) show_info(¤t_record); //显示utmp的内容close(utmpfd);return 0;}void show_info(struct utmp *utbufp){ if(utbufp->ut_type!=USER_PROCESS) // 清除空白记录 return; printf(“%-8.8s/t”,utbufp->ut_name);printf(“%-8.8s/t”,utbufp->ut_line);show_time(utbufp->ut_time);#ifdef SHOWHOST if(utbufp->ut_host[0]!=’/0′) printf(“(%s)”,utbufp->ut_host);#endifprintf(“/n”);}void show_time(long timeval){char *cp;cp=ctime(&timeval);printf(“%12.12s”,cp+4);}
结果如下: [email protected]:~/workspace/test$ ./who1 caoli tty2 Nov 23 15:41 caoli tty7 Nov 23 15:30(:0) caoli pts/0 Nov 23 16:12(:0.0) caoli pts/1 Nov 23 16:51(:0.0) 到这里,已经跟原始的who命令相差无几了,哈哈。
通过这次实践,我最大的收获就是不能什么事都问别人,能自己找答案的就尽量自己找,这也是一种能力。 在这方面,我觉得老公做的很好,崇拜他一下! 好哥,向你致敬。 爱你的老婆。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/131751.html原文链接:https://javaforall.cn
边栏推荐
- Concept of digital currency
- Computer USB, HDMI, DP various interfaces and speeds
- JS原型链
- 新数据库时代,不要只学 Oracle、MySQL
- Niuke monthly race 22- collect pieces of paper
- Swift control encapsulation - paging controller
- Dotnet console uses microsoft Maui. Getting started with graphics and skia
- Huawei accounts work together at multiple ends to create a better internet life
- Solution of EPS image blur by latex insertion
- Win11账号被锁定无法登录怎么办?Win11账号被锁定无法登录
猜你喜欢

JS scope chain and closure

IPv6 learning notes

电脑USB、HDMI、DP各种接口及速度

Who has the vision to cross the cycle?

Upload labs for file upload - white box audit

奇怪,为什么ArrayList初始化容量大小为10?

scratch大鱼吃小鱼 电子学会图形化编程scratch等级考试二级真题和答案解析2022年6月

苹果放大招!这件事干的太漂亮了……

Meituan P4 carefully collated microservice system architecture design manual to see the world of microservice architecture

Construction of esp8266 FreeRTOS development environment
随机推荐
SQL学习笔记(02)——数据库表操作
Swift control encapsulation - paging controller
那个程序员,被打了。
Sd-wan notes
CSDN一站式云服务开放内测,诚邀新老用户来抢鲜
全球基金和资管的股票建仓率达到15年内新低
js原型继承仅可继承实例而非构造器
Nacos service configuration and persistence configuration
PHP code audit and File Inclusion Vulnerability
利用闭包实现私有变量
Implementation and application of queue
【leetcode】287. Find duplicates
持续进阶,软通动力稳步推动云智能战略
富文本实现插值
直播管理项目
Unity tips for reducing the amount of code -- empty protection extension
7-Zip 遭抵制?呼吁者定下“三宗罪”:伪开源、不安全、作者来自俄罗斯!
SDN_ Simple summary
Network counting 01 physical layer
What is P in cap theory