utmp和wtmp文件

 /var/run/utmp   --  database of currently logged-in users
 /var/log/wtmp  --  database of past user logins

utmp文件中保存的是当前正在本系统中的用户的信息。
wtmp文件中保存的是登录过本系统的用户的信息。

他们保存的信息是基于下面的结构体 struct utmp的(/usr/include/bits/utmp.h):

  1. /* The structure describing the status of a terminated process. This
  2.    type is used in `struct utmp' below. */
  3. struct exit_status
  4. {
  5.     short int e_termination;  /* Process termination status. */
  6.     short int e_exit;         /* Process exit status. */
  7. };


  8. /* The structure describing an entry in the user accounting database. */
  9. struct utmp
  10. {
  11.   short int ut_type;          /* Type of login. */
  12.   pid_t ut_pid;               /* Process ID of login process. */
  13.   char ut_line[UT_LINESIZE];  /* Devicename. */
  14.   char ut_id[4];              /* Inittab ID. */
  15.   char ut_user[UT_NAMESIZE];  /* Username. */
  16.   char ut_host[UT_HOSTSIZE];  /* Hostname for remote login. */
  17.   struct exit_status ut_exit; /* Exit status of a process marked as DEAD_PROCESS. */

  18. /* The ut_session and ut_tv fields must be the same size when compiled
  19.    32- and 64-bit. This allows data files and shared memory to be
  20.    shared between 32- and 64-bit applications. */

  21. #if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
  22.   int32_t ut_session;         /* Session ID, used for windowing. */
  23.   struct
  24.   {
  25.     int32_t tv_sec;           /* Seconds. */
  26.     int32_t tv_usec;          /* Microseconds. */
  27.   } ut_tv;                    /* Time entry was made. */
  28. #else
  29.   long int ut_session;        /* Session ID, used for windowing. */
  30.   struct timeval ut_tv;       /* Time entry was made. */
  31. #endif

  32.   int32_t ut_addr_v6[4];      /* Internet address of remote host. */
  33.   char __unused[20];          /* Reserved for future use. */
  34. };

/*  Values for the `ut_type' field of a `struct utmp'.   */
#define EMPTY           0       /* No valid user accounting information.  */

#define RUN_LVL         1       /* The system's runlevel.  */
#define BOOT_TIME       2       /* Time of system boot.   */
#define NEW_TIME        3       /* Time after system clock changed.   */
#define OLD_TIME        4       /* Time when system clock changed.   */

#define INIT_PROCESS    5       /* Process spawned by the init process.   */
#define LOGIN_PROCESS   6       /* Session leader of a logged in user.   */
#define USER_PROCESS    7       /* Normal process.   */
#define DEAD_PROCESS    8       /* Terminated process.   */

#define ACCOUNTING      9

而读取和修改这些文件的函数如下:
  1. #include <utmp.h>

  2. struct utmp *getutent(void);
  3. struct utmp *getutid(struct utmp *ut);
  4. struct utmp *getutline(struct utmp *ut);

  5. struct utmp *pututline(struct utmp *ut);

  6. void setutent(void);
  7. void endutent(void);

  8. int utmpname(const char *file);
utmpname()函数设定utmp文件所在的路径,默认的路径为宏 _PATH_UTMP,该宏定义在/usr/include/paths.h中:
  1. #define _PATH_UTMP "/var/run/utmp"
setutent()函数打开文件utmp,并且将文件指针指向文件的最开始。
getutent()函数从文件utmp中,每次读取一个struct utmp的结构体。读取失败返回NULL。
endutent()函数关闭文件utmp。
pututline()函数将一个struct utmp结构体写进文件utmp中。

下面根据这些知识写一个模仿Linux下的who命令的小程序。
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <utmp.h>
  4. #include <time.h>

  5. int main()
  6. {
  7.         struct utmp *p_utent;
  8.         long t;

  9.         setutent(); /* rewinds the file pointer to the beginning of the utmp file */
  10.         while((p_utent = getutent()) != NULL){
  11.                 if(p_utent->ut_type != USER_PROCESS)
  12.                         continue;
  13.                 printf("%s\t", p_utent->ut_user);
  14.                 printf("%s\t", p_utent->ut_line);
  15.                 t = p_utent->ut_tv.tv_sec;
  16.                 printf("%.20s\t", ctime(&t) + 4);
  17.                 printf("(%s)\n", p_utent->ut_host);

  18.         }
  19.         endutent(); /* closes the utmp file. */

  20.         return 0;
  21. }
