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