Linux下读取wtmp日志文件的内容

最近在搞一个实验箱的串口通信,想要对实验箱内部系统的一个日志文件进项监测并读写,这个日志文件就是wtmp文件。

wtmp文件保存登录系统的用户信息,是一个二进制文件,一开始就规规矩矩的用二进制的方式读写文件(C++对二进制文件读写.md),结果就收到了一串乱码。。。在linux下用vim查看文件也是乱码,但是用last指令或者who指令,完全没有问题,后来就考虑可不可以写一段程序,实现last指令或者who指令的功能,以wtmp文件保存时的格式原样再读出?于是开始查看last和who指令的源码,不过真心没怎么看明白,后来在网上看到一篇类似博文,给了很大帮助。
贴出来共享一下:http://blog.chinaunix.net/uid-25909722-id-2851379.html

1. wtmp文件是什么?

wtmp文件保存的是登陆本系统的用户信息,二进制文件
保存的信息基于结构体struct utmp,该结构体定义在utmp.h头文件中(/usr/include/utmp.h)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// The structure describing the status of a terminated process. This type is used in `struct utmp' below. 
struct exit_status
{
short int e_termination; // Process termination status.
short int e_exit; // Process exit status.
};
// The structure describing an entry in the user accounting database.
struct utmp
{
short int ut_type; /* Type of login. */
pid_t ut_pid; /* Process ID of login process. */
char ut_line[UT_LINESIZE]; /* Devicename. */
char ut_id[4]; /* Inittab ID. */
char ut_user[UT_NAMESIZE]; /* Username. */
char ut_host[UT_HOSTSIZE]; /* Hostname for remote login. */
struct exit_status ut_exit; /* Exit status of a process marked as DEAD_PROCESS. */
// 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, used for windowing.
struct
{
int32_t tv_sec; // Seconds.
int32_t tv_usec; // Microseconds.
} ut_tv; // Time entry was made.
#else
long int ut_session; // Session ID, used for windowing.
struct timeval ut_tv; // Time entry was made.
#endif
int32_t ut_addr_v6[4]; // Internet address of remote host.
char __unused[20]; // Reserved for future use.
};
// 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

2. 对文件读取修改的函数

1
2
3
4
5
6
7
8
9
#include <utmp.h>

struct utmp *getutent(void);//从文件utmp中每次读取一个struct utmp结构体,读取失败返回NULL
struct utmp *getutid(struct utmp *ut);
struct utmp *getutline(struct utmp *ut);
struct utmp *pututline(struct utmp *ut); //将一个结构体写入文件utmp中
void setutent(void);//打开文件utmp,并且将文件指针指向文件的最开始
void endutent(void);//关闭文件
int utmpname(const char *file);

3. 监测wtmp文件,并读取文件内容

类似于who 指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>
#include <stdlib.h>
#include <utmp.h>
#include <time.h>

int main()
{
struct utmp *p_utent;
long t;

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

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

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

return 0;
}

写的还不错?那就来个红包吧!
0%