运行结果:
digdeep@ubuntu:~/uulp$ ./who2
digdeep tty7 Sep 15 15:24:54 2011 (:0)
digdeep pts/0 Sep 15 15:25:14 2011 (:0.0)
digdeep pts/1 Sep 15 16:06:24 2011 (:0.0)
digdeep pts/2 Sep 15 16:07:21 2011 (:0.0)
digdeep pts/3 Sep 15 16:10:41 2011 (:0.0)

在上面的程序中增加一条语句,就可以读取曾经登录过本系统的用户信息:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <utmp.h>
  4. #include <time.h>

  5. int main()
  6. {
  7.         struct utmp *p_utent;
  8.         long t;

  9.         utmpname(_PATH_WTMP); /* #define _PATH_WTMP "/var/log/wtmp" */

  10.         setutent(); /* rewinds the file pointer to the beginning of the utmp file */
  11.         while((p_utent = getutent()) != NULL){
  12.                 if(p_utent->ut_type != USER_PROCESS)
  13.                         continue;
  14.                 printf("%s\t", p_utent->ut_user);
  15.                 printf("%s\t", p_utent->ut_line);
  16.                 t = p_utent->ut_tv.tv_sec;
  17.                 printf("%.20s\t", ctime(&t) + 4);
  18.                 printf("(%s)\n", p_utent->ut_host);

  19.         }
  20.         endutent(); /* closes the utmp file. */

  21.         return 0;
  22. }
上面红色的语句就是新增的。
运行结果如下:
digdeep tty7 Sep  3 13:58:24 2011 (:0)
digdeep pts/0 Sep  3 13:58:30 2011 (:0.0)
digdeep tty7 Sep  3 22:00:31 2011 (:0)
digdeep pts/0 Sep  3 22:00:41 2011 (:0.0)
digdeep pts/1 Sep  3 22:13:42 2011 (:0.0)
digdeep tty7 Sep  4 15:19:10 2011 (:0)
digdeep pts/0 Sep  4 15:19:28 2011 (:0.0)
digdeep pts/1 Sep  4 15:19:51 2011 (:0.0)
digdeep tty7 Sep  5 10:31:59 2011 (:0)
digdeep pts/0 Sep  5 10:32:05 2011 (:0.0)
digdeep pts/1 Sep  5 14:47:23 2011 (:0.0)
digdeep pts/2 Sep  5 16:47:00 2011 (:0.0)
... ...
在上面哪些函数是非线程安全的,不可重入的,因为它们 将返回结果保存在一个static变量中,可以被后面相同的调用所覆盖。
对应可重入的版本如下:
  1. #define _GNU_SOURCE /* or _SVID_SOURCE or _BSD_SOURCE */
  2. #include <utmp.h>

  3. int getutent_r(struct utmp *ubuf, struct utmp **ubufp);
  4. int getutid_r(struct utmp *ut, struct utmp *ubuf, struct utmp **ubufp);
  5. int getutline_r(struct utmp *ut, struct utmp *ubuf, struct utmp **ubufp);







Linux中utmp结构定义如下:
structutmp
{
short int ut_type;                                        // 登录类型
pid_t ut_pid;                                               // login进程的pid
char ut_line[UT_LINE_SIZE];                   // 登录装置名,省略了"/dev/"
char ut_id[4];                                 // Inittab ID
char ut_user[UT_NAMESIZE];                // 登录账号
char ut_host[UT_HOSTSIZE];                 // 登录账号的远程主机名称
struct exit_status ut_exit;                      // 当类型为DEAD_PROCESS时进程的结束状态
long int ut_session;                      // SessionID
struct timeval ut_tv;                               // 时间记录
int32_t ut_addr_v6[4];                          // 远程主机的网络地址
char __unused[20];                                // 保留未使用
};
ut_type有以下几种类型:
EMPTY
此为空的记录
RUN_LVL
记录系统run-level的改变
BOOT_TIME
记录系统开机时间
NEW_TIME
记录系统时间改变后的时间
OLD_TIME
记录当改变系统时间时的时间
INIT_PROCESS
记录一个由init衍生出来的进程
LOGIN_PROCESS
记录login进程
USER_PROCESS
记录一般进程
DEAD_PROSESS
记录一结束的进程
ACCOUNTING
目前尚未被使用
exit_status结构定义:
structexit_status
{
short int e_termination; //进程结束状态
short int e_exit; //进程退出状态
};

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值