当前位置:网站首页>编写自己的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
边栏推荐
猜你喜欢

Computer USB, HDMI, DP various interfaces and speeds

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

Nacos service configuration and persistence configuration

uniapp微信小程序组件按需引入

dsPIC30F6014a LCD 方块显示

硬件中台项目

CSDN's one-stop cloud service is open for internal testing, and new and old users are sincerely invited to grab the fresh

【无标题】

Win11账号被锁定无法登录怎么办?Win11账号被锁定无法登录

樹結構---二叉樹2非遞歸遍曆
随机推荐
JS functionarguments object
Wechat applet WebView prohibits page scrolling without affecting the implementation of overflow scrolling in the business
4hutool实战:DateUtil-格式化时间[通俗易懂]
Introduction to mt7628k eCos development
High precision factorial
手指点击屏幕就模拟进入F11进入全屏
数据中台咋就从“小甜甜”变成了“牛夫人”?
Computer USB, HDMI, DP various interfaces and speeds
JS use toString to distinguish between object and array
项目采购管理
PHP 字符串与二进制相互转换
[unity rendering] customized screen post-processing
短路运算符惰性求值
Hololens2 development -6-eyetracking and speech recognition
SQL learning notes (02) - database table operation
MapReduce programming basics
tensorrt yolov5_ trt. Py comments
Network partition notes
2022.02.15_ Daily question leetcode six hundred and ninety
BSN长话短说之十:如何保证NFT的安全