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