• 用系统调用实现who命令——mywho


    查看who命令的功能

    使用man who查看详细内容

    可以看到,who命令用于显示目前登录系统的用户信息。

    输入man -k utmp,可以看到

    输入man utmp,可以看到utmp的结构

    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
                                                    just ut_addr_v6[0] */
                   char __unused[20];            /* Reserved for future use */
               };

    这是utmp结构体的定义,从注释中可以了解到:ut_line保存设备名,即用户的终端类型;ut_user保存登录名;ut_host保存用户用于登录的远程计算机的名字;用户的登录时间被保存在ut_tv结构体中。

    who的原理便是读取/var/run/utmp部分文件内容,输出到屏幕。

    编写mywho

    #include <stdio.h>
    #include <stdlib.h>
    #include <utmp.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <time.h>
    #define SHOWOST
    void showinfo(struct utmp *utbufp);
    long showtime(long timeval);
    int main()
    {
            struct utmp current_record;
            int utmpfd;
            int reclen = sizeof(current_record);
            if((utmpfd = open(UTMP_FILE,O_RDONLY))==-1)
            {
                    perror(UTMP_FILE);
                    exit(1);
            }
            while (read(utmpfd,&current_record,reclen)==reclen)
                    showinfo(&current_record);
            close(utmpfd);
            return 0;
    }
    void showinfo(struct utmp *utbufp){
            if(utbufp->ut_type!=USER_PROCESS)
                    return;
            else{
                    printf("%-8.8s",utbufp->ut_name);
                    printf(" ");
                    printf("%-8.8s",utbufp->ut_line);
                    printf(" ");
                    showtime(utbufp->ut_time);
                    printf(" ");
                    printf("(%s)",utbufp->ut_host);
                    printf("\n");
            }
    }
    long showtime(long timeval)
    {
            struct tm *cp;
            cp = gmtime(&timeval);
            printf("    ");
            printf("%d-%d-%d %d:%d ",cp->tm_year+1900,cp->tm_mon+1,cp->tm_mday,(cp->tm_hour+8)%24,cp->tm_min);
    }

    main函数

    main函数使用系统调用open,read,close对utmp文件进行操作

    showinfo函数

    用来保存数据的结构体中数据不断读出,但是在utmp中,系统对每种用户都给了标示符:

    #define EMPTY         0 /* Record does not contain valid info (formerly known as UT_UNKNOWN on Linux) */
    #define RUN_LVL       1 /* Change in system run-level (seeinit(8)) */
    #define BOOT_TIME     2 /* Time of system boot (in ut_tv) */
    #define NEW_TIME      3 /* Time after system clock change (in ut_tv) */
    #define OLD_TIME      4 /* Time before system clock change (in ut_tv) */
    #define INIT_PROCESS  5 /* Process spawned by init(8) */
    #define LOGIN_PROCESS 6 /* Session leader process for user login */
    #define USER_PROCESS  7 /* Normal process */
    #define DEAD_PROCESS  8 /* Terminated process */
    #define ACCOUNTING    9 /* Not implemented */

    而我们需要打印的是标识符为7的USER_PROCESS

    showtime函数

    我调用了头文件time.h,其中的储存时间的结构体内容如下所示:

    struct tm {
        int tm_sec;    /* Seconds (0-60) */
        int tm_min;    /* Minutes (0-59) */
        int tm_hour;   /* Hours (0-23) */
        int tm_mday;   /* Day of the month (1-31) */
        int tm_mon;    /* Month (0-11) */
        int tm_year;   /* Year - 1900 */
        int tm_wday;   /* Day of the week (0-6, Sunday = 0) */
        int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */
        int tm_isdst;  /* Daylight saving time */
    };

    utbufp->ut_time是一个时间数据,其储存的是从1970年1月1日0:00开始到现在所经过的秒数。

    通过gmtime可以将这个数据转换为结构体tm。

    但是需要注意的是tm结构体中tm_year年份数值是减去了1900年,所以输出时需要加上1900。

    printf("%d-%d-%d %d:%d ",cp->tm_year+1900,cp->tm_mon+1,cp->tm_mday,(cp->tm_hour+8)%24,cp->tm_min);

    最终结果

  • 相关阅读:
    利用“Java同包同名类执行顺序”取消Java 网站应用程序Licence验证
    “Nested exception: 前言中不允许有内容"错误处理
    服务器日志文件Web远程查看
    Sql Server性能定位及改善
    eHR自动同步获取LDAP中的邮箱地址
    SQL Server中调用WebService
    大数据自学6-Hue集成环境操作Hbase
    大数据自学5-Python操作Hbase
    大数据自学4-Hue集成环境中各模组说明
    大数据自学3-Windows客户端DbVisualizer/SQuirreL配置连接hive
  • 原文地址:https://www.cnblogs.com/20201212ycy/p/16777042.html
Copyright © 2020-2023  润新知