/* Dump dynamic linker configuration. Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc. This file is based on part of the GNU C Library. Contributed by Andreas Jaeger , 1999. Modified by Dmitry V. Levin , 2004. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include void * xmalloc (size_t size) { void *r = malloc (size); if (!r) error (EXIT_FAILURE, errno, "malloc"); return r; } void * xrealloc (void *ptr, size_t size) { void *r = realloc (ptr, size); if (!r) error (EXIT_FAILURE, errno, "realloc"); return r; } char * xstrdup (const char *s) { char *r = strdup (s); if (!r) error (EXIT_FAILURE, errno, "strdup"); return r; } /* List of directories to handle. */ struct dir_entry { struct dir_entry *next; const char *name; }; struct dir_entry *path_list_head, *path_list_tail; static void path_list_add (const char *path) { struct dir_entry *e; #ifndef KEEP_DUPLICATES for (e = path_list_head; e; e = e->next) if (!strcmp (path, e->name)) return; #endif struct stat buf; if (stat (path, &buf)) return; e = xmalloc (sizeof (*e)); e->next = 0; e->name = xstrdup (path); if (!path_list_head) path_list_head = e; if (path_list_tail) path_list_tail->next = e; path_list_tail = e; } static void parse_path_line (char *line) { /* Skip leading space characters */ while (isspace (*line)) ++line; /* Search for an '=' sign. */ char *equal_sign = strchr (line, '='); if (equal_sign) *equal_sign = '\0'; int i = strlen (line) - 1; /* Remove trailing space characters */ for (; i >= 0 && isspace (line[i]); --i) line[i] = '\0'; /* Remove trailing slashes */ for (; i > 0 && line[i] == '/'; --i) line[i] = '\0'; if (line[0] != '\0') path_list_add (line); } static void parse_file (const char *filename); static void parse_include_pattern (const char *filename, const char *pattern) { char *newp = NULL, *p; if (pattern[0] != '/' && (p = strrchr (filename, '/'))) { size_t patlen = strlen (pattern) + 1; newp = xmalloc (p - filename + 1 + patlen); memcpy (newp, filename, p - filename + 1); memcpy (newp + (p - filename + 1), pattern, patlen); pattern = newp; } glob_t gl; if (glob (pattern, 0, NULL, &gl) == 0) { size_t i; for (i = 0; i < gl.gl_pathc; ++i) parse_file (gl.gl_pathv[i]); globfree (&gl); } free (newp); } static void parse_include_line (const char *filename, char *line) { char *arg; while ((arg = strsep (&line, " \t")) != NULL) if (arg[0] != '\0') parse_include_pattern (filename, arg); } static void parse_file (const char *filename) { FILE *fp = fopen (filename, "r"); if (fp == NULL) return; char *line = 0; size_t linesize = 0; while (getline (&line, &linesize, fp) > 0) { char *p = strchr (line, '\n'); if (p) *p = '\0'; /* Because the file format does not know any form of quoting we can search forward for the next '#' character and if found make it terminating the line. */ p = strchr (line, '#'); if (p) *p = '\0'; /* Skip leading whitespace characters. */ for (p = line; isspace (*p); ++p) ; /* If the line is blank it is ignored. */ if (p[0] == '\0') continue; if (!strncmp (p, "include", 7) && isblank (p[7])) parse_include_line (filename, p + 8); else parse_path_line (p); } free (line); fclose (fp); } int main (int ac, const char **av) { const char *fname = (ac > 1) ? av[1] : "/etc/ld.so.conf"; parse_file (fname); struct dir_entry *e; for (e = path_list_head; e; e = e->next) puts (e->name); return 0; }