diff --git a/configure.ac b/configure.ac
index e63b887727..35e926e89e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,1510 +1,1517 @@
 dnl
 dnl autoconf for Pacemaker
 dnl
 dnl License: GNU General Public License (GPL)
 
 dnl ===============================================
 dnl Bootstrap 
 dnl ===============================================
 AC_PREREQ(2.53)
 
 dnl Suggested structure:
 dnl     information on the package
 dnl     checks for programs
 dnl     checks for libraries
 dnl     checks for header files
 dnl     checks for types
 dnl     checks for structures
 dnl     checks for compiler characteristics
 dnl     checks for library functions
 dnl     checks for system services
 
 AC_INIT(pacemaker, 1.1.1, pacemaker@oss.clusterlabs.org)
 CRM_DTD_VERSION="1.2"
 
 PKG_FEATURES=""
 HB_PKG=heartbeat
 
 AC_CONFIG_AUX_DIR(.)
 AC_CANONICAL_HOST
 
 dnl Where #defines go (e.g. `AC_CHECK_HEADERS' below)
 dnl
 dnl Internal header: include/config.h
 dnl   - Contains ALL defines
 dnl   - include/config.h.in is generated automatically by autoheader
 dnl   - NOT to be included in any header files except lha_internal.h
 dnl     (which is also not to be included in any other header files)
 dnl
 dnl External header: include/crm_config.h
 dnl   - Contains a subset of defines checked here
 dnl   - Manually edit include/crm_config.h.in to have configure include
 dnl     new defines
 dnl   - Should not include HAVE_* defines
 dnl   - Safe to include anywhere
 AM_CONFIG_HEADER(include/config.h include/crm_config.h)
 ALL_LINGUAS="en fr"
 
 AC_ARG_WITH(version,
     [  --with-version=version   Override package version (if you're a packager needing to pretend) ],
     [ PACKAGE_VERSION="$withval" ])
 
 AC_ARG_WITH(pkg-name,
     [  --with-pkg-name=name     Override package name (if you're a packager needing to pretend) ],
     [ PACKAGE_NAME="$withval" ])
 
 AM_INIT_AUTOMAKE($PACKAGE_NAME, $PACKAGE_VERSION)
 AC_DEFINE_UNQUOTED(PACEMAKER_VERSION, "$PACKAGE_VERSION", Current pacemaker version)
 
 PACKAGE_SERIES=`echo $PACKAGE_VERSION | awk -F. '{ print $1"."$2 }'`
 AC_SUBST(PACKAGE_SERIES)
 
 dnl automake >= 1.11 offers --enable-silent-rules for suppressing the output from
 dnl normal compilation.  When a failure occurs, it will then display the full 
 dnl command line
 dnl Wrap in m4_ifdef to avoid breaking on older platforms
 m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES])
 
 CC_IN_CONFIGURE=yes
 export CC_IN_CONFIGURE
 
 LDD=ldd
 
 dnl ========================================================================
 dnl Compiler characteristics
 dnl ========================================================================
 
 AC_PROG_CC dnl Can force other with environment variable "CC".
 AM_PROG_CC_C_O
 AC_PROG_CC_STDC
 
 AC_LIBTOOL_DLOPEN               dnl Enable dlopen support...
 AC_LIBLTDL_CONVENIENCE          dnl make libltdl a convenience lib
 AC_PROG_LIBTOOL
 
 AC_C_STRINGIZE
 AC_TYPE_SIZE_T
 AC_CHECK_SIZEOF(char)
 AC_CHECK_SIZEOF(short)
 AC_CHECK_SIZEOF(int)
 AC_CHECK_SIZEOF(long)
 AC_CHECK_SIZEOF(long long)
 AC_STRUCT_TIMEZONE
 
 dnl ===============================================
 dnl Helpers 
 dnl ===============================================
 cc_supports_flag() {
          local CFLAGS="$@"
          AC_MSG_CHECKING(whether $CC supports "$@")
          AC_COMPILE_IFELSE([int main(){return 0;}] ,[RC=0; AC_MSG_RESULT(yes)],[RC=1; AC_MSG_RESULT(no)])
          return $RC
 }
 
 extract_header_define() {
 	  AC_MSG_CHECKING(for $2 in $1)
 	  Cfile=/tmp/extract_define.$2.${$}
 	  printf "#include <stdio.h>\n" > ${Cfile}.c
 	  printf "#include <%s>\n" $1 >> ${Cfile}.c
 	  printf "int main(int argc, char **argv) { printf(\"%%s\", %s); return 0; }\n" $2 >> ${Cfile}.c
 	  $CC $CFLAGS ${Cfile}.c -o ${Cfile}
 	  value=`${Cfile}`
 	  AC_MSG_RESULT($value)
 	  printf $value
 	  rm -f ${Cfile}.c ${Cfile}
 	}
 
 dnl ===============================================
 dnl Configure Options
 dnl ===============================================
 
 dnl Some systems, like Solaris require a custom package name
 AC_ARG_WITH(pkgname,
     [  --with-pkgname=name     name for pkg (typically for Solaris) ],
     [ PKGNAME="$withval" ],
     [ PKGNAME="LXHAhb" ],
   )
 AC_SUBST(PKGNAME)
 
 AC_ARG_ENABLE([ansi],
 [  --enable-ansi force GCC to compile to ANSI/ANSI standard for older compilers.
      [default=yes]])
 
 AC_ARG_ENABLE([fatal-warnings],
 [  --enable-fatal-warnings very pedantic and fatal warnings for gcc
      [default=yes]])
 
 AC_ARG_ENABLE([pretty],
 [  --enable-pretty 
      Pretty-print compiler output unless there is an error
      [default=no]])
 
 AC_ARG_ENABLE([quiet],
 [  --enable-quiet 
      Supress make output unless there is an error
      [default=no]])
 
 AC_ARG_ENABLE([thread-safe],
 [  --enable-thread-safe Enable some client libraries to be thread safe.
      [default=no]])
 
 AC_ARG_ENABLE([bundled-ltdl],
 [  --enable-bundled-ltdl  Configure, build and install the standalone ltdl library bundled with ${PACKAGE} [default=no]]) 
 LTDL_LIBS=""
 
 AC_ARG_WITH(ais,
     [  --with-ais     
        Support the OpenAIS messaging and membership layer ],
     [ SUPPORT_AIS=$withval ],
     [ SUPPORT_AIS=try ],
 )
 
 AC_ARG_WITH(heartbeat,
     [  --with-heartbeat     
        Support the Heartbeat messaging and membership layer ],
     [ SUPPORT_HEARTBEAT=$withval ],
     [ SUPPORT_HEARTBEAT=try ],
 )
 
 AC_ARG_WITH(snmp,
     [  --with-snmp     
        Support the SNMP protocol ],
     [ SUPPORT_SNMP=$withval ],
     [ SUPPORT_SNMP=try ],
 )
 
 AC_ARG_WITH(esmtp,
     [  --with-esmtp  
        Support the sending mail notifications with the esmtp library ],
     [ SUPPORT_ESMTP=$withval ],
     [ SUPPORT_ESMTP=try ],
 )
 
 AISPREFIX=""
 AC_ARG_WITH(ais-prefix,
     [  --with-ais-prefix=DIR  Prefix used when OpenAIS was installed [$prefix]],
     [ AISPREFIX=$withval ], 
     [ AISPREFIX=$prefix ])
 
 LCRSODIR=""
 AC_ARG_WITH(lcrso-dir, 
     [  --with-lcrso-dir=DIR   OpenAIS lcrso files. ],
     [ LCRSODIR="$withval" ])
 
 INITDIR=""
 AC_ARG_WITH(initdir,
     [  --with-initdir=DIR      directory for init (rc) scripts [${INITDIR}]],
     [ INITDIR="$withval" ])
 
 PUBLICAN_BRAND="common"
 AC_ARG_WITH(brand,
     [  --with-brand=brand  Brand to use for generated documentation [$PUBLICAN_BRAND]],
     [ PUBLICAN_BRAND="$withval" ])
 AC_SUBST(PUBLICAN_BRAND)
 
 dnl ===============================================
 dnl General Processing
 dnl ===============================================
 
 AC_SUBST(HB_PKG)
 
 INIT_EXT=""
 echo Our Host OS: $host_os/$host
 
 
 AC_MSG_NOTICE(Sanitizing prefix: ${prefix})
 case $prefix in
   NONE)	prefix=/usr;;
 esac
 
 AC_MSG_NOTICE(Sanitizing exec_prefix: ${exec_prefix})
 case $exec_prefix in
   dnl For consistency with Heartbeat, map NONE->$prefix
   NONE)	  exec_prefix=$prefix;;
   prefix) exec_prefix=$prefix;;
 esac
 
 AC_MSG_NOTICE(Sanitizing ais_prefix: ${AISPREFIX})
 case $AISPREFIX in
   dnl For consistency with Heartbeat, map NONE->$prefix
   NONE)	  AISPREFIX=$prefix;;
   prefix) AISPREFIX=$prefix;;
 esac
 
 AC_MSG_NOTICE(Sanitizing INITDIR: ${INITDIR})
 case $INITDIR in
   prefix) INITDIR=$prefix;;
   "")
     AC_MSG_CHECKING(which init (rc) directory to use)
       for initdir in /etc/init.d /etc/rc.d/init.d /sbin/init.d	\
 	   /usr/local/etc/rc.d /etc/rc.d
       do
         if
           test -d $initdir
         then
           INITDIR=$initdir
           break
         fi
       done
       AC_MSG_RESULT($INITDIR);;
 esac
 AC_SUBST(INITDIR)
 
 AC_MSG_NOTICE(Sanitizing libdir: ${libdir})
 case $libdir in
   dnl For consistency with Heartbeat, map NONE->$prefix
   *prefix*|NONE)
     AC_MSG_CHECKING(which lib directory to use)
     for aDir in lib64 lib
     do
       trydir="${exec_prefix}/${aDir}"
       if
         test -d ${trydir}
       then
         libdir=${trydir}
         break
       fi
     done
     AC_MSG_RESULT($libdir);
     ;;
 esac
 
 dnl Expand autoconf variables so that we dont end up with '${prefix}' 
 dnl in #defines and python scripts
 dnl NOTE: Autoconf deliberately leaves them unexpanded to allow
 dnl    make exec_prefix=/foo install
 dnl No longer being able to do this seems like no great loss to me...
 
 eval prefix="`eval echo ${prefix}`"
 eval exec_prefix="`eval echo ${exec_prefix}`"
 eval bindir="`eval echo ${bindir}`"
 eval sbindir="`eval echo ${sbindir}`"
 eval libexecdir="`eval echo ${libexecdir}`"
 eval datadir="`eval echo ${datadir}`"
 eval sysconfdir="`eval echo ${sysconfdir}`"
 eval sharedstatedir="`eval echo ${sharedstatedir}`"
 eval localstatedir="`eval echo ${localstatedir}`"
 eval libdir="`eval echo ${libdir}`"
 eval includedir="`eval echo ${includedir}`"
 eval oldincludedir="`eval echo ${oldincludedir}`"
 eval infodir="`eval echo ${infodir}`"
 eval mandir="`eval echo ${mandir}`"
 
 dnl Home-grown variables
 eval INITDIR="${INITDIR}"
 eval docdir="`eval echo ${docdir}`"
 if test x"${docdir}" = x""; then
    docdir=${datadir}/doc/${PACKAGE}-${VERSION}
    #docdir=${datadir}/doc/packages/${PACKAGE}
 fi
 AC_SUBST(docdir)
 
 for j in prefix exec_prefix bindir sbindir libexecdir datadir sysconfdir \
     sharedstatedir localstatedir libdir includedir oldincludedir infodir \
     mandir INITDIR docdir
 do 
   dirname=`eval echo '${'${j}'}'`
   if
     test ! -d "$dirname"
   then
     AC_MSG_WARN([$j directory ($dirname) does not exist!])
   fi
 done
 
 dnl This OS-based decision-making is poor autotools practice;
 dnl feature-based mechanisms are strongly preferred.
 dnl
 dnl So keep this section to a bare minimum; regard as a "necessary evil". 
 
 case "$host_os" in
 *bsd*)		LIBS="-L/usr/local/lib"
 		CPPFLAGS="$CPPFLAGS -I/usr/local/include"
 		INIT_EXT=".sh"
 		;;
 *solaris*)
 		;;
 *linux*)	
 		AC_DEFINE_UNQUOTED(ON_LINUX, 1, Compiling for Linux platform)
   		CFLAGS="$CFLAGS -I${prefix}/include"
  		;;
 darwin*)	
 		AC_DEFINE_UNQUOTED(ON_DARWIN, 1, Compiling for Darwin platform)
   		LIBS="$LIBS -L${prefix}/lib"
   		CFLAGS="$CFLAGS -I${prefix}/include"
 		;;
 esac
 
 dnl Eventually remove this 
 CFLAGS="$CFLAGS -I${prefix}/include/heartbeat"
 
 AC_SUBST(INIT_EXT)
 AC_DEFINE_UNQUOTED(HA_LOG_FACILITY, LOG_DAEMON, Default logging facility)
 
 AC_MSG_NOTICE(Host CPU: $host_cpu)
 
 case "$host_cpu" in
   ppc64|powerpc64)
     case $CFLAGS in
      *powerpc64*)			;;
      *)	if test "$GCC" = yes; then
 	  CFLAGS="$CFLAGS -m64"
 	fi				;;
     esac
 esac
 
 AC_MSG_CHECKING(which format is needed to print uint64_t)
 
 ac_save_CFLAGS=$CFLAGS
 CFLAGS="-Wall -Werror"
 
 AC_COMPILE_IFELSE(
     [AC_LANG_PROGRAM(
       [
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
       ],
       [
 int max = 512;	
 uint64_t bignum = 42;
 char *buffer = malloc(max);
 const char *random = "random";
 snprintf(buffer, max-1, "<quorum id=%lu quorate=%s/>", bignum, random);
 fprintf(stderr, "Result: %s\n", buffer);
       ]
     )], 
     [U64T="%lu"],
     [U64T="%llu"]
 )
 CFLAGS=$ac_save_CFLAGS
 
 AC_MSG_RESULT($U64T)
 AC_DEFINE_UNQUOTED(U64T, "$U64T", Correct printf format for logging uint64_t)
 
 AC_CHECK_HEADERS(hb_config.h)
 AC_CHECK_HEADERS(glue_config.h)
 GLUE_HEADER=none
 if test "$ac_cv_header_glue_config_h" = "yes";  then
    GLUE_HEADER=glue_config.h
 
 elif test "$ac_cv_header_hb_config_h" = "yes"; then
    GLUE_HEADER=hb_config.h
 
 else
    AC_MSG_FAILURE(Core development headers were not found)
 fi
 
 dnl Variables needed for substitution
 CRM_DTD_DIRECTORY="${datadir}/pacemaker"
 AC_DEFINE_UNQUOTED(CRM_DTD_DIRECTORY,"$CRM_DTD_DIRECTORY", Location for the Pacemaker Relax-NG Schema)
 AC_SUBST(CRM_DTD_DIRECTORY)
 
 AC_DEFINE_UNQUOTED(CRM_DTD_VERSION,"$CRM_DTD_VERSION", Current version of the Pacemaker Relax-NG Schema)
 AC_SUBST(CRM_DTD_VERSION)
 
 CRM_DAEMON_USER=`extract_header_define $GLUE_HEADER HA_CCMUSER`
 AC_DEFINE_UNQUOTED(CRM_DAEMON_USER,"$CRM_DAEMON_USER", User to run Pacemaker daemons as)
 AC_SUBST(CRM_DAEMON_USER)
 
 CRM_DAEMON_GROUP=`extract_header_define $GLUE_HEADER HA_APIGROUP`
 AC_DEFINE_UNQUOTED(CRM_DAEMON_GROUP,"$CRM_DAEMON_GROUP", Group to run Pacemaker daemons as)
 AC_SUBST(CRM_DAEMON_GROUP)
 
 CRM_STATE_DIR=${localstatedir}/run/crm
 AC_DEFINE_UNQUOTED(CRM_STATE_DIR,"$CRM_STATE_DIR", Where to keep state files and sockets)
 AC_SUBST(CRM_STATE_DIR)
 
 PE_STATE_DIR="${localstatedir}/lib/pengine"
 AC_DEFINE_UNQUOTED(PE_STATE_DIR,"$PE_STATE_DIR", Where to keep PEngine outputs)
 AC_SUBST(PE_STATE_DIR)
 
 dnl Eventually move out of the heartbeat dir tree and create compatability code
 CRM_CONFIG_DIR="${localstatedir}/lib/heartbeat/crm"
 AC_DEFINE_UNQUOTED(CRM_CONFIG_DIR,"$CRM_CONFIG_DIR", Where to keep CIB configuration files)
 AC_SUBST(CRM_CONFIG_DIR)
 
 dnl Eventually move out of the heartbeat dir tree and create symlinks when needed
 CRM_DAEMON_DIR=`extract_header_define $GLUE_HEADER HA_LIBHBDIR`
 AC_DEFINE_UNQUOTED(CRM_DAEMON_DIR,"$CRM_DAEMON_DIR", Location for Pacemaker daemons)
 AC_SUBST(CRM_DAEMON_DIR)
 
 dnl Needed so that the AIS plugin can clear out the directory as Heartbeat does
 HA_STATE_DIR=`extract_header_define $GLUE_HEADER HA_VARRUNDIR`
 AC_DEFINE_UNQUOTED(HA_STATE_DIR,"$HA_STATE_DIR", Where Heartbeat keeps state files and sockets)
 AC_SUBST(HA_STATE_DIR)
 
