4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
30 #include <sys/types.h>
31 #include <sys/socket.h>
40 #include <netinet/in.h>
41 #include <arpa/inet.h>
45 #define FMT_UINT64 "%-15llu"
47 #define FMT_UINT64 "%-15lu"
50 #define MAX_DEPTH 25 /* maximum depth level */
54 typedef struct catalog_item
{
60 * The actual constants are defined in <sys/exacct_catalog.h>.
62 static catalog_item_t catalog
[] = {
63 { EXD_VERSION
, "version" },
64 { EXD_FILETYPE
, "filetype" },
65 { EXD_CREATOR
, "creator" },
66 { EXD_HOSTNAME
, "hostname" },
68 { EXD_GROUP_HEADER
, "group-header" },
69 { EXD_GROUP_PROC
, "group-proc" },
70 { EXD_GROUP_TASK
, "group-task" },
71 { EXD_GROUP_LWP
, "group-lwp" },
72 { EXD_GROUP_FLOW
, "group-flow" },
73 { EXD_GROUP_PROC_TAG
, "group-proc-tag" },
74 { EXD_GROUP_TASK_TAG
, "group-task-tag" },
75 { EXD_GROUP_LWP_TAG
, "group-lwp-tag" },
76 { EXD_GROUP_PROC_PARTIAL
, "group-proc-partial" },
77 { EXD_GROUP_TASK_PARTIAL
, "group-task-partial" },
78 { EXD_GROUP_TASK_INTERVAL
, "group-task-interval" },
80 { EXD_PROC_PID
, "pid" },
81 { EXD_PROC_ANCPID
, "ppid" },
82 { EXD_PROC_UID
, "uid" },
83 { EXD_PROC_GID
, "gid" },
84 { EXD_PROC_TASKID
, "taskid" },
85 { EXD_PROC_PROJID
, "projid" },
86 { EXD_PROC_HOSTNAME
, "hostname" },
87 { EXD_PROC_COMMAND
, "command" },
88 { EXD_PROC_WAIT_STATUS
, "wait-status" },
89 { EXD_PROC_START_SEC
, "start-sec" },
90 { EXD_PROC_START_NSEC
, "start-nsec" },
91 { EXD_PROC_FINISH_SEC
, "finish-sec" },
92 { EXD_PROC_FINISH_NSEC
, "finish-nsec" },
93 { EXD_PROC_CPU_USER_SEC
, "cpu-user-sec" },
94 { EXD_PROC_CPU_USER_NSEC
, "cpu-user-nsec" },
95 { EXD_PROC_CPU_SYS_SEC
, "cpu-sys-sec" },
96 { EXD_PROC_CPU_SYS_NSEC
, "cpu-sys-nsec" },
97 { EXD_PROC_TTY_MAJOR
, "tty-major" },
98 { EXD_PROC_TTY_MINOR
, "tty-minor" },
99 { EXD_PROC_FAULTS_MAJOR
, "faults-major" },
100 { EXD_PROC_FAULTS_MINOR
, "faults-minor" },
101 { EXD_PROC_MESSAGES_RCV
, "msgs-recv" },
102 { EXD_PROC_MESSAGES_SND
, "msgs-snd" },
103 { EXD_PROC_BLOCKS_IN
, "blocks-in" },
104 { EXD_PROC_BLOCKS_OUT
, "blocks-out" },
105 { EXD_PROC_CHARS_RDWR
, "chars-rdwr" },
106 { EXD_PROC_CONTEXT_VOL
, "ctxt-vol" },
107 { EXD_PROC_CONTEXT_INV
, "ctxt-inv" },
108 { EXD_PROC_SIGNALS
, "signals" },
109 { EXD_PROC_SWAPS
, "swaps" },
110 { EXD_PROC_SYSCALLS
, "syscalls" },
111 { EXD_PROC_TAG
, "proc-tag" },
112 { EXD_PROC_ACCT_FLAGS
, "acctflags" },
113 { EXD_PROC_ZONENAME
, "zone" },
114 { EXD_PROC_MEM_RSS_AVG_K
, "memory-rss-avg-k" },
115 { EXD_PROC_MEM_RSS_MAX_K
, "memory-rss-max-k" },
117 { EXD_TASK_TASKID
, "taskid" },
118 { EXD_TASK_ANCTASKID
, "anctaskid" },
119 { EXD_TASK_PROJID
, "projid" },
120 { EXD_TASK_HOSTNAME
, "hostname" },
121 { EXD_TASK_START_SEC
, "start-sec" },
122 { EXD_TASK_START_NSEC
, "start-nsec" },
123 { EXD_TASK_FINISH_SEC
, "finish-sec" },
124 { EXD_TASK_FINISH_NSEC
, "finish-nsec" },
125 { EXD_TASK_CPU_USER_SEC
, "cpu-user-sec" },
126 { EXD_TASK_CPU_USER_NSEC
, "cpu-user-nsec" },
127 { EXD_TASK_CPU_SYS_SEC
, "cpu-sys-sec" },
128 { EXD_TASK_CPU_SYS_NSEC
, "cpu-sys-nsec" },
129 { EXD_TASK_FAULTS_MAJOR
, "faults-major" },
130 { EXD_TASK_FAULTS_MINOR
, "faults-minor" },
131 { EXD_TASK_MESSAGES_RCV
, "msgs-recv" },
132 { EXD_TASK_MESSAGES_SND
, "msgs-snd" },
133 { EXD_TASK_BLOCKS_IN
, "blocks-in" },
134 { EXD_TASK_BLOCKS_OUT
, "blocks-out" },
135 { EXD_TASK_CHARS_RDWR
, "chars-rdwr" },
136 { EXD_TASK_CONTEXT_VOL
, "ctxt-vol" },
137 { EXD_TASK_CONTEXT_INV
, "ctxt-inv" },
138 { EXD_TASK_SIGNALS
, "signals" },
139 { EXD_TASK_SWAPS
, "swaps" },
140 { EXD_TASK_SYSCALLS
, "syscalls" },
141 { EXD_TASK_TAG
, "task-tag" },
142 { EXD_TASK_ZONENAME
, "zone" },
144 { EXD_FLOW_V4SADDR
, "src-addr-v4" },
145 { EXD_FLOW_V4DADDR
, "dest-addr-v4" },
146 { EXD_FLOW_V6SADDR
, "src-addr-v6" },
147 { EXD_FLOW_V6DADDR
, "dest-addr-v6" },
148 { EXD_FLOW_SPORT
, "src-port" },
149 { EXD_FLOW_DPORT
, "dest-port" },
150 { EXD_FLOW_PROTOCOL
, "protocol" },
151 { EXD_FLOW_DSFIELD
, "diffserv-field" },
152 { EXD_FLOW_NBYTES
, "total-bytes" },
153 { EXD_FLOW_NPKTS
, "total-packets" },
154 { EXD_FLOW_CTIME
, "creation-time" },
155 { EXD_FLOW_LSEEN
, "last-seen" },
156 { EXD_FLOW_PROJID
, "projid" },
157 { EXD_FLOW_UID
, "uid" },
158 { EXD_FLOW_ANAME
, "action-name" },
163 static void disp_obj(ea_object_t
*o
, int indent
);
166 * Convert catalog ID into catalog name.
169 catalog_name(int type
)
173 while (catalog
[i
].type
!= EXD_NONE
) {
174 if (catalog
[i
].type
== type
)
175 return (catalog
[i
].name
);
183 * Display port information, if available
186 disp_port(uint16_t port
)
188 struct servent
*port_info
;
190 port_info
= getservbyport(htons(port
), NULL
);
191 if (port_info
!= NULL
) {
192 (void) printf("%s", port_info
->s_name
);
197 * Display host name for a given IP address if available.
200 disp_host(char *addr
, int family
)
206 len
= (family
== AF_INET
) ? sizeof (struct in_addr
) :
207 sizeof (struct in6_addr
);
209 if ((phe
= getipnodebyaddr(addr
, len
, family
, &error_num
)) != NULL
) {
210 (void) printf("%s", phe
->h_name
);
215 * Display protocol information, if available.
218 disp_proto(uint8_t protocol
)
220 struct protoent
*proto_ent
;
222 proto_ent
= getprotobynumber(protocol
);
223 if (proto_ent
!= NULL
) {
224 (void) printf("%s", proto_ent
->p_name
);
230 * Display recursively exacct objects in a given embedded group.
233 disp_embedded_group(ea_object_t
*eo
, int indent
)
236 disp_obj(eo
, indent
+ 1);
237 if (eo
->eo_type
== EO_GROUP
)
238 disp_embedded_group(eo
->eo_group
.eg_objs
, indent
+ 1);
244 * Display the data stored in a given exacct object.
247 disp_obj(ea_object_t
*o
, int indent
)
249 char objname
[30] = " ";
252 if (indent
> MAX_DEPTH
) {
257 (void) printf("%6x\t", (o
->eo_catalog
& EXD_DATA_MASK
));
258 (void) snprintf(objname
+ indent
, 30 - indent
, "%-s",
259 catalog_name(o
->eo_catalog
& EXD_DATA_MASK
));
260 (void) printf("%-30s\t", objname
);
262 switch (o
->eo_catalog
& EXT_TYPE_MASK
) {
264 (void) printf("%-15u", o
->eo_item
.ei_uint8
);
266 ((o
->eo_catalog
& EXD_DATA_MASK
) == EXD_FLOW_PROTOCOL
)) {
267 disp_proto(o
->eo_item
.ei_uint8
);
271 (void) printf("%-15u", o
->eo_item
.ei_uint16
);
273 (((o
->eo_catalog
& EXD_DATA_MASK
) == EXD_FLOW_SPORT
) ||
274 ((o
->eo_catalog
& EXD_DATA_MASK
) == EXD_FLOW_DPORT
))) {
275 disp_port(o
->eo_item
.ei_uint16
);
279 switch (o
->eo_catalog
& EXD_DATA_MASK
) {
280 case EXD_PROC_WAIT_STATUS
:
282 int wstat
= o
->eo_item
.ei_uint32
;
285 if (WIFEXITED(wstat
))
286 (void) printf("%-14d exit",
288 else if (WIFSIGNALED(wstat
))
289 (void) printf("%14d, signal",
292 (void) printf("%d", wstat
);
294 (void) printf("%d", wstat
);
300 uid_t uid
= o
->eo_item
.ei_uint32
;
302 (void) printf("%-15u", uid
);
305 if ((pwd
= getpwuid(uid
)) != NULL
)
313 gid_t gid
= o
->eo_item
.ei_uint32
;
315 (void) printf("%-15u", gid
);
318 if ((grp
= getgrgid(gid
)) != NULL
)
324 case EXD_PROC_PROJID
:
325 case EXD_TASK_PROJID
:
327 projid_t projid
= o
->eo_item
.ei_uint32
;
329 (void) printf("%-15lu", projid
);
332 char projbuf
[PROJECT_BUFSZ
];
334 if (getprojbyid(projid
, &proj
, projbuf
,
335 PROJECT_BUFSZ
) != NULL
)
341 case EXD_PROC_ACCT_FLAGS
:
343 int flag
= o
->eo_item
.ei_uint32
;
345 (void) printf("%-15u", flag
);
348 (void) printf("FORK ");
354 case EXD_FLOW_V4SADDR
:
356 case EXD_FLOW_V4DADDR
:
358 char str
[INET_ADDRSTRLEN
];
359 uint32_t addr
= htonl(o
->eo_item
.ei_uint32
);
361 (void) printf("%-15s",
362 inet_ntop(AF_INET
, &addr
, str
,
365 disp_host((char *)&addr
, AF_INET
);
370 (void) printf("%u", o
->eo_item
.ei_uint32
);
378 (void) printf(FMT_UINT64
, o
->eo_item
.ei_uint64
);
381 if (ea_match_object_catalog(o
, EXD_TASK_START_SEC
) ||
382 ea_match_object_catalog(o
, EXD_TASK_FINISH_SEC
) ||
383 ea_match_object_catalog(o
, EXD_PROC_START_SEC
) ||
384 ea_match_object_catalog(o
, EXD_PROC_FINISH_SEC
) ||
385 ea_match_object_catalog(o
, EXD_FLOW_LSEEN
) ||
386 ea_match_object_catalog(o
, EXD_FLOW_CTIME
)) {
387 _time
= o
->eo_item
.ei_uint64
;
388 (void) strftime(timebuf
, sizeof (timebuf
),
389 "%D %T", localtime(&_time
));
390 (void) fputs(timebuf
, stdout
);
395 (void) printf("%f", o
->eo_item
.ei_double
);
398 (void) printf("\"%s\"", o
->eo_item
.ei_string
);
401 switch (o
->eo_catalog
& EXD_DATA_MASK
) {
402 case EXD_FLOW_V6SADDR
:
404 case EXD_FLOW_V6DADDR
:
407 char str
[INET6_ADDRSTRLEN
];
409 addr
= (in6_addr_t
*)o
->eo_item
.ei_raw
;
410 (void) printf("%-28s", inet_ntop(AF_INET6
,
411 &addr
->s6_addr
, str
, INET6_ADDRSTRLEN
));
413 disp_host((char *)&addr
->s6_addr
,
421 ea_size_t size
= o
->eo_item
.ei_size
;
422 char *buf
= o
->eo_item
.ei_raw
;
425 for (i
= 0; i
< size
&& i
< 6; i
++)
426 (void) printf("0x%2X ", buf
[i
]);
428 (void) printf("...");
433 (void) printf("[group of %u object(s)]", o
->eo_group
.eg_nobjs
);
435 case EXT_EXACCT_OBJECT
:
437 * Embedded exacct records.
444 ot
= ea_unpack_object(&op
, EUP_ALLOC
,
445 o
->eo_item
.ei_object
, o
->eo_item
.ei_size
);
447 if (ot
== EO_ERROR
) {
448 (void) printf("error: couldn't unpack embedded "
453 if (ot
== EO_GROUP
) {
454 (void) printf("[embedded group of %u "
455 "object(s)]\n", op
->eo_group
.eg_nobjs
);
456 eo
= op
->eo_group
.eg_objs
;
457 disp_embedded_group(eo
, indent
);
459 (void) printf("[embedded object]\n");
460 disp_obj(op
, indent
);
462 ea_free_object(op
, EUP_ALLOC
);
466 (void) printf("[complex value]");
476 * Read and display a group of exacct objects from the file.
479 disp_group(ea_file_t
*ef
, uint_t nobjs
, int indent
)
483 for (i
= 0; i
< nobjs
; i
++) {
487 if ((res
= ea_get_object(ef
, &scratch
)) == -1) {
488 (void) fprintf(stderr
,
489 "bad file: ea_get_object()==%d\n", res
);
493 disp_obj(&scratch
, indent
+ 1);
495 if (scratch
.eo_type
== EO_GROUP
)
496 disp_group(ef
, scratch
.eo_group
.eg_nobjs
, indent
+ 1);
498 (void) ea_free_item(&scratch
, EUP_ALLOC
);
505 (void) fprintf(stderr
, "Usage: exdump [-v] <file>\n");
510 main(int argc
, char *argv
[])
517 while ((opt
= getopt(argc
, argv
, "v")) != EOF
) {
530 fname
= argv
[optind
++];
534 if (ea_open(&ef
, fname
, NULL
,
535 vflag
? EO_NO_VALID_HDR
: 0, O_RDONLY
, 0) == -1) {
536 (void) fprintf(stderr
, "exdump: cannot open %s\n", fname
);
540 bzero(&scratch
, sizeof (ea_object_t
));
541 while (ea_get_object(&ef
, &scratch
) != -1) {
542 disp_obj(&scratch
, 0);
543 if (scratch
.eo_type
== EO_GROUP
)
544 disp_group(&ef
, scratch
.eo_group
.eg_nobjs
, 0);
546 (void) ea_free_item(&scratch
, EUP_ALLOC
);
547 (void) bzero(&scratch
, sizeof (ea_object_t
));
550 (void) ea_close(&ef
);