who命令实现

来源:互联网 发布:贵州省数据统计局 编辑:程序博客网 时间:2024/05/16 09:06

who命令实现

1.who命令

1.1who命令实践

在linux环境中使用who命令,可以打印当前登录系统中的用户。

root@ubuntu:~# whoye       tty7         2017-05-12 22:07 (:0)ye       pts/4        2017-06-04 13:40 (192.168.1.5)ye       pts/21       2017-06-04 13:55 (192.168.1.5)

1.2 who命令解释

WHO(1) User Commands NAME       who - show who is logged onSYNOPSIS       who [OPTION]... [ FILE | ARG1 ARG2 ]DESCRIPTION       Print information about users who are currently logged in.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命令查询的是一个/var/run/utmp文件来获取当前系统的登录用户信息。

2. utmp文件

  • utmp maintains a full accounting of the current status of the system, system boot time (used by uptime), recording user logins at which terminals, logouts, system events etc.
  • wtmp acts as a historical utmp
  • btmp records failed login attempts

linux下文件路径:

/var/run/utmp/var/log/wtmp/var/log/btmp

​ These files are not regular text files, but rather a binary format which needs to be edited by specially crafted programs. The implementation and the fields present in the file differ depending of the system or the libc version, and are defined in the utmp.h header file.

3. utmp.h文件

3.1 utmp结构体

#define UT_LINESIZE      32#define UT_NAMESIZE      32#define UT_HOSTSIZE     256struct exit_status {              /* Type for ut_exit, below */               short int e_termination;      /* Process termination status */               short int e_exit;             /* Process exit status */           };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 */           };  /* Backward compatibility hacks */#define ut_name ut_user#ifndef _NO_UT_TIME#define ut_time ut_tv.tv_sec#endif#define ut_xtime ut_tv.tv_sec#define ut_addr ut_addr_v6[0]

3.2 ut_type 值

​ 可根据此值变化判断某个登录用户是否活跃。

    /* Values for ut_type field, below */           #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 (see init(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 */    The first entries ever created result from init(1) processing inittab(5).  Before an entry is processed, though,init(1) cleans up utmp by setting ut_type to DEAD_PROCESS, clearing ut_user, ut_host, and ut_time with null  bytes for  each  record which ut_type is not DEAD_PROCESS or RUN_LVL and where no process with PID ut_pid exists.  If no empty record with the needed ut_id can be found, init(1) creates a new one.It  sets  ut_id  from  the  inittab,ut_pid and ut_time to the current values, and ut_type to INIT_PROCESS.    mingetty(8)  (or  agetty(8)) locates the entry by the PID, changes ut_type to LOGIN_PROCESS, changes ut_time, sets ut_line, and waits for connection to be established.    login(1), after  a  user  has  been  authenticated,  changes ut_type  to  USER_PROCESS, changes ut_time, and sets ut_host and ut_addr.  Depending on mingetty(8) (or agetty(8)) and login(1), records may be located by ut_line instead of the preferable ut_pid.    When init(1) finds that a process has exited, it locates its utmp entry by ut_pid, sets ut_type  to  DEAD_PROCESS,and clears ut_user, ut_host and ut_time with null bytes.

3.3 登录时间值

#define ut_time ut_tv.tv_sec其中:struct utmp ut;struct timeval tv;/* gettimeofday((struct timeval *) &ut.ut_tv, NULL); */gettimeofday(&tv, NULL);ut.ut_tv.tv_sec = tv.tv_sec;ut.ut_tv.tv_usec = tv.tv_usec;DESCRIPTION      The functions gettimeofday and settimeofday can get and set the time as      well as a timezone. The tv argument is a timeval struct, as specified      in <sys/time.h>:      struct timeval {            time_t       tv_sec;     /* seconds */            suseconds_t   tv_usec; /* microseconds */      };  time_t存的是197011000 秒算起至今的UTC时间所经过的秒数time_t是long int类型.

​ 想清晰得得到现在的年月日信息,就不能通过这个time_t了,需要用struct tm来显示,而将time_t和struct tm转换的函数就是localtime(time_t*),返回一个struct tm*类型,注意是指针类型。然后可以得到tm中的成员.

查询关于时间转换的函数:

