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} |