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