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