+CRM_RSCTMP_DIR=`extract_header_define $GLUE_HEADER HA_RSCTMPDIR`
+if test x$CRM_RSCTMP_DIR = x; then
+   CRM_RSCTMP_DIR="$HA_STATE_DIR/heartbeat/rsctmp"
+fi
+AC_DEFINE_UNQUOTED(CRM_RSCTMP_DIR,"$CRM_RSCTMP_DIR", Where resource agents should keep state files)
+AC_SUBST(CRM_RSCTMP_DIR)
+
 dnl Needed for the location of hostcache in CTS.py
 HA_VARLIBHBDIR=`extract_header_define $GLUE_HEADER HA_VARLIBHBDIR`
 AC_SUBST(HA_VARLIBHBDIR)
 
 AC_DEFINE_UNQUOTED(UUID_FILE,"$localstatedir/lib/heartbeat/hb_uuid", Location of Heartbeat's UUID file)
 
 OCF_ROOT_DIR=`extract_header_define $GLUE_HEADER OCF_ROOT_DIR`
 if test "X$OCF_ROOT_DIR" = X; then
   AC_MSG_ERROR(Could not locate OCF directory)
 fi
 AC_SUBST(OCF_ROOT_DIR)
 
 OCF_RA_DIR=`extract_header_define $GLUE_HEADER OCF_RA_DIR`
 AC_DEFINE_UNQUOTED(OCF_RA_DIR,"$OCF_RA_DIR", Location for OCF RAs)
 AC_SUBST(OCF_RA_DIR)
 
 dnl Extract this value from glue_config.h once we no longer support anything else
 STONITH_PLUGIN_DIR="$libdir/stonith/plugins/stonith/"
 AC_DEFINE_UNQUOTED(STONITH_PLUGIN_DIR,"$STONITH_PLUGIN_DIR", Location for Stonith plugins)
 AC_SUBST(STONITH_PLUGIN_DIR)
 
 RH_STONITH_DIR="$sbindir"
 AC_DEFINE_UNQUOTED(RH_STONITH_DIR,"$RH_STONITH_DIR", Location for Red Hat Stonith agents)
 
 RH_STONITH_PREFIX="fence_"
 AC_DEFINE_UNQUOTED(RH_STONITH_PREFIX,"$RH_STONITH_PREFIX", Prefix for Red Hat Stonith agents)
 
 AC_PATH_PROGS(HG, hg false)
 AC_MSG_CHECKING(build version)
 BUILD_VERSION=unknown
 if test -f $srcdir/.hg_archival.txt; then
    BUILD_VERSION=`cat $srcdir/.hg_archival.txt | awk '/node:/ { print $2 }'`
 elif test -x $HG -a -d .hg; then
    BUILD_VERSION=`$HG id -itb`
    if test $? != 0; then
        BUILD_VERSION=unknown
    fi
 fi
 
 AC_DEFINE_UNQUOTED(BUILD_VERSION, "$BUILD_VERSION", Build version)
 AC_MSG_RESULT($BUILD_VERSION)
 AC_SUBST(BUILD_VERSION)
 
 dnl ===============================================
 dnl Program Paths
 dnl ===============================================
 
 PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin"
 export PATH
 
 
 dnl Replacing AC_PROG_LIBTOOL with AC_CHECK_PROG because LIBTOOL
 dnl was NOT being expanded all the time thus causing things to fail.
 AC_CHECK_PROGS(LIBTOOL, glibtool libtool libtool15 libtool13)
 
 AM_PATH_PYTHON
 AC_CHECK_PROGS(MAKE, gmake make)
 AC_PATH_PROGS(HTML2TXT, lynx w3m)
 AC_PATH_PROGS(HELP2MAN, help2man)
 AC_PATH_PROGS(POD2MAN, pod2man, pod2man)
 AC_PATH_PROGS(ASCIIDOC, asciidoc)
 AC_PATH_PROGS(PUBLICAN, publican)
 AC_PATH_PROGS(FOP, fop)
 AC_PATH_PROGS(SSH, ssh, /usr/bin/ssh)
 AC_PATH_PROGS(SCP, scp, /usr/bin/scp)
 AC_PATH_PROGS(HG, hg, /bin/false)
 AC_PATH_PROGS(TAR, tar)
 AC_PATH_PROGS(MD5, md5)
 AC_PATH_PROGS(TEST, test)
 AC_PATH_PROGS(PKGCONFIG, pkg-config)
 AC_PATH_PROGS(XML2CONFIG, xml2-config)
 AC_PATH_PROGS(VALGRIND_BIN, valgrind, /usr/bin/valgrind)
 AC_DEFINE_UNQUOTED(VALGRIND_BIN, "$VALGRIND_BIN", Valgrind command)
 
 if test x"${LIBTOOL}" = x""; then
    AC_MSG_ERROR(You need (g)libtool installed in order to build ${PACKAGE})
 fi
 if test x"${MAKE}" = x""; then
    AC_MSG_ERROR(You need (g)make installed in order to build ${PACKAGE})
 fi
 
 AM_CONDITIONAL(BUILD_HELP, test x"${HELP2MAN}" != x"")
 if test x"${HELP2MAN}" != x""; then
    PKG_FEATURES="$PKG_FEATURES manpages"
 fi
 
 AM_CONDITIONAL(BUILD_ASCIIDOC, test x"${ASCIIDOC}" != x"")
 if test x"${ASCIIDOC}" != x""; then
    PKG_FEATURES="$PKG_FEATURES asciidoc"
 fi
 
 AM_CONDITIONAL(BUILD_DOCBOOK, test ${PUBLICAN} != x"")
 if test ${PUBLICAN} != x""; then
    PKG_FEATURES="$PKG_FEATURES publican"
 fi
 
 dnl ===============================================
 dnl Libraries
 dnl ===============================================
 AC_CHECK_LIB(socket, socket)			dnl -lsocket
 AC_CHECK_LIB(c, dlopen)				dnl if dlopen is in libc...
 AC_CHECK_LIB(dl, dlopen)			dnl -ldl (for Linux)
 AC_CHECK_LIB(rt, sched_getscheduler)            dnl -lrt (for Tru64)
 AC_CHECK_LIB(gnugetopt, getopt_long)		dnl -lgnugetopt ( if available )
 AC_CHECK_LIB(pam, pam_start)			dnl -lpam (if available)
 AC_CHECK_LIB(uuid, uuid_parse)			dnl e2fsprogs
 AC_CHECK_LIB(uuid, uuid_create)			dnl ossp
 
 if test x"${PKGCONFIG}" = x""; then
    AC_MSG_ERROR(You need pkgconfig installed in order to build ${PACKAGE})
 fi
 
 dnl
 dnl     On many systems libcrypto is needed when linking against libsnmp.
 dnl     Check to see if it exists, and if so use it.
 dnl
 AC_CHECK_LIB(crypto, CRYPTO_free, CRYPTOLIB="-lcrypto",)
 AC_SUBST(CRYPTOLIB)
 
 if test "x${enable_thread_safe}" = "xyes"; then
         GPKGNAME="gthread-2.0"
 else
         GPKGNAME="glib-2.0"
 fi
 
 if 
    $PKGCONFIG --exists $GPKGNAME
 then
 	GLIBCONFIG="$PKGCONFIG $GPKGNAME"
 else
 	set -x
         echo PKG_CONFIG_PATH=$PKG_CONFIG_PATH
 	$PKGCONFIG --exists $GPKGNAME; echo $?
 	$PKGCONFIG --cflags $GPKGNAME; echo $?
 	$PKGCONFIG $GPKGNAME; echo $?
 	set +x
         
 	AC_MSG_ERROR(You need glib2-devel installed in order to build ${PACKAGE})
 fi
 AC_MSG_RESULT(using $GLIBCONFIG)
 
 #
 #	Where is dlopen?
 #
 if test "$ac_cv_lib_c_dlopen" = yes; then
 	LIBADD_DL=""
 elif test "$ac_cv_lib_dl_dlopen" = yes; then
 	LIBADD_DL=-ldl
 else
         LIBADD_DL=${lt_cv_dlopen_libs}
 fi
 dnl
 dnl Check for location of gettext
 dnl
 dnl On at least Solaris 2.x, where it is in libc, specifying lintl causes
 dnl grief. Ensure minimal result, not the sum of all possibilities.
 dnl And do libc first.
 dnl Known examples:
 dnl    c:      Linux, Solaris 2.6+
 dnl    intl:   BSD, AIX
 
 AC_CHECK_LIB(c, gettext)
 if test x$ac_cv_lib_c_gettext != xyes; then
    AC_CHECK_LIB(intl, gettext)
 fi
 
 if test x$ac_cv_lib_c_gettext != xyes -a x$ac_cv_lib_intl_gettext != xyes; then
    AC_MSG_ERROR(You need gettext installed in order to build ${PACKAGE})
 fi
 
 if test "X$GLIBCONFIG" != X; then
 	AC_MSG_CHECKING(for special glib includes: )
 	GLIBHEAD=`$GLIBCONFIG --cflags`
 	AC_MSG_RESULT($GLIBHEAD)
 	CPPFLAGS="$CPPFLAGS $GLIBHEAD"
 
 	AC_MSG_CHECKING(for glib library flags)
 	GLIBLIB=`$GLIBCONFIG --libs`
 	AC_MSG_RESULT($GLIBLIB)
 	LIBS="$LIBS $GLIBLIB"
 fi
 
 dnl ========================================================================
 dnl Headers
 dnl ========================================================================
 
 AC_HEADER_STDC
 AC_CHECK_HEADERS(arpa/inet.h)
 AC_CHECK_HEADERS(asm/types.h)
 AC_CHECK_HEADERS(assert.h)
 AC_CHECK_HEADERS(auth-client.h)
 AC_CHECK_HEADERS(ctype.h)
 AC_CHECK_HEADERS(dirent.h)
 AC_CHECK_HEADERS(errno.h)
 AC_CHECK_HEADERS(fcntl.h)
 AC_CHECK_HEADERS(getopt.h)
 AC_CHECK_HEADERS(glib.h)
 AC_CHECK_HEADERS(grp.h)
 AC_CHECK_HEADERS(limits.h)
 AC_CHECK_HEADERS(linux/errqueue.h)
 AC_CHECK_HEADERS(malloc.h)
 AC_CHECK_HEADERS(netdb.h)
 AC_CHECK_HEADERS(netinet/in.h)
 AC_CHECK_HEADERS(netinet/ip.h)
 AC_CHECK_HEADERS(pam/pam_appl.h)
 AC_CHECK_HEADERS(pthread.h)
 AC_CHECK_HEADERS(pwd.h)
 AC_CHECK_HEADERS(security/pam_appl.h)
 AC_CHECK_HEADERS(sgtty.h)
 AC_CHECK_HEADERS(signal.h)
 AC_CHECK_HEADERS(stdarg.h)
 AC_CHECK_HEADERS(stddef.h)
 AC_CHECK_HEADERS(stdio.h)
 AC_CHECK_HEADERS(stdlib.h)
 AC_CHECK_HEADERS(string.h)
 AC_CHECK_HEADERS(strings.h)
 AC_CHECK_HEADERS(sys/dir.h)
 AC_CHECK_HEADERS(sys/ioctl.h)
 AC_CHECK_HEADERS(sys/param.h)
 AC_CHECK_HEADERS(sys/poll.h)
 AC_CHECK_HEADERS(sys/resource.h)
 AC_CHECK_HEADERS(sys/select.h)
 AC_CHECK_HEADERS(sys/socket.h)
 AC_CHECK_HEADERS(sys/sockio.h)
 AC_CHECK_HEADERS(sys/stat.h)
 AC_CHECK_HEADERS(sys/time.h)
 AC_CHECK_HEADERS(sys/timeb.h)
 AC_CHECK_HEADERS(sys/types.h)
 AC_CHECK_HEADERS(sys/uio.h)
 AC_CHECK_HEADERS(sys/un.h)
 AC_CHECK_HEADERS(sys/utsname.h)
 AC_CHECK_HEADERS(sys/wait.h)
 AC_CHECK_HEADERS(time.h)
 AC_CHECK_HEADERS(unistd.h)
 AC_CHECK_HEADERS(winsock.h)
 
 dnl These headers need prerequisits before the tests will pass 
 dnl AC_CHECK_HEADERS(net/if.h)
 dnl AC_CHECK_HEADERS(netinet/icmp6.h)
 dnl AC_CHECK_HEADERS(netinet/ip6.h)
 dnl AC_CHECK_HEADERS(netinet/ip_icmp.h)
 
 AC_MSG_CHECKING(for special libxml2 includes)
 if test "x$XML2CONFIG" = "x"; then
    AC_MSG_ERROR(libxml2 config not found)
 else
    XML2HEAD="`$XML2CONFIG --cflags`"
    AC_MSG_RESULT($XML2HEAD)
    AC_CHECK_LIB(xml2, xmlReadMemory)
    AC_CHECK_LIB(xslt, xsltApplyStylesheet)
 fi
 
 CPPFLAGS="$CPPFLAGS $XML2HEAD"
 
 AC_CHECK_HEADERS(libxml/xpath.h)
 AC_CHECK_HEADERS(libxslt/xslt.h)
 if test "$ac_cv_header_libxml_xpath_h" != "yes"; then
    AC_MSG_ERROR(The libxml developement headers were not found)
 fi
 if test "$ac_cv_header_libxslt_xslt_h" != "yes"; then
    AC_MSG_ERROR(The libxslt developement headers were not found)
 fi
 
 dnl ========================================================================
 dnl Structures
 dnl ========================================================================
 
 AC_CHECK_MEMBERS([struct tm.tm_gmtoff],,,[[#include <time.h>]])
 
 dnl ========================================================================
 dnl Functions
 dnl ========================================================================
 
 AC_CHECK_FUNCS(g_log_set_default_handler)
 AC_CHECK_FUNCS(getopt, AC_DEFINE(HAVE_DECL_GETOPT,  1, [Have getopt function]))
 
 dnl ========================================================================
 dnl   ltdl
 dnl ========================================================================
 
 AC_CHECK_LIB(ltdl, lt_dlopen, [LTDL_foo=1])
 if test "x${enable_bundled_ltdl}" = "xyes"; then
    if test $ac_cv_lib_ltdl_lt_dlopen = yes; then
       AC_MSG_NOTICE([Disabling usage of installed ltdl])
    fi
    ac_cv_lib_ltdl_lt_dlopen=no
 fi
 
 LIBLTDL_DIR=""
 if test $ac_cv_lib_ltdl_lt_dlopen != yes ; then
    AC_MSG_NOTICE([Installing local ltdl])
    LIBLTDL_DIR=libltdl
    ( cd $srcdir ; $TAR -xvf libltdl.tar )
    if test "$?" -ne 0; then
      AC_MSG_ERROR([$TAR of libltdl.tar in $srcdir failed])
    fi
    AC_CONFIG_SUBDIRS(libltdl)
 else
    LIBS="$LIBS -lltdl"
    AC_MSG_NOTICE([Using installed ltdl])
    INCLTDL=""
    LIBLTDL=""
 fi
 
 AC_SUBST(INCLTDL)
 AC_SUBST(LIBLTDL)
 AC_SUBST(LIBLTDL_DIR)
 
 dnl ========================================================================
 dnl   bzip2
 dnl ========================================================================
 AC_CHECK_HEADERS(bzlib.h)
 AC_CHECK_LIB(bz2, BZ2_bzBuffToBuffCompress)
 
 if test x$ac_cv_lib_bz2_BZ2_bzBuffToBuffCompress != xyes ; then
    AC_MSG_ERROR(BZ2 libraries not found)
 fi
 
 if test x$ac_cv_header_bzlib_h != xyes; then
    AC_MSG_ERROR(BZ2 Development headers not found)
 fi
 
 
 dnl ========================================================================
 dnl   ncurses
 dnl ========================================================================
 dnl
 dnl A few OSes (e.g. Linux) deliver a default "ncurses" alongside "curses".
 dnl Many non-Linux deliver "curses"; sites may add "ncurses".
 dnl
 dnl However, the source-code recommendation for both is to #include "curses.h"
 dnl (i.e. "ncurses" still wants the include to be simple, no-'n', "curses.h").
 dnl
 dnl ncurse takes precedence.
 dnl
 AC_CHECK_HEADERS(curses.h)
 AC_CHECK_HEADERS(curses/curses.h)
 AC_CHECK_HEADERS(ncurses.h)
 AC_CHECK_HEADERS(ncurses/ncurses.h)
 
 dnl Although n-library is preferred, only look for it if the n-header was found.
 CURSESLIBS=''
 if test "$ac_cv_header_ncurses_h" = "yes"; then
   AC_CHECK_LIB(ncurses, printw,
     [CURSESLIBS='-lncurses'; AC_DEFINE(HAVE_LIBNCURSES,1, have ncurses library)]
   )
 fi
 
 if test "$ac_cv_header_ncurses_ncurses_h" = "yes"; then
   AC_CHECK_LIB(ncurses, printw,
     [CURSESLIBS='-lncurses'; AC_DEFINE(HAVE_LIBNCURSES,1, have ncurses library)]
   )
 fi
 
 dnl Only look for non-n-library if there was no n-library.
 if test X"$CURSESLIBS" = X"" -a "$ac_cv_header_curses_h" = "yes"; then
   AC_CHECK_LIB(curses, printw,
     [CURSESLIBS='-lcurses'; AC_DEFINE(HAVE_LIBCURSES,1, have curses library)]
   )
 fi
 
 dnl Only look for non-n-library if there was no n-library.
 if test X"$CURSESLIBS" = X"" -a "$ac_cv_header_curses_curses_h" = "yes"; then
   AC_CHECK_LIB(curses, printw,
     [CURSESLIBS='-lcurses'; AC_DEFINE(HAVE_LIBCURSES,1, have curses library)]
   )
 fi
 
 if test "x$CURSESLIBS" != "x"; then
    PKG_FEATURES="$PKG_FEATURES ncurses"
 fi
 
 dnl Check for printw() prototype compatibility
 if test X"$CURSESLIBS" != X"" && cc_supports_flag -Wcast-qual && cc_supports_flag -Werror; then 
     AC_MSG_CHECKING(whether printw() requires argument of "const char *")
     ac_save_LIBS=$LIBS
     LIBS="$CURSESLIBS  $LIBS"
     ac_save_CFLAGS=$CFLAGS
     CFLAGS="-Wcast-qual -Werror"
 
     AC_LINK_IFELSE(
 	    [AC_LANG_PROGRAM(
 	      [
 #if defined(HAVE_CURSES_H)
 #  include <curses.h>
 #elif defined(HAVE_NCURSES_H)
 #  include <ncurses.h>
 #endif
 	      ],
 	      [printw((const char *)"Test");]
 	    )], 
 	    [ac_cv_compatible_printw=yes],
 	    [ac_cv_compatible_printw=no]
     )
 
     LIBS=$ac_save_LIBS
     CFLAGS=$ac_save_CFLAGS
 
     AC_MSG_RESULT([$ac_cv_compatible_printw])
 
     if test "$ac_cv_compatible_printw" = no; then
 		AC_MSG_WARN([The printw() function of your ncurses or curses library is old, we will disable usage of the library. If you want to use this library anyway, please update to newer version of the library, ncurses 5.4 or later is recommended. You can get the library from http://www.gnu.org/software/ncurses/.])
 		AC_MSG_NOTICE([Disabling curses])
 		AC_DEFINE(HAVE_INCOMPATIBLE_PRINTW, 1, [Do we have incompatible printw() in curses library?])
     fi
 fi
 
 AC_SUBST(CURSESLIBS)
 
 dnl ========================================================================
 dnl    Cluster infrastructure - Heartbeat
 dnl ========================================================================
 
 dnl On Debian, AC_CHECK_LIBS fail if a library has any unresolved symbols
 dnl So check for all the depenancies (so they're added to LIBS) before checking for -lplumb
 
 AC_CHECK_LIB(pils, PILLoadPlugin)
 AC_CHECK_LIB(plumb, G_main_add_IPC_Channel)
 
 if test x"$ac_cv_lib_plumb_G_main_add_IPC_Channel" != x"yes"; then
    AC_MSG_FAILURE(Core Heartbeat utility libraries not found: $ac_cv_lib_plumb_G_main_add_IPC_Channel)
 fi
 
 dnl Compatability checks
 AC_CHECK_FUNCS(msgfromIPC_timeout)
 AC_CHECK_MEMBERS([struct lrm_ops.fail_rsc],,,[[#include <lrm/lrm_api.h>]])
 
 dnl ========================================================================
 dnl    Cluster stack - Heartbeat
 dnl ========================================================================
 
 case $SUPPORT_HEARTBEAT in
      1|yes|true) 
         AC_CHECK_LIB(hbclient, ll_cluster_new, 
    		[SUPPORT_HEARTBEAT=1], [AC_MSG_FAILURE(Unable to support Heartbeat: client libraries not found)]);;
      try)
         AC_CHECK_LIB(hbclient, ll_cluster_new, 
    		[SUPPORT_HEARTBEAT=1], [SUPPORT_HEARTBEAT=0]);;
      *) SUPPORT_HEARTBEAT=0;;
 esac
 
 AM_CONDITIONAL(BUILD_HEARTBEAT_SUPPORT, test $SUPPORT_HEARTBEAT = 1)
 AC_DEFINE_UNQUOTED(SUPPORT_HEARTBEAT, $SUPPORT_HEARTBEAT, Support the Heartbeat messaging and membership layer)
 
 
 dnl ========================================================================
 dnl    Cluster stack - OpenAIS
 dnl ========================================================================
 
 AISLIB=""
 
 dnl Normalize the values
 case $SUPPORT_AIS in
      1|yes|true) missingisfatal=1;;
      try)        missingisfatal=0;;
      *) SUPPORT_AIS=no;;
 esac
 
 AC_MSG_CHECKING(for native AIS)
 AISMSGLIB=""
 AIS_VERSION="none"
 COROSYNC_PKG="$PKGCONFIG libcoroipcc"
 
 if test $SUPPORT_AIS = no; then
    AC_MSG_RESULT(no... not requested.)
 
 else
    AC_MSG_RESULT($SUPPORT_AIS, with '$AISPREFIX')
 
    AC_CHECK_HEADERS(openais/saAis.h)
    AC_CHECK_HEADERS(corosync/coroipcc.h)
 
    $COROSYNC_PKG --exists
    if test $? = 0; then
        AIS_VERSION="corosync"
 
    elif test "$ac_cv_header_openais_saAis_h" = "yes"; then
        AIS_VERSION="whitetank"
    else
        aisreason="Whitetank headers not found"
    fi  
 fi
 
 if test $AIS_VERSION != "none"; then
    AC_MSG_CHECKING(for OpenAIS branch)
    AC_MSG_RESULT($AIS_VERSION)
 fi
 
 if test $AIS_VERSION = "corosync"; then
    if test "$ac_cv_header_corosync_coroipcc_h" != "yes"; then
        AIS_VERSION="none"
        aisreason="Corosync headers not found"
    fi
 
    saveLIBS="$LIBS"
    LIBS="$LIBS `$COROSYNC_PKG --libs-only-L`"
    AC_CHECK_LIB(coroipcc, coroipcc_msg_send_reply_receive, [])
    LIBS="$saveLIBS"
 
    if test $ac_cv_lib_coroipcc_coroipcc_msg_send_reply_receive != yes; then
         AC_MSG_RESULT(Cannot locate AIS messaging library)
 	aisreason="requred Corosync libraries not found"
         AIS_VERSION="none"
    fi
 
 fi
 
 dnl continue?
 if test $AIS_VERSION = "whitetank"; then
    dnl Find it in lib, lib64, or wherever it wants to live...
    AC_MSG_CHECKING(location of OpenAIS libraries)
    dnl CoroSync location
    alib=`ls ${AISPREFIX}/*/libcpg.so | head -n 1`
    if test -z "$alib"; then
       dnl Whitetank location
       alib=`ls ${AISPREFIX}/*/*/libcpg.so | head -n 1`
    fi
    AISLIB=`dirname $alib`
    AC_MSG_RESULT($AISLIB)
    if test "x$AISLIB" = "x"; then
      AC_MSG_WARN(Use --with-ais-prefix to specify the prefix OpenAIS was installed with)
      aisreason="library directory not found"
      AIS_VERSION="none"
 
    elif test ! -d "$AISLIB"; then
      AC_MSG_WARN(Use --with-ais-prefix to specify the prefix OpenAIS was installed with)
      aisreason="specified library directory does not exist"
      AIS_VERSION="none"
    fi
 fi
 
 dnl continue?
 if test $AIS_VERSION = "whitetank"; then
    AC_MSG_CHECKING(location of OpenAIS plugins)
    if test -z "$LCRSODIR"; then
       LCRSODIR="$libexecdir/lcrso"
       alib=`ls ${AISPREFIX}/*/lcrso/objdb.lcrso | head -n 1`
       LCRSODIR=`dirname $alib`
    fi
    AC_MSG_RESULT($LCRSODIR)
 
    if test "x$LCRSODIR" = "x"; then
      AC_MSG_RESULT(Invalid.  Please specify the correct location with --with-lcrso-dir)
      aisreason="plugin directory not found"
      AIS_VERSION="none"
 
    elif test ! -d "$LCRSODIR"; then
      AC_MSG_RESULT(Invalid.  Please specify the correct location with --with-lcrso-dir)
      aisreason="specified plugin directory does not exist"
      AIS_VERSION="none"
    fi
 fi
 
 dnl continue?
 if test $AIS_VERSION = "whitetank"; then
      dnl Don't add the messaging library to LIBS since most daemons don't need/use it
      saveLIBS="$LIBS"
      LIBS="$LIBS -L${AISLIB} -R${AISLIB}"
 
      AC_CHECK_LIB(SaMsg, saSendReceiveReply, [])
      AC_CHECK_LIB(SaMsg, openais_msg_send_reply_receive, [])
 
      if test $ac_cv_lib_SaMsg_openais_msg_send_reply_receive = yes; then
        :  OpenAIS
      elif test $ac_cv_lib_SaMsg_saSendReceiveReply = yes; then
        :  OpenAIS
 	AC_DEFINE_UNQUOTED(TRADITIONAL_AIS_IPC, 1, "Use the 'old' AIS IPC interface")
      else
         AC_MSG_RESULT(Cannot locate AIS messaging library)
 	aisreason="requred libraries not found"
         AIS_VERSION="none"
      fi
      LIBS="$saveLIBS"
 fi
 
 SUPPORT_AIS=1
 case $AIS_VERSION in
     corosync)
 	AC_DEFINE_UNQUOTED(AIS_COROSYNC, 1, "AIS target is the corosync series")
    	LCRSODIR=`$PKGCONFIG corosync --variable=lcrsodir`
    	CFLAGS="$CFLAGS `$COROSYNC_PKG --cflags`"
 	AISMSGLIB=`$COROSYNC_PKG --libs`
 	;;
     whitetank) 
 	AC_DEFINE_UNQUOTED(AIS_WHITETANK, 1, "AIS target is the whitetank series")
 	CFLAGS="$CFLAGS -I$AISPREFIX/include/openais"
 	AISMSGLIB="-L${AISLIB} -R${AISLIB} -lSaMsg"
 	;;
     none)
      	SUPPORT_AIS=0
 	if test "x$aisreason" != x; then
      	  if test $missingisfatal = 0; then
 	    AC_MSG_WARN(Unable to support OpenAIS: $aisreason) 
           else
 	    AC_MSG_FAILURE(Unable to support OpenAIS: $aisreason) 
           fi
         fi
 	;;
     *) AC_MSG_FAILURE(Unknown OpenAIS branch: $AIS_VERSION);;
 esac
 
 AC_DEFINE_UNQUOTED(SUPPORT_AIS, $SUPPORT_AIS, Support the OpenAIS messaging and membership layer)
 AM_CONDITIONAL(BUILD_AIS_SUPPORT, test $SUPPORT_AIS = 1)
 
 dnl
 dnl    Cluster stack - Sanity
 dnl
 
 STACKS=""
 CLUSTERLIBS=""
 if test $SUPPORT_HEARTBEAT = 1; then
    STACKS="$STACKS heartbeat"
    CLUSTERLIBS="$CLUSTERLIBS -lhbclient -lccmclient"
 fi
 
 if test $SUPPORT_AIS = 1; then
    STACKS="$STACKS $AIS_VERSION"
    CLUSTERLIBS="$CLUSTERLIBS ${AISMSGLIB}"
 else
    AISPREFIX=""
    LCRSODIR="$libdir"
 fi
 
 PKG_FEATURES="$PKG_FEATURES$STACKS"
 
 AC_MSG_CHECKING(for supported stacks)
 if test x"$STACKS" = x; then
    AC_MSG_FAILURE(You must choose at least one cluster stack to support)
 fi
 AC_MSG_RESULT($STACKS)
 
 AC_SUBST(CLUSTERLIBS)
 AC_SUBST(LCRSODIR)
 
 dnl ========================================================================
 dnl    SNMP
 dnl ========================================================================
 
 case $SUPPORT_SNMP in
      1|yes|true) missingisfatal=1;;
      try)        missingisfatal=0;;
      *)		 SUPPORT_SNMP=no;;
 esac
 
 SNMPLIBS=""
 
 AC_MSG_CHECKING(for snmp support)
 if test $SUPPORT_SNMP = no; then
    AC_MSG_RESULT(no... not requested.)
    SUPPORT_SNMP=0
 else
    SNMPCONFIG=""
    AC_MSG_RESULT($SUPPORT_SNMP)
    AC_CHECK_HEADERS(net-snmp/net-snmp-config.h)
 
    if test "x${ac_cv_header_net_snmp_net_snmp_config_h}" != "xyes"; then
 	SUPPORT_SNMP="no"
    fi
 
    if test $SUPPORT_SNMP != no; then
 	AC_PATH_PROGS(SNMPCONFIG, net-snmp-config)
 	if test "X${SNMPCONFIG}" = "X"; then
 		AC_MSG_RESULT(You need the net_snmp development package to continue.)
 		SUPPORT_SNMP=no
 	fi
    fi
 
    if test $SUPPORT_SNMP != no; then
 	AC_MSG_CHECKING(for special snmp libraries)
 	SNMPLIBS=`$SNMPCONFIG --agent-libs`
 	AC_MSG_RESULT($SNMPLIBS)
    fi
 
    if test $SUPPORT_SNMP != no; then
       savedLibs=$LIBS
       LIBS="$LIBS $SNMPLIBS"
       AC_CHECK_FUNCS(netsnmp_transport_open_client)
       if test $ac_cv_func_netsnmp_transport_open_client != yes; then
          AC_CHECK_FUNCS(netsnmp_tdomain_transport)
          if test $ac_cv_func_netsnmp_tdomain_transport != yes; then
             SUPPORT_SNMP=no
 	 else
             AC_DEFINE_UNQUOTED(NETSNMPV53, 1, [Use the older 5.3 version of the net-snmp API])
          fi
       fi
       LIBS=$savedLibs
    fi
 
    if test $SUPPORT_SNMP = no; then
    	SNMPLIBS=""
    	SUPPORT_SNMP=0
      	if test $missingisfatal = 0; then
 	    AC_MSG_WARN(Unable to support SNMP) 
         else
 	    AC_MSG_FAILURE(Unable to support SNMP) 
         fi
    else
    	SUPPORT_SNMP=1
    fi
 fi
 
 if test $SUPPORT_SNMP = 1; then
    PKG_FEATURES="$PKG_FEATURES snmp"
 fi
 
 AC_SUBST(SNMPLIBS)
 AM_CONDITIONAL(ENABLE_SNMP, test "$SUPPORT_SNMP" = "1")
 AC_DEFINE_UNQUOTED(ENABLE_SNMP, $SUPPORT_SNMP, Build in support for sending SNMP traps)
 
 dnl ========================================================================
 dnl    ESMTP
 dnl ========================================================================
 
 case $SUPPORT_ESMTP in
      1|yes|true) missingisfatal=1;;
      try)        missingisfatal=0;;
      *)		 SUPPORT_ESMTP=no;;
 esac
 
 ESMTPLIB=""
 
 AC_MSG_CHECKING(for esmtp support)
 if test $SUPPORT_ESMTP = no; then
    AC_MSG_RESULT(no... not requested.)
    SUPPORT_ESMTP=0
 else
    ESMTPCONFIG=""
    AC_MSG_RESULT($SUPPORT_ESMTP)
    AC_CHECK_HEADERS(libesmtp.h)
 
    if test "x${ac_cv_header_libesmtp_h}" != "xyes"; then
 	ENABLE_ESMTP="no"
    fi
 
    if test $SUPPORT_ESMTP != no; then
 	AC_PATH_PROGS(ESMTPCONFIG, libesmtp-config)
 	if test "X${ESMTPCONFIG}" = "X"; then
 		AC_MSG_RESULT(You need the libesmtp development package to continue.)
 		SUPPORT_ESMTP=no
 	fi
    fi
 
    if test $SUPPORT_ESMTP != no; then
 	AC_MSG_CHECKING(for special esmtp libraries)
 	ESMTPLIBS=`$ESMTPCONFIG --libs | tr '\n' ' '`
 	AC_MSG_RESULT($ESMTPLIBS)
    fi
 
    if test $SUPPORT_ESMTP = no; then
    	SUPPORT_ESMTP=0
      	if test $missingisfatal = 0; then
 	    AC_MSG_WARN(Unable to support ESMTP) 
         else
 	    AC_MSG_FAILURE(Unable to support ESMTP) 
         fi
    else
    	SUPPORT_ESMTP=1
    fi
 fi
 
 if test $SUPPORT_ESMTP = 1; then
    PKG_FEATURES="$PKG_FEATURES libesmtp"
 fi
 
 AC_SUBST(ESMTPLIBS)
 AM_CONDITIONAL(ENABLE_ESMTP, test "$SUPPORT_ESMTP" = "1")
 AC_DEFINE_UNQUOTED(ENABLE_ESMTP, $SUPPORT_ESMTP, Build in support for sending mail notifications with ESMTP)
 
 dnl ========================================================================
 dnl    GnuTLS
 dnl ========================================================================
 
 AC_CHECK_HEADERS(gnutls/gnutls.h)
 AC_CHECK_HEADERS(security/pam_appl.h pam/pam_appl.h)
 
 dnl GNUTLS library: Attempt to determine by 'libgnutls-config' program.
 dnl If no 'libgnutls-config', try traditional autoconf means.
 AC_PATH_PROGS(LIBGNUTLS_CONFIG, libgnutls-config)
 
 if test -n "$LIBGNUTLS_CONFIG"; then
 	AC_MSG_CHECKING(for gnutls header flags)
 	GNUTLSHEAD="`$LIBGNUTLS_CONFIG --cflags`";
 	AC_MSG_RESULT($GNUTLSHEAD)
 	AC_MSG_CHECKING(for gnutls library flags)
 	GNUTLSLIBS="`$LIBGNUTLS_CONFIG --libs`";
 	AC_MSG_RESULT($GNUTLSLIBS)
 else
 	AC_CHECK_LIB(gnutls, gnutls_init)
 fi
 AC_SUBST(GNUTLSHEAD)
 AC_SUBST(GNUTLSLIBS)
 
 
 dnl ========================================================================
 dnl    System Health
 dnl ========================================================================
 
 dnl Check if servicelog development package is installed
 SERVICELOG=servicelog-1
 SERVICELOG_EXISTS="no"
 AC_MSG_CHECKING(for $SERVICELOG packages)
 if
     $PKGCONFIG --exists $SERVICELOG
 then
     SERVICELOG_EXISTS="yes"
 fi
 AC_MSG_RESULT($SERVICELOG_EXISTS)
 AM_CONDITIONAL(BUILD_SERVICELOG, test "$SERVICELOG_EXISTS" = "yes")
 
 dnl Check if OpenIMPI packages and servicelog are installed
 OPENIPMI="OpenIPMI OpenIPMIposix"
 OPENIPMI_SERVICELOG_EXISTS="no"
 AC_MSG_CHECKING(for $SERVICELOG $OPENIPMI packages)
 if
     $PKGCONFIG --exists $OPENIPMI $SERVICELOG
 then
     OPENIPMI_SERVICELOG_EXISTS="yes"
 fi
 AC_MSG_RESULT($OPENIPMI_SERVICELOG_EXISTS)
 AM_CONDITIONAL(BUILD_OPENIPMI_SERVICELOG, test "$OPENIPMI_SERVICELOG_EXISTS" = "yes")
 
 dnl ========================================================================
 dnl checks for library functions to replace them
 dnl
 dnl     NoSuchFunctionName:
 dnl             is a dummy function which no system supplies.  It is here to make
 dnl             the system compile semi-correctly on OpenBSD which doesn't know
 dnl             how to create an empty archive
 dnl
 dnl     scandir: Only on BSD.
 dnl             System-V systems may have it, but hidden and/or deprecated.
 dnl             A replacement function is supplied for it.
 dnl
 dnl     setenv: is some bsdish function that should also be avoided (use
 dnl             putenv instead)
 dnl             On the other hand, putenv doesn't provide the right API for the
 dnl             code and has memory leaks designed in (sigh...)  Fortunately this
 dnl             A replacement function is supplied for it.
 dnl
 dnl     strerror: returns a string that corresponds to an errno.
 dnl             A replacement function is supplied for it.
 dnl
 dnl     unsetenv: is some bsdish function that should also be avoided (No 
 dnl             replacement)
 dnl             A replacement function is supplied for it.
 dnl
 dnl	strnlen: is a gnu function similar to strlen, but safer.
 dnl		We wrote a tolearably-fast replacement function for it.
 dnl
 dnl	strndup: is a gnu function similar to strdup, but safer.
 dnl		We wrote a tolearably-fast replacement function for it.
 dnl
 dnl	daemon: is a GNU function.  The daemon() function is for programs wishing to
 dnl             detach themselves from the controlling terminal and run in the
 dnl             background as system daemon
 dnl             A replacement function is supplied for it.
 
 AC_REPLACE_FUNCS(alphasort inet_pton NoSuchFunctionName scandir setenv strerror unsetenv strnlen strndup daemon strlcpy strlcat)
 
 dnl ========================================================================
 dnl Compiler flags
 dnl ========================================================================
 
 dnl Make sure that CFLAGS is not exported. If the user did
 dnl not have CFLAGS in their environment then this should have
 dnl no effect. However if CFLAGS was exported from the user's
 dnl environment, then the new CFLAGS will also be exported
 dnl to sub processes.
 
 CC_ERRORS=""
 CC_EXTRAS=""
 
 if export | fgrep " CFLAGS=" > /dev/null; then
 	export -n CFLAGS || true # We don't want to bomb out if this fails
 fi
 
 if test "$GCC" != yes; then
         CFLAGS="$CFLAGS -g"
 	enable_fatal_warnings=no
 else
         CFLAGS="$CFLAGS -ggdb3 -O0"
 
 	# We had to eliminate -Wnested-externs because of libtool changes
         EXTRA_FLAGS="-fgnu89-inline
 		-fstack-protector-all
 		-Wall
 		-Waggregate-return
 		-Wbad-function-cast 
 		-Wcast-qual 
 		-Wcast-align 
 		-Wdeclaration-after-statement
 		-Wendif-labels
 		-Wfloat-equal
 		-Wformat=2
 		-Wformat-security
 		-Wformat-nonliteral
 		-Winline
 		-Wmissing-prototypes 
 		-Wmissing-declarations 
 		-Wnested-externs
 		-Wno-long-long
 		-Wno-strict-aliasing
 		-Wpointer-arith 
 		-Wstrict-prototypes
     		-Wunsigned-char
 		-Wwrite-strings"
 
 # Additional warnings it might be nice to enable one day
 #		-Wshadow
 #		-Wunreachable-code
 
 	for j in $EXTRA_FLAGS
 	do
 	  if
 	    cc_supports_flag $j
 	  then
 	    CC_EXTRAS="$CC_EXTRAS $j"
 	  fi
 	done
 
 dnl In lib/ais/Makefile.am there's a gcc option available as of v4.x
 
 	GCC_MAJOR=`gcc -v 2>&1 | awk 'END{print $3}' | sed 's/[.].*//'`
 	AM_CONDITIONAL(GCC_4, test "${GCC_MAJOR}" = 4)
 
 dnl System specific options
 
 	case "$host_os" in
   	*linux*|*bsd*)
 		if test "${enable_fatal_warnings}" = "unknown"; then
         		enable_fatal_warnings=yes
         	fi
           	;;
 	esac
 
 	if test "x${enable_fatal_warnings}" != xno && cc_supports_flag -Werror ; then
 	   enable_fatal_warnings=yes
 	else
 	   enable_fatal_warnings=no
         fi
 
 	if test "x${enable_ansi}" != xno && cc_supports_flag -std=iso9899:199409 ; then
 	  AC_MSG_NOTICE(Enabling ANSI Compatibility)
 	  CC_EXTRAS="$CC_EXTRAS -ansi -D_GNU_SOURCE -DANSI_ONLY"
 	fi
 
   	AC_MSG_NOTICE(Activated additional gcc flags: ${CC_EXTRAS})
 fi
 
 CFLAGS="$CFLAGS $CC_EXTRAS"
 
 NON_FATAL_CFLAGS="$CFLAGS"
 AC_SUBST(NON_FATAL_CFLAGS)
 
 dnl
 dnl We reset CFLAGS to include our warnings *after* all function
 dnl checking goes on, so that our warning flags don't keep the
 dnl AC_*FUNCS() calls above from working.  In particular, -Werror will
 dnl *always* cause us troubles if we set it before here.
 dnl
 dnl
 if test "x${enable_fatal_warnings}" = xyes ; then
    AC_MSG_NOTICE(Enabling Fatal Warnings)
    CFLAGS="$CFLAGS -Werror"
 fi
 AC_SUBST(CFLAGS)
 
 dnl This is useful for use in Makefiles that need to remove one specific flag
 CFLAGS_COPY="$CFLAGS"
 AC_SUBST(CFLAGS_COPY)
 
 AC_SUBST(LIBADD_DL)	dnl extra flags for dynamic linking libraries
 AC_SUBST(LIBADD_INTL)	dnl extra flags for GNU gettext stuff...
 
 AC_SUBST(LOCALE)
 
 dnl Options for cleaning up the compiler output 
 QUIET_LIBTOOL_OPTS=""
 QUIET_MAKE_OPTS=""
 if test "x${enable_quiet}" = "xyes"; then
    QUIET_LIBTOOL_OPTS="--quiet"
    QUIET_MAKE_OPTS="--quiet"
 fi
 
 AC_MSG_RESULT(Supress make details: ${enable_quiet})
 
 dnl Put the above variables to use
 LIBTOOL="${LIBTOOL} --tag=CC \$(QUIET_LIBTOOL_OPTS)"
 MAKE="${MAKE} \$(QUIET_MAKE_OPTS)"
 
 AC_SUBST(CC)
 AC_SUBST(MAKE)
 AC_SUBST(LIBTOOL)
 AC_SUBST(QUIET_MAKE_OPTS)
 AC_SUBST(QUIET_LIBTOOL_OPTS)
 AC_DEFINE_UNQUOTED(CRM_FEATURES, "$PKG_FEATURES", Set of enabled features)
 
 dnl The Makefiles and shell scripts we output
 AC_CONFIG_FILES(Makefile				        \
 cts/Makefile					        	\
 	cts/CTSvars.py						\
 	cts/LSBDummy						\
 cib/Makefile							\
 crmd/Makefile							\
 pengine/Makefile						\
 	pengine/regression.core.sh				\
 doc/Makefile							\
 	doc/cibadmin.8						\
 	doc/crm_resource.8					\
 	doc/Pacemaker_Explained/publican.cfg			\
 include/Makefile						\
 	include/crm/Makefile					\
 		include/crm/common/Makefile			\
 		include/crm/pengine/Makefile			\
 replace/Makefile						\
 lib/Makefile							\
 	lib/ais/Makefile					\
 	lib/common/Makefile					\
 	lib/cib/Makefile					\
 	lib/pengine/Makefile					\
 	lib/transition/Makefile					\
 	lib/fencing/Makefile					\
 	lib/plugins/Makefile					\
 		lib/plugins/lrm/Makefile			\
 fencing/Makefile                                                \
 extra/Makefile							\
 	extra/resources/Makefile				\
 tools/Makefile							\
 	tools/crm_report					\
 	tools/hb2openais.sh					\
 	tools/crm_primitive.py					\
 shell/Makefile							\
 	shell/templates/Makefile				\
 	shell/regression/Makefile				\
 	shell/regression/testcases/Makefile			\
 	shell/modules/Makefile					\
 	shell/modules/ui.py					\
 	shell/modules/ra.py					\
 	shell/modules/vars.py					\
 	shell/modules/help.py					\
 xml/Makefile							\
 		)
 
 dnl Now process the entire list of files added by previous 
 dnl  calls to AC_CONFIG_FILES()
 AC_OUTPUT()
 
 dnl *****************
 dnl Configure summary
 dnl *****************
 
 AC_MSG_RESULT([])
 AC_MSG_RESULT([$PACKAGE configuration:])
 AC_MSG_RESULT([  Version                  = ${VERSION} (Build: $BUILD_VERSION)])
 AC_MSG_RESULT([  Features                 =${PKG_FEATURES}])
 AC_MSG_RESULT([])
 AC_MSG_RESULT([  Prefix                   = ${prefix}])
 AC_MSG_RESULT([  Executables              = ${sbindir}])
 AC_MSG_RESULT([  Man pages                = ${mandir}])
 AC_MSG_RESULT([  Libraries                = ${libdir}])
 AC_MSG_RESULT([  Header files             = ${includedir}])
 AC_MSG_RESULT([  Arch-independent files   = ${datadir}])
 AC_MSG_RESULT([  State information        = ${localstatedir}])
 AC_MSG_RESULT([  System configuration     = ${sysconfdir}])
 AC_MSG_RESULT([  AIS Plugins              = ${LCRSODIR}])
 AC_MSG_RESULT([])
 AC_MSG_RESULT([  Use system LTDL          = ${ac_cv_lib_ltdl_lt_dlopen}])
 AC_MSG_RESULT([])
 AC_MSG_RESULT([  HA group name            = ${CRM_DAEMON_GROUP}])
 AC_MSG_RESULT([  HA user name             = ${CRM_DAEMON_USER}])
 AC_MSG_RESULT([])
 AC_MSG_RESULT([  CFLAGS                   = ${CFLAGS}])
 AC_MSG_RESULT([  Libraries                = ${LIBS}])
 AC_MSG_RESULT([  Stack Libraries          = ${CLUSTERLIBS}])
 
