4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <sys/rctl_impl.h>
27 #include <sys/types.h>
46 #define CONFIGPATH "/etc/rctladm.conf"
47 #define CONFIGOWNER 0 /* uid 0 (root) */
48 #define CONFIGGROUP 1 /* gid 1 (other) */
49 #define CONFIGPERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) /* 0644 */
52 * Macros to produce a quoted string containing the value of a
53 * preprocessor macro. For example, if SIZE is defined to be 256,
54 * VAL2STR(SIZE) is "256". This is used to construct format
55 * strings for scanf-family functions below.
58 #define VAL2STR(x) QUOTE(x)
60 static const char USAGE
[] =
61 "Usage:\trctladm -l\n"
63 "\trctladm -e actions -d actions rctl_name\n";
65 static const char OPTS
[] = "d:e:lu";
66 static int dflg
, eflg
, lflg
, uflg
;
68 static uint_t op_failures
;
70 static void rctladm_enable(const char *, char *);
77 (void) fprintf(stderr
, gettext(USAGE
));
81 #define LOG_HIGHEST LOG_DEBUG
82 static const char *syslog_priorities
[] = {
83 "emerg", /* LOG_EMERG */
84 "alert", /* LOG_ALERT */
85 "crit", /* LOG_CRIT */
87 "warning", /* LOG_WARNING */
88 "notice", /* LOG_NOTICE */
89 "info", /* LOG_INFO */
90 "debug" /* LOG_DEBUG */
94 rctladm_syslog_prio(const char *priority
)
98 for (i
= 0; i
< LOG_HIGHEST
+ 1; i
++) {
99 if ((strcasecmp(priority
, syslog_priorities
[i
]) == 0))
103 die(gettext("unknown syslog priority \"%s\"\n"), priority
);
110 rctl_save_walk_cb(const char *rctl_name
, void *file
)
117 if ((gblk
= malloc(rctlblk_size())) == NULL
)
118 die(gettext("unable to allocate control block"));
121 if (rctlctl(rctl_name
, gblk
, RCTLCTL_GET
) == -1) {
122 warn(gettext("unable to obtain control block contents for %s"),
125 action
= rctlblk_get_global_action(gblk
);
126 gopq
= (rctl_opaque_t
*)gblk
;
128 (void) fprintf(fp
, "%s=", rctl_name
);
129 if (action
& RCTL_GLOBAL_SYSLOG
)
130 (void) fprintf(fp
, "syslog=%s\n",
131 syslog_priorities
[gopq
->rcq_global_syslog_level
]);
133 (void) fprintf(fp
, "none\n");
142 rctladm_save_config()
148 * Non-root users shouldn't update the configuration file.
153 if ((fd
= open(CONFIGPATH
, O_WRONLY
|O_CREAT
|O_TRUNC
, CONFIGPERM
)) == -1)
154 die(gettext("failed to open %s"), CONFIGPATH
);
156 if ((fp
= fdopen(fd
, "w")) == NULL
)
157 die(gettext("failed to open stream for %s"), CONFIGPATH
);
163 "# Parameters for resource controls configuration.\n"
164 "# Do NOT edit this file by hand -- use rctladm(1m) instead.\n"
168 (void) rctl_walk(rctl_save_walk_cb
, fp
);
172 (void) fchmod(fd
, CONFIGPERM
);
173 (void) fchown(fd
, CONFIGOWNER
, CONFIGGROUP
);
178 rctladm_setup_action(char *name
, char *action
, int line
)
180 if (action
[0] == '\0') {
181 warn(gettext("\"%s\", line %d, syntax error\n"), CONFIGPATH
,
185 rctladm_enable(name
, action
);
189 rctladm_read_config()
194 char name
[BUFSIZE
+1], actions
[BUFSIZE
+1];
200 * Non-root users shouldn't do this.
203 die(gettext("you must be root to use this option\n"));
205 if ((fd
= open(CONFIGPATH
, O_RDONLY
, CONFIGPERM
)) == -1)
206 die(gettext("failed to open %s"), CONFIGPATH
);
208 if ((fp
= fdopen(fd
, "r")) == NULL
)
209 die(gettext("failed to open stream for %s"), CONFIGPATH
);
211 if ((gblk
= malloc(rctlblk_size())) == NULL
)
212 die(gettext("unable to allocate control block"));
214 for (line
= 1; fgets(buf
, BUFSIZE
, fp
) != NULL
; line
++) {
216 * Skip comment lines and empty lines.
218 if (buf
[0] == '#' || buf
[0] == '\n')
222 * Look for "rctl_name=action;action;...;action, with
223 * optional whitespace on either side, terminated by a newline,
224 * and consuming the whole line.
227 " %" VAL2STR(BUFSIZE
) "[^=]=%" VAL2STR(BUFSIZE
) "s \n%n",
228 name
, actions
, &len
);
229 if (n
>= 1 && name
[0] != '\0' &&
230 (n
== 1 || len
== strlen(buf
))) {
232 warn(gettext("\"%s\", line %d, syntax error\n"),
236 if (rctlctl(name
, (rctlblk_t
*)gblk
,
237 RCTLCTL_GET
) == -1) {
238 warn(gettext("\"%s\", line %d, unknown resource"
239 " control: %s\n"), CONFIGPATH
, line
, name
);
242 if (actions
[0] == ';') {
243 warn(gettext("\"%s\", line %d, syntax error\n"),
247 action
= strtok(actions
, ";");
248 rctladm_setup_action(name
, action
, line
);
249 while (action
= strtok(NULL
, ";"))
250 rctladm_setup_action(name
, action
, line
);
255 die(gettext("failed to read rctl configuration from \"%s\""),
262 rctladm_modify_action(const char *rctl_name
, uint_t enable
, uint_t action
,
267 if ((gblk
= malloc(rctlblk_size())) == NULL
)
268 die(gettext("unable to allocate control block"));
270 if (rctlctl(rctl_name
, (rctlblk_t
*)gblk
, RCTLCTL_GET
) == -1)
271 die(gettext("unable to obtain resource control block"));
273 if ((gblk
->rcq_global_flagaction
& RCTL_GLOBAL_SYSLOG_NEVER
) &&
274 (action
== RCTL_GLOBAL_SYSLOG
)) {
275 warn(gettext("\"syslog\" action not valid for %s\n"),
283 gblk
->rcq_global_flagaction
|= (action
&
284 ~RCTL_GLOBAL_ACTION_MASK
);
285 gblk
->rcq_global_syslog_level
= log_level
;
287 gblk
->rcq_global_flagaction
&= ~(action
&
288 ~RCTL_GLOBAL_ACTION_MASK
);
289 gblk
->rcq_global_syslog_level
= LOG_NOTICE
;
292 if (rctlctl(rctl_name
, (rctlblk_t
*)gblk
, RCTLCTL_SET
) == -1) {
293 warn(gettext("unable to update control block contents"));
301 rctladm_get_log_level(char *action
)
306 * Our syslog priority defaults to LOG_NOTICE.
308 if (strcmp("syslog", action
) == 0)
311 if (strncmp("syslog=", action
, strlen("syslog=")) != 0)
312 die(gettext("unknown action \"%s\"\n"), action
);
314 log_lvl_str
= action
+ strlen("syslog=");
316 return (rctladm_syslog_prio(log_lvl_str
));
321 rctladm_enable(const char *rctl_name
, char *action
)
324 * Two valid values: "none" and "syslog[=level]".
326 if (strcmp("none", action
) == 0) {
327 rctladm_modify_action(rctl_name
, DISABLE
,
328 ~RCTL_GLOBAL_ACTION_MASK
, 0);
332 rctladm_modify_action(rctl_name
, ENABLE
, RCTL_GLOBAL_SYSLOG
,
333 rctladm_get_log_level(action
));
337 rctladm_disable(const char *rctl_name
, char *action
)
340 * Two valid values: "all" and "syslog".
342 if (strcmp("all", action
) == 0) {
343 rctladm_modify_action(rctl_name
, DISABLE
,
344 ~RCTL_GLOBAL_ACTION_MASK
, 0);
346 } else if (strcmp("syslog", action
) == 0) {
347 rctladm_modify_action(rctl_name
, DISABLE
, RCTL_GLOBAL_SYSLOG
,
352 die(gettext("unknown action \"%s\"\n"), action
);
356 rctlblk_display(FILE *f
, rctlblk_t
*gblk
)
358 uint_t action
= rctlblk_get_global_action(gblk
);
359 uint_t flags
= rctlblk_get_global_flags(gblk
);
360 rctl_opaque_t
*gopq
= (rctl_opaque_t
*)gblk
;
362 if (flags
& RCTL_GLOBAL_SYSLOG_NEVER
)
363 (void) fprintf(f
, "syslog=n/a ");
364 else if (action
& RCTL_GLOBAL_SYSLOG
)
365 (void) fprintf(f
, "syslog=%-7s",
366 syslog_priorities
[gopq
->rcq_global_syslog_level
]);
368 (void) fprintf(f
, "syslog=off ");
370 if (flags
& RCTL_GLOBAL_ACTION_MASK
)
371 (void) fprintf(f
, " [");
373 if (flags
& RCTL_GLOBAL_NOBASIC
)
374 (void) fprintf(f
, " no-basic");
375 if (flags
& RCTL_GLOBAL_LOWERABLE
)
376 (void) fprintf(f
, " lowerable");
377 if (flags
& RCTL_GLOBAL_DENY_ALWAYS
)
378 (void) fprintf(f
, " deny");
379 if (flags
& RCTL_GLOBAL_DENY_NEVER
)
380 (void) fprintf(f
, " no-deny");
381 if (flags
& RCTL_GLOBAL_CPU_TIME
)
382 (void) fprintf(f
, " cpu-time");
383 if (flags
& RCTL_GLOBAL_FILE_SIZE
)
384 (void) fprintf(f
, " file-size");
385 if (flags
& RCTL_GLOBAL_SIGNAL_NEVER
)
386 (void) fprintf(f
, " no-signal");
387 if (flags
& RCTL_GLOBAL_UNOBSERVABLE
)
388 (void) fprintf(f
, " no-obs");
389 if (flags
& RCTL_GLOBAL_INFINITE
)
390 (void) fprintf(f
, " inf");
391 if (flags
& RCTL_GLOBAL_SYSLOG_NEVER
)
392 (void) fprintf(f
, " no-syslog");
393 if (flags
& RCTL_GLOBAL_SECONDS
)
394 (void) fprintf(f
, " seconds");
395 if (flags
& RCTL_GLOBAL_BYTES
)
396 (void) fprintf(f
, " bytes");
397 if (flags
& RCTL_GLOBAL_COUNT
)
398 (void) fprintf(f
, " count");
399 if (flags
& RCTL_GLOBAL_ACTION_MASK
)
400 (void) fprintf(f
, " ]");
402 (void) fprintf(f
, "\n");
407 rctl_walk_cb(const char *rctl_name
, void *pvt
)
411 if ((gblk
= malloc(rctlblk_size())) == NULL
)
412 die(gettext("unable to allocate control block"));
414 if (rctlctl(rctl_name
, gblk
, RCTLCTL_GET
) == -1) {
416 warn(gettext("unknown resource control: %s\n"),
419 warn(gettext("unable to obtain %s properties"),
423 (void) printf("%-27s ", rctl_name
);
424 rctlblk_display(stdout
, gblk
);
433 rctladm_list_rctls(int optind
, int argc
, char *argv
[])
435 if (optind
>= argc
) {
436 (void) rctl_walk(rctl_walk_cb
, NULL
);
440 for (; optind
< argc
; optind
++)
441 (void) rctl_walk_cb(argv
[optind
], NULL
);
445 main(int argc
, char *argv
[])
447 int c
; /* options character */
451 (void) setlocale(LC_ALL
, "");
452 (void) textdomain(TEXT_DOMAIN
);
453 (void) setpname(argv
[0]);
455 while ((c
= getopt(argc
, argv
, OPTS
)) != EOF
) {
478 rctladm_read_config();
482 if (lflg
&& (dflg
|| eflg
)) {
483 warn(gettext("-l, -d, and -e flags are exclusive\n"));
488 warn(gettext("-d and -e flags are exclusive\n"));
492 if (dflg
> 1 || eflg
> 1) {
493 warn(gettext("only one -d or -e flag per line\n"));
497 if (lflg
|| !(dflg
|| eflg
)) {
498 rctladm_list_rctls(optind
, argc
, argv
);
499 rctladm_save_config();
501 return (op_failures
? E_ERROR
: E_SUCCESS
);
504 if (optind
>= argc
) {
505 warn(gettext("must specify one or more "
506 "resource control names\n"));
510 for (; optind
< argc
; optind
++) {
514 rctladm_enable(rctl
, action
);
515 rctladm_save_config();
517 rctladm_disable(rctl
, action
);
518 rctladm_save_config();
524 return (op_failures
? E_ERROR
: E_SUCCESS
);