#include <sys/endian.h>
#include <sys/param.h>
#include <err.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <utmpx.h>
struct outmp {
char ut_line[8];
char ut_user[16];
char ut_host[16];
time_t ut_time;
};
static const char vers[] = "utmpx-2.00";
static void
usage(void)
{
fprintf(stderr, "usage: wtmpcvt input output\n");
exit(1);
}
static void
outmp_to_utmpx(const struct outmp *ui, struct utmpx *uo)
{
memset(uo, 0, sizeof *uo);
#define COPY_STRING(field) do { \
strncpy(uo->ut_ ## field, ui->ut_ ## field, \
MIN(sizeof uo->ut_ ## field, sizeof ui->ut_ ## field)); \
} while (0)
#define COPY_LINE_TO_ID() do { \
strncpy(uo->ut_id, ui->ut_line, \
MIN(sizeof uo->ut_id, sizeof ui->ut_line)); \
} while (0)
#define MATCH(field, value) (strncmp(ui->ut_ ## field, (value), \
sizeof(ui->ut_ ## field)) == 0)
if (MATCH(user, "reboot") && MATCH(line, "~")) {
uo->ut_type = INIT_PROCESS;
COPY_STRING(user);
COPY_STRING(line);
} else if (MATCH(user, "date") && MATCH(line, "|")) {
uo->ut_type = OLD_TIME;
} else if (MATCH(user, "date") && MATCH(line, "{")) {
uo->ut_type = NEW_TIME;
} else if (MATCH(user, "shutdown") && MATCH(line, "~")) {
uo->ut_type = INIT_PROCESS;
COPY_STRING(user);
COPY_STRING(line);
} else if (MATCH(user, "") && MATCH(host, "") && !MATCH(line, "")) {
uo->ut_type = DEAD_PROCESS;
COPY_LINE_TO_ID();
} else if (!MATCH(user, "") && !MATCH(line, "") && ui->ut_time != 0) {
uo->ut_type = USER_PROCESS;
COPY_STRING(user);
COPY_STRING(line);
COPY_STRING(host);
COPY_LINE_TO_ID();
} else {
uo->ut_type = EMPTY;
return;
}
#undef COPY_STRING
#undef COPY_LINE_TO_ID
#undef MATCH
uo->ut_tv.tv_sec = ui->ut_time;
uo->ut_tv.tv_usec = 0;
}
int
main(int argc, char *argv[])
{
FILE *in, *out;
struct outmp ui;
struct utmpx uo;
if (argc != 3)
usage();
in = fopen(argv[1], "r");
if (in == NULL)
err(1, "%s", argv[1]);
out = fopen(argv[2], "w");
if (out == NULL)
err(1, "%s", argv[2]);
memset(&uo, 0, sizeof uo);
uo.ut_type = SIGNATURE;
memcpy(uo.ut_user, vers, sizeof(vers));
fwrite(&uo, sizeof uo, 1, out);
while (fread(&ui, sizeof ui, 1, in) == 1) {
outmp_to_utmpx(&ui, &uo);
if (uo.ut_type == EMPTY)
continue;
fwrite(&uo, sizeof uo, 1, out);
}
fclose(in);
fclose(out);
return (0);
}