xref: /titanic_50/usr/src/cmd/acctadm/main.c (revision 711890bc9379ceea66272dc8d4981812224ea86e)
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