2012-06-19 51 views
1

对于我们的任务,我们得到一份wtmp日志的副本,并且需要对其进行解析并以排序格式输出,类似于last的输出。使用C解析wtmp日志

现在,我知道文件wtmp包含一个utmp结构的列表。提供的文件保证至少包含一个utmp结构,我应该假设二进制文件中的所有结构都正确构建。

我读过man utmp,并且我已经成功地编写了一个程序来从所提供的二进制文件中读取结构。 (我道歉的漫长的打印方法)

#include <stdio.h> 
#include <string.h> 
#include <utmp.h> 
#include <stdlib.h> 

void utmpprint(struct utmp *log); 

int main() { 

    int logsize = 10; 
    FILE *file; 
    struct utmp log[logsize]; 
    int i = 0; 

    file = fopen("wtmp", "rb"); 

    if (file) { 
      fread(&log, sizeof(struct utmp), logsize, file); 
      for(i = 0; i < logsize; i++) { 
        utmpprint(&log[i]); 
      } 
    } else { 
      return(0); 
    } 
    return(0); 
} 


void utmpprint(struct utmp *log) { 
    printf("{ ut_type: %i, ut_pid: %i, ut_line: %s, ut_id: %s, 
     ut_user: %s, ut_host: %s, ut_exit: { e_termination: %i, 
     e_exit: %i }, ut_session: %i, timeval: { tv_sec: %i, tv_usec: %i }, 
     ut_addr_v6: %i }\n\n", log->ut_type, log->ut_pid, log->ut_line, 
     log->ut_id, log->ut_user, log->ut_host, log->ut_exit.e_termination, 
     log->ut_exit.e_exit, log->ut_session, log->ut_tv.tv_sec, 
     log->ut_tv.tv_usec, log->ut_addr_v6); 
} 

现在,我遇到的问题是,当我运行此,输出为ut_id比我期望它是不同的。

来源:man utmp

char ut_id[4];  /*Terminal name suffix, or inittab(5) ID */ 

我的输出:

... ut_line: pts/2, ut_id: ts/2jsmith, ut_user: jsmith, ... 

我不太清楚是怎么回事。我认为可能发生的情况是ut_id字段可能不存在于我正在阅读的结构中。我认为这可以解释为什么ut_id字段显示为两边的字段压扁在一起。

我认为我可以使用fprintf格式来正确显示字段,但似乎只能将文本格式化为字符数组的一侧,而不是从字符串内部抓取特定部分。

否则,我很迷路。这只是我对结构理解的一个缺口吗?

不寻找答案,更多的只是一些刺激正确的方向。

另外,究竟是什么终端名称后缀?那只是pts/之后的数字?

回答

2

man utmp说“如果字段的长度小于字段的大小,则字符串字段由空字节('\ 0')终止。”所以,特别是,如果它们与字段的大小相同,则它们是由空字节终止的而不是。格式良好的C字符串必须以空字节结尾。它看起来像ut_id字段的长度是4个字符,“ts/2”表示它没有终止空字节。

您正在使用%s格式参数打印字符数组到printf。这会一直打印,直到达到空字节。我建议您需要将utmp的每个字段复制到一个临时字符数组中,该字符数组是,比utmp结构中的大小大一个。确保临时数组的最后一个字节是空字节,并且应该打印出OK。