BSD 3 development
[unix-history] / usr / src / cmd / last.c
CommitLineData
dfbdb50f
HK
1#
2/*
3 * NAME: last
4 *
5 * SYNOPSIS: last [list]
6 *
7 * DESCRIPTION: Displays login history of named users or tty's.
8 * Last with no argument prints history for all users.
9 *
10 * AUTHOR - Howard P. Katseff
11 */
12
13# include <sys/types.h>
14# include <stdio.h>
15# include <stat.h>
16# include <utmp.h>
17
18char yes = 1,
19 no = 0,
20
21 *wtmp = "/usr/adm/wtmp",
22 b [512],
23
24 Arg [25] [9],
25 tty_names [48] [9],
26
27 *ctime (),
28 *move (),
29 *rmchar ();
30
31
32long logouts [48],
33 bl,
34 rec,
35 nblock;
36
37struct utmp buf [128]; /* buf takes exactly 5 blocks */
38
39main (argc, argv)
40char **argv;
41{
42 char f,
43 narg,
44
45 *bend,
46 *p,
47 *q;
48
49 short n_byte,
50 n_record;
51
52 long i,
53 k,
54 ntime,
55 otime,
56
57 intrp ();
58
59 struct stat sbuf;
60
61 for (i = 1; i < argc; i++)
62 {
63 if
64 (
65 length (argv [i]) > 2 /* long tty or user name */
66 ||
67 equal (argv [i], "~") /* tilde */
68 ||
69 getpwnam (argv [i]) /* user name */
70 )
71 {
72 move (argv [i], Arg [narg++]);
73 }
74 else /* short tty name */
75 {
76 move (argv [i], move ("tty", Arg [narg++]));
77 }
78 }
79 f = open (wtmp, 0);
80 if (f < 0)
81 {
82 perror (wtmp);
83 fflush (stdout);
84 exit ();
85 }
86 if (fstat (f, &sbuf) < 0)
87 {
88 perror ("/usr/adm/wtmp");
89 fflush (stdout);
90 exit ();
91 }
92 nblock = (sbuf.st_size + 2559) / 2560;
93 signal (2, intrp);
94 for (bl = nblock - 1; bl >= 0; bl--)
95 {
96 lseek (f, bl * 2560, 0);
97 n_byte = read (f, buf, 2560);
98 n_record = n_byte / sizeof buf [0];
99 for (rec = n_record - 1; rec >= 0; rec--)
100 {
101
102 if (should_print ())
103 {
104 q = ctime (&buf[rec].ut_time);
105 printf
106 (
107 "%-8.8s %-8.8s %10.10s %5.5s ",
108 buf[rec].ut_name, buf[rec].ut_line, q, 11+q
109 );
110 otime = buf[rec].ut_time;
111 /*
112 * look up the logout time for the tty
113 */
114 for (i = 0;; i++)
115 {
116 if (!*tty_names [i])
117 /* not in the table, therefore add it */
118 {
119 move
120 (
121 buf[rec].ut_line,
122 tty_names [i]
123 );
124 ntime = 0;
125 break;
126 }
127 if
128 (
129 equal
130 (
131 tty_names [i],
132 buf [rec].ut_line
133 )
134 )
135 {
136 ntime = logouts [i];
137 break;
138 }
139 }
140 if (ntime == 0)
141 {
142 printf (" still logged in\n");
143 }
144 else
145 {
146 if (ntime < 0)
147 {
148 ntime = -ntime;
149 printf ("- crash");
150 }
151 else
152 {
153 printf ("- %5.5s", ctime (&ntime) + 11);
154 }
155 /*
156 * calculate how long logged in
157 */
158 otime = ntime - otime;
159 otime += 231220830 + 10800;
160 if (otime < 231220830 + 86400 + 10800)
161 {
162 printf
163 (
164 " (%5.5s)\n",
165 ctime (&otime) + 11
166 );
167 }
168 else
169 {
170 printf
171 (
172 " (%ld+%5.5s)\n",
173 (otime -
174 (231330830-86400-10800))/86400,
175 ctime (&otime) + 11
176 );
177 }
178 }
179 fflush (stdout);
180 }
181 if
182 (
183 equal (buf[rec].ut_line, "~")
184 ||
185 equal (buf[rec].ut_line, "tty~")
186 )
187 {
188 for (i = 0; *tty_names [i]; i++)
189 {
190 logouts [i] = -buf[rec].ut_time;
191 }
192 }
193 else
194 {
195 for (k = 0;; k++)
196 {
197 if (!*tty_names [k])
198 {
199 move
200 (
201 buf[rec].ut_line,
202 tty_names [k]
203 );
204 logouts [k] = buf[rec].ut_time;
205 break;
206 }
207 if (equal (tty_names [k], buf[rec].ut_line))
208 {
209 logouts [k] = buf[rec].ut_time;
210 break;
211 }
212 }
213 }
214 }
215 }
216 q = ctime (&buf [0].ut_time);
217 printf
218 (
219 "\nwtmp begins %10.10s %5.5s \n",
220 q, q + 11
221 );
222}
223
224equal (a, b)
225char *a, *b;
226{
227 char i;
228
229 for (i = 0; i < 8; i++)
230 {
231 if (!*a) return (!*b);
232 if (*a++ != *b++) return (0);
233 }
234 return (1);
235}
236
237
238intrp ()
239{
240 char *q;
241
242 signal (2, 1); /* ignore further interrupts */
243 q = ctime (&buf[rec].ut_time);
244 printf
245 (
246 "\ninterrupted %10.10s %5.5s \n",
247 q, q + 11
248 );
249 exit ();
250}
251
252char *
253rmchar (c, s)
254char c, *s;
255{
256 for (; *s; s++)
257 {
258 if (*s == c)
259 {
260 *s = 0;
261 return (s);
262 }
263 }
264 return (0);
265}
266
267length (a)
268char *a;
269{
270 char *b;
271
272 for (b = a; *b; b++);
273 return (b - a);
274}
275
276char *
277move (a, b)
278char *a, *b;
279{
280 while (*b++ = *a++);
281 return (b - 1);
282}
283
284should_print ()
285{
286 short i;
287
288 if (buf [rec].ut_name [0] == no) return no; /* a logout entry */
289 if (!**Arg) return yes; /* no arguments? Print all login entries */
290 for (i = 0; i < *Arg [i]; i++)
291 {
292 if
293 (
294 equal (Arg [i], buf[rec].ut_name)
295 ||
296 equal (Arg [i], buf[rec].ut_line)
297 )
298 return yes;
299 }
300 return no;
301}