当前位置:网站首页>编写自己的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
边栏推荐
- uniapp微信小程序组件按需引入
- Tree structure --- binary tree 1
- Hololens2 development -6-eyetracking and speech recognition
- Error org apache. catalina. core. StandardContext. FilterStart start filter exception
- Cortex M4 systick details
- CSDN's one-stop cloud service is open for internal testing, and new and old users are sincerely invited to grab the fresh
- delete和delete[]引发的问题
- 架构实战营 模块九:设计电商秒杀系统
- 7-Zip boycotted? The callers have committed "three crimes": pseudo open source, unsafe, and the author is from Russia!
- Packetdrill script analysis guide
猜你喜欢
JS prototype chain
那个程序员,被打了。
直播管理项目
嵌入式开发用到的一些工具
【无标题】
PR training notes
Dotnet console uses microsoft Maui. Getting started with graphics and skia
Precautions for lvgl v8.2 string display on keil MDK (take little bear pie as an example)
Network counting 01 physical layer
Swift control encapsulation - paging controller
随机推荐
Introduction to mt7628k eCos development
数据中台咋就从“小甜甜”变成了“牛夫人”?
A 419 error occurred in the laravel postman submission form. July 6th, 2020 diary.
Dotnet console uses microsoft Maui. Getting started with graphics and skia
Problems caused by delete and delete[]
Exception handling of classes in C #
历史上的今天:九十年代末的半导体大战;冯·诺依曼发表第一份草案;CBS 收购 CNET...
Click the screen with your finger to simulate F11 and enter the full screen
JS use toString to distinguish between object and array
闭包实现迭代器效果
Strange, why is the ArrayList initialization capacity size 10?
Using closures to implement private variables
LeetCode 344. Reverse string
MT7628K eCos开发入门
Learning practice: comprehensive application of cycle and branch structure (II)
Dspic30f6014a LCD block display
Get the list of a column in phpexcel get the letters of a column
架构实战营 毕业总结
Weidongshan board compilation kernel problem solving
Sd-wan notes