17c478bd9Sstevel@tonic-gate#!/usr/perl5/bin/perl -w
27c478bd9Sstevel@tonic-gate#
37c478bd9Sstevel@tonic-gate# CDDL HEADER START
47c478bd9Sstevel@tonic-gate#
57c478bd9Sstevel@tonic-gate# The contents of this file are subject to the terms of the
67c478bd9Sstevel@tonic-gate# Common Development and Distribution License, Version 1.0 only
77c478bd9Sstevel@tonic-gate# (the "License").  You may not use this file except in compliance
87c478bd9Sstevel@tonic-gate# with the License.
97c478bd9Sstevel@tonic-gate#
107c478bd9Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
117c478bd9Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing.
127c478bd9Sstevel@tonic-gate# See the License for the specific language governing permissions
137c478bd9Sstevel@tonic-gate# and limitations under the License.
147c478bd9Sstevel@tonic-gate#
157c478bd9Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each
167c478bd9Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
177c478bd9Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the
187c478bd9Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying
197c478bd9Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner]
207c478bd9Sstevel@tonic-gate#
217c478bd9Sstevel@tonic-gate# CDDL HEADER END
227c478bd9Sstevel@tonic-gate#
237c478bd9Sstevel@tonic-gate# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate# Use is subject to license terms.
257c478bd9Sstevel@tonic-gate#
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate#
287c478bd9Sstevel@tonic-gate# This utility program reads the contents file to extract Solaris ELF
297c478bd9Sstevel@tonic-gate# libraries, and then runs pvs(1) on them to find the library versioning
307c478bd9Sstevel@tonic-gate# information (if any).  This info is printed to stdout in an index file
317c478bd9Sstevel@tonic-gate# format.
327c478bd9Sstevel@tonic-gate#
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gaterequire 5.005;
357c478bd9Sstevel@tonic-gateuse strict;
367c478bd9Sstevel@tonic-gateuse locale;
377c478bd9Sstevel@tonic-gateuse POSIX qw(locale_h);
387c478bd9Sstevel@tonic-gateuse Sun::Solaris::Utils qw(textdomain gettext);
397c478bd9Sstevel@tonic-gateuse File::Basename;
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gateuse vars qw(
427c478bd9Sstevel@tonic-gate	@liblist
437c478bd9Sstevel@tonic-gate	%symlink
447c478bd9Sstevel@tonic-gate	%inode_hash
457c478bd9Sstevel@tonic-gate	%fileoutput
467c478bd9Sstevel@tonic-gate	%didlib
477c478bd9Sstevel@tonic-gate);
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gatesetlocale(LC_ALL, "");
507c478bd9Sstevel@tonic-gatetextdomain(TEXT_DOMAIN);
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate# parameters for what types of libraries to list out:
537c478bd9Sstevel@tonic-gatemy $must_be_versioned = 0;
547c478bd9Sstevel@tonic-gatemy $must_be_public = 0;
557c478bd9Sstevel@tonic-gate
567c478bd9Sstevel@tonic-gate# paths to skip outright.
577c478bd9Sstevel@tonic-gatemy @skip_list = qw(
587c478bd9Sstevel@tonic-gate	/etc
597c478bd9Sstevel@tonic-gate	/usr/perl5
607c478bd9Sstevel@tonic-gate);
617c478bd9Sstevel@tonic-gatemy $path_skip = join('|', @skip_list);
627c478bd9Sstevel@tonic-gate$path_skip = qr/^($path_skip)/;
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate# find library names:
657c478bd9Sstevel@tonic-gate#
667c478bd9Sstevel@tonic-gate# We have to use pkgchk -l output (even though it is much slower than
677c478bd9Sstevel@tonic-gate# parsing /var/sadm/install/contents ourselves) because the contents
687c478bd9Sstevel@tonic-gate# file will go away or change incompatibly at some point.
697c478bd9Sstevel@tonic-gate#
707c478bd9Sstevel@tonic-gatemy $old = $ENV{'LC_ALL'};
717c478bd9Sstevel@tonic-gate$ENV{'LC_ALL'} = 'C';
727c478bd9Sstevel@tonic-gatemy $contents_fh = do { local *FH; *FH };
737c478bd9Sstevel@tonic-gateopen($contents_fh, "/usr/sbin/pkgchk -l|") || die "$!\n";
747c478bd9Sstevel@tonic-gateif (defined($old)) {
757c478bd9Sstevel@tonic-gate	$ENV{'LC_ALL'} = $old;
767c478bd9Sstevel@tonic-gate} else {
777c478bd9Sstevel@tonic-gate	delete($ENV{'LC_ALL'});
787c478bd9Sstevel@tonic-gate}
797c478bd9Sstevel@tonic-gate
807c478bd9Sstevel@tonic-gatemy $pathname = '';
817c478bd9Sstevel@tonic-gatemy $type = '';
827c478bd9Sstevel@tonic-gatemy $link = '';
837c478bd9Sstevel@tonic-gatemy $pkgs = '';
847c478bd9Sstevel@tonic-gatemy $status = '';
857c478bd9Sstevel@tonic-gatemy $inpkgs = 0;
867c478bd9Sstevel@tonic-gatewhile (<$contents_fh>) {
877c478bd9Sstevel@tonic-gate	next if (/^Ex/);
887c478bd9Sstevel@tonic-gate	chomp;
897c478bd9Sstevel@tonic-gate	if (/^Pathname:\s*/i) {
907c478bd9Sstevel@tonic-gate		$pathname = $';
917c478bd9Sstevel@tonic-gate		$type = '';
927c478bd9Sstevel@tonic-gate		$link = '';
937c478bd9Sstevel@tonic-gate		$status = '';
947c478bd9Sstevel@tonic-gate		$pkgs = '';
957c478bd9Sstevel@tonic-gate		$inpkgs = 0;
967c478bd9Sstevel@tonic-gate		next;
977c478bd9Sstevel@tonic-gate	} elsif (/^Type:\s*/i) {
987c478bd9Sstevel@tonic-gate		$type = $';
997c478bd9Sstevel@tonic-gate		next;
1007c478bd9Sstevel@tonic-gate	} elsif (/^Source of link:\s*/i) {
1017c478bd9Sstevel@tonic-gate		$link = $';
1027c478bd9Sstevel@tonic-gate		next;
1037c478bd9Sstevel@tonic-gate	} elsif (/^Referenced by/i) {
1047c478bd9Sstevel@tonic-gate		$inpkgs = 1;
1057c478bd9Sstevel@tonic-gate	} elsif (/^Current status:\s*/i) {
1067c478bd9Sstevel@tonic-gate		$status = $';
1077c478bd9Sstevel@tonic-gate		$inpkgs = 0;
1087c478bd9Sstevel@tonic-gate		next;
1097c478bd9Sstevel@tonic-gate	} elsif (/^\s*$/) {
1107c478bd9Sstevel@tonic-gate		next unless ($pathname =~ m,\.so,);
1117c478bd9Sstevel@tonic-gate		next unless ($pathname =~ m,/lib,);
1127c478bd9Sstevel@tonic-gate		next unless ($pathname =~ m,/lib[^/]*\.so\b,);
113*15fa1d04SToomas Soome		next unless ($type =~ /regular file|symbolic link/i);
1147c478bd9Sstevel@tonic-gate		next unless ($status =~ /^\s*installed\s*$/);
1157c478bd9Sstevel@tonic-gate		$pathname = trim($pathname);
1167c478bd9Sstevel@tonic-gate		$link = trim($link);
1177c478bd9Sstevel@tonic-gate		filter($pathname, $link, $pkgs);
1187c478bd9Sstevel@tonic-gate	}
1197c478bd9Sstevel@tonic-gate	if ($inpkgs) {
1207c478bd9Sstevel@tonic-gate		$pkgs .= $_ . ' ';
1217c478bd9Sstevel@tonic-gate	}
1227c478bd9Sstevel@tonic-gate}
1237c478bd9Sstevel@tonic-gateclose($contents_fh);
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate# run pvs(1) on the libraries found:
1267c478bd9Sstevel@tonic-gatemy $batch = 30;	# batch size to use (running in batches is faster).
1277c478bd9Sstevel@tonic-gate
1287c478bd9Sstevel@tonic-gatemy @list = ();
1297c478bd9Sstevel@tonic-gatefor (my $i = 1; $i <= scalar(@liblist); $i++) {
1307c478bd9Sstevel@tonic-gate	push(@list, $liblist[$i-1]);
1317c478bd9Sstevel@tonic-gate	if ($i % $batch == 0) {
1327c478bd9Sstevel@tonic-gate		do_pvs(@list) if (@list);
1337c478bd9Sstevel@tonic-gate		@list = ();
1347c478bd9Sstevel@tonic-gate	}
1357c478bd9Sstevel@tonic-gate}
1367c478bd9Sstevel@tonic-gatedo_pvs(@list) if (@list);	# finish any remainder.
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gateexit 0;
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate#
1417c478bd9Sstevel@tonic-gate# Take a pkgchk -l entry and decide if it corresponds to a Solaris
1427c478bd9Sstevel@tonic-gate# library. If so, save it in the list @liblist, and record info in
1437c478bd9Sstevel@tonic-gate# %symlink & %inode_hash associative arrays as appropriate.
1447c478bd9Sstevel@tonic-gate#
1457c478bd9Sstevel@tonic-gatesub filter
1467c478bd9Sstevel@tonic-gate{
1477c478bd9Sstevel@tonic-gate	my ($path, $link, $pkgs) = @_;
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate	# consider only SUNW packages:
1517c478bd9Sstevel@tonic-gate	return unless ($pkgs =~ /\bSUNW\S+/);
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate	my $basename;
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate	$basename = basename($path);
1567c478bd9Sstevel@tonic-gate
1577c478bd9Sstevel@tonic-gate	if ($link ne '') {
1587c478bd9Sstevel@tonic-gate		# include developer build-time symlinks:
1597c478bd9Sstevel@tonic-gate		return unless ($basename =~ /^lib.*\.so[\.\d]*$/);
1607c478bd9Sstevel@tonic-gate	} else {
1617c478bd9Sstevel@tonic-gate		return unless ($basename =~ /^lib.*\.so\.[\.\d]+$/);
1627c478bd9Sstevel@tonic-gate	}
1637c478bd9Sstevel@tonic-gate	return if ($path =~ /$path_skip/);
1647c478bd9Sstevel@tonic-gate
1657c478bd9Sstevel@tonic-gate	return unless (-f $path);
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate	# inode is used to identify what file a symlink point to:
1687c478bd9Sstevel@tonic-gate	my $inode;
1697c478bd9Sstevel@tonic-gate	$inode = (stat($path))[1];
1707c478bd9Sstevel@tonic-gate	return unless (defined($inode));
1717c478bd9Sstevel@tonic-gate
1727c478bd9Sstevel@tonic-gate	if ($link ne '') {
1737c478bd9Sstevel@tonic-gate		# record info about symlinks:
1747c478bd9Sstevel@tonic-gate		if (exists($symlink{$inode})) {
1757c478bd9Sstevel@tonic-gate			$symlink{$inode} .= ":" . $path;
1767c478bd9Sstevel@tonic-gate		} else {
1777c478bd9Sstevel@tonic-gate			$symlink{$inode} = ":" . $path;
1787c478bd9Sstevel@tonic-gate		}
1797c478bd9Sstevel@tonic-gate	} else {
1807c478bd9Sstevel@tonic-gate		# ordinary file case:
1817c478bd9Sstevel@tonic-gate		$inode_hash{$path} = $inode;
1827c478bd9Sstevel@tonic-gate		push(@liblist, $path);
1837c478bd9Sstevel@tonic-gate	}
1847c478bd9Sstevel@tonic-gate}
1857c478bd9Sstevel@tonic-gate
1867c478bd9Sstevel@tonic-gate#
1877c478bd9Sstevel@tonic-gate# Run pvs(1) on a list of libraries. More than one is done at a time to
1887c478bd9Sstevel@tonic-gate# speed things up.
1897c478bd9Sstevel@tonic-gate#
1907c478bd9Sstevel@tonic-gate# Extracts the version information and passes it to the output() routine
1917c478bd9Sstevel@tonic-gate# for final processing.
1927c478bd9Sstevel@tonic-gate#
1937c478bd9Sstevel@tonic-gatesub do_pvs
1947c478bd9Sstevel@tonic-gate{
1957c478bd9Sstevel@tonic-gate	my (@list) = @_;
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate	my (%list, $paths, $path, $cnt);
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate	#
2007c478bd9Sstevel@tonic-gate	# record info about the library paths and construct the list of
2017c478bd9Sstevel@tonic-gate	# files for the pvs command line.
2027c478bd9Sstevel@tonic-gate	#
2037c478bd9Sstevel@tonic-gate	$cnt = 0;
2047c478bd9Sstevel@tonic-gate	$paths = '';
2057c478bd9Sstevel@tonic-gate	foreach $path (@list) {
2067c478bd9Sstevel@tonic-gate		$list{$path} = 1;
2077c478bd9Sstevel@tonic-gate		$paths .= ' ' if ($paths ne '');
2087c478bd9Sstevel@tonic-gate		#
2097c478bd9Sstevel@tonic-gate		# $path should never have single quote in it in
2107c478bd9Sstevel@tonic-gate		# all normal usage. Make sure this is so:
2117c478bd9Sstevel@tonic-gate		#
2127c478bd9Sstevel@tonic-gate		next if ($path =~ /'/);
2137c478bd9Sstevel@tonic-gate		#
2147c478bd9Sstevel@tonic-gate		# quote the filename in case it has meta-characters
215*15fa1d04SToomas Soome		# (which should never happen in all normal usage)
2167c478bd9Sstevel@tonic-gate		#
2177c478bd9Sstevel@tonic-gate		$paths .= "'$path'";
2187c478bd9Sstevel@tonic-gate		$cnt++;
2197c478bd9Sstevel@tonic-gate	}
2207c478bd9Sstevel@tonic-gate
2217c478bd9Sstevel@tonic-gate	return if ($cnt == 0);
2227c478bd9Sstevel@tonic-gate
2237c478bd9Sstevel@tonic-gate	# set locale to C for running command, since we interpret the output:
2247c478bd9Sstevel@tonic-gate	my $old = $ENV{'LC_ALL'};
2257c478bd9Sstevel@tonic-gate	$ENV{'LC_ALL'} = 'C';
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate	# get the file(1) output for each item:
2287c478bd9Sstevel@tonic-gate	my $file_fh = do { local *FH; *FH };
2297c478bd9Sstevel@tonic-gate	open($file_fh, "/usr/bin/file $paths 2>&1 |") || die "$!\n";
2307c478bd9Sstevel@tonic-gate	my ($file, $out);
2317c478bd9Sstevel@tonic-gate	while (<$file_fh>) {
2327c478bd9Sstevel@tonic-gate		($file, $out) = split(/:/, $_, 2);
2337c478bd9Sstevel@tonic-gate		if ($list{$file} && $out =~ /\bELF\b/) {
2347c478bd9Sstevel@tonic-gate			$fileoutput{$file} = $out;
2357c478bd9Sstevel@tonic-gate		}
2367c478bd9Sstevel@tonic-gate	}
2377c478bd9Sstevel@tonic-gate	close($file_fh);
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate	#
2407c478bd9Sstevel@tonic-gate	# in the case of only 1 item, we place it on the command line
2417c478bd9Sstevel@tonic-gate	# twice to induce pvs(1) to indicate which file it is reporting
2427c478bd9Sstevel@tonic-gate	# on.
2437c478bd9Sstevel@tonic-gate	#
2447c478bd9Sstevel@tonic-gate	if ($cnt == 1) {
2457c478bd9Sstevel@tonic-gate		$paths .= " $paths";
2467c478bd9Sstevel@tonic-gate	}
2477c478bd9Sstevel@tonic-gate
2487c478bd9Sstevel@tonic-gate	#
2497c478bd9Sstevel@tonic-gate	# $paths are entries from /var/sadm/install/contents and
2507c478bd9Sstevel@tonic-gate	# so should not contain spaces or meta characters:
2517c478bd9Sstevel@tonic-gate	#
2527c478bd9Sstevel@tonic-gate	my $pvs_fh = do { local *FH; *FH };
2537c478bd9Sstevel@tonic-gate	open($pvs_fh, "/usr/bin/pvs -dn $paths 2>&1 |") || die "$!\n";
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate	# reset LC_ALL, if there was any:
2567c478bd9Sstevel@tonic-gate	if (defined($old)) {
2577c478bd9Sstevel@tonic-gate		$ENV{'LC_ALL'} = $old;
2587c478bd9Sstevel@tonic-gate	} else {
2597c478bd9Sstevel@tonic-gate		delete($ENV{'LC_ALL'});
2607c478bd9Sstevel@tonic-gate	}
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate	my ($pub, $pri, $obs, $evo, $vers, $new_path);
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate	undef($path);
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate	# initialize strings used below for appending info to:
2677c478bd9Sstevel@tonic-gate	$pub = '';
2687c478bd9Sstevel@tonic-gate	$pri = '';
2697c478bd9Sstevel@tonic-gate	$obs = '';
2707c478bd9Sstevel@tonic-gate	$evo = '';
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate	while (<$pvs_fh>) {
2737c478bd9Sstevel@tonic-gate		$_ =~ s/\s*$//;
2747c478bd9Sstevel@tonic-gate		if (m,^([^:]+):$,) {
2757c478bd9Sstevel@tonic-gate		    # a new pvs file header, e.g. "/usr/lib/libc.so.1:"
2767c478bd9Sstevel@tonic-gate		    if ($list{$1}) {
2777c478bd9Sstevel@tonic-gate			$new_path = $1;
2787c478bd9Sstevel@tonic-gate
2797c478bd9Sstevel@tonic-gate			# output the previous one and reset accumulators:
2807c478bd9Sstevel@tonic-gate			if (defined($path)) {
2817c478bd9Sstevel@tonic-gate				output($path, $pub, $pri, $obs, $evo);
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate				$pub = '';
2847c478bd9Sstevel@tonic-gate				$pri = '';
2857c478bd9Sstevel@tonic-gate				$obs = '';
2867c478bd9Sstevel@tonic-gate				$evo = '';
2877c478bd9Sstevel@tonic-gate			}
2887c478bd9Sstevel@tonic-gate			$path = $new_path;
2897c478bd9Sstevel@tonic-gate			next;	# done with pvs header case
2907c478bd9Sstevel@tonic-gate		    }
2917c478bd9Sstevel@tonic-gate		}
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate		# extract SUNW version head end:
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate		$vers = trim($_);
2967c478bd9Sstevel@tonic-gate		$vers =~ s/;//g;
2977c478bd9Sstevel@tonic-gate
2987c478bd9Sstevel@tonic-gate		# handle the various non-standard cases in Solaris libraries:
2997c478bd9Sstevel@tonic-gate		if ($vers =~ /^(SUNW.*private|SUNW_XIL_GPI)/i) {
3007c478bd9Sstevel@tonic-gate			$pri .= $vers . ":";
3017c478bd9Sstevel@tonic-gate		} elsif ($vers =~ /^(SUNW_\d|SYSVABI|SISCD)/) {
3027c478bd9Sstevel@tonic-gate			$pub .= $vers . ":";
3037c478bd9Sstevel@tonic-gate		} elsif ($vers =~ /^(SUNW\.\d|SUNW_XIL)/) {
3047c478bd9Sstevel@tonic-gate			$pub .= $vers . ":";
3057c478bd9Sstevel@tonic-gate		} elsif ($vers =~ /^SUNWobsolete/) {
3067c478bd9Sstevel@tonic-gate			$obs .= $vers . ":";
3077c478bd9Sstevel@tonic-gate		} elsif ($vers =~ /^SUNWevolving/) {
3087c478bd9Sstevel@tonic-gate			$evo .= $vers . ":";
3097c478bd9Sstevel@tonic-gate		} else {
3107c478bd9Sstevel@tonic-gate			next;
3117c478bd9Sstevel@tonic-gate		}
3127c478bd9Sstevel@tonic-gate	}
3137c478bd9Sstevel@tonic-gate	close($pvs_fh);
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate	# output the last one (if any):
3167c478bd9Sstevel@tonic-gate	if (defined($path)) {
3177c478bd9Sstevel@tonic-gate		output($path, $pub, $pri, $obs, $evo);
3187c478bd9Sstevel@tonic-gate	}
3197c478bd9Sstevel@tonic-gate}
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate#
3227c478bd9Sstevel@tonic-gate# Take the raw library versioning information and process it into index
3237c478bd9Sstevel@tonic-gate# file format and then print it out.
3247c478bd9Sstevel@tonic-gate#
3257c478bd9Sstevel@tonic-gatesub output
3267c478bd9Sstevel@tonic-gate{
3277c478bd9Sstevel@tonic-gate	my ($path, $pub, $pri, $obs, $evo) = @_;
3287c478bd9Sstevel@tonic-gate
3297c478bd9Sstevel@tonic-gate	return if ($didlib{$path});	# skip repeating a library
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate	# trim off any trailing separators:
3327c478bd9Sstevel@tonic-gate	$pub =~ s/:$//;
3337c478bd9Sstevel@tonic-gate	$pri =~ s/:$//;
3347c478bd9Sstevel@tonic-gate	$obs =~ s/:$//;
3357c478bd9Sstevel@tonic-gate	$evo =~ s/:$//;
3367c478bd9Sstevel@tonic-gate
3377c478bd9Sstevel@tonic-gate	# work out the type of library:
3387c478bd9Sstevel@tonic-gate	my $type;
3397c478bd9Sstevel@tonic-gate	my $defn;
3407c478bd9Sstevel@tonic-gate	my $n;
3417c478bd9Sstevel@tonic-gate	if ($pri && ! $pub && ! $obs && ! $evo) {
3427c478bd9Sstevel@tonic-gate		$type = 'INTERNAL';
3437c478bd9Sstevel@tonic-gate		$defn = 'NO_PUBLIC_SYMS';
3447c478bd9Sstevel@tonic-gate	} elsif ($obs) {
3457c478bd9Sstevel@tonic-gate		$type = 'OBSOLETE';
3467c478bd9Sstevel@tonic-gate		$defn = $obs;
3477c478bd9Sstevel@tonic-gate	} elsif ($pub) {
3487c478bd9Sstevel@tonic-gate		$type = 'PUBLIC';
3497c478bd9Sstevel@tonic-gate		$defn = $pub;
3507c478bd9Sstevel@tonic-gate		if ($defn =~ /:/) {
3517c478bd9Sstevel@tonic-gate			$defn =~ s/:/,/g;
3527c478bd9Sstevel@tonic-gate			$defn = "PUBLIC=$defn";
3537c478bd9Sstevel@tonic-gate		}
3547c478bd9Sstevel@tonic-gate	} elsif ($evo) {
3557c478bd9Sstevel@tonic-gate		$type = 'EVOLVING';
3567c478bd9Sstevel@tonic-gate		$defn = $evo;
3577c478bd9Sstevel@tonic-gate	} elsif (! $pri && ! $pub && ! $obs && ! $evo) {
3587c478bd9Sstevel@tonic-gate		$type = 'UNVERSIONED';
3597c478bd9Sstevel@tonic-gate		$defn = '-';
3607c478bd9Sstevel@tonic-gate	} else {
3617c478bd9Sstevel@tonic-gate		return;
3627c478bd9Sstevel@tonic-gate	}
3637c478bd9Sstevel@tonic-gate
3647c478bd9Sstevel@tonic-gate	# return if instructed to skip either of these cases:
3657c478bd9Sstevel@tonic-gate	if ($must_be_versioned && $type eq 'UNVERSIONED') {
3667c478bd9Sstevel@tonic-gate		return;
3677c478bd9Sstevel@tonic-gate	}
3687c478bd9Sstevel@tonic-gate	if ($must_be_public && $type eq 'INTERNAL') {
3697c478bd9Sstevel@tonic-gate		return;
3707c478bd9Sstevel@tonic-gate	}
3717c478bd9Sstevel@tonic-gate
3727c478bd9Sstevel@tonic-gate
3737c478bd9Sstevel@tonic-gate	# prepare the output line, including any symlink information:
3747c478bd9Sstevel@tonic-gate	my $inode = $inode_hash{$path};
3757c478bd9Sstevel@tonic-gate	my $links;
3767c478bd9Sstevel@tonic-gate	if ($inode && exists($symlink{$inode})) {
3777c478bd9Sstevel@tonic-gate		$links = "${path}$symlink{$inode}";
3787c478bd9Sstevel@tonic-gate	} else {
3797c478bd9Sstevel@tonic-gate		$links = "$path";
3807c478bd9Sstevel@tonic-gate	}
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate	# count the total number of references:
3837c478bd9Sstevel@tonic-gate	my (@n) = split(/:/, $links);
3847c478bd9Sstevel@tonic-gate	$n = scalar(@n);
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate	# determine the abi to which the library file belongs:
3877c478bd9Sstevel@tonic-gate	my ($fout, $abi);
3887c478bd9Sstevel@tonic-gate	$abi = 'unknown';
3897c478bd9Sstevel@tonic-gate	$fout = $fileoutput{$path};
3907c478bd9Sstevel@tonic-gate	if ($fout =~ /\bSPARCV9\b/) {
3917c478bd9Sstevel@tonic-gate		$abi = 'sparcv9';
3927c478bd9Sstevel@tonic-gate	} elsif ($fout =~ /\bSPARC/) {
3937c478bd9Sstevel@tonic-gate		$abi = 'sparc';
3947c478bd9Sstevel@tonic-gate	} elsif ($fout =~ /\bAMD64\b/ || $fout =~ /\bELF\s+64-bit\s+LSB\b/) {
3957c478bd9Sstevel@tonic-gate		$abi = 'amd64';
3967c478bd9Sstevel@tonic-gate	} elsif ($fout =~ /\b80386\b/) {
3977c478bd9Sstevel@tonic-gate		$abi = 'i386';
3987c478bd9Sstevel@tonic-gate	}
3997c478bd9Sstevel@tonic-gate	print STDOUT "$abi|$path|$defn|$n|$links\n";
4007c478bd9Sstevel@tonic-gate
4017c478bd9Sstevel@tonic-gate	# record that we did this library so we do not process it a second time.
4027c478bd9Sstevel@tonic-gate	$didlib{$path} = 1;
4037c478bd9Sstevel@tonic-gate}
4047c478bd9Sstevel@tonic-gate
4057c478bd9Sstevel@tonic-gate#
4067c478bd9Sstevel@tonic-gate# Remove leading and trailing spaces.
4077c478bd9Sstevel@tonic-gate#
4087c478bd9Sstevel@tonic-gatesub trim
4097c478bd9Sstevel@tonic-gate{
4107c478bd9Sstevel@tonic-gate	my ($x) = @_;
4117c478bd9Sstevel@tonic-gate	$x =~ s/^\s*//;
4127c478bd9Sstevel@tonic-gate	$x =~ s/\s*$//;
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate	return $x;
4157c478bd9Sstevel@tonic-gate}
416