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