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