|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that the above copyright notice and this paragraph are
7: * duplicated in all such forms and that any documentation,
8: * advertising materials, and other materials related to such
9: * distribution and use acknowledge that the software was developed
10: * by the University of California, Berkeley. The name of the
11: * University may not be used to endorse or promote products derived
12: * from this software without specific prior written permission.
13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16: */
17:
18: #ifndef lint
19: char copyright[] =
20: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
21: All rights reserved.\n";
22: #endif /* not lint */
23:
24: #ifndef lint
25: static char sccsid[] = "@(#)lastcomm.c 5.6 (Berkeley) 6/29/88";
26: #endif /* not lint */
27:
28: /*
29: * last command
30: */
31: #include <sys/param.h>
32: #include <sys/acct.h>
33: #include <sys/file.h>
34: #include <sys/stat.h>
35: #include <utmp.h>
36: #include <struct.h>
37: #include <ctype.h>
38: #include <stdio.h>
39:
40: struct acct buf[DEV_BSIZE / sizeof (struct acct)];
41:
42: time_t expand();
43: char *flagbits();
44: char *getname();
45: char *getdev();
46:
47: main(argc, argv)
48: int argc;
49: char *argv[];
50: {
51: extern int optind;
52: extern char *optarg;
53: register struct acct *acp;
54: register int bn, cc;
55: struct stat sb;
56: int ch, fd;
57: char *acctfile, *strcpy(), *ctime();
58: long lseek();
59:
60: acctfile = NULL;
61: while ((ch = getopt(argc, argv, "f:")) != EOF)
62: switch((char)ch) {
63: case 'f':
64: acctfile = optarg;
65: break;
66: case '?':
67: default:
68: fputs("lastcomm [ -f file ]\n", stderr);
69: exit(1);
70: }
71: argv += optind;
72: if (!acctfile)
73: acctfile = "/usr/adm/acct";
74: fd = open(acctfile, O_RDONLY);
75: if (fd < 0) {
76: perror(acctfile);
77: exit(1);
78: }
79: (void)fstat(fd, &sb);
80: for (bn = btodb(sb.st_size); bn >= 0; bn--) {
81: (void)lseek(fd, (off_t)dbtob(bn), L_SET);
82: cc = read(fd, buf, DEV_BSIZE);
83: if (cc < 0) {
84: perror("read");
85: break;
86: }
87: acp = buf + (cc / sizeof (buf[0])) - 1;
88: for (; acp >= buf; acp--) {
89: register char *cp;
90: time_t x;
91:
92: if (acp->ac_comm[0] == '\0')
93: (void)strcpy(acp->ac_comm, "?");
94: for (cp = &acp->ac_comm[0];
95: cp < &acp->ac_comm[fldsiz(acct, ac_comm)] && *cp;
96: cp++)
97: if (!isascii(*cp) || iscntrl(*cp))
98: *cp = '?';
99: if (*argv && !ok(argv, acp))
100: continue;
101: x = expand(acp->ac_utime) + expand(acp->ac_stime);
102: printf("%-*.*s %s %-*s %-*s %6.2f secs %.16s\n",
103: fldsiz(acct, ac_comm),
104: fldsiz(acct, ac_comm),
105: acp->ac_comm, flagbits(acp->ac_flag),
106: fldsiz(utmp, ut_name),
107: (cp = getname(acp->ac_uid)) ? cp : "",
108: fldsiz(utmp, ut_line), getdev(acp->ac_tty),
109: x / (double)AHZ, ctime(&acp->ac_btime));
110: }
111: }
112: }
113:
114: time_t
115: expand (t)
116: unsigned t;
117: {
118: register time_t nt;
119:
120: nt = t & 017777;
121: t >>= 13;
122: while (t) {
123: t--;
124: nt <<= 3;
125: }
126: return (nt);
127: }
128:
129: char *
130: flagbits(f)
131: register int f;
132: {
133: static char flags[20];
134: char *p, *strcpy();
135:
136: #define BIT(flag, ch) if (f & flag) *p++ = ch;
137: p = strcpy(flags, "- ");
138: BIT(ASU, 'S');
139: BIT(AFORK, 'F');
140: BIT(ACOMPAT, 'C');
141: BIT(ACORE, 'D');
142: BIT(AXSIG, 'X');
143: return (flags);
144: }
145:
146: ok(argv, acp)
147: register char *argv[];
148: register struct acct *acp;
149: {
150: register char *cp;
151:
152: do {
153: if ((cp = getname(acp->ac_uid)) && !strcmp(cp, *argv) ||
154: (cp = getdev(acp->ac_tty)) && !strcmp(cp, *argv) ||
155: !strncmp(acp->ac_comm, *argv, fldsiz(acct, ac_comm)))
156: return(1);
157: } while (*++argv);
158: return(0);
159: }
160:
161: /* should be done with nameserver or database */
162:
163: #include <pwd.h>
164:
165: struct utmp utmp;
166: #define NMAX (sizeof (utmp.ut_name))
167: #define SCPYN(a, b) strncpy(a, b, NMAX)
168:
169: #define NCACHE 64 /* power of 2 */
170: #define CAMASK NCACHE - 1
171:
172: char *
173: getname(uid)
174: uid_t uid;
175: {
176: extern int _pw_stayopen;
177: static struct ncache {
178: uid_t uid;
179: char name[NMAX+1];
180: } c_uid[NCACHE];
181: register struct passwd *pw;
182: register struct ncache *cp;
183:
184: _pw_stayopen = 1;
185: cp = c_uid + (uid & CAMASK);
186: if (cp->uid == uid && *cp->name)
187: return(cp->name);
188: if (!(pw = getpwuid(uid)))
189: return((char *)0);
190: cp->uid = uid;
191: SCPYN(cp->name, pw->pw_name);
192: return(cp->name);
193: }
194:
195: #include <sys/dir.h>
196:
197: #define N_DEVS 43 /* hash value for device names */
198: #define NDEVS 500 /* max number of file names in /dev */
199:
200: struct devhash {
201: dev_t dev_dev;
202: char dev_name [fldsiz(utmp, ut_line) + 1];
203: struct devhash * dev_nxt;
204: };
205: struct devhash *dev_hash[N_DEVS];
206: struct devhash *dev_chain;
207: #define HASH(d) (((int) d) % N_DEVS)
208:
209: setupdevs()
210: {
211: register DIR * fd;
212: register struct devhash * hashtab;
213: register ndevs = NDEVS;
214: struct direct * dp;
215: char *malloc();
216:
217: /*NOSTRICT*/
218: hashtab = (struct devhash *)malloc(NDEVS * sizeof(struct devhash));
219: if (hashtab == (struct devhash *)0) {
220: fputs("No mem for dev table\n", stderr);
221: return;
222: }
223: if ((fd = opendir("/dev")) == NULL) {
224: perror("/dev");
225: return;
226: }
227: while (dp = readdir(fd)) {
228: if (dp->d_ino == 0)
229: continue;
230: if (dp->d_name[0] != 't' && strcmp(dp->d_name, "console"))
231: continue;
232: strncpy(hashtab->dev_name, dp->d_name, fldsiz(utmp, ut_line));
233: hashtab->dev_name[fldsiz(utmp, ut_line)] = 0;
234: hashtab->dev_nxt = dev_chain;
235: dev_chain = hashtab;
236: hashtab++;
237: if (--ndevs <= 0)
238: break;
239: }
240: closedir(fd);
241: }
242:
243: char *
244: getdev(dev)
245: dev_t dev;
246: {
247: register struct devhash *hp, *nhp;
248: struct stat statb;
249: char name[fldsiz(devhash, dev_name) + 6];
250: static dev_t lastdev = (dev_t) -1;
251: static char *lastname;
252: static int init = 0;
253: char *strcpy(), *strcat();
254:
255: if (dev == NODEV)
256: return ("__");
257: if (dev == lastdev)
258: return (lastname);
259: if (!init) {
260: setupdevs();
261: init++;
262: }
263: for (hp = dev_hash[HASH(dev)]; hp; hp = hp->dev_nxt)
264: if (hp->dev_dev == dev) {
265: lastdev = dev;
266: return (lastname = hp->dev_name);
267: }
268: for (hp = dev_chain; hp; hp = nhp) {
269: nhp = hp->dev_nxt;
270: strcpy(name, "/dev/");
271: strcat(name, hp->dev_name);
272: if (stat(name, &statb) < 0) /* name truncated usually */
273: continue;
274: if ((statb.st_mode & S_IFMT) != S_IFCHR)
275: continue;
276: hp->dev_dev = statb.st_rdev;
277: hp->dev_nxt = dev_hash[HASH(hp->dev_dev)];
278: dev_hash[HASH(hp->dev_dev)] = hp;
279: if (hp->dev_dev == dev) {
280: dev_chain = nhp;
281: lastdev = dev;
282: return (lastname = hp->dev_name);
283: }
284: }
285: dev_chain = (struct devhash *) 0;
286: return ("??");
287: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.