|
|
1.1 root 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
8: char copyright[] =
9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10: All rights reserved.\n";
11: #endif not lint
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)last.c 5.3 (Berkeley) 5/15/86";
15: #endif not lint
16:
17: /*
18: * last
19: */
20: #include <sys/types.h>
21: #include <stdio.h>
22: #include <signal.h>
23: #include <sys/stat.h>
24: #include <utmp.h>
25:
26: #define NMAX sizeof(buf[0].ut_name)
27: #define LMAX sizeof(buf[0].ut_line)
28: #define HMAX sizeof(buf[0].ut_host)
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))
33: #define hosteq(a,b) (!strncmp(a,b,HMAX))
34:
35: #define MAXTTYS 256
36:
37: char **argv;
38: int argc;
39: int nameargs;
40:
41: struct utmp buf[128];
42: char ttnames[MAXTTYS][LMAX+1];
43: long logouts[MAXTTYS];
44:
45: char *ctime(), *strspl();
46: int onintr();
47:
48: main(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;
58: char * crmsg = (char *)0;
59: long crtime;
60: long outrec = 0;
61: long maxrec = 0x7fffffffL;
62:
63: time(&buf[0].ut_time);
64: ac--, av++;
65: nameargs = argc = ac;
66: argv = av;
67: for (i = 0; i < argc; i++) {
68: if (argv[i][0] == '-' &&
69: argv[i][1] >= '0' && argv[i][1] <= '9') {
70: maxrec = atoi(argv[i]+1);
71: nameargs--;
72: continue;
73: }
74: if (strlen(argv[i])>2)
75: continue;
76: if (!strcmp(argv[i], "~"))
77: continue;
78: if (!strcmp(argv[i], "ftp"))
79: continue;
80: if (!strcmp(argv[i], "uucp"))
81: continue;
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);
104: printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s ",
105: NMAX, NMAX, bp->ut_name,
106: LMAX, LMAX, bp->ut_line,
107: HMAX, HMAX, bp->ut_host,
108: ct, 11+ct);
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));
114: otime = logouts[i];
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) {
125: if (lineq(bp->ut_line, "~"))
126: printf("\n");
127: else if (otime == 0)
128: printf(" still logged in\n");
129: else {
130: long delta;
131: if (otime < 0) {
132: otime = -otime;
133: printf("- %s", crmsg);
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);
147: if (++outrec >= maxrec)
148: exit(0);
149: }
150: if (lineq(bp->ut_line, "~")) {
151: for (i = 0; i < MAXTTYS; i++)
152: logouts[i] = -bp->ut_time;
153: if (nameq(bp->ut_name, "shutdown"))
154: crmsg = "down ";
155: else
156: crmsg = "crash";
157: }
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:
165: onintr(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);
174: fflush(stdout);
175: if (signo == SIGINT)
176: exit(1);
177: }
178:
179: want(bp)
180: struct utmp *bp;
181: {
182: register char **av;
183: register int ac;
184:
185: if (bp->ut_line[0] == '~' && bp->ut_name[0] == '\0')
186: strcpy(bp->ut_name, "reboot"); /* bandaid */
187: if (strncmp(bp->ut_line, "ftp", 3) == 0)
188: bp->ut_line[3] = '\0';
189: if (strncmp(bp->ut_line, "uucp", 4) == 0)
190: bp->ut_line[4] = '\0';
191: if (bp->ut_name[0] == 0)
192: return (0);
193: if (nameargs == 0)
194: return (1);
195: av = argv;
196: for (ac = 0; ac < argc; ac++, av++) {
197: if (av[0][0] == '-')
198: continue;
199: if (nameq(*av, bp->ut_name) || lineq(*av, bp->ut_line))
200: return (1);
201: }
202: return (0);
203: }
204:
205: char *
206: strspl(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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.