2012-06-19 50 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。