xref: /dragonfly/usr.bin/wtmpcvt/wtmpcvt.c (revision ec21d9fb)
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