Subject: libdl syms routines for SVR4

From: [email-masked]
Date: Wed, 21 Jul 93 08:22:56 -0700

Since I never seem to get time to package up and distribut my working
version of postgres 4.0.1, I can, at least, distribute the following
stuff (the contents of /usr/postgres/src/port/svr4)..  This is,
however, not the complete port.  I may yet get the time to package it
up. 

Be advised that there is a bug in SVR4.0.3.0 (and perhaps others) in
that symbols in the a.out are *not* exported into the dyn symbol table
unless they are referenced by a shared library that was linked with
the a.out.  This prevents you from using things like
GetAttributeByName from dyn loaded code unless you go to truly
extraordinary lengths.

What do I mean by ``extraordinary lengths''?  Well, you have to make a
C file that is filled with lines like this:

    typedef void f(void);
    extern void local_heap_open(void);
    static f *locallocal_heap_open = local_heap_open;
    extern void CopyTo(void);
    static f *localCopyTo = CopyTo;
    extern void LOisdir(void);
    static f *localLOisdir = LOisdir;
    extern void pbuf_addTupleValueLengths(void);
    static f *localpbuf_addTupleValueLengths = pbuf_addTupleValueLengths;
    ...

This is generated automatically by picking through the symbol table of
the postgres backend.  I call it exports.c.

Then you build a shared library with just this file in it.  Then you
link the postgres backend with this library, causing all of the
referenced a.out symbols to be exported into the dyn symbol table.
Finally, since the above library is rather hefty, and would lengthen
backend startup time, and doesn't do anything, you need to excise the
``required'' entry for this library from the a.out, so that it doesn't
get loaded when the backend starts.  I wrote a program to do this.
Whew...

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  svr4 svr4/dynamic_syms.c svr4/dynloader.c svr4/machine.h
#   svr4/port-protos.h svr4/port.c svr4/strings.h svr4/sys
#   svr4/sys/file.h svr4/sys/resource.h svr4/sys/wait.h svr4/time.h
#   svr4/README
# Wrapped by postgres@spooky on Wed Jul 21 11:22:30 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test ! -d 'svr4' ; then
    echo shar: Creating directory \"'svr4'\"
    mkdir 'svr4'
fi
if test -f 'svr4/dynamic_syms.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'svr4/dynamic_syms.c'\"
else
echo shar: Extracting \"'svr4/dynamic_syms.c'\" \(0 characters\)
sed "s/^X//" >'svr4/dynamic_syms.c' <<'END_OF_FILE'
END_OF_FILE
if test 0 -ne `wc -c <'svr4/dynamic_syms.c'`; then
    echo shar: \"'svr4/dynamic_syms.c'\" unpacked with wrong size!
fi
# end of 'svr4/dynamic_syms.c'
fi
if test -f 'svr4/dynloader.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'svr4/dynloader.c'\"
else
echo shar: Extracting \"'svr4/dynloader.c'\" \(2538 characters\)
sed "s/^X//" >'svr4/dynloader.c' <<'END_OF_FILE'
X/*
X  Copyright 1993 by Robert Withrow, Swampscott MA, 01907, USA.
X  All rights reserved.
X
X  Permission is granted to copy and use this file for any purpose
X  as long as the above Copyright statment is retained in the file.
X*/
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <dlfcn.h>
X
X#include "tmp/c.h"
X#include "utils/fmgr.h"
X
Xstatic DynamicFunctionList *get_text_symbols(char *filename, char **err);
X
Xstatic char msg[255];		/* Holds error messages */
X
XDynamicFunctionList *
Xdynamic_file_load(char **err, char *filename, char **address, long *size)
X{
X  /* 
X    We use the dl library to attach shared objects
X    We never do a dlclose so that reloads accumulate in the address
X    space of the backend.  This is because there is no dynamic_file_reaload
X    call and no space to leave the handle to the old loaded code.  This
X    is a design flaw in the dynloading design of postgres.
X  */
X  void * dlhandle;
X  DynamicFunctionList *list, *l;
X
X  dlhandle = dlopen(filename,RTLD_LAZY);
X  if (dlhandle == NULL) {
X    sprintf(msg,"\"dlopen(%s,RTLD_LAZY)\" failed",filename);
X    *err = msg;
X    return(NULL);
X  }
X
X  /*
X    The shared object has been attached to the address space of postgres,
X    but we don't know what text symbols it contains...
X  */
X
X  list = get_text_symbols(filename,err);
X
X  /*
X    Now, fill in the address of the text symbols returned.
X  */
X  l = list;
X  while(l) {
X    l->func = (func_ptr)dlsym(dlhandle,l->funcname);
X    l = l->next;
X  }
X
X  /*
X    Since the dl stuff mmaps, this is bogus!  Why are these variables
X    here anyway?
X  */
X  *address = NULL;
X  *size = 0;
X  return(list);
X}
X
X/*
X  This is sorta hacky, but the elf_ routines have too much hair for
X  me, and nlist() didn't work...
X
X  Returns the list with the ->func field unfilled.
X*/
X#define BSIZE (255)
X
Xstatic DynamicFunctionList *get_text_symbols(char *filename, char **err)
X{
X  DynamicFunctionList *list = NULL;
X  char command[BSIZE], line[BSIZE];
X  FILE *p;
X
X  sprintf(command,"nm -p %s | grep ' T '",filename);
X
X  p = popen(command,"r");
X
X  if (p == NULL) {
X    sprintf(msg,"\"%s\" failed",command);
X    *err = msg;
X    return NULL;
X  }
X
X  while (fgets(line,BSIZE,p) != NULL) {
X    DynamicFunctionList *item = malloc(sizeof(DynamicFunctionList));
X    int garb1;
X    char garb2[BSIZE], name[BSIZE];
X
X    if (item) {
X      sscanf(line,"%d %s %s",&garb1, garb2, name);
X      if (name[0] == '_') {
X	free(item);
X      } else {
X	strncpy(item->funcname,name,16);
X	item->next = list;
X	list = item;
X      }
X    }
X  }
X
X  (void) pclose(p);
X  return(list);
X}
END_OF_FILE
if test 2538 -ne `wc -c <'svr4/dynloader.c'`; then
    echo shar: \"'svr4/dynloader.c'\" unpacked with wrong size!
