|
|
1.1 root 1: #ifndef lint
2: static char *sccsid = "@(#)last.c 4.8 (Berkeley) 9/25/83";
3: #endif
4:
5: /*
6: * last
7: */
8: #include <sys/types.h>
9: #include <stdio.h>
10: #include <signal.h>
11: #include <sys/stat.h>
12: #include <utmp.h>
13:
14: #define NMAX sizeof(buf[0].ut_name)
15: #define LMAX sizeof(buf[0].ut_line)
16: #define HMAX sizeof(buf[0].ut_host)
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))
21: #define hosteq(a,b) (!strncmp(a,b,HMAX))
22:
23: #define MAXTTYS 256
24:
25: char **argv;
26: int argc;
27: int nameargs;
28:
29: struct utmp buf[128];
30: char ttnames[MAXTTYS][LMAX+1];
31: long logouts[MAXTTYS];
32:
33: char *ctime(), *strspl();
34: int onintr();
35:
36: main(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;
46: char * crmsg = (char *)0;
47: long crtime;
48: long outrec = 0;
49: long maxrec = 0x7fffffffL;
50:
51: time(&buf[0].ut_time);
52: ac--, av++;
53: nameargs = argc = ac;
54: argv = av;
55: for (i = 0; i < argc; i++) {
56: if (argv[i][0] == '-' &&
57: argv[i][1] >= '0' && argv[i][1] <= '9') {
58: maxrec = atoi(argv[i]+1);
59: nameargs--;
60: continue;
61: }
62: if (strlen(argv[i])>2)
63: continue;
64: if (!strcmp(argv[i], "~"))
65: continue;
66: if (!strcmp(argv[i], "ftp"))
67: continue;
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);
90: printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s ",
91: NMAX, NMAX, bp->ut_name,
92: LMAX, LMAX, bp->ut_line,
93: HMAX, HMAX, bp->ut_host,
94: ct, 11+ct);
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));
100: otime = logouts[i];
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 (lineq(bp->ut_line, "~"))
112: printf("\n");
113: else if (otime == 0)
114: printf(" still logged in\n");
115: else {
116: long delta;
117: if (otime < 0) {
118: otime = -otime;
119: printf("- %s", crmsg);
120: } else
121: printf("- %5.5s",
122: ctime(&otime)+11);
123: delta = otime - bp->ut_time;
124: if (delta < SECDAY)
125: printf(" (%5.5s)\n",
126: asctime(gmtime(&delta))+11);
127: else
128: printf(" (%ld+%5.5s)\n",
129: delta / SECDAY,
130: asctime(gmtime(&delta))+11);
131: }
132: fflush(stdout);
133: if (++outrec >= maxrec)
134: exit(0);
135: }
136: if (lineq(bp->ut_line, "~")) {
137: for (i = 0; i < MAXTTYS; i++)
138: logouts[i] = -bp->ut_time;
139: if (nameq(bp->ut_name, "shutdown"))
140: crmsg = "down ";
141: else
142: crmsg = "crash";
143: }
144: }
145: }
146: ct = ctime(&buf[0].ut_time);
147: printf("\nwtmp begins %10.10s %5.5s \n", ct, ct + 11);
148: exit(0);
149: }
150:
151: onintr(signo)
152: int signo;
153: {
154: char *ct;
155:
156: if (signo == SIGQUIT)
157: signal(SIGQUIT, onintr);
158: ct = ctime(&buf[0].ut_time);
159: printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11);
160: if (signo == SIGINT)
161: exit(1);
162: }
163:
164: want(bp)
165: struct utmp *bp;
166: {
167: register char **av;
168: register int ac;
169:
170: if (bp->ut_line[0] == '~' && bp->ut_name[0] == '\0')
171: strcpy(bp->ut_name, "reboot"); /* bandaid */
172: if (strncmp(bp->ut_line, "ftp", 3) == 0)
173: bp->ut_line[3] = '\0';
174: if (bp->ut_name[0] == 0)
175: return (0);
176: if (nameargs == 0)
177: return (1);
178: av = argv;
179: for (ac = 0; ac < argc; ac++, av++) {
180: if (av[0][0] == '-')
181: continue;
182: if (nameq(*av, bp->ut_name) || lineq(*av, bp->ut_line))
183: return (1);
184: }
185: return (0);
186: }
187:
188: char *
189: strspl(left, right)
190: char *left, *right;
191: {
192: char *res = (char *)malloc(strlen(left)+strlen(right)+1);
193:
194: strcpy(res, left);
195: strcat(res, right);
196: return (res);
197: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.