xref: /titanic_44/usr/src/cmd/lastcomm/lc_exacct.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
30*7c478bd9Sstevel@tonic-gate #include <errno.h>
31*7c478bd9Sstevel@tonic-gate #include "lastcomm.h"
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate /* ARGSUSED1 */
34*7c478bd9Sstevel@tonic-gate static void
skip_group(ea_file_t * ef,uint_t nobjs)35*7c478bd9Sstevel@tonic-gate skip_group(ea_file_t *ef, uint_t nobjs)
36*7c478bd9Sstevel@tonic-gate {
37*7c478bd9Sstevel@tonic-gate 	ea_object_t curr_obj;
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate 	if (ea_previous_object(ef, &curr_obj) == -1) {
40*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("lastcomm: "
41*7c478bd9Sstevel@tonic-gate 		    "corrupted exacct file\n"));
42*7c478bd9Sstevel@tonic-gate 		exit(1);
43*7c478bd9Sstevel@tonic-gate 	}
44*7c478bd9Sstevel@tonic-gate }
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate static int
ok(int argc,char * argv[],int index,uid_t uid,dev_t tty,char * command)47*7c478bd9Sstevel@tonic-gate ok(int argc, char *argv[], int index, uid_t uid, dev_t tty, char *command)
48*7c478bd9Sstevel@tonic-gate {
49*7c478bd9Sstevel@tonic-gate 	int j;
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate 	for (j = index; j < argc; j++)
52*7c478bd9Sstevel@tonic-gate 		if (strcmp(getname(uid), argv[j]) &&
53*7c478bd9Sstevel@tonic-gate 		    strcmp(getdev(tty), argv[j]) &&
54*7c478bd9Sstevel@tonic-gate 		    strncmp(command, argv[j], fldsiz(acct, ac_comm)))
55*7c478bd9Sstevel@tonic-gate 			break;
56*7c478bd9Sstevel@tonic-gate 	return (j == argc);
57*7c478bd9Sstevel@tonic-gate }
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate static void
disp_group(ea_file_t * ef,uint_t nobjs,int argc,char * argv[],int index)60*7c478bd9Sstevel@tonic-gate disp_group(ea_file_t *ef, uint_t nobjs, int argc, char *argv[], int index)
61*7c478bd9Sstevel@tonic-gate {
62*7c478bd9Sstevel@tonic-gate 	uint_t i;
63*7c478bd9Sstevel@tonic-gate 	char *command = NULL;
64*7c478bd9Sstevel@tonic-gate 	double cpu_usr_secs = 0.;
65*7c478bd9Sstevel@tonic-gate 	double cpu_usr_nsecs = 0.;
66*7c478bd9Sstevel@tonic-gate 	double cpu_sys_secs = 0.;
67*7c478bd9Sstevel@tonic-gate 	double cpu_sys_nsecs = 0.;
68*7c478bd9Sstevel@tonic-gate 	double totalsecs;
69*7c478bd9Sstevel@tonic-gate 	dev_t tty = 0;
70*7c478bd9Sstevel@tonic-gate 	major_t tty_major = 0;
71*7c478bd9Sstevel@tonic-gate 	minor_t tty_minor = 0;
72*7c478bd9Sstevel@tonic-gate 	uid_t uid = 0;
73*7c478bd9Sstevel@tonic-gate 	time_t time = 0;
74*7c478bd9Sstevel@tonic-gate 	uint32_t flag = 0;
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < nobjs; i++) {
77*7c478bd9Sstevel@tonic-gate 		ea_object_t curr_obj;
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate 		if (ea_get_object(ef, &curr_obj) == -1) {
80*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("lastcomm: "
81*7c478bd9Sstevel@tonic-gate 			    "corrupted exacct file\n"));
82*7c478bd9Sstevel@tonic-gate 			exit(1);
83*7c478bd9Sstevel@tonic-gate 		}
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate 		switch (curr_obj.eo_catalog) {
86*7c478bd9Sstevel@tonic-gate 			case EXT_STRING | EXC_DEFAULT | EXD_PROC_COMMAND:
87*7c478bd9Sstevel@tonic-gate 				command = curr_obj.eo_item.ei_string;
88*7c478bd9Sstevel@tonic-gate 				break;
89*7c478bd9Sstevel@tonic-gate 			case EXT_UINT32 | EXC_DEFAULT | EXD_PROC_UID:
90*7c478bd9Sstevel@tonic-gate 				uid = curr_obj.eo_item.ei_uint32;
91*7c478bd9Sstevel@tonic-gate 				break;
92*7c478bd9Sstevel@tonic-gate 			case EXT_UINT64 | EXC_DEFAULT | EXD_PROC_CPU_SYS_SEC:
93*7c478bd9Sstevel@tonic-gate 				cpu_sys_secs = curr_obj.eo_item.ei_uint64;
94*7c478bd9Sstevel@tonic-gate 				break;
95*7c478bd9Sstevel@tonic-gate 			case EXT_UINT64 | EXC_DEFAULT | EXD_PROC_CPU_USER_SEC:
96*7c478bd9Sstevel@tonic-gate 				cpu_usr_secs = curr_obj.eo_item.ei_uint64;
97*7c478bd9Sstevel@tonic-gate 				break;
98*7c478bd9Sstevel@tonic-gate 			case EXT_UINT64 | EXC_DEFAULT | EXD_PROC_CPU_SYS_NSEC:
99*7c478bd9Sstevel@tonic-gate 				cpu_sys_nsecs = curr_obj.eo_item.ei_uint64;
100*7c478bd9Sstevel@tonic-gate 				break;
101*7c478bd9Sstevel@tonic-gate 			case EXT_UINT64 | EXC_DEFAULT | EXD_PROC_CPU_USER_NSEC:
102*7c478bd9Sstevel@tonic-gate 				cpu_usr_nsecs = curr_obj.eo_item.ei_uint64;
103*7c478bd9Sstevel@tonic-gate 				break;
104*7c478bd9Sstevel@tonic-gate 			case EXT_UINT32 | EXC_DEFAULT | EXD_PROC_TTY_MAJOR:
105*7c478bd9Sstevel@tonic-gate 				tty_major = curr_obj.eo_item.ei_uint32;
106*7c478bd9Sstevel@tonic-gate 				break;
107*7c478bd9Sstevel@tonic-gate 			case EXT_UINT32 | EXC_DEFAULT | EXD_PROC_TTY_MINOR:
108*7c478bd9Sstevel@tonic-gate 				tty_minor = curr_obj.eo_item.ei_uint32;
109*7c478bd9Sstevel@tonic-gate 				break;
110*7c478bd9Sstevel@tonic-gate 			case EXT_UINT32 | EXC_DEFAULT | EXD_PROC_ACCT_FLAGS:
111*7c478bd9Sstevel@tonic-gate 				flag = curr_obj.eo_item.ei_uint32;
112*7c478bd9Sstevel@tonic-gate 				break;
113*7c478bd9Sstevel@tonic-gate 			case EXT_UINT64 | EXC_DEFAULT | EXD_PROC_START_SEC:
114*7c478bd9Sstevel@tonic-gate 				time = (uint32_t)curr_obj.eo_item.ei_uint64;
115*7c478bd9Sstevel@tonic-gate 				break;
116*7c478bd9Sstevel@tonic-gate 			default:
117*7c478bd9Sstevel@tonic-gate 				break;
118*7c478bd9Sstevel@tonic-gate 		}
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate 		if (curr_obj.eo_type == EO_GROUP)
121*7c478bd9Sstevel@tonic-gate 			disp_group(ef, curr_obj.eo_group.eg_nobjs,
122*7c478bd9Sstevel@tonic-gate 			    argc, argv, index);
123*7c478bd9Sstevel@tonic-gate 	}
124*7c478bd9Sstevel@tonic-gate 
125*7c478bd9Sstevel@tonic-gate 	if (command == NULL) {
126*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("lastcomm: "
127*7c478bd9Sstevel@tonic-gate 		    "corrupted exacct file\n"));
128*7c478bd9Sstevel@tonic-gate 		exit(1);
129*7c478bd9Sstevel@tonic-gate 	}
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate 	/*
132*7c478bd9Sstevel@tonic-gate 	 * If a 64-bit kernel returns a major or minor value that would exceed
133*7c478bd9Sstevel@tonic-gate 	 * the capacity of a 32-bit dev_t (and these also become visible in the
134*7c478bd9Sstevel@tonic-gate 	 * filesystem), then the 32-bit makedev may be inaccurate and return
135*7c478bd9Sstevel@tonic-gate 	 * NODEV.  When this occurs, we can remedy the problem by providing
136*7c478bd9Sstevel@tonic-gate 	 * either a function which returns "dev64_t"'s or by providing an LP64
137*7c478bd9Sstevel@tonic-gate 	 * version of lastcomm.
138*7c478bd9Sstevel@tonic-gate 	 */
139*7c478bd9Sstevel@tonic-gate 	tty = makedev(tty_major, tty_minor);
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 	/*
142*7c478bd9Sstevel@tonic-gate 	 * If this record doesn't match the optional arguments, go on to the
143*7c478bd9Sstevel@tonic-gate 	 * next record.
144*7c478bd9Sstevel@tonic-gate 	 */
145*7c478bd9Sstevel@tonic-gate 	if (argc > index && !ok(argc, argv, index, uid, tty, command))
146*7c478bd9Sstevel@tonic-gate 		return;
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate 	totalsecs =
149*7c478bd9Sstevel@tonic-gate 	    cpu_usr_secs + cpu_usr_nsecs / NANOSEC +
150*7c478bd9Sstevel@tonic-gate 	    cpu_sys_secs + cpu_sys_nsecs / NANOSEC;
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate 	(void) printf("%-*.*s %s %-*s %-*s %6.2f secs %.16s\n",
153*7c478bd9Sstevel@tonic-gate 	    fldsiz(acct, ac_comm), fldsiz(acct, ac_comm), command,
154*7c478bd9Sstevel@tonic-gate 	    flagbits(flag), NMAX, getname(uid), LMAX, getdev(tty),
155*7c478bd9Sstevel@tonic-gate 	    totalsecs, ctime(&time));
156*7c478bd9Sstevel@tonic-gate }
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate int
lc_exacct(char * filename,int argc,char * argv[],int index)159*7c478bd9Sstevel@tonic-gate lc_exacct(char *filename, int argc, char *argv[], int index)
160*7c478bd9Sstevel@tonic-gate {
161*7c478bd9Sstevel@tonic-gate 	ea_file_t ef;
162*7c478bd9Sstevel@tonic-gate 	ea_object_t curr_obj;
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate 	if (ea_open(&ef, filename, EXACCT_CREATOR,
165*7c478bd9Sstevel@tonic-gate 		    EO_TAIL | EO_VALID_HDR, O_RDONLY, 0) < 0) {
166*7c478bd9Sstevel@tonic-gate 		switch (ea_error()) {
167*7c478bd9Sstevel@tonic-gate 			case EXR_CORRUPT_FILE:
168*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext("lastcomm: "
169*7c478bd9Sstevel@tonic-gate 				    "exacct file corrupted\n"));
170*7c478bd9Sstevel@tonic-gate 				break;
171*7c478bd9Sstevel@tonic-gate 			case EXR_SYSCALL_FAIL:
172*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext("lastcomm: "
173*7c478bd9Sstevel@tonic-gate 				    "cannot open %s: %s\n"), filename,
174*7c478bd9Sstevel@tonic-gate 				    strerror(errno));
175*7c478bd9Sstevel@tonic-gate 				break;
176*7c478bd9Sstevel@tonic-gate 			default:
177*7c478bd9Sstevel@tonic-gate 				break;
178*7c478bd9Sstevel@tonic-gate 		}
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 		return (1);
181*7c478bd9Sstevel@tonic-gate 	}
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 	while (ea_previous_object(&ef, &curr_obj) != -1) {
184*7c478bd9Sstevel@tonic-gate 		if (ea_get_object(&ef, &curr_obj) == -1) {
185*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("lastcomm: "
186*7c478bd9Sstevel@tonic-gate 			    "exacct file corrupted\n"));
187*7c478bd9Sstevel@tonic-gate 			exit(1);
188*7c478bd9Sstevel@tonic-gate 		}
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate 		/*
191*7c478bd9Sstevel@tonic-gate 		 * lc_exacct(), in parsing the extended process accounting file,
192*7c478bd9Sstevel@tonic-gate 		 * has knowledge of the fact that process records are top-level
193*7c478bd9Sstevel@tonic-gate 		 * records.
194*7c478bd9Sstevel@tonic-gate 		 */
195*7c478bd9Sstevel@tonic-gate 		if ((curr_obj.eo_catalog & EXT_TYPE_MASK) == EXT_GROUP) {
196*7c478bd9Sstevel@tonic-gate 			if (curr_obj.eo_catalog ==
197*7c478bd9Sstevel@tonic-gate 			    (EXT_GROUP | EXC_DEFAULT | EXD_GROUP_PROC))
198*7c478bd9Sstevel@tonic-gate 				disp_group(&ef, curr_obj.eo_group.eg_nobjs,
199*7c478bd9Sstevel@tonic-gate 				    argc, argv, index);
200*7c478bd9Sstevel@tonic-gate 			else
201*7c478bd9Sstevel@tonic-gate 				skip_group(&ef, curr_obj.eo_group.eg_nobjs);
202*7c478bd9Sstevel@tonic-gate 		}
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate 		/*
205*7c478bd9Sstevel@tonic-gate 		 * Back up to the head of the object we just consumed.
206*7c478bd9Sstevel@tonic-gate 		 */
207*7c478bd9Sstevel@tonic-gate 		if (ea_previous_object(&ef, &curr_obj) == -1) {
208*7c478bd9Sstevel@tonic-gate 			if (ea_error() == EXR_EOF)
209*7c478bd9Sstevel@tonic-gate 				break;
210*7c478bd9Sstevel@tonic-gate 
211*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("lastcomm: "
212*7c478bd9Sstevel@tonic-gate 			    "exacct file corrupted\n"));
213*7c478bd9Sstevel@tonic-gate 			exit(1);
214*7c478bd9Sstevel@tonic-gate 		}
215*7c478bd9Sstevel@tonic-gate 	}
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate 	if (ea_error() != EXR_EOF) {
218*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("lastcomm: "
219*7c478bd9Sstevel@tonic-gate 		    "exacct file corrupted\n"));
220*7c478bd9Sstevel@tonic-gate 		exit(1);
221*7c478bd9Sstevel@tonic-gate 	}
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate 	(void) ea_close(&ef);
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 	return (0);
226*7c478bd9Sstevel@tonic-gate }
227