summaryrefslogtreecommitdiff
path: root/miscutils/dutmp.c
blob: 113f850fed7f32c1100d25693da381cfcc432ffe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/* vi: set sw=4 ts=4: */
/*
 * public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com>
 * 
 * dutmp
 * Takes utmp formated file on stdin and dumps it's contents 
 * out in colon delimited fields. Easy to 'cut' for shell based 
 * versions of 'who', 'last', etc. IP Addr is output in hex, 
 * little endian on x86.
 * 
 */

/* Mar 13, 2003       Manuel Novoa III
 *
 * 1) Added proper error checking.
 * 2) Allow '-' arg for stdin.
 * 3) For modern libcs, take into account that utmp char[] members
 *    need not be nul-terminated.
 */

#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <utmp.h>
#include "busybox.h"

/* Grr... utmp char[] members  do not have to be nul-terminated.
 * Do what we can while still keeping this reasonably small.
 * Note: We are assuming the ut_id[] size is fixed at 4. */

#if __GNU_LIBRARY__ < 5
#warning the format string needs to be changed
#else
#if (UT_LINESIZE != 32) || (UT_NAMESIZE != 32) || (UT_HOSTSIZE != 256)
#error struct utmp member char[] size(s) have changed!
#endif
#endif

extern int dutmp_main(int argc, char **argv)
{
	int file = STDIN_FILENO;
	ssize_t n;
	struct utmp ut;

	if (argc > 2) {
		bb_show_usage();
	}
	++argv;
	if ((argc == 2) && ((argv[0][0] != '-') || argv[0][1])) {
		file = bb_xopen(*argv, O_RDONLY);
	}


	while ((n = safe_read(file, (void*)&ut, sizeof(struct utmp))) != 0) {

		if (n != sizeof(struct utmp)) {
			bb_perror_msg_and_die("short read");
		}

		/* Kludge around the fact that the binary format for utmp has changed. */
#if __GNU_LIBRARY__ < 5
		/* Linux libc5 */

		bb_printf("%d|%d|%s|%s|%s|%s|%s|%lx\n",
				  ut.ut_type, ut.ut_pid, ut.ut_line,
				  ut.ut_id, ut.ut_user, ut.ut_host,
				  ctime(&(ut.ut_time)), 
				  (long)ut.ut_addr);
#else
		/* Glibc, uClibc, etc. */

		bb_printf("%d|%d|%.32s|%.4s|%.32s|%.256s|%d|%d|%ld|%ld|%ld|%x\n",
				  ut.ut_type, ut.ut_pid, ut.ut_line,
				  ut.ut_id, ut.ut_user,	ut.ut_host,
				  ut.ut_exit.e_termination, ut.ut_exit.e_exit,
				  ut.ut_session,
				  ut.ut_tv.tv_sec, ut.ut_tv.tv_usec,
				  ut.ut_addr);
#endif
	}

	bb_fflush_stdout_and_exit(EXIT_SUCCESS);
}