Commit | Line | Data |
---|---|---|
69739ccc BJ |
1 | /* |
2 | * NAME: last | |
3 | * | |
4 | * SYNOPSIS: last [-] [name ...] | |
5 | * | |
6 | * DESCRIPTION: Displays login history of named users or tty's. | |
7 | * Last with no argument prints history for all users. | |
8 | * Last - displays history for all non-class users. | |
9 | * | |
10 | * EXTERNAL ROUTINES USED: bread.c blseek.c | |
11 | * | |
12 | * AUTHOR - Howard P. Katseff | |
13 | */ | |
14 | ||
15 | struct {char c1, c2, c3, c4;}; | |
16 | struct {long l1;}; | |
17 | int allflag; | |
18 | char buf[32]; | |
19 | extern fout; | |
20 | ||
21 | main(argc, argv) | |
22 | char **argv; { | |
23 | register char tty; | |
24 | register char **p; | |
25 | register char *q; | |
26 | int f, i, count; | |
27 | int intrp(), qintrp(); | |
28 | long lx; | |
29 | long otime, ntime; | |
30 | long logouts[128]; | |
31 | ||
32 | count = 0; | |
33 | fout = dup(1); | |
34 | if (allflag = argc==1) argv--; | |
35 | f = open("/usr/adm/wtmp", 0); | |
36 | if (f < 0) { | |
37 | printf("Can't open /usr/adm/wtmp\n"); | |
38 | exit(); | |
39 | } | |
40 | x: fstat(f, buf); | |
41 | ||
42 | for (i=0; i<127; i++) logouts[i] = 0; | |
43 | ||
44 | lx.c2 = 0; | |
45 | lx.c1 = buf[9]; | |
46 | lx.c3 = buf[10] & 0360; | |
47 | lx.c4 = buf[11]; | |
48 | ||
49 | blseek(f, lx, 0); | |
50 | lx =- 16; | |
51 | ||
52 | if ((signal(2,1) && 01) == 0) { | |
53 | signal(2, &intrp); | |
54 | signal(3, &qintrp); | |
55 | } | |
56 | ||
57 | for(;;) { | |
58 | if (lx < 16) { | |
59 | f = open("/usr/adm/owtmp", 0); | |
60 | if (count++ == 0 && f > 0) goto x; | |
61 | q = ctime(buf+10); | |
62 | printf("\nwtmp begins at %10.10s %5.5s \n", | |
63 | q, 11+q); | |
64 | flush(); | |
65 | exit(); | |
66 | } | |
67 | ||
68 | if (bread(f, buf+16, -16) < 16) { | |
69 | perror("impossible error"); | |
70 | exit(); | |
71 | } | |
72 | ||
73 | for (p = 1+argv; *p != -1; p++) { | |
74 | if (equal(*p, buf)) { | |
75 | tty = buf[8]; | |
76 | q = ctime(buf+10); | |
77 | if (tty >= ' ') | |
78 | printf("%8.8s tty%c %10.10s %5.5s ", | |
79 | buf, tty, q, 11+q); | |
80 | else | |
81 | printf("%8.8s tty^%c %10.10s %5.5s ", | |
82 | buf, tty+0140, q, 11+q); | |
83 | otime = (buf+10)->l1; | |
84 | ntime = logouts[tty]; | |
85 | if (ntime == 0) { | |
86 | printf(" still logged in\n"); | |
87 | } | |
88 | else { | |
89 | if (ntime <= 0) { | |
90 | ntime = -ntime; | |
91 | printf("- crash"); | |
92 | } | |
93 | else printf("- %5.5s", 11+ctime(&ntime)); | |
94 | otime = ntime - otime; | |
95 | otime =+ 231231630; | |
96 | if (otime < 231318030) | |
97 | printf(" (%5.5s)\n", 11+ | |
98 | ctime(&otime)); | |
99 | else | |
100 | printf(" (%ld+%5.5s)\n", | |
101 | (otime-231231630)/86400, | |
102 | 11+ctime(&otime)); | |
103 | } | |
104 | flush(); | |
105 | break; | |
106 | } | |
107 | } | |
108 | lx =- 16; | |
109 | ||
110 | if (buf[0] == '\0') { | |
111 | tty = buf[8]; | |
112 | if (tty == '~') | |
113 | for (i=0; i<127; i++) logouts[i] = -(buf+10)->l1; | |
114 | else logouts[tty] = (buf+10)->l1; | |
115 | } | |
116 | } | |
117 | } | |
118 | ||
119 | ||
120 | equal(c1, c2) | |
121 | char *c1, *c2; { | |
122 | int i; | |
123 | ||
124 | if (allflag && (*c2 != '\0' || *(c2+8) >= '|')) return(1); | |
125 | ||
126 | if (*(c1+1) == '\0') { | |
127 | if ((*c1 == '-') || (*c1 == 'x')) { | |
128 | if (*c2 == '\0' && *(c2+8) < '|') return(0); | |
129 | if (*c2 >= '0' && *c2 <= '9') return(0); | |
130 | if (*(c2+2) >= '0' && *(c2+2) <= '9') return(0); | |
131 | for(i=0; i<8; i++) if (*c2++ == '-') return(0); | |
132 | return(1); | |
133 | } | |
134 | ||
135 | if (*c1 == *(c2+8) && (*c1 >= '|' || *c2 != '\0')) return(1); | |
136 | ||
137 | return(0); | |
138 | } | |
139 | ||
140 | for (i=0; i<8; i++) { | |
141 | if (*c1 == '\0') return(*c2 == ' '); | |
142 | if (*c1++ != *c2++) return(0); | |
143 | } | |
144 | ||
145 | return(1); | |
146 | } | |
147 | ||
148 | ||
149 | intrp() { | |
150 | register char *q; | |
151 | ||
152 | signal(2,1); | |
153 | fout = 1; | |
154 | *(&fout+1) = 1; | |
155 | *(&fout+2) = 0; | |
156 | *(&fout+3) = 0; | |
157 | ||
158 | q = ctime(buf+10); | |
159 | printf("\ninterrupted at %10.10s %5.5s \n", | |
160 | q, 11+q); | |
161 | ||
162 | exit(); | |
163 | } | |
164 | qintrp() { | |
165 | register char *q; | |
166 | ||
167 | signal(3, &qintrp); | |
168 | fout = 1; | |
169 | *(&fout+1) = 1; | |
170 | *(&fout+2) = 0; | |
171 | *(&fout+3) = 0; | |
172 | ||
173 | q = ctime(buf+10); | |
174 | printf("\ninterrupted at %10.10s %5.5s \n", | |
175 | q, 11+q); | |
176 | ||
177 | } | |
178 | ||
179 | /* | |
180 | * NAMES: bread(), brseek(), blseek() | |
181 | * | |
182 | * DESCRIPTION: | |
183 | * This is a buffered read package which simulates read(), seek() and | |
184 | * lseek(). | |
185 | * Bread may be called with a negative nbytes which causes it to | |
186 | * read backwards. In this case, buffer should point to the first | |
187 | * byte following the buffer. If only a partial read is possible | |
188 | * (due to beginning of file), only the last bytes of the buffer | |
189 | * will be filled. | |
190 | */ | |
191 | ||
192 | int i, j, k; | |
193 | int nl, nr; | |
194 | char *next; | |
195 | char b[512]; | |
196 | ||
197 | bread(file, buff, nbytes) | |
198 | char *buff; { | |
199 | register nb; | |
200 | ||
201 | if (nbytes > 0) { | |
202 | for (nb=nbytes; nb>0; nb--) { | |
203 | if (nr == 0) { | |
204 | nr = read(file, next=b, 512); | |
205 | nl = 0; | |
206 | if (nr < 0) return(-1); | |
207 | if (nr == 0) return(nbytes-nb); | |
208 | } | |
209 | *buff++ = *next++; | |
210 | nr--; | |
211 | nl++; | |
212 | } | |
213 | } | |
214 | else { | |
215 | nbytes = -nbytes; | |
216 | for (nb=nbytes; nb>0; nb--) { | |
217 | if (nl == 0) { | |
218 | seek(file, -(512 + nr), 1); | |
219 | nl = read(file, b, 512); | |
220 | if (nl < 0) { | |
221 | for (k=511; k>0; k--) { | |
222 | seek(file, 1, 1); | |
223 | nl = read(file, b, k); | |
224 | if (nl >= 0) break; | |
225 | } | |
226 | if (nl < 0) return(nbytes-nb); | |
227 | } | |
228 | if (nl == 0) return(nbytes-nb); | |
229 | next = b + nl; | |
230 | nr = 0; | |
231 | } | |
232 | *--buff = *--next; | |
233 | nr++; | |
234 | nl--; | |
235 | } | |
236 | } | |
237 | return(nbytes); | |
238 | } | |
239 | ||
240 | ||
241 | brseek(file, offset, flag) { | |
242 | nl = 0; | |
243 | nr = 0; | |
244 | return(seek(file,offset,flag)); | |
245 | } | |
246 | ||
247 | ||
248 | blseek(file, offset, flag) | |
249 | long offset; { | |
250 | nl = 0; | |
251 | nr = 0; | |
252 | return(lseek(file,offset,flag)); | |
253 | } |