xref: /illumos-gate/usr/src/lib/libexacct/demo/exdump.c (revision 7c478bd9)
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/acct.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/wait.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/socket.h>
33*7c478bd9Sstevel@tonic-gate #include <stdio.h>
34*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
35*7c478bd9Sstevel@tonic-gate #include <exacct.h>
36*7c478bd9Sstevel@tonic-gate #include <pwd.h>
37*7c478bd9Sstevel@tonic-gate #include <grp.h>
38*7c478bd9Sstevel@tonic-gate #include <project.h>
39*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
40*7c478bd9Sstevel@tonic-gate #include <strings.h>
41*7c478bd9Sstevel@tonic-gate #include <netinet/in.h>
42*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
43*7c478bd9Sstevel@tonic-gate #include <netdb.h>
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate #ifndef _LP64
46*7c478bd9Sstevel@tonic-gate #define	FMT_UINT64	"%-15llu"
47*7c478bd9Sstevel@tonic-gate #else
48*7c478bd9Sstevel@tonic-gate #define	FMT_UINT64	"%-15lu"
49*7c478bd9Sstevel@tonic-gate #endif
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate #define	MAX_DEPTH	25		/* maximum depth level */
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate static int vflag = 0;
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate typedef struct catalog_item {
56*7c478bd9Sstevel@tonic-gate 	int	type;
57*7c478bd9Sstevel@tonic-gate 	char	*name;
58*7c478bd9Sstevel@tonic-gate } catalog_item_t;
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate /*
61*7c478bd9Sstevel@tonic-gate  * The actual constants are defined in <sys/exacct_catalog.h>.
62*7c478bd9Sstevel@tonic-gate  */
63*7c478bd9Sstevel@tonic-gate static catalog_item_t catalog[] = {
64*7c478bd9Sstevel@tonic-gate 	{ EXD_VERSION,			"version" },
65*7c478bd9Sstevel@tonic-gate 	{ EXD_FILETYPE,			"filetype" },
66*7c478bd9Sstevel@tonic-gate 	{ EXD_CREATOR,			"creator" },
67*7c478bd9Sstevel@tonic-gate 	{ EXD_HOSTNAME,			"hostname" },
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate 	{ EXD_GROUP_HEADER,		"group-header" },
70*7c478bd9Sstevel@tonic-gate 	{ EXD_GROUP_PROC,		"group-proc" },
71*7c478bd9Sstevel@tonic-gate 	{ EXD_GROUP_TASK,		"group-task" },
72*7c478bd9Sstevel@tonic-gate 	{ EXD_GROUP_LWP,		"group-lwp" },
73*7c478bd9Sstevel@tonic-gate 	{ EXD_GROUP_FLOW,		"group-flow" },
74*7c478bd9Sstevel@tonic-gate 	{ EXD_GROUP_PROC_TAG,		"group-proc-tag" },
75*7c478bd9Sstevel@tonic-gate 	{ EXD_GROUP_TASK_TAG,		"group-task-tag" },
76*7c478bd9Sstevel@tonic-gate 	{ EXD_GROUP_LWP_TAG,		"group-lwp-tag" },
77*7c478bd9Sstevel@tonic-gate 	{ EXD_GROUP_PROC_PARTIAL,	"group-proc-partial" },
78*7c478bd9Sstevel@tonic-gate 	{ EXD_GROUP_TASK_PARTIAL,	"group-task-partial" },
79*7c478bd9Sstevel@tonic-gate 	{ EXD_GROUP_TASK_INTERVAL,	"group-task-interval" },
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_PID,			"pid" },
82*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_ANCPID, 		"ppid" },
83*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_UID,			"uid" },
84*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_GID,			"gid" },
85*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_TASKID,		"taskid" },
86*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_PROJID,		"projid" },
87*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_HOSTNAME,		"hostname" },
88*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_COMMAND,		"command" },
89*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_WAIT_STATUS,		"wait-status" },
90*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_START_SEC,		"start-sec" },
91*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_START_NSEC,		"start-nsec" },
92*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_FINISH_SEC,		"finish-sec" },
93*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_FINISH_NSEC,		"finish-nsec" },
94*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_CPU_USER_SEC,	"cpu-user-sec" },
95*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_CPU_USER_NSEC,	"cpu-user-nsec" },
96*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_CPU_SYS_SEC,		"cpu-sys-sec" },
97*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_CPU_SYS_NSEC,	"cpu-sys-nsec" },
98*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_TTY_MAJOR,		"tty-major" },
99*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_TTY_MINOR,		"tty-minor" },
100*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_FAULTS_MAJOR,	"faults-major" },
101*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_FAULTS_MINOR,	"faults-minor" },
102*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_MESSAGES_RCV,	"msgs-recv" },
103*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_MESSAGES_SND,	"msgs-snd" },
104*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_BLOCKS_IN,		"blocks-in" },
105*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_BLOCKS_OUT,		"blocks-out" },
106*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_CHARS_RDWR,		"chars-rdwr" },
107*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_CONTEXT_VOL,		"ctxt-vol" },
108*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_CONTEXT_INV,		"ctxt-inv" },
109*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_SIGNALS,		"signals" },
110*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_SWAPS,		"swaps" },
111*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_SYSCALLS,		"syscalls" },
112*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_TAG,			"proc-tag" },
113*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_ACCT_FLAGS,		"acctflags" },
114*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_ZONENAME,		"zone" },
115*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_MEM_RSS_AVG_K,	"memory-rss-avg-k" },
116*7c478bd9Sstevel@tonic-gate 	{ EXD_PROC_MEM_RSS_MAX_K,	"memory-rss-max-k" },
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_TASKID,		"taskid" },
119*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_ANCTASKID,		"anctaskid" },
120*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_PROJID,		"projid" },
121*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_HOSTNAME,		"hostname" },
122*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_START_SEC,		"start-sec" },
123*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_START_NSEC,		"start-nsec" },
124*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_FINISH_SEC,		"finish-sec" },
125*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_FINISH_NSEC,		"finish-nsec" },
126*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_CPU_USER_SEC,	"cpu-user-sec" },
127*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_CPU_USER_NSEC,	"cpu-user-nsec" },
128*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_CPU_SYS_SEC,		"cpu-sys-sec" },
129*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_CPU_SYS_NSEC,	"cpu-sys-nsec" },
130*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_FAULTS_MAJOR,	"faults-major" },
131*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_FAULTS_MINOR,	"faults-minor" },
132*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_MESSAGES_RCV,	"msgs-recv" },
133*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_MESSAGES_SND,	"msgs-snd" },
134*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_BLOCKS_IN,		"blocks-in" },
135*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_BLOCKS_OUT,		"blocks-out" },
136*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_CHARS_RDWR,		"chars-rdwr" },
137*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_CONTEXT_VOL,		"ctxt-vol" },
138*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_CONTEXT_INV,		"ctxt-inv" },
139*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_SIGNALS,		"signals" },
140*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_SWAPS,		"swaps" },
141*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_SYSCALLS,		"syscalls" },
142*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_TAG,			"task-tag" },
143*7c478bd9Sstevel@tonic-gate 	{ EXD_TASK_ZONENAME,		"zone" },
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 	{ EXD_FLOW_V4SADDR,		"src-addr-v4" },
146*7c478bd9Sstevel@tonic-gate 	{ EXD_FLOW_V4DADDR,		"dest-addr-v4" },
147*7c478bd9Sstevel@tonic-gate 	{ EXD_FLOW_V6SADDR,		"src-addr-v6" },
148*7c478bd9Sstevel@tonic-gate 	{ EXD_FLOW_V6DADDR,		"dest-addr-v6" },
149*7c478bd9Sstevel@tonic-gate 	{ EXD_FLOW_SPORT,		"src-port" },
150*7c478bd9Sstevel@tonic-gate 	{ EXD_FLOW_DPORT,		"dest-port" },
151*7c478bd9Sstevel@tonic-gate 	{ EXD_FLOW_PROTOCOL,		"protocol" },
152*7c478bd9Sstevel@tonic-gate 	{ EXD_FLOW_DSFIELD,		"diffserv-field" },
153*7c478bd9Sstevel@tonic-gate 	{ EXD_FLOW_NBYTES,		"total-bytes" },
154*7c478bd9Sstevel@tonic-gate 	{ EXD_FLOW_NPKTS,		"total-packets" },
155*7c478bd9Sstevel@tonic-gate 	{ EXD_FLOW_CTIME,		"creation-time" },
156*7c478bd9Sstevel@tonic-gate 	{ EXD_FLOW_LSEEN,		"last-seen" },
157*7c478bd9Sstevel@tonic-gate 	{ EXD_FLOW_PROJID,		"projid" },
158*7c478bd9Sstevel@tonic-gate 	{ EXD_FLOW_UID,			"uid" },
159*7c478bd9Sstevel@tonic-gate 	{ EXD_FLOW_ANAME,		"action-name" },
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate 	{ EXD_NONE,			"none" }
162*7c478bd9Sstevel@tonic-gate };
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate static void disp_obj(ea_object_t *o, int indent);
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate /*
167*7c478bd9Sstevel@tonic-gate  * Convert catalog ID into catalog name.
168*7c478bd9Sstevel@tonic-gate  */
169*7c478bd9Sstevel@tonic-gate static char *
170*7c478bd9Sstevel@tonic-gate catalog_name(int type)
171*7c478bd9Sstevel@tonic-gate {
172*7c478bd9Sstevel@tonic-gate 	int i = 0;
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate 	while (catalog[i].type != EXD_NONE) {
175*7c478bd9Sstevel@tonic-gate 		if (catalog[i].type == type)
176*7c478bd9Sstevel@tonic-gate 			return (catalog[i].name);
177*7c478bd9Sstevel@tonic-gate 		i++;
178*7c478bd9Sstevel@tonic-gate 	}
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 	return ("unknown");
181*7c478bd9Sstevel@tonic-gate }
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate /*
184*7c478bd9Sstevel@tonic-gate  * Display port information, if available
185*7c478bd9Sstevel@tonic-gate  */
186*7c478bd9Sstevel@tonic-gate static void
187*7c478bd9Sstevel@tonic-gate disp_port(uint16_t port)
188*7c478bd9Sstevel@tonic-gate {
189*7c478bd9Sstevel@tonic-gate 	struct servent *port_info;
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate 	port_info = getservbyport(htons(port), NULL);
192*7c478bd9Sstevel@tonic-gate 	if (port_info != NULL) {
193*7c478bd9Sstevel@tonic-gate 		(void) printf("%s", port_info->s_name);
194*7c478bd9Sstevel@tonic-gate 	}
195*7c478bd9Sstevel@tonic-gate }
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate /*
198*7c478bd9Sstevel@tonic-gate  * Display host name for a given IP address if available.
199*7c478bd9Sstevel@tonic-gate  */
200*7c478bd9Sstevel@tonic-gate static void
201*7c478bd9Sstevel@tonic-gate disp_host(char *addr, int family)
202*7c478bd9Sstevel@tonic-gate {
203*7c478bd9Sstevel@tonic-gate 	struct hostent *phe;
204*7c478bd9Sstevel@tonic-gate 	uint_t len;
205*7c478bd9Sstevel@tonic-gate 	int error_num;
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate 	len = (family == AF_INET) ? sizeof (struct in_addr) :
208*7c478bd9Sstevel@tonic-gate 	    sizeof (struct in6_addr);
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 	if ((phe = getipnodebyaddr(addr, len, family, &error_num)) != NULL) {
211*7c478bd9Sstevel@tonic-gate 		(void) printf("%s", phe->h_name);
212*7c478bd9Sstevel@tonic-gate 	}
213*7c478bd9Sstevel@tonic-gate }
214*7c478bd9Sstevel@tonic-gate 
215*7c478bd9Sstevel@tonic-gate /*
216*7c478bd9Sstevel@tonic-gate  * Display protocol information, if available.
217*7c478bd9Sstevel@tonic-gate  */
218*7c478bd9Sstevel@tonic-gate static void
219*7c478bd9Sstevel@tonic-gate disp_proto(uint8_t protocol)
220*7c478bd9Sstevel@tonic-gate {
221*7c478bd9Sstevel@tonic-gate 	struct protoent *proto_ent;
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate 	proto_ent = getprotobynumber(protocol);
224*7c478bd9Sstevel@tonic-gate 	if (proto_ent != NULL) {
225*7c478bd9Sstevel@tonic-gate 		(void) printf("%s", proto_ent->p_name);
226*7c478bd9Sstevel@tonic-gate 	}
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate }
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate /*
231*7c478bd9Sstevel@tonic-gate  * Display recursively exacct objects in a given embedded group.
232*7c478bd9Sstevel@tonic-gate  */
233*7c478bd9Sstevel@tonic-gate static void
234*7c478bd9Sstevel@tonic-gate disp_embedded_group(ea_object_t *eo, int indent)
235*7c478bd9Sstevel@tonic-gate {
236*7c478bd9Sstevel@tonic-gate 	while (eo != NULL) {
237*7c478bd9Sstevel@tonic-gate 		disp_obj(eo, indent + 1);
238*7c478bd9Sstevel@tonic-gate 		if (eo->eo_type == EO_GROUP)
239*7c478bd9Sstevel@tonic-gate 			disp_embedded_group(eo->eo_group.eg_objs, indent + 1);
240*7c478bd9Sstevel@tonic-gate 		eo = eo->eo_next;
241*7c478bd9Sstevel@tonic-gate 	}
242*7c478bd9Sstevel@tonic-gate }
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate /*
245*7c478bd9Sstevel@tonic-gate  * Display the data stored in a given exacct object.
246*7c478bd9Sstevel@tonic-gate  */
247*7c478bd9Sstevel@tonic-gate static void
248*7c478bd9Sstevel@tonic-gate disp_obj(ea_object_t *o, int indent)
249*7c478bd9Sstevel@tonic-gate {
250*7c478bd9Sstevel@tonic-gate 	char objname[30] = "                              ";
251*7c478bd9Sstevel@tonic-gate 	int eol = 1;
252*7c478bd9Sstevel@tonic-gate 
253*7c478bd9Sstevel@tonic-gate 	if (indent > MAX_DEPTH) {
254*7c478bd9Sstevel@tonic-gate 		objname[0] = '>';
255*7c478bd9Sstevel@tonic-gate 		indent = 1;
256*7c478bd9Sstevel@tonic-gate 	}
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate 	(void) printf("%6x\t", (o->eo_catalog & EXD_DATA_MASK));
259*7c478bd9Sstevel@tonic-gate 	(void) snprintf(objname + indent, 30 - indent, "%-s",
260*7c478bd9Sstevel@tonic-gate 	    catalog_name(o->eo_catalog & EXD_DATA_MASK));
261*7c478bd9Sstevel@tonic-gate 	(void) printf("%-30s\t", objname);
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate 	switch (o->eo_catalog & EXT_TYPE_MASK) {
264*7c478bd9Sstevel@tonic-gate 	case EXT_UINT8:
265*7c478bd9Sstevel@tonic-gate 		(void) printf("%-15u", o->eo_item.ei_uint8);
266*7c478bd9Sstevel@tonic-gate 		if (vflag &&
267*7c478bd9Sstevel@tonic-gate 		    ((o->eo_catalog & EXD_DATA_MASK) == EXD_FLOW_PROTOCOL)) {
268*7c478bd9Sstevel@tonic-gate 			disp_proto(o->eo_item.ei_uint8);
269*7c478bd9Sstevel@tonic-gate 		}
270*7c478bd9Sstevel@tonic-gate 		break;
271*7c478bd9Sstevel@tonic-gate 	case EXT_UINT16:
272*7c478bd9Sstevel@tonic-gate 		(void) printf("%-15u", o->eo_item.ei_uint16);
273*7c478bd9Sstevel@tonic-gate 		if (vflag &&
274*7c478bd9Sstevel@tonic-gate 		    (((o->eo_catalog & EXD_DATA_MASK) == EXD_FLOW_SPORT) ||
275*7c478bd9Sstevel@tonic-gate 		    ((o->eo_catalog & EXD_DATA_MASK) == EXD_FLOW_DPORT))) {
276*7c478bd9Sstevel@tonic-gate 			disp_port(o->eo_item.ei_uint16);
277*7c478bd9Sstevel@tonic-gate 		}
278*7c478bd9Sstevel@tonic-gate 		break;
279*7c478bd9Sstevel@tonic-gate 	case EXT_UINT32:
280*7c478bd9Sstevel@tonic-gate 		switch (o->eo_catalog & EXD_DATA_MASK) {
281*7c478bd9Sstevel@tonic-gate 		case EXD_PROC_WAIT_STATUS:
282*7c478bd9Sstevel@tonic-gate 			{
283*7c478bd9Sstevel@tonic-gate 				int wstat = o->eo_item.ei_uint32;
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate 				if (vflag) {
286*7c478bd9Sstevel@tonic-gate 					if (WIFEXITED(wstat))
287*7c478bd9Sstevel@tonic-gate 						(void) printf("%-14d exit",
288*7c478bd9Sstevel@tonic-gate 						    WEXITSTATUS(wstat));
289*7c478bd9Sstevel@tonic-gate 					else if (WIFSIGNALED(wstat))
290*7c478bd9Sstevel@tonic-gate 						(void) printf("%14d, signal",
291*7c478bd9Sstevel@tonic-gate 						    WTERMSIG(wstat));
292*7c478bd9Sstevel@tonic-gate 					else
293*7c478bd9Sstevel@tonic-gate 						(void) printf("%d", wstat);
294*7c478bd9Sstevel@tonic-gate 				} else {
295*7c478bd9Sstevel@tonic-gate 					(void) printf("%d", wstat);
296*7c478bd9Sstevel@tonic-gate 				}
297*7c478bd9Sstevel@tonic-gate 			}
298*7c478bd9Sstevel@tonic-gate 			break;
299*7c478bd9Sstevel@tonic-gate 		case EXD_PROC_UID:
300*7c478bd9Sstevel@tonic-gate 			{
301*7c478bd9Sstevel@tonic-gate 				uid_t uid = o->eo_item.ei_uint32;
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 				(void) printf("%-15lu", uid);
304*7c478bd9Sstevel@tonic-gate 				if (vflag) {
305*7c478bd9Sstevel@tonic-gate 					struct passwd *pwd;
306*7c478bd9Sstevel@tonic-gate 					if ((pwd = getpwuid(uid)) != NULL)
307*7c478bd9Sstevel@tonic-gate 						(void) printf("%s",
308*7c478bd9Sstevel@tonic-gate 						    pwd->pw_name);
309*7c478bd9Sstevel@tonic-gate 				}
310*7c478bd9Sstevel@tonic-gate 			}
311*7c478bd9Sstevel@tonic-gate 			break;
312*7c478bd9Sstevel@tonic-gate 		case EXD_PROC_GID:
313*7c478bd9Sstevel@tonic-gate 			{
314*7c478bd9Sstevel@tonic-gate 				gid_t gid = o->eo_item.ei_uint32;
315*7c478bd9Sstevel@tonic-gate 
316*7c478bd9Sstevel@tonic-gate 				(void) printf("%-15lu", gid);
317*7c478bd9Sstevel@tonic-gate 				if (vflag) {
318*7c478bd9Sstevel@tonic-gate 					struct group *grp;
319*7c478bd9Sstevel@tonic-gate 					if ((grp = getgrgid(gid)) != NULL)
320*7c478bd9Sstevel@tonic-gate 						(void) printf("%s",
321*7c478bd9Sstevel@tonic-gate 						    grp->gr_name);
322*7c478bd9Sstevel@tonic-gate 				}
323*7c478bd9Sstevel@tonic-gate 			}
324*7c478bd9Sstevel@tonic-gate 			break;
325*7c478bd9Sstevel@tonic-gate 		case EXD_PROC_PROJID:
326*7c478bd9Sstevel@tonic-gate 		case EXD_TASK_PROJID:
327*7c478bd9Sstevel@tonic-gate 			{
328*7c478bd9Sstevel@tonic-gate 				projid_t projid = o->eo_item.ei_uint32;
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 				(void) printf("%-15lu", projid);
331*7c478bd9Sstevel@tonic-gate 				if (vflag) {
332*7c478bd9Sstevel@tonic-gate 					struct project proj;
333*7c478bd9Sstevel@tonic-gate 					char projbuf[PROJECT_BUFSZ];
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate 					if (getprojbyid(projid, &proj, projbuf,
336*7c478bd9Sstevel@tonic-gate 					    PROJECT_BUFSZ) != NULL)
337*7c478bd9Sstevel@tonic-gate 						(void) printf("%s",
338*7c478bd9Sstevel@tonic-gate 						    proj.pj_name);
339*7c478bd9Sstevel@tonic-gate 				}
340*7c478bd9Sstevel@tonic-gate 			}
341*7c478bd9Sstevel@tonic-gate 			break;
342*7c478bd9Sstevel@tonic-gate 		case EXD_PROC_ACCT_FLAGS:
343*7c478bd9Sstevel@tonic-gate 			{
344*7c478bd9Sstevel@tonic-gate 				int flag = o->eo_item.ei_uint32;
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 				(void) printf("%-15u", flag);
347*7c478bd9Sstevel@tonic-gate 				if (vflag) {
348*7c478bd9Sstevel@tonic-gate 					if (flag & AFORK)
349*7c478bd9Sstevel@tonic-gate 						(void) printf("FORK ");
350*7c478bd9Sstevel@tonic-gate 					if (flag & ASU)
351*7c478bd9Sstevel@tonic-gate 						(void) printf("SU");
352*7c478bd9Sstevel@tonic-gate 				}
353*7c478bd9Sstevel@tonic-gate 			}
354*7c478bd9Sstevel@tonic-gate 			break;
355*7c478bd9Sstevel@tonic-gate 		case EXD_FLOW_V4SADDR:
356*7c478bd9Sstevel@tonic-gate 			/* FALLTHRU */
357*7c478bd9Sstevel@tonic-gate 		case EXD_FLOW_V4DADDR:
358*7c478bd9Sstevel@tonic-gate 			{
359*7c478bd9Sstevel@tonic-gate 				char str[INET_ADDRSTRLEN];
360*7c478bd9Sstevel@tonic-gate 				uint32_t addr = htonl(o->eo_item.ei_uint32);
361*7c478bd9Sstevel@tonic-gate 
362*7c478bd9Sstevel@tonic-gate 				(void) printf("%-15s",
363*7c478bd9Sstevel@tonic-gate 				    inet_ntop(AF_INET, &addr, str,
364*7c478bd9Sstevel@tonic-gate 				    INET_ADDRSTRLEN));
365*7c478bd9Sstevel@tonic-gate 				if (vflag) {
366*7c478bd9Sstevel@tonic-gate 					disp_host((char *)&addr, AF_INET);
367*7c478bd9Sstevel@tonic-gate 				}
368*7c478bd9Sstevel@tonic-gate 			}
369*7c478bd9Sstevel@tonic-gate 			break;
370*7c478bd9Sstevel@tonic-gate 		default:
371*7c478bd9Sstevel@tonic-gate 			(void) printf("%u", o->eo_item.ei_uint32);
372*7c478bd9Sstevel@tonic-gate 		}
373*7c478bd9Sstevel@tonic-gate 		break;
374*7c478bd9Sstevel@tonic-gate 	case EXT_UINT64:
375*7c478bd9Sstevel@tonic-gate 		{
376*7c478bd9Sstevel@tonic-gate 			time_t _time;
377*7c478bd9Sstevel@tonic-gate 			char timebuf[20];
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate 			(void) printf(FMT_UINT64, o->eo_item.ei_uint64);
380*7c478bd9Sstevel@tonic-gate 			if (!vflag)
381*7c478bd9Sstevel@tonic-gate 				break;
382*7c478bd9Sstevel@tonic-gate 			if (ea_match_object_catalog(o, EXD_TASK_START_SEC) ||
383*7c478bd9Sstevel@tonic-gate 			    ea_match_object_catalog(o, EXD_TASK_FINISH_SEC) ||
384*7c478bd9Sstevel@tonic-gate 			    ea_match_object_catalog(o, EXD_PROC_START_SEC) ||
385*7c478bd9Sstevel@tonic-gate 			    ea_match_object_catalog(o, EXD_PROC_FINISH_SEC) ||
386*7c478bd9Sstevel@tonic-gate 			    ea_match_object_catalog(o, EXD_FLOW_LSEEN) ||
387*7c478bd9Sstevel@tonic-gate 			    ea_match_object_catalog(o, EXD_FLOW_CTIME)) {
388*7c478bd9Sstevel@tonic-gate 				_time = o->eo_item.ei_uint64;
389*7c478bd9Sstevel@tonic-gate 				(void) strftime(timebuf, sizeof (timebuf),
390*7c478bd9Sstevel@tonic-gate 				    "%D %T", localtime(&_time));
391*7c478bd9Sstevel@tonic-gate 				(void) fputs(timebuf, stdout);
392*7c478bd9Sstevel@tonic-gate 			}
393*7c478bd9Sstevel@tonic-gate 		}
394*7c478bd9Sstevel@tonic-gate 		break;
395*7c478bd9Sstevel@tonic-gate 	case EXT_DOUBLE:
396*7c478bd9Sstevel@tonic-gate 		(void) printf("%f", o->eo_item.ei_double);
397*7c478bd9Sstevel@tonic-gate 		break;
398*7c478bd9Sstevel@tonic-gate 	case EXT_STRING:
399*7c478bd9Sstevel@tonic-gate 		(void) printf("\"%s\"", o->eo_item.ei_string);
400*7c478bd9Sstevel@tonic-gate 		break;
401*7c478bd9Sstevel@tonic-gate 	case EXT_RAW:
402*7c478bd9Sstevel@tonic-gate 		switch (o->eo_catalog & EXD_DATA_MASK) {
403*7c478bd9Sstevel@tonic-gate 		case EXD_FLOW_V6SADDR:
404*7c478bd9Sstevel@tonic-gate 			/* FALLTHRU */
405*7c478bd9Sstevel@tonic-gate 		case EXD_FLOW_V6DADDR:
406*7c478bd9Sstevel@tonic-gate 			{
407*7c478bd9Sstevel@tonic-gate 				in6_addr_t *addr;
408*7c478bd9Sstevel@tonic-gate 				char str[INET6_ADDRSTRLEN];
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate 				addr = (in6_addr_t *)o->eo_item.ei_raw;
411*7c478bd9Sstevel@tonic-gate 				(void) printf("%-28s", inet_ntop(AF_INET6,
412*7c478bd9Sstevel@tonic-gate 				    &addr->s6_addr, str, INET6_ADDRSTRLEN));
413*7c478bd9Sstevel@tonic-gate 				if (vflag) {
414*7c478bd9Sstevel@tonic-gate 					disp_host((char *)&addr->s6_addr,
415*7c478bd9Sstevel@tonic-gate 					    AF_INET6);
416*7c478bd9Sstevel@tonic-gate 				}
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate 			}
419*7c478bd9Sstevel@tonic-gate 			break;
420*7c478bd9Sstevel@tonic-gate 		default:
421*7c478bd9Sstevel@tonic-gate 			{
422*7c478bd9Sstevel@tonic-gate 				ea_size_t size = o->eo_item.ei_size;
423*7c478bd9Sstevel@tonic-gate 				char *buf = o->eo_item.ei_raw;
424*7c478bd9Sstevel@tonic-gate 				uint64_t i;
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate 				for (i = 0; i < size && i < 6; i++)
427*7c478bd9Sstevel@tonic-gate 					(void) printf("0x%2X ", buf[i]);
428*7c478bd9Sstevel@tonic-gate 				if (size > 6)
429*7c478bd9Sstevel@tonic-gate 					(void) printf("...");
430*7c478bd9Sstevel@tonic-gate 			}
431*7c478bd9Sstevel@tonic-gate 		}
432*7c478bd9Sstevel@tonic-gate 		break;
433*7c478bd9Sstevel@tonic-gate 	case EXT_GROUP:
434*7c478bd9Sstevel@tonic-gate 		(void) printf("[group of %u object(s)]", o->eo_group.eg_nobjs);
435*7c478bd9Sstevel@tonic-gate 		break;
436*7c478bd9Sstevel@tonic-gate 	case EXT_EXACCT_OBJECT:
437*7c478bd9Sstevel@tonic-gate 		/*
438*7c478bd9Sstevel@tonic-gate 		 * Embedded exacct records.
439*7c478bd9Sstevel@tonic-gate 		 */
440*7c478bd9Sstevel@tonic-gate 		{
441*7c478bd9Sstevel@tonic-gate 			ea_object_type_t ot;
442*7c478bd9Sstevel@tonic-gate 			ea_object_t *op;
443*7c478bd9Sstevel@tonic-gate 			ea_object_t *eo;
444*7c478bd9Sstevel@tonic-gate 
445*7c478bd9Sstevel@tonic-gate 			ot = ea_unpack_object(&op, EUP_ALLOC,
446*7c478bd9Sstevel@tonic-gate 			    o->eo_item.ei_object, o->eo_item.ei_size);
447*7c478bd9Sstevel@tonic-gate 
448*7c478bd9Sstevel@tonic-gate 			if (ot == EO_ERROR) {
449*7c478bd9Sstevel@tonic-gate 				(void) printf("error: couldn't unpack embedded "
450*7c478bd9Sstevel@tonic-gate 				    "object\n");
451*7c478bd9Sstevel@tonic-gate 				break;
452*7c478bd9Sstevel@tonic-gate 			}
453*7c478bd9Sstevel@tonic-gate 			eol = 0;
454*7c478bd9Sstevel@tonic-gate 			if (ot == EO_GROUP) {
455*7c478bd9Sstevel@tonic-gate 				(void) printf("[embedded group of %u "
456*7c478bd9Sstevel@tonic-gate 				    "object(s)]\n", op->eo_group.eg_nobjs);
457*7c478bd9Sstevel@tonic-gate 				eo = op->eo_group.eg_objs;
458*7c478bd9Sstevel@tonic-gate 				disp_embedded_group(eo, indent);
459*7c478bd9Sstevel@tonic-gate 			} else {
460*7c478bd9Sstevel@tonic-gate 				(void) printf("[embedded object]\n");
461*7c478bd9Sstevel@tonic-gate 				disp_obj(op, indent);
462*7c478bd9Sstevel@tonic-gate 			}
463*7c478bd9Sstevel@tonic-gate 			ea_free_object(op, EUP_ALLOC);
464*7c478bd9Sstevel@tonic-gate 		}
465*7c478bd9Sstevel@tonic-gate 		break;
466*7c478bd9Sstevel@tonic-gate 	default:
467*7c478bd9Sstevel@tonic-gate 		(void) printf("[complex value]");
468*7c478bd9Sstevel@tonic-gate 		break;
469*7c478bd9Sstevel@tonic-gate 	}
470*7c478bd9Sstevel@tonic-gate 
471*7c478bd9Sstevel@tonic-gate 	if (eol)
472*7c478bd9Sstevel@tonic-gate 		(void) printf("\n");
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate }
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate /*
477*7c478bd9Sstevel@tonic-gate  * Read and display a group of exacct objects from the file.
478*7c478bd9Sstevel@tonic-gate  */
479*7c478bd9Sstevel@tonic-gate static void
480*7c478bd9Sstevel@tonic-gate disp_group(ea_file_t *ef, uint_t nobjs, int indent)
481*7c478bd9Sstevel@tonic-gate {
482*7c478bd9Sstevel@tonic-gate 	uint_t i;
483*7c478bd9Sstevel@tonic-gate 
484*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < nobjs; i++) {
485*7c478bd9Sstevel@tonic-gate 		ea_object_t scratch;
486*7c478bd9Sstevel@tonic-gate 		int res;
487*7c478bd9Sstevel@tonic-gate 
488*7c478bd9Sstevel@tonic-gate 		if ((res = ea_get_object(ef, &scratch)) == -1) {
489*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
490*7c478bd9Sstevel@tonic-gate 			    "bad file: ea_get_object()==%d\n", res);
491*7c478bd9Sstevel@tonic-gate 			exit(2);
492*7c478bd9Sstevel@tonic-gate 		}
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate 		disp_obj(&scratch, indent + 1);
495*7c478bd9Sstevel@tonic-gate 
496*7c478bd9Sstevel@tonic-gate 		if (scratch.eo_type == EO_GROUP)
497*7c478bd9Sstevel@tonic-gate 			disp_group(ef, scratch.eo_group.eg_nobjs, indent + 1);
498*7c478bd9Sstevel@tonic-gate 		else
499*7c478bd9Sstevel@tonic-gate 			(void) ea_free_item(&scratch, EUP_ALLOC);
500*7c478bd9Sstevel@tonic-gate 	}
501*7c478bd9Sstevel@tonic-gate }
502*7c478bd9Sstevel@tonic-gate 
503*7c478bd9Sstevel@tonic-gate static void
504*7c478bd9Sstevel@tonic-gate usage()
505*7c478bd9Sstevel@tonic-gate {
506*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "Usage: exdump [-v] <file>\n");
507*7c478bd9Sstevel@tonic-gate 	exit(2);
508*7c478bd9Sstevel@tonic-gate }
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate int
511*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
512*7c478bd9Sstevel@tonic-gate {
513*7c478bd9Sstevel@tonic-gate 	ea_file_t ef;
514*7c478bd9Sstevel@tonic-gate 	ea_object_t scratch;
515*7c478bd9Sstevel@tonic-gate 	char *fname;
516*7c478bd9Sstevel@tonic-gate 	int opt;
517*7c478bd9Sstevel@tonic-gate 
518*7c478bd9Sstevel@tonic-gate 	while ((opt = getopt(argc, argv, "v")) != EOF) {
519*7c478bd9Sstevel@tonic-gate 		switch (opt) {
520*7c478bd9Sstevel@tonic-gate 		case 'v':
521*7c478bd9Sstevel@tonic-gate 			vflag = 1;
522*7c478bd9Sstevel@tonic-gate 			break;
523*7c478bd9Sstevel@tonic-gate 		default:
524*7c478bd9Sstevel@tonic-gate 			usage();
525*7c478bd9Sstevel@tonic-gate 		}
526*7c478bd9Sstevel@tonic-gate 	}
527*7c478bd9Sstevel@tonic-gate 
528*7c478bd9Sstevel@tonic-gate 	if (argc == optind)
529*7c478bd9Sstevel@tonic-gate 		usage();
530*7c478bd9Sstevel@tonic-gate 	if (argc > optind)
531*7c478bd9Sstevel@tonic-gate 		fname = argv[optind++];
532*7c478bd9Sstevel@tonic-gate 	if (argc > optind)
533*7c478bd9Sstevel@tonic-gate 		usage();
534*7c478bd9Sstevel@tonic-gate 
535*7c478bd9Sstevel@tonic-gate 	if (ea_open(&ef, fname, NULL,
536*7c478bd9Sstevel@tonic-gate 	    vflag ? EO_NO_VALID_HDR : 0, O_RDONLY, 0) == -1) {
537*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "exdump: cannot open %s\n", fname);
538*7c478bd9Sstevel@tonic-gate 		return (1);
539*7c478bd9Sstevel@tonic-gate 	}
540*7c478bd9Sstevel@tonic-gate 
541*7c478bd9Sstevel@tonic-gate 	bzero(&scratch, sizeof (ea_object_t));
542*7c478bd9Sstevel@tonic-gate 	while (ea_get_object(&ef, &scratch) != -1) {
543*7c478bd9Sstevel@tonic-gate 		disp_obj(&scratch, 0);
544*7c478bd9Sstevel@tonic-gate 		if (scratch.eo_type == EO_GROUP)
545*7c478bd9Sstevel@tonic-gate 			disp_group(&ef, scratch.eo_group.eg_nobjs, 0);
546*7c478bd9Sstevel@tonic-gate 		else
547*7c478bd9Sstevel@tonic-gate 			(void) ea_free_item(&scratch, EUP_ALLOC);
548*7c478bd9Sstevel@tonic-gate 		(void) bzero(&scratch, sizeof (ea_object_t));
549*7c478bd9Sstevel@tonic-gate 	}
550*7c478bd9Sstevel@tonic-gate 
551*7c478bd9Sstevel@tonic-gate 	(void) ea_close(&ef);
552*7c478bd9Sstevel@tonic-gate 	return (0);
553*7c478bd9Sstevel@tonic-gate }
554