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 (the "License"). 6 * You may not use this file except in compliance with the License. 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 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/types.h> 29 #include <sys/stat.h> 30 #include <sys/mman.h> 31 #include <fcntl.h> 32 #include <stdio.h> 33 #include <string.h> 34 #include <unistd.h> 35 #include <errno.h> 36 #include <limits.h> 37 #include <alloca.h> 38 #include "sgs.h" 39 #include "rtc.h" 40 #include "conv.h" 41 #include "_crle.h" 42 #include "msg.h" 43 44 45 /* 46 * Display the command line required to regenerate the configuration file. 47 * 48 * Under normal mode the command is printed on one line to make it more 49 * available for grep(1) use. Under verbose mode the command is separated 50 * into each argument (a little more readable perhaps when the arguments are 51 * numerous of have long pathnames). 52 * 53 * Note that for version 1 configuration files we never used to generate any 54 * command-line information, and as the attempt to do so is only a best effort 55 * don't bother printing anything. 56 */ 57 static void 58 printcmd(Crle_desc * crle, Rtc_head * head, List * cmdline) 59 { 60 Listnode *lnp; 61 const char *fmto, *fmtb, *fmtm, *fmte; 62 char *cmd; 63 int output = 0; 64 65 if (crle->c_flags & CRLE_VERBOSE) { 66 fmto = MSG_INTL(MSG_DMP_CMD_ONE_V); 67 fmtb = MSG_INTL(MSG_DMP_CMD_BGN_V); 68 fmtm = MSG_INTL(MSG_DMP_CMD_MID_V); 69 fmte = MSG_INTL(MSG_DMP_CMD_END_V); 70 71 } else if (head->ch_version > RTC_VER_ONE) { 72 fmto = MSG_INTL(MSG_DMP_CMD_ONE); 73 fmtb = MSG_INTL(MSG_DMP_CMD_BGN); 74 fmtm = MSG_INTL(MSG_DMP_CMD_MID); 75 fmte = MSG_INTL(MSG_DMP_CMD_END); 76 77 } else { 78 (void) printf(MSG_ORIG(MSG_STR_NL)); 79 return; 80 } 81 82 (void) printf(MSG_INTL(MSG_DMP_CMD_TITLE)); 83 for (LIST_TRAVERSE(cmdline, lnp, cmd)) { 84 if (output++ == 0) { 85 if (lnp->next) 86 (void) printf(fmtb, cmd); 87 else 88 (void) printf(fmto, cmd); 89 } else { 90 if (lnp->next) 91 (void) printf(fmtm, cmd); 92 else 93 (void) printf(fmte, cmd); 94 } 95 } 96 } 97 98 /* 99 * Establish the argument required to generate the associated object. 100 */ 101 static const char * 102 getformat(Half flags) 103 { 104 if (flags & RTC_OBJ_ALTER) { 105 if (flags & RTC_OBJ_DUMP) { 106 if (flags & RTC_OBJ_GROUP) 107 return (MSG_ORIG(MSG_CMD_DUMPGRP)); 108 else 109 return (MSG_ORIG(MSG_CMD_DUMPIND)); 110 } else { 111 if (flags & RTC_OBJ_OPTINAL) 112 return (MSG_ORIG(MSG_CMD_OPTIONAL)); 113 else 114 return (MSG_ORIG(MSG_CMD_ALTER)); 115 } 116 } else { 117 if (flags & RTC_OBJ_GROUP) 118 return (MSG_ORIG(MSG_CMD_GRP)); 119 else 120 return (MSG_ORIG(MSG_CMD_IND)); 121 } 122 } 123 124 /* 125 * Fabricate a system default search path. If an update is requested, and 126 * new search paths are specified while no configuration file exists, or if a 127 * configuration file does exist but doesn't specify this particular search 128 * path, create any system defaults. The intent is to allow 129 * "crle -u -l/usr/local/lib" and have this append the search path to the 130 * system default, rather than have the user have to determine and specify 131 * this default themselves. 132 */ 133 static int 134 fablib(Crle_desc * crle, int flag) 135 { 136 const char *path; 137 char **list; 138 139 switch (flag) { 140 case CRLE_EDLIB: 141 #if M_CLASS == ELFCLASS64 142 #ifndef SGS_PRE_UNIFIED_PROCESS 143 path = MSG_ORIG(MSG_PTH_NEWDLP_64); 144 #else 145 path = MSG_ORIG(MSG_PTH_OLDDLP_64); 146 #endif 147 #else 148 #ifndef SGS_PRE_UNIFIED_PROCESS 149 path = MSG_ORIG(MSG_PTH_NEWDLP); 150 #else 151 path = MSG_ORIG(MSG_PTH_OLDDLP); 152 #endif 153 #endif 154 list = &crle->c_edlibpath; 155 break; 156 157 case CRLE_ESLIB: 158 #if M_CLASS == ELFCLASS64 159 #ifndef SGS_PRE_UNIFIED_PROCESS 160 path = MSG_ORIG(MSG_PTH_NEWTD_64); 161 #else 162 path = MSG_ORIG(MSG_PTH_OLDTD_64); 163 #endif 164 #else 165 #ifndef SGS_PRE_UNIFIED_PROCESS 166 path = MSG_ORIG(MSG_PTH_NEWTD); 167 #else 168 path = MSG_ORIG(MSG_PTH_OLDTD); 169 #endif 170 #endif 171 list = &crle->c_eslibpath; 172 break; 173 174 case CRLE_ADLIB: 175 path = MSG_ORIG(MSG_PTH_AOUTDLP); 176 list = &crle->c_adlibpath; 177 break; 178 179 case CRLE_ASLIB: 180 path = MSG_ORIG(MSG_PTH_AOUTTD); 181 list = &crle->c_aslibpath; 182 break; 183 184 default: 185 return (1); 186 } 187 188 return (addlib(crle, list, path)); 189 } 190 191 /* 192 * Establish the flags required to generate the associated object. Actually 193 * the flags are already part of the object being inspected from the present 194 * configuration file, but instead of using them all, which can cause some 195 * unsuspected propagation down the inspect() family, only use those flags that 196 * would have been contributed from crle()'s calls to inspect. 197 */ 198 static Half 199 getflags(Half flags) 200 { 201 flags &= 202 (RTC_OBJ_ALTER | RTC_OBJ_DUMP | RTC_OBJ_GROUP | RTC_OBJ_OPTINAL); 203 return (flags | RTC_OBJ_CMDLINE); 204 } 205 206 /* 207 * Dump a configuration files information. This routine is very close to the 208 * scanconfig() in libcrle. 209 */ 210 static INSCFG_RET 211 scanconfig(Crle_desc * crle, Addr addr) 212 { 213 Rtc_id *id; 214 Rtc_head *head; 215 Rtc_dir *dirtbl; 216 Rtc_file *filetbl; 217 Rtc_obj *objtbl, * obj; 218 Word *hash, * chain; 219 const char *strtbl; 220 int ndx, bkts; 221 List cmdline = { 0 }; 222 char _cmd[PATH_MAX], * cmd; 223 char _objdir[PATH_MAX], * objdir = 0; 224 225 226 /* 227 * If there is an Rtc_id present, the Rtc_head follows it. 228 * Otherwise, it is at the top. 229 */ 230 if (RTC_ID_TEST(addr)) { 231 id = (Rtc_id *) addr; 232 addr += sizeof (*id); /* Rtc_head follows */ 233 } else { 234 id = NULL; 235 /* 236 * When updating an existing config file that is lacking 237 * the Rtc_id block, don't put one into the resulting file. 238 */ 239 crle->c_flags &= ~CRLE_ADDID; 240 } 241 head = (Rtc_head *) addr; 242 243 244 /* 245 * The rest of the configuration file can only be examined by 246 * a program of the same ELFCLASS, byte order, and hardware 247 * architecture as the one that created it. 248 */ 249 #ifdef _ELF64 250 /* 64-bit program with an existing 32-bit file? Abort. */ 251 if (!(head->ch_cnflags & RTC_HDR_64)) { 252 (void) fprintf(stderr, MSG_INTL(MSG_ARG_CLASS), 253 crle->c_name, crle->c_confil); 254 return (INSCFG_RET_FAIL); 255 } 256 #else 257 /* 32-bit program with an existing 64-bit file? Restart. */ 258 if (head->ch_cnflags & RTC_HDR_64) 259 return (INSCFG_RET_NEED64); 260 #endif 261 /* 262 * Now that the ELFCLASS has been settled, ensure that the 263 * byte order and hardware match. Unlike ELFCLASS, where restarting 264 * the other version is an option, we cannot work around a mismatch 265 * of these attributes. 266 */ 267 if (id) { /* Rtc_id is present */ 268 /* 269 * Was the file produced by compatible hardware? 270 * ELFCLASS doesn't matter here, because we can 271 * adjust for that, but byte order and machine type do. 272 */ 273 if ((id->id_data != M_DATA) || (id->id_machine != M_MACH)) { 274 (void) fprintf(stderr, MSG_INTL(MSG_ARG_WRONGARCH), 275 crle->c_name, crle->c_confil, 276 conv_ehdr_data(id->id_data, CONV_FMT_ALTFILE), 277 conv_ehdr_mach(id->id_machine, CONV_FMT_ALTFILE), 278 conv_ehdr_data(M_DATA, CONV_FMT_ALTFILE), 279 conv_ehdr_mach(M_MACH, CONV_FMT_ALTFILE)); 280 return (INSCFG_RET_FAIL); 281 } 282 } 283 284 285 /* LINTED */ 286 objtbl = (Rtc_obj *)(CAST_PTRINT(char *, head->ch_obj) + addr); 287 strtbl = (const char *)(CAST_PTRINT(char *, head->ch_str) + addr); 288 289 /* 290 * If the configuration file has a version higher than we 291 * recognise, we face two issues: 292 * (1) Updates are not possible because we have no 293 * way to recognise or propagate the new features. 294 * This has to be a fatal error. 295 * (2) Printing has the risk that we may have been 296 * handed something other than a real config file, as 297 * well as the fact that we can't display the information 298 * for the new features. So, we print a warning, but 299 * continue on to do the best we can with it. 300 */ 301 if (head->ch_version > RTC_VER_CURRENT) { 302 if (crle->c_flags & CRLE_UPDATE) { 303 (void) fprintf(stderr, MSG_INTL(MSG_ARG_UPDATEVER), 304 crle->c_name, crle->c_confil, 305 head->ch_version, RTC_VER_CURRENT); 306 return (INSCFG_RET_FAIL); 307 } else { 308 (void) fprintf(stderr, MSG_INTL(MSG_ARG_PRINTVER), 309 crle->c_name, crle->c_confil, 310 head->ch_version, RTC_VER_CURRENT); 311 } 312 } 313 314 /* 315 * If this is a version 1 configuration file we can't generate accurate 316 * update information, or the command-line used to create the file. 317 */ 318 if (head->ch_version == RTC_VER_ONE) { 319 (void) printf(MSG_INTL(MSG_ARG_UPDATE), crle->c_name, 320 crle->c_confil, head->ch_version); 321 } 322 323 324 if (!(crle->c_flags & CRLE_UPDATE) && (head->ch_cnflags & RTC_HDR_64)) { 325 /* 326 * Construct the original command line argument. 327 */ 328 cmd = strcpy(alloca(MSG_CMD_64_SIZE + 1), MSG_ORIG(MSG_CMD_64)); 329 if (list_append(&cmdline, cmd) == 0) 330 return (INSCFG_RET_FAIL); 331 } 332 333 334 /* 335 * Start analyzing the configuration files header information. 336 */ 337 if ((crle->c_flags & CRLE_UPDATE) == 0) { 338 const char *fmt; 339 340 if (head->ch_dlflags) 341 fmt = conv_dl_flag(head->ch_dlflags, 0); 342 else 343 fmt = MSG_ORIG(MSG_STR_EMPTY); 344 345 (void) printf(MSG_INTL(MSG_DMP_HEAD), head->ch_version, 346 crle->c_confil, fmt); 347 348 /* 349 * If the file has an id block, show the information 350 */ 351 if (id) 352 printf(MSG_INTL(MSG_DMP_PLATFORM), 353 conv_ehdr_class(id->id_class, CONV_FMT_ALTFILE), 354 conv_ehdr_data(id->id_data, CONV_FMT_ALTFILE), 355 conv_ehdr_mach(id->id_machine, CONV_FMT_ALTFILE)); 356 357 /* 358 * Construct the original command line argument. 359 */ 360 (void) snprintf(_cmd, PATH_MAX, MSG_ORIG(MSG_CMD_CONF), 361 crle->c_confil); 362 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 363 if (list_append(&cmdline, cmd) == 0) 364 return (INSCFG_RET_FAIL); 365 366 /* 367 * Construct any -f usage. 368 */ 369 if (head->ch_dlflags && 370 (head->ch_dlflags != RTLD_REL_RELATIVE)) { 371 (void) snprintf(_cmd, PATH_MAX, MSG_ORIG(MSG_CMD_FLAGS), 372 conv_dl_flag(head->ch_dlflags, 1)); 373 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 374 if (list_append(&cmdline, cmd) == 0) 375 return (INSCFG_RET_FAIL); 376 } 377 } else { 378 /* 379 * Establish any -f usage. 380 */ 381 if (head->ch_dlflags && 382 (head->ch_dlflags != RTLD_REL_RELATIVE)) 383 crle->c_dlflags = head->ch_dlflags; 384 } 385 386 387 /* 388 * Determine if this configuration file is only applicable to a specific 389 * application. 390 */ 391 if (head->ch_app) { 392 char *alter; 393 394 obj = (Rtc_obj *)(head->ch_app + addr); 395 396 /* 397 * Determine the output directory for the files 398 * alternative name. 399 */ 400 alter = (char *)(strtbl + obj->co_alter); 401 (void) strcpy(_objdir, alter); 402 alter = strrchr(_objdir, '/'); 403 *alter = '\0'; 404 405 crle->c_objdir = objdir = _objdir; 406 407 if (crle->c_flags & CRLE_UPDATE) { 408 if (inspect(crle, (strtbl + obj->co_name), 409 (RTC_OBJ_DUMP | RTC_OBJ_ALTER | 410 RTC_OBJ_GROUP | RTC_OBJ_CMDLINE)) != 0) 411 return (INSCFG_RET_FAIL); 412 } else { 413 (void) printf(MSG_INTL(MSG_DMP_APP), 414 (strtbl + obj->co_alter), (strtbl + obj->co_name)); 415 416 /* 417 * Construct the original command line arguments. 418 */ 419 (void) snprintf(_cmd, PATH_MAX, 420 MSG_ORIG(MSG_CMD_OUTPUT), crle->c_objdir); 421 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 422 if (list_append(&cmdline, cmd) == 0) 423 return (INSCFG_RET_FAIL); 424 425 (void) snprintf(_cmd, PATH_MAX, 426 MSG_ORIG(MSG_CMD_DUMPGRP), (strtbl + obj->co_name)); 427 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 428 if (list_append(&cmdline, cmd) == 0) 429 return (INSCFG_RET_FAIL); 430 } 431 } 432 433 /* 434 * Analyze any alternative library path and trusted directory entries. 435 */ 436 if (head->ch_edlibpath) { 437 const char *str; 438 439 str = (const char *)(head->ch_edlibpath + addr); 440 441 if (crle->c_flags & CRLE_UPDATE) { 442 crle->c_flags &= ~CRLE_AOUT; 443 444 #ifndef SGS_PRE_UNIFIED_PROCESS 445 if ((head->ch_cnflags & RTC_HDR_UPM) == 0) { 446 if (head->ch_cnflags & RTC_HDR_64) 447 str = conv_config_upm(str, 448 MSG_ORIG(MSG_PTH_OLDDLP_64), 449 MSG_ORIG(MSG_PTH_UPDLP_64), 450 MSG_PTH_UPDLP_64_SIZE); 451 else 452 str = conv_config_upm(str, 453 MSG_ORIG(MSG_PTH_OLDDLP), 454 MSG_ORIG(MSG_PTH_UPDLP), 455 MSG_PTH_UPDLP_SIZE); 456 } 457 #endif 458 if (addlib(crle, &crle->c_edlibpath, str) != 0) 459 return (INSCFG_RET_FAIL); 460 } else { 461 (void) printf(MSG_INTL(MSG_DMP_DLIBPTH), 462 MSG_ORIG(MSG_STR_ELF), str); 463 464 (void) snprintf(_cmd, PATH_MAX, 465 MSG_ORIG(MSG_CMD_EDLIB), str); 466 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 467 if (list_append(&cmdline, cmd) == 0) 468 return (INSCFG_RET_FAIL); 469 } 470 } else { 471 if (crle->c_flags & CRLE_UPDATE) { 472 if (crle->c_flags & CRLE_EDLIB) { 473 /* 474 * If we've been asked to update a configuration 475 * file, and no existing default ELF search 476 * path exists, but the user is going to add new 477 * entries, fabricate the system defaults so 478 * that the users get added to them. 479 */ 480 if (fablib(crle, CRLE_EDLIB) != 0) 481 return (INSCFG_RET_FAIL); 482 } 483 } else { 484 /* 485 * Indicate any system default. 486 */ 487 #if M_CLASS == ELFCLASS64 488 #ifndef SGS_PRE_UNIFIED_PROCESS 489 (void) printf(MSG_INTL(MSG_DEF_NEWDLP_64)); 490 #else 491 (void) printf(MSG_INTL(MSG_DEF_OLDDLP_64)); 492 #endif 493 #else 494 #ifndef SGS_PRE_UNIFIED_PROCESS 495 (void) printf(MSG_INTL(MSG_DEF_NEWDLP)); 496 #else 497 (void) printf(MSG_INTL(MSG_DEF_OLDDLP)); 498 #endif 499 #endif 500 } 501 } 502 503 if (head->ch_eslibpath) { 504 const char *str; 505 506 str = (const char *)(head->ch_eslibpath + addr); 507 508 if (crle->c_flags & CRLE_UPDATE) { 509 crle->c_flags &= ~CRLE_AOUT; 510 511 #ifndef SGS_PRE_UNIFIED_PROCESS 512 if ((head->ch_cnflags & RTC_HDR_UPM) == 0) { 513 if (head->ch_cnflags & RTC_HDR_64) 514 str = conv_config_upm(str, 515 MSG_ORIG(MSG_PTH_OLDTD_64), 516 MSG_ORIG(MSG_PTH_UPTD_64), 517 MSG_PTH_UPTD_64_SIZE); 518 else 519 str = conv_config_upm(str, 520 MSG_ORIG(MSG_PTH_OLDTD), 521 MSG_ORIG(MSG_PTH_UPTD), 522 MSG_PTH_UPTD_SIZE); 523 } 524 #endif 525 if (addlib(crle, &crle->c_eslibpath, str) != 0) 526 return (INSCFG_RET_FAIL); 527 } else { 528 (void) printf(MSG_INTL(MSG_DMP_TLIBPTH), 529 MSG_ORIG(MSG_STR_ELF), str); 530 531 (void) snprintf(_cmd, PATH_MAX, 532 MSG_ORIG(MSG_CMD_ESLIB), str); 533 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 534 if (list_append(&cmdline, cmd) == 0) 535 return (INSCFG_RET_FAIL); 536 } 537 } else { 538 if (crle->c_flags & CRLE_UPDATE) { 539 if (crle->c_flags & CRLE_ESLIB) { 540 /* 541 * If we've been asked to update a configuration 542 * file, and no existing default ELF secure 543 * path exists, but the user is going to add new 544 * entries, fabricate the system defaults so 545 * that the users get added to them. 546 */ 547 if (fablib(crle, CRLE_ESLIB) != 0) 548 return (INSCFG_RET_FAIL); 549 } 550 } else { 551 /* 552 * Indicate any system default. 553 */ 554 #if M_CLASS == ELFCLASS64 555 #ifndef SGS_PRE_UNIFIED_PROCESS 556 (void) printf(MSG_INTL(MSG_DEF_NEWTD_64)); 557 #else 558 (void) printf(MSG_INTL(MSG_DEF_OLDTD_64)); 559 #endif 560 #else 561 #ifndef SGS_PRE_UNIFIED_PROCESS 562 (void) printf(MSG_INTL(MSG_DEF_NEWTD)); 563 #else 564 (void) printf(MSG_INTL(MSG_DEF_OLDTD)); 565 #endif 566 #endif 567 } 568 } 569 570 if (head->ch_adlibpath) { 571 const char *str; 572 573 str = (const char *)(head->ch_adlibpath + addr); 574 575 if (crle->c_flags & CRLE_UPDATE) { 576 crle->c_flags |= CRLE_AOUT; 577 if (addlib(crle, &crle->c_adlibpath, str) != 0) 578 return (INSCFG_RET_FAIL); 579 } else { 580 (void) printf(MSG_INTL(MSG_DMP_DLIBPTH), 581 MSG_ORIG(MSG_STR_AOUT), str); 582 583 (void) snprintf(_cmd, PATH_MAX, 584 MSG_ORIG(MSG_CMD_ADLIB), str); 585 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 586 if (list_append(&cmdline, cmd) == 0) 587 return (INSCFG_RET_FAIL); 588 } 589 } else { 590 if (crle->c_flags & CRLE_UPDATE) { 591 if (crle->c_flags & CRLE_ADLIB) { 592 /* 593 * If we've been asked to update a configuration 594 * file, and no existing default AOUT search 595 * path exists, but the user is going to add new 596 * entries, fabricate the system defaults so 597 * that the users get added to them. 598 */ 599 if (fablib(crle, CRLE_ADLIB) != 0) 600 return (INSCFG_RET_FAIL); 601 } 602 } else if (crle->c_flags & CRLE_AOUT) { 603 /* 604 * Indicate any system default. 605 */ 606 (void) printf(MSG_INTL(MSG_DEF_AOUTDLP)); 607 } 608 } 609 610 if (head->ch_aslibpath) { 611 const char *str; 612 613 str = (const char *)(head->ch_aslibpath + addr); 614 615 if (crle->c_flags & CRLE_UPDATE) { 616 crle->c_flags |= CRLE_AOUT; 617 if (addlib(crle, &crle->c_aslibpath, str) != 0) 618 return (INSCFG_RET_FAIL); 619 } else { 620 (void) printf(MSG_INTL(MSG_DMP_TLIBPTH), 621 MSG_ORIG(MSG_STR_AOUT), str); 622 623 (void) snprintf(_cmd, PATH_MAX, 624 MSG_ORIG(MSG_CMD_ASLIB), str); 625 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 626 if (list_append(&cmdline, cmd) == 0) 627 return (INSCFG_RET_FAIL); 628 } 629 } else { 630 if (crle->c_flags & CRLE_UPDATE) { 631 if (crle->c_flags & CRLE_ASLIB) { 632 /* 633 * If we've been asked to update a configuration 634 * file, and no existing default AOUT secure 635 * path exists, but the user is going to add new 636 * entries, fabricate the system defaults so 637 * that the users get added to them. 638 */ 639 if (fablib(crle, CRLE_ASLIB) != 0) 640 return (INSCFG_RET_FAIL); 641 } 642 } else if (crle->c_flags & CRLE_AOUT) { 643 /* 644 * Indicate any system default. 645 */ 646 (void) printf(MSG_INTL(MSG_DEF_AOUTTD)); 647 } 648 } 649 650 /* 651 * Display any environment variables. 652 */ 653 if ((head->ch_version >= RTC_VER_THREE) && head->ch_env) { 654 Rtc_env * envtbl; 655 656 if ((crle->c_flags & CRLE_UPDATE) == 0) 657 (void) printf(MSG_INTL(MSG_ENV_TITLE)); 658 659 for (envtbl = (Rtc_env *)(head->ch_env + addr); 660 envtbl->env_str; envtbl++) { 661 const char *str; 662 663 str = (const char *)(envtbl->env_str + addr); 664 665 if (crle->c_flags & CRLE_UPDATE) { 666 if (addenv(crle, str, 667 (envtbl->env_flags | RTC_ENV_CONFIG)) == 0) 668 return (INSCFG_RET_FAIL); 669 } else { 670 const char *pfmt, *sfmt; 671 672 if (envtbl->env_flags & RTC_ENV_PERMANT) { 673 pfmt = MSG_INTL(MSG_ENV_PRM); 674 sfmt = MSG_ORIG(MSG_CMD_PRMENV); 675 } else { 676 pfmt = MSG_INTL(MSG_ENV_RPL); 677 sfmt = MSG_ORIG(MSG_CMD_RPLENV); 678 } 679 (void) printf(pfmt, str); 680 (void) snprintf(_cmd, PATH_MAX, sfmt, str); 681 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 682 if (list_append(&cmdline, cmd) == 0) 683 return (INSCFG_RET_FAIL); 684 } 685 } 686 } 687 688 /* 689 * Display any filter/filtee associations. 690 */ 691 if ((head->ch_version >= RTC_VER_FOUR) && head->ch_fltr) { 692 if ((crle->c_flags & CRLE_UPDATE) == 0) { 693 Rtc_fltr * fltrtbl; 694 Rtc_flte * fltetbl; 695 696 /* LINTED */ 697 fltrtbl = (Rtc_fltr *) 698 (CAST_PTRINT(char *, head->ch_fltr) + addr); 699 /* LINTED */ 700 fltetbl = (Rtc_flte *) 701 (CAST_PTRINT(char *, head->ch_flte) + addr); 702 703 (void) printf(MSG_INTL(MSG_FLT_TITLE)); 704 705 while (fltrtbl->fr_filter) { 706 Rtc_flte *_fltetbl; 707 708 /* 709 * Print the filter and filtee string pair. 710 */ 711 (void) printf(MSG_INTL(MSG_FLT_FILTER), 712 (strtbl + fltrtbl->fr_filter), 713 (strtbl + fltrtbl->fr_string)); 714 715 /* 716 * Print each filtee. 717 */ 718 /* LINTED */ 719 for (_fltetbl = (Rtc_flte *)((char *)fltetbl + 720 fltrtbl->fr_filtee); _fltetbl->fe_filtee; 721 _fltetbl++) { 722 (void) printf(MSG_INTL(MSG_FLT_FILTEE), 723 (strtbl + _fltetbl->fe_filtee)); 724 } 725 fltrtbl++; 726 } 727 } 728 } 729 730 /* 731 * Display any memory reservations required for any alternative 732 * objects. 733 */ 734 if (head->ch_resbgn && ((crle->c_flags & CRLE_UPDATE) == 0)) 735 (void) printf(MSG_INTL(MSG_DMP_RESV), head->ch_resbgn, 736 head->ch_resend, (head->ch_resend - head->ch_resbgn)); 737 738 /* 739 * If there's no hash table there's nothing else to process. 740 */ 741 if (head->ch_hash == 0) { 742 if ((crle->c_flags & CRLE_UPDATE) == 0) 743 printcmd(crle, head, &cmdline); 744 return (INSCFG_RET_OK); 745 } 746 747 /* 748 * Traverse the directory and filename arrays. 749 */ 750 for (dirtbl = (Rtc_dir *)(head->ch_dir + addr); 751 dirtbl->cd_obj; dirtbl++) { 752 struct stat status; 753 Rtc_obj *dobj; 754 const char *str; 755 756 dobj = (Rtc_obj *)(dirtbl->cd_obj + addr); 757 filetbl = (Rtc_file *)(dirtbl->cd_file + addr); 758 str = strtbl + dobj->co_name; 759 760 /* 761 * Simplify recreation by using any command-line directories. 762 * If we're dealing with a version 1 configuration file use 763 * every directory. 764 */ 765 if ((dobj->co_flags & RTC_OBJ_CMDLINE) || 766 (head->ch_version == RTC_VER_ONE)) { 767 if (crle->c_flags & CRLE_UPDATE) { 768 if (inspect(crle, str, 769 getflags(dobj->co_flags)) != 0) 770 return (INSCFG_RET_FAIL); 771 if ((dobj->co_flags & 772 (RTC_OBJ_NOEXIST | RTC_OBJ_ALTER)) == 773 RTC_OBJ_NOEXIST) 774 continue; 775 } else { 776 /* LINTED */ 777 (void) snprintf(_cmd, PATH_MAX, 778 getformat(dobj->co_flags), str); 779 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 780 if (list_append(&cmdline, cmd) == 0) 781 return (INSCFG_RET_FAIL); 782 } 783 } 784 785 /* 786 * If this isn't an update print the directory name. If the 787 * directory has no entries (possible if the directory is a 788 * symlink to another directory, in which case we record the 789 * real path also), don't bother printing it unless we're in 790 * verbose mode. 791 */ 792 if ((crle->c_flags & CRLE_UPDATE) == 0) { 793 if ((dobj->co_flags & 794 (RTC_OBJ_NOEXIST | RTC_OBJ_ALTER)) == 795 RTC_OBJ_NOEXIST) { 796 (void) printf(MSG_INTL(MSG_DMP_DIR_2), str); 797 continue; 798 } else if (filetbl->cf_obj || 799 (crle->c_flags & CRLE_VERBOSE)) 800 (void) printf(MSG_INTL(MSG_DMP_DIR_1), str); 801 } 802 803 /* 804 * Under verbose mode validate any real directory entry - the 805 * same test will be carried out by ld.so.1. 806 */ 807 if (((crle->c_flags & CRLE_UPDATE) == 0) && 808 (crle->c_flags & CRLE_VERBOSE) && 809 (dobj->co_flags & RTC_OBJ_REALPTH)) { 810 if (stat(str, &status) != 0) { 811 int err = errno; 812 (void) printf(MSG_INTL(MSG_DMP_STAT), str, 813 strerror(err)); 814 } else if (status.st_mtime != dobj->co_info) { 815 (void) printf(MSG_INTL(MSG_DMP_DCMP), str); 816 } 817 } 818 819 for (; filetbl->cf_obj; filetbl++) { 820 Rtc_obj * fobj; 821 Half flags; 822 823 fobj = (Rtc_obj *)(filetbl->cf_obj + addr); 824 str = strtbl + fobj->co_name; 825 flags = fobj->co_flags; 826 827 /* 828 * Only update individual files that were originally 829 * specified on the command-line. Or, if this is a 830 * version 1 configuration file use every file that 831 * isn't part of an all-entries directory. 832 */ 833 if (((flags & RTC_OBJ_CMDLINE) && 834 ((fobj->co_flags & RTC_OBJ_APP) == 0)) || 835 ((head->ch_version == RTC_VER_ONE) && 836 ((dobj->co_flags & RTC_OBJ_ALLENTS) == 0))) { 837 char *alter = 0, altdir[PATH_MAX]; 838 839 /* 840 * Determine whether this file requires an 841 * alternative, and if so, and we haven't 842 * already an alternative in affect, create one. 843 */ 844 if (fobj->co_flags & RTC_OBJ_ALTER) { 845 alter = (char *)(strtbl + 846 fobj->co_alter); 847 (void) strcpy(altdir, alter); 848 alter = strrchr(altdir, '/'); 849 *alter = '\0'; 850 851 if ((objdir == 0) || 852 (strcmp(objdir, altdir) != 0)) { 853 (void) strcpy(_objdir, altdir); 854 crle->c_objdir = alter = 855 objdir = _objdir; 856 } else 857 alter = 0; 858 } 859 860 if (crle->c_flags & CRLE_UPDATE) { 861 if (inspect(crle, str, 862 getflags(flags)) != 0) 863 return (INSCFG_RET_FAIL); 864 continue; 865 } 866 867 if (alter) { 868 (void) snprintf(_cmd, PATH_MAX, 869 MSG_ORIG(MSG_CMD_OUTPUT), 870 crle->c_objdir); 871 cmd = strcpy(alloca(strlen(_cmd) + 1), 872 _cmd); 873 if (list_append(&cmdline, cmd) == 0) 874 return (INSCFG_RET_FAIL); 875 } 876 877 /* LINTED */ 878 (void) snprintf(_cmd, PATH_MAX, 879 getformat(flags), str); 880 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 881 if (list_append(&cmdline, cmd) == 0) 882 return (INSCFG_RET_FAIL); 883 } 884 885 if (crle->c_flags & CRLE_UPDATE) 886 continue; 887 888 /* 889 * Although we record both full pathnames and their 890 * simple filenames (basename), only print the simple 891 * names unless we're under verbose mode. 892 */ 893 if ((strchr(str, '/') == 0) || 894 (crle->c_flags & CRLE_VERBOSE)) { 895 if (fobj->co_flags & RTC_OBJ_ALTER) 896 (void) printf(MSG_INTL(MSG_DMP_FILE_2), 897 str, (strtbl + fobj->co_alter)); 898 else 899 (void) printf(MSG_INTL(MSG_DMP_FILE_1), 900 str); 901 } 902 903 /* 904 * Under verbose mode validate any real file entry - the 905 * same test will be carried out by ld.so.1. 906 */ 907 if ((crle->c_flags & CRLE_VERBOSE) && 908 (fobj->co_flags & RTC_OBJ_REALPTH)) { 909 if (stat(str, &status) != 0) { 910 int err = errno; 911 (void) printf(MSG_INTL(MSG_DMP_STAT), 912 str, strerror(err)); 913 } else if (status.st_size != fobj->co_info) { 914 (void) printf(MSG_INTL(MSG_DMP_FCMP), 915 str); 916 } 917 } 918 } 919 } 920 921 if ((crle->c_flags & CRLE_UPDATE) == 0) 922 printcmd(crle, head, &cmdline); 923 924 if ((crle->c_flags & CRLE_VERBOSE) == 0) 925 return (INSCFG_RET_OK); 926 927 /* 928 * If we've in verbose mode scan the hash list. 929 */ 930 /* LINTED */ 931 hash = (Word *)(CAST_PTRINT(char *, head->ch_hash) + addr); 932 bkts = hash[0]; 933 chain = &hash[2 + bkts]; 934 hash += 2; 935 936 (void) printf(MSG_INTL(MSG_DMP_HASH)); 937 938 /* 939 * Scan the hash buckets looking for valid entries. 940 */ 941 for (ndx = 0; ndx < bkts; ndx++, hash++) { 942 Rtc_obj *obj; 943 const char *str; 944 Word _ndx; 945 946 if (*hash == 0) 947 continue; 948 949 obj = objtbl + *hash; 950 str = strtbl + obj->co_name; 951 952 (void) printf(MSG_INTL(MSG_DMP_HASHENT_1), obj->co_id, ndx, 953 str, conv_config_obj(obj->co_flags)); 954 955 /* 956 * Determine whether there are other objects chained to this 957 * bucket. 958 */ 959 for (_ndx = chain[*hash]; _ndx; _ndx = chain[_ndx]) { 960 obj = objtbl + _ndx; 961 str = strtbl + obj->co_name; 962 963 (void) printf(MSG_INTL(MSG_DMP_HASHENT_2), obj->co_id, 964 str, conv_config_obj(obj->co_flags)); 965 } 966 } 967 (void) printf(MSG_ORIG(MSG_STR_NL)); 968 969 return (INSCFG_RET_OK); 970 } 971 972 973 INSCFG_RET 974 inspectconfig(Crle_desc * crle) 975 { 976 INSCFG_RET error; 977 int fd; 978 Addr addr; 979 struct stat status; 980 const char *caller = crle->c_name, *file = crle->c_confil; 981 982 /* 983 * Open the configuration file, determine its size and map it in. 984 */ 985 if ((fd = open(file, O_RDONLY, 0)) == -1) { 986 int err = errno; 987 988 if ((err == ENOENT)) { 989 /* 990 * To allow an update (-u) from scratch, fabricate any 991 * default search and secure paths that the user 992 * intends to add to. 993 */ 994 if (crle->c_flags & CRLE_UPDATE) { 995 if (crle->c_flags & CRLE_EDLIB) { 996 if (fablib(crle, CRLE_EDLIB)) 997 return (1); 998 } 999 if (crle->c_flags & CRLE_ESLIB) { 1000 if (fablib(crle, CRLE_ESLIB)) 1001 return (1); 1002 } 1003 if (crle->c_flags & CRLE_ADLIB) { 1004 if (fablib(crle, CRLE_ADLIB)) 1005 return (1); 1006 } 1007 if (crle->c_flags & CRLE_ASLIB) { 1008 if (fablib(crle, CRLE_ASLIB)) 1009 return (1); 1010 } 1011 return (0); 1012 1013 } else if (crle->c_flags & CRLE_CONFDEF) { 1014 const char *fmt1, *fmt2; 1015 1016 /* 1017 * Otherwise if the user is inspecting a default 1018 * configuration file that doesn't exist inform 1019 * them and display the ELF defaults. 1020 */ 1021 (void) printf(MSG_INTL(MSG_DEF_NOCONF), file); 1022 1023 if (crle->c_flags & CRLE_AOUT) { 1024 fmt1 = MSG_INTL(MSG_DEF_AOUTDLP); 1025 fmt2 = MSG_INTL(MSG_DEF_AOUTTD); 1026 } else { 1027 #if M_CLASS == ELFCLASS64 1028 #ifndef SGS_PRE_UNIFIED_PROCESS 1029 fmt1 = MSG_INTL(MSG_DEF_NEWDLP_64); 1030 fmt2 = MSG_INTL(MSG_DEF_NEWTD_64); 1031 #else 1032 fmt1 = MSG_INTL(MSG_DEF_OLDDLP_64); 1033 fmt2 = MSG_INTL(MSG_DEF_OLDTD_64); 1034 #endif 1035 #else 1036 #ifndef SGS_PRE_UNIFIED_PROCESS 1037 fmt1 = MSG_INTL(MSG_DEF_NEWDLP); 1038 fmt2 = MSG_INTL(MSG_DEF_NEWTD); 1039 #else 1040 fmt1 = MSG_INTL(MSG_DEF_OLDDLP); 1041 fmt2 = MSG_INTL(MSG_DEF_OLDTD); 1042 #endif 1043 #endif 1044 } 1045 (void) printf(fmt1); 1046 (void) printf(fmt2); 1047 1048 return (0); 1049 } 1050 } 1051 1052 /* 1053 * Otherwise there's an error condition in accessing the file. 1054 */ 1055 (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), caller, file, 1056 strerror(err)); 1057 1058 return (1); 1059 } 1060 1061 (void) fstat(fd, &status); 1062 if (status.st_size < sizeof (Rtc_head)) { 1063 (void) close(fd); 1064 (void) fprintf(stderr, MSG_INTL(MSG_COR_TRUNC), caller, file); 1065 return (1); 1066 } 1067 if ((addr = (Addr)mmap(0, status.st_size, PROT_READ, MAP_SHARED, 1068 fd, 0)) == (Addr)MAP_FAILED) { 1069 int err = errno; 1070 (void) fprintf(stderr, MSG_INTL(MSG_SYS_MMAP), caller, file, 1071 strerror(err)); 1072 (void) close(fd); 1073 return (1); 1074 } 1075 (void) close(fd); 1076 1077 /* 1078 * Print the contents of the configuration file. 1079 */ 1080 error = scanconfig(crle, addr); 1081 1082 (void) munmap((void *)addr, status.st_size); 1083 return (error); 1084 } 1085