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 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 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 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 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