1696Spaul/* 214260Spst * Copyright (c) 1993,1995 Paul Kranenburg 3696Spaul * All rights reserved. 4696Spaul * 5696Spaul * Redistribution and use in source and binary forms, with or without 6696Spaul * modification, are permitted provided that the following conditions 7696Spaul * are met: 8696Spaul * 1. Redistributions of source code must retain the above copyright 9696Spaul * notice, this list of conditions and the following disclaimer. 10696Spaul * 2. Redistributions in binary form must reproduce the above copyright 11696Spaul * notice, this list of conditions and the following disclaimer in the 12696Spaul * documentation and/or other materials provided with the distribution. 13696Spaul * 3. All advertising materials mentioning features or use of this software 14696Spaul * must display the following acknowledgement: 15696Spaul * This product includes software developed by Paul Kranenburg. 16696Spaul * 4. The name of the author may not be used to endorse or promote products 171153Sjkh * derived from this software without specific prior written permission 18696Spaul * 19696Spaul * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20696Spaul * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21696Spaul * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22696Spaul * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23696Spaul * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24696Spaul * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25696Spaul * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26696Spaul * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27696Spaul * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28696Spaul * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29696Spaul */ 30696Spaul 3137420Scharnier#ifndef lint 3237420Scharnierstatic const char rcsid[] = 3350476Speter "$FreeBSD$"; 3437420Scharnier#endif /* not lint */ 3537420Scharnier 36696Spaul#include <sys/param.h> 37696Spaul#include <sys/types.h> 38696Spaul#include <sys/stat.h> 39696Spaul#include <sys/mman.h> 4037420Scharnier#include <a.out.h> 4137420Scharnier#include <ctype.h> 421741Srich#include <dirent.h> 4376224Sobrien#include <elf-hints.h> 4437420Scharnier#include <err.h> 451741Srich#include <errno.h> 46696Spaul#include <fcntl.h> 47103436Speter#include <sys/link_aout.h> 481741Srich#include <stdio.h> 491741Srich#include <stdlib.h> 50696Spaul#include <string.h> 511741Srich#include <unistd.h> 52696Spaul 5338836Sjdp#include "ldconfig.h" 5418597Speter#include "shlib.h" 5518597Speter#include "support.h" 5618597Speter 5718859Sjdp#if DEBUG 5818859Sjdp/* test */ 5918859Sjdp#undef _PATH_LD_HINTS 6018859Sjdp#define _PATH_LD_HINTS "./ld.so.hints" 6138836Sjdp#undef _PATH_ELF_HINTS 6238836Sjdp#define _PATH_ELF_HINTS "./ld-elf.so.hints" 6318859Sjdp#endif 6418597Speter 65127250Speter#define _PATH_LD32_HINTS "/var/run/ld32.so.hints" 66127250Speter#define _PATH_ELF32_HINTS "/var/run/ld-elf32.so.hints" 67127250Speter 68696Spaul#undef major 69696Spaul#undef minor 70696Spaul 71696Spaulstatic int verbose; 72696Spaulstatic int nostd; 73696Spaulstatic int justread; 749290Sasamistatic int merge; 7528559Speterstatic int rescan; 76140241Sdelphijstatic const char *hints_file; 77696Spaul 78696Spaulstruct shlib_list { 79696Spaul /* Internal list of shared libraries found */ 80696Spaul char *name; 81696Spaul char *path; 82696Spaul int dewey[MAXDEWEY]; 83696Spaul int ndewey; 84696Spaul#define major dewey[0] 85696Spaul#define minor dewey[1] 86696Spaul struct shlib_list *next; 87696Spaul}; 88696Spaul 89696Spaulstatic struct shlib_list *shlib_head = NULL, **shlib_tail = &shlib_head; 9018597Speterstatic char *dir_list; 91696Spaul 9292882Simpstatic int buildhints(void); 9392882Simpstatic int dodir(char *, int); 9492882Simpint dofile(char *, int); 9592882Simpstatic void enter(char *, char *, char *, int *, int); 9692882Simpstatic void listhints(void); 9792882Simpstatic int readhints(void); 9892882Simpstatic void usage(void); 99696Spaul 100696Spaulint 101140241Sdelphijmain(int argc, char **argv) 102696Spaul{ 103696Spaul int i, c; 104696Spaul int rval = 0; 105127250Speter int is_aout = 0; 106127250Speter int is_32 = 0; 107696Spaul 108127250Speter while (argc > 1) { 109127250Speter if (strcmp(argv[1], "-aout") == 0) { 110127250Speter is_aout = 1; 111127250Speter argc--; 112127250Speter argv++; 113127250Speter } else if (strcmp(argv[1], "-elf") == 0) { 114127250Speter is_aout = 0; 115127250Speter argc--; 116127250Speter argv++; 117127250Speter } else if (strcmp(argv[1], "-32") == 0) { 118127250Speter is_32 = 1; 119127250Speter argc--; 120127250Speter argv++; 121127250Speter } else { 122127250Speter break; 123127250Speter } 124103436Speter } 12538960Sjdp 126127250Speter if (is_32) 127127250Speter hints_file = is_aout ? _PATH_LD32_HINTS : _PATH_ELF32_HINTS; 128127250Speter else 129127250Speter hints_file = is_aout ? _PATH_LD_HINTS : _PATH_ELF_HINTS; 13062858Sjdp if (argc == 1) 13162858Sjdp rescan = 1; 13264360Sjdp else while((c = getopt(argc, argv, "Rf:imrsv")) != -1) { 133696Spaul switch (c) { 13428559Speter case 'R': 13528559Speter rescan = 1; 13628559Speter break; 13718859Sjdp case 'f': 13818859Sjdp hints_file = optarg; 13918859Sjdp break; 14064360Sjdp case 'i': 14164360Sjdp insecure = 1; 14264360Sjdp break; 1439290Sasami case 'm': 1449290Sasami merge = 1; 145696Spaul break; 1469290Sasami case 'r': 1479290Sasami justread = 1; 1489290Sasami break; 149696Spaul case 's': 150696Spaul nostd = 1; 151696Spaul break; 1529290Sasami case 'v': 1539290Sasami verbose = 1; 154696Spaul break; 155696Spaul default: 15637420Scharnier usage(); 157696Spaul break; 158696Spaul } 159696Spaul } 160696Spaul 16138960Sjdp if (!is_aout) { 16238836Sjdp if (justread) 16338836Sjdp list_elf_hints(hints_file); 16438836Sjdp else 16538836Sjdp update_elf_hints(hints_file, argc - optind, 16638836Sjdp argv + optind, merge || rescan); 16738836Sjdp return 0; 16838836Sjdp } 16938836Sjdp 17064360Sjdp /* Here begins the aout libs processing */ 17118597Speter dir_list = strdup(""); 17218597Speter 17328559Speter if (justread || merge || rescan) { 1749290Sasami if ((rval = readhints()) != 0) 1759290Sasami return rval; 1769290Sasami } 177696Spaul 17828559Speter if (!nostd && !merge && !rescan) 1791741Srich std_search_path(); 180696Spaul 18127334Sjkh /* Add any directories/files from the command line */ 18227334Sjkh if (!justread) { 18319522Sjdp for (i = optind; i < argc; i++) { 18427334Sjkh struct stat stbuf; 18527334Sjkh 18627334Sjkh if (stat(argv[i], &stbuf) == -1) { 18719522Sjdp warn("%s", argv[i]); 18819522Sjdp rval = -1; 18938885Sjdp } else if (strcmp(argv[i], "/usr/lib") == 0) { 19036397Ssos warnx("WARNING! '%s' can not be used", argv[i]); 19136397Ssos rval = -1; 19238885Sjdp } else { 19327334Sjkh /* 19427334Sjkh * See if this is a directory-containing 19527334Sjkh * file instead of a directory 19627334Sjkh */ 19727334Sjkh if (S_ISREG(stbuf.st_mode)) 19827334Sjkh rval |= dofile(argv[i], 0); 19927334Sjkh else 20027334Sjkh add_search_path(argv[i]); 20127334Sjkh } 20219522Sjdp } 20319522Sjdp } 20418597Speter 20518597Speter for (i = 0; i < n_search_dirs; i++) { 20618597Speter char *cp = concat(dir_list, *dir_list?":":"", search_dirs[i]); 20718597Speter free(dir_list); 20818597Speter dir_list = cp; 20918597Speter } 21018597Speter 21118597Speter if (justread) { 21218597Speter listhints(); 21318597Speter return 0; 21418597Speter } 21518597Speter 216696Spaul for (i = 0; i < n_search_dirs; i++) 2171153Sjkh rval |= dodir(search_dirs[i], 1); 218696Spaul 2199290Sasami rval |= buildhints(); 220696Spaul 221696Spaul return rval; 222696Spaul} 223696Spaul 22437420Scharnierstatic void 225201217Sedusage(void) 22637420Scharnier{ 22737420Scharnier fprintf(stderr, 228152323Sjhb "usage: ldconfig [-32] [-aout | -elf] [-Rimrsv] [-f hints_file] [directory | file ...]\n"); 22937420Scharnier exit(1); 23037420Scharnier} 23137420Scharnier 232696Spaulint 233201217Seddofile(char *fname, int silent) 23427334Sjkh{ 23527334Sjkh FILE *hfp; 23627334Sjkh char buf[MAXPATHLEN]; 23727334Sjkh int rval = 0; 23827334Sjkh char *cp, *sp; 23927334Sjkh 24027334Sjkh if ((hfp = fopen(fname, "r")) == NULL) { 24127334Sjkh warn("%s", fname); 24227334Sjkh return -1; 24327334Sjkh } 24427334Sjkh 24527334Sjkh while (fgets(buf, sizeof(buf), hfp)) { 24627334Sjkh cp = buf; 24727334Sjkh while (isspace(*cp)) 24827334Sjkh cp++; 24927334Sjkh if (*cp == '#' || *cp == '\0') 25027334Sjkh continue; 25127334Sjkh sp = cp; 25227334Sjkh while (!isspace(*cp) && *cp != '\0') 25327334Sjkh cp++; 25427334Sjkh 25527334Sjkh if (*cp != '\n') { 25627334Sjkh *cp = '\0'; 25737420Scharnier warnx("%s: trailing characters ignored", sp); 25827334Sjkh } 25927334Sjkh 26027334Sjkh *cp = '\0'; 26127334Sjkh 26227334Sjkh rval |= dodir(sp, silent); 26327334Sjkh } 26427334Sjkh 26527334Sjkh (void)fclose(hfp); 26627334Sjkh return rval; 26727334Sjkh} 26827334Sjkh 26927334Sjkhint 270201217Seddodir(char *dir, int silent) 271696Spaul{ 272696Spaul DIR *dd; 273696Spaul struct dirent *dp; 27414260Spst char name[MAXPATHLEN]; 275696Spaul int dewey[MAXDEWEY], ndewey; 276696Spaul 277696Spaul if ((dd = opendir(dir)) == NULL) { 27819522Sjdp if (silent && errno == ENOENT) /* Ignore the error */ 27919522Sjdp return 0; 28019522Sjdp warn("%s", dir); 281696Spaul return -1; 282696Spaul } 283696Spaul 284696Spaul while ((dp = readdir(dd)) != NULL) { 28592806Sobrien int n; 28692806Sobrien char *cp; 287696Spaul 28814260Spst /* Check for `lib' prefix */ 28914260Spst if (dp->d_name[0] != 'l' || 29014260Spst dp->d_name[1] != 'i' || 29114260Spst dp->d_name[2] != 'b') 29214260Spst continue; 293696Spaul 29414260Spst /* Copy the entry minus prefix */ 29514260Spst (void)strcpy(name, dp->d_name + 3); 29614260Spst n = strlen(name); 29714260Spst if (n < 4) 29814260Spst continue; 299696Spaul 30014260Spst /* Find ".so." in name */ 30114260Spst for (cp = name + n - 4; cp > name; --cp) { 30214260Spst if (cp[0] == '.' && 30314260Spst cp[1] == 's' && 30414260Spst cp[2] == 'o' && 30514260Spst cp[3] == '.') 30614260Spst break; 30714260Spst } 30814260Spst if (cp <= name) 309696Spaul continue; 310696Spaul 31114260Spst *cp = '\0'; 31214260Spst if (!isdigit(*(cp+4))) 31314260Spst continue; 31414260Spst 31514260Spst bzero((caddr_t)dewey, sizeof(dewey)); 31614260Spst ndewey = getdewey(dewey, cp + 4); 31738868Sjdp if (ndewey < 2) 31838868Sjdp continue; 319696Spaul enter(dir, dp->d_name, name, dewey, ndewey); 320696Spaul } 321696Spaul 32227334Sjkh closedir(dd); 323696Spaul return 0; 324696Spaul} 325696Spaul 326696Spaulstatic void 327201217Sedenter(char *dir, char *file, char *name, int dewey[], int ndewey) 328696Spaul{ 329696Spaul struct shlib_list *shp; 330696Spaul 331696Spaul for (shp = shlib_head; shp; shp = shp->next) { 332696Spaul if (strcmp(name, shp->name) != 0 || major != shp->major) 333696Spaul continue; 334696Spaul 335696Spaul /* Name matches existing entry */ 336696Spaul if (cmpndewey(dewey, ndewey, shp->dewey, shp->ndewey) > 0) { 337696Spaul 338696Spaul /* Update this entry with higher versioned lib */ 339696Spaul if (verbose) 340696Spaul printf("Updating lib%s.%d.%d to %s/%s\n", 341696Spaul shp->name, shp->major, shp->minor, 342696Spaul dir, file); 343696Spaul 344696Spaul free(shp->name); 345696Spaul shp->name = strdup(name); 346696Spaul free(shp->path); 347696Spaul shp->path = concat(dir, "/", file); 348696Spaul bcopy(dewey, shp->dewey, sizeof(shp->dewey)); 349696Spaul shp->ndewey = ndewey; 350696Spaul } 351696Spaul break; 352696Spaul } 353696Spaul 354696Spaul if (shp) 355696Spaul /* Name exists: older version or just updated */ 356696Spaul return; 357696Spaul 358696Spaul /* Allocate new list element */ 359696Spaul if (verbose) 360696Spaul printf("Adding %s/%s\n", dir, file); 361696Spaul 362696Spaul shp = (struct shlib_list *)xmalloc(sizeof *shp); 363696Spaul shp->name = strdup(name); 364696Spaul shp->path = concat(dir, "/", file); 365126896Scperciva bcopy(dewey, shp->dewey, sizeof(shp->dewey)); 366696Spaul shp->ndewey = ndewey; 367696Spaul shp->next = NULL; 368696Spaul 369696Spaul *shlib_tail = shp; 370696Spaul shlib_tail = &shp->next; 371696Spaul} 372696Spaul 373696Spaul 374140241Sdelphijstatic int 375140241Sdelphijhinthash(char *cp, int vmajor) 376696Spaul{ 377696Spaul int k = 0; 378696Spaul 379696Spaul while (*cp) 380696Spaul k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff; 381696Spaul 382696Spaul k = (((k << 1) + (k >> 14)) ^ (vmajor*257)) & 0x3fff; 383696Spaul 384696Spaul return k; 385696Spaul} 386696Spaul 387696Spaulint 388201217Sedbuildhints(void) 389696Spaul{ 390696Spaul struct hints_header hdr; 391696Spaul struct hints_bucket *blist; 392696Spaul struct shlib_list *shp; 393696Spaul char *strtab; 394696Spaul int i, n, str_index = 0; 395696Spaul int strtab_sz = 0; /* Total length of strings */ 396696Spaul int nhints = 0; /* Total number of hints */ 397696Spaul int fd; 398140244Sdelphij char *tmpfilename; 399696Spaul 400696Spaul for (shp = shlib_head; shp; shp = shp->next) { 401696Spaul strtab_sz += 1 + strlen(shp->name); 402696Spaul strtab_sz += 1 + strlen(shp->path); 403696Spaul nhints++; 404696Spaul } 405696Spaul 406696Spaul /* Fill hints file header */ 407696Spaul hdr.hh_magic = HH_MAGIC; 40818597Speter hdr.hh_version = LD_HINTS_VERSION_2; 409696Spaul hdr.hh_nbucket = 1 * nhints; 410696Spaul n = hdr.hh_nbucket * sizeof(struct hints_bucket); 411696Spaul hdr.hh_hashtab = sizeof(struct hints_header); 412696Spaul hdr.hh_strtab = hdr.hh_hashtab + n; 41318597Speter hdr.hh_dirlist = strtab_sz; 41418597Speter strtab_sz += 1 + strlen(dir_list); 415696Spaul hdr.hh_strtab_sz = strtab_sz; 416696Spaul hdr.hh_ehints = hdr.hh_strtab + hdr.hh_strtab_sz; 417696Spaul 418696Spaul if (verbose) 41917142Sjkh printf("Totals: entries %d, buckets %ld, string size %d\n", 42038023Sbde nhints, (long)hdr.hh_nbucket, strtab_sz); 421696Spaul 422696Spaul /* Allocate buckets and string table */ 423696Spaul blist = (struct hints_bucket *)xmalloc(n); 424696Spaul bzero((char *)blist, n); 425696Spaul for (i = 0; i < hdr.hh_nbucket; i++) 426696Spaul /* Empty all buckets */ 427696Spaul blist[i].hi_next = -1; 428696Spaul 429696Spaul strtab = (char *)xmalloc(strtab_sz); 430696Spaul 431696Spaul /* Enter all */ 432696Spaul for (shp = shlib_head; shp; shp = shp->next) { 433696Spaul struct hints_bucket *bp; 434696Spaul 435696Spaul bp = blist + 4365551Sjoerg (hinthash(shp->name, shp->major) % hdr.hh_nbucket); 437696Spaul 438696Spaul if (bp->hi_pathx) { 439140241Sdelphij int j; 440696Spaul 441140241Sdelphij for (j = 0; j < hdr.hh_nbucket; j++) { 442140241Sdelphij if (blist[j].hi_pathx == 0) 443696Spaul break; 444696Spaul } 445140241Sdelphij if (j == hdr.hh_nbucket) { 44637420Scharnier warnx("bummer!"); 447696Spaul return -1; 448696Spaul } 449696Spaul while (bp->hi_next != -1) 450696Spaul bp = &blist[bp->hi_next]; 451140241Sdelphij bp->hi_next = j; 452140241Sdelphij bp = blist + j; 453696Spaul } 454696Spaul 455696Spaul /* Insert strings in string table */ 456696Spaul bp->hi_namex = str_index; 457696Spaul strcpy(strtab + str_index, shp->name); 458696Spaul str_index += 1 + strlen(shp->name); 459696Spaul 460696Spaul bp->hi_pathx = str_index; 461696Spaul strcpy(strtab + str_index, shp->path); 462696Spaul str_index += 1 + strlen(shp->path); 463696Spaul 464696Spaul /* Copy versions */ 465696Spaul bcopy(shp->dewey, bp->hi_dewey, sizeof(bp->hi_dewey)); 466696Spaul bp->hi_ndewey = shp->ndewey; 467696Spaul } 468696Spaul 46918597Speter /* Copy search directories */ 47018597Speter strcpy(strtab + str_index, dir_list); 47118597Speter str_index += 1 + strlen(dir_list); 47218597Speter 47318597Speter /* Sanity check */ 47418597Speter if (str_index != strtab_sz) { 47518597Speter errx(1, "str_index(%d) != strtab_sz(%d)", str_index, strtab_sz); 47618597Speter } 47718597Speter 478140244Sdelphij tmpfilename = concat(hints_file, ".XXXXXXXXXX", ""); 47956125Skris umask(0); /* Create with exact permissions */ 480140244Sdelphij if ((fd = mkstemp(tmpfilename)) == -1) { 481140244Sdelphij warn("%s", tmpfilename); 48218597Speter return -1; 48318597Speter } 48456125Skris fchmod(fd, 0444); 48518597Speter 4861153Sjkh if (write(fd, &hdr, sizeof(struct hints_header)) != 4871153Sjkh sizeof(struct hints_header)) { 48818859Sjdp warn("%s", hints_file); 4891153Sjkh return -1; 4901153Sjkh } 491140248Sdelphij if (write(fd, blist, hdr.hh_nbucket * sizeof(*blist)) != 492140248Sdelphij (ssize_t)(hdr.hh_nbucket * sizeof(*blist))) { 49318859Sjdp warn("%s", hints_file); 4941153Sjkh return -1; 4951153Sjkh } 4961153Sjkh if (write(fd, strtab, strtab_sz) != strtab_sz) { 49718859Sjdp warn("%s", hints_file); 4981153Sjkh return -1; 4991153Sjkh } 500696Spaul if (close(fd) != 0) { 50118859Sjdp warn("%s", hints_file); 502696Spaul return -1; 503696Spaul } 504696Spaul 5051153Sjkh /* Install it */ 50618859Sjdp if (unlink(hints_file) != 0 && errno != ENOENT) { 50718859Sjdp warn("%s", hints_file); 508696Spaul return -1; 509696Spaul } 510696Spaul 511140244Sdelphij if (rename(tmpfilename, hints_file) != 0) { 51218859Sjdp warn("%s", hints_file); 513696Spaul return -1; 514696Spaul } 515696Spaul 516696Spaul return 0; 517696Spaul} 518696Spaul 5191741Srichstatic int 520201217Sedreadhints(void) 521696Spaul{ 522696Spaul int fd; 52338885Sjdp void *addr; 52438885Sjdp long fsize; 525696Spaul long msize; 526696Spaul struct hints_header *hdr; 527696Spaul struct hints_bucket *blist; 528696Spaul char *strtab; 5299290Sasami struct shlib_list *shp; 530696Spaul int i; 531696Spaul 53218859Sjdp if ((fd = open(hints_file, O_RDONLY, 0)) == -1) { 53318859Sjdp warn("%s", hints_file); 534696Spaul return -1; 535696Spaul } 536696Spaul 53718597Speter msize = PAGE_SIZE; 5385205Snate addr = mmap(0, msize, PROT_READ, MAP_COPY, fd, 0); 539696Spaul 54038885Sjdp if (addr == MAP_FAILED) { 54118859Sjdp warn("%s", hints_file); 542696Spaul return -1; 543696Spaul } 544696Spaul 545696Spaul hdr = (struct hints_header *)addr; 546696Spaul if (HH_BADMAG(*hdr)) { 54738023Sbde warnx("%s: bad magic: %lo", hints_file, 54838023Sbde (unsigned long)hdr->hh_magic); 549696Spaul return -1; 550696Spaul } 551696Spaul 55218597Speter if (hdr->hh_version != LD_HINTS_VERSION_1 && 55318597Speter hdr->hh_version != LD_HINTS_VERSION_2) { 55438023Sbde warnx("unsupported version: %ld", (long)hdr->hh_version); 555696Spaul return -1; 556696Spaul } 557696Spaul 558696Spaul if (hdr->hh_ehints > msize) { 55938885Sjdp fsize = hdr->hh_ehints; 56038885Sjdp munmap(addr, msize); 56138885Sjdp addr = mmap(0, fsize, PROT_READ, MAP_COPY, fd, 0); 56238885Sjdp if (addr == MAP_FAILED) { 56318859Sjdp warn("%s", hints_file); 564696Spaul return -1; 565696Spaul } 56638885Sjdp hdr = (struct hints_header *)addr; 567696Spaul } 568696Spaul close(fd); 569696Spaul 570133723Sstefanf strtab = (char *)addr + hdr->hh_strtab; 571696Spaul 57228559Speter if (hdr->hh_version >= LD_HINTS_VERSION_2) 57328559Speter add_search_path(strtab + hdr->hh_dirlist); 57428559Speter else if (rescan) 57528559Speter errx(1, "%s too old and does not contain the search path", 57628559Speter hints_file); 57728559Speter 57828559Speter if (rescan) 57928559Speter return 0; 58028559Speter 581140248Sdelphij blist = malloc(sizeof(*blist) * hdr->hh_nbucket); 582140241Sdelphij if (blist == NULL) 583140241Sdelphij err(1, "readhints"); 584140241Sdelphij memcpy(blist, (char *)addr + hdr->hh_hashtab, 585140248Sdelphij sizeof(*blist) * hdr->hh_nbucket); 586140241Sdelphij 587140241Sdelphij 588696Spaul for (i = 0; i < hdr->hh_nbucket; i++) { 589696Spaul struct hints_bucket *bp = &blist[i]; 590696Spaul 591696Spaul /* Sanity check */ 592696Spaul if (bp->hi_namex >= hdr->hh_strtab_sz) { 59337420Scharnier warnx("bad name index: %#x", bp->hi_namex); 594140241Sdelphij free(blist); 595696Spaul return -1; 596696Spaul } 597696Spaul if (bp->hi_pathx >= hdr->hh_strtab_sz) { 59837420Scharnier warnx("bad path index: %#x", bp->hi_pathx); 599140241Sdelphij free(blist); 600696Spaul return -1; 601696Spaul } 602696Spaul 6039290Sasami /* Allocate new list element */ 6049290Sasami shp = (struct shlib_list *)xmalloc(sizeof *shp); 6059290Sasami shp->name = strdup(strtab + bp->hi_namex); 6069290Sasami shp->path = strdup(strtab + bp->hi_pathx); 6079290Sasami bcopy(bp->hi_dewey, shp->dewey, sizeof(shp->dewey)); 6089290Sasami shp->ndewey = bp->hi_ndewey; 6099290Sasami shp->next = NULL; 6109290Sasami 6119290Sasami *shlib_tail = shp; 6129290Sasami shlib_tail = &shp->next; 613696Spaul } 614696Spaul 615140241Sdelphij free(blist); 616696Spaul return 0; 617696Spaul} 618696Spaul 6199290Sasamistatic void 620201217Sedlisthints(void) 6219290Sasami{ 6229290Sasami struct shlib_list *shp; 6239290Sasami int i; 6249290Sasami 62518859Sjdp printf("%s:\n", hints_file); 62618597Speter printf("\tsearch directories: %s\n", dir_list); 6279290Sasami 6289290Sasami for (i = 0, shp = shlib_head; shp; i++, shp = shp->next) 6299290Sasami printf("\t%d:-l%s.%d.%d => %s\n", 6309290Sasami i, shp->name, shp->major, shp->minor, shp->path); 6319290Sasami 6329290Sasami return; 6339290Sasami} 634