fi
# end of 'svr4/dynloader.c'
fi
if test -f 'svr4/machine.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'svr4/machine.h'\"
else
echo shar: Extracting \"'svr4/machine.h'\" \(65 characters\)
sed "s/^X//" >'svr4/machine.h' <<'END_OF_FILE'
X#ifndef MACHINE_H
X#define MACHINE_H
X
X#define BLCKSZ	8192
X
X#endif
END_OF_FILE
if test 65 -ne `wc -c <'svr4/machine.h'`; then
    echo shar: \"'svr4/machine.h'\" unpacked with wrong size!
fi
# end of 'svr4/machine.h'
fi
if test -f 'svr4/port-protos.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'svr4/port-protos.h'\"
else
echo shar: Extracting \"'svr4/port-protos.h'\" \(161 characters\)
sed "s/^X//" >'svr4/port-protos.h' <<'END_OF_FILE'
X/* dynamic_syms.c */
X
X/* dynloader.c */
XDynamicFunctionList *dynamic_file_load ARGS((char **err , char *filename , char **address , long *size ));
X
X/* port.c */
END_OF_FILE
if test 161 -ne `wc -c <'svr4/port-protos.h'`; then
    echo shar: \"'svr4/port-protos.h'\" unpacked with wrong size!
fi
# end of 'svr4/port-protos.h'
fi
if test -f 'svr4/port.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'svr4/port.c'\"
else
echo shar: Extracting \"'svr4/port.c'\" \(455 characters\)
sed "s/^X//" >'svr4/port.c' <<'END_OF_FILE'
X/* Fixit routines for the svr4 port... */
X
X/* Reliable signals */
X/* This was taken from Stevens... */
X
X#include <signal.h>
X
Xtypedef void Sigfunc(int);
X
XSigfunc *signal(int signo, Sigfunc *func)
X{
X  struct sigaction act, oact;
X
X  act.sa_handler = func;
X  sigemptyset(&act.sa_mask);
X  act.sa_flags = 0;
X  if (signo != SIGALRM) {
X    act.sa_flags |= SA_RESTART;
X  }
X  if (sigaction(signo, &act, &oact) < 0)
X    return(SIG_ERR);
X  return(oact.sa_handler);
X}
END_OF_FILE
if test 455 -ne `wc -c <'svr4/port.c'`; then
    echo shar: \"'svr4/port.c'\" unpacked with wrong size!
fi
# end of 'svr4/port.c'
fi
if test -f 'svr4/strings.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'svr4/strings.h'\"
else
echo shar: Extracting \"'svr4/strings.h'\" \(120 characters\)
sed "s/^X//" >'svr4/strings.h' <<'END_OF_FILE'
X/* Include bouncer for the BSD strings.h */
X
X#ifndef _PORT_STRINGS_H
X#define _PORT_STRINGS_H
X#include <string.h>
X#endif
END_OF_FILE
if test 120 -ne `wc -c <'svr4/strings.h'`; then
    echo shar: \"'svr4/strings.h'\" unpacked with wrong size!
