#! /usr/bin/ksh

# Original Author: Tim Mooney <mooney@golem.phys.ndsu.NoDak.edu>
# $Id: osf.prov,v 1.7 2000/10/31 20:47:23 mooney Exp $
#
# This file is distributed under the terms of the GNU Public License
#
# find-provides is part of RPM, the Red Hat Package Manager.  find-provides
# reads a list of full pathnames (in a package) on stdin, and outputs all
# shared libraries provided by (contained in) the package.
#
#
# On Digital/Tru64 Unix (OSF1), use `odump -D' to find what libraries a
# package provides.  Note that Tru64 Unix 5.x and later come with `ldd',
# but sticking with `odump' works with versions of the OS back to at least
# 3.x, so it's the preferred method.
#
# Example `odump -D' output:
#
#$odump -D /usr/shlib/libc.so
#
#
#
#
#			***DYNAMIC SECTION***
#	         Tag            Value
#
#/usr/shlib/libc.so:
#	          UNREFEXTNO: 14.
#	         LOCAL_GOTNO: 521.
#	              GOTSYM: 2205.
#	         LOCAL_GOTNO: 1606.
#	              GOTSYM: 3289.
#	              SONAME: libc.so
#	          TIME_STAMP: (0x34a82daa) Mon Dec 29 17:09:30 1997
#
#	           ICHECKSUM: 0x5e955f9b
#	            IVERSION: osf.1
#	          CONFLICTNO: 0.
#	         RLD_VERSION: 2.
#	                HASH: 0x000003ff800a82e0
#	              STRTAB: 0x000003ff8008aad0
#	              SYMTAB: 0x000003ff80094ab0
#	                MSYM: 0x000003ff800842c0
#	               STRSZ: 40922.
#	              SYMENT: 24.
#	              PLTGOT: 0x000003ffc008f240
#	            SYMTABNO: 3330.
#	        BASE_ADDRESS: 0x000003ff80080000
#	            HIPAGENO: 0.
#	               RELSZ: 15296.
#	              RELENT: 16.
#	                 REL: 0x000003ff80080700
#	           LIBLISTNO: 0.
#	                INIT: 0x000003ff8019c520
#	                FINI: 0x000003ff8019c570
#	               FLAGS: 0x00000001
#

PATH=/usr/bin:/usr/sbin:/sbin:/usr/ccs/bin
export PATH

#
# TVM: Marc Stephenson (marc@austin.ibm.com) points out we run things
# like `file', et. al. and expect the output to be what we see in the
# C/POSIX locale.  Make sure it is so.
#
LANG=C
export LANG

#
# Use `while read ...' instead of a `for f in ...', because there may
# be too many files to stuff into one shell variable.
#
IFS=""
while read f
do

	#
	# if it's a shared library, run odump on it.
	#
	maybe_shared_lib=`file $f | grep -E 'COFF.*shared library'`
	if test X"$maybe_shared_lib" != X ; then
		odump -D $f 2>/dev/null | awk '

			BEGIN { 
				FS = " ";
				RS = "\n";
				OFS = "";

				found_soname = 0;
				found_iversion = 0;

			}

			# Uncomment the next line for some debugging info.
			#{ print NR , ":", $0  }

			/^[	 ]+SONAME: .*[ 	]*$/ {
				found_soname = 1;
				numfields = split($0, internal_name)
				if (numfields == 2) {
					soname = $2
					#
					# we should probably check to see if the soname ends with
					# a number (indicating that it contains versioning info,
					# possibly in addition to the versioning info in the
					# versions field) and generate a warning here.  Shared
					# libraries should not be built with version info in
					# the soname on Digital/Tru64 Unix.
					#
				} else {
					#
					# Should never be here.
					#
					print "Really odd looking soname:", $0 | "cat 1>&2"
					exit
				}
			}

			/^[ 	]+IVERSION: .*[ 	]*$/ {
				if (found_soname == 1) {
					numfields = split($0, iversion)
					if (numfields == 2) {
						version = $2
						#
						# handle libraries with multiple versions, like
						# 1.1:1.2.  Since they really provide both versions,
						# we need to generate output for each version.
						#
						numfields = split(version, versions, ":")
						if (numfields > 1) {
							for (i = 1; i < numfields; i++) {
								print soname, "(", versions[i], ")"
							}
							#
							# let our END routine print out the *last* version
							# provided
							#
							version = versions[numfields]
						}
						#
						# stick a fork in us.
						#
						found_iversion = 1;
						exit
					} else {
						#
						# Should never be here.
						#
						print "Odd looking library version:", $0 | "cat 1>&2"
						exit
					}
				} else {
					#
					# found an iversion without an soname.  Is that possible?
					#
					print "Found version but no soname:", $0 | "cat 1>&2"
					exit
				}
			}

			#
			# we could probably watch for some other token (like RLD_VERSION)
			# that *generally* occurs later in the input than the stuff we watch
			# for, and exit if we see it, but it is just as easy to read all
			# the output, even after we have seen what we are looking for.
			#

			END {
				# Uncomment the next line for debugging info
				#{ print "END: NR: ", NR }
				if ( (found_soname == 1) && (found_iversion == 1) ) {
					print soname, "(", version, ")"
					exit
				} else if (found_soname == 1) {
					#
					# no library version information
					#
					print soname
				}
				# else do nothing
			}
		' # end of awk
	fi
done | sort -u
#comment out the previous line and uncomment the next line when debugging
#done
