1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 7734 David * Common Development and Distribution License (the "License"). 6 7734 David * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 7734 David * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel #include <stdio.h> 27 0 stevel #include <fcntl.h> 28 0 stevel #include <ctype.h> 29 0 stevel #include <string.h> 30 0 stevel #include <stdlib.h> 31 0 stevel #include <unistd.h> 32 0 stevel #include <errno.h> 33 0 stevel #include <limits.h> 34 0 stevel #include <libintl.h> 35 0 stevel #include <locale.h> 36 0 stevel #include <sys/stat.h> 37 0 stevel #include <sys/corectl.h> 38 0 stevel #include <libproc.h> 39 7734 David #include <libscf.h> 40 7734 David #include <libscf_priv.h> 41 7734 David #include <assert.h> 42 0 stevel 43 0 stevel #define E_SUCCESS 0 /* Exit status for success */ 44 0 stevel #define E_ERROR 1 /* Exit status for error */ 45 0 stevel #define E_USAGE 2 /* Exit status for usage error */ 46 0 stevel 47 0 stevel static const char PATH_CONFIG[] = "/etc/coreadm.conf"; 48 7734 David static const char PATH_CONFIG_OLD[] = "/etc/coreadm.conf.old"; 49 7734 David 50 7734 David #define COREADM_INST_NAME "system/coreadm:default" 51 7734 David #define COREADM_INST_FMRI \ 52 7734 David SCF_FMRI_SVC_PREFIX SCF_FMRI_SERVICE_PREFIX COREADM_INST_NAME 53 7734 David 54 7734 David #define CONFIG_PARAMS "config_params" 55 7734 David #define GLOBAL_ENABLED "global_enabled" 56 7734 David #define PROCESS_ENABLED "process_enabled" 57 7734 David #define GLOBAL_SETID_ENABLED "global_setid_enabled" 58 7734 David #define PROCESS_SETID_ENABLED "process_setid_enabled" 59 7734 David #define GLOBAL_LOG_ENABLED "global_log_enabled" 60 7734 David #define GLOBAL_PATTERN "global_pattern" 61 7734 David #define GLOBAL_CONTENT "global_content" 62 7734 David #define INIT_PATTERN "init_pattern" 63 7734 David #define INIT_CONTENT "init_content" 64 0 stevel 65 0 stevel static char *command; 66 7734 David static uint64_t options; 67 7734 David static int alloptions; 68 0 stevel static char *glob_pattern; 69 7734 David static char gpattern[PATH_MAX]; 70 0 stevel static core_content_t glob_content = CC_CONTENT_INVALID; 71 0 stevel static char *init_pattern; 72 7734 David static char ipattern[PATH_MAX]; 73 0 stevel static core_content_t init_content = CC_CONTENT_INVALID; 74 0 stevel static char *proc_pattern; 75 0 stevel static size_t proc_size; 76 0 stevel static core_content_t proc_content = CC_CONTENT_INVALID; 77 0 stevel 78 0 stevel static int report_settings(void); 79 0 stevel static int do_processes(int, char **); 80 7734 David static int do_modify(boolean_t); 81 0 stevel static int do_update(void); 82 7734 David static int do_legacy(void); 83 7734 David 84 7734 David static scf_propvec_t prop_gpattern = { GLOBAL_PATTERN, NULL, SCF_TYPE_ASTRING }; 85 7734 David static scf_propvec_t prop_gcontent = { GLOBAL_CONTENT, NULL, SCF_TYPE_ASTRING }; 86 7734 David static scf_propvec_t prop_ipattern = { INIT_PATTERN, NULL, SCF_TYPE_ASTRING }; 87 7734 David static scf_propvec_t prop_icontent = { INIT_CONTENT, NULL, SCF_TYPE_ASTRING }; 88 7734 David static scf_propvec_t prop_option[] = { 89 7734 David { GLOBAL_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL, CC_GLOBAL_PATH }, 90 7734 David { PROCESS_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL, CC_PROCESS_PATH }, 91 7734 David { GLOBAL_SETID_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL, CC_GLOBAL_SETID }, 92 7734 David { PROCESS_SETID_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL, CC_PROCESS_SETID }, 93 7734 David { GLOBAL_LOG_ENABLED, NULL, SCF_TYPE_BOOLEAN, NULL, CC_GLOBAL_LOG }, 94 7734 David { NULL } 95 7734 David }; 96 7734 David #define MAX_PROPS (4 + (sizeof (prop_option) / sizeof (scf_propvec_t))) 97 0 stevel 98 0 stevel static void 99 0 stevel usage(void) 100 0 stevel { 101 0 stevel (void) fprintf(stderr, gettext( 102 0 stevel "usage:\n")); 103 0 stevel (void) fprintf(stderr, gettext( 104 0 stevel " %s [ -g pattern ] [ -i pattern ] [ -G content ] [ -I content ]\n"), 105 7734 David command); 106 0 stevel (void) fprintf(stderr, gettext( 107 0 stevel " [ -e {global | process | global-setid | proc-setid | log} ]\n")); 108 0 stevel (void) fprintf(stderr, gettext( 109 0 stevel " [ -d {global | process | global-setid | proc-setid | log} ]\n")); 110 0 stevel (void) fprintf(stderr, gettext( 111 0 stevel " %s [ -p pattern ] [ -P content ] [ pid ... ]\n"), command); 112 0 stevel exit(E_USAGE); 113 0 stevel } 114 0 stevel 115 0 stevel static int 116 0 stevel perm(void) 117 0 stevel { 118 0 stevel (void) fprintf(stderr, gettext("%s: insufficient privileges to " 119 7734 David "exercise the -[GIgied] options\n"), command); 120 0 stevel return (E_USAGE); 121 7734 David } 122 7734 David 123 7734 David static int 124 7734 David parse_content(char *arg, core_content_t *content) 125 7734 David { 126 7734 David if (proc_str2content(arg, content) == 0) 127 7734 David return (0); 128 7734 David (void) fprintf(stderr, gettext("%s: invalid content string '%s'\n"), 129 7734 David command, arg); 130 7734 David return (1); 131 0 stevel } 132 0 stevel 133 0 stevel int 134 0 stevel main(int argc, char **argv) 135 0 stevel { 136 0 stevel int flag; 137 0 stevel int opt; 138 0 stevel int modify; 139 0 stevel int update = 0; 140 7734 David int legacy_update = 0; 141 0 stevel int error = 0; 142 0 stevel int npids; 143 0 stevel char **pidlist; 144 0 stevel 145 0 stevel char curpid[11]; 146 0 stevel char *curpid_ptr = &curpid[0]; 147 0 stevel 148 0 stevel (void) setlocale(LC_ALL, ""); 149 0 stevel (void) textdomain(TEXT_DOMAIN); 150 0 stevel 151 0 stevel /* command name (e.g., "coreadm") */ 152 0 stevel if ((command = strrchr(argv[0], '/')) != NULL) 153 0 stevel command++; 154 0 stevel else 155 0 stevel command = argv[0]; 156 0 stevel 157 7734 David while ((opt = getopt(argc, argv, "g:G:i:I:p:P:e:d:uU?")) != EOF) { 158 0 stevel switch (opt) { 159 0 stevel case 'g': 160 0 stevel glob_pattern = optarg; 161 0 stevel break; 162 0 stevel case 'i': 163 0 stevel init_pattern = optarg; 164 0 stevel break; 165 0 stevel case 'p': 166 0 stevel proc_pattern = optarg; 167 0 stevel proc_size = strlen(proc_pattern) + 1; 168 0 stevel break; 169 0 stevel case 'G': 170 7734 David error |= parse_content(optarg, &glob_content); 171 0 stevel break; 172 0 stevel case 'I': 173 7734 David error |= parse_content(optarg, &init_content); 174 0 stevel break; 175 0 stevel case 'P': 176 7734 David error |= parse_content(optarg, &proc_content); 177 0 stevel break; 178 0 stevel case 'e': 179 0 stevel case 'd': 180 0 stevel if (strcmp(optarg, "global") == 0) 181 0 stevel flag = CC_GLOBAL_PATH; 182 0 stevel else if (strcmp(optarg, "process") == 0) 183 0 stevel flag = CC_PROCESS_PATH; 184 0 stevel else if (strcmp(optarg, "global-setid") == 0) 185 0 stevel flag = CC_GLOBAL_SETID; 186 0 stevel else if (strcmp(optarg, "proc-setid") == 0) 187 0 stevel flag = CC_PROCESS_SETID; 188 0 stevel else if (strcmp(optarg, "log") == 0) 189 0 stevel flag = CC_GLOBAL_LOG; 190 0 stevel else { 191 0 stevel flag = 0; 192 0 stevel error = 1; 193 0 stevel } 194 7734 David if (opt == 'e') 195 7734 David options |= flag; 196 7734 David else 197 7734 David options &= ~flag; 198 7734 David alloptions |= flag; 199 7734 David break; 200 7734 David case 'U': 201 7734 David update = 1; 202 0 stevel break; 203 0 stevel case 'u': 204 7734 David legacy_update = 1; 205 0 stevel break; 206 0 stevel case '?': 207 0 stevel default: 208 0 stevel error = 1; 209 0 stevel break; 210 0 stevel } 211 0 stevel } 212 0 stevel 213 0 stevel npids = argc - optind; 214 0 stevel pidlist = argv + optind; 215 0 stevel 216 0 stevel if (error) 217 0 stevel usage(); 218 0 stevel 219 0 stevel /* 220 0 stevel * If 'modify' is true, we must modify the system settings 221 0 stevel * and update the configuration file with the new parameters. 222 0 stevel */ 223 0 stevel modify = glob_pattern != NULL || glob_content != CC_CONTENT_INVALID || 224 7734 David init_pattern != NULL || init_content != CC_CONTENT_INVALID || 225 7734 David alloptions != 0; 226 0 stevel 227 7734 David if ((update || legacy_update) && (modify || proc_pattern != NULL || 228 0 stevel proc_content != CC_CONTENT_INVALID || npids != 0)) { 229 0 stevel (void) fprintf(stderr, 230 7734 David gettext("%s: the -u option must stand alone\n"), command); 231 0 stevel usage(); 232 0 stevel } 233 0 stevel if (modify && 234 0 stevel (proc_pattern != NULL || proc_content != CC_CONTENT_INVALID)) { 235 7734 David (void) fprintf(stderr, gettext( 236 0 stevel "%s: -[GIgied] and -[Pp] options are mutually exclusive\n"), 237 0 stevel command); 238 0 stevel usage(); 239 0 stevel } 240 0 stevel if (modify && npids != 0) { 241 7734 David (void) fprintf(stderr, gettext( 242 0 stevel "%s: -[GIgied] options cannot have a process-id list\n"), 243 0 stevel command); 244 0 stevel usage(); 245 0 stevel } 246 0 stevel if ((proc_pattern != NULL || proc_content != CC_CONTENT_INVALID) && 247 0 stevel npids == 0) { 248 0 stevel (void) sprintf(curpid, "%u", (uint_t)getppid()); 249 0 stevel npids = 1; 250 0 stevel pidlist = &curpid_ptr; 251 0 stevel } 252 0 stevel 253 7734 David if (legacy_update) 254 7734 David return (do_legacy()); 255 0 stevel if (update) 256 0 stevel return (do_update()); 257 0 stevel if (modify) 258 7734 David return (do_modify(B_FALSE)); 259 0 stevel if (npids != 0) 260 0 stevel return (do_processes(npids, pidlist)); 261 0 stevel 262 0 stevel return (report_settings()); 263 0 stevel } 264 0 stevel 265 0 stevel static int 266 0 stevel report_settings(void) 267 0 stevel { 268 7734 David char content_str[PRCONTENTBUFSZ]; 269 0 stevel 270 0 stevel if ((options = core_get_options()) == -1) { 271 0 stevel perror("core_get_options()"); 272 0 stevel return (E_ERROR); 273 0 stevel } 274 7734 David if (core_get_global_path(gpattern, sizeof (gpattern)) != 0) { 275 0 stevel perror("core_get_global_path()"); 276 0 stevel return (E_ERROR); 277 0 stevel } 278 7734 David if (core_get_default_path(ipattern, sizeof (ipattern)) != 0) { 279 0 stevel perror("core_get_default_path()"); 280 0 stevel return (E_ERROR); 281 0 stevel } 282 7734 David if (core_get_global_content(&glob_content) != 0) { 283 0 stevel perror("core_get_global_content()"); 284 0 stevel return (E_ERROR); 285 0 stevel } 286 7734 David if (core_get_default_content(&init_content) != 0) { 287 0 stevel perror("core_get_default_content()"); 288 0 stevel return (E_ERROR); 289 0 stevel } 290 7734 David 291 0 stevel (void) printf(gettext(" global core file pattern: %s\n"), 292 7734 David gpattern); 293 7734 David (void) proc_content2str(glob_content, content_str, 294 7734 David sizeof (content_str)); 295 0 stevel (void) printf(gettext(" global core file content: %s\n"), 296 0 stevel content_str); 297 0 stevel (void) printf(gettext(" init core file pattern: %s\n"), 298 7734 David ipattern); 299 7734 David (void) proc_content2str(init_content, content_str, 300 7734 David sizeof (content_str)); 301 0 stevel (void) printf(gettext(" init core file content: %s\n"), 302 0 stevel content_str); 303 0 stevel (void) printf(gettext(" global core dumps: %s\n"), 304 0 stevel (options & CC_GLOBAL_PATH)? "enabled" : "disabled"); 305 0 stevel (void) printf(gettext(" per-process core dumps: %s\n"), 306 0 stevel (options & CC_PROCESS_PATH)? "enabled" : "disabled"); 307 0 stevel (void) printf(gettext(" global setid core dumps: %s\n"), 308 0 stevel (options & CC_GLOBAL_SETID)? "enabled" : "disabled"); 309 0 stevel (void) printf(gettext(" per-process setid core dumps: %s\n"), 310 0 stevel (options & CC_PROCESS_SETID)? "enabled" : "disabled"); 311 0 stevel (void) printf(gettext(" global core dump logging: %s\n"), 312 0 stevel (options & CC_GLOBAL_LOG)? "enabled" : "disabled"); 313 0 stevel return (E_SUCCESS); 314 0 stevel } 315 0 stevel 316 0 stevel static int 317 0 stevel do_processes(int npids, char **pidlist) 318 0 stevel { 319 0 stevel char process_path[PATH_MAX]; 320 0 stevel core_content_t content; 321 0 stevel pid_t pid; 322 0 stevel char *next; 323 0 stevel int rc = E_SUCCESS; 324 7734 David char content_str[PRCONTENTBUFSZ]; 325 0 stevel 326 0 stevel if (proc_pattern == NULL && proc_content == CC_CONTENT_INVALID) { 327 0 stevel while (npids-- > 0) { 328 0 stevel pid = strtol(*pidlist, &next, 10); 329 0 stevel if (*next != '\0' || !isdigit(**pidlist)) { 330 0 stevel (void) fprintf(stderr, 331 0 stevel gettext("%s: invalid process-id\n"), 332 0 stevel *pidlist); 333 0 stevel rc = E_USAGE; 334 0 stevel } else if (core_get_process_path(process_path, 335 0 stevel sizeof (process_path), pid) != 0 || 336 0 stevel core_get_process_content(&content, pid) != 0) { 337 0 stevel perror(*pidlist); 338 0 stevel rc = E_USAGE; 339 0 stevel } else { 340 0 stevel (void) proc_content2str(content, content_str, 341 0 stevel sizeof (content_str)); 342 0 stevel (void) printf(gettext("%s:\t%s\t%s\n"), 343 0 stevel *pidlist, process_path, content_str); 344 0 stevel } 345 0 stevel pidlist++; 346 0 stevel } 347 0 stevel } else { 348 0 stevel while (npids-- > 0) { 349 0 stevel pid = strtol(*pidlist, &next, 10); 350 0 stevel if (*next != '\0') { 351 0 stevel (void) fprintf(stderr, 352 0 stevel gettext("%s: invalid process-id\n"), 353 0 stevel *pidlist); 354 0 stevel rc = E_USAGE; 355 0 stevel } else { 356 0 stevel if (proc_pattern != NULL && 357 0 stevel core_set_process_path(proc_pattern, 358 0 stevel proc_size, pid) != 0) { 359 0 stevel perror(*pidlist); 360 0 stevel rc = E_USAGE; 361 0 stevel } 362 0 stevel 363 0 stevel if (proc_content != CC_CONTENT_INVALID && 364 0 stevel core_set_process_content( 365 0 stevel &proc_content, pid) != 0) { 366 0 stevel perror(*pidlist); 367 0 stevel rc = E_USAGE; 368 0 stevel } 369 0 stevel } 370 0 stevel pidlist++; 371 0 stevel } 372 0 stevel } 373 0 stevel 374 0 stevel return (rc); 375 0 stevel } 376 0 stevel 377 7734 David static void 378 7734 David addprop(scf_propvec_t *props, int size, int count, scf_propvec_t *pv, void *ptr) 379 7734 David { 380 7734 David assert(count + 1 < size); 381 7734 David props[count] = *pv; 382 7734 David props[count].pv_ptr = ptr; 383 7734 David } 384 7734 David 385 7734 David static boolean_t 386 7734 David is_online(const char *fmri) 387 7734 David { 388 7734 David char *state = smf_get_state(fmri); 389 7734 David boolean_t result = state != NULL && 390 7734 David strcmp(state, SCF_STATE_STRING_ONLINE) == 0; 391 7734 David 392 7734 David free(state); 393 7734 David return (result); 394 7734 David } 395 7734 David 396 7734 David /* 397 7734 David * The user has specified the -g, -G, -i, -I, -d, or -e options to 398 7734 David * modify the given configuration parameter. Perform the modification 399 7734 David * in the smf repository and then perform a smf_refresh_instance which 400 7734 David * will cause a coreadm -u to occur which will transfer ALL coreadm 401 7734 David * configuration information from the repository to the kernel. 402 7734 David */ 403 0 stevel static int 404 7734 David do_modify(boolean_t method) 405 0 stevel { 406 7734 David char gcontentstr[PRCONTENTBUFSZ]; 407 7734 David char icontentstr[PRCONTENTBUFSZ]; 408 7734 David scf_propvec_t *prop; 409 7734 David scf_propvec_t properties[MAX_PROPS + 1]; 410 7734 David int count = 0; 411 0 stevel 412 7734 David if (!method && !is_online(COREADM_INST_FMRI)) { 413 7734 David (void) fprintf(stderr, 414 7734 David gettext("%s: coreadm service not online\n"), command); 415 0 stevel return (E_ERROR); 416 0 stevel } 417 7734 David 418 7734 David if (glob_pattern != NULL) 419 7734 David addprop(properties, MAX_PROPS, count++, &prop_gpattern, 420 7734 David glob_pattern); 421 7734 David 422 7734 David if (glob_content != CC_CONTENT_INVALID) { 423 7734 David (void) proc_content2str(glob_content, gcontentstr, 424 7734 David sizeof (gcontentstr)); 425 7734 David addprop(properties, MAX_PROPS, count++, &prop_gcontent, 426 7734 David gcontentstr); 427 7734 David } 428 7734 David 429 7734 David if (init_pattern != NULL) 430 7734 David addprop(properties, MAX_PROPS, count++, &prop_ipattern, 431 7734 David init_pattern); 432 7734 David 433 7734 David if (init_content != CC_CONTENT_INVALID) { 434 7734 David (void) proc_content2str(init_content, icontentstr, 435 7734 David sizeof (icontentstr)); 436 7734 David addprop(properties, MAX_PROPS, count++, &prop_icontent, 437 7734 David icontentstr); 438 7734 David } 439 7734 David 440 7734 David for (prop = prop_option; prop->pv_prop != NULL; prop++) 441 7734 David if ((alloptions & prop->pv_aux) != 0) 442 7734 David addprop(properties, MAX_PROPS, count++, prop, &options); 443 7734 David 444 7734 David properties[count].pv_prop = NULL; 445 7734 David 446 7734 David prop = NULL; 447 7734 David if (scf_write_propvec(COREADM_INST_FMRI, CONFIG_PARAMS, properties, 448 7734 David &prop) == SCF_FAILED) { 449 7734 David if (prop != NULL) { 450 7734 David (void) fprintf(stderr, gettext( 451 7734 David "%s: Unable to write property '%s': %s"), command, 452 7734 David prop->pv_prop, scf_strerror(scf_error())); 453 7734 David } else { 454 7734 David (void) fprintf(stderr, gettext( 455 7734 David "%s: Unable to write configuration: %s\n"), 456 7734 David command, scf_strerror(scf_error())); 457 7734 David } 458 0 stevel return (E_ERROR); 459 0 stevel } 460 7734 David 461 7734 David if (smf_refresh_instance(COREADM_INST_FMRI) != 0) { 462 7734 David (void) fprintf(stderr, 463 7734 David gettext("%s: Unable to refresh %s: %s\n" 464 7734 David "Configuration stored but not made active.\n"), 465 7734 David command, COREADM_INST_FMRI, scf_strerror(scf_error())); 466 0 stevel return (E_ERROR); 467 0 stevel } 468 7734 David 469 7734 David return (E_SUCCESS); 470 7734 David } 471 7734 David 472 7734 David static const char * 473 7734 David write_kernel(void) 474 7734 David { 475 7734 David if (core_set_global_path(glob_pattern, strlen(glob_pattern) + 1) != 0) 476 7734 David return ("core_set_global_path()"); 477 7734 David 478 7734 David if (core_set_global_content(&glob_content) != 0) 479 7734 David return ("core_set_global_content()"); 480 7734 David 481 7734 David if (core_set_default_path(init_pattern, strlen(init_pattern) + 1) != 0) 482 7734 David return ("core_set_default_path()"); 483 7734 David 484 7734 David if (core_set_default_content(&init_content) != 0) 485 7734 David return ("core_set_init_content()"); 486 7734 David 487 7734 David if (core_set_options((int)options) != 0) 488 7734 David return ("core_set_options()"); 489 7734 David 490 7734 David return (NULL); 491 0 stevel } 492 0 stevel 493 0 stevel /* 494 0 stevel * BUFSIZE must be large enough to contain the longest path plus some more. 495 0 stevel */ 496 0 stevel #define BUFSIZE (PATH_MAX + 80) 497 0 stevel 498 0 stevel static int 499 0 stevel yes(char *name, char *value, int line) 500 0 stevel { 501 0 stevel if (strcmp(value, "yes") == 0) 502 0 stevel return (1); 503 0 stevel if (strcmp(value, "no") == 0) 504 0 stevel return (0); 505 7734 David (void) fprintf(stderr, gettext( 506 7734 David "\"%s\", line %d: warning: value must be yes or no: %s=%s\n"), 507 7734 David PATH_CONFIG, line, name, value); 508 0 stevel return (0); 509 0 stevel } 510 0 stevel 511 0 stevel static int 512 7734 David read_legacy(void) 513 0 stevel { 514 0 stevel FILE *fp; 515 0 stevel int line; 516 0 stevel char buf[BUFSIZE]; 517 0 stevel char name[BUFSIZE], value[BUFSIZE]; 518 7734 David int n, len; 519 0 stevel 520 0 stevel /* defaults */ 521 7734 David alloptions = CC_OPTIONS; 522 0 stevel options = CC_PROCESS_PATH; 523 0 stevel gpattern[0] = '\0'; 524 0 stevel (void) strcpy(ipattern, "core"); 525 7734 David glob_content = init_content = CC_CONTENT_DEFAULT; 526 0 stevel 527 7734 David glob_pattern = gpattern; 528 7734 David init_pattern = ipattern; 529 7734 David 530 7734 David if ((fp = fopen(PATH_CONFIG, "r")) == NULL) 531 7734 David return (0); 532 0 stevel 533 0 stevel for (line = 1; fgets(buf, sizeof (buf), fp) != NULL; line++) { 534 0 stevel /* 535 0 stevel * Skip comment lines and empty lines. 536 0 stevel */ 537 0 stevel if (buf[0] == '#' || buf[0] == '\n') 538 0 stevel continue; 539 0 stevel /* 540 0 stevel * Look for "name=value", with optional whitespace on either 541 0 stevel * side, terminated by a newline, and consuming the whole line. 542 0 stevel */ 543 0 stevel /* LINTED - unbounded string specifier */ 544 0 stevel n = sscanf(buf, " %[^=]=%s \n%n", name, value, &len); 545 0 stevel if (n >= 1 && name[0] != '\0' && 546 0 stevel (n == 1 || len == strlen(buf))) { 547 0 stevel if (n == 1) 548 0 stevel value[0] = '\0'; 549 0 stevel if (strcmp(name, "COREADM_GLOB_PATTERN") == 0) { 550 0 stevel (void) strcpy(gpattern, value); 551 0 stevel continue; 552 0 stevel } 553 0 stevel if (strcmp(name, "COREADM_GLOB_CONTENT") == 0) { 554 7734 David (void) proc_str2content(value, &glob_content); 555 0 stevel continue; 556 0 stevel } 557 0 stevel if (strcmp(name, "COREADM_INIT_PATTERN") == 0) { 558 0 stevel (void) strcpy(ipattern, value); 559 0 stevel continue; 560 0 stevel } 561 0 stevel if (strcmp(name, "COREADM_INIT_CONTENT") == 0) { 562 7734 David (void) proc_str2content(value, &init_content); 563 0 stevel continue; 564 0 stevel } 565 0 stevel if (strcmp(name, "COREADM_GLOB_ENABLED") == 0) { 566 0 stevel if (yes(name, value, line)) 567 0 stevel options |= CC_GLOBAL_PATH; 568 0 stevel continue; 569 0 stevel } 570 0 stevel if (strcmp(name, "COREADM_PROC_ENABLED") == 0) { 571 0 stevel if (yes(name, value, line)) 572 0 stevel options |= CC_PROCESS_PATH; 573 0 stevel else 574 0 stevel options &= ~CC_PROCESS_PATH; 575 0 stevel continue; 576 0 stevel } 577 0 stevel if (strcmp(name, "COREADM_GLOB_SETID_ENABLED") == 0) { 578 0 stevel if (yes(name, value, line)) 579 0 stevel options |= CC_GLOBAL_SETID; 580 0 stevel continue; 581 0 stevel } 582 0 stevel if (strcmp(name, "COREADM_PROC_SETID_ENABLED") == 0) { 583 0 stevel if (yes(name, value, line)) 584 0 stevel options |= CC_PROCESS_SETID; 585 0 stevel continue; 586 0 stevel } 587 0 stevel if (strcmp(name, "COREADM_GLOB_LOG_ENABLED") == 0) { 588 0 stevel if (yes(name, value, line)) 589 0 stevel options |= CC_GLOBAL_LOG; 590 0 stevel continue; 591 0 stevel } 592 7734 David (void) fprintf(stderr, gettext( 593 7734 David "\"%s\", line %d: warning: invalid token: %s\n"), 594 7734 David PATH_CONFIG, line, name); 595 0 stevel } else { 596 0 stevel (void) fprintf(stderr, 597 7734 David gettext("\"%s\", line %d: syntax error\n"), 598 7734 David PATH_CONFIG, line); 599 0 stevel } 600 0 stevel } 601 0 stevel (void) fclose(fp); 602 7734 David 603 7734 David return (1); 604 7734 David } 605 7734 David 606 7734 David /* 607 7734 David * Loads and applies the coreadm configuration stored in the default 608 7734 David * coreadm instance. As this option is (only) used from within an SMF 609 7734 David * service method, this function must return an SMF_EXIT_* exit status 610 7734 David * to its caller. 611 7734 David */ 612 7734 David static int 613 7734 David do_update(void) 614 7734 David { 615 7734 David char *gcstr, *icstr; 616 7734 David scf_propvec_t properties[MAX_PROPS + 1]; 617 7734 David scf_propvec_t *prop; 618 7734 David int count = 0; 619 7734 David const char *errstr; 620 7734 David 621 7734 David if (read_legacy()) { 622 7734 David if ((errstr = write_kernel()) != NULL) 623 7734 David goto error; 624 7734 David 625 7734 David if (do_modify(B_TRUE) != 0 || 626 7734 David rename(PATH_CONFIG, PATH_CONFIG_OLD) != 0) { 627 7734 David (void) fprintf(stderr, gettext( 628 7734 David "%s: failed to import legacy configuration.\n"), 629 7734 David command); 630 7734 David return (SMF_EXIT_ERR_FATAL); 631 7734 David } 632 7734 David return (SMF_EXIT_OK); 633 7734 David } 634 7734 David 635 7734 David addprop(properties, MAX_PROPS, count++, &prop_gpattern, &glob_pattern); 636 7734 David addprop(properties, MAX_PROPS, count++, &prop_gcontent, &gcstr); 637 7734 David addprop(properties, MAX_PROPS, count++, &prop_ipattern, &init_pattern); 638 7734 David addprop(properties, MAX_PROPS, count++, &prop_icontent, &icstr); 639 7734 David for (prop = prop_option; prop->pv_prop != NULL; prop++) 640 7734 David addprop(properties, MAX_PROPS, count++, prop, &options); 641 7734 David properties[count].pv_prop = NULL; 642 7734 David 643 7734 David alloptions = CC_OPTIONS; 644 7734 David if (scf_read_propvec(COREADM_INST_FMRI, CONFIG_PARAMS, B_TRUE, 645 7734 David properties, &prop) == SCF_FAILED) { 646 7734 David if (prop != NULL) { 647 7734 David (void) fprintf(stderr, gettext( 648 7734 David "%s: configuration property '%s' not found.\n"), 649 7734 David command, prop->pv_prop); 650 7734 David } else { 651 7734 David (void) fprintf(stderr, gettext( 652 7734 David "%s: unable to read configuration: %s\n"), 653 7734 David command, scf_strerror(scf_error())); 654 7734 David } 655 7734 David return (SMF_EXIT_ERR_FATAL); 656 7734 David } 657 7734 David 658 7734 David (void) proc_str2content(gcstr, &glob_content); 659 7734 David (void) proc_str2content(icstr, &init_content); 660 7734 David 661 7734 David errstr = write_kernel(); 662 7734 David scf_clean_propvec(properties); 663 7734 David if (errstr == NULL) 664 7734 David return (SMF_EXIT_OK); 665 7734 David 666 7734 David error: 667 7734 David if (errno == EPERM) { 668 7734 David (void) perm(); 669 7734 David return (SMF_EXIT_ERR_PERM); 670 7734 David } 671 7734 David perror(errstr); 672 7734 David return (SMF_EXIT_ERR_FATAL); 673 7734 David } 674 7734 David 675 7734 David static int do_legacy() 676 7734 David { 677 7734 David const char *errstr; 678 7734 David 679 7734 David if (read_legacy() && (errstr = write_kernel()) != NULL) { 680 0 stevel if (errno == EPERM) 681 0 stevel return (perm()); 682 7734 David perror(errstr); 683 0 stevel return (E_ERROR); 684 0 stevel } 685 7734 David 686 7734 David return (E_SUCCESS); 687 0 stevel } 688