fi
# end of 'svr4/strings.h'
fi
if test ! -d 'svr4/sys' ; then
    echo shar: Creating directory \"'svr4/sys'\"
    mkdir 'svr4/sys'
fi
if test -f 'svr4/sys/file.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'svr4/sys/file.h'\"
else
echo shar: Extracting \"'svr4/sys/file.h'\" \(451 characters\)
sed "s/^X//" >'svr4/sys/file.h' <<'END_OF_FILE'
X/* Fixups for file.h */
X
X#ifndef _PORT_FILE_H
X#define _PORT_FILE_H
X
X/* SYSV file.h needs to include types.h but doesnt */
X
X#include <sys/types.h>
X
X/* Need to define L_SET, L_INCR, L_XTND in terms of SEEK_xxx */
X
X#include <unistd.h>
X#define L_SET (SEEK_SET)
X#define L_INCR (SEEK_CUR)
X#define L_XTND (SEEK_END)
X
X#include "include/sys/file.h"
X
X/* Also include fcntl for the O_xxx stuff, since code assumes file.h does this */
X
X#include <fcntl.h>
X
X#endif
END_OF_FILE
if test 451 -ne `wc -c <'svr4/sys/file.h'`; then
    echo shar: \"'svr4/sys/file.h'\" unpacked with wrong size!
fi
# end of 'svr4/sys/file.h'
fi
if test -f 'svr4/sys/resource.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'svr4/sys/resource.h'\"
else
echo shar: Extracting \"'svr4/sys/resource.h'\" \(161 characters\)
sed "s/^X//" >'svr4/sys/resource.h' <<'END_OF_FILE'
X/* Fixups for resource. */
X
X#ifndef _PORT_RESOURCE_H
X#define _PORT_RESOURCE_H
X
X/* Postgres wants bsd resource.h */
X
X#include <ucbinclude/sys/resource.h>
X
X#endif
END_OF_FILE
if test 161 -ne `wc -c <'svr4/sys/resource.h'`; then
    echo shar: \"'svr4/sys/resource.h'\" unpacked with wrong size!
fi
# end of 'svr4/sys/resource.h'
fi
if test -f 'svr4/sys/wait.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'svr4/sys/wait.h'\"
else
echo shar: Extracting \"'svr4/sys/wait.h'\" \(141 characters\)
sed "s/^X//" >'svr4/sys/wait.h' <<'END_OF_FILE'
X/* Fixups for wait. */
X
X#ifndef _PORT_WAIT_H
X#define _PORT_WAIT_H
X
X/* Postgres wants bsd wait.h */
X
X#include <ucbinclude/sys/wait.h>
X
X#endif
END_OF_FILE
if test 141 -ne `wc -c <'svr4/sys/wait.h'`; then
    echo shar: \"'svr4/sys/wait.h'\" unpacked with wrong size!
fi
# end of 'svr4/sys/wait.h'
fi
if test -f 'svr4/time.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'svr4/time.h'\"
else
echo shar: Extracting \"'svr4/time.h'\" \(155 characters\)
sed "s/^X//" >'svr4/time.h' <<'END_OF_FILE'
X/* Cause inclusion of time.h to also include timeb.h */
X
X#ifndef _PORT_TIME_H
X#define _PORT_TIME_H
X#include "include/time.h"
X#include <sys/timeb.h>
X#endif
END_OF_FILE
if test 155 -ne `wc -c <'svr4/time.h'`; then
    echo shar: \"'svr4/time.h'\" unpacked with wrong size!
fi
# end of 'svr4/time.h'
fi
if test -f 'svr4/README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'svr4/README'\"
else
echo shar: Extracting \"'svr4/README'\" \(42 characters\)
sed "s/^X//" >'svr4/README' <<'END_OF_FILE'
XMay require a fixed SED, such as gnu sed.
END_OF_FILE
if test 42 -ne `wc -c <'svr4/README'`; then
    echo shar: \"'svr4/README'\" unpacked with wrong size!
fi
# end of 'svr4/README'
fi
echo shar: End of shell archive.
exit 0
---
 Robert Withrow, Tel: +1 617 598 4480, Fax: +1 617 598 4430, Net: [email-masked]
 R.W. Withrow Associates, 21 Railroad Ave, Swampscott MA 01907-1821 USA