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