Old version of filePro

Brian K. White bw.aljex at gmail.com
Tue Dec 21 15:57:26 PST 2021


GUYS... I just discovered something awesome

There is a program called patchelf that can edit the library references 
in an ELF executable.

One of the things it can do is edit the RPATH in an executable, and one 
of the values you can put in RPATH is a magic value '$ORIGIN'.

RPATH is essentially the same as LD_LIBRARY_PATH, except it's built-in 
to the executable. Normally you have to set that at compile-time, but 
this util can edit the compiled executable after the fact. It makes the 
executable look in the directory you say itself before asking the system 
to provide the library.

$ORIGIN is a special value that means "the directory where this 
executable is" and it means at run-time. So, if the executable has that 
in RPATH, then all you have to do is put a copy of whatever library 
files it needs in the directory along side the executable, and then you 
never have to worry about it again.

SO, you can patch the rclerk and other fp executables this way, and just 
stick any problem libs right in the fp directory with the executables 
and forget about them forever after that.
If you re-arrange your system to put the fp binaries in some other 
location, it still works. If you move everything to a new system, it 
still works, as long as you just copy the entire fp directory together, 
which you have to do anyway.

The process goes like this:

Install "patchelf"
debian & derivatives like ubuntu: "apt install patchelf"
redhat & derivatives like centos: "yum install patchelf"

Use "ldd" to list the dependencies of an executable, to find out what 
library files we want to bundle:
bkw at fw:~$ cd /opt/fp/fp
bkw at fw:/opt/fp/fp$ ldd rclerk
     linux-gate.so.1 (0xf7f6a000)
     libtermcap.so.2 => /lib32/libtermcap.so.2 (0xf7f3a000)
     libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xf7e35000)
     libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7c38000)
     /lib/ld-linux.so.2 (0xf7f6c000)
bkw at fw:/opt/fp/fp$

Ignore the linux-gate and ld-linux ones, they're special. One way to 
recognize what makes them "special" or how you know to ignore them, 
notice they don't point to a file, so there is nothing for you to copy 
anyway. It IS actually possible with another tool to take this all a 
step further and bundle not only the libraries but also the interpreter 
or dynamic linker, and pack them all into a new single executable file 
with everything built-in, but we don't need to go that far.

Another way to see what files you need is "readelf -d rclerk |grep NEEDED"
bkw at fw:/opt/fp/fp$ readelf -d rclerk |grep NEEDED
  0x00000001 (NEEDED)                     Shared library: [libtermcap.so.2]
  0x00000001 (NEEDED)                     Shared library: [libm.so.6]
  0x00000001 (NEEDED)                     Shared library: [libc.so.6]
bkw at fw:/opt/fp/fp$

If you're doing this on a system where the fp binaries currently work, 
then ldd will show not only what's needed but also where to find the 
actual file to copy from your current system.
If you're doing this on a new system where the fp binaries don't work 
yet, then you can get the files from centos or rhel 6.10 i686 rpm 
packages like I showed below, and the secret is just knowing that for 
the termcap one specifically, the centos 7 and later ones are broken so 
get the one from centos 6.10, and, that it needs to be the i686 (32 bit) 
one.

The other libraries still have working packages right up to current on 
most systems, so they aren't really a problem. You could do this for all 
3 library files shown here, but really you don't need to for libc and lbm.

In this case, that just leaves libtermcap as the only annoying problem 
library that would be simpler if it were just built-in or at least bundled.

So now, just take libtermcap.so.2 from the ldd output and copy it into 
the fp directory:
cp /usr/lib32/libtermcap.so.2 .

And finally use patchelf to patch the executable, so that the executable 
looks for libraries in it's own directory first from now on.
patchelf --set-rpath '$ORIGIN' rclerk

Now the point of all this: I'll remove libtermcap from the system 
directory and rclerk will still work because now it will find the lib in 
the fp directory:

# remove libtermcap from the system into the fp dir
bkw at fw:~$ sudo mv -f /lib32/libtermcap.so.2 /opt/fp/fp

# show that rclerk is now broken
bkw at fw:~$ ldd rclerk
     linux-gate.so.1 (0xf7f9b000)
     libtermcap.so.2 => not found
     libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xf7e6a000)
     libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7c6d000)
     /lib/ld-linux.so.2 (0xf7f9d000)

# patch rclerk
# $ORIGIN is single-quoted because we need the literal exact string 
$ORIGIN, it's not an environment variable.
bkw at fw:~$ sudo patchelf --set-rpath '$ORIGIN' /opt/fp/fp/rclerk

# show that rclerk is now fixed
bkw at fw:~$ ldd /opt/fp/fp/rclerk
     linux-gate.so.1 (0xf7f0d000)
     libtermcap.so.2 => /opt/fp/fp/libtermcap.so.2 (0xf7f03000)
     libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xf7dd8000)
     libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7bdb000)
     /lib/ld-linux.so.2 (0xf7f0f000)
bkw at fw:~$

So now rclerk is finding libtermcap again, only now finding it in the fp 
directory. Which is fine, it means that right now a cron job could run 
rclerk directly without a script to set LD_LIBRARY_PATH and it would 
work, the executable is searching in the right spot all on it's own.

But the real point of all this is this:

# move the entire fp tree somewhere else
bkw at fw:~$ sudo mv /opt/fp/ /opt/fp_moved/

