coreadm.c (7c478bd9) coreadm.c (dfac3eb2)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
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.
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance 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/*
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21/*
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
23 * Use is subject to license terms.
24 */
25
27#pragma ident "%Z%%M% %I% %E% SMI"
28
29#include <stdio.h>
30#include <fcntl.h>
31#include <ctype.h>
32#include <string.h>
33#include <stdlib.h>
34#include <unistd.h>
35#include <errno.h>
36#include <limits.h>
37#include <libintl.h>
38#include <locale.h>
39#include <sys/stat.h>
40#include <sys/corectl.h>
41#include <libproc.h>
26#include <stdio.h>
27#include <fcntl.h>
28#include <ctype.h>
29#include <string.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <errno.h>
33#include <limits.h>
34#include <libintl.h>
35#include <locale.h>
36#include <sys/stat.h>
37#include <sys/corectl.h>
38#include <libproc.h>
39#include <libscf.h>
40#include <libscf_priv.h>
41#include <assert.h>
42
43#define E_SUCCESS 0 /* Exit status for success */
44#define E_ERROR 1 /* Exit status for error */
45#define E_USAGE 2 /* Exit status for usage error */
46
47static const char PATH_CONFIG[] = "/etc/coreadm.conf";
42
43#define E_SUCCESS 0 /* Exit status for success */
44#define E_ERROR 1 /* Exit status for error */
45#define E_USAGE 2 /* Exit status for usage error */
46
47static const char PATH_CONFIG[] = "/etc/coreadm.conf";
48#define CF_OWNER 0 /* Uid 0 (root) */
49#define CF_GROUP 1 /* Gid 1 (other) */
50#define CF_PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) /* Mode 0644 */
48static const char PATH_CONFIG_OLD[] = "/etc/coreadm.conf.old";
51
49
50#define COREADM_INST_NAME "system/coreadm:default"
51#define COREADM_INST_FMRI \
52 SCF_FMRI_SVC_PREFIX SCF_FMRI_SERVICE_PREFIX COREADM_INST_NAME
53
54#define CONFIG_PARAMS "config_params"
55#define GLOBAL_ENABLED "global_enabled"
56#define PROCESS_ENABLED "process_enabled"
57#define GLOBAL_SETID_ENABLED "global_setid_enabled"
58#define PROCESS_SETID_ENABLED "process_setid_enabled"
59#define GLOBAL_LOG_ENABLED "global_log_enabled"
60#define GLOBAL_PATTERN "global_pattern"
61#define GLOBAL_CONTENT "global_content"
62#define INIT_PATTERN "init_pattern"
63#define INIT_CONTENT "init_content"
64
52static char *command;
65static char *command;
66static uint64_t options;
67static int alloptions;
53static char *glob_pattern;
68static char *glob_pattern;
54static size_t glob_size;
69static char gpattern[PATH_MAX];
55static core_content_t glob_content = CC_CONTENT_INVALID;
56static char *init_pattern;
70static core_content_t glob_content = CC_CONTENT_INVALID;
71static char *init_pattern;
57static size_t init_size;
72static char ipattern[PATH_MAX];
58static core_content_t init_content = CC_CONTENT_INVALID;
59static char *proc_pattern;
60static size_t proc_size;
61static core_content_t proc_content = CC_CONTENT_INVALID;
73static core_content_t init_content = CC_CONTENT_INVALID;
74static char *proc_pattern;
75static size_t proc_size;
76static core_content_t proc_content = CC_CONTENT_INVALID;
62static int enable;
63static int disable;
64
65static int report_settings(void);
66static int do_processes(int, char **);
77
78static int report_settings(void);
79static int do_processes(int, char **);
67static int do_modify(void);
80static int do_modify(boolean_t);
68static int do_update(void);
81static int do_update(void);
69static int write_config(int);
82static int do_legacy(void);
70
83
84static scf_propvec_t prop_gpattern = { GLOBAL_PATTERN, NULL, SCF_TYPE_ASTRING };
85static scf_propvec_t prop_gcontent = { GLOBAL_CONTENT, NULL, SCF_TYPE_ASTRING };
86static scf_propvec_t prop_ipattern = { INIT_PATTERN, NULL, SCF_TYPE_ASTRING };
87static scf_propvec_t prop_icontent = { INIT_CONTENT, NULL, SCF_TYPE_ASTRING };
88static scf_propvec_t prop_option[] = {
89 { GLOBAL_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL, CC_GLOBAL_PATH },
90 { PROCESS_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL, CC_PROCESS_PATH },
91 { GLOBAL_SETID_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL, CC_GLOBAL_SETID },
92 { PROCESS_SETID_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL, CC_PROCESS_SETID },
93 { GLOBAL_LOG_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL, CC_GLOBAL_LOG },
94 { NULL }
95};
96#define MAX_PROPS (4 + (sizeof (prop_option) / sizeof (scf_propvec_t)))
97
71static void
72usage(void)
73{
74 (void) fprintf(stderr, gettext(
75"usage:\n"));
76 (void) fprintf(stderr, gettext(
77" %s [ -g pattern ] [ -i pattern ] [ -G content ] [ -I content ]\n"),
98static void
99usage(void)
100{
101 (void) fprintf(stderr, gettext(
102"usage:\n"));
103 (void) fprintf(stderr, gettext(
104" %s [ -g pattern ] [ -i pattern ] [ -G content ] [ -I content ]\n"),
78 command);
105 command);
79 (void) fprintf(stderr, gettext(
80" [ -e {global | process | global-setid | proc-setid | log} ]\n"));
81 (void) fprintf(stderr, gettext(
82" [ -d {global | process | global-setid | proc-setid | log} ]\n"));
83 (void) fprintf(stderr, gettext(
84" %s [ -p pattern ] [ -P content ] [ pid ... ]\n"), command);
106 (void) fprintf(stderr, gettext(
107" [ -e {global | process | global-setid | proc-setid | log} ]\n"));
108 (void) fprintf(stderr, gettext(
109" [ -d {global | process | global-setid | proc-setid | log} ]\n"));
110 (void) fprintf(stderr, gettext(
111" %s [ -p pattern ] [ -P content ] [ pid ... ]\n"), command);
85 (void) fprintf(stderr, gettext(
86" %s -u\n"), command);
87 exit(E_USAGE);
88}
89
90static int
91perm(void)
92{
93 (void) fprintf(stderr, gettext("%s: insufficient privileges to "
112 exit(E_USAGE);
113}
114
115static int
116perm(void)
117{
118 (void) fprintf(stderr, gettext("%s: insufficient privileges to "
94 "exercise the -[GIgiedu] options\n"), command);
119 "exercise the -[GIgied] options\n"), command);
95 return (E_USAGE);
96}
97
120 return (E_USAGE);
121}
122
123static int
124parse_content(char *arg, core_content_t *content)
125{
126 if (proc_str2content(arg, content) == 0)
127 return (0);
128 (void) fprintf(stderr, gettext("%s: invalid content string '%s'\n"),
129 command, arg);
130 return (1);
131}
132
98int
99main(int argc, char **argv)
100{
101 int flag;
102 int opt;
103 int modify;
104 int update = 0;
133int
134main(int argc, char **argv)
135{
136 int flag;
137 int opt;
138 int modify;
139 int update = 0;
140 int legacy_update = 0;
105 int error = 0;
106 int npids;
107 char **pidlist;
108
109 char curpid[11];
110 char *curpid_ptr = &curpid[0];
111
112 (void) setlocale(LC_ALL, "");
113 (void) textdomain(TEXT_DOMAIN);
114
115 /* command name (e.g., "coreadm") */
116 if ((command = strrchr(argv[0], '/')) != NULL)
117 command++;
118 else
119 command = argv[0];
120
141 int error = 0;
142 int npids;
143 char **pidlist;
144
145 char curpid[11];
146 char *curpid_ptr = &curpid[0];
147
148 (void) setlocale(LC_ALL, "");
149 (void) textdomain(TEXT_DOMAIN);
150
151 /* command name (e.g., "coreadm") */
152 if ((command = strrchr(argv[0], '/')) != NULL)
153 command++;
154 else
155 command = argv[0];
156
121 while ((opt = getopt(argc, argv, "g:G:i:I:p:P:e:d:u?")) != EOF) {
157 while ((opt = getopt(argc, argv, "g:G:i:I:p:P:e:d:uU?")) != EOF) {
122 switch (opt) {
123 case 'g':
124 glob_pattern = optarg;
158 switch (opt) {
159 case 'g':
160 glob_pattern = optarg;
125 glob_size = strlen(glob_pattern) + 1;
126 break;
127 case 'i':
128 init_pattern = optarg;
161 break;
162 case 'i':
163 init_pattern = optarg;
129 init_size = strlen(init_pattern) + 1;
130 break;
131 case 'p':
132 proc_pattern = optarg;
133 proc_size = strlen(proc_pattern) + 1;
134 break;
135 case 'G':
164 break;
165 case 'p':
166 proc_pattern = optarg;
167 proc_size = strlen(proc_pattern) + 1;
168 break;
169 case 'G':
136 if (proc_str2content(optarg, &glob_content) != 0) {
137 (void) fprintf(stderr, gettext("invalid "
138 "content string '%s'\n"), optarg);
139 error = 1;
140 }
170 error |= parse_content(optarg, &glob_content);
141 break;
142 case 'I':
171 break;
172 case 'I':
143 if (proc_str2content(optarg, &init_content) != 0) {
144 (void) fprintf(stderr, gettext("invalid "
145 "content string '%s'\n"), optarg);
146 error = 1;
147 }
173 error |= parse_content(optarg, &init_content);
148 break;
149 case 'P':
174 break;
175 case 'P':
150 if (proc_str2content(optarg, &proc_content) != 0) {
151 (void) fprintf(stderr, gettext("invalid "
152 "content string '%s'\n"), optarg);
153 error = 1;
154 }
176 error |= parse_content(optarg, &proc_content);
155 break;
156 case 'e':
157 case 'd':
158 if (strcmp(optarg, "global") == 0)
159 flag = CC_GLOBAL_PATH;
160 else if (strcmp(optarg, "process") == 0)
161 flag = CC_PROCESS_PATH;
162 else if (strcmp(optarg, "global-setid") == 0)
163 flag = CC_GLOBAL_SETID;
164 else if (strcmp(optarg, "proc-setid") == 0)
165 flag = CC_PROCESS_SETID;
166 else if (strcmp(optarg, "log") == 0)
167 flag = CC_GLOBAL_LOG;
168 else {
169 flag = 0;
170 error = 1;
171 }
177 break;
178 case 'e':
179 case 'd':
180 if (strcmp(optarg, "global") == 0)
181 flag = CC_GLOBAL_PATH;
182 else if (strcmp(optarg, "process") == 0)
183 flag = CC_PROCESS_PATH;
184 else if (strcmp(optarg, "global-setid") == 0)
185 flag = CC_GLOBAL_SETID;
186 else if (strcmp(optarg, "proc-setid") == 0)
187 flag = CC_PROCESS_SETID;
188 else if (strcmp(optarg, "log") == 0)
189 flag = CC_GLOBAL_LOG;
190 else {
191 flag = 0;
192 error = 1;
193 }
172 if (opt == 'e') {
173 enable |= flag;
174 disable &= ~flag;
175 } else {
176 disable |= flag;
177 enable &= ~flag;
178 }
194 if (opt == 'e')
195 options |= flag;
196 else
197 options &= ~flag;
198 alloptions |= flag;
179 break;
199 break;
180 case 'u':
200 case 'U':
181 update = 1;
182 break;
201 update = 1;
202 break;
203 case 'u':
204 legacy_update = 1;
205 break;
183 case '?':
184 default:
185 error = 1;
186 break;
187 }
188 }
189
190 npids = argc - optind;
191 pidlist = argv + optind;
192
193 if (error)
194 usage();
195
196 /*
197 * If 'modify' is true, we must modify the system settings
198 * and update the configuration file with the new parameters.
199 */
200 modify = glob_pattern != NULL || glob_content != CC_CONTENT_INVALID ||
206 case '?':
207 default:
208 error = 1;
209 break;
210 }
211 }
212
213 npids = argc - optind;
214 pidlist = argv + optind;
215
216 if (error)
217 usage();
218
219 /*
220 * If 'modify' is true, we must modify the system settings
221 * and update the configuration file with the new parameters.
222 */
223 modify = glob_pattern != NULL || glob_content != CC_CONTENT_INVALID ||
201 init_pattern != NULL || init_content != CC_CONTENT_INVALID ||
202 (enable | disable) != 0;
224 init_pattern != NULL || init_content != CC_CONTENT_INVALID ||
225 alloptions != 0;
203
226
204 if (update && (modify || proc_pattern != NULL ||
227 if ((update || legacy_update) && (modify || proc_pattern != NULL ||
205 proc_content != CC_CONTENT_INVALID || npids != 0)) {
206 (void) fprintf(stderr,
228 proc_content != CC_CONTENT_INVALID || npids != 0)) {
229 (void) fprintf(stderr,
207 gettext(
208 "%s: the -u option must stand alone\n"),
209 command);
230 gettext("%s: the -u option must stand alone\n"), command);
210 usage();
211 }
212 if (modify &&
213 (proc_pattern != NULL || proc_content != CC_CONTENT_INVALID)) {
231 usage();
232 }
233 if (modify &&
234 (proc_pattern != NULL || proc_content != CC_CONTENT_INVALID)) {
214 (void) fprintf(stderr,
215 gettext(
235 (void) fprintf(stderr, gettext(
216 "%s: -[GIgied] and -[Pp] options are mutually exclusive\n"),
217 command);
218 usage();
219 }
220 if (modify && npids != 0) {
236 "%s: -[GIgied] and -[Pp] options are mutually exclusive\n"),
237 command);
238 usage();
239 }
240 if (modify && npids != 0) {
221 (void) fprintf(stderr,
222 gettext(
241 (void) fprintf(stderr, gettext(
223 "%s: -[GIgied] options cannot have a process-id list\n"),
224 command);
225 usage();
226 }
227 if ((proc_pattern != NULL || proc_content != CC_CONTENT_INVALID) &&
228 npids == 0) {
229 (void) sprintf(curpid, "%u", (uint_t)getppid());
230 npids = 1;
231 pidlist = &curpid_ptr;
232 }
233
242 "%s: -[GIgied] options cannot have a process-id list\n"),
243 command);
244 usage();
245 }
246 if ((proc_pattern != NULL || proc_content != CC_CONTENT_INVALID) &&
247 npids == 0) {
248 (void) sprintf(curpid, "%u", (uint_t)getppid());
249 npids = 1;
250 pidlist = &curpid_ptr;
251 }
252
253 if (legacy_update)
254 return (do_legacy());
234 if (update)
235 return (do_update());
236 if (modify)
255 if (update)
256 return (do_update());
257 if (modify)
237 return (do_modify());
258 return (do_modify(B_FALSE));
238 if (npids != 0)
239 return (do_processes(npids, pidlist));
240
241 return (report_settings());
242}
243
244static int
245report_settings(void)
246{
259 if (npids != 0)
260 return (do_processes(npids, pidlist));
261
262 return (report_settings());
263}
264
265static int
266report_settings(void)
267{
247 int options;
248 char global_path[PATH_MAX];
249 char init_path[PATH_MAX];
250 core_content_t gcontent, icontent;
251 char content_str[80];
268 char content_str[PRCONTENTBUFSZ];
252
253 if ((options = core_get_options()) == -1) {
254 perror("core_get_options()");
255 return (E_ERROR);
256 }
269
270 if ((options = core_get_options()) == -1) {
271 perror("core_get_options()");
272 return (E_ERROR);
273 }
257 if (core_get_global_path(global_path, sizeof (global_path)) != 0) {
274 if (core_get_global_path(gpattern, sizeof (gpattern)) != 0) {
258 perror("core_get_global_path()");
259 return (E_ERROR);
260 }
275 perror("core_get_global_path()");
276 return (E_ERROR);
277 }
261 if (core_get_default_path(init_path, sizeof (init_path)) != 0) {
278 if (core_get_default_path(ipattern, sizeof (ipattern)) != 0) {
262 perror("core_get_default_path()");
263 return (E_ERROR);
264 }
279 perror("core_get_default_path()");
280 return (E_ERROR);
281 }
265 if (core_get_global_content(&gcontent) != 0) {
282 if (core_get_global_content(&glob_content) != 0) {
266 perror("core_get_global_content()");
267 return (E_ERROR);
268 }
283 perror("core_get_global_content()");
284 return (E_ERROR);
285 }
269 if (core_get_default_content(&icontent) != 0) {
286 if (core_get_default_content(&init_content) != 0) {
270 perror("core_get_default_content()");
271 return (E_ERROR);
272 }
287 perror("core_get_default_content()");
288 return (E_ERROR);
289 }
290
273 (void) printf(gettext(" global core file pattern: %s\n"),
291 (void) printf(gettext(" global core file pattern: %s\n"),
274 global_path);
275 (void) proc_content2str(gcontent, content_str, sizeof (content_str));
292 gpattern);
293 (void) proc_content2str(glob_content, content_str,
294 sizeof (content_str));
276 (void) printf(gettext(" global core file content: %s\n"),
277 content_str);
278 (void) printf(gettext(" init core file pattern: %s\n"),
295 (void) printf(gettext(" global core file content: %s\n"),
296 content_str);
297 (void) printf(gettext(" init core file pattern: %s\n"),
279 init_path);
280 (void) proc_content2str(icontent, content_str, sizeof (content_str));
298 ipattern);
299 (void) proc_content2str(init_content, content_str,
300 sizeof (content_str));
281 (void) printf(gettext(" init core file content: %s\n"),
282 content_str);
283 (void) printf(gettext(" global core dumps: %s\n"),
284 (options & CC_GLOBAL_PATH)? "enabled" : "disabled");
285 (void) printf(gettext(" per-process core dumps: %s\n"),
286 (options & CC_PROCESS_PATH)? "enabled" : "disabled");
287 (void) printf(gettext(" global setid core dumps: %s\n"),
288 (options & CC_GLOBAL_SETID)? "enabled" : "disabled");

--- 7 unchanged lines hidden (view full) ---

296static int
297do_processes(int npids, char **pidlist)
298{
299 char process_path[PATH_MAX];
300 core_content_t content;
301 pid_t pid;
302 char *next;
303 int rc = E_SUCCESS;
301 (void) printf(gettext(" init core file content: %s\n"),
302 content_str);
303 (void) printf(gettext(" global core dumps: %s\n"),
304 (options & CC_GLOBAL_PATH)? "enabled" : "disabled");
305 (void) printf(gettext(" per-process core dumps: %s\n"),
306 (options & CC_PROCESS_PATH)? "enabled" : "disabled");
307 (void) printf(gettext(" global setid core dumps: %s\n"),
308 (options & CC_GLOBAL_SETID)? "enabled" : "disabled");

--- 7 unchanged lines hidden (view full) ---

316static int
317do_processes(int npids, char **pidlist)
318{
319 char process_path[PATH_MAX];
320 core_content_t content;
321 pid_t pid;
322 char *next;
323 int rc = E_SUCCESS;
304 char content_str[80];
324 char content_str[PRCONTENTBUFSZ];
305
306 if (proc_pattern == NULL && proc_content == CC_CONTENT_INVALID) {
307 while (npids-- > 0) {
308 pid = strtol(*pidlist, &next, 10);
309 if (*next != '\0' || !isdigit(**pidlist)) {
310 (void) fprintf(stderr,
311 gettext("%s: invalid process-id\n"),
312 *pidlist);

--- 36 unchanged lines hidden (view full) ---

349 }
350 pidlist++;
351 }
352 }
353
354 return (rc);
355}
356
325
326 if (proc_pattern == NULL && proc_content == CC_CONTENT_INVALID) {
327 while (npids-- > 0) {
328 pid = strtol(*pidlist, &next, 10);
329 if (*next != '\0' || !isdigit(**pidlist)) {
330 (void) fprintf(stderr,
331 gettext("%s: invalid process-id\n"),
332 *pidlist);

--- 36 unchanged lines hidden (view full) ---

369 }
370 pidlist++;
371 }
372 }
373
374 return (rc);
375}
376
377static void
378addprop(scf_propvec_t *props, int size, int count, scf_propvec_t *pv, void *ptr)
379{
380 assert(count + 1 < size);
381 props[count] = *pv;
382 props[count].pv_ptr = ptr;
383}
384
385static boolean_t
386is_online(const char *fmri)
387{
388 char *state = smf_get_state(fmri);
389 boolean_t result = state != NULL &&
390 strcmp(state, SCF_STATE_STRING_ONLINE) == 0;
391
392 free(state);
393 return (result);
394}
395
396/*
397 * The user has specified the -g, -G, -i, -I, -d, or -e options to
398 * modify the given configuration parameter. Perform the modification
399 * in the smf repository and then perform a smf_refresh_instance which
400 * will cause a coreadm -u to occur which will transfer ALL coreadm
401 * configuration information from the repository to the kernel.
402 */
357static int
403static int
358do_modify(void)
404do_modify(boolean_t method)
359{
405{
360 int options;
406 char gcontentstr[PRCONTENTBUFSZ];
407 char icontentstr[PRCONTENTBUFSZ];
408 scf_propvec_t *prop;
409 scf_propvec_t properties[MAX_PROPS + 1];
410 int count = 0;
361
411
362 if ((options = core_get_options()) == -1) {
363 perror("core_get_options()");
412 if (!method && !is_online(COREADM_INST_FMRI)) {
413 (void) fprintf(stderr,
414 gettext("%s: coreadm service not online\n"), command);
364 return (E_ERROR);
365 }
415 return (E_ERROR);
416 }
366 options |= enable;
367 options &= ~disable;
368 if (core_set_options(options) != 0) {
369 if (errno == EPERM)
370 return (perm());
371 perror("core_set_options()");
372 return (E_ERROR);
417
418 if (glob_pattern != NULL)
419 addprop(properties, MAX_PROPS, count++, &prop_gpattern,
420 glob_pattern);
421
422 if (glob_content != CC_CONTENT_INVALID) {
423 (void) proc_content2str(glob_content, gcontentstr,
424 sizeof (gcontentstr));
425 addprop(properties, MAX_PROPS, count++, &prop_gcontent,
426 gcontentstr);
373 }
427 }
374 if (glob_pattern != NULL &&
375 core_set_global_path(glob_pattern, glob_size) != 0) {
376 if (errno == EPERM)
377 return (perm());
378 perror("core_set_global_path()");
379 return (E_ERROR);
428
429 if (init_pattern != NULL)
430 addprop(properties, MAX_PROPS, count++, &prop_ipattern,
431 init_pattern);
432
433 if (init_content != CC_CONTENT_INVALID) {
434 (void) proc_content2str(init_content, icontentstr,
435 sizeof (icontentstr));
436 addprop(properties, MAX_PROPS, count++, &prop_icontent,
437 icontentstr);
380 }
438 }
381 if (glob_content != CC_CONTENT_INVALID &&
382 core_set_global_content(&glob_content) != 0) {
383 if (errno == EPERM)
384 return (perm());
385 perror("core_set_global_content()");
439
440 for (prop = prop_option; prop->pv_prop != NULL; prop++)
441 if ((alloptions & prop->pv_aux) != 0)
442 addprop(properties, MAX_PROPS, count++, prop, &options);
443
444 properties[count].pv_prop = NULL;
445
446 prop = NULL;
447 if (scf_write_propvec(COREADM_INST_FMRI, CONFIG_PARAMS, properties,
448 &prop) == SCF_FAILED) {
449 if (prop != NULL) {
450 (void) fprintf(stderr, gettext(
451 "%s: Unable to write property '%s': %s"), command,
452 prop->pv_prop, scf_strerror(scf_error()));
453 } else {
454 (void) fprintf(stderr, gettext(
455 "%s: Unable to write configuration: %s\n"),
456 command, scf_strerror(scf_error()));
457 }
386 return (E_ERROR);
387 }
458 return (E_ERROR);
459 }
388 if (init_pattern != NULL &&
389 core_set_default_path(init_pattern, init_size) != 0) {
390 if (errno == EPERM)
391 return (perm());
392 perror("core_set_default_path()");
460
461 if (smf_refresh_instance(COREADM_INST_FMRI) != 0) {
462 (void) fprintf(stderr,
463 gettext("%s: Unable to refresh %s: %s\n"
464 "Configuration stored but not made active.\n"),
465 command, COREADM_INST_FMRI, scf_strerror(scf_error()));
393 return (E_ERROR);
394 }
466 return (E_ERROR);
467 }
395 if (init_content != CC_CONTENT_INVALID &&
396 core_set_default_content(&init_content) != 0) {
397 if (errno == EPERM)
398 return (perm());
399 perror("core_set_default_content()");
400 return (E_ERROR);
401 }
402 return (write_config(0));
468
469 return (E_SUCCESS);
403}
404
470}
471
472static const char *
473write_kernel(void)
474{
475 if (core_set_global_path(glob_pattern, strlen(glob_pattern) + 1) != 0)
476 return ("core_set_global_path()");
477
478 if (core_set_global_content(&glob_content) != 0)
479 return ("core_set_global_content()");
480
481 if (core_set_default_path(init_pattern, strlen(init_pattern) + 1) != 0)
482 return ("core_set_default_path()");
483
484 if (core_set_default_content(&init_content) != 0)
485 return ("core_set_init_content()");
486
487 if (core_set_options((int)options) != 0)
488 return ("core_set_options()");
489
490 return (NULL);
491}
492
405/*
406 * BUFSIZE must be large enough to contain the longest path plus some more.
407 */
408#define BUFSIZE (PATH_MAX + 80)
409
410static int
411yes(char *name, char *value, int line)
412{
413 if (strcmp(value, "yes") == 0)
414 return (1);
415 if (strcmp(value, "no") == 0)
416 return (0);
493/*
494 * BUFSIZE must be large enough to contain the longest path plus some more.
495 */
496#define BUFSIZE (PATH_MAX + 80)
497
498static int
499yes(char *name, char *value, int line)
500{
501 if (strcmp(value, "yes") == 0)
502 return (1);
503 if (strcmp(value, "no") == 0)
504 return (0);
417 (void) fprintf(stderr,
418 gettext(
419 "\"%s\", line %d: warning: value must be yes or no: %s=%s\n"),
420 PATH_CONFIG, line, name, value);
505 (void) fprintf(stderr, gettext(
506 "\"%s\", line %d: warning: value must be yes or no: %s=%s\n"),
507 PATH_CONFIG, line, name, value);
421 return (0);
422}
423
424static int
508 return (0);
509}
510
511static int
425do_update(void)
512read_legacy(void)
426{
427 FILE *fp;
428 int line;
513{
514 FILE *fp;
515 int line;
429 int options;
430 char gpattern[PATH_MAX];
431 char ipattern[PATH_MAX];
432 core_content_t gcontent, icontent;
433 char buf[BUFSIZE];
434 char name[BUFSIZE], value[BUFSIZE];
516 char buf[BUFSIZE];
517 char name[BUFSIZE], value[BUFSIZE];
435 int n;
436 int len;
518 int n, len;
437
438 /* defaults */
519
520 /* defaults */
521 alloptions = CC_OPTIONS;
439 options = CC_PROCESS_PATH;
440 gpattern[0] = '\0';
441 (void) strcpy(ipattern, "core");
522 options = CC_PROCESS_PATH;
523 gpattern[0] = '\0';
524 (void) strcpy(ipattern, "core");
442 gcontent = icontent = CC_CONTENT_DEFAULT;
525 glob_content = init_content = CC_CONTENT_DEFAULT;
443
526
444 if ((fp = fopen(PATH_CONFIG, "r")) == NULL) {
445 /*
446 * No config file, just accept the current settings.
447 */
448 return (write_config(1));
449 }
527 glob_pattern = gpattern;
528 init_pattern = ipattern;
450
529
530 if ((fp = fopen(PATH_CONFIG, "r")) == NULL)
531 return (0);
532
451 for (line = 1; fgets(buf, sizeof (buf), fp) != NULL; line++) {
452 /*
453 * Skip comment lines and empty lines.
454 */
455 if (buf[0] == '#' || buf[0] == '\n')
456 continue;
457 /*
458 * Look for "name=value", with optional whitespace on either

--- 5 unchanged lines hidden (view full) ---

464 (n == 1 || len == strlen(buf))) {
465 if (n == 1)
466 value[0] = '\0';
467 if (strcmp(name, "COREADM_GLOB_PATTERN") == 0) {
468 (void) strcpy(gpattern, value);
469 continue;
470 }
471 if (strcmp(name, "COREADM_GLOB_CONTENT") == 0) {
533 for (line = 1; fgets(buf, sizeof (buf), fp) != NULL; line++) {
534 /*
535 * Skip comment lines and empty lines.
536 */
537 if (buf[0] == '#' || buf[0] == '\n')
538 continue;
539 /*
540 * Look for "name=value", with optional whitespace on either

--- 5 unchanged lines hidden (view full) ---

546 (n == 1 || len == strlen(buf))) {
547 if (n == 1)
548 value[0] = '\0';
549 if (strcmp(name, "COREADM_GLOB_PATTERN") == 0) {
550 (void) strcpy(gpattern, value);
551 continue;
552 }
553 if (strcmp(name, "COREADM_GLOB_CONTENT") == 0) {
472 (void) proc_str2content(value, &gcontent);
554 (void) proc_str2content(value, &glob_content);
473 continue;
474 }
475 if (strcmp(name, "COREADM_INIT_PATTERN") == 0) {
476 (void) strcpy(ipattern, value);
477 continue;
478 }
479 if (strcmp(name, "COREADM_INIT_CONTENT") == 0) {
555 continue;
556 }
557 if (strcmp(name, "COREADM_INIT_PATTERN") == 0) {
558 (void) strcpy(ipattern, value);
559 continue;
560 }
561 if (strcmp(name, "COREADM_INIT_CONTENT") == 0) {
480 (void) proc_str2content(value, &icontent);
562 (void) proc_str2content(value, &init_content);
481 continue;
482 }
483 if (strcmp(name, "COREADM_GLOB_ENABLED") == 0) {
484 if (yes(name, value, line))
485 options |= CC_GLOBAL_PATH;
486 continue;
487 }
488 if (strcmp(name, "COREADM_PROC_ENABLED") == 0) {

--- 13 unchanged lines hidden (view full) ---

502 options |= CC_PROCESS_SETID;
503 continue;
504 }
505 if (strcmp(name, "COREADM_GLOB_LOG_ENABLED") == 0) {
506 if (yes(name, value, line))
507 options |= CC_GLOBAL_LOG;
508 continue;
509 }
563 continue;
564 }
565 if (strcmp(name, "COREADM_GLOB_ENABLED") == 0) {
566 if (yes(name, value, line))
567 options |= CC_GLOBAL_PATH;
568 continue;
569 }
570 if (strcmp(name, "COREADM_PROC_ENABLED") == 0) {

--- 13 unchanged lines hidden (view full) ---

584 options |= CC_PROCESS_SETID;
585 continue;
586 }
587 if (strcmp(name, "COREADM_GLOB_LOG_ENABLED") == 0) {
588 if (yes(name, value, line))
589 options |= CC_GLOBAL_LOG;
590 continue;
591 }
510 (void) fprintf(stderr,
511 gettext(
512 "\"%s\", line %d: warning: invalid token: %s\n"),
513 PATH_CONFIG, line, name);
592 (void) fprintf(stderr, gettext(
593 "\"%s\", line %d: warning: invalid token: %s\n"),
594 PATH_CONFIG, line, name);
514 } else {
515 (void) fprintf(stderr,
595 } else {
596 (void) fprintf(stderr,
516 gettext("\"%s\", line %d: syntax error\n"),
517 PATH_CONFIG, line);
597 gettext("\"%s\", line %d: syntax error\n"),
598 PATH_CONFIG, line);
518 }
519 }
520 (void) fclose(fp);
599 }
600 }
601 (void) fclose(fp);
521 if (core_set_options(options) != 0) {
522 if (errno == EPERM)
523 return (perm());
524 perror("core_set_options()");
525 return (E_ERROR);
526 }
527 if (core_set_global_path(gpattern, strlen(gpattern) + 1) != 0) {
528 if (errno == EPERM)
529 return (perm());
530 perror("core_set_global_path()");
531 return (E_ERROR);
532 }
533 if (core_set_default_path(ipattern, strlen(ipattern) + 1) != 0) {
534 if (errno == EPERM)
535 return (perm());
536 perror("core_set_default_path()");
537 return (E_ERROR);
538 }
539 if (core_set_global_content(&gcontent) != 0) {
540 if (errno == EPERM)
541 return (perm());
542 perror("core_set_global_content()");
543 return (E_ERROR);
544 }
545 if (core_set_default_content(&icontent) != 0) {
546 if (errno == EPERM)
547 return (perm());
548 perror("core_set_default_content()");
549 return (E_ERROR);
550 }
551 return (write_config(1));
602
603 return (1);
552}
553
604}
605
606/*
607 * Loads and applies the coreadm configuration stored in the default
608 * coreadm instance. As this option is (only) used from within an SMF
609 * service method, this function must return an SMF_EXIT_* exit status
610 * to its caller.
611 */
554static int
612static int
555write_config(int justtry)
613do_update(void)
556{
614{
557 int fd;
558 FILE *fp;
559 int options;
560 char global_path[PATH_MAX];
561 char init_path[PATH_MAX];
562 core_content_t gcontent, icontent;
563 char content_str[PRCONTENTBUFSZ];
615 char *gcstr, *icstr;
616 scf_propvec_t properties[MAX_PROPS + 1];
617 scf_propvec_t *prop;
618 int count = 0;
619 const char *errstr;
564
620
565 if ((fd = open(PATH_CONFIG, O_WRONLY | O_CREAT | O_TRUNC,
566 CF_PERM)) == -1) {
567 /*
568 * If we're updating the kernel settings from the contents
569 * of the config file, it's not essential that we rewrite
570 * that file.
571 */
572 if (justtry)
573 return (E_SUCCESS);
621 if (read_legacy()) {
622 if ((errstr = write_kernel()) != NULL)
623 goto error;
574
624
575 if (errno == EACCES) {
576 (void) fprintf(stderr, gettext("%s: insufficient "
577 "privileges to update %s\n"), command, PATH_CONFIG);
578 return (E_SUCCESS);
625 if (do_modify(B_TRUE) != 0 ||
626 rename(PATH_CONFIG, PATH_CONFIG_OLD) != 0) {
627 (void) fprintf(stderr, gettext(
628 "%s: failed to import legacy configuration.\n"),
629 command);
630 return (SMF_EXIT_ERR_FATAL);
579 }
631 }
632 return (SMF_EXIT_OK);
633 }
580
634
581 (void) fprintf(stderr, gettext("failed to open %s: %s\n"),
582 PATH_CONFIG, strerror(errno));
583 return (E_ERROR);
635 addprop(properties, MAX_PROPS, count++, &prop_gpattern, &glob_pattern);
636 addprop(properties, MAX_PROPS, count++, &prop_gcontent, &gcstr);
637 addprop(properties, MAX_PROPS, count++, &prop_ipattern, &init_pattern);
638 addprop(properties, MAX_PROPS, count++, &prop_icontent, &icstr);
639 for (prop = prop_option; prop->pv_prop != NULL; prop++)
640 addprop(properties, MAX_PROPS, count++, prop, &options);
641 properties[count].pv_prop = NULL;
642
643 alloptions = CC_OPTIONS;
644 if (scf_read_propvec(COREADM_INST_FMRI, CONFIG_PARAMS, B_TRUE,
645 properties, &prop) == SCF_FAILED) {
646 if (prop != NULL) {
647 (void) fprintf(stderr, gettext(
648 "%s: configuration property '%s' not found.\n"),
649 command, prop->pv_prop);
650 } else {
651 (void) fprintf(stderr, gettext(
652 "%s: unable to read configuration: %s\n"),
653 command, scf_strerror(scf_error()));
654 }
655 return (SMF_EXIT_ERR_FATAL);
584 }
656 }
585 if ((options = core_get_options()) == -1) {
586 perror("core_get_options()");
587 goto err;
588 }
589 if (core_get_global_path(global_path, sizeof (global_path)) != 0) {
590 perror("core_get_global_path()");
591 goto err;
592 }
593 if (core_get_default_path(init_path, sizeof (init_path)) != 0) {
594 perror("core_get_default_path()");
595 goto err;
596 }
597 if (core_get_global_content(&gcontent) != 0) {
598 perror("core_get_global_content()");
599 goto err;
600 }
601 if (core_get_default_content(&icontent) != 0) {
602 perror("core_get_default_content()");
603 goto err;
604 }
605 if ((fp = fdopen(fd, "w")) == NULL) {
606 (void) fprintf(stderr,
607 gettext("failed to open stream for %s: %s\n"),
608 PATH_CONFIG, strerror(errno));
609 goto err;
610 }
611 (void) fputs(
612 "#\n"
613 "# coreadm.conf\n"
614 "#\n"
615 "# Parameters for system core file configuration.\n"
616 "# Do NOT edit this file by hand -- use coreadm(1) instead.\n"
617 "#\n",
618 fp);
619
657
620 (void) fprintf(fp, "COREADM_GLOB_PATTERN=%s\n", global_path);
621 (void) proc_content2str(gcontent, content_str, sizeof (content_str));
622 (void) fprintf(fp, "COREADM_GLOB_CONTENT=%s\n", content_str);
623 (void) fprintf(fp, "COREADM_INIT_PATTERN=%s\n", init_path);
624 (void) proc_content2str(icontent, content_str, sizeof (content_str));
625 (void) fprintf(fp, "COREADM_INIT_CONTENT=%s\n", content_str);
658 (void) proc_str2content(gcstr, &glob_content);
659 (void) proc_str2content(icstr, &init_content);
626
660
627 (void) fprintf(fp, "COREADM_GLOB_ENABLED=%s\n",
628 (options & CC_GLOBAL_PATH)? "yes" : "no");
629 (void) fprintf(fp, "COREADM_PROC_ENABLED=%s\n",
630 (options & CC_PROCESS_PATH)? "yes" : "no");
631 (void) fprintf(fp, "COREADM_GLOB_SETID_ENABLED=%s\n",
632 (options & CC_GLOBAL_SETID)? "yes" : "no");
633 (void) fprintf(fp, "COREADM_PROC_SETID_ENABLED=%s\n",
634 (options & CC_PROCESS_SETID)? "yes" : "no");
635 (void) fprintf(fp, "COREADM_GLOB_LOG_ENABLED=%s\n",
636 (options & CC_GLOBAL_LOG)? "yes" : "no");
661 errstr = write_kernel();
662 scf_clean_propvec(properties);
663 if (errstr == NULL)
664 return (SMF_EXIT_OK);
637
665
638 (void) fflush(fp);
639 (void) fsync(fd);
640 (void) fchmod(fd, CF_PERM);
641 (void) fchown(fd, CF_OWNER, CF_GROUP);
642 (void) fclose(fp);
666error:
667 if (errno == EPERM) {
668 (void) perm();
669 return (SMF_EXIT_ERR_PERM);
670 }
671 perror(errstr);
672 return (SMF_EXIT_ERR_FATAL);
673}
643
674
644 return (0);
675static int do_legacy()
676{
677 const char *errstr;
645
678
646err:
647 (void) close(fd);
648 return (E_ERROR);
679 if (read_legacy() && (errstr = write_kernel()) != NULL) {
680 if (errno == EPERM)
681 return (perm());
682 perror(errstr);
683 return (E_ERROR);
684 }
685
686 return (E_SUCCESS);
649}
687}