Chinaunix首页 | 论坛 | 博客
  • 博客访问: 90791
  • 博文数量: 31
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 11
  • 用 户 组: 普通用户
  • 注册时间: 2014-10-23 00:16
文章分类
文章存档

2015年(13)

2014年(18)

我的朋友

分类: C/C++

2014-12-26 11:08:09

原文地址:utmp和wtmp文件 作者:digdeep126

 /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);
阅读(1457) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~