source: MondoRescue/branches/3.3/mindi-busybox/miscutils/last.c@ 3865

Last change on this file since 3865 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

File size: 4.1 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * last implementation for busybox
4 *
5 * Copyright (C) 2003-2004 by Erik Andersen <andersen@codepoet.org>
6 *
7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */
9
10//usage:#define last_trivial_usage
11//usage: ""IF_FEATURE_LAST_FANCY("[-HW] [-f FILE]")
12//usage:#define last_full_usage "\n\n"
13//usage: "Show listing of the last users that logged into the system"
14//usage: IF_FEATURE_LAST_FANCY( "\n"
15/* //usage: "\n -H Show header line" */
16//usage: "\n -W Display with no host column truncation"
17//usage: "\n -f FILE Read from FILE instead of /var/log/wtmp"
18//usage: )
19
20#include "libbb.h"
21
22/* NB: ut_name and ut_user are the same field, use only one name (ut_user)
23 * to reduce confusion */
24
25#ifndef SHUTDOWN_TIME
26# define SHUTDOWN_TIME 254
27#endif
28
29/* Grr... utmp char[] members do not have to be nul-terminated.
30 * Do what we can while still keeping this reasonably small.
31 * Note: We are assuming the ut_id[] size is fixed at 4. */
32
33#if defined UT_LINESIZE \
34 && ((UT_LINESIZE != 32) || (UT_NAMESIZE != 32) || (UT_HOSTSIZE != 256))
35#error struct utmpx member char[] size(s) have changed!
36#elif defined __UT_LINESIZE \
37 && ((__UT_LINESIZE != 32) || (__UT_NAMESIZE != 32) || (__UT_HOSTSIZE != 256))
38/* __UT_NAMESIZE was checked with 64 above, but glibc-2.11 definitely uses 32! */
39#error struct utmpx member char[] size(s) have changed!
40#endif
41
42#if EMPTY != 0 || RUN_LVL != 1 || BOOT_TIME != 2 || NEW_TIME != 3 || \
43 OLD_TIME != 4
44#error Values for the ut_type field of struct utmpx changed
45#endif
46
47int last_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
48int last_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
49{
50 struct utmpx ut;
51 int n, file = STDIN_FILENO;
52 time_t t_tmp;
53 off_t pos;
54 static const char _ut_usr[] ALIGN1 =
55 "runlevel\0" "reboot\0" "shutdown\0";
56 static const char _ut_lin[] ALIGN1 =
57 "~\0" "{\0" "|\0" /* "LOGIN\0" "date\0" */;
58 enum {
59 TYPE_RUN_LVL = RUN_LVL, /* 1 */
60 TYPE_BOOT_TIME = BOOT_TIME, /* 2 */
61 TYPE_SHUTDOWN_TIME = SHUTDOWN_TIME
62 };
63 enum {
64 _TILDE = EMPTY, /* 0 */
65 TYPE_NEW_TIME, /* NEW_TIME, 3 */
66 TYPE_OLD_TIME /* OLD_TIME, 4 */
67 };
68
69 if (argv[1]) {
70 bb_show_usage();
71 }
72 file = xopen(bb_path_wtmp_file, O_RDONLY);
73
74 printf("%-10s %-14s %-18s %-12.12s %s\n",
75 "USER", "TTY", "HOST", "LOGIN", "TIME");
76 /* yikes. We reverse over the file and that is a not too elegant way */
77 pos = xlseek(file, 0, SEEK_END);
78 pos = lseek(file, pos - sizeof(ut), SEEK_SET);
79 while ((n = full_read(file, &ut, sizeof(ut))) > 0) {
80 if (n != sizeof(ut)) {
81 bb_perror_msg_and_die("short read");
82 }
83 n = index_in_strings(_ut_lin, ut.ut_line);
84 if (n == _TILDE) { /* '~' */
85#if 1
86/* do we really need to be cautious here? */
87 n = index_in_strings(_ut_usr, ut.ut_user);
88 if (++n > 0)
89 ut.ut_type = n != 3 ? n : SHUTDOWN_TIME;
90#else
91 if (is_prefixed_with(ut.ut_user, "shutdown"))
92 ut.ut_type = SHUTDOWN_TIME;
93 else if (is_prefixed_with(ut.ut_user, "reboot"))
94 ut.ut_type = BOOT_TIME;
95 else if (is_prefixed_with(ut.ut_user, "runlevel"))
96 ut.ut_type = RUN_LVL;
97#endif
98 } else {
99 if (ut.ut_user[0] == '\0' || strcmp(ut.ut_user, "LOGIN") == 0) {
100 /* Don't bother. This means we can't find how long
101 * someone was logged in for. Oh well. */
102 goto next;
103 }
104 if (ut.ut_type != DEAD_PROCESS
105 && ut.ut_user[0]
106 && ut.ut_line[0]
107 ) {
108 ut.ut_type = USER_PROCESS;
109 }
110 if (strcmp(ut.ut_user, "date") == 0) {
111 if (n == TYPE_OLD_TIME) { /* '|' */
112 ut.ut_type = OLD_TIME;
113 }
114 if (n == TYPE_NEW_TIME) { /* '{' */
115 ut.ut_type = NEW_TIME;
116 }
117 }
118 }
119
120 if (ut.ut_type != USER_PROCESS) {
121 switch (ut.ut_type) {
122 case OLD_TIME:
123 case NEW_TIME:
124 case RUN_LVL:
125 case SHUTDOWN_TIME:
126 goto next;
127 case BOOT_TIME:
128 strcpy(ut.ut_line, "system boot");
129 }
130 }
131 /* manpages say ut_tv.tv_sec *is* time_t,
132 * but some systems have it wrong */
133 t_tmp = (time_t)ut.ut_tv.tv_sec;
134 printf("%-10s %-14s %-18s %-12.12s\n",
135 ut.ut_user, ut.ut_line, ut.ut_host, ctime(&t_tmp) + 4);
136 next:
137 pos -= sizeof(ut);
138 if (pos <= 0)
139 break; /* done. */
140 xlseek(file, pos, SEEK_SET);
141 }
142
143 fflush_stdout_and_exit(EXIT_SUCCESS);
144}
Note: See TracBrowser for help on using the repository browser.