1 /*- 2 * Copyright (c) 2010 Ed Schouten <ed@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/endian.h> 28 #include <sys/param.h> 29 30 #include <err.h> 31 #include <stdio.h> 32 #include <stdint.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <utmpx.h> 36 37 struct outmp { 38 char ut_line[8]; 39 char ut_user[16]; 40 char ut_host[16]; 41 time_t ut_time; 42 }; 43 44 static const char vers[] = "utmpx-2.00"; 45 46 static void 47 usage(void) 48 { 49 50 fprintf(stderr, "usage: wtmpcvt input output\n"); 51 exit(1); 52 } 53 54 static void 55 outmp_to_utmpx(const struct outmp *ui, struct utmpx *uo) 56 { 57 58 memset(uo, 0, sizeof *uo); 59 #define COPY_STRING(field) do { \ 60 strncpy(uo->ut_ ## field, ui->ut_ ## field, \ 61 MIN(sizeof uo->ut_ ## field, sizeof ui->ut_ ## field)); \ 62 } while (0) 63 #define COPY_LINE_TO_ID() do { \ 64 strncpy(uo->ut_id, ui->ut_line, \ 65 MIN(sizeof uo->ut_id, sizeof ui->ut_line)); \ 66 } while (0) 67 #define MATCH(field, value) (strncmp(ui->ut_ ## field, (value), \ 68 sizeof(ui->ut_ ## field)) == 0) 69 if (MATCH(user, "reboot") && MATCH(line, "~")) { 70 uo->ut_type = INIT_PROCESS; 71 COPY_STRING(user); 72 COPY_STRING(line); 73 } else if (MATCH(user, "date") && MATCH(line, "|")) { 74 uo->ut_type = OLD_TIME; 75 } else if (MATCH(user, "date") && MATCH(line, "{")) { 76 uo->ut_type = NEW_TIME; 77 } else if (MATCH(user, "shutdown") && MATCH(line, "~")) { 78 uo->ut_type = INIT_PROCESS; 79 COPY_STRING(user); 80 COPY_STRING(line); 81 } else if (MATCH(user, "") && MATCH(host, "") && !MATCH(line, "")) { 82 uo->ut_type = DEAD_PROCESS; 83 COPY_LINE_TO_ID(); 84 } else if (!MATCH(user, "") && !MATCH(line, "") && ui->ut_time != 0) { 85 uo->ut_type = USER_PROCESS; 86 COPY_STRING(user); 87 COPY_STRING(line); 88 COPY_STRING(host); 89 COPY_LINE_TO_ID(); 90 } else { 91 uo->ut_type = EMPTY; 92 return; 93 } 94 #undef COPY_STRING 95 #undef COPY_LINE_TO_ID 96 #undef MATCH 97 98 uo->ut_tv.tv_sec = ui->ut_time; 99 uo->ut_tv.tv_usec = 0; 100 } 101 102 int 103 main(int argc, char *argv[]) 104 { 105 FILE *in, *out; 106 struct outmp ui; 107 struct utmpx uo; 108 109 if (argc != 3) 110 usage(); 111 112 /* Open files. */ 113 in = fopen(argv[1], "r"); 114 if (in == NULL) 115 err(1, "%s", argv[1]); 116 out = fopen(argv[2], "w"); 117 if (out == NULL) 118 err(1, "%s", argv[2]); 119 120 /* Write signature. */ 121 memset(&uo, 0, sizeof uo); 122 uo.ut_type = SIGNATURE; 123 memcpy(uo.ut_user, vers, sizeof(vers)); 124 fwrite(&uo, sizeof uo, 1, out); 125 126 /* Process entries. */ 127 while (fread(&ui, sizeof ui, 1, in) == 1) { 128 outmp_to_utmpx(&ui, &uo); 129 if (uo.ut_type == EMPTY) 130 continue; 131 132 /* Write new entry to output file. */ 133 fwrite(&uo, sizeof uo, 1, out); 134 } 135 136 fclose(in); 137 fclose(out); 138 return (0); 139 } 140