xref: /titanic_41/usr/src/tools/depcheck/get_depend_info (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate#!/usr/bin/perl
2*7c478bd9Sstevel@tonic-gate#
3*7c478bd9Sstevel@tonic-gate# CDDL HEADER START
4*7c478bd9Sstevel@tonic-gate#
5*7c478bd9Sstevel@tonic-gate# The contents of this file are subject to the terms of the
6*7c478bd9Sstevel@tonic-gate# Common Development and Distribution License, Version 1.0 only
7*7c478bd9Sstevel@tonic-gate# (the "License").  You may not use this file except in compliance
8*7c478bd9Sstevel@tonic-gate# with the License.
9*7c478bd9Sstevel@tonic-gate#
10*7c478bd9Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11*7c478bd9Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing.
12*7c478bd9Sstevel@tonic-gate# See the License for the specific language governing permissions
13*7c478bd9Sstevel@tonic-gate# and limitations under the License.
14*7c478bd9Sstevel@tonic-gate#
15*7c478bd9Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each
16*7c478bd9Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17*7c478bd9Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the
18*7c478bd9Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying
19*7c478bd9Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner]
20*7c478bd9Sstevel@tonic-gate#
21*7c478bd9Sstevel@tonic-gate# CDDL HEADER END
22*7c478bd9Sstevel@tonic-gate#
23*7c478bd9Sstevel@tonic-gate#
24*7c478bd9Sstevel@tonic-gate# Copyright (c) 2000 by Sun Microsystems, Inc.
25*7c478bd9Sstevel@tonic-gate# All rights reserved.
26*7c478bd9Sstevel@tonic-gate#
27*7c478bd9Sstevel@tonic-gate
28*7c478bd9Sstevel@tonic-gate# ident	"%Z%%M%	%I%	%E% SMI"
29*7c478bd9Sstevel@tonic-gate
30*7c478bd9Sstevel@tonic-gate#
31*7c478bd9Sstevel@tonic-gate# check for perl5 -- we use things unavailable in perl4
32*7c478bd9Sstevel@tonic-gate#
33*7c478bd9Sstevel@tonic-gate
34*7c478bd9Sstevel@tonic-gatedie "Sorry, this program requires perl version 5.000 or up. You have $]. Stopping" if $] < 5.000;
35*7c478bd9Sstevel@tonic-gate
36*7c478bd9Sstevel@tonic-gate$DBM_DIR_CHARACTERIZATION = "directory for the dbm databases";
37*7c478bd9Sstevel@tonic-gate
38*7c478bd9Sstevel@tonic-gate$Usage =
39*7c478bd9Sstevel@tonic-gate"Usage: get_depend_info
40*7c478bd9Sstevel@tonic-gate  -dbdir <$DBM_DIR_CHARACTERIZATION>  [ -s ] [ -cons ] [ -root directory ]
41*7c478bd9Sstevel@tonic-gate  [ -f ] [ -p ] [ -pkg SUNWxxx ] [ filename ]
42*7c478bd9Sstevel@tonic-gate  [-h for help]\n";
43*7c478bd9Sstevel@tonic-gate
44*7c478bd9Sstevel@tonic-gate$Help =
45*7c478bd9Sstevel@tonic-gate"This program statically analyzes executable files and their
46*7c478bd9Sstevel@tonic-gatesymbolic links using /usr/bin/ldd and /usr/bin/strings.  It
47*7c478bd9Sstevel@tonic-gatecan accept filename(s) or packages as the list of files to be
48*7c478bd9Sstevel@tonic-gateanalyzed.  By default, the program will report the file
49*7c478bd9Sstevel@tonic-gatedependencies and which packages those dependencies came from.
50*7c478bd9Sstevel@tonic-gateThere is one required argument:
51*7c478bd9Sstevel@tonic-gate
52*7c478bd9Sstevel@tonic-gate        -dbdir  <dir>			the $DBM_DIR_CHARACTERIZATION
53*7c478bd9Sstevel@tonic-gate
54*7c478bd9Sstevel@tonic-gateThe optional argument -h produces this message instead of any processing.
55*7c478bd9Sstevel@tonic-gateThe optional argument -cons tells the tool to be conservative and not to
56*7c478bd9Sstevel@tonic-gaterun /usr/bin/strings.
57*7c478bd9Sstevel@tonic-gateThe optional argument -root allows you to specify a new root (useful for
58*7c478bd9Sstevel@tonic-gatedoing analysis on build trees).
59*7c478bd9Sstevel@tonic-gateThe optional argument -pkg allows you to specify a package name.
60*7c478bd9Sstevel@tonic-gateThe optional argument -f only outputs the filename of the dependencies
61*7c478bd9Sstevel@tonic-gateThe optional argument -p only outputs the packanames of the dependencies
62*7c478bd9Sstevel@tonic-gate
63*7c478bd9Sstevel@tonic-gateThe optional argument -s ONLY outputs symbolic links for files or packages.
64*7c478bd9Sstevel@tonic-gateNo ldd or strings analysis is done.
65*7c478bd9Sstevel@tonic-gate
66*7c478bd9Sstevel@tonic-gateSome Examples:
67*7c478bd9Sstevel@tonic-gateget_depend_info -dbdir ./DBM /usr/bin/ls
68*7c478bd9Sstevel@tonic-gateget_depend_info -dbdir ./DBM /usr/bin/*
69*7c478bd9Sstevel@tonic-gateget_depend_info -dbdir ./DBM -pkg SUNWnisu
70*7c478bd9Sstevel@tonic-gateget_depend_info -f -dbdir ./DBM -pkg SUNWnisu
71*7c478bd9Sstevel@tonic-gateget_depend_info -s -dbdir ./DBM /usr/bin/*
72*7c478bd9Sstevel@tonic-gateget_depend_info -s -dbdir ./DBM -pkg SUNWnisu
73*7c478bd9Sstevel@tonic-gate
74*7c478bd9Sstevel@tonic-gate
75*7c478bd9Sstevel@tonic-gateNOTE: Run make_pkg_db to create the database directory for get_depend_info
76*7c478bd9Sstevel@tonic-gate";
77*7c478bd9Sstevel@tonic-gate
78*7c478bd9Sstevel@tonic-gate#
79*7c478bd9Sstevel@tonic-gate# process arguments
80*7c478bd9Sstevel@tonic-gate#
81*7c478bd9Sstevel@tonic-gate
82*7c478bd9Sstevel@tonic-gate@PkgList = "";
83*7c478bd9Sstevel@tonic-gate$PackageOnly = false;
84*7c478bd9Sstevel@tonic-gate$FileOnly = false;
85*7c478bd9Sstevel@tonic-gate$Verbose = true;
86*7c478bd9Sstevel@tonic-gate$Silent = false;
87*7c478bd9Sstevel@tonic-gate$SymLink = false;
88*7c478bd9Sstevel@tonic-gate$NoStrings = false;
89*7c478bd9Sstevel@tonic-gate$Root = "";
90*7c478bd9Sstevel@tonic-gate
91*7c478bd9Sstevel@tonic-gatewhile (@ARGV) {
92*7c478bd9Sstevel@tonic-gate    $arg = shift (@ARGV);
93*7c478bd9Sstevel@tonic-gate    if ($arg eq "-h") {
94*7c478bd9Sstevel@tonic-gate        print "$Help\n$Usage";
95*7c478bd9Sstevel@tonic-gate        exit 0;
96*7c478bd9Sstevel@tonic-gate    } elsif ($arg eq "-dbdir") {
97*7c478bd9Sstevel@tonic-gate        $DBDir = shift(@ARGV) unless ($ARGV[0] =~ /^-/);
98*7c478bd9Sstevel@tonic-gate    } elsif ($arg eq "-s") {
99*7c478bd9Sstevel@tonic-gate	$SymLink = true;
100*7c478bd9Sstevel@tonic-gate	$Silent = true;
101*7c478bd9Sstevel@tonic-gate    } elsif ($arg eq "-p") {
102*7c478bd9Sstevel@tonic-gate	$PackageOnly = true;
103*7c478bd9Sstevel@tonic-gate	$Verbose = false;
104*7c478bd9Sstevel@tonic-gate    } elsif ($arg eq "-f") {
105*7c478bd9Sstevel@tonic-gate	$FileOnly = true;
106*7c478bd9Sstevel@tonic-gate	$Verbose = false;
107*7c478bd9Sstevel@tonic-gate    } elsif ($arg eq "-cons") {
108*7c478bd9Sstevel@tonic-gate	$NoStrings = true;
109*7c478bd9Sstevel@tonic-gate    } elsif ($arg eq "-pkg") {
110*7c478bd9Sstevel@tonic-gate        $PKGName = shift(@ARGV) unless ($ARGV[0] =~ /^-/);
111*7c478bd9Sstevel@tonic-gate    } elsif ($arg eq "-root") {
112*7c478bd9Sstevel@tonic-gate        $Root = shift(@ARGV) unless ($ARGV[0] =~ /^-/);
113*7c478bd9Sstevel@tonic-gate    }else {
114*7c478bd9Sstevel@tonic-gate	push(@filelist, $arg);
115*7c478bd9Sstevel@tonic-gate    }
116*7c478bd9Sstevel@tonic-gate}
117*7c478bd9Sstevel@tonic-gate
118*7c478bd9Sstevel@tonic-gateif (!$DBDir) {
119*7c478bd9Sstevel@tonic-gate    print STDERR "Required argument -dbdir missing. \n$Usage";
120*7c478bd9Sstevel@tonic-gate    exit 1;
121*7c478bd9Sstevel@tonic-gate}
122*7c478bd9Sstevel@tonic-gate
123*7c478bd9Sstevel@tonic-gateif ($PKGName) {
124*7c478bd9Sstevel@tonic-gate    # For a given pkg definition directory, this subroutine will
125*7c478bd9Sstevel@tonic-gate    # go through the proto files and look for executable files.
126*7c478bd9Sstevel@tonic-gate    # It will then put all the executable files into @filelist
127*7c478bd9Sstevel@tonic-gate    &HandlePackageName($PKGName);
128*7c478bd9Sstevel@tonic-gate
129*7c478bd9Sstevel@tonic-gate    if ($PackageOnly eq true) {
130*7c478bd9Sstevel@tonic-gate        $Silent = true;
131*7c478bd9Sstevel@tonic-gate    }
132*7c478bd9Sstevel@tonic-gate}
133*7c478bd9Sstevel@tonic-gate
134*7c478bd9Sstevel@tonic-gate&OpenDBs;
135*7c478bd9Sstevel@tonic-gate
136*7c478bd9Sstevel@tonic-gate$Silent = true if (($Verbose eq false) && ($PackageOnly eq false)
137*7c478bd9Sstevel@tonic-gate			&& ($FileOnly eq false));
138*7c478bd9Sstevel@tonic-gate
139*7c478bd9Sstevel@tonic-gateforeach $entry (@filelist) {
140*7c478bd9Sstevel@tonic-gate
141*7c478bd9Sstevel@tonic-gate	print("\n\nAnalyzing $Root$entry:\n") unless ($Silent eq true);
142*7c478bd9Sstevel@tonic-gate
143*7c478bd9Sstevel@tonic-gate        # make sure file exists
144*7c478bd9Sstevel@tonic-gate	if (!(-r $entry)) {
145*7c478bd9Sstevel@tonic-gate    		print STDERR "Could not open file $entry\n";
146*7c478bd9Sstevel@tonic-gate    		next;
147*7c478bd9Sstevel@tonic-gate	}
148*7c478bd9Sstevel@tonic-gate
149*7c478bd9Sstevel@tonic-gate
150*7c478bd9Sstevel@tonic-gate	$file = $FTYPE{$entry};
151*7c478bd9Sstevel@tonic-gate	$pkgs = $PKGS{$entry};
152*7c478bd9Sstevel@tonic-gate	$abslink = $ABSLINK{$entry};
153*7c478bd9Sstevel@tonic-gate
154*7c478bd9Sstevel@tonic-gate	if ($file eq "d") {
155*7c478bd9Sstevel@tonic-gate		print("Input file is a directory\n") unless ($Silent eq true);
156*7c478bd9Sstevel@tonic-gate    		next;
157*7c478bd9Sstevel@tonic-gate	}
158*7c478bd9Sstevel@tonic-gate
159*7c478bd9Sstevel@tonic-gate	# destfile represents the actual file we are interested in!
160*7c478bd9Sstevel@tonic-gate	if ($abslink =~ /\w/) {
161*7c478bd9Sstevel@tonic-gate		$destfile = $abslink;
162*7c478bd9Sstevel@tonic-gate
163*7c478bd9Sstevel@tonic-gate		if (($FTYPE{$entry} eq "s") && ($SymLink eq true)) {
164*7c478bd9Sstevel@tonic-gate			print("$entry is linked to $destfile:$PKGS{$destfile}\n");
165*7c478bd9Sstevel@tonic-gate		}
166*7c478bd9Sstevel@tonic-gate	}
167*7c478bd9Sstevel@tonic-gate	else {
168*7c478bd9Sstevel@tonic-gate		$destfile = $entry;
169*7c478bd9Sstevel@tonic-gate	}
170*7c478bd9Sstevel@tonic-gate
171*7c478bd9Sstevel@tonic-gate	# if the -s flag is set, tell 'em about sym links and go to the next file
172*7c478bd9Sstevel@tonic-gate	next if ($SymLink eq true);
173*7c478bd9Sstevel@tonic-gate
174*7c478bd9Sstevel@tonic-gate	$mode = $MODE{$destfile};
175*7c478bd9Sstevel@tonic-gate
176*7c478bd9Sstevel@tonic-gate        # Handle the case where the user resets $ROOT
177*7c478bd9Sstevel@tonic-gate	$destfile = "$Root$destfile" if ($Root =~ /\w/);
178*7c478bd9Sstevel@tonic-gate	$filecmd = `/usr/bin/file $destfile 2>&1`;
179*7c478bd9Sstevel@tonic-gate
180*7c478bd9Sstevel@tonic-gate	# make sure we are dealing with an executable
181*7c478bd9Sstevel@tonic-gate	if (($mode !~ /(.)(.*)7/) && ($mode !~ /(.)(.*)5/) && ($mode !~ /(.)(.*)3/) && ($mode !~ /(.)(.*)1/)){
182*7c478bd9Sstevel@tonic-gate		print("Input file is not an executable\n");
183*7c478bd9Sstevel@tonic-gate		next;
184*7c478bd9Sstevel@tonic-gate	}
185*7c478bd9Sstevel@tonic-gate
186*7c478bd9Sstevel@tonic-gate        # Kernel modules are handled separately
187*7c478bd9Sstevel@tonic-gate	if ($destfile =~ /\/kernel\//) {
188*7c478bd9Sstevel@tonic-gate		&HandleKernelMod($destfile, $FTYPE{$entry});
189*7c478bd9Sstevel@tonic-gate		&OutputPackageList if (($PackageOnly eq true) && !($PKGName));
190*7c478bd9Sstevel@tonic-gate		next;
191*7c478bd9Sstevel@tonic-gate	}
192*7c478bd9Sstevel@tonic-gate
193*7c478bd9Sstevel@tonic-gate	# take care of scripts
194*7c478bd9Sstevel@tonic-gate	if (($filecmd =~ /script/) || ($filecmd =~ /text/)) {
195*7c478bd9Sstevel@tonic-gate		&HandleScripts($destfile);
196*7c478bd9Sstevel@tonic-gate		&OutputPackageList if (($PackageOnly eq true) && !($PKGName));
197*7c478bd9Sstevel@tonic-gate		next;
198*7c478bd9Sstevel@tonic-gate	}
199*7c478bd9Sstevel@tonic-gate
200*7c478bd9Sstevel@tonic-gate	# Its not a script, not a kernel module, so its get to be a binary
201*7c478bd9Sstevel@tonic-gate	&HandleBinaries($destfile);
202*7c478bd9Sstevel@tonic-gate	&OutputPackageList if (($PackageOnly eq true) && !($PKGName));
203*7c478bd9Sstevel@tonic-gate}
204*7c478bd9Sstevel@tonic-gate
205*7c478bd9Sstevel@tonic-gateif (($PKGName) && ($SymLink eq false)) {
206*7c478bd9Sstevel@tonic-gate	print ("\n\nPackage dependencies for $PKGName:\n");
207*7c478bd9Sstevel@tonic-gate	&OutputPackageList;
208*7c478bd9Sstevel@tonic-gate}
209*7c478bd9Sstevel@tonic-gate
210*7c478bd9Sstevel@tonic-gate&CloseDBs;
211*7c478bd9Sstevel@tonic-gate
212*7c478bd9Sstevel@tonic-gate#===========================END OF MAIN====================================
213*7c478bd9Sstevel@tonic-gate
214*7c478bd9Sstevel@tonic-gatesub GetLddInfo {		# return multi-line string of ldd info for File
215*7c478bd9Sstevel@tonic-gatelocal ($FileID, $FileType) = @_;
216*7c478bd9Sstevel@tonic-gate
217*7c478bd9Sstevel@tonic-gate    $outstring = "* Not a File\n";
218*7c478bd9Sstevel@tonic-gate    return ($outstring) if $FileType =~ /[Mlsdc]/;	# ldd results not useful here
219*7c478bd9Sstevel@tonic-gate
220*7c478bd9Sstevel@tonic-gate    #
221*7c478bd9Sstevel@tonic-gate    # use map file to see if this is a file that gives a known bad ldd return
222*7c478bd9Sstevel@tonic-gate    #
223*7c478bd9Sstevel@tonic-gate
224*7c478bd9Sstevel@tonic-gate#    if ($Unsup{$FileID} == 1) {
225*7c478bd9Sstevel@tonic-gate#	$outstring = "* unsupported or unknown file type, per map file";
226*7c478bd9Sstevel@tonic-gate#	return ($outstring);
227*7c478bd9Sstevel@tonic-gate#    }
228*7c478bd9Sstevel@tonic-gate#    $err = "";
229*7c478bd9Sstevel@tonic-gate#    $string = `/usr/bin/ldd $FileID 2>&1`;
230*7c478bd9Sstevel@tonic-gate#    if ($?) {	# if some error (don't just get wait status here)
231*7c478bd9Sstevel@tonic-gate#	$errnum = 0 + $!;
232*7c478bd9Sstevel@tonic-gate#	$err = "==$?==$errnum==";
233*7c478bd9Sstevel@tonic-gate#	if (($err eq "==256==29==") || ($err eq "==256==0==")) {
234*7c478bd9Sstevel@tonic-gate#	    $err = "*";			# these are normal ldd returns
235*7c478bd9Sstevel@tonic-gate#	} else {
236*7c478bd9Sstevel@tonic-gate#	    die "Unexpected ldd return $? $!";
237*7c478bd9Sstevel@tonic-gate#	}
238*7c478bd9Sstevel@tonic-gate#	$string =~ s/\/usr\/bin\/ldd:[^\0]*://g;	# trim up error line
239*7c478bd9Sstevel@tonic-gate#    } elsif ($string =~ s/warning:.*://) {	# other normal ldd returns
240*7c478bd9Sstevel@tonic-gate#	$err = "*";
241*7c478bd9Sstevel@tonic-gate#    }
242*7c478bd9Sstevel@tonic-gate
243*7c478bd9Sstevel@tonic-gate    $outstring = "";
244*7c478bd9Sstevel@tonic-gate    $string = `/usr/bin/ldd $FileID 2>&1`;
245*7c478bd9Sstevel@tonic-gate    # on a non-zero ldd, return nothing
246*7c478bd9Sstevel@tonic-gate    return ($outstring) if ($?);
247*7c478bd9Sstevel@tonic-gate
248*7c478bd9Sstevel@tonic-gate
249*7c478bd9Sstevel@tonic-gate    $outstring = "";
250*7c478bd9Sstevel@tonic-gate    @infolines = split(/\s*\n\s*/, $string);
251*7c478bd9Sstevel@tonic-gate    foreach $line (@infolines) {
252*7c478bd9Sstevel@tonic-gate	$line =~ s/^\s+//;			# trim leading ws
253*7c478bd9Sstevel@tonic-gate	next unless $line;			# skip if blank
254*7c478bd9Sstevel@tonic-gate	@words = split(/\s/, $line);
255*7c478bd9Sstevel@tonic-gate	$filename = $words[0];
256*7c478bd9Sstevel@tonic-gate	$outstring .= "$filename\n";
257*7c478bd9Sstevel@tonic-gate    }
258*7c478bd9Sstevel@tonic-gate    return ($outstring);
259*7c478bd9Sstevel@tonic-gate}
260*7c478bd9Sstevel@tonic-gate
261*7c478bd9Sstevel@tonic-gatesub CloseDBs {
262*7c478bd9Sstevel@tonic-gate	# close the dbs
263*7c478bd9Sstevel@tonic-gate	dbmclose(FTYPE);
264*7c478bd9Sstevel@tonic-gate	dbmclose(MODE);
265*7c478bd9Sstevel@tonic-gate	dbmclose(PKGS);
266*7c478bd9Sstevel@tonic-gate	dbmclose(ABSLINK);
267*7c478bd9Sstevel@tonic-gate	dbmclose(PKGNAMES);
268*7c478bd9Sstevel@tonic-gate}
269*7c478bd9Sstevel@tonic-gate
270*7c478bd9Sstevel@tonic-gatesub OpenDBs {
271*7c478bd9Sstevel@tonic-gate	# open the databases for read-only
272*7c478bd9Sstevel@tonic-gate	dbmopen(%FTYPE, "$DBDir/FTYPE", 0664) ||
273*7c478bd9Sstevel@tonic-gate		die"Cannot open dbm db $DBDir/FTYPE\n";
274*7c478bd9Sstevel@tonic-gate
275*7c478bd9Sstevel@tonic-gate	dbmopen(%MODE, "$DBDir/MODE", 0664) ||
276*7c478bd9Sstevel@tonic-gate		die"Cannot open dbm db $DBDir/MODE\n";
277*7c478bd9Sstevel@tonic-gate
278*7c478bd9Sstevel@tonic-gate	dbmopen(%PKGS, "$DBDir/PKGS", 0664) ||
279*7c478bd9Sstevel@tonic-gate		die"Cannot open dbm db $DBDir/PKGS\n";
280*7c478bd9Sstevel@tonic-gate
281*7c478bd9Sstevel@tonic-gate	dbmopen(%ABSLINK, "$DBDir/ABSLINK", 0664) ||
282*7c478bd9Sstevel@tonic-gate		die"Cannot open dbm db $DBDir/ABSLINK \n";
283*7c478bd9Sstevel@tonic-gate
284*7c478bd9Sstevel@tonic-gate	dbmopen(%PKGNAMES, "$DBDir/PKGNAMES", 0644) ||
285*7c478bd9Sstevel@tonic-gate		die"Cannot open dbm db $DBDir/PKGNAMES\n";
286*7c478bd9Sstevel@tonic-gate}
287*7c478bd9Sstevel@tonic-gate
288*7c478bd9Sstevel@tonic-gatesub HandleKernelMod {
289*7c478bd9Sstevel@tonic-gatelocal ($entry, $ftype) = @_;
290*7c478bd9Sstevel@tonic-gate
291*7c478bd9Sstevel@tonic-gate	# search for the magic right, starting from the right (ie. end of path)
292*7c478bd9Sstevel@tonic-gate	$index = rindex($entry, "kernel");
293*7c478bd9Sstevel@tonic-gate	# rindex() returns where the "kernel" began, add 6 to get
294*7c478bd9Sstevel@tonic-gate	# "{some path}/kernel"
295*7c478bd9Sstevel@tonic-gate	$index += 6;
296*7c478bd9Sstevel@tonic-gate	# OK, now pull out the absolute path
297*7c478bd9Sstevel@tonic-gate	$KernelPath = substr($entry, 0, $index);
298*7c478bd9Sstevel@tonic-gate
299*7c478bd9Sstevel@tonic-gate	# There are two ways to figure out the dependencies.
300*7c478bd9Sstevel@tonic-gate	# First, we check to see if /usr/bin/ldd will tell us.
301*7c478bd9Sstevel@tonic-gate	# If ldd fails, then we need to look at the output of /usr/bin/strings
302*7c478bd9Sstevel@tonic-gate
303*7c478bd9Sstevel@tonic-gate	$LddInfo = "";
304*7c478bd9Sstevel@tonic-gate	$LddInfo = &GetLddInfo($entry, $ftype);
305*7c478bd9Sstevel@tonic-gate
306*7c478bd9Sstevel@tonic-gate	if ($LddInfo =~ /\w/) {
307*7c478bd9Sstevel@tonic-gate		@list = "";
308*7c478bd9Sstevel@tonic-gate		@list = split(/\n/, $LddInfo);
309*7c478bd9Sstevel@tonic-gate		foreach $file (@list) {
310*7c478bd9Sstevel@tonic-gate			$found = 0;
311*7c478bd9Sstevel@tonic-gate
312*7c478bd9Sstevel@tonic-gate			# first, check to see if there is a module relative to
313*7c478bd9Sstevel@tonic-gate			# this file
314*7c478bd9Sstevel@tonic-gate			if ($FTYPE{"$KernelPath/$file"} =~ /\w/){
315*7c478bd9Sstevel@tonic-gate				&Output("$KernelPath/$file");
316*7c478bd9Sstevel@tonic-gate				$found++;
317*7c478bd9Sstevel@tonic-gate			}
318*7c478bd9Sstevel@tonic-gate
319*7c478bd9Sstevel@tonic-gate			# Haven't found it yet, check /kernel
320*7c478bd9Sstevel@tonic-gate			if (($FTYPE{"/kernel/$file"} =~ /\w/) && ($found == 0)){
321*7c478bd9Sstevel@tonic-gate				&Output("/kernel/$file");
322*7c478bd9Sstevel@tonic-gate				$found++;
323*7c478bd9Sstevel@tonic-gate			}
324*7c478bd9Sstevel@tonic-gate
325*7c478bd9Sstevel@tonic-gate			# Haven't found it yet, check /usr/kernel
326*7c478bd9Sstevel@tonic-gate			if (($FTYPE{"/usr/kernel/$file"} =~ /\w/) && ($found == 0)){
327*7c478bd9Sstevel@tonic-gate				&Output("/usr/kernel/$file");
328*7c478bd9Sstevel@tonic-gate				$found++;
329*7c478bd9Sstevel@tonic-gate			}
330*7c478bd9Sstevel@tonic-gate
331*7c478bd9Sstevel@tonic-gate			if ($found == 0) {
332*7c478bd9Sstevel@tonic-gate				print("Could not resolve $file\n");
333*7c478bd9Sstevel@tonic-gate			}
334*7c478bd9Sstevel@tonic-gate		}
335*7c478bd9Sstevel@tonic-gate		return;
336*7c478bd9Sstevel@tonic-gate	}
337*7c478bd9Sstevel@tonic-gate
338*7c478bd9Sstevel@tonic-gate	# the ldd failed, so now let's look at the string output
339*7c478bd9Sstevel@tonic-gate	$string = "";
340*7c478bd9Sstevel@tonic-gate	@infolines = "";
341*7c478bd9Sstevel@tonic-gate	@outlines = "";
342*7c478bd9Sstevel@tonic-gate
343*7c478bd9Sstevel@tonic-gate    	$string = `/usr/bin/strings $entry 2>&1`;
344*7c478bd9Sstevel@tonic-gate    	@infolines = split(/\s*\n\s*/, $string);
345*7c478bd9Sstevel@tonic-gate
346*7c478bd9Sstevel@tonic-gate	foreach $line (@infolines) {
347*7c478bd9Sstevel@tonic-gate		if ($line =~ /\//){
348*7c478bd9Sstevel@tonic-gate			push (@outlines,$line);
349*7c478bd9Sstevel@tonic-gate		}
350*7c478bd9Sstevel@tonic-gate    	}
351*7c478bd9Sstevel@tonic-gate
352*7c478bd9Sstevel@tonic-gate	foreach $line (@outlines) {
353*7c478bd9Sstevel@tonic-gate		@words = split(/\s/, $line);
354*7c478bd9Sstevel@tonic-gate		foreach $word (@words) {
355*7c478bd9Sstevel@tonic-gate			$found = 0;
356*7c478bd9Sstevel@tonic-gate
357*7c478bd9Sstevel@tonic-gate			# first, check to see if there is a module relative to
358*7c478bd9Sstevel@tonic-gate			# this file
359*7c478bd9Sstevel@tonic-gate			if ($FTYPE{"$KernelPath/$word"} =~ /\w/){
360*7c478bd9Sstevel@tonic-gate				&Output("$KernelPath/$word");
361*7c478bd9Sstevel@tonic-gate				$found++;
362*7c478bd9Sstevel@tonic-gate			}
363*7c478bd9Sstevel@tonic-gate
364*7c478bd9Sstevel@tonic-gate			# Haven't found it yet, check /kernel
365*7c478bd9Sstevel@tonic-gate			if (($FTYPE{"/kernel/$word"} =~ /\w/) && ($found == 0)){
366*7c478bd9Sstevel@tonic-gate				&Output("/kernel/$word");
367*7c478bd9Sstevel@tonic-gate				$found++;
368*7c478bd9Sstevel@tonic-gate			}
369*7c478bd9Sstevel@tonic-gate
370*7c478bd9Sstevel@tonic-gate			# Haven't found it yet, check /usr/kernel
371*7c478bd9Sstevel@tonic-gate			if (($FTYPE{"/usr/kernel/$word"} =~ /\w/) && ($found == 0)){
372*7c478bd9Sstevel@tonic-gate				&Output("/usr/kernel/$word");
373*7c478bd9Sstevel@tonic-gate				$found++;
374*7c478bd9Sstevel@tonic-gate			}
375*7c478bd9Sstevel@tonic-gate		}
376*7c478bd9Sstevel@tonic-gate	}
377*7c478bd9Sstevel@tonic-gate}
378*7c478bd9Sstevel@tonic-gate
379*7c478bd9Sstevel@tonic-gatesub GetStringsInfo {		# return multi-line string of ldd info for File
380*7c478bd9Sstevel@tonic-gatelocal ($FileID, $FileType) = @_;
381*7c478bd9Sstevel@tonic-gate
382*7c478bd9Sstevel@tonic-gate    $outstring = "* Not a File\n";
383*7c478bd9Sstevel@tonic-gate    return ($outstring) if $FileType =~ /[Mlsdc]/;	# ldd results not useful here
384*7c478bd9Sstevel@tonic-gate    return ($outstring) if ($NoStrings eq true);	# we are running in conservative mode
385*7c478bd9Sstevel@tonic-gate
386*7c478bd9Sstevel@tonic-gate    # use map file to see if this is a file that gives a known bad ldd return
387*7c478bd9Sstevel@tonic-gate    if ($Unsup{$FileID} == 1) {
388*7c478bd9Sstevel@tonic-gate	$outstring = "* unsupported or unknown file type, per map file";
389*7c478bd9Sstevel@tonic-gate	return ($outstring);
390*7c478bd9Sstevel@tonic-gate    }
391*7c478bd9Sstevel@tonic-gate    $err = "";
392*7c478bd9Sstevel@tonic-gate    $string = "";
393*7c478bd9Sstevel@tonic-gate    $string = `/usr/bin/strings $FileID 2>&1`;
394*7c478bd9Sstevel@tonic-gate
395*7c478bd9Sstevel@tonic-gate    $outstring = "";
396*7c478bd9Sstevel@tonic-gate    @infolines = "";
397*7c478bd9Sstevel@tonic-gate    @outlines = "";
398*7c478bd9Sstevel@tonic-gate    @infolines = split(/\s*\n\s*/, $string);
399*7c478bd9Sstevel@tonic-gate
400*7c478bd9Sstevel@tonic-gate    foreach $line (@infolines) {
401*7c478bd9Sstevel@tonic-gate	if (($line =~ /\//) && !($line =~ /%/) && !($line =~ m%/$%)){
402*7c478bd9Sstevel@tonic-gate		push (@outlines,$line);
403*7c478bd9Sstevel@tonic-gate        }
404*7c478bd9Sstevel@tonic-gate    }
405*7c478bd9Sstevel@tonic-gate    @outlines = sort(@outlines);
406*7c478bd9Sstevel@tonic-gate
407*7c478bd9Sstevel@tonic-gate    foreach $word (@outlines) {
408*7c478bd9Sstevel@tonic-gate	if ($lastword ne $word) {
409*7c478bd9Sstevel@tonic-gate		$outstring .= $word; $outstring .= "\n";
410*7c478bd9Sstevel@tonic-gate	}
411*7c478bd9Sstevel@tonic-gate	$lastword = $word;
412*7c478bd9Sstevel@tonic-gate    }
413*7c478bd9Sstevel@tonic-gate    return ($outstring);
414*7c478bd9Sstevel@tonic-gate}
415*7c478bd9Sstevel@tonic-gate
416*7c478bd9Sstevel@tonic-gatesub HandleScripts {
417*7c478bd9Sstevel@tonic-gatelocal ($filename) = @_;
418*7c478bd9Sstevel@tonic-gate	open(SCRIPT, $filename);
419*7c478bd9Sstevel@tonic-gate
420*7c478bd9Sstevel@tonic-gate	undef @output;
421*7c478bd9Sstevel@tonic-gate	while (<SCRIPT>) {
422*7c478bd9Sstevel@tonic-gate		s/^\s+//;		# trim leading ws
423*7c478bd9Sstevel@tonic-gate		s/=/ /g;		# get rid of all =
424*7c478bd9Sstevel@tonic-gate		s/\`/ /g;		# get rid of all `
425*7c478bd9Sstevel@tonic-gate		next if ($_ =~ /^#/);	# strip out obvious comments
426*7c478bd9Sstevel@tonic-gate		next unless $_;		# skip if blank
427*7c478bd9Sstevel@tonic-gate
428*7c478bd9Sstevel@tonic-gate		$line = $_;
429*7c478bd9Sstevel@tonic-gate		@words = split(/\s/, $line);
430*7c478bd9Sstevel@tonic-gate		foreach $word (@words) {
431*7c478bd9Sstevel@tonic-gate			if (($PKGS{$word} =~ /\w/) && ($FTYPE{$word} ne "d")) {
432*7c478bd9Sstevel@tonic-gate				push(@output, $word);
433*7c478bd9Sstevel@tonic-gate			}
434*7c478bd9Sstevel@tonic-gate		}
435*7c478bd9Sstevel@tonic-gate	}
436*7c478bd9Sstevel@tonic-gate
437*7c478bd9Sstevel@tonic-gate	@output = sort(@output);
438*7c478bd9Sstevel@tonic-gate	$count = 0;
439*7c478bd9Sstevel@tonic-gate
440*7c478bd9Sstevel@tonic-gate	# make sure we don't output dupes
441*7c478bd9Sstevel@tonic-gate	foreach $file (@output) {
442*7c478bd9Sstevel@tonic-gate		if ($count == 0) {
443*7c478bd9Sstevel@tonic-gate			&Output($file);
444*7c478bd9Sstevel@tonic-gate		}
445*7c478bd9Sstevel@tonic-gate
446*7c478bd9Sstevel@tonic-gate		if (($count > 0) && ($output[$count] ne $output[$count-1])) {
447*7c478bd9Sstevel@tonic-gate			&Output($file);
448*7c478bd9Sstevel@tonic-gate		}
449*7c478bd9Sstevel@tonic-gate		$count++;
450*7c478bd9Sstevel@tonic-gate	}
451*7c478bd9Sstevel@tonic-gate
452*7c478bd9Sstevel@tonic-gate	# remember to play nice
453*7c478bd9Sstevel@tonic-gate	close(SCRIPT);
454*7c478bd9Sstevel@tonic-gate}
455*7c478bd9Sstevel@tonic-gate
456*7c478bd9Sstevel@tonic-gatesub HandleBinaries {
457*7c478bd9Sstevel@tonic-gatelocal ($filename) = @_;
458*7c478bd9Sstevel@tonic-gate	$LddInfo = &GetLddInfo($destfile, $FTYPE{$filename});
459*7c478bd9Sstevel@tonic-gate	$StringInfo = &GetStringsInfo($destfile, $FTYPE{$filename});
460*7c478bd9Sstevel@tonic-gate
461*7c478bd9Sstevel@tonic-gate	# Parse the ldd output.
462*7c478bd9Sstevel@tonic-gate	# Libs can be found in /kernel or /usr/lib
463*7c478bd9Sstevel@tonic-gate	@list = split(/\n/, $LddInfo);
464*7c478bd9Sstevel@tonic-gate	foreach $file (@list) {
465*7c478bd9Sstevel@tonic-gate		$found = 0;
466*7c478bd9Sstevel@tonic-gate		if ($FTYPE{"/kernel/$file"} =~ /\w/){
467*7c478bd9Sstevel@tonic-gate			&Output("/kernel/$file");
468*7c478bd9Sstevel@tonic-gate			$found++;
469*7c478bd9Sstevel@tonic-gate		}
470*7c478bd9Sstevel@tonic-gate
471*7c478bd9Sstevel@tonic-gate		if ($FTYPE{"/usr/lib/$file"} =~ /\w/){
472*7c478bd9Sstevel@tonic-gate			&Output("/usr/lib/$file");
473*7c478bd9Sstevel@tonic-gate			$found++;
474*7c478bd9Sstevel@tonic-gate		}
475*7c478bd9Sstevel@tonic-gate
476*7c478bd9Sstevel@tonic-gate		if ($found == 0) {
477*7c478bd9Sstevel@tonic-gate			print("Could not resolve $file\n");
478*7c478bd9Sstevel@tonic-gate		}
479*7c478bd9Sstevel@tonic-gate	}
480*7c478bd9Sstevel@tonic-gate
481*7c478bd9Sstevel@tonic-gate	# For the strings output, we parse it to see if we can match it to
482*7c478bd9Sstevel@tonic-gate	# any files distributed in a package.
483*7c478bd9Sstevel@tonic-gate	@list = split(/\n/, $StringInfo);
484*7c478bd9Sstevel@tonic-gate	foreach $file (@list) {
485*7c478bd9Sstevel@tonic-gate		if (($FTYPE{$file} =~ /\w/) && ($FTYPE{$file} ne "d")) {
486*7c478bd9Sstevel@tonic-gate			&Output($file);
487*7c478bd9Sstevel@tonic-gate		}
488*7c478bd9Sstevel@tonic-gate	}
489*7c478bd9Sstevel@tonic-gate}
490*7c478bd9Sstevel@tonic-gate
491*7c478bd9Sstevel@tonic-gatesub Output {
492*7c478bd9Sstevel@tonic-gatelocal($filename) = @_;
493*7c478bd9Sstevel@tonic-gate
494*7c478bd9Sstevel@tonic-gate        # If they want a package listing, a unique sorted list
495*7c478bd9Sstevel@tonic-gate        # will be outputted later.  Here we simply push elements onto
496*7c478bd9Sstevel@tonic-gate	# this list.
497*7c478bd9Sstevel@tonic-gate	if ($PKGName) {
498*7c478bd9Sstevel@tonic-gate		push(@PkgList, "$PKGS{$filename}\n");
499*7c478bd9Sstevel@tonic-gate	}
500*7c478bd9Sstevel@tonic-gate
501*7c478bd9Sstevel@tonic-gate	if ($Verbose eq true) {
502*7c478bd9Sstevel@tonic-gate		print("$filename:$PKGS{$filename}\n");
503*7c478bd9Sstevel@tonic-gate		return;
504*7c478bd9Sstevel@tonic-gate	}
505*7c478bd9Sstevel@tonic-gate
506*7c478bd9Sstevel@tonic-gate        # If they want a package listing, a unique sorted list
507*7c478bd9Sstevel@tonic-gate        # will be outputted later.  Here we simply push elements onto
508*7c478bd9Sstevel@tonic-gate	# this list.
509*7c478bd9Sstevel@tonic-gate	if ($PackageOnly eq true) {
510*7c478bd9Sstevel@tonic-gate		push(@PkgList, "$PKGS{$filename}\n");
511*7c478bd9Sstevel@tonic-gate		return;
512*7c478bd9Sstevel@tonic-gate	}
513*7c478bd9Sstevel@tonic-gate
514*7c478bd9Sstevel@tonic-gate	if ($FileOnly eq true) {
515*7c478bd9Sstevel@tonic-gate		print("$filename\n");
516*7c478bd9Sstevel@tonic-gate		return;
517*7c478bd9Sstevel@tonic-gate	}
518*7c478bd9Sstevel@tonic-gate}
519*7c478bd9Sstevel@tonic-gate
520*7c478bd9Sstevel@tonic-gatesub HandlePackageName {
521*7c478bd9Sstevel@tonic-gatelocal($pkg) = @_;
522*7c478bd9Sstevel@tonic-gate	$pkgchk = `/usr/sbin/pkgchk -l $pkg | grep Pathname | sed 's/Pathname: //'`;
523*7c478bd9Sstevel@tonic-gate
524*7c478bd9Sstevel@tonic-gate	@files = split(/\n/, $pkgchk);
525*7c478bd9Sstevel@tonic-gate	foreach $file (@files) {
526*7c478bd9Sstevel@tonic-gate		push(@filelist, $file);
527*7c478bd9Sstevel@tonic-gate	}
528*7c478bd9Sstevel@tonic-gate}
529*7c478bd9Sstevel@tonic-gate
530*7c478bd9Sstevel@tonic-gatesub OutputPackageList {
531*7c478bd9Sstevel@tonic-gatelocal($filename) = @_;
532*7c478bd9Sstevel@tonic-gate	# If the user specified a package list, here we sort
533*7c478bd9Sstevel@tonic-gate	# the list and make sure we don't output dupes.
534*7c478bd9Sstevel@tonic-gate	$lastpkg = "";
535*7c478bd9Sstevel@tonic-gate	@outPkgs = sort(@PkgList);
536*7c478bd9Sstevel@tonic-gate
537*7c478bd9Sstevel@tonic-gate	foreach $pkg (@outPkgs) {
538*7c478bd9Sstevel@tonic-gate		$pkg =~ s/\s*$//;   # trim extra space off the end
539*7c478bd9Sstevel@tonic-gate
540*7c478bd9Sstevel@tonic-gate		# make sure this entry isn't a dupe before
541*7c478bd9Sstevel@tonic-gate		# printing it
542*7c478bd9Sstevel@tonic-gate		if ($lastpkg ne $pkg) {
543*7c478bd9Sstevel@tonic-gate			print("P $pkg\t$PKGNAMES{$pkg}\n");
544*7c478bd9Sstevel@tonic-gate		}
545*7c478bd9Sstevel@tonic-gate
546*7c478bd9Sstevel@tonic-gate		$lastpkg = $pkg;
547*7c478bd9Sstevel@tonic-gate	}
548*7c478bd9Sstevel@tonic-gate
549*7c478bd9Sstevel@tonic-gate	# reset the list for the next entry
550*7c478bd9Sstevel@tonic-gate	@PkgList = "";
551*7c478bd9Sstevel@tonic-gate}
552*7c478bd9Sstevel@tonic-gate
553