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 1999-2002 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/acctctl.h> 30*7c478bd9Sstevel@tonic-gate #include <stdio.h> 31*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 32*7c478bd9Sstevel@tonic-gate #include <unistd.h> 33*7c478bd9Sstevel@tonic-gate #include <string.h> 34*7c478bd9Sstevel@tonic-gate #include <errno.h> 35*7c478bd9Sstevel@tonic-gate #include <libintl.h> 36*7c478bd9Sstevel@tonic-gate #include <locale.h> 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate #include "utils.h" 39*7c478bd9Sstevel@tonic-gate #include "aconf.h" 40*7c478bd9Sstevel@tonic-gate #include "res.h" 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate static const char USAGE[] = "\ 43*7c478bd9Sstevel@tonic-gate Usage:\n\ 44*7c478bd9Sstevel@tonic-gate acctadm [ {process | task | flow} ]\n\ 45*7c478bd9Sstevel@tonic-gate acctadm -u\n\ 46*7c478bd9Sstevel@tonic-gate acctadm -r [ {process | task | flow} ]\n\ 47*7c478bd9Sstevel@tonic-gate acctadm -x|-E|-D {process | task | flow}\n\ 48*7c478bd9Sstevel@tonic-gate acctadm -f filename {process | task | flow}\n\ 49*7c478bd9Sstevel@tonic-gate acctadm -e resources -d resources {process | task | flow}\n"; 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate static const char OPTS[] = "ruxf:e:d:ED"; 52*7c478bd9Sstevel@tonic-gate static const char PATH_CONFIG[] = "/etc/acctadm.conf"; 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate static void 55*7c478bd9Sstevel@tonic-gate usage() 56*7c478bd9Sstevel@tonic-gate { 57*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(USAGE)); 58*7c478bd9Sstevel@tonic-gate exit(E_USAGE); 59*7c478bd9Sstevel@tonic-gate } 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate int 62*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 63*7c478bd9Sstevel@tonic-gate { 64*7c478bd9Sstevel@tonic-gate int c; /* options character */ 65*7c478bd9Sstevel@tonic-gate int type = 0; /* type of accounting */ 66*7c478bd9Sstevel@tonic-gate int modified = 0; /* have we modified the /etc/acctadm.conf? */ 67*7c478bd9Sstevel@tonic-gate acctconf_t ac; /* current configuration */ 68*7c478bd9Sstevel@tonic-gate char *typestr = NULL; /* type of accounting argument string */ 69*7c478bd9Sstevel@tonic-gate char *enabled = NULL; /* enabled resources string */ 70*7c478bd9Sstevel@tonic-gate char *disabled = NULL; /* disabled resources string */ 71*7c478bd9Sstevel@tonic-gate char *file = NULL; 72*7c478bd9Sstevel@tonic-gate int Eflg = 0; 73*7c478bd9Sstevel@tonic-gate int Dflg = 0; 74*7c478bd9Sstevel@tonic-gate int rflg = 0; 75*7c478bd9Sstevel@tonic-gate int uflg = 0; 76*7c478bd9Sstevel@tonic-gate int xflg = 0; 77*7c478bd9Sstevel@tonic-gate int optcnt = 0; 78*7c478bd9Sstevel@tonic-gate int state; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 81*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 82*7c478bd9Sstevel@tonic-gate (void) setprogname(argv[0]); 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate for (; optind < argc; optind++) { 85*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, OPTS)) != (int)EOF) { 86*7c478bd9Sstevel@tonic-gate switch (c) { 87*7c478bd9Sstevel@tonic-gate case 'd': 88*7c478bd9Sstevel@tonic-gate disabled = optarg; 89*7c478bd9Sstevel@tonic-gate break; 90*7c478bd9Sstevel@tonic-gate case 'e': 91*7c478bd9Sstevel@tonic-gate enabled = optarg; 92*7c478bd9Sstevel@tonic-gate break; 93*7c478bd9Sstevel@tonic-gate case 'D': 94*7c478bd9Sstevel@tonic-gate Dflg = 1; 95*7c478bd9Sstevel@tonic-gate optcnt++; 96*7c478bd9Sstevel@tonic-gate break; 97*7c478bd9Sstevel@tonic-gate case 'E': 98*7c478bd9Sstevel@tonic-gate Eflg = 1; 99*7c478bd9Sstevel@tonic-gate optcnt++; 100*7c478bd9Sstevel@tonic-gate break; 101*7c478bd9Sstevel@tonic-gate case 'f': 102*7c478bd9Sstevel@tonic-gate file = optarg; 103*7c478bd9Sstevel@tonic-gate optcnt++; 104*7c478bd9Sstevel@tonic-gate break; 105*7c478bd9Sstevel@tonic-gate case 'r': 106*7c478bd9Sstevel@tonic-gate rflg = 1; 107*7c478bd9Sstevel@tonic-gate optcnt++; 108*7c478bd9Sstevel@tonic-gate break; 109*7c478bd9Sstevel@tonic-gate case 'u': 110*7c478bd9Sstevel@tonic-gate uflg = 1; 111*7c478bd9Sstevel@tonic-gate optcnt++; 112*7c478bd9Sstevel@tonic-gate break; 113*7c478bd9Sstevel@tonic-gate case 'x': 114*7c478bd9Sstevel@tonic-gate xflg = 1; 115*7c478bd9Sstevel@tonic-gate optcnt++; 116*7c478bd9Sstevel@tonic-gate break; 117*7c478bd9Sstevel@tonic-gate case '?': 118*7c478bd9Sstevel@tonic-gate default: 119*7c478bd9Sstevel@tonic-gate usage(); 120*7c478bd9Sstevel@tonic-gate } 121*7c478bd9Sstevel@tonic-gate } 122*7c478bd9Sstevel@tonic-gate if (optind < argc) { 123*7c478bd9Sstevel@tonic-gate if (typestr != NULL) { 124*7c478bd9Sstevel@tonic-gate warn(gettext("illegal argument -- %s\n"), 125*7c478bd9Sstevel@tonic-gate argv[optind]); 126*7c478bd9Sstevel@tonic-gate usage(); 127*7c478bd9Sstevel@tonic-gate } else { 128*7c478bd9Sstevel@tonic-gate typestr = argv[optind]; 129*7c478bd9Sstevel@tonic-gate } 130*7c478bd9Sstevel@tonic-gate } 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate if (typestr != NULL) { 133*7c478bd9Sstevel@tonic-gate if (strcmp(typestr, "process") == 0 || 134*7c478bd9Sstevel@tonic-gate strcmp(typestr, "proc") == 0) 135*7c478bd9Sstevel@tonic-gate type |= AC_PROC; 136*7c478bd9Sstevel@tonic-gate else if (strcmp(typestr, "task") == 0) 137*7c478bd9Sstevel@tonic-gate type |= AC_TASK; 138*7c478bd9Sstevel@tonic-gate else if (strcmp(typestr, "flow") == 0) 139*7c478bd9Sstevel@tonic-gate type |= AC_FLOW; 140*7c478bd9Sstevel@tonic-gate else { 141*7c478bd9Sstevel@tonic-gate warn(gettext("unknown accounting type -- %s\n"), 142*7c478bd9Sstevel@tonic-gate typestr); 143*7c478bd9Sstevel@tonic-gate usage(); 144*7c478bd9Sstevel@tonic-gate } 145*7c478bd9Sstevel@tonic-gate } else 146*7c478bd9Sstevel@tonic-gate type = AC_PROC | AC_TASK | AC_FLOW; 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate /* 149*7c478bd9Sstevel@tonic-gate * check for invalid options 150*7c478bd9Sstevel@tonic-gate */ 151*7c478bd9Sstevel@tonic-gate if (optcnt > 1) 152*7c478bd9Sstevel@tonic-gate usage(); 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate if ((enabled || disabled) && (rflg || Dflg || uflg || xflg || Eflg)) 155*7c478bd9Sstevel@tonic-gate usage(); 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate if ((file || xflg || Dflg || Eflg || enabled || disabled) && 158*7c478bd9Sstevel@tonic-gate !typestr) { 159*7c478bd9Sstevel@tonic-gate warn(gettext("accounting type must be specified\n")); 160*7c478bd9Sstevel@tonic-gate usage(); 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate if ((file || enabled || disabled || xflg || uflg || Dflg || Eflg) && 164*7c478bd9Sstevel@tonic-gate geteuid() != 0) 165*7c478bd9Sstevel@tonic-gate die(gettext("must be root to change extended " 166*7c478bd9Sstevel@tonic-gate "accounting configuration\n")); 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate if (rflg) { 169*7c478bd9Sstevel@tonic-gate printgroups(type); 170*7c478bd9Sstevel@tonic-gate return (E_SUCCESS); 171*7c478bd9Sstevel@tonic-gate } 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate /* 174*7c478bd9Sstevel@tonic-gate * If no arguments has been passed then just print out the current 175*7c478bd9Sstevel@tonic-gate * state, save it in the configuration file and exit. 176*7c478bd9Sstevel@tonic-gate */ 177*7c478bd9Sstevel@tonic-gate if (!enabled && !disabled && !file && 178*7c478bd9Sstevel@tonic-gate !Eflg && !rflg && !Dflg && !uflg && !xflg) { 179*7c478bd9Sstevel@tonic-gate aconf_init(&ac); 180*7c478bd9Sstevel@tonic-gate aconf_print(&ac, stdout, type); 181*7c478bd9Sstevel@tonic-gate return (E_SUCCESS); 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate if (uflg) { 185*7c478bd9Sstevel@tonic-gate if (aconf_open(&ac, PATH_CONFIG) == -1) 186*7c478bd9Sstevel@tonic-gate return (E_ERROR); 187*7c478bd9Sstevel@tonic-gate if (aconf_setup(&ac) == -1) 188*7c478bd9Sstevel@tonic-gate exit(E_ERROR); 189*7c478bd9Sstevel@tonic-gate modified++; 190*7c478bd9Sstevel@tonic-gate } 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate if (xflg) { 193*7c478bd9Sstevel@tonic-gate /* 194*7c478bd9Sstevel@tonic-gate * Turn off the specified accounting and close its file 195*7c478bd9Sstevel@tonic-gate */ 196*7c478bd9Sstevel@tonic-gate state = AC_OFF; 197*7c478bd9Sstevel@tonic-gate if (acctctl(type | AC_STATE_SET, &state, sizeof (int)) == -1) 198*7c478bd9Sstevel@tonic-gate die(gettext("cannot disable accounting")); 199*7c478bd9Sstevel@tonic-gate if (aconf_str2enable(&ac, AC_STR_NO, type) == -1) 200*7c478bd9Sstevel@tonic-gate die(gettext("cannot modify configuration file\n")); 201*7c478bd9Sstevel@tonic-gate if (acctctl(type | AC_FILE_SET, NULL, 0) == -1) 202*7c478bd9Sstevel@tonic-gate die(gettext("cannot close accounting file")); 203*7c478bd9Sstevel@tonic-gate if (aconf_str2file(&ac, AC_STR_NONE, type) == -1) 204*7c478bd9Sstevel@tonic-gate die(gettext("cannot modify configuration file\n")); 205*7c478bd9Sstevel@tonic-gate modified++; 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate if (enabled || disabled) { 209*7c478bd9Sstevel@tonic-gate char *tracked, *untracked; 210*7c478bd9Sstevel@tonic-gate ac_res_t *buf; 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate /* 213*7c478bd9Sstevel@tonic-gate * Enable/disable resources 214*7c478bd9Sstevel@tonic-gate */ 215*7c478bd9Sstevel@tonic-gate if ((buf = malloc(AC_BUFSIZE)) == NULL) 216*7c478bd9Sstevel@tonic-gate die(gettext("not enough memory\n")); 217*7c478bd9Sstevel@tonic-gate (void) memset(buf, 0, AC_BUFSIZE); 218*7c478bd9Sstevel@tonic-gate if (acctctl(type | AC_RES_GET, buf, AC_BUFSIZE) == -1) { 219*7c478bd9Sstevel@tonic-gate free(buf); 220*7c478bd9Sstevel@tonic-gate die(gettext("cannot obtain list of resources\n")); 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate if (disabled) 223*7c478bd9Sstevel@tonic-gate str2buf(buf, disabled, AC_OFF, type); 224*7c478bd9Sstevel@tonic-gate if (enabled) 225*7c478bd9Sstevel@tonic-gate str2buf(buf, enabled, AC_ON, type); 226*7c478bd9Sstevel@tonic-gate if (acctctl(type | AC_RES_SET, buf, AC_BUFSIZE) == -1) { 227*7c478bd9Sstevel@tonic-gate free(buf); 228*7c478bd9Sstevel@tonic-gate die(gettext("cannot enable or disable resources\n")); 229*7c478bd9Sstevel@tonic-gate } 230*7c478bd9Sstevel@tonic-gate tracked = buf2str(buf, AC_BUFSIZE, AC_ON, type); 231*7c478bd9Sstevel@tonic-gate untracked = buf2str(buf, AC_BUFSIZE, AC_OFF, type); 232*7c478bd9Sstevel@tonic-gate if (aconf_str2tracked(&ac, tracked, type) == -1 || 233*7c478bd9Sstevel@tonic-gate aconf_str2untracked(&ac, untracked, type)) { 234*7c478bd9Sstevel@tonic-gate free(buf); 235*7c478bd9Sstevel@tonic-gate free(tracked); 236*7c478bd9Sstevel@tonic-gate free(untracked); 237*7c478bd9Sstevel@tonic-gate die(gettext("cannot modify configuration file\n")); 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate free(tracked); 240*7c478bd9Sstevel@tonic-gate free(untracked); 241*7c478bd9Sstevel@tonic-gate free(buf); 242*7c478bd9Sstevel@tonic-gate modified++; 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate if (file) { 246*7c478bd9Sstevel@tonic-gate /* 247*7c478bd9Sstevel@tonic-gate * Open new accounting file 248*7c478bd9Sstevel@tonic-gate */ 249*7c478bd9Sstevel@tonic-gate state = AC_ON; 250*7c478bd9Sstevel@tonic-gate if (aconf_str2file(&ac, file, type) == -1) 251*7c478bd9Sstevel@tonic-gate die(gettext("cannot modify configuration file")); 252*7c478bd9Sstevel@tonic-gate if (acctctl(type | AC_FILE_SET, file, strlen(file) + 1) == -1) 253*7c478bd9Sstevel@tonic-gate die(gettext("cannot open accounting file")); 254*7c478bd9Sstevel@tonic-gate if (aconf_str2enable(&ac, AC_STR_YES, type) == -1) 255*7c478bd9Sstevel@tonic-gate die(gettext("cannot modify configuration file")); 256*7c478bd9Sstevel@tonic-gate if (acctctl(type | AC_STATE_SET, &state, sizeof (int)) == -1) 257*7c478bd9Sstevel@tonic-gate die(gettext("cannot enable accounting")); 258*7c478bd9Sstevel@tonic-gate modified++; 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate if (Dflg) { 262*7c478bd9Sstevel@tonic-gate /* 263*7c478bd9Sstevel@tonic-gate * Disable accounting 264*7c478bd9Sstevel@tonic-gate */ 265*7c478bd9Sstevel@tonic-gate state = AC_OFF; 266*7c478bd9Sstevel@tonic-gate if (acctctl(type | AC_STATE_SET, &state, sizeof (int)) == -1) 267*7c478bd9Sstevel@tonic-gate die(gettext("cannot disable accounting")); 268*7c478bd9Sstevel@tonic-gate if (aconf_str2enable(&ac, AC_STR_NO, type) == -1) 269*7c478bd9Sstevel@tonic-gate die(gettext("cannot modify configuration file")); 270*7c478bd9Sstevel@tonic-gate modified++; 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate if (Eflg) { 274*7c478bd9Sstevel@tonic-gate /* 275*7c478bd9Sstevel@tonic-gate * Enable accounting 276*7c478bd9Sstevel@tonic-gate */ 277*7c478bd9Sstevel@tonic-gate state = AC_ON; 278*7c478bd9Sstevel@tonic-gate if (acctctl(type | AC_STATE_SET, &state, sizeof (int)) == -1) 279*7c478bd9Sstevel@tonic-gate die(gettext("cannot enable accounting")); 280*7c478bd9Sstevel@tonic-gate if (aconf_str2enable(&ac, AC_STR_YES, type) == -1) 281*7c478bd9Sstevel@tonic-gate die(gettext("cannot modify configuration file")); 282*7c478bd9Sstevel@tonic-gate modified++; 283*7c478bd9Sstevel@tonic-gate } 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate if (modified) { 286*7c478bd9Sstevel@tonic-gate /* 287*7c478bd9Sstevel@tonic-gate * If we're modifying the configuration, then write out 288*7c478bd9Sstevel@tonic-gate * the new configuration file 289*7c478bd9Sstevel@tonic-gate */ 290*7c478bd9Sstevel@tonic-gate if (aconf_create(&ac, PATH_CONFIG) == -1) 291*7c478bd9Sstevel@tonic-gate return (E_ERROR); 292*7c478bd9Sstevel@tonic-gate aconf_init(&ac); 293*7c478bd9Sstevel@tonic-gate if (aconf_write(&ac) == -1) 294*7c478bd9Sstevel@tonic-gate return (E_ERROR); 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate if (aconf_close(&ac) == -1) 298*7c478bd9Sstevel@tonic-gate die(gettext("failed to close configuration file")); 299*7c478bd9Sstevel@tonic-gate return (E_SUCCESS); 300*7c478bd9Sstevel@tonic-gate } 301