diff --git a/lib/ais/plugin.c b/lib/ais/plugin.c
index dae0eb4369..01f3f6c260 100644
--- a/lib/ais/plugin.c
+++ b/lib/ais/plugin.c
@@ -1,1674 +1,1696 @@
 /*
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #include <crm_internal.h>
 #include <sys/types.h>
 #include <sys/uio.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <errno.h>
 #include <signal.h>
 #include <string.h>
 
 #ifdef AIS_COROSYNC
 #  include <corosync/totem/totempg.h>
 #  include <corosync/engine/objdb.h>
 #  include <corosync/engine/config.h>
 #endif
 
 #include <config.h>
 #include <crm/ais.h>
 #include "plugin.h"
 #include "utils.h"
 
 #include <glib/ghash.h>
 
 #include <sys/resource.h>
 #include <sys/utsname.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
 #include <pthread.h>
 #include <bzlib.h>
 #include <pwd.h>
 
 struct corosync_api_v1 *pcmk_api = NULL;
 
 uint32_t plugin_has_votes = 0;
 uint32_t plugin_expected_votes = 2;
 
 int use_mgmtd = 0;
 int plugin_log_level = LOG_DEBUG;
 char *local_uname = NULL;
 int local_uname_len = 0;
 char *local_cname = NULL;
 int local_cname_len = 0;
 uint32_t local_nodeid = 0;
 char *ipc_channel_name = NULL;
 static uint64_t local_born_on = 0;
 
 uint64_t membership_seq = 0;
 pthread_t pcmk_wait_thread;
 
 gboolean wait_active = TRUE;
 gboolean have_reliable_membership_id = FALSE;
 GHashTable *ipc_client_list = NULL;
 GHashTable *membership_list = NULL;
 GHashTable *membership_notify_list = NULL;
 
 #define MAX_RESPAWN		100
 #define LOOPBACK_ID		16777343
 #define crm_flag_none		0x00000000
 #define crm_flag_members	0x00000001
 
 struct crm_identify_msg_s
 {
 	coroipc_request_header_t	header __attribute__((aligned(8)));
 	uint32_t		id;
 	uint32_t		pid;
 	 int32_t		votes;
 	uint32_t		processes;
 	char			uname[256];
 	char			version[256];
 	uint64_t		born_on;
 } __attribute__((packed));
 
 static crm_child_t pcmk_children[] = {
     { 0, crm_proc_none,     crm_flag_none,    0, 0, FALSE, "none",     NULL,       NULL,		   NULL, NULL },
     { 0, crm_proc_ais,      crm_flag_none,    0, 0, FALSE, "ais",      NULL,       NULL,		   NULL, NULL },
     { 0, crm_proc_lrmd,     crm_flag_none,    3, 0, TRUE,  "lrmd",     NULL,       CRM_DAEMON_DIR"/lrmd",     NULL, NULL },
     { 0, crm_proc_cib,      crm_flag_members, 2, 0, TRUE,  "cib",      CRM_DAEMON_USER, CRM_DAEMON_DIR"/cib",      NULL, NULL },
     { 0, crm_proc_crmd,     crm_flag_members, 6, 0, TRUE,  "crmd",     CRM_DAEMON_USER, CRM_DAEMON_DIR"/crmd",     NULL, NULL },
     { 0, crm_proc_attrd,    crm_flag_none,    4, 0, TRUE,  "attrd",    CRM_DAEMON_USER, CRM_DAEMON_DIR"/attrd",    NULL, NULL },
     { 0, crm_proc_stonithd, crm_flag_none,    0, 0, TRUE,  "stonithd", NULL,       "/bin/false", NULL, NULL },
     { 0, crm_proc_pe,       crm_flag_none,    5, 0, TRUE,  "pengine",  CRM_DAEMON_USER, CRM_DAEMON_DIR"/pengine",  NULL, NULL },
     { 0, crm_proc_mgmtd,    crm_flag_none,    7, 0, TRUE,  "mgmtd",    NULL,	   CRM_DAEMON_DIR"/mgmtd",    NULL, NULL },
     { 0, crm_proc_stonith_ng, crm_flag_none,  1, 0, TRUE,  "stonith-ng", NULL,     CRM_DAEMON_DIR"/stonithd", NULL, NULL },
 };
 
 void send_cluster_id(void);
 int send_cluster_msg_raw(const AIS_Message *ais_msg);
 char *pcmk_generate_membership_data(void);
 gboolean check_message_sanity(const AIS_Message *msg, const char *data);
 
 #ifdef AIS_COROSYNC
 typedef const void ais_void_ptr;
 int pcmk_shutdown(void);
 void pcmk_peer_update(enum totem_configuration_type configuration_type,
 		      const unsigned int *member_list, size_t member_list_entries,
 		      const unsigned int *left_list, size_t left_list_entries,
 		      const unsigned int *joined_list, size_t joined_list_entries,
 		      const struct memb_ring_id *ring_id);
 #else
 
 typedef void ais_void_ptr;
 extern totempg_groups_handle openais_group_handle;
 int pcmk_shutdown(struct objdb_iface_ver0 *objdb);
 void pcmk_peer_update(enum totem_configuration_type configuration_type,
 		      unsigned int *member_list, int member_list_entries,
 		      unsigned int *left_list, int left_list_entries,
 		      unsigned int *joined_list, int joined_list_entries,
 		      struct memb_ring_id *ring_id);
 #endif
 
 int pcmk_startup (struct corosync_api_v1 *corosync_api);
 int pcmk_config_init(struct corosync_api_v1 *corosync_api);
 
 int pcmk_ipc_exit (void *conn);
 int pcmk_ipc_connect (void *conn);
 void pcmk_ipc(void *conn, ais_void_ptr *msg);
 
 void pcmk_exec_dump(void);
 void pcmk_cluster_swab(void *msg);
 void pcmk_cluster_callback(ais_void_ptr *message, unsigned int nodeid);
 
 void pcmk_nodeid(void *conn, ais_void_ptr *msg);
 void pcmk_nodes(void *conn, ais_void_ptr *msg);
 void pcmk_notify(void *conn, ais_void_ptr *msg);
 void pcmk_remove_member(void *conn, ais_void_ptr *msg);
 void pcmk_quorum(void *conn, ais_void_ptr *msg);
 
 void pcmk_cluster_id_swab(void *msg);
 void pcmk_cluster_id_callback(ais_void_ptr *message, unsigned int nodeid);
 void ais_remove_peer(char *node_id);
 
 static struct corosync_lib_handler pcmk_lib_service[] =
 {
     { /* 0 */
 	.lib_handler_fn		= pcmk_ipc,
 	.flow_control		= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
 #ifdef AIS_WHITETANK
 	.response_size		= sizeof (coroipc_response_header_t),
 	.response_id		= CRM_MESSAGE_IPC_ACK,
 #endif
     },
     { /* 1 */
 	.lib_handler_fn		= pcmk_nodes,
 	.flow_control		= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
 #ifdef AIS_WHITETANK
 	.response_size		= sizeof (coroipc_response_header_t),
 	.response_id		= CRM_MESSAGE_IPC_ACK,
 #endif
     },
     { /* 2 */
 	.lib_handler_fn		= pcmk_notify,
 	.flow_control		= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
 #ifdef AIS_WHITETANK
 	.response_size		= sizeof (coroipc_response_header_t),
 	.response_id		= CRM_MESSAGE_IPC_ACK,
 #endif
     },
     { /* 3 */
 	.lib_handler_fn		= pcmk_nodeid,
 	.flow_control		= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
 #ifdef AIS_WHITETANK
 	.response_size		= sizeof (struct crm_ais_nodeid_resp_s),
 	.response_id		= crm_class_nodeid,
 #endif
     },
     { /* 4 */
 	.lib_handler_fn		= pcmk_remove_member,
 	.flow_control		= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
 #ifdef AIS_WHITETANK
 	.response_size		= sizeof (coroipc_response_header_t),
 	.response_id		= CRM_MESSAGE_IPC_ACK,
 #endif
     },
     { /* 5 */
 	.lib_handler_fn		= pcmk_quorum,
 	.flow_control		= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED,
 #ifdef AIS_WHITETANK
 	.response_size		= sizeof (coroipc_response_header_t),
 	.response_id		= CRM_MESSAGE_IPC_ACK,
 #endif
     },
 };
 
 static struct corosync_exec_handler pcmk_exec_service[] =
 {
     { /* 0 */
 	.exec_handler_fn	= pcmk_cluster_callback,
 	.exec_endian_convert_fn = pcmk_cluster_swab
     },
     { /* 1 */
 	.exec_handler_fn	= pcmk_cluster_id_callback,
 	.exec_endian_convert_fn = pcmk_cluster_id_swab
     }
 };
 
 /*
  * Exports the interface for the service
  */
 struct corosync_service_engine pcmk_service_handler = {
     .name			= (unsigned char *)"Pacemaker Cluster Manager "PACKAGE_VERSION,
     .id				= PCMK_SERVICE_ID,
     .private_data_size		= 0,
     .flow_control		= COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED, 
     .lib_init_fn		= pcmk_ipc_connect,
     .lib_exit_fn		= pcmk_ipc_exit,
     .exec_init_fn		= pcmk_startup,
     .exec_exit_fn		= pcmk_shutdown,
     .config_init_fn		= pcmk_config_init,
 #ifdef AIS_COROSYNC
     .priority			= 50,    
     .lib_engine			= pcmk_lib_service,
     .lib_engine_count		= sizeof (pcmk_lib_service) / sizeof (struct corosync_lib_handler),
     .exec_engine		= pcmk_exec_service,
     .exec_engine_count		= sizeof (pcmk_exec_service) / sizeof (struct corosync_exec_handler),
 #else
     .lib_service		= pcmk_lib_service,
     .lib_service_count		= sizeof (pcmk_lib_service) / sizeof (struct corosync_lib_handler),
     .exec_service		= pcmk_exec_service,
     .exec_service_count		= sizeof (pcmk_exec_service) / sizeof (struct corosync_exec_handler),
 #endif
     .confchg_fn			= pcmk_peer_update,
     .exec_dump_fn		= pcmk_exec_dump,
 /* 	void (*sync_init) (void); */
 /* 	int (*sync_process) (void); */
 /* 	void (*sync_activate) (void); */
 /* 	void (*sync_abort) (void); */
 };
 
 
 /*
  * Dynamic Loader definition
  */
 struct corosync_service_engine *pcmk_get_handler_ver0 (void);
 
 #ifdef AIS_COROSYNC
 struct corosync_service_engine_iface_ver0 pcmk_service_handler_iface = {
     .corosync_get_service_engine_ver0 = pcmk_get_handler_ver0
 };
 #else
 struct openais_service_handler_iface_ver0 pcmk_service_handler_iface = {
     .openais_get_service_handler_ver0 = pcmk_get_handler_ver0
 };
 #endif
 
 static struct lcr_iface openais_pcmk_ver0[1] = {
     {
 	.name				= "pacemaker",
 	.version			= 0,
 	.versions_replace		= 0,
 	.versions_replace_count		= 0,
 	.dependencies			= 0,
 	.dependency_count		= 0,
 	.constructor			= NULL,
 	.destructor			= NULL,
 	.interfaces			= NULL
     }
 };
 
 static struct lcr_comp pcmk_comp_ver0 = {
     .iface_count				= 1,
     .ifaces					= openais_pcmk_ver0
 };
 
 struct corosync_service_engine *pcmk_get_handler_ver0 (void)
 {
     return (&pcmk_service_handler);
 }
 
 __attribute__ ((constructor)) static void register_this_component (void) {
     lcr_interfaces_set (&openais_pcmk_ver0[0], &pcmk_service_handler_iface);
 
     lcr_component_register (&pcmk_comp_ver0);
 }
 
 static int plugin_has_quorum(void) 
 {
     if((plugin_expected_votes >> 1) < plugin_has_votes) {
 	return 1;
     }
     return 0;
 }
 
 static void update_expected_votes(int value) 
 {
     if(value < plugin_has_votes) {
 	/* Never drop below the number of connected nodes */
 	ais_info("Cannot update expected quorum votes %d -> %d:"
 		 " value cannot be less that the current number of votes",
 		 plugin_expected_votes, value);
 
     } else if(plugin_expected_votes != value) {
 	ais_info("Expected quorum votes %d -> %d",
 		 plugin_expected_votes, value);
 	plugin_expected_votes = value;
     }
 }
 
 /* Create our own local copy of the config so we can navigate it */
 static void process_ais_conf(void)
 {
     char *value = NULL;
     gboolean any_log = FALSE;
     hdb_handle_t top_handle = 0;
     hdb_handle_t local_handle = 0;
     
     ais_info("Reading configure");
     top_handle = config_find_init(pcmk_api, "logging");
     local_handle = config_find_next(pcmk_api, "logging", top_handle);
     
     get_config_opt(pcmk_api, local_handle, "debug", &value, "on");
     if(ais_get_boolean(value)) {
 	plugin_log_level = LOG_DEBUG;
 	pcmk_env.debug = "1";
 	
     } else {
 	plugin_log_level = LOG_INFO;
 	pcmk_env.debug = "0";
     }    
     
     get_config_opt(pcmk_api, local_handle, "to_logfile", &value, "off");
     if(ais_get_boolean(value)) {
 	get_config_opt(pcmk_api, local_handle, "logfile", &value, NULL);
 
 	if(value == NULL) {
 	    ais_err("Logging to a file requested but no log file specified");
 
 	} else {
 	    struct passwd *superuser = getpwnam("root");
 	    struct passwd *user = getpwnam(CRM_DAEMON_USER);
 	    
 	    AIS_CHECK(user != NULL,
 		      ais_err("Cluster user %s does not exist", CRM_DAEMON_USER));
 	    AIS_CHECK(superuser != NULL,
 		      ais_err("Superuser %s does not exist", "root"));
 	    pcmk_env.logfile = value;
 
 	    if(superuser && user) {
 		/* Ensure the file has the correct permissions */
 		FILE *logfile = fopen(value, "a");
 		int logfd = fileno(logfile);
 		
 		fchown(logfd, superuser->pw_uid, user->pw_gid);
 		fchmod(logfd, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
 		
 		fprintf(logfile, "Set r/w permissions for "CRM_DAEMON_USER"\n");
 		fflush(logfile);
 		fsync(fileno(logfile));
 		fclose(logfile);
 		any_log = TRUE;
 	    }
 	}
     }
 
     get_config_opt(pcmk_api, local_handle, "to_syslog", &value, "on");
     if(any_log && ais_get_boolean(value) == FALSE) {
 	ais_info("User configured file based logging and explicitly disabled syslog.");
 	value = "none";
 
     } else {
 	if(ais_get_boolean(value) == FALSE) {
 	    ais_err("Please enable some sort of logging, either 'to_file: on' or  'to_syslog: on'.");
 	    ais_err("If you use file logging, be sure to also define a value for 'logfile'");	    
 	}
 	get_config_opt(pcmk_api, local_handle, "syslog_facility", &value, "daemon");
     }
     pcmk_env.syslog = value;
 
     config_find_done(pcmk_api, local_handle);
     
     top_handle = config_find_init(pcmk_api, "service");
     local_handle = config_find_next(pcmk_api, "service", top_handle);
     while(local_handle) {
 	value = NULL;
 	pcmk_api->object_key_get(local_handle, "name", strlen("name"), (void**)&value, NULL);
 	if(ais_str_eq("pacemaker", value)) {
 	    break;
 	}
 	local_handle = config_find_next(pcmk_api, "service", top_handle);
     }
 
     get_config_opt(pcmk_api, local_handle, "clustername", &local_cname, "pcmk");
     local_cname_len = strlen(local_cname);
     
     get_config_opt(pcmk_api, local_handle, "use_logd", &value, "no");
     pcmk_env.use_logd = value;
 
     get_config_opt(pcmk_api, local_handle, "use_mgmtd", &value, "no");
     if(ais_get_boolean(value) == FALSE) {
 	int lpc = 0;
 	for (; lpc < SIZEOF(pcmk_children); lpc++) {
 	    if(crm_proc_mgmtd & pcmk_children[lpc].flag) {
 		/* Disable mgmtd startup */
 		pcmk_children[lpc].start_seq = 0;
 		break;
 	    }
 	}
     }
     
     config_find_done(pcmk_api, local_handle);
 }
 
 int pcmk_config_init(struct corosync_api_v1 *unused)
 {
     return 0;
 }
 
 static void *pcmk_wait_dispatch (void *arg)
 {
     struct timespec waitsleep = {
 	.tv_sec = 1,
 	.tv_nsec = 0
     };
     
     while(wait_active) {
 	int lpc = 0;
 	for (; lpc < SIZEOF(pcmk_children); lpc++) {
 	    if(pcmk_children[lpc].pid > 0) {
 		int status;
 		pid_t pid = wait4(
 		    pcmk_children[lpc].pid, &status, WNOHANG, NULL);
 
 		if(pid == 0) {
 		    continue;
 		    
 		} else if(pid < 0) {
 		    ais_perror("Call to wait4(%s) failed", pcmk_children[lpc].name);
 		    continue;
 		}
 
 		/* cleanup */
 		pcmk_children[lpc].pid = 0;
 		pcmk_children[lpc].conn = NULL;
 		pcmk_children[lpc].async_conn = NULL;
 
 		if(WIFSIGNALED(status)) {
 		    int sig = WTERMSIG(status);
 		    ais_err("Child process %s terminated with signal %d"
 			     " (pid=%d, core=%s)",
 			     pcmk_children[lpc].name, sig, pid,
 			     WCOREDUMP(status)?"true":"false");
 
 		} else if (WIFEXITED(status)) {
 		    int rc = WEXITSTATUS(status);
 		    do_ais_log(rc==0?LOG_NOTICE:LOG_ERR, "Child process %s exited (pid=%d, rc=%d)",
 			       pcmk_children[lpc].name, pid, rc);
 
 		    if(rc == 100) {
 			ais_notice("Child process %s no longer wishes"
 				   " to be respawned", pcmk_children[lpc].name);
 			pcmk_children[lpc].respawn = FALSE;
 		    }
 		}
 
 		pcmk_children[lpc].respawn_count += 1;
 		if(pcmk_children[lpc].respawn_count > MAX_RESPAWN) {
 		    ais_err("Child respawn count exceeded by %s",
 			       pcmk_children[lpc].name);
 		    pcmk_children[lpc].respawn = FALSE;
 		}
 		if(pcmk_children[lpc].respawn) {
 		    ais_notice("Respawning failed child process: %s",
 			       pcmk_children[lpc].name);
 		    spawn_child(&(pcmk_children[lpc]));
 		} else {
 		    send_cluster_id();
 		}
 	    }
 	}
 	sched_yield ();
 	nanosleep (&waitsleep, 0);
     }
     return 0;
 }
 
 static uint32_t pcmk_update_nodeid(void)  
 {
     int last = local_nodeid;
 #if AIS_COROSYNC
     local_nodeid = pcmk_api->totem_nodeid_get();
 #else
     local_nodeid = totempg_my_nodeid_get();
 #endif
 
     if(last != local_nodeid) {
 	if(last == 0) {
 	    ais_info("Local node id: %u", local_nodeid);
 
 	} else {
 	    char *last_s = NULL;
 	    ais_malloc0(last_s, 32);
 	    ais_warn("Detected local node id change: %u -> %u", last, local_nodeid);
 	    snprintf(last_s, 31, "%u", last);
 	    ais_remove_peer(last_s);
 	    ais_free(last_s);
 	}
 	update_member(local_nodeid, 0, 0, 1, 0, local_uname, CRM_NODE_MEMBER, NULL);
     }
     
     return local_nodeid;
 }
 
+static void build_path(const char *path_c, mode_t mode)
+{
+    int offset = 1, len = 0;
+    char *path = ais_strdup(path_c);
+
+    AIS_CHECK(path != NULL, return);
+    for(len = strlen(path); offset < len; offset++) {
+	if(path[offset] == '/') {
+	    path[offset] = 0;
+	    if(mkdir(path, mode) < 0 && errno != EEXIST) {
+		ais_perror("Could not create directory '%s'", path);
+		break;
+	    }
+	    path[offset] = '/';
+	}
+    }
+    ais_free(path);
+}
+
 int pcmk_startup(struct corosync_api_v1 *init_with)
 {
     int rc = 0;
     int lpc = 0;
     int start_seq = 1;
     struct utsname us;
     struct rlimit cores;
     static int max = SIZEOF(pcmk_children);
     struct passwd *pwentry = getpwnam(CRM_DAEMON_USER);
 
     pcmk_api = init_with;
 
 #ifdef AIS_WHITETANK 
     log_init ("crm");
 #endif
 
     pcmk_env.debug    = "0";
     pcmk_env.logfile  = NULL;
     pcmk_env.use_logd = "false";
     pcmk_env.syslog   = "daemon";
     
     process_ais_conf();
     
     membership_list = g_hash_table_new_full(
 	g_direct_hash, g_direct_equal, NULL, destroy_ais_node);
     membership_notify_list = g_hash_table_new(g_direct_hash, g_direct_equal);
     ipc_client_list = g_hash_table_new(g_direct_hash, g_direct_equal);
     
     ais_info("CRM: Initialized");
     log_printf(LOG_INFO, "Logging: Initialized %s\n", __PRETTY_FUNCTION__);
     
     rc = getrlimit(RLIMIT_CORE, &cores);
     if(rc < 0) {
 	ais_perror("Cannot determine current maximum core size.");
     }
     
     if(cores.rlim_max <= 0) {
 	cores.rlim_max = RLIM_INFINITY;
 	
 	rc = setrlimit(RLIMIT_CORE, &cores);
 	if(rc < 0) {
 	    ais_perror("Core file generation will remain disabled."
 		       " Core files are an important diagnositic tool,"
 		       " please consider enabling them by default.");
 	}
 	
     } else {
 	ais_info("Maximum core file size is: %lu", cores.rlim_max);
 	if(system("echo 1 > /proc/sys/kernel/core_uses_pid") != 0) {
 	    ais_perror("Could not enable /proc/sys/kernel/core_uses_pid");
 	}
     }
     
     AIS_CHECK(pwentry != NULL,
 	      ais_err("Cluster user %s does not exist", CRM_DAEMON_USER);
 	      return TRUE);
     
     mkdir(CRM_STATE_DIR, 0750);
     chown(CRM_STATE_DIR, pwentry->pw_uid, pwentry->pw_gid);
-    
-    mkdir(HA_STATE_DIR"/heartbeat", 0755); /* Used by RAs - Leave owned by root */
-    mkdir(HA_STATE_DIR"/heartbeat/rsctmp", 0755); /* Used by RAs - Leave owned by root */
+
+    /* Used by stonithd */
+    build_path(HA_STATE_DIR"/heartbeat", 0755); 
+
+    /* Used by RAs - Leave owned by root */
+    build_path(CRM_RSCTMP_DIR, 0755); 
 
     rc = uname(&us);
     AIS_ASSERT(rc == 0);
     local_uname = ais_strdup(us.nodename);
     local_uname_len = strlen(local_uname);	
     
     ais_info("Service: %d", PCMK_SERVICE_ID);
     ais_info("Local hostname: %s", local_uname);
     pcmk_update_nodeid();    
     
     pthread_create (&pcmk_wait_thread, NULL, pcmk_wait_dispatch, NULL);
     for (start_seq = 1; start_seq < max; start_seq++) {
 	/* dont start anything with start_seq < 1 */
 	for (lpc = 0; lpc < max; lpc++) {
 	    if(start_seq == pcmk_children[lpc].start_seq) {
 		spawn_child(&(pcmk_children[lpc]));
 	    }
 	}
     }
     
     return 0;
 }
 
 /*
   static void ais_print_node(const char *prefix, struct totem_ip_address *host) 
   {
   int len = 0;
   char *buffer = NULL;
 
   ais_malloc0(buffer, INET6_ADDRSTRLEN+1);
 	
   inet_ntop(host->family, host->addr, buffer, INET6_ADDRSTRLEN);
 
   len = strlen(buffer);
   ais_info("%s: %.*s", prefix, len, buffer);
   ais_free(buffer);
   }
 */
 
 #if 0
 /* copied here for reference from exec/totempg.c */
 char *totempg_ifaces_print (unsigned int nodeid)
 {
     static char iface_string[256 * INTERFACE_MAX];
     char one_iface[64];
     struct totem_ip_address interfaces[INTERFACE_MAX];
     char **status;
     unsigned int iface_count;
     unsigned int i;
     int res;
 
     iface_string[0] = '\0';
 
     res = totempg_ifaces_get (nodeid, interfaces, &status, &iface_count);
     if (res == -1) {
 	return ("no interface found for nodeid");
     }
 
     for (i = 0; i < iface_count; i++) {
 	sprintf (one_iface, "r(%d) ip(%s), ",
 		 i, totemip_print (&interfaces[i]));
 	strcat (iface_string, one_iface);
     }
     return (iface_string);
 }
 #endif
 
 static void ais_mark_unseen_peer_dead(
     gpointer key, gpointer value, gpointer user_data)
 {
     int *changed = user_data;
     crm_node_t *node = value;
     if(node->last_seen != membership_seq
        && ais_str_eq(CRM_NODE_LOST, node->state) == FALSE) {
 	ais_info("Node %s was not seen in the previous transition", node->uname);
 	*changed += update_member(node->id, 0, membership_seq, node->votes,
 				  node->processes, node->uname, CRM_NODE_LOST, NULL);
     }
 }
 
 void pcmk_peer_update (
     enum totem_configuration_type configuration_type,
 #ifdef AIS_COROSYNC 
     const unsigned int *member_list, size_t member_list_entries,
     const unsigned int *left_list, size_t left_list_entries,
     const unsigned int *joined_list, size_t joined_list_entries,
     const struct memb_ring_id *ring_id
 #else
     unsigned int *member_list, int member_list_entries,
     unsigned int *left_list, int left_list_entries,
     unsigned int *joined_list, int joined_list_entries,
     struct memb_ring_id *ring_id
 #endif
     )
 {
     int lpc = 0;
     int changed = 0;
     int do_update = 0;
     
     AIS_ASSERT(ring_id != NULL);
     switch(configuration_type) {
 	case TOTEM_CONFIGURATION_REGULAR:
 	    do_update = 1;
 	    break;
 	case TOTEM_CONFIGURATION_TRANSITIONAL:
 	    break;
     }
 
     membership_seq = ring_id->seq;
     ais_notice("%s membership event on ring %lld: memb=%ld, new=%ld, lost=%ld",
 	       do_update?"Stable":"Transitional", ring_id->seq,
 	       (long)member_list_entries, (long)joined_list_entries, (long)left_list_entries);
 
     if(do_update == 0) {
 	for(lpc = 0; lpc < joined_list_entries; lpc++) {
 	    const char *prefix = "new: ";
 	    uint32_t nodeid = joined_list[lpc];
 	    ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid);
 	}
 	for(lpc = 0; lpc < member_list_entries; lpc++) {
 	    const char *prefix = "memb:";
 	    uint32_t nodeid = member_list[lpc];
 	    ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid);
 	}
 	for(lpc = 0; lpc < left_list_entries; lpc++) {
 	    const char *prefix = "lost:";
 	    uint32_t nodeid = left_list[lpc];
 	    ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid);
 	}
 	return;
     }
     
     for(lpc = 0; lpc < joined_list_entries; lpc++) {
 	const char *prefix = "NEW: ";
 	uint32_t nodeid = joined_list[lpc];
 	crm_node_t *node = NULL;
 	changed += update_member(
 	    nodeid, 0, membership_seq, -1, 0, NULL, CRM_NODE_MEMBER, NULL);
 
 	ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid);
 
 	node = g_hash_table_lookup(membership_list, GUINT_TO_POINTER(nodeid));	
 	if(node->addr == NULL) {
 	    const char *addr = totempg_ifaces_print(nodeid);
 	    node->addr = ais_strdup(addr);
 	    ais_debug("Node %u has address %s", nodeid, node->addr);	    
 	}
     }
 
     for(lpc = 0; lpc < member_list_entries; lpc++) {
 	const char *prefix = "MEMB:";
 	uint32_t nodeid = member_list[lpc];
 	changed += update_member(
 	    nodeid, 0, membership_seq, -1, 0, NULL, CRM_NODE_MEMBER, NULL);
 
 	ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid);
     }
     
     for(lpc = 0; lpc < left_list_entries; lpc++) {
 	const char *prefix = "LOST:";
 	uint32_t nodeid = left_list[lpc];
 	changed += update_member(
 	    nodeid, 0, membership_seq, -1, 0, NULL, CRM_NODE_LOST, NULL);
 	ais_info("%s %s %u", prefix, member_uname(nodeid), nodeid);
     }    
 
     if(changed && joined_list_entries == 0 && left_list_entries == 0) {
 	ais_err("Something strange happened: %d", changed);
 	changed = 0;
     }
     
     ais_debug_2("Reaping unseen nodes...");
     g_hash_table_foreach(membership_list, ais_mark_unseen_peer_dead, &changed);
 
     if(member_list_entries > 1) {
 	/* Used to set born-on in send_cluster_id())
 	 * We need to wait until we have at least one peer since first
 	 * membership id is based on the one before we stopped and isn't reliable
 	 */
 	have_reliable_membership_id = TRUE;
     }
     
     if(changed) {
 	ais_debug("%d nodes changed", changed);
 	pcmk_update_nodeid();
 	send_member_notification();
     }
     
     send_cluster_id();
 }
 
 int pcmk_ipc_exit (void *conn)
 {
     int lpc = 0;
     const char *client = NULL;
     void *async_conn = conn;
     
     for (; lpc < SIZEOF(pcmk_children); lpc++) {
 	if(pcmk_children[lpc].conn == conn) {
 	    if(wait_active == FALSE) {
 		/* Make sure the shutdown loop exits */
 		pcmk_children[lpc].pid = 0;
 	    }
 	    pcmk_children[lpc].conn = NULL;
 	    pcmk_children[lpc].async_conn = NULL;
 	    client = pcmk_children[lpc].name;
 	    break;
 	}
     }
 
     g_hash_table_remove(membership_notify_list, async_conn);
     g_hash_table_remove(ipc_client_list, async_conn);
 
     do_ais_log(client?LOG_INFO:(LOG_DEBUG+1), "Client %s (conn=%p, async-conn=%p) left",
 	     client?client:"unknown-transient", conn, async_conn);
 
     return (0);
 }
 
 int pcmk_ipc_connect (void *conn)
 {
     /* OpenAIS hasn't finished setting up the connection at this point
      * Sending messages now messes up the protocol!
      */
     return (0);
 }
 
 /*
  * Executive message handlers
  */
 void pcmk_cluster_swab(void *msg)
 {
     AIS_Message *ais_msg = msg;
 
     ais_debug_3("Performing endian conversion...");
     ais_msg->id                = swab32 (ais_msg->id);
     ais_msg->size              = swab32 (ais_msg->size);
     ais_msg->is_compressed     = swab32 (ais_msg->is_compressed);
     ais_msg->compressed_size   = swab32 (ais_msg->compressed_size);
     
     ais_msg->host.id      = swab32 (ais_msg->host.id);
     ais_msg->host.pid     = swab32 (ais_msg->host.pid);
     ais_msg->host.type    = swab32 (ais_msg->host.type);
     ais_msg->host.size    = swab32 (ais_msg->host.size);
     ais_msg->host.local   = swab32 (ais_msg->host.local);
     
     ais_msg->sender.id    = swab32 (ais_msg->sender.id);
     ais_msg->sender.pid   = swab32 (ais_msg->sender.pid);
     ais_msg->sender.type  = swab32 (ais_msg->sender.type);
     ais_msg->sender.size  = swab32 (ais_msg->sender.size);
     ais_msg->sender.local = swab32 (ais_msg->sender.local);
 
     ais_msg->header.size   = swab32 (ais_msg->header.size);
     ais_msg->header.id     = swab32 (ais_msg->header.id);
     ais_msg->header.error  = swab32 (ais_msg->header.error);
 }
 
 void pcmk_cluster_callback (
     ais_void_ptr *message, unsigned int nodeid)
 {
     const AIS_Message *ais_msg = message;
 
     ais_debug_2("Message from node %u (%s)",
 		nodeid, nodeid==local_nodeid?"local":"remote");
 /*  Shouldn't be required...
     update_member(
  	ais_msg->sender.id, membership_seq, -1, 0, ais_msg->sender.uname, NULL);
 */
 
     if(ais_msg->host.size == 0
        || ais_str_eq(ais_msg->host.uname, local_uname)) {
 	route_ais_message(ais_msg, FALSE);
 
     } else {
 	ais_debug_3("Discarding Msg[%d] (dest=%s:%s, from=%s:%s)",
 		    ais_msg->id, ais_dest(&(ais_msg->host)),
 		    msg_type2text(ais_msg->host.type),
 		    ais_dest(&(ais_msg->sender)),
 		    msg_type2text(ais_msg->sender.type));
     }
 }
 
 void pcmk_cluster_id_swab(void *msg)
 {
     struct crm_identify_msg_s *ais_msg = msg;
 
     ais_debug_3("Performing endian conversion...");
     ais_msg->id        = swab32 (ais_msg->id);
     ais_msg->pid       = swab32 (ais_msg->pid);
     ais_msg->votes     = swab32 (ais_msg->votes);
     ais_msg->processes = swab32 (ais_msg->processes);
     ais_msg->born_on   = swab64 (ais_msg->born_on);
 
     ais_msg->header.size   = swab32 (ais_msg->header.size);
     ais_msg->header.id     = swab32 (ais_msg->header.id);
 }
 
 void pcmk_cluster_id_callback (ais_void_ptr *message, unsigned int nodeid)
 {
     int changed = 0;
     const struct crm_identify_msg_s *msg = message;
     if(nodeid != msg->id) {
 	ais_err("Invalid message: Node %u claimed to be node %d",
 		nodeid, msg->id);
 	return;
     }
     ais_debug("Node update: %s (%s)", msg->uname, msg->version);
     changed = update_member(
 	nodeid, msg->born_on, membership_seq, msg->votes, msg->processes, msg->uname, NULL, msg->version);
 
     if(changed) {
 	send_member_notification();
     }
 }
 
 struct res_overlay {
 	coroipc_response_header_t header __attribute((aligned(8)));
 	char buf[4096];
 };
 
 struct res_overlay *res_overlay = NULL;
 
 static void send_ipc_ack(void *conn)
 {
     if(res_overlay == NULL) {
 	ais_malloc0(res_overlay, sizeof(struct res_overlay));
     }
     
     res_overlay->header.id = CRM_MESSAGE_IPC_ACK;
     res_overlay->header.size = sizeof (coroipc_response_header_t);
     res_overlay->header.error = CS_OK;
 #ifdef AIS_COROSYNC
     pcmk_api->ipc_response_send (conn, res_overlay, res_overlay->header.size);
 #else
     openais_response_send (conn, res_overlay, res_overlay->header.size);
 #endif
 }
 
 
 /* local callbacks */
 void pcmk_ipc(void *conn, ais_void_ptr *msg)
 {
     AIS_Message *mutable;
     int type = 0, size = 0;
     gboolean transient = TRUE;
     const AIS_Message *ais_msg = (const AIS_Message*)msg;
     void *async_conn = conn;
     ais_debug_2("Message from client %p", conn);
 
     if(check_message_sanity(msg, ((const AIS_Message*)msg)->data) == FALSE) {
 	/* The message is corrupted - ignore */
 	send_ipc_ack(conn);  msg = NULL; 
 	return;
     }
 
     /* Make a copy of the message here and ACK it
      * The message is only valid until a response is sent
      * but the response must also be sent _before_ we send anything else
      */
 
     mutable = ais_msg_copy(ais_msg);
     AIS_ASSERT(check_message_sanity(mutable, mutable->data));
     
     size = mutable->header.size;
     /* ais_malloc0(ais_msg, size); */
     /* memcpy(ais_msg, msg, size); */    
     
     type = mutable->sender.type;
     ais_debug_3("type: %d local: %d conn: %p host type: %d ais: %d sender pid: %d child pid: %d size: %d",
 		type, mutable->host.local, pcmk_children[type].conn, mutable->host.type, crm_msg_ais,
 		mutable->sender.pid, pcmk_children[type].pid, ((int)SIZEOF(pcmk_children)));
     
     if(type > crm_msg_none && type < SIZEOF(pcmk_children)) {
 	/* known child process */
 	transient = FALSE;
     }
     
     /* If this check fails, the order of pcmk_children probably 
      *   doesn't match that of the crm_ais_msg_types enum
      */
     AIS_CHECK(transient || mutable->sender.pid == pcmk_children[type].pid,
 	      ais_err("Sender: %d, child[%d]: %d", mutable->sender.pid, type, pcmk_children[type].pid);
 	      return);
     
     if(transient == FALSE
        && type > crm_msg_none
        && mutable->host.local
        && pcmk_children[type].conn == NULL
        && mutable->host.type == crm_msg_ais) {
 	AIS_CHECK(mutable->sender.type != mutable->sender.pid,
 		  ais_err("Pid=%d, type=%d", mutable->sender.pid, mutable->sender.type));
 	
 	ais_info("Recorded connection %p for %s/%d",
 		 conn, pcmk_children[type].name, pcmk_children[type].pid);
 	pcmk_children[type].conn = conn;
 	pcmk_children[type].async_conn = async_conn;
 
 	/* Make sure they have the latest membership */
 	if(pcmk_children[type].flags & crm_flag_members) {
 	    char *update = pcmk_generate_membership_data();
 	    g_hash_table_replace(membership_notify_list, async_conn, async_conn);
 	    ais_info("Sending membership update "U64T" to %s",
 		     membership_seq, pcmk_children[type].name);
  	    send_client_msg(async_conn, crm_class_members, crm_msg_none,update);
 	}	
 
     } else if(transient) {
 	AIS_CHECK(mutable->sender.type == mutable->sender.pid,
 		  ais_err("Pid=%d, type=%d", mutable->sender.pid, mutable->sender.type));
 	g_hash_table_replace(ipc_client_list, async_conn, GUINT_TO_POINTER(mutable->sender.pid));
     }
 
     mutable->sender.id = local_nodeid;
     mutable->sender.size = local_uname_len;
     memset(mutable->sender.uname, 0, MAX_NAME);
     memcpy(mutable->sender.uname, local_uname, mutable->sender.size);
 
     route_ais_message(mutable, TRUE);
     send_ipc_ack(conn);  msg = NULL;
     ais_free(mutable);
 }
 
 int pcmk_shutdown (
 #ifdef AIS_COROSYNC
     void
 #else
     struct objdb_iface_ver0 *objdb
 #endif
     )
 {
     int lpc = 0;
     static int phase = 0;
     static int max_wait = 0;
     static time_t next_log = 0;
     static int max = SIZEOF(pcmk_children);
     
     if(phase == 0) {
 	ais_notice("Shuting down Pacemaker");    
 	phase = max;
     }
 
     wait_active = FALSE; /* stop the wait loop */
 
     for (; phase > 0; phase--) {
 	/* dont stop anything with start_seq < 1 */
    
 	for (lpc = max - 1; lpc >= 0; lpc--) {
 	    if(phase != pcmk_children[lpc].start_seq) {
 		continue;
 	    }
 		
 #ifdef AIS_WHITETANK
 	  retry:
 #endif
 	    
 	    if(pcmk_children[lpc].pid) {
 		pid_t pid = 0;
 		int status = 0;
 		time_t now = time(NULL);
 
 		if(pcmk_children[lpc].respawn) {
 		    max_wait = 5; /* 5 * 30s = 2.5 minutes... plenty once the crmd is gone */
 		    next_log = now + 30;
 		    pcmk_children[lpc].respawn = FALSE;
 		    stop_child(&(pcmk_children[lpc]), SIGTERM);   
 		}
 
 		pid = wait4(pcmk_children[lpc].pid, &status, WNOHANG, NULL);
 		if(pid < 0) {
 		    ais_perror("Call to wait4(%s/%d) failed - treating it as stopped",
 			       pcmk_children[lpc].name, pcmk_children[lpc].pid);
 		    
 		} else if(pid == 0) {
 		    if(now >= next_log) {
 			max_wait--;
 			next_log = now + 30;
 			ais_notice("Still waiting for %s (pid=%d, seq=%d) to terminate...",
 				   pcmk_children[lpc].name, pcmk_children[lpc].pid, pcmk_children[lpc].start_seq);
 			if(max_wait <= 0 && phase < pcmk_children[crm_msg_crmd].start_seq) {
 			    ais_err("Child %s taking too long to terminate, sending SIGKILL", pcmk_children[lpc].name);
 			    stop_child(&(pcmk_children[lpc]), SIGKILL);
 			}
 		    }		    
 #ifdef AIS_WHITETANK
 		    {
 			struct timespec waitsleep = {
 			    .tv_sec = 1,
 			    .tv_nsec = 0
 			};
 			
 			sched_yield ();
 			nanosleep (&waitsleep, 0);
 			goto retry;
 		    }
 #else
 		    /* Return control to corosync */
 		    return -1;
 #endif
 		}
 	    }
 	    
 	    /* cleanup */
 	    ais_notice("%s confirmed stopped", pcmk_children[lpc].name);
 	    pcmk_children[lpc].async_conn = NULL;
 	    pcmk_children[lpc].conn = NULL;
 	    pcmk_children[lpc].pid = 0;
 	}
     }
     
     send_cluster_id();
     ais_notice("Shutdown complete");
     /* TODO: Add back the logsys flush call once its written */
     
 #ifdef AIS_WHITETANK
     /* Bug bnc#482847, bnc#482905
      *
      * All cluster services are now down, we could allow OpenAIS to continue
      * unloading plugins, but its kinda new at that and there are a bunch of
      * race conditions that get exercised.
      *
      * Take the easy way out for now (on whitetank) and eventually fix for
      * CoroSync which is where everyone wants to be eventually anyway
      */
     ais_notice("Forcing clean exit of OpenAIS");
     exit(0);
 #endif
     return 0;
 }
 
 struct member_loop_data 
 {
 	char *string;
 };
 
 void member_vote_count_fn(gpointer key, gpointer value, gpointer user_data)
 {
     crm_node_t *node = value;
     if (ais_str_eq(CRM_NODE_MEMBER, node->state)) {
         plugin_has_votes += node->votes;
     }
 }
 
 
 void member_loop_fn(gpointer key, gpointer value, gpointer user_data)
 {
     crm_node_t *node = value;
     struct member_loop_data *data = user_data;    
 
     ais_debug_2("Dumping node %u", node->id);
     data->string = append_member(data->string, node);
 }
 
 char *pcmk_generate_membership_data(void)
 {
     int size = 0;
     struct member_loop_data data;
     size = 256; 
     ais_malloc0(data.string, size);
 
     plugin_has_votes = 0;
     g_hash_table_foreach(membership_list, member_vote_count_fn, NULL);
     if(plugin_has_votes > plugin_expected_votes) {
 	update_expected_votes(plugin_has_votes);
     }
     
     snprintf(data.string, size,
 	     "<nodes id=\""U64T"\" quorate=\"%s\" expected=\"%u\" actual=\"%u\">",
 	     membership_seq, plugin_has_quorum()?"true":"false",
 	     plugin_expected_votes, plugin_has_votes);
 
     g_hash_table_foreach(membership_list, member_loop_fn, &data);
     size = strlen(data.string);
     data.string = realloc(data.string, size + 9) ;/* 9 = </nodes> + nul */
     sprintf(data.string + size, "</nodes>");
     return data.string;
 }
 
 void pcmk_nodes(void *conn, ais_void_ptr *msg)
 {
     char *data = pcmk_generate_membership_data();
     void *async_conn = conn;
 
     /* send the ACK before we send any other messages
      * - but after we no longer need to access the message
      */
     send_ipc_ack(conn);  msg = NULL;
 
     if(async_conn) {
 	send_client_msg(async_conn, crm_class_members, crm_msg_none, data);
     }
     ais_free(data);
 }
 
 void pcmk_remove_member(void *conn, ais_void_ptr *msg)
 {
     const AIS_Message *ais_msg = msg;
     char *data = get_ais_data(ais_msg);
     send_ipc_ack(conn);  msg = NULL;
     
     if(data != NULL) {
 	char *bcast = ais_concat("remove-peer", data, ':');
 	send_cluster_msg(crm_msg_ais, NULL, bcast);
 	ais_info("Sent: %s", bcast);
 	ais_free(bcast);
     }
     
     ais_free(data);
 }
 
 static void send_quorum_details(void *conn) 
 {
     int size = 256;
     char *data = NULL;
     ais_malloc0(data, size);
     
     snprintf(data, size, "<quorum id=\""U64T"\" quorate=\"%s\" expected=\"%u\" actual=\"%u\"/>",
 	    membership_seq, plugin_has_quorum()?"true":"false",
 	    plugin_expected_votes, plugin_has_votes);
 
     send_client_msg(conn, crm_class_quorum, crm_msg_none, data);
     ais_free(data);
 }
 
 void pcmk_quorum(void *conn, ais_void_ptr *msg)
 {
     char *dummy = NULL;
     const AIS_Message *ais_msg = msg;
     char *data = get_ais_data(ais_msg);
     send_ipc_ack(conn);  msg = NULL;
 
     /* Make sure the current number of votes is accurate */
     dummy = pcmk_generate_membership_data();
     ais_free(dummy);
 
     /* Calls without data just want the current quorum details */
     if(data != NULL && strlen(data) > 0) {
 	int value = ais_get_int(data, NULL);
 	update_expected_votes(value);
     }
 
     send_quorum_details(conn);
     ais_free(data);
 }
 
 void pcmk_notify(void *conn, ais_void_ptr *msg)
 {
     const AIS_Message *ais_msg = msg;
     char *data = get_ais_data(ais_msg);
     void *async_conn = conn;
 
     int enable = 0;
     int sender = ais_msg->sender.pid;
     
     send_ipc_ack(conn);  msg = NULL;
 
     if(ais_str_eq("true", data)) {
 	enable = 1;
     }
     
     ais_info("%s node notifications for child %d (%p)",
 	     enable?"Enabling":"Disabling", sender, async_conn);
     if(enable) {
 	g_hash_table_replace(membership_notify_list, async_conn, async_conn);
     } else {
 	g_hash_table_remove(membership_notify_list, async_conn);
     }
     ais_free(data);
 }
 
 void pcmk_nodeid(void *conn, ais_void_ptr *msg)
 {
     static int counter = 0;
     struct crm_ais_nodeid_resp_s resp;
     ais_debug_2("Sending local nodeid: %d to %p[%d]", local_nodeid, conn, counter);
     
     resp.header.id = crm_class_nodeid;
     resp.header.size = sizeof (struct crm_ais_nodeid_resp_s);
     resp.header.error = CS_OK;
     resp.id = local_nodeid;
     resp.counter = counter++;
     memset(resp.uname, 0, MAX_NAME);
     memcpy(resp.uname, local_uname, local_uname_len);
     memset(resp.cname, 0, MAX_NAME);
     memcpy(resp.cname, local_cname, local_cname_len);
     
 #ifdef AIS_COROSYNC
     pcmk_api->ipc_response_send (conn, &resp, resp.header.size);
 #else
     openais_response_send (conn, &resp, resp.header.size);
 #endif
 }
 
 static gboolean
 ghash_send_update(gpointer key, gpointer value, gpointer data)
 {
     if(send_client_msg(value, crm_class_members, crm_msg_none, data) != 0) {
 	/* remove it */
 	return TRUE;
     }
     return FALSE;
 }
 
 void send_member_notification(void)
 {
     char *update = pcmk_generate_membership_data();
 
     ais_info("Sending membership update "U64T" to %d children",
 	     membership_seq,
 	     g_hash_table_size(membership_notify_list));
 
     g_hash_table_foreach_remove(membership_notify_list, ghash_send_update, update);
     ais_free(update);
 }
 
 gboolean check_message_sanity(const AIS_Message *msg, const char *data) 
 {
     gboolean sane = TRUE;
     gboolean repaired = FALSE;
     int dest = msg->host.type;
     int tmp_size = msg->header.size - sizeof(AIS_Message);
 
     if(sane && msg->header.size == 0) {
 	ais_err("Message with no size");
 	sane = FALSE;
     }
 
     if(sane && msg->header.error != CS_OK) {
 	ais_err("Message header contains an error: %d", msg->header.error);
 	sane = FALSE;
     }
 
     AIS_CHECK(msg->header.size > sizeof(AIS_Message),
 	      ais_err("Message %d size too small: %d < %zu",
 		      msg->header.id, msg->header.size, sizeof(AIS_Message));
 	      return FALSE);
 
     if(sane && ais_data_len(msg) != tmp_size) {
 	ais_warn("Message payload size is incorrect: expected %d, got %d", ais_data_len(msg), tmp_size);
 	sane = TRUE;
     }
 
     if(sane && ais_data_len(msg) == 0) {
 	ais_err("Message with no payload");
 	sane = FALSE;
     }
 
     if(sane && data && msg->is_compressed == FALSE) {
 	int str_size = strlen(data) + 1;
 	if(ais_data_len(msg) != str_size) {
 	    int lpc = 0;
 	    ais_err("Message payload is corrupted: expected %d bytes, got %d",
 		    ais_data_len(msg), str_size);
 	    sane = FALSE;
 	    for(lpc = (str_size - 10); lpc < msg->size; lpc++) {
 		if(lpc < 0) {
 		    lpc = 0;
 		}
 		ais_debug_2("bad_data[%d]: %d / '%c'", lpc, data[lpc], data[lpc]);
 	    }
 	}
     }
     
     if(sane == FALSE) {
 	AIS_CHECK(sane,
 		  ais_err("Invalid message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)",
 			  msg->id, ais_dest(&(msg->host)), msg_type2text(dest),
 			  ais_dest(&(msg->sender)), msg_type2text(msg->sender.type),
 			  msg->sender.pid, msg->is_compressed, ais_data_len(msg),
 			  msg->header.size));
 	
     } else if(repaired) {
 	ais_err("Repaired message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)",
 		msg->id, ais_dest(&(msg->host)), msg_type2text(dest),
 		ais_dest(&(msg->sender)), msg_type2text(msg->sender.type),
 		msg->sender.pid, msg->is_compressed, ais_data_len(msg),
 		msg->header.size);
     } else {
 	ais_debug_3("Verified message %d: (dest=%s:%s, from=%s:%s.%d, compressed=%d, size=%d, total=%d)",
 		    msg->id, ais_dest(&(msg->host)), msg_type2text(dest),
 		    ais_dest(&(msg->sender)), msg_type2text(msg->sender.type),
 		    msg->sender.pid, msg->is_compressed, ais_data_len(msg),
 		    msg->header.size);
     }
     return sane;
 }
 
 static int delivered_transient = 0;
 static void deliver_transient_msg(gpointer key, gpointer value, gpointer user_data)
 {
     int pid = GPOINTER_TO_INT(value); 
     AIS_Message *mutable = user_data;
 
     if(pid == mutable->host.type) {
 	int rc = send_client_ipc(key, mutable);
 	delivered_transient++;
 	
 	ais_info("Sent message to %s.%d (rc=%d)",
 		 ais_dest(&(mutable->host)), pid, rc);
 	if(rc != 0) {
 	    ais_warn("Sending message to %s.%d failed (rc=%d)",
 		     ais_dest(&(mutable->host)), pid, rc);
 	    log_ais_message(LOG_DEBUG, mutable);
 	}
     }
 }
 
 gboolean route_ais_message(const AIS_Message *msg, gboolean local_origin) 
 {
     int rc = 0;
     int dest = msg->host.type;
     const char *reason = "unknown";
     AIS_Message *mutable = ais_msg_copy(msg);
     static int service_id =  SERVICE_ID_MAKE(PCMK_SERVICE_ID, 0);
 
     ais_debug_3("Msg[%d] (dest=%s:%s, from=%s:%s.%d, remote=%s, size=%d)",
 		mutable->id, ais_dest(&(mutable->host)), msg_type2text(dest),
 		ais_dest(&(mutable->sender)), msg_type2text(mutable->sender.type),
 		mutable->sender.pid, local_origin?"false":"true", ais_data_len((mutable)));
 
     if(local_origin == FALSE) {
        if(mutable->host.size == 0
 	  || ais_str_eq(local_uname, mutable->host.uname)) {
 	   mutable->host.local = TRUE;
        }
     }
 
     if(check_message_sanity(mutable, mutable->data) == FALSE) {
 	/* Dont send this message to anyone */
 	rc = 1;
 	goto bail;
     }
     
     if(mutable->host.local) {
 	void *conn = NULL;
 	const char *lookup = NULL;
 
 	if(dest == crm_msg_ais) {
 	    process_ais_message(mutable);
 	    goto bail;
 
 	} else if(dest == crm_msg_lrmd) {
 	    /* lrmd messages are routed via the crm */
 	    dest = crm_msg_crmd;
 
 	} else if(dest == crm_msg_te) {
 	    /* te messages are routed via the crm */
 	    dest = crm_msg_crmd;
 
 	} else if(dest >= SIZEOF(pcmk_children)) {
 	    /* Transient client */	    
 
 	    delivered_transient = 0;
 	    g_hash_table_foreach(ipc_client_list, deliver_transient_msg, mutable);
 	    if(delivered_transient) {
 		ais_debug_2("Sent message to %d transient clients: %d", delivered_transient, dest);
 		goto bail;
 
 	    } else {
 		/* try the crmd */
 		ais_debug_2("Sending message to transient client %d via crmd", dest);
 		dest = crm_msg_crmd;		
 	    }
 	    
 	} else if(dest == 0) {
 	    ais_err("Invalid destination: %d", dest);
 	    log_ais_message(LOG_ERR, mutable);
 	    log_printf(LOG_ERR, "%s", get_ais_data(mutable));
 	    rc = 1;
 	    goto bail;
 	}
 	
 	lookup = msg_type2text(dest);
 	conn = pcmk_children[dest].async_conn;
 
 	/* the cluster fails in weird and wonderfully obscure ways when this is not true */
 	AIS_ASSERT(ais_str_eq(lookup, pcmk_children[dest].name));
 
 	if(mutable->header.id == service_id) {
 	    mutable->header.id = 0; /* reset this back to zero for IPC messages */
 
 	} else if(mutable->header.id != 0) {
 	    ais_err("reset header id back to zero from %d", mutable->header.id);
 	    mutable->header.id = 0; /* reset this back to zero for IPC messages */
 	}
 	
 	reason = "ipc delivery failed";
 	rc = send_client_ipc(conn, mutable);
 
     } else if(local_origin) {
 	/* forward to other hosts */
 	ais_debug_3("Forwarding to cluster");
 	reason = "cluster delivery failed";
 	rc = send_cluster_msg_raw(mutable);    
     }
     
     if(rc != 0) {
 	ais_warn("Sending message to %s.%s failed: %s (rc=%d)",
 		 ais_dest(&(mutable->host)), msg_type2text(dest), reason, rc);
 	log_ais_message(LOG_DEBUG, mutable);
     }
     
   bail:
     ais_free(mutable);
     return rc==0?TRUE:FALSE;
 }
 
 int send_cluster_msg_raw(const AIS_Message *ais_msg) 
 {
     int rc = 0;
     struct iovec iovec;
     static uint32_t msg_id = 0;
     AIS_Message *mutable = ais_msg_copy(ais_msg);
 
     AIS_ASSERT(local_nodeid != 0);
     AIS_ASSERT(ais_msg->header.size == (sizeof(AIS_Message) + ais_data_len(ais_msg)));
 
     if(mutable->id == 0) {
 	msg_id++;
 	AIS_CHECK(msg_id != 0 /* detect wrap-around */,
 		  msg_id++; ais_err("Message ID wrapped around"));
 	mutable->id = msg_id;
     }
     
     mutable->header.error = CS_OK;
     mutable->header.id = SERVICE_ID_MAKE(PCMK_SERVICE_ID, 0);	
 
     mutable->sender.id = local_nodeid;
     mutable->sender.size = local_uname_len;
     memset(mutable->sender.uname, 0, MAX_NAME);
     memcpy(mutable->sender.uname, local_uname, mutable->sender.size);
 
     iovec.iov_base = (char *)mutable;
     iovec.iov_len = mutable->header.size;
 
     ais_debug_3("Sending message (size=%u)", (unsigned int)iovec.iov_len);
 #if AIS_COROSYNC
     rc = pcmk_api->totem_mcast(&iovec, 1, TOTEMPG_SAFE);
 #else
     rc = totempg_groups_mcast_joined(openais_group_handle, &iovec, 1, TOTEMPG_SAFE);
 #endif
 
     if(rc == 0 && mutable->is_compressed == FALSE) {
 	ais_debug_2("Message sent: %.80s", mutable->data);
     }
     
     AIS_CHECK(rc == 0, ais_err("Message not sent (%d): %.120s", rc, mutable->data));
 
     ais_free(mutable);
     return rc;	
 }
 
 #define min(x,y) (x)<(y)?(x):(y)
 
 void send_cluster_id(void) 
 {
     int rc = 0;
     int lpc = 0;
     int len = 0;
     struct iovec iovec;
     struct crm_identify_msg_s *msg = NULL;
     
     AIS_ASSERT(local_nodeid != 0);
 
     if(local_born_on == 0 && have_reliable_membership_id) {
 	local_born_on = membership_seq;
     }
     
     ais_malloc0(msg, sizeof(struct crm_identify_msg_s));
     msg->header.size = sizeof(struct crm_identify_msg_s);
 
     msg->id = local_nodeid;
     /* msg->header.error = CS_OK; */
     msg->header.id = SERVICE_ID_MAKE(PCMK_SERVICE_ID, 1);	
 
     len = min(local_uname_len, MAX_NAME-1);
     memset(msg->uname, 0, MAX_NAME);
     memcpy(msg->uname, local_uname, len);
 
     len = min(strlen(VERSION), MAX_NAME-1);
     memset(msg->version, 0, MAX_NAME);
     memcpy(msg->version, VERSION, len);
     
     msg->votes = 1;
     msg->pid = getpid();
     msg->processes = crm_proc_ais;
     msg->born_on = local_born_on;
 
     for (lpc = 0; lpc < SIZEOF(pcmk_children); lpc++) {
 	if(pcmk_children[lpc].pid != 0) {
 	    msg->processes |= pcmk_children[lpc].flag;
 	}
     }
     
     ais_debug("Local update: id=%u, born="U64T", seq="U64T"",
 	      local_nodeid, local_born_on, membership_seq);
     update_member(
 	local_nodeid, local_born_on, membership_seq, msg->votes, msg->processes, NULL, NULL, VERSION);
 
     iovec.iov_base = (char *)msg;
     iovec.iov_len = msg->header.size;
     
 #if AIS_COROSYNC
     rc = pcmk_api->totem_mcast(&iovec, 1, TOTEMPG_SAFE);
 #else
     rc = totempg_groups_mcast_joined(openais_group_handle, &iovec, 1, TOTEMPG_SAFE);
 #endif
 
     AIS_CHECK(rc == 0, ais_err("Message not sent (%d)", rc));
 
     ais_free(msg);
 }
 
 static gboolean
 ghash_send_removal(gpointer key, gpointer value, gpointer data)
 {
     send_quorum_details(value);
     if(send_client_msg(value, crm_class_rmpeer, crm_msg_none, data) != 0) {
 	/* remove it */
 	return TRUE;
     }
     return FALSE;
 }
 
 void ais_remove_peer(char *node_id)
 {
     uint32_t id = ais_get_int(node_id, NULL);    
     crm_node_t *node = g_hash_table_lookup(membership_list, GUINT_TO_POINTER(id));
     if(node == NULL) {
 	ais_info("Peer %u is unknown", id);
 
     } else if(ais_str_eq(CRM_NODE_MEMBER, node->state)) {
 	ais_warn("Peer %u/%s is still active", id, node->uname);
 
     } else if(g_hash_table_remove(membership_list, GUINT_TO_POINTER(id))) {
 	plugin_expected_votes--;
 	ais_notice("Removed dead peer %u from the membership list", id);
 	ais_info("Sending removal of %u to %d children",
 		 id, g_hash_table_size(membership_notify_list));
 	
 	g_hash_table_foreach_remove(membership_notify_list, ghash_send_removal, node_id);
 	
     } else {
 	ais_warn("Peer %u/%s was not removed", id, node->uname);
     }
 }
 
 gboolean process_ais_message(const AIS_Message *msg) 
 {
     int len = ais_data_len(msg);
     char *data = get_ais_data(msg);
     do_ais_log(LOG_DEBUG,
 	       "Msg[%d] (dest=%s:%s, from=%s:%s.%d, remote=%s, size=%d): %.90s",
 	       msg->id, ais_dest(&(msg->host)), msg_type2text(msg->host.type),
 	       ais_dest(&(msg->sender)), msg_type2text(msg->sender.type),
 	       msg->sender.pid,
 	       msg->sender.uname==local_uname?"false":"true",
 	       ais_data_len(msg), data);
 
     if(data && len > 12 && strncmp("remove-peer:", data, 12) == 0) {
 	char *node = data+12;
 	ais_remove_peer(node);
     }
     
     ais_free(data);
     return TRUE;
 }
 
 static void member_dump_fn(gpointer key, gpointer value, gpointer user_data)
 {
     crm_node_t *node = value;
     ais_info(" node id:%u, uname=%s state=%s processes=%.16x born="U64T" seen="U64T" addr=%s version=%s", 
 	     node->id, node->uname?node->uname:"-unknown-",
 	     node->state, node->processes, node->born, node->last_seen,
 	     node->addr?node->addr:"-unknown-", node->version?node->version:"-unknown-");
 }
 
 void pcmk_exec_dump(void) 
 {
     /* Called after SIG_USR2 */
     process_ais_conf();
     ais_info("Local id: %u, uname: %s, born: "U64T, local_nodeid, local_uname, local_born_on);
     ais_info("Membership id: "U64T", quorate: %s, expected: %u, actual: %u",
 	     membership_seq, plugin_has_quorum()?"true":"false",
 	     plugin_expected_votes, plugin_has_votes);
 
     g_hash_table_foreach(membership_list, member_dump_fn, NULL);
 }