编写自己的who命令

编写自己的who命令
今天自己照着书一步步敲了who命令的实现。老外写的有些书就是不错,一步步启发你告诉你怎么思考,怎么根据已有的线索查询联机帮助,怎么一步步最终解决问题。真不错。
下面我就根据书上的思想,来回顾一下这将近2个小时的工作。

1.who命令能

大家好,又见面了,我是你们的朋友全栈君。

今天自己照着书一步步敲了who命令的实现。老外写的有些书就是不错,一步步启发你告诉你怎么思考,怎么根据已有的线索查询联机帮助,怎么一步步最终解决问题。真不错。
下面我就根据书上的思想,来回顾一下这将近2个小时的工作。

1.who命令能做什么
2.who命令是怎么工作的
3.怎样编写who命令

1.who命令能做什么

我们可以在命令行下输入who命令,结果如下:
caoli@caoli-laptop:~$ who
caoli    tty2         2010-11-23 15:41
caoli    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)
caoli@caoli-laptop:~$

通过联机帮助
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,&current_record,reclen)==reclen)
        show_info(&current_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”);
}


运行结果:
caoli@caoli-laptop:~/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);

最后的代码如下:

结果如下:
caoli@caoli-laptop:~/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.net/131751.html原文链接:https://javaforall.net

(0)
上一篇 2022年6月11日 下午10:16
下一篇 2022年6月11日 下午10:16


相关推荐

  • HorizontalScrollView

    HorizontalScrollView一、概述、水平滚动条可以左右滑动可与ViewPager协同使用二、HorizontalScrollView里边只能放一个子元素可以放一个Layout布局对象来盛放多个元素里边可以设置指示器

    2022年7月1日
    29
  • JS中height、clientHeight、scrollHeight、offsetHeight区别

    JS中height、clientHeight、scrollHeight、offsetHeight区别我们来实现test中的onclick事件  functionjustAtest()    {       vartest= document.getElementById(“test”);       vartest2=document.getElementById(“test2”)       vartest3=document.getElementB

    2022年7月23日
    16
  • Servlet的生命周期

    Servlet的生命周期Servlet 的生命周期 servlet 的生命周期就是从 servlet 出现到销毁的全过程 主要分为以下几个阶段 加载类 gt 实例化 为对象分配空间 gt 初始化 为对象的属性赋值 gt 请求处理 服务阶段 gt 销毁服务器启动时 web xml 中配置 load on startup 1 默认为 0 或者第一次请求该 servlet 时 就会初始化一个 Servlet 对象 也就是会执行初始

    2026年3月20日
    2
  • django-redis_redis缓存使用场景

    django-redis_redis缓存使用场景前言动态网站的基本权衡是,它们是动态的。每次用户请求页面时,Web服务器都会进行各种计算-从数据库查询到模板呈现再到业务逻辑-以创建站点访问者看到的页面。从处理开销的角度来看,这比标准的文件

    2022年7月30日
    12
  • 计算机基本配置清单表3500,3500元电脑配置清单

    计算机基本配置清单表3500,3500元电脑配置清单3500元电脑配置清单很多游戏发烧友在攒机时搭配了高效能的硬件,可以获得更加畅爽的游戏体验,不过对于普通的用户来说,高性价比的主机就可以满足日常影音及娱乐使用需求,更加亲民的价格也是吸引更多用户的基础,下面我们就为您推荐3500元价位的主机配置,追求性价比的朋友不妨看看。我们首先选择英特尔的i3-4170处理器,这款CPU基于Haswell架构设计,22nm制程,双核心四线程,主频为3.7GHz,…

    2022年7月27日
    10
  • centos7安装python 3.7_python安装后如何使用

    centos7安装python 3.7_python安装后如何使用文章目录什么是EPEL更新一下yum:安装EPEL:安装python3使用python3什么是EPELRHEL以及他的衍生发行版如CentOS、ScientificLinux为了稳定,官方的rpmrepository提供的rpm包往往是很滞后的,当然了,这样做这是无可厚非的,毕竟这是服务器版本,安全稳定是重点,官方的rpmrepository提供的rpm包也不够丰富,很多时候需要自己编译那太辛苦了,而EPEL恰恰可以解决这两方面的问题。什么是EPEL?EPEL的全称叫ExtraPackag

    2026年3月10日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号