|
|
1.1 root 1: #ifndef lint
2: static char *sccsid = "@(#)lastcomm.c 4.9 (Berkeley) 9/8/83";
3: #endif
4:
5: /*
6: * last command
7: */
8: #include <sys/param.h>
9: #include <sys/acct.h>
10: #include <sys/file.h>
11:
12: #include <stdio.h>
13: #include <pwd.h>
14: #include <sys/stat.h>
15: #include <utmp.h>
16: #include <struct.h>
17: #include <ctype.h>
18:
19: struct acct buf[DEV_BSIZE / sizeof (struct acct)];
20:
21: time_t expand();
22: char *flagbits();
23: char *getname();
24: char *getdev();
25:
26: main(argc, argv)
27: char *argv[];
28: {
29: register int bn, cc;
30: register struct acct *acp;
31: int fd;
32: struct stat sb;
33:
34: fd = open("/usr/adm/acct", O_RDONLY);
35: if (fd < 0) {
36: perror("/usr/adm/acct");
37: exit(1);
38: }
39: fstat(fd, &sb);
40: for (bn = btodb(sb.st_size) - 1; bn >= 0; bn--) {
41: lseek(fd, bn * DEV_BSIZE, L_SET);
42: cc = read(fd, buf, DEV_BSIZE);
43: if (cc < 0) {
44: perror("read");
45: break;
46: }
47: acp = buf + (cc / sizeof (buf[0])) - 1;
48: for (; acp >= buf; acp--) {
49: register char *cp;
50: time_t x =
51: expand(acp->ac_utime) + expand(acp->ac_stime);
52:
53: acp->ac_comm[10] = '\0';
54: if (*acp->ac_comm == '\0')
55: strcpy(acp->ac_comm, "?");
56: for (cp = acp->ac_comm; *cp; cp++)
57: if (iscntrl(*cp))
58: *cp = '?';
59: if (!ok(argc, argv, acp) && argc != 1)
60: continue;
61: printf("%-*s %s %-*s %-*s %4d sec%s %.16s\n",
62: fldsiz(acct, ac_comm), acp->ac_comm,
63: flagbits(acp->ac_flag),
64: fldsiz(utmp, ut_name), getname(acp->ac_uid),
65: fldsiz(utmp, ut_line), getdev(acp->ac_tty),
66: x, x > 1 || x == 0 ? "s" : " ",
67: ctime(&acp->ac_btime));
68: }
69: }
70: }
71:
72: time_t
73: expand (t)
74: unsigned t;
75: {
76: register time_t nt;
77:
78: nt = t & 017777;
79: t >>= 13;
80: while (t) {
81: t--;
82: nt <<= 3;
83: }
84: return (nt);
85: }
86:
87: char *
88: flagbits(f)
89: register int f;
90: {
91: register int i = 0;
92: static char flags[20];
93:
94: #define BIT(flag, ch) flags[i++] = (f & flag) ? ch : ' '
95: BIT(ASU, 'S');
96: BIT(AFORK, 'F');
97: BIT(ACOMPAT, 'C');
98: BIT(ACORE, 'D');
99: BIT(AXSIG, 'X');
100: flags[i] = '\0';
101: return (flags);
102: }
103:
104: ok(argc, argv, acp)
105: register int argc;
106: register char *argv[];
107: register struct acct *acp;
108: {
109: register int j;
110:
111: for (j = 1; j < argc; j++)
112: if (strcmp(getname(acp->ac_uid), argv[j]) &&
113: strcmp(getdev(acp->ac_tty), argv[j]) &&
114: strcmp(acp->ac_comm, argv[j]))
115: break;
116: return (j == argc);
117: }
118:
119: /* should be done with nameserver or database */
120:
121: struct utmp utmp;
122:
123: #define NUID 2048
124: #define NMAX (sizeof (utmp.ut_name))
125:
126: char names[NUID][NMAX+1];
127: char outrangename[NMAX+1];
128: int outrangeuid = -1;
129:
130: char *
131: getname(uid)
132: {
133: register struct passwd *pw;
134: static init;
135: struct passwd *getpwent();
136:
137: if (uid >= 0 && uid < NUID && names[uid][0])
138: return (&names[uid][0]);
139: if (uid >= 0 && uid == outrangeuid)
140: return (outrangename);
141: if (init == 2) {
142: if (uid < NUID)
143: return (0);
144: setpwent();
145: while (pw = getpwent()) {
146: if (pw->pw_uid != uid)
147: continue;
148: outrangeuid = pw->pw_uid;
149: strncpy(outrangename, pw->pw_name, NMAX);
150: endpwent();
151: return (outrangename);
152: }
153: endpwent();
154: return (0);
155: }
156: if (init == 0)
157: setpwent(), init = 1;
158: while (pw = getpwent()) {
159: if (pw->pw_uid < 0 || pw->pw_uid >= NUID) {
160: if (pw->pw_uid == uid) {
161: outrangeuid = pw->pw_uid;
162: strncpy(outrangename, pw->pw_name, NMAX);
163: return (outrangename);
164: }
165: continue;
166: }
167: if (names[pw->pw_uid][0])
168: continue;
169: strncpy(names[pw->pw_uid], pw->pw_name, NMAX);
170: if (pw->pw_uid == uid)
171: return (&names[uid][0]);
172: }
173: init = 2;
174: endpwent();
175: return (0);
176: }
177:
178: #include <sys/dir.h>
179:
180: #define N_DEVS 43 /* hash value for device names */
181: #define NDEVS 500 /* max number of file names in /dev */
182:
183: struct devhash {
184: dev_t dev_dev;
185: char dev_name [fldsiz(utmp, ut_line) + 1];
186: struct devhash * dev_nxt;
187: };
188: struct devhash *dev_hash[N_DEVS];
189: struct devhash *dev_chain;
190: #define HASH(d) (((int) d) % N_DEVS)
191:
192: setupdevs()
193: {
194: register DIR * fd;
195: register struct devhash * hashtab;
196: register ndevs = NDEVS;
197: struct direct * dp;
198:
199: if ((fd = opendir("/dev")) == NULL) {
200: perror("/dev");
201: return;
202: }
203: hashtab = (struct devhash *)malloc(NDEVS * sizeof(struct devhash));
204: if (hashtab == (struct devhash *)0) {
205: fprintf(stderr, "No mem for dev table\n");
206: closedir(fd);
207: return;
208: }
209: while (dp = readdir(fd)) {
210: if (dp->d_ino == 0)
211: continue;
212: if (dp->d_name[0] != 't' && strcmp(dp->d_name, "console"))
213: continue;
214: strncpy(hashtab->dev_name, dp->d_name, fldsiz(utmp, ut_line));
215: hashtab->dev_name[fldsiz(utmp, ut_line)] = 0;
216: hashtab->dev_nxt = dev_chain;
217: dev_chain = hashtab;
218: hashtab++;
219: if (--ndevs <= 0)
220: break;
221: }
222: closedir(fd);
223: }
224:
225: char *
226: getdev(dev)
227: dev_t dev;
228: {
229: register struct devhash *hp, *nhp;
230: struct stat statb;
231: char name[fldsiz(devhash, dev_name) + 6];
232: static dev_t lastdev = (dev_t) -1;
233: static char *lastname;
234: static int init = 0;
235:
236: if (dev == NODEV)
237: return ("__");
238: if (dev == lastdev)
239: return (lastname);
240: if (!init) {
241: setupdevs();
242: init++;
243: }
244: for (hp = dev_hash[HASH(dev)]; hp; hp = hp->dev_nxt)
245: if (hp->dev_dev == dev) {
246: lastdev = dev;
247: return (lastname = hp->dev_name);
248: }
249: for (hp = dev_chain; hp; hp = nhp) {
250: nhp = hp->dev_nxt;
251: strcpy(name, "/dev/");
252: strcat(name, hp->dev_name);
253: if (stat(name, &statb) < 0) /* name truncated usually */
254: continue;
255: if ((statb.st_mode & S_IFMT) != S_IFCHR)
256: continue;
257: hp->dev_dev = statb.st_rdev;
258: hp->dev_nxt = dev_hash[HASH(hp->dev_dev)];
259: dev_hash[HASH(hp->dev_dev)] = hp;
260: if (hp->dev_dev == dev) {
261: dev_chain = nhp;
262: lastdev = dev;
263: return (lastname = hp->dev_name);
264: }
265: }
266: dev_chain = (struct devhash *) 0;
267: return ("??");
268: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.