2006-01-09 23:55:49 +03:00
/*
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 < aj @ suse . de > , 1999.
Modified by Dmitry V . Levin < ldv @ altlinux . org > , 2004 , 2006.
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 <string.h>
# include <stdlib.h>
# include <stdio.h>
# include <errno.h>
# include <error.h>
# include <ctype.h>
# include <glob.h>
# include <sys/stat.h>
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 )
{
size_t len = strlen ( s ) ;
char * r = xmalloc ( len + 1 ) ;
memcpy ( r , s , len + 1 ) ;
return r ;
}
/* List of directories to handle. */
struct dir_entry
{
struct dir_entry * next ;
const char * name ;
} ;
static struct dir_entry * path_list_head , * path_list_tail ;
static const char * prefix ;
static void
path_list_add ( const char * path )
{
if ( path [ 0 ] ! = ' / ' )
return ;
struct dir_entry * e ;
# ifndef KEEP_DUPLICATES
for ( e = path_list_head ; e ; e = e - > next )
if ( ! strcmp ( path , e - > name ) )
return ;
# endif
char * newp = NULL ;
if ( prefix )
{
newp = xmalloc ( strlen ( prefix ) + strlen ( path ) + 1 ) ;
strcpy ( newp , prefix ) ;
strcat ( newp , path ) ;
path = newp ;
}
struct stat buf ;
if ( stat ( path , & buf ) )
{
free ( newp ) ;
return ;
}
e = xmalloc ( sizeof ( * e ) ) ;
e - > next = 0 ;
2006-01-11 03:50:33 +03:00
e - > name = xstrdup ( prefix ? ( path + strlen ( prefix ) ) : path ) ;
2006-01-09 23:55:49 +03:00
if ( ! path_list_head )
path_list_head = e ;
if ( path_list_tail )
path_list_tail - > next = e ;
path_list_tail = e ;
free ( newp ) ;
}
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 ] = = ' / ' )
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 ;
2006-01-12 14:58:59 +03:00
if ( prefix )
2006-01-09 23:55:49 +03:00
{
2006-01-12 14:58:59 +03:00
if ( pattern [ 0 ] = = ' / ' )
{
newp = xmalloc ( strlen ( prefix ) + strlen ( pattern ) + 1 ) ;
strcpy ( newp , prefix ) ;
strcat ( newp , pattern ) ;
pattern = newp ;
} else if ( ( p = strrchr ( filename , ' / ' ) ) )
{
size_t preflen = strlen ( prefix ) ;
size_t patlen = strlen ( pattern ) + 1 ;
newp = xmalloc ( p - filename + 1 + preflen + patlen ) ;
memcpy ( newp , prefix , preflen ) ;
memcpy ( newp + preflen , filename , p - filename + 1 ) ;
memcpy ( newp + ( p - filename + 1 + preflen ) , pattern ,
patlen ) ;
pattern = newp ;
}
} else
2006-01-09 23:55:49 +03:00
{
2006-01-12 14:58:59 +03:00
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 ;
}
2006-01-09 23:55:49 +03:00
}
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 , char * * av )
{
const char * fname = " /etc/ld.so.conf " ;
if ( ac > 3 )
return 1 ;
if ( ac > 2 )
{
int len = strlen ( av [ 2 ] ) - 1 ;
/* Remove trailing slashes */
for ( ; len > 0 & & av [ 2 ] [ len ] = = ' / ' ; - - len )
av [ 2 ] [ len ] = ' \0 ' ;
if ( len < 1 | | av [ 2 ] [ 0 ] ! = ' / ' )
return 1 ;
prefix = av [ 2 ] ;
}
2006-01-12 14:58:59 +03:00
if ( ac > 1 & & av [ 1 ] [ 0 ] )
2006-01-09 23:55:49 +03:00
fname = av [ 1 ] ;
parse_file ( fname ) ;
# if defined(SLIBDIR) && defined(LIBDIR)
/* Always add the standard search paths. */
path_list_add ( SLIBDIR ) ;
if ( strcmp ( SLIBDIR , LIBDIR ) )
path_list_add ( LIBDIR ) ;
# endif
struct dir_entry * e ;
for ( e = path_list_head ; e ; e = e - > next )
puts ( e - > name ) ;
return 0 ;
}