|
|
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;
1.1.1.2 ! root 61: printf("%-*s %s %-*s %-*s %4d m%s %.16s\n",
1.1 root 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(ACORE, 'D');
98: BIT(AXSIG, 'X');
99: flags[i] = '\0';
100: return (flags);
101: }
102:
103: ok(argc, argv, acp)
104: register int argc;
105: register char *argv[];
106: register struct acct *acp;
107: {
108: register int j;
109:
110: for (j = 1; j < argc; j++)
111: if (strcmp(getname(acp->ac_uid), argv[j]) &&
112: strcmp(getdev(acp->ac_tty), argv[j]) &&
113: strcmp(acp->ac_comm, argv[j]))
114: break;
115: return (j == argc);
116: }
117:
118: /* should be done with nameserver or database */
119:
120: struct utmp utmp;
121:
122: #define NUID 2048
123: #define NMAX (sizeof (utmp.ut_name))
124:
125: char names[NUID][NMAX+1];
126: char outrangename[NMAX+1];
127: int outrangeuid = -1;
128:
129: char *
130: getname(uid)
131: {
132: register struct passwd *pw;
133: static init;
134: struct passwd *getpwent();
135:
136: if (uid >= 0 && uid < NUID && names[uid][0])
137: return (&names[uid][0]);
138: if (uid >= 0 && uid == outrangeuid)
139: return (outrangename);
140: if (init == 2) {
141: if (uid < NUID)
142: return (0);
143: setpwent();
144: while (pw = getpwent()) {
145: if (pw->pw_uid != uid)
146: continue;
147: outrangeuid = pw->pw_uid;
148: strncpy(outrangename, pw->pw_name, NMAX);
149: endpwent();
150: return (outrangename);
151: }
152: endpwent();
153: return (0);
154: }
155: if (init == 0)
156: setpwent(), init = 1;
157: while (pw = getpwent()) {
158: if (pw->pw_uid < 0 || pw->pw_uid >= NUID) {
159: if (pw->pw_uid == uid) {
160: outrangeuid = pw->pw_uid;
161: strncpy(outrangename, pw->pw_name, NMAX);
162: return (outrangename);
163: }
164: continue;
165: }
166: if (names[pw->pw_uid][0])
167: continue;
168: strncpy(names[pw->pw_uid], pw->pw_name, NMAX);
169: if (pw->pw_uid == uid)
170: return (&names[uid][0]);
171: }
172: init = 2;
173: endpwent();
174: return (0);
175: }
176:
177: #include <sys/dir.h>
178:
179: #define N_DEVS 43 /* hash value for device names */
180: #define NDEVS 500 /* max number of file names in /dev */
181:
182: struct devhash {
183: dev_t dev_dev;
184: char dev_name [fldsiz(utmp, ut_line) + 1];
185: struct devhash * dev_nxt;
186: };
187: struct devhash *dev_hash[N_DEVS];
188: struct devhash *dev_chain;
189: #define HASH(d) (((int) d) % N_DEVS)
190:
191: setupdevs()
192: {
193: register DIR * fd;
194: register struct devhash * hashtab;
195: register ndevs = NDEVS;
196: struct direct * dp;
197:
198: if ((fd = opendir("/dev")) == NULL) {
199: perror("/dev");
200: return;
201: }
202: hashtab = (struct devhash *)malloc(NDEVS * sizeof(struct devhash));
203: if (hashtab == (struct devhash *)0) {
204: fprintf(stderr, "No mem for dev table\n");
205: closedir(fd);
206: return;
207: }
208: while (dp = readdir(fd)) {
209: if (dp->d_ino == 0)
210: continue;
211: if (dp->d_name[0] != 't' && strcmp(dp->d_name, "console"))
212: continue;
213: strncpy(hashtab->dev_name, dp->d_name, fldsiz(utmp, ut_line));
214: hashtab->dev_name[fldsiz(utmp, ut_line)] = 0;
215: hashtab->dev_nxt = dev_chain;
216: dev_chain = hashtab;
217: hashtab++;
218: if (--ndevs <= 0)
219: break;
220: }
221: closedir(fd);
222: }
223:
224: char *
225: getdev(dev)
226: dev_t dev;
227: {
228: register struct devhash *hp, *nhp;
229: struct stat statb;
230: char name[fldsiz(devhash, dev_name) + 6];
231: static dev_t lastdev = (dev_t) -1;
232: static char *lastname;
233: static int init = 0;
234:
235: if (dev == NODEV)
236: return ("__");
237: if (dev == lastdev)
238: return (lastname);
239: if (!init) {
240: setupdevs();
241: init++;
242: }
243: for (hp = dev_hash[HASH(dev)]; hp; hp = hp->dev_nxt)
244: if (hp->dev_dev == dev) {
245: lastdev = dev;
246: return (lastname = hp->dev_name);
247: }
248: for (hp = dev_chain; hp; hp = nhp) {
249: nhp = hp->dev_nxt;
250: strcpy(name, "/dev/");
251: strcat(name, hp->dev_name);
252: if (stat(name, &statb) < 0) /* name truncated usually */
253: continue;
254: if ((statb.st_mode & S_IFMT) != S_IFCHR)
255: continue;
256: hp->dev_dev = statb.st_rdev;
257: hp->dev_nxt = dev_hash[HASH(hp->dev_dev)];
258: dev_hash[HASH(hp->dev_dev)] = hp;
259: if (hp->dev_dev == dev) {
260: dev_chain = nhp;
261: lastdev = dev;
262: return (lastname = hp->dev_name);
263: }
264: }
265: dev_chain = (struct devhash *) 0;
266: return ("??");
267: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.