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 2007 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 /*ARGSUSED2*/ 211 static INSCFG_RET 212 scanconfig(Crle_desc * crle, Addr addr, int c_class) 213 { 214 Conv_inv_buf_t inv_buf1, inv_buf2, inv_buf3, inv_buf4; 215 Conv_dl_flag_buf_t dl_flag_buf; 216 Rtc_id *id; 217 Rtc_head *head; 218 Rtc_dir *dirtbl; 219 Rtc_file *filetbl; 220 Rtc_obj *objtbl, * obj; 221 Word *hash, * chain; 222 const char *strtbl; 223 int ndx, bkts; 224 List cmdline = { 0 }; 225 char _cmd[PATH_MAX], * cmd; 226 char _objdir[PATH_MAX], * objdir = 0; 227 228 229 /* 230 * If there is an Rtc_id present, the Rtc_head follows it. 231 * Otherwise, it is at the top. 232 */ 233 if (RTC_ID_TEST(addr)) { 234 id = (Rtc_id *) addr; 235 addr += sizeof (*id); /* Rtc_head follows */ 236 } else { 237 id = NULL; 238 /* 239 * When updating an existing config file that is lacking 240 * the Rtc_id block, don't put one into the resulting file. 241 */ 242 crle->c_flags &= ~CRLE_ADDID; 243 } 244 head = (Rtc_head *) addr; 245 246 247 /* 248 * The rest of the configuration file can only be examined by 249 * a program of the same ELFCLASS, byte order, and hardware 250 * architecture as the one that created it. 251 */ 252 #ifdef _ELF64 253 /* 64-bit program with an existing 32-bit file? Abort. */ 254 if (!(head->ch_cnflags & RTC_HDR_64)) { 255 (void) fprintf(stderr, MSG_INTL(MSG_ARG_CLASS), 256 crle->c_name, crle->c_confil); 257 return (INSCFG_RET_FAIL); 258 } 259 #else 260 /* 32-bit program with an existing 64-bit file? Restart. */ 261 if (head->ch_cnflags & RTC_HDR_64) 262 return (INSCFG_RET_NEED64); 263 264 /* 265 * 32-bit program with an existing 32-bit file, but the 266 * user specified the -64 option? Abort 267 */ 268 if (c_class != ELFCLASS32) { 269 (void) fprintf(stderr, MSG_INTL(MSG_ARG_CLASS), 270 crle->c_name, crle->c_confil); 271 return (INSCFG_RET_FAIL); 272 } 273 #endif 274 /* 275 * Now that the ELFCLASS has been settled, ensure that the 276 * byte order and hardware match. Unlike ELFCLASS, where restarting 277 * the other version is an option, we cannot work around a mismatch 278 * of these attributes. 279 */ 280 if (id) { /* Rtc_id is present */ 281 /* 282 * Was the file produced by compatible hardware? 283 * ELFCLASS doesn't matter here, because we can 284 * adjust for that, but byte order and machine type do. 285 */ 286 if ((id->id_data != M_DATA) || (id->id_machine != M_MACH)) { 287 (void) fprintf(stderr, MSG_INTL(MSG_ARG_WRONGARCH), 288 crle->c_name, crle->c_confil, 289 conv_ehdr_data(id->id_data, CONV_FMT_ALTFILE, 290 &inv_buf1), 291 conv_ehdr_mach(id->id_machine, CONV_FMT_ALTFILE, 292 &inv_buf2), 293 conv_ehdr_data(M_DATA, CONV_FMT_ALTFILE, &inv_buf3), 294 conv_ehdr_mach(M_MACH, CONV_FMT_ALTFILE, 295 &inv_buf4)); 296 return (INSCFG_RET_FAIL); 297 } 298 } 299 300 301 /* LINTED */ 302 objtbl = (Rtc_obj *)(CAST_PTRINT(char *, head->ch_obj) + addr); 303 strtbl = (const char *)(CAST_PTRINT(char *, head->ch_str) + addr); 304 305 /* 306 * If the configuration file has a version higher than we 307 * recognise, we face two issues: 308 * (1) Updates are not possible because we have no 309 * way to recognise or propagate the new features. 310 * This has to be a fatal error. 311 * (2) Printing has the risk that we may have been 312 * handed something other than a real config file, as 313 * well as the fact that we can't display the information 314 * for the new features. So, we print a warning, but 315 * continue on to do the best we can with it. 316 */ 317 if (head->ch_version > RTC_VER_CURRENT) { 318 if (crle->c_flags & CRLE_UPDATE) { 319 (void) fprintf(stderr, MSG_INTL(MSG_ARG_UPDATEVER), 320 crle->c_name, crle->c_confil, 321 (int)head->ch_version, RTC_VER_CURRENT); 322 return (INSCFG_RET_FAIL); 323 } else { 324 (void) fprintf(stderr, MSG_INTL(MSG_ARG_PRINTVER), 325 crle->c_name, crle->c_confil, 326 (int)head->ch_version, RTC_VER_CURRENT); 327 } 328 } 329 330 /* 331 * If this is a version 1 configuration file we can't generate accurate 332 * update information, or the command-line used to create the file. 333 */ 334 if (head->ch_version == RTC_VER_ONE) { 335 (void) printf(MSG_INTL(MSG_ARG_UPDATE), crle->c_name, 336 crle->c_confil, (int)head->ch_version); 337 } 338 339 340 if (!(crle->c_flags & CRLE_UPDATE) && (head->ch_cnflags & RTC_HDR_64)) { 341 /* 342 * Construct the original command line argument. 343 */ 344 cmd = strcpy(alloca(MSG_CMD_64_SIZE + 1), MSG_ORIG(MSG_CMD_64)); 345 if (list_append(&cmdline, cmd) == 0) 346 return (INSCFG_RET_FAIL); 347 } 348 349 350 /* 351 * Start analyzing the configuration files header information. 352 */ 353 if ((crle->c_flags & CRLE_UPDATE) == 0) { 354 const char *fmt; 355 356 if (head->ch_dlflags) 357 fmt = conv_dl_flag(head->ch_dlflags, 0, &dl_flag_buf); 358 else 359 fmt = MSG_ORIG(MSG_STR_EMPTY); 360 361 (void) printf(MSG_INTL(MSG_DMP_HEAD), (int)head->ch_version, 362 crle->c_confil, fmt); 363 364 /* 365 * If the file has an id block, show the information 366 */ 367 if (id) 368 (void) printf(MSG_INTL(MSG_DMP_PLATFORM), 369 conv_ehdr_class(id->id_class, CONV_FMT_ALTFILE, 370 &inv_buf1), 371 conv_ehdr_data(id->id_data, CONV_FMT_ALTFILE, 372 &inv_buf2), 373 conv_ehdr_mach(id->id_machine, CONV_FMT_ALTFILE, 374 &inv_buf3)); 375 376 /* 377 * Construct the original command line argument. 378 */ 379 (void) snprintf(_cmd, PATH_MAX, MSG_ORIG(MSG_CMD_CONF), 380 crle->c_confil); 381 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 382 if (list_append(&cmdline, cmd) == 0) 383 return (INSCFG_RET_FAIL); 384 385 /* 386 * Construct any -f usage. 387 */ 388 if (head->ch_dlflags && 389 (head->ch_dlflags != RTLD_REL_RELATIVE)) { 390 (void) snprintf(_cmd, PATH_MAX, MSG_ORIG(MSG_CMD_FLAGS), 391 conv_dl_flag(head->ch_dlflags, CONV_FMT_ALTCRLE, 392 &dl_flag_buf)); 393 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 394 if (list_append(&cmdline, cmd) == 0) 395 return (INSCFG_RET_FAIL); 396 } 397 } else { 398 /* 399 * Establish any -f usage. 400 */ 401 if (head->ch_dlflags && 402 (head->ch_dlflags != RTLD_REL_RELATIVE)) 403 crle->c_dlflags = head->ch_dlflags; 404 } 405 406 407 /* 408 * Determine if this configuration file is only applicable to a specific 409 * application. 410 */ 411 if (head->ch_app) { 412 char *alter; 413 414 obj = (Rtc_obj *)(head->ch_app + addr); 415 416 /* 417 * Determine the output directory for the files 418 * alternative name. 419 */ 420 alter = (char *)(strtbl + obj->co_alter); 421 (void) strcpy(_objdir, alter); 422 alter = strrchr(_objdir, '/'); 423 *alter = '\0'; 424 425 crle->c_objdir = objdir = _objdir; 426 427 if (crle->c_flags & CRLE_UPDATE) { 428 if (inspect(crle, (strtbl + obj->co_name), 429 (RTC_OBJ_DUMP | RTC_OBJ_ALTER | 430 RTC_OBJ_GROUP | RTC_OBJ_CMDLINE)) != 0) 431 return (INSCFG_RET_FAIL); 432 } else { 433 (void) printf(MSG_INTL(MSG_DMP_APP), 434 (strtbl + obj->co_alter), (strtbl + obj->co_name)); 435 436 /* 437 * Construct the original command line arguments. 438 */ 439 (void) snprintf(_cmd, PATH_MAX, 440 MSG_ORIG(MSG_CMD_OUTPUT), crle->c_objdir); 441 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 442 if (list_append(&cmdline, cmd) == 0) 443 return (INSCFG_RET_FAIL); 444 445 (void) snprintf(_cmd, PATH_MAX, 446 MSG_ORIG(MSG_CMD_DUMPGRP), (strtbl + obj->co_name)); 447 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 448 if (list_append(&cmdline, cmd) == 0) 449 return (INSCFG_RET_FAIL); 450 } 451 } 452 453 /* 454 * Analyze any alternative library path and trusted directory entries. 455 */ 456 if (head->ch_edlibpath) { 457 const char *str; 458 459 str = (const char *)(head->ch_edlibpath + addr); 460 461 if (crle->c_flags & CRLE_UPDATE) { 462 crle->c_flags &= ~CRLE_AOUT; 463 464 #ifndef SGS_PRE_UNIFIED_PROCESS 465 if ((head->ch_cnflags & RTC_HDR_UPM) == 0) { 466 if (head->ch_cnflags & RTC_HDR_64) 467 str = conv_config_upm(str, 468 MSG_ORIG(MSG_PTH_OLDDLP_64), 469 MSG_ORIG(MSG_PTH_UPDLP_64), 470 MSG_PTH_UPDLP_64_SIZE); 471 else 472 str = conv_config_upm(str, 473 MSG_ORIG(MSG_PTH_OLDDLP), 474 MSG_ORIG(MSG_PTH_UPDLP), 475 MSG_PTH_UPDLP_SIZE); 476 } 477 #endif 478 if (addlib(crle, &crle->c_edlibpath, str) != 0) 479 return (INSCFG_RET_FAIL); 480 } else { 481 (void) printf(MSG_INTL(MSG_DMP_DLIBPTH), 482 MSG_ORIG(MSG_STR_ELF), str); 483 484 (void) snprintf(_cmd, PATH_MAX, 485 MSG_ORIG(MSG_CMD_EDLIB), str); 486 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 487 if (list_append(&cmdline, cmd) == 0) 488 return (INSCFG_RET_FAIL); 489 } 490 } else { 491 if (crle->c_flags & CRLE_UPDATE) { 492 if (crle->c_flags & CRLE_EDLIB) { 493 /* 494 * If we've been asked to update a configuration 495 * file, and no existing default ELF search 496 * path exists, but the user is going to add new 497 * entries, fabricate the system defaults so 498 * that the users get added to them. 499 */ 500 if (fablib(crle, CRLE_EDLIB) != 0) 501 return (INSCFG_RET_FAIL); 502 } 503 } else { 504 /* 505 * Indicate any system default. 506 */ 507 #if M_CLASS == ELFCLASS64 508 #ifndef SGS_PRE_UNIFIED_PROCESS 509 (void) printf(MSG_INTL(MSG_DEF_NEWDLP_64)); 510 #else 511 (void) printf(MSG_INTL(MSG_DEF_OLDDLP_64)); 512 #endif 513 #else 514 #ifndef SGS_PRE_UNIFIED_PROCESS 515 (void) printf(MSG_INTL(MSG_DEF_NEWDLP)); 516 #else 517 (void) printf(MSG_INTL(MSG_DEF_OLDDLP)); 518 #endif 519 #endif 520 } 521 } 522 523 if (head->ch_eslibpath) { 524 const char *str; 525 526 str = (const char *)(head->ch_eslibpath + addr); 527 528 if (crle->c_flags & CRLE_UPDATE) { 529 crle->c_flags &= ~CRLE_AOUT; 530 531 #ifndef SGS_PRE_UNIFIED_PROCESS 532 if ((head->ch_cnflags & RTC_HDR_UPM) == 0) { 533 if (head->ch_cnflags & RTC_HDR_64) 534 str = conv_config_upm(str, 535 MSG_ORIG(MSG_PTH_OLDTD_64), 536 MSG_ORIG(MSG_PTH_UPTD_64), 537 MSG_PTH_UPTD_64_SIZE); 538 else 539 str = conv_config_upm(str, 540 MSG_ORIG(MSG_PTH_OLDTD), 541 MSG_ORIG(MSG_PTH_UPTD), 542 MSG_PTH_UPTD_SIZE); 543 } 544 #endif 545 if (addlib(crle, &crle->c_eslibpath, str) != 0) 546 return (INSCFG_RET_FAIL); 547 } else { 548 (void) printf(MSG_INTL(MSG_DMP_TLIBPTH), 549 MSG_ORIG(MSG_STR_ELF), str); 550 551 (void) snprintf(_cmd, PATH_MAX, 552 MSG_ORIG(MSG_CMD_ESLIB), str); 553 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 554 if (list_append(&cmdline, cmd) == 0) 555 return (INSCFG_RET_FAIL); 556 } 557 } else { 558 if (crle->c_flags & CRLE_UPDATE) { 559 if (crle->c_flags & CRLE_ESLIB) { 560 /* 561 * If we've been asked to update a configuration 562 * file, and no existing default ELF secure 563 * path exists, but the user is going to add new 564 * entries, fabricate the system defaults so 565 * that the users get added to them. 566 */ 567 if (fablib(crle, CRLE_ESLIB) != 0) 568 return (INSCFG_RET_FAIL); 569 } 570 } else { 571 /* 572 * Indicate any system default. 573 */ 574 #if M_CLASS == ELFCLASS64 575 #ifndef SGS_PRE_UNIFIED_PROCESS 576 (void) printf(MSG_INTL(MSG_DEF_NEWTD_64)); 577 #else 578 (void) printf(MSG_INTL(MSG_DEF_OLDTD_64)); 579 #endif 580 #else 581 #ifndef SGS_PRE_UNIFIED_PROCESS 582 (void) printf(MSG_INTL(MSG_DEF_NEWTD)); 583 #else 584 (void) printf(MSG_INTL(MSG_DEF_OLDTD)); 585 #endif 586 #endif 587 } 588 } 589 590 if (head->ch_adlibpath) { 591 const char *str; 592 593 str = (const char *)(head->ch_adlibpath + addr); 594 595 if (crle->c_flags & CRLE_UPDATE) { 596 crle->c_flags |= CRLE_AOUT; 597 if (addlib(crle, &crle->c_adlibpath, str) != 0) 598 return (INSCFG_RET_FAIL); 599 } else { 600 (void) printf(MSG_INTL(MSG_DMP_DLIBPTH), 601 MSG_ORIG(MSG_STR_AOUT), str); 602 603 (void) snprintf(_cmd, PATH_MAX, 604 MSG_ORIG(MSG_CMD_ADLIB), str); 605 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 606 if (list_append(&cmdline, cmd) == 0) 607 return (INSCFG_RET_FAIL); 608 } 609 } else { 610 if (crle->c_flags & CRLE_UPDATE) { 611 if (crle->c_flags & CRLE_ADLIB) { 612 /* 613 * If we've been asked to update a configuration 614 * file, and no existing default AOUT search 615 * path exists, but the user is going to add new 616 * entries, fabricate the system defaults so 617 * that the users get added to them. 618 */ 619 if (fablib(crle, CRLE_ADLIB) != 0) 620 return (INSCFG_RET_FAIL); 621 } 622 } else if (crle->c_flags & CRLE_AOUT) { 623 /* 624 * Indicate any system default. 625 */ 626 (void) printf(MSG_INTL(MSG_DEF_AOUTDLP)); 627 } 628 } 629 630 if (head->ch_aslibpath) { 631 const char *str; 632 633 str = (const char *)(head->ch_aslibpath + addr); 634 635 if (crle->c_flags & CRLE_UPDATE) { 636 crle->c_flags |= CRLE_AOUT; 637 if (addlib(crle, &crle->c_aslibpath, str) != 0) 638 return (INSCFG_RET_FAIL); 639 } else { 640 (void) printf(MSG_INTL(MSG_DMP_TLIBPTH), 641 MSG_ORIG(MSG_STR_AOUT), str); 642 643 (void) snprintf(_cmd, PATH_MAX, 644 MSG_ORIG(MSG_CMD_ASLIB), str); 645 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 646 if (list_append(&cmdline, cmd) == 0) 647 return (INSCFG_RET_FAIL); 648 } 649 } else { 650 if (crle->c_flags & CRLE_UPDATE) { 651 if (crle->c_flags & CRLE_ASLIB) { 652 /* 653 * If we've been asked to update a configuration 654 * file, and no existing default AOUT secure 655 * path exists, but the user is going to add new 656 * entries, fabricate the system defaults so 657 * that the users get added to them. 658 */ 659 if (fablib(crle, CRLE_ASLIB) != 0) 660 return (INSCFG_RET_FAIL); 661 } 662 } else if (crle->c_flags & CRLE_AOUT) { 663 /* 664 * Indicate any system default. 665 */ 666 (void) printf(MSG_INTL(MSG_DEF_AOUTTD)); 667 } 668 } 669 670 /* 671 * Display any environment variables. 672 */ 673 if ((head->ch_version >= RTC_VER_THREE) && head->ch_env) { 674 Rtc_env * envtbl; 675 676 if ((crle->c_flags & CRLE_UPDATE) == 0) 677 (void) printf(MSG_INTL(MSG_ENV_TITLE)); 678 679 for (envtbl = (Rtc_env *)(head->ch_env + addr); 680 envtbl->env_str; envtbl++) { 681 const char *str; 682 683 str = (const char *)(envtbl->env_str + addr); 684 685 if (crle->c_flags & CRLE_UPDATE) { 686 if (addenv(crle, str, 687 (envtbl->env_flags | RTC_ENV_CONFIG)) == 0) 688 return (INSCFG_RET_FAIL); 689 } else { 690 const char *pfmt, *sfmt; 691 692 if (envtbl->env_flags & RTC_ENV_PERMANT) { 693 pfmt = MSG_INTL(MSG_ENV_PRM); 694 sfmt = MSG_ORIG(MSG_CMD_PRMENV); 695 } else { 696 pfmt = MSG_INTL(MSG_ENV_RPL); 697 sfmt = MSG_ORIG(MSG_CMD_RPLENV); 698 } 699 (void) printf(pfmt, str); 700 (void) snprintf(_cmd, PATH_MAX, sfmt, str); 701 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 702 if (list_append(&cmdline, cmd) == 0) 703 return (INSCFG_RET_FAIL); 704 } 705 } 706 } 707 708 /* 709 * Display any filter/filtee associations. 710 */ 711 if ((head->ch_version >= RTC_VER_FOUR) && head->ch_fltr) { 712 if ((crle->c_flags & CRLE_UPDATE) == 0) { 713 Rtc_fltr * fltrtbl; 714 Rtc_flte * fltetbl; 715 716 /* LINTED */ 717 fltrtbl = (Rtc_fltr *) 718 (CAST_PTRINT(char *, head->ch_fltr) + addr); 719 /* LINTED */ 720 fltetbl = (Rtc_flte *) 721 (CAST_PTRINT(char *, head->ch_flte) + addr); 722 723 (void) printf(MSG_INTL(MSG_FLT_TITLE)); 724 725 while (fltrtbl->fr_filter) { 726 Rtc_flte *_fltetbl; 727 728 /* 729 * Print the filter and filtee string pair. 730 */ 731 (void) printf(MSG_INTL(MSG_FLT_FILTER), 732 (strtbl + fltrtbl->fr_filter), 733 (strtbl + fltrtbl->fr_string)); 734 735 /* 736 * Print each filtee. 737 */ 738 /* LINTED */ 739 for (_fltetbl = (Rtc_flte *)((char *)fltetbl + 740 fltrtbl->fr_filtee); _fltetbl->fe_filtee; 741 _fltetbl++) { 742 (void) printf(MSG_INTL(MSG_FLT_FILTEE), 743 (strtbl + _fltetbl->fe_filtee)); 744 } 745 fltrtbl++; 746 } 747 } 748 } 749 750 /* 751 * Display any memory reservations required for any alternative 752 * objects. 753 */ 754 if (head->ch_resbgn && ((crle->c_flags & CRLE_UPDATE) == 0)) 755 (void) printf(MSG_INTL(MSG_DMP_RESV), 756 (u_longlong_t)head->ch_resbgn, 757 (u_longlong_t)head->ch_resend, 758 (u_longlong_t)(head->ch_resend - head->ch_resbgn)); 759 760 /* 761 * If there's no hash table there's nothing else to process. 762 */ 763 if (head->ch_hash == 0) { 764 if ((crle->c_flags & CRLE_UPDATE) == 0) 765 printcmd(crle, head, &cmdline); 766 return (INSCFG_RET_OK); 767 } 768 769 /* 770 * Traverse the directory and filename arrays. 771 */ 772 for (dirtbl = (Rtc_dir *)(head->ch_dir + addr); 773 dirtbl->cd_obj; dirtbl++) { 774 struct stat status; 775 Rtc_obj *dobj; 776 const char *str; 777 778 dobj = (Rtc_obj *)(dirtbl->cd_obj + addr); 779 filetbl = (Rtc_file *)(dirtbl->cd_file + addr); 780 str = strtbl + dobj->co_name; 781 782 /* 783 * Simplify recreation by using any command-line directories. 784 * If we're dealing with a version 1 configuration file use 785 * every directory. 786 */ 787 if ((dobj->co_flags & RTC_OBJ_CMDLINE) || 788 (head->ch_version == RTC_VER_ONE)) { 789 if (crle->c_flags & CRLE_UPDATE) { 790 if (inspect(crle, str, 791 getflags(dobj->co_flags)) != 0) 792 return (INSCFG_RET_FAIL); 793 if ((dobj->co_flags & 794 (RTC_OBJ_NOEXIST | RTC_OBJ_ALTER)) == 795 RTC_OBJ_NOEXIST) 796 continue; 797 } else { 798 /* LINTED */ 799 (void) snprintf(_cmd, PATH_MAX, 800 getformat(dobj->co_flags), str); 801 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 802 if (list_append(&cmdline, cmd) == 0) 803 return (INSCFG_RET_FAIL); 804 } 805 } 806 807 /* 808 * If this isn't an update print the directory name. If the 809 * directory has no entries (possible if the directory is a 810 * symlink to another directory, in which case we record the 811 * real path also), don't bother printing it unless we're in 812 * verbose mode. 813 */ 814 if ((crle->c_flags & CRLE_UPDATE) == 0) { 815 if ((dobj->co_flags & 816 (RTC_OBJ_NOEXIST | RTC_OBJ_ALTER)) == 817 RTC_OBJ_NOEXIST) { 818 (void) printf(MSG_INTL(MSG_DMP_DIR_2), str); 819 continue; 820 } else if (filetbl->cf_obj || 821 (crle->c_flags & CRLE_VERBOSE)) 822 (void) printf(MSG_INTL(MSG_DMP_DIR_1), str); 823 } 824 825 /* 826 * Under verbose mode validate any real directory entry - the 827 * same test will be carried out by ld.so.1. 828 */ 829 if (((crle->c_flags & CRLE_UPDATE) == 0) && 830 (crle->c_flags & CRLE_VERBOSE) && 831 (dobj->co_flags & RTC_OBJ_REALPTH)) { 832 if (stat(str, &status) != 0) { 833 int err = errno; 834 (void) printf(MSG_INTL(MSG_DMP_STAT), str, 835 strerror(err)); 836 } else if (status.st_mtime != dobj->co_info) { 837 (void) printf(MSG_INTL(MSG_DMP_DCMP), str); 838 } 839 } 840 841 for (; filetbl->cf_obj; filetbl++) { 842 Rtc_obj * fobj; 843 Half flags; 844 845 fobj = (Rtc_obj *)(filetbl->cf_obj + addr); 846 str = strtbl + fobj->co_name; 847 flags = fobj->co_flags; 848 849 /* 850 * Only update individual files that were originally 851 * specified on the command-line. Or, if this is a 852 * version 1 configuration file use every file that 853 * isn't part of an all-entries directory. 854 */ 855 if (((flags & RTC_OBJ_CMDLINE) && 856 ((fobj->co_flags & RTC_OBJ_APP) == 0)) || 857 ((head->ch_version == RTC_VER_ONE) && 858 ((dobj->co_flags & RTC_OBJ_ALLENTS) == 0))) { 859 char *alter = 0, altdir[PATH_MAX]; 860 861 /* 862 * Determine whether this file requires an 863 * alternative, and if so, and we haven't 864 * already an alternative in affect, create one. 865 */ 866 if (fobj->co_flags & RTC_OBJ_ALTER) { 867 alter = (char *)(strtbl + 868 fobj->co_alter); 869 (void) strcpy(altdir, alter); 870 alter = strrchr(altdir, '/'); 871 *alter = '\0'; 872 873 if ((objdir == 0) || 874 (strcmp(objdir, altdir) != 0)) { 875 (void) strcpy(_objdir, altdir); 876 crle->c_objdir = alter = 877 objdir = _objdir; 878 } else 879 alter = 0; 880 } 881 882 if (crle->c_flags & CRLE_UPDATE) { 883 if (inspect(crle, str, 884 getflags(flags)) != 0) 885 return (INSCFG_RET_FAIL); 886 continue; 887 } 888 889 if (alter) { 890 (void) snprintf(_cmd, PATH_MAX, 891 MSG_ORIG(MSG_CMD_OUTPUT), 892 crle->c_objdir); 893 cmd = strcpy(alloca(strlen(_cmd) + 1), 894 _cmd); 895 if (list_append(&cmdline, cmd) == 0) 896 return (INSCFG_RET_FAIL); 897 } 898 899 /* LINTED */ 900 (void) snprintf(_cmd, PATH_MAX, 901 getformat(flags), str); 902 cmd = strcpy(alloca(strlen(_cmd) + 1), _cmd); 903 if (list_append(&cmdline, cmd) == 0) 904 return (INSCFG_RET_FAIL); 905 } 906 907 if (crle->c_flags & CRLE_UPDATE) 908 continue; 909 910 /* 911 * Although we record both full pathnames and their 912 * simple filenames (basename), only print the simple 913 * names unless we're under verbose mode. 914 */ 915 if ((strchr(str, '/') == 0) || 916 (crle->c_flags & CRLE_VERBOSE)) { 917 if (fobj->co_flags & RTC_OBJ_ALTER) 918 (void) printf(MSG_INTL(MSG_DMP_FILE_2), 919 str, (strtbl + fobj->co_alter)); 920 else 921 (void) printf(MSG_INTL(MSG_DMP_FILE_1), 922 str); 923 } 924 925 /* 926 * Under verbose mode validate any real file entry - the 927 * same test will be carried out by ld.so.1. 928 */ 929 if ((crle->c_flags & CRLE_VERBOSE) && 930 (fobj->co_flags & RTC_OBJ_REALPTH)) { 931 if (stat(str, &status) != 0) { 932 int err = errno; 933 (void) printf(MSG_INTL(MSG_DMP_STAT), 934 str, strerror(err)); 935 } else if (status.st_size != fobj->co_info) { 936 (void) printf(MSG_INTL(MSG_DMP_FCMP), 937 str); 938 } 939 } 940 } 941 } 942 943 if ((crle->c_flags & CRLE_UPDATE) == 0) 944 printcmd(crle, head, &cmdline); 945 946 if ((crle->c_flags & CRLE_VERBOSE) == 0) 947 return (INSCFG_RET_OK); 948 949 /* 950 * If we've in verbose mode scan the hash list. 951 */ 952 /* LINTED */ 953 hash = (Word *)(CAST_PTRINT(char *, head->ch_hash) + addr); 954 bkts = hash[0]; 955 chain = &hash[2 + bkts]; 956 hash += 2; 957 958 (void) printf(MSG_INTL(MSG_DMP_HASH)); 959 960 /* 961 * Scan the hash buckets looking for valid entries. 962 */ 963 for (ndx = 0; ndx < bkts; ndx++, hash++) { 964 Conv_config_obj_buf_t config_obj_buf; 965 Rtc_obj *obj; 966 const char *str; 967 Word _ndx; 968 969 if (*hash == 0) 970 continue; 971 972 obj = objtbl + *hash; 973 str = strtbl + obj->co_name; 974 975 (void) printf(MSG_INTL(MSG_DMP_HASHENT_1), obj->co_id, ndx, 976 str, conv_config_obj(obj->co_flags, &config_obj_buf)); 977 978 /* 979 * Determine whether there are other objects chained to this 980 * bucket. 981 */ 982 for (_ndx = chain[*hash]; _ndx; _ndx = chain[_ndx]) { 983 obj = objtbl + _ndx; 984 str = strtbl + obj->co_name; 985 986 (void) printf(MSG_INTL(MSG_DMP_HASHENT_2), obj->co_id, 987 str, conv_config_obj(obj->co_flags, 988 &config_obj_buf)); 989 } 990 } 991 (void) printf(MSG_ORIG(MSG_STR_NL)); 992 993 return (INSCFG_RET_OK); 994 } 995 996 997 INSCFG_RET 998 inspectconfig(Crle_desc * crle, int c_class) 999 { 1000 INSCFG_RET error; 1001 int fd; 1002 Addr addr; 1003 struct stat status; 1004 const char *caller = crle->c_name, *file = crle->c_confil; 1005 Conv_inv_buf_t inv_buf1, inv_buf2, inv_buf3; 1006 1007 /* 1008 * Open the configuration file, determine its size and map it in. 1009 */ 1010 if ((fd = open(file, O_RDONLY, 0)) == -1) { 1011 int err = errno; 1012 1013 if (err == ENOENT) { 1014 #ifndef _ELF64 1015 /* Must restart if user requested a 64-bit file */ 1016 if (c_class == ELFCLASS64) 1017 return (INSCFG_RET_NEED64); 1018 #endif 1019 1020 /* 1021 * To allow an update (-u) from scratch, fabricate any 1022 * default search and secure paths that the user 1023 * intends to add to. 1024 */ 1025 if (crle->c_flags & CRLE_UPDATE) { 1026 if (crle->c_flags & CRLE_EDLIB) { 1027 if (fablib(crle, CRLE_EDLIB)) 1028 return (INSCFG_RET_FAIL); 1029 } 1030 if (crle->c_flags & CRLE_ESLIB) { 1031 if (fablib(crle, CRLE_ESLIB)) 1032 return (INSCFG_RET_FAIL); 1033 } 1034 if (crle->c_flags & CRLE_ADLIB) { 1035 if (fablib(crle, CRLE_ADLIB)) 1036 return (INSCFG_RET_FAIL); 1037 } 1038 if (crle->c_flags & CRLE_ASLIB) { 1039 if (fablib(crle, CRLE_ASLIB)) 1040 return (INSCFG_RET_FAIL); 1041 } 1042 return (INSCFG_RET_OK); 1043 1044 } else if (crle->c_flags & CRLE_CONFDEF) { 1045 const char *fmt1, *fmt2; 1046 1047 /* 1048 * Otherwise if the user is inspecting a default 1049 * configuration file that doesn't exist inform 1050 * them and display the ELF defaults. 1051 */ 1052 (void) printf(MSG_INTL(MSG_DEF_NOCONF), file); 1053 (void) printf(MSG_INTL(MSG_DMP_PLATFORM), 1054 conv_ehdr_class(M_CLASS, 1055 CONV_FMT_ALTFILE, &inv_buf1), 1056 conv_ehdr_data(M_DATA, 1057 CONV_FMT_ALTFILE, &inv_buf2), 1058 conv_ehdr_mach(M_MACH, 1059 CONV_FMT_ALTFILE, &inv_buf3)); 1060 1061 1062 if (crle->c_flags & CRLE_AOUT) { 1063 fmt1 = MSG_INTL(MSG_DEF_AOUTDLP); 1064 fmt2 = MSG_INTL(MSG_DEF_AOUTTD); 1065 } else { 1066 #if M_CLASS == ELFCLASS64 1067 #ifndef SGS_PRE_UNIFIED_PROCESS 1068 fmt1 = MSG_INTL(MSG_DEF_NEWDLP_64); 1069 fmt2 = MSG_INTL(MSG_DEF_NEWTD_64); 1070 #else 1071 fmt1 = MSG_INTL(MSG_DEF_OLDDLP_64); 1072 fmt2 = MSG_INTL(MSG_DEF_OLDTD_64); 1073 #endif 1074 #else 1075 #ifndef SGS_PRE_UNIFIED_PROCESS 1076 fmt1 = MSG_INTL(MSG_DEF_NEWDLP); 1077 fmt2 = MSG_INTL(MSG_DEF_NEWTD); 1078 #else 1079 fmt1 = MSG_INTL(MSG_DEF_OLDDLP); 1080 fmt2 = MSG_INTL(MSG_DEF_OLDTD); 1081 #endif 1082 #endif 1083 } 1084 (void) printf(fmt1); 1085 (void) printf(fmt2); 1086 1087 return (INSCFG_RET_OK); 1088 } 1089 } 1090 1091 /* 1092 * Otherwise there's an error condition in accessing the file. 1093 */ 1094 (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), caller, file, 1095 strerror(err)); 1096 1097 return (INSCFG_RET_FAIL); 1098 } 1099 1100 (void) fstat(fd, &status); 1101 if (status.st_size < sizeof (Rtc_head)) { 1102 (void) close(fd); 1103 (void) fprintf(stderr, MSG_INTL(MSG_COR_TRUNC), caller, file); 1104 return (INSCFG_RET_FAIL); 1105 } 1106 if ((addr = (Addr)mmap(0, status.st_size, PROT_READ, MAP_SHARED, 1107 fd, 0)) == (Addr)MAP_FAILED) { 1108 int err = errno; 1109 (void) fprintf(stderr, MSG_INTL(MSG_SYS_MMAP), caller, file, 1110 strerror(err)); 1111 (void) close(fd); 1112 return (INSCFG_RET_FAIL); 1113 } 1114 (void) close(fd); 1115 1116 /* 1117 * Print the contents of the configuration file. 1118 */ 1119 error = scanconfig(crle, addr, c_class); 1120 1121 (void) munmap((void *)addr, status.st_size); 1122 return (error); 1123 } 1124