BSD 3 development
[unix-history] / .ref-BSD-2 / upgrade / src / last.c
CommitLineData
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
15struct {char c1, c2, c3, c4;};
16struct {long l1;};
17int allflag;
18char buf[32];
19extern fout;
20
21main(argc, argv)
22char **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 }
40x: 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
120equal(c1, c2)
121char *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
149intrp() {
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 }
164qintrp() {
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
192int i, j, k;
193int nl, nr;
194char *next;
195char b[512];
196
197bread(file, buff, nbytes)
198char *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
241brseek(file, offset, flag) {
242 nl = 0;
243 nr = 0;
244 return(seek(file,offset,flag));
245 }
246
247
248blseek(file, offset, flag)
249long offset; {
250 nl = 0;
251 nr = 0;
252 return(lseek(file,offset,flag));
253 }