# see that rclerk is still fixed, even though the library file moved, 
because the executable is looking in a path relative to itself instead 
of an absolute path:
bkw at fw:~$ ldd /opt/fp_moved/fp/rclerk
     linux-gate.so.1 (0xf7eef000)
     libtermcap.so.2 => /opt/fp_moved/fp/libtermcap.so.2 (0xf7ee5000)
     libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xf7dba000)
     libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7bbd000)
     /lib/ld-linux.so.2 (0xf7ef1000)
bkw at fw:~$

And this no longer needs any setup in the system. No /usr/lib32, no 
ldconfig. Just copy your fp dir somewhere on any new system and resume 
using it.

You have to do the same patchelf command for every fp executable. A 
little tedious but it's a one-time-for-life thing.

It's slightly more work than installing the library file like below, but 
the point is now the file can live in the fp directory, get copied along 
with everything else, and everything keeps working wherever you move it 
because now it's self-contained. You don't have to remember to set it up 
on a new system.

It's not necessarily better than below, just another option.

-- 
bkw


On 12/20/21 4:44 AM, Brian K. White wrote:
> I don't even bother trying to find a proper package any more. Just get 
> compat-libtermcap-2.0.8-49.el6.i686.rpm  from any Centos 6.10 repo,
> Doesn't matter if your current distro uses rpm packages, and just use 
> the file from that regardless what the current system is.
>
> For reference, I just did this on an ubuntu 20.10 system:
>
> # First, see we have a broken rclerk (see the not found message):
>
> bkw at fw:~/Documents/centos_termcap_32$ ldd /opt/fp/fp/rclerk
>     linux-gate.so.1 (0xf7ef5000)
>     libtermcap.so.2 => not found
>     libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xf7dc4000)
>     libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7bc7000)
>     /lib/ld-linux.so.2 (0xf7ef7000)
> bkw at fw:~/Documents/centos_termcap_32$
>
> # Download a centos 6.10 i686 rpm containing the file we need:
>
> bkw at fw:~/Documents/centos_termcap_32$ wget 
> https://mirror.chpc.utah.edu/pub/vault.centos.org/6.10/os/i386/Packages/compat-libtermcap-2.0.8-49.el6.i686.rpm
> --2021-12-20 04:00:26-- 
> https://mirror.chpc.utah.edu/pub/vault.centos.org/6.10/os/i386/Packages/compat-libtermcap-2.0.8-49.el6.i686.rpm
> Resolving mirror.chpc.utah.edu (mirror.chpc.utah.edu)... 
> 204.99.128.20, 2001:1948:417:5::20
> Connecting to mirror.chpc.utah.edu 
> (mirror.chpc.utah.edu)|204.99.128.20|:443... connected.
> HTTP request sent, awaiting response... 200 OK
> Length: 15840 (15K) [application/x-rpm]
> Saving to: ‘compat-libtermcap-2.0.8-49.el6.i686.rpm’
>
> compat-libtermcap-2.0.8-49.el6.i686.rpm 
> 100%[=====================================================================================================>] 
> 15.47K  --.-KB/s    in 0.08s
>
> 2021-12-20 04:00:26 (202 KB/s) - 
> ‘compat-libtermcap-2.0.8-49.el6.i686.rpm’ saved [15840/15840]
>
>
> # Extract the contents of the rpm as though it were a tar, using a 
> handy command called "unar"
>
> bkw at fw:~/Documents/centos_termcap_32$ unar 
> compat-libtermcap-2.0.8-49.el6.i686.rpm
> compat-libtermcap-2.0.8-49.el6.i686.rpm: XZ in RPM
>   compat-libtermcap.cpio... OK.
> Successfully extracted to "compat-libtermcap.cpio".
>
> # Use "unar" again to extract the .cpipo
>
> bkw at fw:~/Documents/centos_termcap_32$ unar compat-libtermcap.cpio
> compat-libtermcap.cpio: Cpio
>   ./lib/libtermcap.so.2  (link)... OK.
>   ./lib/libtermcap.so.2.0.8  (12308 B)... OK.
> Successfully extracted to "./lib".
>
> # Now copy and rename libtermcap.so.2.0.8 to libtermcap.so.2 into some 
> lib dir, in my case /usr/lib32 but yours could be different, you can 
> see where all the lib dirs are in the *.conf files in /etc/ld.so.conf.d
>
> bkw at fw:~/Documents/centos_termcap_32$ sudo cp -v 
> lib/libtermcap.so.2.0.8 /usr/lib32/libtermcap.so.2
> [sudo] password for bkw:
> 'lib/libtermcap.so.2.0.8' -> '/usr/lib32/libtermcap.so.2'
>
> # Now run "ldconfig"
>
> bkw at fw:~/Documents/centos_termcap_32$ sudo ldconfig
>
> # Now we have a working rclerk
>
> bkw at fw:~/Documents/centos_termcap_32$ ldd /opt/fp/fp/rclerk
>     linux-gate.so.1 (0xf7f47000)
>     libtermcap.so.2 => /lib32/libtermcap.so.2 (0xf7f17000)
>     libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xf7e12000)
>     libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7c15000)
>     /lib/ld-linux.so.2 (0xf7f49000)
> bkw at fw:~/Documents/centos_termcap_32$
>
>
> Annoying but at least you can do it any time on any system.
>
> If it wasn't for cron jobs or web apps that may sometimes want to run 
> clerk or report without starting from "p" or an environment 
> start-script, I wouldn't even bother integrating the library in the 
> system like this. I'd just stick it right in the fp directory and put 
> "export LD_LIBRARY_PATH=${PFPROG}/fp" into the start script, or into p 
> right before the runmenu. Then the library is just part of the filepro 
> install and goes wherever it goes from now on.
>



More information about the Filepro-list mailing list