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 <stdlib.h> 30*7c478bd9Sstevel@tonic-gate #include <stdio.h> 31*7c478bd9Sstevel@tonic-gate #include <libintl.h> 32*7c478bd9Sstevel@tonic-gate #include <string.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/acctctl.h> 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate #include "utils.h" 36*7c478bd9Sstevel@tonic-gate #include "aconf.h" 37*7c478bd9Sstevel@tonic-gate #include "res.h" 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate /* 40*7c478bd9Sstevel@tonic-gate * resource names 41*7c478bd9Sstevel@tonic-gate */ 42*7c478bd9Sstevel@tonic-gate static ac_resname_t ac_names[] = { 43*7c478bd9Sstevel@tonic-gate /* 44*7c478bd9Sstevel@tonic-gate * Process accounting resources 45*7c478bd9Sstevel@tonic-gate */ 46*7c478bd9Sstevel@tonic-gate { AC_PROC, AC_PROC_PID, "pid" }, 47*7c478bd9Sstevel@tonic-gate { AC_PROC, AC_PROC_UID, "uid" }, 48*7c478bd9Sstevel@tonic-gate { AC_PROC, AC_PROC_GID, "gid" }, 49*7c478bd9Sstevel@tonic-gate { AC_PROC, AC_PROC_PROJID, "projid" }, 50*7c478bd9Sstevel@tonic-gate { AC_PROC, AC_PROC_TASKID, "taskid" }, 51*7c478bd9Sstevel@tonic-gate { AC_PROC, AC_PROC_CPU, "cpu" }, 52*7c478bd9Sstevel@tonic-gate { AC_PROC, AC_PROC_TIME, "time" }, 53*7c478bd9Sstevel@tonic-gate { AC_PROC, AC_PROC_COMMAND, "command" }, 54*7c478bd9Sstevel@tonic-gate { AC_PROC, AC_PROC_TTY, "tty" }, 55*7c478bd9Sstevel@tonic-gate { AC_PROC, AC_PROC_HOSTNAME, "host" }, 56*7c478bd9Sstevel@tonic-gate { AC_PROC, AC_PROC_MICROSTATE, "mstate" }, 57*7c478bd9Sstevel@tonic-gate { AC_PROC, AC_PROC_FLAG, "flag" }, 58*7c478bd9Sstevel@tonic-gate { AC_PROC, AC_PROC_ANCPID, "ancpid" }, 59*7c478bd9Sstevel@tonic-gate { AC_PROC, AC_PROC_WAIT_STATUS, "wait-status" }, 60*7c478bd9Sstevel@tonic-gate { AC_PROC, AC_PROC_ZONENAME, "zone" }, 61*7c478bd9Sstevel@tonic-gate { AC_PROC, AC_PROC_MEM, "memory" }, 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate /* 64*7c478bd9Sstevel@tonic-gate * Task accounting resources 65*7c478bd9Sstevel@tonic-gate */ 66*7c478bd9Sstevel@tonic-gate { AC_TASK, AC_TASK_TASKID, "taskid" }, 67*7c478bd9Sstevel@tonic-gate { AC_TASK, AC_TASK_PROJID, "projid" }, 68*7c478bd9Sstevel@tonic-gate { AC_TASK, AC_TASK_CPU, "cpu" }, 69*7c478bd9Sstevel@tonic-gate { AC_TASK, AC_TASK_TIME, "time" }, 70*7c478bd9Sstevel@tonic-gate { AC_TASK, AC_TASK_HOSTNAME, "host" }, 71*7c478bd9Sstevel@tonic-gate { AC_TASK, AC_TASK_MICROSTATE, "mstate" }, 72*7c478bd9Sstevel@tonic-gate { AC_TASK, AC_TASK_ANCTASKID, "anctaskid" }, 73*7c478bd9Sstevel@tonic-gate { AC_TASK, AC_TASK_ZONENAME, "zone" }, 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate /* 76*7c478bd9Sstevel@tonic-gate * Flow accounting resources 77*7c478bd9Sstevel@tonic-gate */ 78*7c478bd9Sstevel@tonic-gate { AC_FLOW, AC_FLOW_SADDR, "saddr" }, 79*7c478bd9Sstevel@tonic-gate { AC_FLOW, AC_FLOW_DADDR, "daddr" }, 80*7c478bd9Sstevel@tonic-gate { AC_FLOW, AC_FLOW_SPORT, "sport" }, 81*7c478bd9Sstevel@tonic-gate { AC_FLOW, AC_FLOW_DPORT, "dport" }, 82*7c478bd9Sstevel@tonic-gate { AC_FLOW, AC_FLOW_PROTOCOL, "proto" }, 83*7c478bd9Sstevel@tonic-gate { AC_FLOW, AC_FLOW_DSFIELD, "dsfield" }, 84*7c478bd9Sstevel@tonic-gate { AC_FLOW, AC_FLOW_NBYTES, "nbytes" }, 85*7c478bd9Sstevel@tonic-gate { AC_FLOW, AC_FLOW_NPKTS, "npkts" }, 86*7c478bd9Sstevel@tonic-gate { AC_FLOW, AC_FLOW_CTIME, "ctime" }, 87*7c478bd9Sstevel@tonic-gate { AC_FLOW, AC_FLOW_LSEEN, "lseen" }, 88*7c478bd9Sstevel@tonic-gate { AC_FLOW, AC_FLOW_PROJID, "projid" }, 89*7c478bd9Sstevel@tonic-gate { AC_FLOW, AC_FLOW_UID, "uid" }, 90*7c478bd9Sstevel@tonic-gate { AC_FLOW, AC_FLOW_ANAME, "action" }, 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate /* 93*7c478bd9Sstevel@tonic-gate * These are included for compatibility with old acctadm that 94*7c478bd9Sstevel@tonic-gate * didn't have resource groups for individual accounting types. 95*7c478bd9Sstevel@tonic-gate * It was possible to have resource "pid" enabled for task 96*7c478bd9Sstevel@tonic-gate * accounting even though we couldn't actually track it. 97*7c478bd9Sstevel@tonic-gate */ 98*7c478bd9Sstevel@tonic-gate { AC_TASK, AC_NONE, "pid" }, 99*7c478bd9Sstevel@tonic-gate { AC_TASK, AC_NONE, "uid" }, 100*7c478bd9Sstevel@tonic-gate { AC_TASK, AC_NONE, "gid" }, 101*7c478bd9Sstevel@tonic-gate { AC_TASK, AC_NONE, "command" }, 102*7c478bd9Sstevel@tonic-gate { AC_TASK, AC_NONE, "tty" }, 103*7c478bd9Sstevel@tonic-gate { AC_TASK, AC_NONE, "flag" }, 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate { AC_NONE, AC_NONE, NULL } 106*7c478bd9Sstevel@tonic-gate }; 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate /* 109*7c478bd9Sstevel@tonic-gate * resource groups 110*7c478bd9Sstevel@tonic-gate */ 111*7c478bd9Sstevel@tonic-gate static ac_group_t ac_groups[] = { 112*7c478bd9Sstevel@tonic-gate { AC_PROC, "extended", 113*7c478bd9Sstevel@tonic-gate { AC_PROC_PID, AC_PROC_UID, AC_PROC_GID, AC_PROC_CPU, 114*7c478bd9Sstevel@tonic-gate AC_PROC_TIME, AC_PROC_COMMAND, AC_PROC_TTY, AC_PROC_PROJID, 115*7c478bd9Sstevel@tonic-gate AC_PROC_TASKID, AC_PROC_ANCPID, AC_PROC_WAIT_STATUS, 116*7c478bd9Sstevel@tonic-gate AC_PROC_ZONENAME, AC_PROC_FLAG, AC_PROC_MEM, 117*7c478bd9Sstevel@tonic-gate AC_PROC_MICROSTATE, AC_NONE } }, 118*7c478bd9Sstevel@tonic-gate { AC_PROC, "basic", 119*7c478bd9Sstevel@tonic-gate { AC_PROC_PID, AC_PROC_UID, AC_PROC_GID, AC_PROC_CPU, 120*7c478bd9Sstevel@tonic-gate AC_PROC_TIME, AC_PROC_COMMAND, AC_PROC_TTY, AC_PROC_FLAG, 121*7c478bd9Sstevel@tonic-gate AC_NONE } }, 122*7c478bd9Sstevel@tonic-gate { AC_TASK, "extended", 123*7c478bd9Sstevel@tonic-gate { AC_TASK_TASKID, AC_TASK_PROJID, AC_TASK_CPU, AC_TASK_TIME, 124*7c478bd9Sstevel@tonic-gate AC_TASK_HOSTNAME, AC_TASK_MICROSTATE, AC_TASK_ANCTASKID, 125*7c478bd9Sstevel@tonic-gate AC_TASK_ZONENAME, AC_NONE } }, 126*7c478bd9Sstevel@tonic-gate { AC_TASK, "basic", 127*7c478bd9Sstevel@tonic-gate { AC_TASK_TASKID, AC_TASK_PROJID, AC_TASK_CPU, AC_TASK_TIME, 128*7c478bd9Sstevel@tonic-gate AC_NONE } }, 129*7c478bd9Sstevel@tonic-gate { AC_FLOW, "extended", 130*7c478bd9Sstevel@tonic-gate { AC_FLOW_SADDR, AC_FLOW_DADDR, AC_FLOW_SPORT, AC_FLOW_DPORT, 131*7c478bd9Sstevel@tonic-gate AC_FLOW_PROTOCOL, AC_FLOW_DSFIELD, AC_FLOW_NBYTES, 132*7c478bd9Sstevel@tonic-gate AC_FLOW_NPKTS, AC_FLOW_ANAME, AC_FLOW_CTIME, AC_FLOW_LSEEN, 133*7c478bd9Sstevel@tonic-gate AC_FLOW_PROJID, AC_FLOW_UID, AC_NONE } }, 134*7c478bd9Sstevel@tonic-gate { AC_FLOW, "basic", 135*7c478bd9Sstevel@tonic-gate { AC_FLOW_SADDR, AC_FLOW_DADDR, AC_FLOW_SPORT, AC_FLOW_DPORT, 136*7c478bd9Sstevel@tonic-gate AC_FLOW_PROTOCOL, AC_FLOW_NBYTES, AC_FLOW_NPKTS, AC_FLOW_ANAME, 137*7c478bd9Sstevel@tonic-gate AC_NONE } }, 138*7c478bd9Sstevel@tonic-gate { AC_NONE, NULL, 139*7c478bd9Sstevel@tonic-gate { AC_NONE } } 140*7c478bd9Sstevel@tonic-gate }; 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate /* 143*7c478bd9Sstevel@tonic-gate * this function returns the id of the named resource 144*7c478bd9Sstevel@tonic-gate */ 145*7c478bd9Sstevel@tonic-gate static int 146*7c478bd9Sstevel@tonic-gate name2id(char *name, int type) 147*7c478bd9Sstevel@tonic-gate { 148*7c478bd9Sstevel@tonic-gate ac_resname_t *acname = ac_names; 149*7c478bd9Sstevel@tonic-gate while (acname->ar_type != AC_NONE) { 150*7c478bd9Sstevel@tonic-gate if (acname->ar_type == type && 151*7c478bd9Sstevel@tonic-gate strcmp(acname->ar_name, name) == 0) { 152*7c478bd9Sstevel@tonic-gate if (acname->ar_id == AC_NONE) 153*7c478bd9Sstevel@tonic-gate /* 154*7c478bd9Sstevel@tonic-gate * For compatibility with older versions. 155*7c478bd9Sstevel@tonic-gate */ 156*7c478bd9Sstevel@tonic-gate return (-1); 157*7c478bd9Sstevel@tonic-gate else 158*7c478bd9Sstevel@tonic-gate return (acname->ar_id); 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate acname++; 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate return (0); 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate /* 166*7c478bd9Sstevel@tonic-gate * this function gives name of the resource by its id 167*7c478bd9Sstevel@tonic-gate */ 168*7c478bd9Sstevel@tonic-gate static char * 169*7c478bd9Sstevel@tonic-gate id2name(int id, int type) 170*7c478bd9Sstevel@tonic-gate { 171*7c478bd9Sstevel@tonic-gate ac_resname_t *acname = ac_names; 172*7c478bd9Sstevel@tonic-gate while (acname->ar_id != AC_NONE) { 173*7c478bd9Sstevel@tonic-gate if (acname->ar_type == type && 174*7c478bd9Sstevel@tonic-gate acname->ar_id == id) 175*7c478bd9Sstevel@tonic-gate return (acname->ar_name); 176*7c478bd9Sstevel@tonic-gate acname++; 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate return (NULL); 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate static void 182*7c478bd9Sstevel@tonic-gate printgroup(int type) 183*7c478bd9Sstevel@tonic-gate { 184*7c478bd9Sstevel@tonic-gate int r, g, id; 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate for (g = 0; ac_groups[g].ag_type != AC_NONE; g++) { 187*7c478bd9Sstevel@tonic-gate if (ac_groups[g].ag_type != type) 188*7c478bd9Sstevel@tonic-gate continue; 189*7c478bd9Sstevel@tonic-gate (void) printf("%-9s", ac_groups[g].ag_name); 190*7c478bd9Sstevel@tonic-gate (void) printf("%s", id2name(ac_groups[g].ag_mem[0], type)); 191*7c478bd9Sstevel@tonic-gate for (r = 1; (id = ac_groups[g].ag_mem[r]) != AC_NONE; r++) 192*7c478bd9Sstevel@tonic-gate (void) printf(",%s", id2name(id, type)); 193*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate /* 199*7c478bd9Sstevel@tonic-gate * this function prints the list of resource groups and their members 200*7c478bd9Sstevel@tonic-gate */ 201*7c478bd9Sstevel@tonic-gate void 202*7c478bd9Sstevel@tonic-gate printgroups(int type) 203*7c478bd9Sstevel@tonic-gate { 204*7c478bd9Sstevel@tonic-gate int header = 0; 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate if ((type & AC_PROC) && (type & AC_TASK) && (type & AC_FLOW)) 207*7c478bd9Sstevel@tonic-gate header = 1; 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate if (type & AC_PROC) { 210*7c478bd9Sstevel@tonic-gate if (header == 1) 211*7c478bd9Sstevel@tonic-gate (void) printf("process:\n"); 212*7c478bd9Sstevel@tonic-gate printgroup(AC_PROC); 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate if (type & AC_TASK) { 215*7c478bd9Sstevel@tonic-gate if (header == 1) 216*7c478bd9Sstevel@tonic-gate (void) printf("task:\n"); 217*7c478bd9Sstevel@tonic-gate printgroup(AC_TASK); 218*7c478bd9Sstevel@tonic-gate } 219*7c478bd9Sstevel@tonic-gate if (type & AC_FLOW) { 220*7c478bd9Sstevel@tonic-gate if (header == 1) 221*7c478bd9Sstevel@tonic-gate (void) printf("flow:\n"); 222*7c478bd9Sstevel@tonic-gate printgroup(AC_FLOW); 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate } 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate /* 227*7c478bd9Sstevel@tonic-gate * this function sets the state of the particular resource 228*7c478bd9Sstevel@tonic-gate */ 229*7c478bd9Sstevel@tonic-gate static void 230*7c478bd9Sstevel@tonic-gate resset(ac_res_t *res, int id, int state) 231*7c478bd9Sstevel@tonic-gate { 232*7c478bd9Sstevel@tonic-gate ac_res_t *resp; 233*7c478bd9Sstevel@tonic-gate resp = (ac_res_t *)((uintptr_t)res + (sizeof (ac_res_t) * (id - 1))); 234*7c478bd9Sstevel@tonic-gate resp->ar_state = state; 235*7c478bd9Sstevel@tonic-gate resp->ar_id = id; 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate /* 239*7c478bd9Sstevel@tonic-gate * this function gets the state of the particular resource 240*7c478bd9Sstevel@tonic-gate */ 241*7c478bd9Sstevel@tonic-gate static int 242*7c478bd9Sstevel@tonic-gate resget(ac_res_t *res, int id) 243*7c478bd9Sstevel@tonic-gate { 244*7c478bd9Sstevel@tonic-gate ac_res_t *resp; 245*7c478bd9Sstevel@tonic-gate resp = (ac_res_t *)((uintptr_t)res + (sizeof (ac_res_t) * (id - 1))); 246*7c478bd9Sstevel@tonic-gate return (resp->ar_state); 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate /* 250*7c478bd9Sstevel@tonic-gate * this function converts a string of resources into a buffer which then 251*7c478bd9Sstevel@tonic-gate * can be used for acctctl() system call 252*7c478bd9Sstevel@tonic-gate */ 253*7c478bd9Sstevel@tonic-gate void 254*7c478bd9Sstevel@tonic-gate str2buf(ac_res_t *buf, char *str, int state, int type) 255*7c478bd9Sstevel@tonic-gate { 256*7c478bd9Sstevel@tonic-gate int i, j, id, ok; 257*7c478bd9Sstevel@tonic-gate char *p, *g, *copy; 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate if (strcmp(str, AC_STR_NONE) == 0) 260*7c478bd9Sstevel@tonic-gate return; 261*7c478bd9Sstevel@tonic-gate /* 262*7c478bd9Sstevel@tonic-gate * Take a lap through str, processing resources, modifying buf copy 263*7c478bd9Sstevel@tonic-gate * as appropriate and making sure that all resource names are valid. 264*7c478bd9Sstevel@tonic-gate */ 265*7c478bd9Sstevel@tonic-gate if ((copy = malloc(strlen(str) + 1)) == NULL) 266*7c478bd9Sstevel@tonic-gate die(gettext("not enough memory\n")); 267*7c478bd9Sstevel@tonic-gate (void) memcpy(copy, str, strlen(str) + 1); 268*7c478bd9Sstevel@tonic-gate p = strtok(copy, ", "); 269*7c478bd9Sstevel@tonic-gate while (p != NULL) { 270*7c478bd9Sstevel@tonic-gate /* 271*7c478bd9Sstevel@tonic-gate * check if str contains any resource groups 272*7c478bd9Sstevel@tonic-gate */ 273*7c478bd9Sstevel@tonic-gate for (ok = 0, i = 0; (g = ac_groups[i].ag_name) != NULL; i++) { 274*7c478bd9Sstevel@tonic-gate if (strcmp(p, g) == 0 && ac_groups[i].ag_type == type) { 275*7c478bd9Sstevel@tonic-gate for (j = 0; (id = ac_groups[i].ag_mem[j]) != 276*7c478bd9Sstevel@tonic-gate AC_NONE; j++) 277*7c478bd9Sstevel@tonic-gate resset(buf, id, state); 278*7c478bd9Sstevel@tonic-gate ok = 1; 279*7c478bd9Sstevel@tonic-gate break; 280*7c478bd9Sstevel@tonic-gate } 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate if (ok == 0) { 283*7c478bd9Sstevel@tonic-gate id = name2id(p, type); 284*7c478bd9Sstevel@tonic-gate if (id > 0) 285*7c478bd9Sstevel@tonic-gate resset(buf, id, state); 286*7c478bd9Sstevel@tonic-gate else if (id == 0) 287*7c478bd9Sstevel@tonic-gate die(gettext("unknown %s resource: %s\n"), 288*7c478bd9Sstevel@tonic-gate type == AC_PROC ? "process" : "task", p); 289*7c478bd9Sstevel@tonic-gate } 290*7c478bd9Sstevel@tonic-gate p = strtok(NULL, ", "); 291*7c478bd9Sstevel@tonic-gate } 292*7c478bd9Sstevel@tonic-gate free(copy); 293*7c478bd9Sstevel@tonic-gate } 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate /* 296*7c478bd9Sstevel@tonic-gate * this function converts a buffer into a string of resource names. 297*7c478bd9Sstevel@tonic-gate * state (on/off) for resources of interest is selected by the third argument. 298*7c478bd9Sstevel@tonic-gate * accounting type is selected by the fourth argument. 299*7c478bd9Sstevel@tonic-gate * it is caller's responsibility to free the allocated string buffer. 300*7c478bd9Sstevel@tonic-gate */ 301*7c478bd9Sstevel@tonic-gate char * 302*7c478bd9Sstevel@tonic-gate buf2str(ac_res_t *buffer, size_t bufsz, int state, int type) 303*7c478bd9Sstevel@tonic-gate { 304*7c478bd9Sstevel@tonic-gate int i, j, ok, id; 305*7c478bd9Sstevel@tonic-gate char *str, *g; 306*7c478bd9Sstevel@tonic-gate ac_res_t *buf, *cur; 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate if ((buf = malloc(bufsz)) == NULL || 309*7c478bd9Sstevel@tonic-gate (str = malloc(MAXRESLEN)) == NULL) 310*7c478bd9Sstevel@tonic-gate die(gettext("not enough memory\n")); 311*7c478bd9Sstevel@tonic-gate (void) memset(str, 0, MAXRESLEN); 312*7c478bd9Sstevel@tonic-gate (void) memcpy(buf, buffer, bufsz); 313*7c478bd9Sstevel@tonic-gate /* 314*7c478bd9Sstevel@tonic-gate * check if buf has any resource groups in it 315*7c478bd9Sstevel@tonic-gate */ 316*7c478bd9Sstevel@tonic-gate for (i = 0; (g = ac_groups[i].ag_name) != NULL; i++) { 317*7c478bd9Sstevel@tonic-gate if (ac_groups[i].ag_type != type) 318*7c478bd9Sstevel@tonic-gate continue; 319*7c478bd9Sstevel@tonic-gate for (j = 0; (id = ac_groups[i].ag_mem[j]) != AC_NONE; j++) { 320*7c478bd9Sstevel@tonic-gate ok = 1; 321*7c478bd9Sstevel@tonic-gate if (resget(buf, id) != state) { 322*7c478bd9Sstevel@tonic-gate ok = 0; 323*7c478bd9Sstevel@tonic-gate break; 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate } 326*7c478bd9Sstevel@tonic-gate if (ok) { /* buf contains this resource group */ 327*7c478bd9Sstevel@tonic-gate if (strlen(str) != 0) 328*7c478bd9Sstevel@tonic-gate (void) strcat(str, ","); 329*7c478bd9Sstevel@tonic-gate (void) strcat(str, g); 330*7c478bd9Sstevel@tonic-gate for (j = 0; (id = ac_groups[i].ag_mem[j]) != AC_NONE; 331*7c478bd9Sstevel@tonic-gate j++) 332*7c478bd9Sstevel@tonic-gate resset(buf, id, 333*7c478bd9Sstevel@tonic-gate state == AC_ON ? AC_OFF : AC_ON); 334*7c478bd9Sstevel@tonic-gate ok = 0; 335*7c478bd9Sstevel@tonic-gate } 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate /* 338*7c478bd9Sstevel@tonic-gate * browse through the rest of the buf for all remaining resources 339*7c478bd9Sstevel@tonic-gate * that are not a part of any groups 340*7c478bd9Sstevel@tonic-gate */ 341*7c478bd9Sstevel@tonic-gate for (cur = buf; cur->ar_id != AC_NONE; cur++) { 342*7c478bd9Sstevel@tonic-gate if (cur->ar_state == state) { 343*7c478bd9Sstevel@tonic-gate if (strlen(str) != 0) 344*7c478bd9Sstevel@tonic-gate (void) strcat(str, ","); 345*7c478bd9Sstevel@tonic-gate if (id2name(cur->ar_id, type) == NULL) 346*7c478bd9Sstevel@tonic-gate die(gettext("unknown %s resource id (%d)\n"), 347*7c478bd9Sstevel@tonic-gate type == AC_PROC ? "process" : "task", 348*7c478bd9Sstevel@tonic-gate cur->ar_id); 349*7c478bd9Sstevel@tonic-gate (void) strcat(str, id2name(cur->ar_id, type)); 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate if (strlen(str) == 0) 353*7c478bd9Sstevel@tonic-gate (void) strcpy(str, AC_STR_NONE); 354*7c478bd9Sstevel@tonic-gate free(buf); 355*7c478bd9Sstevel@tonic-gate return (str); 356*7c478bd9Sstevel@tonic-gate } 357