Add copyright
[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
22e155fc
DF
14static char sccsid[] = "@(#)last.c 5.1 (Berkeley) %G%";
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;
c9af8668
BJ
80 if (getpwnam(argv[i]))
81 continue;
82 argv[i] = strspl("tty", argv[i]);
83 }
84 wtmp = open("/usr/adm/wtmp", 0);
85 if (wtmp < 0) {
86 perror("/usr/adm/wtmp");
87 exit(1);
88 }
89 fstat(wtmp, &stb);
90 bl = (stb.st_size + sizeof (buf)-1) / sizeof (buf);
91 if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
92 signal(SIGINT, onintr);
93 signal(SIGQUIT, onintr);
94 }
95 for (bl--; bl >= 0; bl--) {
96 lseek(wtmp, bl * sizeof (buf), 0);
97 bp = &buf[read(wtmp, buf, sizeof (buf)) / sizeof(buf[0]) - 1];
98 for ( ; bp >= buf; bp--) {
99 print = want(bp);
100 if (print) {
101 ct = ctime(&bp->ut_time);
68f635b7 102 printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s ",
c9af8668 103 NMAX, NMAX, bp->ut_name,
37c640e2
SL
104 LMAX, LMAX, bp->ut_line,
105 HMAX, HMAX, bp->ut_host,
106 ct, 11+ct);
c9af8668
BJ
107 }
108 for (i = 0; i < MAXTTYS; i++) {
109 if (ttnames[i][0] == 0) {
110 strncpy(ttnames[i], bp->ut_line,
111 sizeof(bp->ut_line));
cf779ba2 112 otime = logouts[i];
c9af8668
BJ
113 logouts[i] = bp->ut_time;
114 break;
115 }
116 if (lineq(ttnames[i], bp->ut_line)) {
117 otime = logouts[i];
118 logouts[i] = bp->ut_time;
119 break;
120 }
121 }
122 if (print) {
68f635b7
MK
123 if (lineq(bp->ut_line, "~"))
124 printf("\n");
125 else if (otime == 0)
c9af8668
BJ
126 printf(" still logged in\n");
127 else {
128 long delta;
129 if (otime < 0) {
130 otime = -otime;
fe6cb666 131 printf("- %s", crmsg);
c9af8668
BJ
132 } else
133 printf("- %5.5s",
134 ctime(&otime)+11);
135 delta = otime - bp->ut_time;
136 if (delta < SECDAY)
137 printf(" (%5.5s)\n",
138 asctime(gmtime(&delta))+11);
139 else
140 printf(" (%ld+%5.5s)\n",
141 delta / SECDAY,
142 asctime(gmtime(&delta))+11);
143 }
144 fflush(stdout);
b50e7db3
DW
145 if (++outrec >= maxrec)
146 exit(0);
c9af8668 147 }
fe6cb666 148 if (lineq(bp->ut_line, "~")) {
cf779ba2 149 for (i = 0; i < MAXTTYS; i++)
c9af8668 150 logouts[i] = -bp->ut_time;
fe6cb666
BJ
151 if (nameq(bp->ut_name, "shutdown"))
152 crmsg = "down ";
153 else
154 crmsg = "crash";
155 }
c9af8668
BJ
156 }
157 }
158 ct = ctime(&buf[0].ut_time);
159 printf("\nwtmp begins %10.10s %5.5s \n", ct, ct + 11);
160 exit(0);
161}
162
163onintr(signo)
164 int signo;
165{
166 char *ct;
167
168 if (signo == SIGQUIT)
169 signal(SIGQUIT, onintr);
170 ct = ctime(&buf[0].ut_time);
171 printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11);
172 if (signo == SIGINT)
173 exit(1);
174}
175
176want(bp)
177 struct utmp *bp;
178{
179 register char **av;
180 register int ac;
181
fe6cb666 182 if (bp->ut_line[0] == '~' && bp->ut_name[0] == '\0')
c9af8668 183 strcpy(bp->ut_name, "reboot"); /* bandaid */
ac7e4ccf
SL
184 if (strncmp(bp->ut_line, "ftp", 3) == 0)
185 bp->ut_line[3] = '\0';
c9af8668
BJ
186 if (bp->ut_name[0] == 0)
187 return (0);
b50e7db3 188 if (nameargs == 0)
c9af8668
BJ
189 return (1);
190 av = argv;
b50e7db3
DW
191 for (ac = 0; ac < argc; ac++, av++) {
192 if (av[0][0] == '-')
193 continue;
c9af8668
BJ
194 if (nameq(*av, bp->ut_name) || lineq(*av, bp->ut_line))
195 return (1);
c9af8668
BJ
196 }
197 return (0);
198}
199
200char *
201strspl(left, right)
202 char *left, *right;
203{
204 char *res = (char *)malloc(strlen(left)+strlen(right)+1);
205
206 strcpy(res, left);
207 strcat(res, right);
208 return (res);
209}