实现who

还是按照问题一步一步的展开

1. who能做什么

2. who怎样工作的

3. 如何实现who

 

1. who能做什么

  在linux中who就是显示谁在使用系统。

2. who怎样工作的:

  直接man who,可以看到如下的描述

If FILE is not specified, use /var/run/utmp.  /var/log/wtmp as FILE  is
       common.   If  ARG1  ARG2  given, -m presumed: 'am i' or 'mom likes' are
       usual.

可以看到who是从utmp获取信息的, 收索联机帮助 寻找utmp

man -k  utmp

utmp (5)             - login records

直接man 5 utmp

 The  file  is  a  sequence  of  utmp structures, declared as follows in
       <utmp.h> (note that this is only one  of  several  definitions  around;
       details depend on the version of libc):
... ...
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 */
               struct  exit_status ut_exit;  /* Exit status of a process
                                                marked as DEAD_PROCESS; not
                                                used by Linux init (1 */
               /* The ut_session and ut_tv fields must be the same size when
                  compiled 32- and 64-bit.  This allows data files and shared
                  memory to be shared between 32- and 64-bit applications. */
           #if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
               int32_t ut_session;           /* Session ID (getsid(2)),
                                                used for windowing */
               struct {
                   int32_t tv_sec;           /* Seconds */
                   int32_t tv_usec;          /* Microseconds */
               } ut_tv;                      /* Time entry was made */
           #else
                long   ut_session;           /* Session ID */
                struct timeval ut_tv;        /* Time entry was made */
           #endif

               int32_t ut_addr_v6[4];        /* Internet address of remote
                                                host; IPv4 address uses

可以看到数据都放在utmp中.继续往下可以看到文件的位置信息

FILES
       /var/run/utmp
       /var/log/wtmp

 

3. 如何实现who

到这里基本上就可以开始用伪代码编写了:

伪代码如下:

  打开utmp

  读取用户记录

  显示用户记录

  关闭utmp

 

因为这次读取是直接读取数据块,一行一行(fgets)和一个字符一个字符(getchar)的读取都不合适,所以选用read函数。

第一步自然是打开utmp,这个文件的路径在哪里呢, 头文件一般都是放在/USR/INCLUDE/下的,果然在头文件中找到路径的定义:

/* Compatibility names for the strings of the canonical file names.  */
#define UTMP_FILE        _PATH_UTMP
#define UTMP_FILENAME    _PATH_UTMP
#define WTMP_FILE        _PATH_WTMP
#define WTMP_FILENAME    _PATH_WTMP

可以随便选一个,我们就选第一个作为路径。按照伪代码编写如下

#include <stdio.h>
#include <utmp.h>
#include <fcntl.h>
#include <unistd.h>

void ShowRecord(struct utmp*);

int main(int ac, char* av[]){

    struct utmp record;
    int recordSize = sizeof(record);
    int utmpFd;

    //打开utmp
    utmpFd = open(UTMP_FILE,O_RDONLY);
    if(-1 == utmpFd) {
        perror(UTMP_FILE);
        return -1;
    }

    //读取用户记录
    while (read(utmpFd,&record,recordSize) == recordSize) {
       //显示用户记录
        ShowRecord(&record);
    }

    //关闭utmp
    close(utmpFd);
    return 0;
}

void ShowRecord(struct utmp* pRecord){
    printf("%-8.8s\n",pRecord->ut_name);
    printf("%-8.8s\n",pRecord->ut_line);
    printf("%-8.8d\n",pRecord->ut_time);
    printf("\n");
}

运行结果:

jerry@ubuntu:~/work/chapter01$ ./test 
reboot  
~       
1492427813

LOGIN   
tty1    
1492427835

runlevel
~       
1492427839

jerry   
tty7    
1492427909

jerry@ubuntu:~/work/chapter01$ 

数据读出来了,就是显示格式需要再调整。继续进行优化如下问题,今天就到这里

 1. 格式排版问题

 2. 时间显示问题

 

posted @ 2017-04-17 20:52  xwqaz  阅读(212)  评论(0编辑  收藏  举报