added last to "see also" list
[unix-history] / usr / src / usr.bin / last / last.c
CommitLineData
22e155fc
DF
1/*
2 * Copyright (c) 1980 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
8char copyright[] =
9"@(#) Copyright (c) 1980 Regents of the University of California.\n\
10 All rights reserved.\n";
11#endif not lint
12
37c640e2 13#ifndef lint
131f9f19 14static char sccsid[] = "@(#)last.c 5.3 (Berkeley) %G%";
22e155fc 15#endif not lint
37c640e2 16
c9af8668
BJ
17/*
18 * last
19 */
20#include <sys/types.h>
21#include <stdio.h>
22#include <signal.h>
40d69e19 23#include <sys/stat.h>
c9af8668
BJ
24#include <utmp.h>
25
26#define NMAX sizeof(buf[0].ut_name)
27#define LMAX sizeof(buf[0].ut_line)
37c640e2 28#define HMAX sizeof(buf[0].ut_host)
c9af8668
BJ
29#define SECDAY (24*60*60)
30
31#define lineq(a,b) (!strncmp(a,b,LMAX))
32#define nameq(a,b) (!strncmp(a,b,NMAX))
37c640e2 33#define hosteq(a,b) (!strncmp(a,b,HMAX))
c9af8668
BJ
34
35#define MAXTTYS 256
36
37char **argv;
38int argc;
b50e7db3 39int nameargs;
c9af8668
BJ
40
41struct utmp buf[128];
42char ttnames[MAXTTYS][LMAX+1];
43long logouts[MAXTTYS];
44
45char *ctime(), *strspl();
46int onintr();
47
48main(ac, av)
49 char **av;
50{
51 register int i, k;
52 int bl, wtmp;
53 char *ct;
54 register struct utmp *bp;
55 long otime;
56 struct stat stb;
57 int print;
fe6cb666
BJ
58 char * crmsg = (char *)0;
59 long crtime;
b50e7db3
DW
60 long outrec = 0;
61 long maxrec = 0x7fffffffL;
c9af8668
BJ
62
63 time(&buf[0].ut_time);
64 ac--, av++;
b50e7db3 65 nameargs = argc = ac;
c9af8668
BJ
66 argv = av;
67 for (i = 0; i < argc; i++) {
37c640e2
SL
68 if (argv[i][0] == '-' &&
69 argv[i][1] >= '0' && argv[i][1] <= '9') {
b50e7db3
DW
70 maxrec = atoi(argv[i]+1);
71 nameargs--;
72 continue;
73 }
c9af8668
BJ
74 if (strlen(argv[i])>2)
75 continue;
76 if (!strcmp(argv[i], "~"))
77 continue;
ac7e4ccf
SL
78 if (!strcmp(argv[i], "ftp"))
79 continue;
400ed241
JL
80 if (!strcmp(argv[i], "uucp"))
81 continue;
c9af8668
BJ
82 if (getpwnam(argv[i]))
83 continue;
84 argv[i] = strspl("tty", argv[i]);
85 }
86 wtmp = open("/usr/adm/wtmp", 0);
87 if (wtmp < 0) {
88 perror("/usr/adm/wtmp");
89 exit(1);
90 }
91 fstat(wtmp, &stb);
92 bl = (stb.st_size + sizeof (buf)-1) / sizeof (buf);
93 if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
94 signal(SIGINT, onintr);
95 signal(SIGQUIT, onintr);
96 }
97 for (bl--; bl >= 0; bl--) {
98 lseek(wtmp, bl * sizeof (buf), 0);
99 bp = &buf[read(wtmp, buf, sizeof (buf)) / sizeof(buf[0]) - 1];
100 for ( ; bp >= buf; bp--) {
101 print = want(bp);
102 if (print) {
103 ct = ctime(&bp->ut_time);
68f635b7 104 printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s ",
c9af8668 105 NMAX, NMAX, bp->ut_name,
37c640e2
SL
106 LMAX, LMAX, bp->ut_line,
107 HMAX, HMAX, bp->ut_host,
108 ct, 11+ct);
c9af8668
BJ
109 }
110 for (i = 0; i < MAXTTYS; i++) {
111 if (ttnames[i][0] == 0) {
112 strncpy(ttnames[i], bp->ut_line,
113 sizeof(bp->ut_line));
cf779ba2 114 otime = logouts[i];
c9af8668
BJ
115 logouts[i] = bp->ut_time;
116 break;
117 }
118 if (lineq(ttnames[i], bp->ut_line)) {
119 otime = logouts[i];
120 logouts[i] = bp->ut_time;
121 break;
122 }
123 }
124 if (print) {
68f635b7
MK
125 if (lineq(bp->ut_line, "~"))
126 printf("\n");
127 else if (otime == 0)
c9af8668
BJ
128 printf(" still logged in\n");
129 else {
130 long delta;
131 if (otime < 0) {
132 otime = -otime;
fe6cb666 133 printf("- %s", crmsg);
c9af8668
BJ
134 } else
135 printf("- %5.5s",
136 ctime(&otime)+11);
137 delta = otime - bp->ut_time;
138 if (delta < SECDAY)
139 printf(" (%5.5s)\n",
140 asctime(gmtime(&delta))+11);
141 else
142 printf(" (%ld+%5.5s)\n",
143 delta / SECDAY,
144 asctime(gmtime(&delta))+11);
145 }
146 fflush(stdout);
b50e7db3
DW
147 if (++outrec >= maxrec)
148 exit(0);
c9af8668 149 }
fe6cb666 150 if (lineq(bp->ut_line, "~")) {
cf779ba2 151 for (i = 0; i < MAXTTYS; i++)
c9af8668 152 logouts[i] = -bp->ut_time;
fe6cb666
BJ
153 if (nameq(bp->ut_name, "shutdown"))
154 crmsg = "down ";
155 else
156 crmsg = "crash";
157 }
c9af8668
BJ
158 }
159 }
160 ct = ctime(&buf[0].ut_time);
161 printf("\nwtmp begins %10.10s %5.5s \n", ct, ct + 11);
162 exit(0);
163}
164
165onintr(signo)
166 int signo;
167{
168 char *ct;
169
170 if (signo == SIGQUIT)
171 signal(SIGQUIT, onintr);
172 ct = ctime(&buf[0].ut_time);
173 printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11);
131f9f19 174 fflush(stdout);
c9af8668
BJ
175 if (signo == SIGINT)
176 exit(1);
177}
178
179want(bp)
180 struct utmp *bp;
181{
182 register char **av;
183 register int ac;
184
fe6cb666 185 if (bp->ut_line[0] == '~' && bp->ut_name[0] == '\0')
c9af8668 186 strcpy(bp->ut_name, "reboot"); /* bandaid */
ac7e4ccf
SL
187 if (strncmp(bp->ut_line, "ftp", 3) == 0)
188 bp->ut_line[3] = '\0';
400ed241
JL
189 if (strncmp(bp->ut_line, "uucp", 4) == 0)
190 bp->ut_line[4] = '\0';
c9af8668
BJ
191 if (bp->ut_name[0] == 0)
192 return (0);
b50e7db3 193 if (nameargs == 0)
c9af8668
BJ
194 return (1);
195 av = argv;
b50e7db3
DW
196 for (ac = 0; ac < argc; ac++, av++) {
197 if (av[0][0] == '-')
198 continue;
c9af8668
BJ
199 if (nameq(*av, bp->ut_name) || lineq(*av, bp->ut_line))
200 return (1);
c9af8668
BJ
201 }
202 return (0);
203}
204
205char *
206strspl(left, right)
207 char *left, *right;
208{
209 char *res = (char *)malloc(strlen(left)+strlen(right)+1);
210
211 strcpy(res, left);
212 strcat(res, right);
213 return (res);
214}