使用C解析wtmp日志

时间:2012-06-19 01:22:12

标签: c file-io struct fread

对于我们的赋值,我们会得到wtmp日志的副本,并且应该对其进行解析,并以排序的格式输出,类似于last的输出。

现在,我知道文件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/之后的数字吗?

1 个答案:

答案 0 :(得分:2)

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

您使用%s格式化参数将char数组打印到printf。这样可以保持打印直到达到空字节。我建议您需要将utmp的每个字段复制到一个临时字符数组,该数组utmp结构中的大一个。确保该临时数组的最后一个字节是一个空字节,它应该打印出来。