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