|
|
1.1 root 1: static char *sccsid = "@(#)last.c 4.2 (Berkeley) 10/9/80";
2: /*
3: * last
4: */
5: #include <sys/types.h>
6: #include <stdio.h>
7: #include <signal.h>
8: #include <sys/stat.h>
9: #include <utmp.h>
10:
11: #define NMAX sizeof(buf[0].ut_name)
12: #define LMAX sizeof(buf[0].ut_line)
13: #define SECDAY (24*60*60)
14:
15: #define lineq(a,b) (!strncmp(a,b,LMAX))
16: #define nameq(a,b) (!strncmp(a,b,NMAX))
17:
18: #define MAXTTYS 256
19:
20: char **argv;
21: int argc;
22:
23: struct utmp buf[128];
24: char ttnames[MAXTTYS][LMAX+1];
25: long logouts[MAXTTYS];
26:
27: char *wfile = "/usr/adm/wtmp";
28:
29: char *ctime(), *strspl();
30: int onintr();
31:
32: main(ac, av)
33: char **av;
34: {
35: register int i, k;
36: int bl, wtmp;
37: char *ct;
38: register struct utmp *bp;
39: long otime;
40: struct stat stb;
41: int print;
42:
43: time(&buf[0].ut_time);
44: ac--, av++;
45: argc = ac;
46: argv = av;
47: if (argc >= 2 && strcmp(argv[0], "-f") == 0) {
48: wfile = argv[1];
49: argv += 2;
50: argc -= 2;
51: }
52: for (i = 0; i < argc; i++) {
53: if (strlen(argv[i])>2)
54: continue;
55: if (!strcmp(argv[i], "~"))
56: continue;
57: if (getpwnam(argv[i]))
58: continue;
59: argv[i] = strspl("tty", argv[i]);
60: }
61: wtmp = open(wfile, 0);
62: if (wtmp < 0) {
63: perror(wfile);
64: exit(1);
65: }
66: fstat(wtmp, &stb);
67: bl = (stb.st_size + sizeof (buf)-1) / sizeof (buf);
68: if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
69: signal(SIGINT, onintr);
70: signal(SIGQUIT, onintr);
71: }
72: for (bl--; bl >= 0; bl--) {
73: lseek(wtmp, bl * sizeof (buf), 0);
74: bp = &buf[read(wtmp, buf, sizeof (buf)) / sizeof(buf[0]) - 1];
75: for ( ; bp >= buf; bp--) {
76: print = want(bp);
77: if (print) {
78: ct = ctime(&bp->ut_time);
79: printf("%-*.*s %-*.*s %10.10s %5.5s ",
80: NMAX, NMAX, bp->ut_name,
81: LMAX, LMAX, bp->ut_line, ct, 11+ct);
82: }
83: for (i = 0; i < MAXTTYS; i++) {
84: if (ttnames[i][0] == 0) {
85: strncpy(ttnames[i], bp->ut_line,
86: sizeof(bp->ut_line));
87: otime = logouts[i];
88: logouts[i] = bp->ut_time;
89: break;
90: }
91: if (lineq(ttnames[i], bp->ut_line)) {
92: otime = logouts[i];
93: logouts[i] = bp->ut_time;
94: break;
95: }
96: }
97: if (print) {
98: if (otime == 0)
99: printf(" still logged in\n");
100: else {
101: long delta;
102: if (otime < 0) {
103: otime = -otime;
104: printf("- crash");
105: } else
106: printf("- %5.5s",
107: ctime(&otime)+11);
108: delta = otime - bp->ut_time;
109: if (delta < SECDAY)
110: printf(" (%5.5s)\n",
111: asctime(gmtime(&delta))+11);
112: else
113: printf(" (%ld+%5.5s)\n",
114: delta / SECDAY,
115: asctime(gmtime(&delta))+11);
116: }
117: fflush(stdout);
118: }
119: if (!strcmp(bp->ut_name, "reboot"))
120: for (i = 0; i < MAXTTYS; i++)
121: logouts[i] = -bp->ut_time;
122: }
123: }
124: ct = ctime(&buf[0].ut_time);
125: printf("\nwtmp begins %10.10s %5.5s \n", ct, ct + 11);
126: exit(0);
127: }
128:
129: onintr(signo)
130: int signo;
131: {
132: char *ct;
133:
134: if (signo == SIGQUIT)
135: signal(SIGQUIT, onintr);
136: ct = ctime(&buf[0].ut_time);
137: printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11);
138: if (signo == SIGINT)
139: exit(1);
140: }
141:
142: want(bp)
143: struct utmp *bp;
144: {
145: register char **av;
146: register int ac;
147:
148: if (bp->ut_line[0] == '~')
149: strcpy(bp->ut_name, "reboot"); /* bandaid */
150: if (bp->ut_name[0] == 0)
151: return (0);
152: if (argc == 0)
153: return (1);
154: av = argv;
155: for (ac = 0; ac < argc; ac++) {
156: if (nameq(*av, bp->ut_name) || lineq(*av, bp->ut_line))
157: return (1);
158: av++;
159: }
160: return (0);
161: }
162:
163: char *
164: strspl(left, right)
165: char *left, *right;
166: {
167: char *res = (char *)malloc(strlen(left)+strlen(right)+1);
168:
169: strcpy(res, left);
170: strcat(res, right);
171: return (res);
172: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.