root@ubuntu:/var/run# man -k time | grep transformasctime (3)          - transform date and time to broken-down time or ASCIIasctime_r (3)        - transform date and time to broken-down time or ASCIIctime (3)            - transform date and time to broken-down time or ASCIIctime_r (3)          - transform date and time to broken-down time or ASCIIgmtime (3)           - transform date and time to broken-down time or ASCIIgmtime_r (3)         - transform date and time to broken-down time or ASCIIlocaltime (3)        - transform date and time to broken-down time or ASCIIlocaltime_r (3)      - transform date and time to broken-down time or ASCIImktime (3)           - transform date and time to broken-down time or ASCIIroot@ubuntu:/var/run# man 3 localtime       #include <time.h>       struct tm *localtime(const time_t *timep);       struct tm *localtime_r(const time_t *timep, struct tm *result);        struct tm {          int tm_sec;      /* 秒 – 取值区间为[0,59] */          int tm_min;      /* 分 - 取值区间为[0,59] */          int tm_hour;      /* 时 - 取值区间为[0,23] */          int tm_mday;      /* 一个月中的日期 - 取值区间为[1,31] */          int tm_mon;      /* 月份(从一月开始,0代表一月) - 取值区间为[0,11] */          int tm_year;      /* 年份,其值等于实际年份减去1900 */          int tm_wday;      /* 星期 – 取值区间为[0,6],其中0代表星期天,1代表星期一,以此类推 */          int tm_yday;      /* 从每年的11日开始的天数 – 取值区间为[0,365],其中0代表11日,1代表12日        };

4 实例代码

/*who01.c文件*/#include <stdio.h>#include <utmp.h>#include <string.h>#include <time.h>/* 文件路径 */#define FILE_PATH "/var/run/utmp"#define SHOWHOST/*函数名称:show_info函数功能:打印登录用户信息输入参数:struct utmp *utmpfp输出参数:无备注:*/void show_info(struct utmp *utmpfp){    /* 时间值转换 */    time_t timelong = utmpfp->ut_time;    struct tm *localnow=localtime(&timelong);   /* 根据当前用户的状态值,判断是否为当前登录用户 */    if(utmpfp->ut_type == USER_PROCESS)    {        printf("%8s\t",utmpfp->ut_name);        printf("%12s\t",utmpfp->ut_line);        printf("%d-%d-%d %d:%d ",localnow->tm_year+1900,localnow->tm_mon+1,localnow->tm_mday,localnow->tm_hour,localnow->tm_min); //登录时间        #ifdef SHOWHOST            printf("(%s)",utmpfp->ut_host);        #endif          printf("\n");    }}/*函数名称:main()函数功能:主函数输入参数:无输出参数:无备注:*/int main(){    struct utmp current_record;    FILE *utmpfd = NULL;    int reclen = sizeof(current_record);    /* 打开登录信息记录文件 */    if((utmpfd = fopen(FILE_PATH,"r"))==NULL)    {        printf("file open error!\n");        return 0;    }       printf("file open success!\n");    memset(&current_record,0x00,reclen);    /*循环读取*/    while(fread(&current_record,sizeof(char),reclen,utmpfd)==reclen)    {        //read success        show_info(&current_record);        memset(&current_record,0x00,reclen);    }   /* 关闭文件 */    fclose(utmpfd);    return 0;}

程序测试:

root@ubuntu:/work/shell_cmd/1_code# gcc -g -Wall who01.c -o mainroot@ubuntu:/work/shell_cmd/1_code# ./mainfile open success!      ye            tty7    2017-5-12 22:7 (:0)      ye           pts/4    2017-6-4 13:40 (192.168.1.5)      ye          pts/21    2017-6-4 13:55 (192.168.1.5)
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 眼线笔没用完干了怎么办 新的眼线笔干了怎么办 不涂口红没气色怎么办 眼线笔容易晕妆怎么办 眼线笔老是晕妆怎么办 眼线液老是晕妆怎么办 旋转眼线笔断了怎么办 眼睛去皮以后眉眼距窄怎么办 速写型总是画不准怎么办 速写人物不会打形怎么办 鼻头又圆又大怎么办 耳鸣嘴溃疡眼流泪上火怎么办 孩子看电视总挤眼睛怎么办 小孩老是咳嗽有痰怎么办 长时间看手机眼睛模糊怎么办 长时间看电脑眼睛模糊怎么办 手机玩多了眼睛模糊怎么办 手机看多了眼睛模糊怎么办 孩子玩手机眼睛红怎么办 手机玩多了眼睛红怎么办 手机看久了眼花怎么办 玩手机眼睛近视了怎么办 近视了怎么办30个字 吃了长牙的土豆怎么办 鸡蛋和土豆吃了怎么办 狗狗眼睛流血水怎么办 石粉粘土干了怎么办 樱花针管笔干了怎么办 想学linux不会c语言怎么办 被摩托车排气管烫伤了怎么办 泡泡糖粘在衣服上怎么办 皮卡书屋办卡怎么办 照证件照齐刘海怎么办 哈挺机床卡刀了怎么办 绝地求生卡在登陆页面怎么办 白鞋子长霉了怎么办 幸福树树干烂了怎么办 花椒树树叶掉落枝干发黑怎么办 茉莉枝干变干了怎么办 冲风了头蒙怎么办 不小心把腰扭了怎么办