[geeks] The Joys of Unix and Unsigned Code

Jonathan Patschke jp at celestrion.net
Wed Dec 14 20:46:32 CST 2011


With all these "modern" computing environments and their code signing,
and their package management, and their object-file checksums, it's easy
to forget how fun and simple the "legacy" environments can be.

At $ork, I support HP-UX 10.20 because we have some laboratory equipment
and semiconductor test equipment that only have drivers for HP-UX 9.x and
10.x.  I also write software to target this environment, and, call me
greedy, but I really like having cutting-edge features like Perl 5,
revision control, ANSI C, C++ namespaces, and an editor that isn't AT&T
vi.

So, I've built fairly recent versions of GNU everything, subversion, git,
vim, Perl, and a bunch of other stuff for this ancient platform, and
installed it in /usr/local, naturally.  Another developer here has come to
rely on these luxuries and wants to ship code of his to one of our
contractors in Taiwan, who absolutely will not hear of us installing code
in /usr/local, but will let us have a directory in /opt.

Man, that sucks.  It took me a month or so to get all this stuff
hand-hacked and built right (just building GCC 4.4 is a 6-hour ordeal on a
550MHz PA-8600), and $developer and I both have deadlines to ship
nontrivial code by Chinese New Year.

To complicate matters, this old version of HP-UX really doesn't support
any dynamic linking with partial library paths.  So, all the library
dependencies have their paths embedded.  What to do?

Simple, pick a directory whose name has the same length and patch
-everything- (binaries, perl modules, libraries) in place:

   $ mkdir /opt/austx
   $ rsync -aHx /usr/local/. /opt/austx/.
   $ cd /opt/austx
   $ (find . -type l -exec ls -la '{}' \; ) | grep local > /tmp/links.lst
   $ # fix symlinks manually by making them relative
   $ (find . -type f -links +1 -exec ls -i '{}' \;) | sort -n | \
      awk 'BEGIN { inode = 0; filename = ""; }
      $1 == inode { printf("rm %s\nln %s %s\n", $2, filename, $2); next; }
      { inode = $1; filename = $2; }' > /tmp/fix-hardlinks.sh
   $ find . -type f -exec grep -l usr/local '{}' \; > /tmp/files-to-fix
   $ for file in `cat /tmp/files-to-fix` ; do gsed --in-place=.bak -e \
     's,usr/local,opt/austx,g' ${file} ; done
   $ sed -e 's,$,.bak,' < /tmp/files-to-fix > /tmp/files-to-archive
   $ gtar cpzTf /tmp/files-to-archive /tmp/usr-local-backups.tgz
   $ for file in `cat /tmp/files-to-archive` ; do rm ${file} ; done
   $ sh /tmp/fix-hardlinks.sh

This is perhaps not the most efficient way of getting the job done, but
sometimes "So stupid it might actually work," actually works.

-- 
Jonathan Patschke    |    "It is easier to build two chimneys than to
Elgin, TX            %     keep one in fuel."
USA                  |                            --Benjamin Franklin


More information about the geeks mailing list