|
|
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: (1) source distributions retain this entire copyright
7: * notice and comment, and (2) distributions including binaries display
8: * the following acknowledgement: ``This product includes software
9: * developed by the University of California, Berkeley and its contributors''
10: * in the documentation or other materials provided with the distribution
11: * and in all advertising materials mentioning features or use of this
12: * software. Neither the name of the University nor the names of its
13: * contributors may be used to endorse or promote products derived
14: * from this software without specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: char copyright[] =
22: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
23: All rights reserved.\n";
24: #endif /* not lint */
25:
26: #ifndef lint
27: static char sccsid[] = "@(#)lastcomm.c 5.11 (Berkeley) 6/1/90";
28: #endif /* not lint */
29:
30: /*
31: * last command
32: */
33: #include <sys/param.h>
34: #include <sys/acct.h>
35: #include <sys/file.h>
36: #include <sys/stat.h>
37: #include <utmp.h>
38: #include <struct.h>
39: #include <ctype.h>
40: #include <stdio.h>
41: #include "pathnames.h"
42:
43: struct acct buf[DEV_BSIZE / sizeof (struct acct)];
44:
45: time_t expand();
46: char *flagbits();
47: char *getdev();
48:
49: main(argc, argv)
50: int argc;
51: char *argv[];
52: {
53: extern int optind;
54: extern char *optarg;
55: register struct acct *acp;
56: register int bn, cc;
57: struct stat sb;
58: int ch, fd;
59: char *acctfile, *ctime(), *strcpy(), *user_from_uid();
60: long lseek();
61:
62: acctfile = _PATH_ACCT;
63: while ((ch = getopt(argc, argv, "f:")) != EOF)
64: switch((char)ch) {
65: case 'f':
66: acctfile = optarg;
67: break;
68: case '?':
69: default:
70: fputs("lastcomm [ -f file ]\n", stderr);
71: exit(1);
72: }
73: argv += optind;
74:
75: fd = open(acctfile, O_RDONLY);
76: if (fd < 0) {
77: perror(acctfile);
78: exit(1);
79: }
80: (void)fstat(fd, &sb);
81: setpassent(1);
82: for (bn = btodb(sb.st_size); bn >= 0; bn--) {
83: (void)lseek(fd, (off_t)dbtob(bn), L_SET);
84: cc = read(fd, buf, DEV_BSIZE);
85: if (cc < 0) {
86: perror("read");
87: break;
88: }
89: acp = buf + (cc / sizeof (buf[0])) - 1;
90: for (; acp >= buf; acp--) {
91: register char *cp;
92: time_t x;
93:
94: if (acp->ac_comm[0] == '\0')
95: (void)strcpy(acp->ac_comm, "?");
96: for (cp = &acp->ac_comm[0];
97: cp < &acp->ac_comm[fldsiz(acct, ac_comm)] && *cp;
98: cp++)
99: if (!isascii(*cp) || iscntrl(*cp))
100: *cp = '?';
101: if (*argv && !ok(argv, acp))
102: continue;
103: x = expand(acp->ac_utime) + expand(acp->ac_stime);
104: printf("%-*.*s %s %-*s %-*s %6.2f secs %.16s\n",
105: fldsiz(acct, ac_comm), fldsiz(acct, ac_comm),
106: acp->ac_comm, flagbits(acp->ac_flag),
107: UT_NAMESIZE, user_from_uid(acp->ac_uid, 0),
108: UT_LINESIZE, 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: char *user_from_uid();
152:
153: do {
154: cp = user_from_uid(acp->ac_uid, 0);
155: if (!strcmp(cp, *argv))
156: return(1);
157: if ((cp = getdev(acp->ac_tty)) && !strcmp(cp, *argv))
158: return(1);
159: if (!strncmp(acp->ac_comm, *argv, fldsiz(acct, ac_comm)))
160: return(1);
161: } while (*++argv);
162: return(0);
163: }
164:
165: #include <sys/dir.h>
166:
167: #define N_DEVS 43 /* hash value for device names */
168: #define NDEVS 500 /* max number of file names in /dev */
169:
170: struct devhash {
171: dev_t dev_dev;
172: char dev_name [UT_LINESIZE + 1];
173: struct devhash * dev_nxt;
174: };
175: struct devhash *dev_hash[N_DEVS];
176: struct devhash *dev_chain;
177: #define HASH(d) (((int) d) % N_DEVS)
178:
179: setupdevs()
180: {
181: register DIR * fd;
182: register struct devhash * hashtab;
183: register ndevs = NDEVS;
184: struct direct * dp;
185: char *malloc();
186:
187: /*NOSTRICT*/
188: hashtab = (struct devhash *)malloc(NDEVS * sizeof(struct devhash));
189: if (hashtab == (struct devhash *)0) {
190: fputs("No mem for dev table\n", stderr);
191: return;
192: }
193: if ((fd = opendir(_PATH_DEV)) == NULL) {
194: perror(_PATH_DEV);
195: return;
196: }
197: while (dp = readdir(fd)) {
198: if (dp->d_ino == 0)
199: continue;
200: if (dp->d_name[0] != 't' && strcmp(dp->d_name, "console"))
201: continue;
202: (void)strncpy(hashtab->dev_name, dp->d_name, UT_LINESIZE);
203: hashtab->dev_name[UT_LINESIZE] = 0;
204: hashtab->dev_nxt = dev_chain;
205: dev_chain = hashtab;
206: hashtab++;
207: if (--ndevs <= 0)
208: break;
209: }
210: closedir(fd);
211: }
212:
213: char *
214: getdev(dev)
215: dev_t dev;
216: {
217: register struct devhash *hp, *nhp;
218: struct stat statb;
219: char name[fldsiz(devhash, dev_name) + 6];
220: static dev_t lastdev = (dev_t) -1;
221: static char *lastname;
222: static int init = 0;
223: char *strcpy(), *strcat();
224:
225: if (dev == NODEV)
226: return ("__");
227: if (dev == lastdev)
228: return (lastname);
229: if (!init) {
230: setupdevs();
231: init++;
232: }
233: for (hp = dev_hash[HASH(dev)]; hp; hp = hp->dev_nxt)
234: if (hp->dev_dev == dev) {
235: lastdev = dev;
236: return (lastname = hp->dev_name);
237: }
238: for (hp = dev_chain; hp; hp = nhp) {
239: nhp = hp->dev_nxt;
240: (void)strcpy(name, _PATH_DEV);
241: strcat(name, hp->dev_name);
242: if (stat(name, &statb) < 0) /* name truncated usually */
243: continue;
244: if ((statb.st_mode & S_IFMT) != S_IFCHR)
245: continue;
246: hp->dev_dev = statb.st_rdev;
247: hp->dev_nxt = dev_hash[HASH(hp->dev_dev)];
248: dev_hash[HASH(hp->dev_dev)] = hp;
249: if (hp->dev_dev == dev) {
250: dev_chain = nhp;
251: lastdev = dev;
252: return (lastname = hp->dev_name);
253: }
254: }
255: dev_chain = (struct devhash *) 0;
256: return ("??");
257: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.