]> sourceware.org Git - glibc.git/blame - elf/ldconfig.c
Update.
[glibc.git] / elf / ldconfig.c
CommitLineData
45eca4d1 1/* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
591e1ffb
UD
2 This file is part of the GNU C Library.
3 Contributed by Andreas Jaeger <aj@suse.de>, 1999.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
19
20#include <argp.h>
21#include <dirent.h>
9c95d361 22#include <elf.h>
591e1ffb
UD
23#include <error.h>
24#include <errno.h>
25#include <libintl.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <unistd.h>
30#include <sys/fcntl.h>
31#include <sys/mman.h>
32#include <sys/stat.h>
33#include <sys/types.h>
34
35#include "ldconfig.h"
45eca4d1 36#include "dl-cache.h"
591e1ffb 37
45eca4d1
UD
38/* We don't need this here - silence the compiler. */
39#define _dl_sysdep_message(string, args...) do {} while (0);
40
41#include "dl-procinfo.h"
591e1ffb
UD
42
43#ifndef LD_SO_CONF
8ca91b36 44# define LD_SO_CONF SYSCONFDIR "/ld.so.conf"
591e1ffb
UD
45#endif
46
47/* Get libc version number. */
48#include <version.h>
49
50#define PACKAGE _libc_intl_domainname
51
52struct lib_entry
53 {
54 int flags;
45eca4d1 55 unsigned long int hwcap;
591e1ffb
UD
56 char *lib;
57 char *path;
58 };
59
60static const struct
61{
62 const char *name;
63 int flag;
64} lib_types [] =
65{
66 {"libc4", FLAG_LIBC4},
67 {"libc5", FLAG_ELF_LIBC5},
68 {"libc6", FLAG_ELF_LIBC6},
69 {"glibc2", FLAG_ELF_LIBC6}
45eca4d1 70};
591e1ffb
UD
71
72
73/* List of directories to handle. */
74struct dir_entry
75{
76 char *path;
77 int flag;
78 struct dir_entry *next;
79};
80
81/* The list is unsorted, contains no duplicates. Entries are added at
82 the end. */
83static struct dir_entry *dir_entries;
84
85/* Flags for different options. */
86/* Print Cache. */
87static int opt_print_cache = 0;
88
89/* Be verbose. */
90int opt_verbose = 0;
91
45eca4d1
UD
92/* Format to support. */
93/* 0: only libc5/glibc2; 1: both; 2: only glibc 2.2. */
94int opt_format = 1;
95
591e1ffb
UD
96/* Build cache. */
97static int opt_build_cache = 1;
98
99/* Generate links. */
100static int opt_link = 1;
101
102/* Only process directories specified on the command line. */
103static int opt_only_cline = 0;
104
105/* Path to root for chroot. */
106static char *opt_chroot;
107
b85697f6
UD
108/* Manually link given shared libraries. */
109static int opt_manual_link = 0;
110
591e1ffb
UD
111/* Cache file to use. */
112static const char *cache_file;
113
114/* Configuration file. */
115static const char *config_file;
116
117/* Name and version of program. */
118static void print_version (FILE *stream, struct argp_state *state);
119void (*argp_program_version_hook) (FILE *, struct argp_state *)
120 = print_version;
121
122/* Definitions of arguments for argp functions. */
123static const struct argp_option options[] =
124{
125 { "print-cache", 'p', NULL, 0, N_("Print cache"), 0},
126 { "verbose", 'v', NULL, 0, N_("Generate verbose messages"), 0},
127 { NULL, 'N', NULL, 0, N_("Don't build cache"), 0},
128 { NULL, 'X', NULL, 0, N_("Don't generate links"), 0},
129 { NULL, 'r', "ROOT", 0, N_("Change to and use ROOT as root directory"), 0},
130 { NULL, 'C', "CACHE", 0, N_("Use CACHE as cache file"), 0},
131 { NULL, 'f', "CONF", 0, N_("Use CONF as configuration file"), 0},
132 { NULL, 'n', NULL, 0, N_("Only process directories specified on the command line. Don't build cache."), 0},
b85697f6 133 { NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0},
45eca4d1 134 { "format", 'c', "FORMAT", 0, N_("Format to use: new, old or compat (default)"), 0},
591e1ffb
UD
135 { NULL, 0, NULL, 0, NULL, 0 }
136};
137
138/* Short description of program. */
139static const char doc[] = N_("Configure Dynamic Linker Run Time Bindings.");
140
141/* Prototype for option handler. */
142static error_t parse_opt (int key, char *arg, struct argp_state *state);
143
144/* Data structure to communicate with argp functions. */
145static struct argp argp =
146{
147 options, parse_opt, NULL, doc, NULL, NULL, NULL
148};
149
45eca4d1
UD
150/* Check if string corresponds to an important hardware capability. */
151static int
152is_hwcap (const char *name)
153{
154 int hwcap_idx = _dl_string_hwcap (name);
8ca91b36 155
45eca4d1
UD
156 if (hwcap_idx != -1 && ((1 << hwcap_idx) & HWCAP_IMPORTANT))
157 return 1;
158 return 0;
159}
160
161/* Get hwcap encoding of path. */
162static unsigned long int
163path_hwcap (const char *path)
164{
165 char *str = xstrdup (path);
166 char *ptr;
167 unsigned long int hwcap = 0;
168 unsigned long int h;
169
170 size_t len;
171
172 len = strlen (str);
173 if (str[len] == '/')
174 str[len] = '\0';
175
176 /* Search pathname from the end and check for hwcap strings. */
177 for (;;)
178 {
179 ptr = strrchr (str, '/');
180
181 if (ptr == NULL)
182 break;
183
184 h = _dl_string_hwcap (ptr+1);
185
186 if (h == -1)
187 break;
188 hwcap += 1 << h;
591e1ffb 189
45eca4d1
UD
190 /* Search the next part of the path. */
191 *ptr = '\0';
192 }
193
194 free (str);
195 return hwcap;
196}
591e1ffb
UD
197
198/* Handle program arguments. */
199static error_t
200parse_opt (int key, char *arg, struct argp_state *state)
201{
202 switch (key)
203 {
204 case 'C':
205 cache_file = arg;
206 break;
207 case 'f':
208 config_file = arg;
209 break;
b85697f6
UD
210 case 'l':
211 opt_manual_link = 1;
212 break;
591e1ffb
UD
213 case 'N':
214 opt_build_cache = 0;
215 break;
216 case 'n':
217 opt_build_cache = 0;
218 opt_only_cline = 1;
219 break;
220 case 'p':
221 opt_print_cache = 1;
222 break;
223 case 'r':
224 opt_chroot = arg;
225 break;
226 case 'v':
227 opt_verbose = 1;
228 break;
229 case 'X':
230 opt_link = 0;
231 break;
45eca4d1
UD
232 case 'c':
233 if (strcmp (arg, "old") == 0)
234 opt_format = 0;
235 else if (strcmp (arg, "compat") == 0)
236 opt_format = 1;
237 else if (strcmp (arg, "new") == 0)
238 opt_format = 2;
239 break;
591e1ffb
UD
240 default:
241 return ARGP_ERR_UNKNOWN;
242 }
243
244 return 0;
245}
246
247/* Print the version information. */
248static void
249print_version (FILE *stream, struct argp_state *state)
250{
251 fprintf (stream, "ldconfig (GNU %s) %s\n", PACKAGE, VERSION);
252 fprintf (stream, gettext ("\
253Copyright (C) %s Free Software Foundation, Inc.\n\
254This is free software; see the source for copying conditions. There is NO\n\
255warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
45eca4d1 256"), "2000");
591e1ffb
UD
257 fprintf (stream, gettext ("Written by %s.\n"),
258 "Andreas Jaeger");
259}
260
a8fd59b0
AJ
261/* Add a single directory entry. */
262static void
263add_single_dir (struct dir_entry *entry, int verbose)
264{
265 struct dir_entry *ptr, *prev;
266
267 ptr = dir_entries;
268 prev = ptr;
269 while (ptr != NULL)
270 {
271 /* Check for duplicates. */
272 if (strcmp (ptr->path, entry->path) == 0)
273 {
274 if (opt_verbose && verbose)
275 error (0, 0, _("Path `%s' given more than once"), entry->path);
276 /* Use the newer information. */
277 ptr->flag = entry->flag;
278 free (entry);
279 break;
280 }
281 prev = ptr;
282 ptr = ptr->next;
283 }
284 /* Is this the first entry? */
285 if (ptr == NULL && dir_entries == NULL)
286 dir_entries = entry;
287 else if (ptr == NULL)
288 prev->next = entry;
289}
290
591e1ffb
UD
291/* Add one directory to the list of directories to process. */
292static void
293add_dir (const char *line)
294{
295 char *equal_sign;
a8fd59b0 296 struct dir_entry *entry;
591e1ffb 297 unsigned int i;
45eca4d1 298
591e1ffb
UD
299 entry = xmalloc (sizeof (struct dir_entry));
300 entry->next = NULL;
45eca4d1 301
591e1ffb
UD
302 /* Search for an '=' sign. */
303 entry->path = xstrdup (line);
304 equal_sign = strchr (entry->path, '=');
305 if (equal_sign)
306 {
307 *equal_sign = '\0';
308 ++equal_sign;
309 entry->flag = FLAG_ANY;
310 for (i = 0; i < sizeof (lib_types) / sizeof (lib_types [0]); ++i)
311 if (strcmp (equal_sign, lib_types[i].name) == 0)
312 {
313 entry->flag = lib_types[i].flag;
314 break;
315 }
316 if (entry->flag == FLAG_ANY)
317 error (0, 0, _("%s is not a known library type"), equal_sign);
318 }
319 else
320 {
321 entry->flag = FLAG_ANY;
322 }
323
324 /* Canonify path: for now only remove trailing slashes. */
325 i = strlen (entry->path) - 1;
326 while (entry->path[i] == '/' && i > 0)
327 {
328 entry->path [i] = '\0';
329 --i;
330 }
45eca4d1 331
a8fd59b0 332 add_single_dir (entry, 1);
591e1ffb
UD
333}
334
335
336/* Create a symbolic link from soname to libname in directory path. */
337static void
338create_links (const char *path, const char *libname, const char *soname)
339{
340 char full_libname [PATH_MAX], full_soname [PATH_MAX];
341 struct stat stat_lib, stat_so, lstat_so;
342 int do_link = 1;
343 int do_remove = 1;
344 /* XXX: The logics in this function should be simplified. */
45eca4d1 345
591e1ffb
UD
346 /* Get complete path. */
347 snprintf (full_libname, sizeof full_libname, "%s/%s", path, libname);
348 snprintf (full_soname, sizeof full_soname, "%s/%s", path, soname);
349
350 /* Does soname already exist and point to the right library? */
351 if (stat (full_soname, &stat_so) == 0)
352 {
353 if (stat (full_libname, &stat_lib))
354 {
355 error (0, 0, _("Can't stat %s\n"), full_libname);
356 return;
357 }
358 if (stat_lib.st_dev == stat_so.st_dev
359 && stat_lib.st_ino == stat_so.st_ino)
360 /* Link is already correct. */
361 do_link = 0;
362 else if (lstat (full_soname, &lstat_so) == 0
363 && !S_ISLNK (lstat_so.st_mode))
364 {
365 error (0, 0, _("%s is not a symbolic link\n"), full_soname);
366 do_link = 0;
367 do_remove = 0;
368 }
369 }
370 else if (lstat (full_soname, &lstat_so) != 0
371 || !S_ISLNK (lstat_so.st_mode))
372 /* Unless it is a stale symlink, there is no need to remove. */
373 do_remove = 0;
374
375 if (opt_verbose)
376 printf ("\t%s -> %s", soname, libname);
377
378 if (do_link && opt_link)
379 {
380 /* Remove old link. */
381 if (do_remove)
382 if (unlink (full_soname))
383 {
384 error (0, 0, _("Can't unlink %s"), full_soname);
385 do_link = 0;
386 }
387 /* Create symbolic link. */
388 if (do_link && symlink (libname, full_soname))
389 {
390 error (0, 0, _("Can't link %s to %s"), full_soname, libname);
391 do_link = 0;
392 }
393 if (opt_verbose)
394 {
395 if (do_link)
396 fputs (_(" (changed)\n"), stdout);
397 else
398 fputs (_(" (SKIPPED)\n"), stdout);
399 }
400 }
401 else if (opt_verbose)
402 fputs ("\n", stdout);
403}
404
b85697f6
UD
405/* Manually link the given library. */
406static void
407manual_link (char *library)
408{
409 char *path;
410 char *libname;
411 char *soname;
412 struct stat stat_buf;
413 int flag;
414
415 /* Prepare arguments for create_links call. Split library name in
416 directory and filename first. Since path is allocated, we've got
417 to be careful to free at the end. */
418 path = xstrdup (library);
419 libname = strrchr (path, '/');
420
421 if (libname)
422 {
423 /* Successfully split names. Check if path is just "/" to avoid
424 an empty path. */
425 if (libname == path)
426 {
427 libname = library + 1;
428 path = xrealloc (path, 2);
429 strcpy (path, "/");
430 }
431 else
432 {
433 *libname = '\0';
434 ++libname;
435 }
436 }
437 else
438 {
439 /* There's no path, construct one. */
440 libname = library;
441 path = xrealloc (path, 2);
442 strcpy (path, ".");
443 }
444
445 /* Do some sanity checks first. */
446 if (lstat (library, &stat_buf))
447 {
448 error (0, errno, _("Can't lstat %s"), library);
449 free (path);
450 return;
451 }
452 /* We don't want links here! */
453 else if (!S_ISREG (stat_buf.st_mode))
454 {
455 error (0, 0, _("Ignored file %s since it is not a regular file."),
456 library);
457 free (path);
458 return;
459 }
460 libname = basename (library);
461 if (process_file (library, libname, &flag, &soname, 0))
462 {
463 error (0, 0, _("No link created since soname could not be found for %s"),
464 library);
465 free (path);
466 return;
467 }
468 create_links (path, libname, soname);
469 free (soname);
470 free (path);
471}
472
473
591e1ffb
UD
474/* Read a whole directory and search for libraries.
475 The purpose is two-fold:
476 - search for libraries which will be added to the cache
477 - create symbolic links to the soname for each library
478
479 This has to be done separatly for each directory.
45eca4d1 480
591e1ffb
UD
481 To keep track of which libraries to add to the cache and which
482 links to create, we save a list of all libraries.
483
484 The algorithm is basically:
485 for all libraries in the directory do
486 get soname of library
487 if soname is already in list
488 if new library is newer, replace entry
489 otherwise ignore this library
490 otherwise add library to list
45eca4d1 491
591e1ffb
UD
492 For example, if the two libraries libxy.so.1.1 and libxy.so.1.2
493 exist and both have the same soname, e.g. libxy.so, a symbolic link
494 is created from libxy.so.1.2 (the newer one) to libxy.so.
495 libxy.so.1.2 and libxy.so are added to the cache - but not
496 libxy.so.1.1. */
497
498/* Information for one library. */
45eca4d1 499struct dlib_entry
591e1ffb
UD
500{
501 char *name;
502 char *soname;
503 int flag;
504 int is_link;
505 struct dlib_entry *next;
506};
507
508
509static void
510search_dir (const struct dir_entry *entry)
511{
512 DIR *dir;
513 struct dirent *direntry;
514 char buf [PATH_MAX];
515 char *soname;
516 struct dlib_entry *dlibs;
517 struct dlib_entry *dlib_ptr;
518 int nchars;
519 struct stat stat_buf;
520 int is_link;
45eca4d1
UD
521 unsigned long int hwcap = path_hwcap (entry->path);
522
591e1ffb
UD
523 dlibs = NULL;
524
525 if (opt_verbose)
45eca4d1
UD
526 {
527 if (hwcap != 0)
528 printf ("%s: (hwcap: 0x%lx)\n", entry->path, hwcap);
529 else
530 printf ("%s:\n", entry->path);
531 }
532
591e1ffb
UD
533 dir = opendir (entry->path);
534 if (dir == NULL)
535 {
536 if (opt_verbose)
537 error (0, errno, _("Can't open directory %s"), entry->path);
538 return;
539 }
45eca4d1 540
591e1ffb
UD
541
542 while ((direntry = readdir (dir)) != NULL)
543 {
544 int flag;
545#ifdef _DIRENT_HAVE_D_TYPE
546 /* We only look at links and regular files. */
547 if (direntry->d_type != DT_UNKNOWN
548 && direntry->d_type != DT_LNK
45eca4d1
UD
549 && direntry->d_type != DT_REG
550 && direntry->d_type != DT_DIR)
591e1ffb
UD
551 continue;
552#endif /* _DIRENT_HAVE_D_TYPE */
45eca4d1
UD
553 /* Does this file look like a shared library or is it a hwcap
554 subdirectory? The dynamic linker is also considered as
555 shared library. */
556 if (((strncmp (direntry->d_name, "lib", 3) != 0
557 && strncmp (direntry->d_name, "ld-", 3) != 0)
558 || strstr (direntry->d_name, ".so") == NULL)
559 && !is_hwcap (direntry->d_name))
591e1ffb
UD
560 continue;
561 nchars = snprintf (buf, sizeof (buf), "%s/%s", entry->path,
562 direntry->d_name);
563 /* Check for overflow. */
564 if (nchars >= (int) sizeof (buf))
565 {
566 error (0, 0, _("buffer for snprintf too small for %s/%s--file is ignored\n"),
567 entry->path, direntry->d_name);
568 continue;
569 }
7c3002f0
UD
570#ifdef _DIRENT_HAVE_D_TYPE
571 if (direntry->d_type != DT_UNKNOWN)
572 stat_buf.st_mode = DTTOIF (direntry->d_type);
573 else
574#endif
575 if (lstat (buf, &stat_buf))
576 {
577 error (0, errno, _("Can't lstat %s"), buf);
578 continue;
579 }
580
581 if (S_ISDIR (stat_buf.st_mode) && is_hwcap (direntry->d_name))
45eca4d1 582 {
a8fd59b0
AJ
583 /* Handle subdirectory later. */
584 struct dir_entry *new_entry;
585
586 new_entry = xmalloc (sizeof (struct dir_entry));
587
588 new_entry->path = buf;
589 new_entry->flag = entry->flag;
590 new_entry->next = NULL;
591 add_single_dir (new_entry, 0);
45eca4d1
UD
592 continue;
593 }
591e1ffb
UD
594 else if (!S_ISREG (stat_buf.st_mode) && !S_ISLNK (stat_buf.st_mode))
595 continue;
596
597 is_link = S_ISLNK (stat_buf.st_mode);
598
599 if (process_file (buf, direntry->d_name, &flag, &soname, is_link))
600 continue;
601
602 /* Links will just point to itself. */
603 if (is_link)
604 {
605 free (soname);
606 soname = xstrdup (direntry->d_name);
607 }
45eca4d1 608
591e1ffb
UD
609 if (flag == FLAG_ELF
610 && (entry->flag == FLAG_ELF_LIBC5
611 || entry->flag == FLAG_ELF_LIBC6))
612 flag = entry->flag;
613 /* Some sanity checks to print warnings. */
614 if (opt_verbose)
615 {
616 if (flag == FLAG_ELF_LIBC5 && entry->flag != FLAG_ELF_LIBC5
617 && entry->flag != FLAG_ANY)
618 error (0, 0, _("libc5 library %s in wrong directory"), buf);
619 if (flag == FLAG_ELF_LIBC6 && entry->flag != FLAG_ELF_LIBC6
620 && entry->flag != FLAG_ANY)
621 error (0, 0, _("libc6 library %s in wrong directory"), buf);
622 if (flag == FLAG_LIBC4 && entry->flag != FLAG_LIBC4
623 && entry->flag != FLAG_ANY)
624 error (0, 0, _("libc4 library %s in wrong directory"), buf);
625 }
45eca4d1 626
591e1ffb
UD
627 /* Add library to list. */
628 for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
629 {
630 /* Is soname already in list? */
631 if (strcmp (dlib_ptr->soname, soname) == 0)
632 {
633 /* Prefer a file to a link, otherwise check which one
634 is newer. */
635 if ((!is_link && dlib_ptr->is_link)
636 || (is_link == dlib_ptr->is_link
45eca4d1 637 && _dl_cache_libcmp (dlib_ptr->name, direntry->d_name) < 0))
591e1ffb
UD
638 {
639 /* It's newer - add it. */
640 /* Flag should be the same - sanity check. */
641 if (dlib_ptr->flag != flag)
642 {
643 if (dlib_ptr->flag == FLAG_ELF
644 && (flag == FLAG_ELF_LIBC5 || flag == FLAG_ELF_LIBC6))
645 dlib_ptr->flag = flag;
646 else if ((dlib_ptr->flag == FLAG_ELF_LIBC5
647 || dlib_ptr->flag == FLAG_ELF_LIBC6)
648 && flag == FLAG_ELF)
649 dlib_ptr->flag = flag;
650 else
651 error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."),
652 dlib_ptr->name, direntry->d_name, entry->path);
653 }
654 free (dlib_ptr->name);
655 dlib_ptr->name = xstrdup (direntry->d_name);
656 dlib_ptr->is_link = is_link;
657 }
658 /* Don't add this library, abort loop. */
659 /* Also free soname, since it's dynamically allocated. */
660 free (soname);
661 break;
662 }
663 }
664 /* Add the library if it's not already in. */
665 if (dlib_ptr == NULL)
666 {
667 dlib_ptr = (struct dlib_entry *)xmalloc (sizeof (struct dlib_entry));
668 dlib_ptr->name = xstrdup (direntry->d_name);
669 dlib_ptr->flag = flag;
670 dlib_ptr->soname = soname;
671 dlib_ptr->is_link = is_link;
672 /* Add at head of list. */
673 dlib_ptr->next = dlibs;
674 dlibs = dlib_ptr;
675 }
676 }
677
678 closedir (dir);
679
680 /* Now dlibs contains a list of all libs - add those to the cache
681 and created all symbolic links. */
682 for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
683 {
684 /* Don't create links to links. */
685 if (dlib_ptr->is_link == 0)
686 create_links (entry->path, dlib_ptr->name, dlib_ptr->soname);
687 if (opt_build_cache)
45eca4d1 688 add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag, hwcap);
591e1ffb
UD
689 }
690
691 /* Free all resources. */
45eca4d1 692 while (dlibs)
591e1ffb
UD
693 {
694 dlib_ptr = dlibs;
695 free (dlib_ptr->soname);
696 free (dlib_ptr->name);
697 dlibs = dlibs->next;
698 free (dlib_ptr);
699 }
700}
701
702/* Search through all libraries. */
703static void
704search_dirs (void)
705{
706 struct dir_entry *entry;
707
708 for (entry = dir_entries; entry != NULL; entry = entry->next)
709 search_dir (entry);
710
711 /* Free all allocated memory. */
712 while (dir_entries)
713 {
714 entry = dir_entries;
715 dir_entries = dir_entries->next;
716 free (entry->path);
717 free (entry);
718 }
719}
720
721
722/* Parse configuration file. */
723static void
724parse_conf (const char *filename)
725{
726 FILE *file;
727 char *line = NULL;
728 size_t len = 0;
45eca4d1 729
591e1ffb
UD
730 file = fopen (filename, "r");
731
732 if (file == NULL)
733 {
734 error (0, errno, _("Can't open configuration file %s"), filename);
735 return;
736 }
737
738 do
739 {
740 ssize_t n = getline (&line, &len, file);
741 if (n < 0)
742 break;
743
744 if (line[n - 1] == '\n')
745 line[n - 1] = '\0';
746
747 /* Because the file format does not know any form of quoting we
748 can search forward for the next '#' character and if found
749 make it terminating the line. */
750 *strchrnul (line, '#') = '\0';
751
752 /* If the line is blank it is ignored. */
753 if (line[0] == '\0')
754 continue;
755
756 add_dir (line);
757 } while (!feof (file));
758
759 /* Free buffer and close file. */
760 free (line);
761 fclose (file);
762}
763
764
765int
766main (int argc, char **argv)
767{
768 int remaining;
45eca4d1 769
591e1ffb
UD
770 /* Parse and process arguments. */
771 argp_parse (&argp, argc, argv, 0, &remaining, NULL);
772
b85697f6
UD
773 /* Remaining arguments are additional libraries if opt_manual_link
774 is not set. */
775 if (remaining != argc && !opt_manual_link)
591e1ffb
UD
776 {
777 int i;
778 for (i = remaining; i < argc; ++i)
779 add_dir (argv [i]);
780 }
781
782 if (cache_file == NULL)
783 cache_file = LD_SO_CACHE;
784
785 if (config_file == NULL)
786 config_file = LD_SO_CONF;
45eca4d1 787
591e1ffb
UD
788 /* Chroot first. */
789 if (opt_chroot)
790 {
791 if (chroot (opt_chroot))
792 /* Report failure and exit program. */
793 error (EXIT_FAILURE, errno, _("Can't chroot to %s"), opt_chroot);
794 /* chroot doesn't change the working directory, let's play safe. */
795 if (chdir ("/"))
796 error (EXIT_FAILURE, errno, _("Can't chdir to /"));
797 }
798
799 if (opt_print_cache)
800 {
801 print_cache (cache_file);
802 exit (0);
803 }
804
b85697f6
UD
805 if (opt_manual_link)
806 {
807 /* Link all given libraries manually. */
808 int i;
809
810 for (i = remaining; i < argc; ++i)
811 manual_link (argv [i]);
812
813 exit (0);
814 }
45eca4d1
UD
815
816
591e1ffb
UD
817 if (opt_build_cache)
818 init_cache ();
819
820 if (!opt_only_cline)
821 {
822 /* Always add the standard search paths. */
8ca91b36
UD
823 add_dir (SLIBDIR);
824 if (strcmp (SLIBDIR, LIBDIR))
825 add_dir (LIBDIR);
591e1ffb
UD
826
827 parse_conf (config_file);
828 }
45eca4d1 829
591e1ffb
UD
830 search_dirs ();
831
832 if (opt_build_cache)
833 save_cache (cache_file);
834
835 return 0;
836}
This page took 0.186969 seconds and 5 git commands to generate.