1 /* $NetBSD: last.c,v 1.15 2000/06/30 06:19:58 simonb Exp $ */
4 * Copyright (c) 1987, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 static struct utmp
*buf
;
33 static void onintr(int);
34 static int want(struct utmp
*, int);
38 * read through the wtmp file
41 wtmp(const char *file
, int namesz
, int linesz
, int hostsz
)
43 struct utmp
*bp
; /* current structure */
44 TTY
*T
; /* tty list entry */
45 struct stat stb
; /* stat of file for sz */
46 time_t delta
; /* time difference */
51 size_t len
= sizeof(*buf
) * MAXUTMP
;
53 if ((buf
= malloc(len
)) == NULL
)
54 err(1, "Cannot allocate utmp buffer");
58 if ((wfd
= open(file
, O_RDONLY
, 0)) < 0 || fstat(wfd
, &stb
) == -1)
60 bl
= (stb
.st_size
+ len
- 1) / len
;
62 buf
[FIRSTVALID
].ut_timefld
= time(NULL
);
63 (void)signal(SIGINT
, onintr
);
64 (void)signal(SIGQUIT
, onintr
);
67 if (lseek(wfd
, bl
* len
, SEEK_SET
) == -1 ||
68 (bytes
= read(wfd
, buf
, len
)) == -1)
70 for (bp
= &buf
[bytes
/ sizeof(*buf
) - 1]; bp
>= buf
; --bp
) {
72 * if the terminal line is '~', the machine stopped.
73 * see utmp(5) for more info.
75 if (bp
->ut_line
[0] == '~' && !bp
->ut_line
[1]) {
76 /* everybody just logged out */
77 for (T
= ttylist
; T
; T
= T
->next
)
78 T
->logout
= -bp
->ut_timefld
;
79 currentout
= -bp
->ut_timefld
;
80 crmsg
= strncmp(bp
->ut_name
, "shutdown",
81 namesz
) ? "crash" : "shutdown";
83 ct
= fmttime(bp
->ut_timefld
, fulltime
);
84 printf("%-*.*s %-*.*s %-*.*s %s\n",
85 namesz
, namesz
, bp
->ut_name
,
86 linesz
, linesz
, bp
->ut_line
,
87 hostsz
, hostsz
, bp
->ut_host
, ct
);
88 if (maxrec
!= -1 && !--maxrec
)
94 * if the line is '{' or '|', date got set; see
95 * utmp(5) for more info.
97 if ((bp
->ut_line
[0] == '{' || bp
->ut_line
[0] == '|')
100 ct
= fmttime(bp
->ut_timefld
, fulltime
);
101 printf("%-*.*s %-*.*s %-*.*s %s\n",
109 if (maxrec
&& !--maxrec
)
114 /* find associated tty */
115 for (T
= ttylist
;; T
= T
->next
) {
118 T
= addtty(bp
->ut_line
);
121 if (!strncmp(T
->tty
, bp
->ut_line
, LINESIZE
))
124 if (TYPE(bp
) == SIGNATURE
)
126 if (bp
->ut_name
[0] && want(bp
, YES
)) {
127 ct
= fmttime(bp
->ut_timefld
, fulltime
);
128 printf("%-*.*s %-*.*s %-*.*s %s ",
129 namesz
, namesz
, bp
->ut_name
,
130 linesz
, linesz
, bp
->ut_line
,
131 hostsz
, hostsz
, bp
->ut_host
,
134 puts(" still logged in");
137 T
->logout
= -T
->logout
;
138 printf("- %s", crmsg
);
143 fulltime
| TIMEONLY
));
144 delta
= T
->logout
- bp
->ut_timefld
;
145 if (delta
< SECSPERDAY
)
148 fulltime
| TIMEONLY
| GMT
));
150 printf(" (%ld+%s)\n",
153 fulltime
| TIMEONLY
| GMT
));
155 if (maxrec
!= -1 && !--maxrec
)
158 T
->logout
= bp
->ut_timefld
;
161 fulltime
= 1; /* show full time */
162 crmsg
= fmttime(buf
[FIRSTVALID
].ut_timefld
, FULLTIME
);
163 if ((ct
= strrchr(file
, '/')) != NULL
)
165 printf("\n%s begins %s\n", ct
? ct
: file
, crmsg
);
170 * see if want this entry
173 want(struct utmp
*bp
, int check
)
179 * when uucp and ftp log in over a network, the entry in
180 * the utmp file is the name plus their process id. See
181 * etc/ftpd.c and usr.bin/uucp/uucpd.c for more information.
183 if (!strncmp(bp
->ut_line
, "ftp", sizeof("ftp") - 1))
184 bp
->ut_line
[3] = '\0';
185 else if (!strncmp(bp
->ut_line
, "uucp", sizeof("uucp") - 1))
186 bp
->ut_line
[4] = '\0';
191 for (step
= arglist
; step
; step
= step
->next
)
194 if (!strncasecmp(step
->name
, bp
->ut_host
, HOSTSIZE
))
198 if (!strncmp(step
->name
, bp
->ut_line
, LINESIZE
))
202 if (!strncmp(step
->name
, bp
->ut_name
, NAMESIZE
))
211 * on interrupt, we inform the user how far we've gotten
217 printf("\ninterrupted %s\n", fmttime(buf
[FIRSTVALID
].ut_timefld
,
221 (void)fflush(stdout
); /* fix required for rsh */