]> git.ipfire.org Git - thirdparty/util-linux.git/blame - login-utils/utmpdump.c
utmpdump: add NLS and closestream support
[thirdparty/util-linux.git] / login-utils / utmpdump.c
CommitLineData
78d5ceac 1/*
fa9baa80 2 * utmpdump
78d5ceac 3 *
fa9baa80
KZ
4 * Simple program to dump UTMP and WTMP files in raw format, so they can be
5 * examined.
78d5ceac 6 *
fa9baa80 7 * Based on utmpdump dump from sysvinit suite.
78d5ceac 8 *
fa9baa80 9 * Copyright (C) 1991-2000 Miquel van Smoorenburg <miquels@cistron.nl>
78d5ceac 10 *
fa9baa80
KZ
11 * Copyright (C) 1998 Danek Duvall <duvall@alumni.princeton.edu>
12 * Copyright (C) 2012 Karel Zak <kzak@redhat.com>
78d5ceac 13 *
fa9baa80
KZ
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
78d5ceac 18 *
fa9baa80
KZ
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
78d5ceac 23 *
fa9baa80
KZ
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
78d5ceac 27 */
78d5ceac
KZ
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <utmp.h>
32#include <time.h>
33#include <ctype.h>
34#include <unistd.h>
35#include <netinet/in.h>
36#include <arpa/inet.h>
37
23031b99
KZ
38#include "c.h"
39#include "nls.h"
40#include "closestream.h"
41
fa9baa80 42char *timetostr(const time_t time)
78d5ceac
KZ
43{
44 static char s[29]; /* [Sun Sep 01 00:00:00 1998 PST] */
45
46 if (time != 0)
47 strftime(s, 29, "%a %b %d %T %Y %Z", localtime(&time));
48 else
49 s[0] = '\0';
50
51 return s;
52}
53
fa9baa80 54time_t strtotime(const char *s_time)
78d5ceac
KZ
55{
56 struct tm tm;
fa9baa80 57
78d5ceac
KZ
58 memset(&tm, '\0', sizeof(struct tm));
59
60 if (s_time[0] == ' ' || s_time[0] == '\0')
61 return (time_t)0;
62
63 strptime(s_time, "%a %b %d %T %Y", &tm);
64
65 /* Cheesy way of checking for DST */
66 if (s_time[26] == 'D')
67 tm.tm_isdst = 1;
68
69 return mktime(&tm);
70}
71
72#define cleanse(x) xcleanse(x, sizeof(x))
fa9baa80 73void xcleanse(char *s, int len)
78d5ceac
KZ
74{
75 for ( ; *s && len-- > 0; s++)
76 if (!isprint(*s) || *s == '[' || *s == ']')
77 *s = '?';
78}
79
fa9baa80 80void unspace(char *s, int len)
78d5ceac
KZ
81{
82 while (*s && *s != ' ' && len--)
83 ++s;
84
85 if (len > 0)
86 *s = '\0';
87}
88
fa9baa80 89void print_utline(struct utmp ut)
78d5ceac
KZ
90{
91 char *addr_string, *time_string;
92 struct in_addr in;
93
94 in.s_addr = ut.ut_addr;
95 addr_string = inet_ntoa(in);
96 time_string = timetostr(ut.ut_time);
97 cleanse(ut.ut_id);
98 cleanse(ut.ut_user);
99 cleanse(ut.ut_line);
100 cleanse(ut.ut_host);
101
102 /* pid id user line host addr time */
103 printf("[%d] [%05d] [%-4.4s] [%-*.*s] [%-*.*s] [%-*.*s] [%-15.15s] [%-28.28s]\n",
104 ut.ut_type, ut.ut_pid, ut.ut_id, 8, UT_NAMESIZE, ut.ut_user,
105 12, UT_LINESIZE, ut.ut_line, 20, UT_HOSTSIZE, ut.ut_host,
106 addr_string, time_string);
107}
108
b89fc915 109void dump(FILE *fp, int forever)
78d5ceac
KZ
110{
111 struct utmp ut;
78d5ceac
KZ
112
113 if (forever)
b89fc915 114 fseek(fp, -10 * sizeof ut, SEEK_END);
78d5ceac
KZ
115
116 do {
b89fc915
KZ
117 while (fread(&ut, sizeof ut, 1, fp) == 1)
118 print_utline(ut);
78d5ceac
KZ
119 if (forever) sleep(1);
120 } while (forever);
121}
122
123/* This function won't work properly if there's a ']' or a ' ' in the real
124 * token. Thankfully, this should never happen. */
fa9baa80 125int gettok(char *line, char *dest, int size, int eatspace)
78d5ceac
KZ
126{
127 int bpos, epos, eaten;
128 char *t;
129
130 bpos = strchr(line, '[') - line;
131 if (bpos < 0) {
23031b99 132 fprintf(stderr, _("Extraneous newline in file. Exiting."));
78d5ceac
KZ
133 exit(1);
134 }
135 line += 1 + bpos;
136
137 epos = strchr(line, ']') - line;
138 if (epos < 0) {
23031b99 139 fprintf(stderr, _("Extraneous newline in file. Exiting."));
78d5ceac
KZ
140 exit(1);
141 }
142 line[epos] = '\0';
143
144 eaten = bpos + epos + 1;
145
146 if (eatspace)
147 if ((t = strchr(line, ' ')))
148 *t = 0;
149
150 strncpy(dest, line, size);
151
152 return eaten + 1;
153}
154
a9eee870 155void undump(FILE *fp)
78d5ceac
KZ
156{
157 struct utmp ut;
78d5ceac
KZ
158 char s_addr[16], s_time[29], *linestart, *line;
159 int count = 0;
160
161 line = linestart = malloc(1024 * sizeof *linestart);
162 s_addr[15] = 0;
163 s_time[28] = 0;
164
165 while(fgets(linestart, 1023, fp))
166 {
167 line = linestart;
168 memset(&ut, '\0', sizeof(ut));
169 sscanf(line, "[%hd] [%d] [%4c] ", &ut.ut_type, &ut.ut_pid, ut.ut_id);
170
171 line += 19;
172 line += gettok(line, ut.ut_user, sizeof(ut.ut_user), 1);
173 line += gettok(line, ut.ut_line, sizeof(ut.ut_line), 1);
174 line += gettok(line, ut.ut_host, sizeof(ut.ut_host), 1);
175 line += gettok(line, s_addr, sizeof(s_addr)-1, 1);
176 line += gettok(line, s_time, sizeof(s_time)-1, 0);
177
178 ut.ut_addr = inet_addr(s_addr);
179 ut.ut_time = strtotime(s_time);
180
b89fc915 181 fwrite(&ut, sizeof(ut), 1, stdout);
78d5ceac
KZ
182
183 ++count;
184 }
185
186 free(linestart);
187}
188
189void
190usage(int result)
191{
23031b99 192 printf(_("Usage: utmpdump [ -frh ] [ filename ]\n"));
78d5ceac
KZ
193 exit(result);
194}
195
196int main(int argc, char **argv)
197{
198 int c;
199 FILE *fp;
b89fc915 200 int reverse = 0, forever = 0;
78d5ceac 201
23031b99
KZ
202 setlocale(LC_ALL, "");
203 bindtextdomain(PACKAGE, LOCALEDIR);
204 textdomain(PACKAGE);
205 atexit(close_stdout);
206
78d5ceac
KZ
207 while ((c = getopt(argc, argv, "froh")) != EOF) {
208 switch (c) {
209 case 'r':
210 reverse = 1;
211 break;
212
213 case 'f':
214 forever = 1;
215 break;
216
78d5ceac
KZ
217 case 'h':
218 usage(0);
219 break;
220
221 default:
222 usage(1);
223 }
224 }
225
226 if (optind < argc) {
23031b99 227 fprintf(stderr, _("Utmp %sdump of %s\n"), reverse ? "un" : "", argv[optind]);
78d5ceac
KZ
228 if ((fp = fopen(argv[optind], "r")) == NULL) {
229 perror("Unable to open file");
230 exit(1);
231 }
232 }
233 else {
23031b99 234 fprintf(stderr, _("Utmp %sdump of stdin\n"), reverse ? "un" : "");
78d5ceac
KZ
235 fp = stdin;
236 }
237
238 if (reverse)
a9eee870 239 undump(fp);
78d5ceac 240 else
b89fc915 241 dump(fp, forever);
78d5ceac
KZ
242
243 fclose(fp);
78d5ceac
KZ
244 return 0;
245}