#!/bin/sh
#
# Configuration script for Services.

###########################################################################

# Create a temporary directory for our use.

if [ ! -d tmp ] ; then
	if ! mkdir tmp ; then
		res=$?
		echo "Failed to create temporary directory!  Exiting."
		exit $res
	fi
fi
if ! chmod u+rwx tmp ; then
	res=$?
	echo "Cannot write to temporary directory!  Exiting."
	exit $res
fi

###########################################################################

# Variable initialization.

BINDEST=/usr/local/sbin
DATDEST=/usr/local/lib/services

RUNGROUP=
UMASK=

INSTALL=

CC=
CC_FLAGS=bonkle
CC_LIBS=bonkle

HAVE_STRERROR=
HAVE_SYS_ERRLIST=0

HAVE_STRICMP=
HAVE_STRDUP=
HAVE_STRSPN=
HAVE_STRSIGNAL=
MISSING=bonkle

###########################################################################

# How can we echo something without going to the next line?

ECHO2SUF=''
if [ "`echo -n a ; echo b`" = "ab" ] ; then
	ECHO2='echo -n'
elif [ "`echo 'a\c' ; echo 'b'`" = "ab" ] ; then
	ECHO2='echo' ; ECHO2SUF='\c'
elif [ "`printf 'a' 2>&1 ; printf 'b\n' 2>&1`" = "ab" ] ; then
	ECHO2='printf "%s"'
else
	# oh well...
	ECHO2='echo'
fi

###########################################################################

# Command-line parsing.

IGNORE_CACHE= ; USER_CC= ; USER_CC_FLAGS=bonkle ; USER_CC_LFLAGS=
USER_CC_LIBS=
export IGNORE_CACHE USER_CC USER_CC_FLAGS USER_CC_LFLAGS USER_CC_LIBS

while [ $# -gt 0 ] ; do
	if [ "$1" = "-ignore-cache" ] ; then
		IGNORE_CACHE=bonkle
	elif [ "$1" = "-cc" ] ; then
		shift
		USER_CC=$1
	elif [ "$1" = "-cflags" ] ; then
		shift
		USER_CC_FLAGS=$1
	elif [ "$1" = "-lflags" ] ; then
		shift
		USER_CC_LFLAGS=$1
	elif [ "$1" = "-libs" ] ; then
		shift
		USER_CC_LIBS=$1
	else
		if [ "$1" != "-help" ] ; then
			echo >&2 Unknown option/parameter: "$1"
		fi
		cat >&2 <<EOT
Available options:
	-ignore-cache	Don't use cache file if it exists
	-cc		Specify C compiler to use (overrides cache and check)
	-cflags		Specify compilation flags (defaults: -O2 for gcc,
			    -O for other compilers; overrides cache/check)
	-lflags		Specify link flags for C compiler (default: none)
	-libs		Specify extra link libraries to use (default: none)
EOT
		exit 2
	fi
	shift
done

###########################################################################

echo ""
echo "Beginning Services configuration."
echo ""

###########################################################################

# First, test for the presence of a config.cache file.  If found, either
# don't use it (-ignore-cache), or let the user know how to not use it and
# then use it.

if [ -f config.cache -a ! "$IGNORE_CACHE" ] ; then
	cat <<EOT
Using defaults from config.cache.  To ignore, either remove config.cache or
give the command-line option "-ignore-cache".

EOT
	. config.cache
fi

###########################################################################

# Ask the user anything we need to know ahead of time.

export ok INPUT

####

ok=0
while [ $ok -eq 0 ] ; do
	echo "In what directory do you want the binaries to be installed?"
	echo "Press Return for the default, or enter a new value."
	$ECHO2 "[$BINDEST] "$ECHO2SUF
	read INPUT
	if [ ! "$INPUT" ] ; then
		INPUT=$BINDEST
	fi
	if [ ! -d "$INPUT" ] ; then
		if [ -e "$INPUT" ] ; then
			echo "$INPUT exists, but is not a directory!"
		else
			echo "$INPUT does not exist.  Create it?"
			$ECHO2 "[y] "$ECHO2SUF
			read YN
			if [ "$YN" != "n" ] ; then
				if mkdir $INPUT ; then
					ok=1
				fi
			fi
		fi
	else
		ok=1
	fi
done
BINDEST=$INPUT
echo ""

####

ok=0
while [ $ok -eq 0 ] ; do
	echo "Where do you want the data files to be installed?"
	$ECHO2 "[$DATDEST] "$ECHO2SUF
	read INPUT
	if [ ! "$INPUT" ] ; then
		INPUT=$DATDEST
	fi
	if [ ! -d "$INPUT" ] ; then
		if [ -e "$INPUT" ] ; then
			echo "$INPUT exists, but is not a directory!"
		else
			echo "$INPUT does not exist.  Create it?"
			$ECHO2 "[y] "$ECHO2SUF
			read YN
			if [ "$YN" != "n" ] ; then
				if mkdir $INPUT ; then
					ok=1
				fi
			fi
		fi
	else
		ok=1
	fi
done
DATDEST=$INPUT
echo ""

####

OLD_RUNGROUP="$RUNGROUP"
echo "Which group should all Services data files be owned by?  (If Services"
echo "should not force files to be owned by a particular group, just press"
echo "Return.)"
$ECHO2 "[$RUNGROUP] "$ECHO2SUF
read INPUT
if [ "$INPUT" ] ; then
	RUNGROUP=`echo $INPUT`
fi
echo ""

####

if [ ! "$UMASK" -o "$RUNGROUP" != "$OLD_RUNGROUP" ] ; then
	if [ "$RUNGROUP" ] ; then
		UMASK=007
	else
		UMASK=077
	fi
fi

ok=0
while [ $ok -eq 0 ] ; do
	echo "What should the default umask for data files be (in octal)?"
	echo "(077 = only accessible by owner; 007 = accessible by owner and group)"
	$ECHO2 "[$UMASK] "$ECHO2SUF
	read INPUT
	if [ ! "$INPUT" ] ; then
		INPUT=$UMASK
	fi
	if [ `echo $INPUT | grep -c '[^0-7]'` -gt 0 ] ; then
		echo "$UMASK is not a valid octal number!"
	else
		if [ "`echo $INPUT | cut -c1`" != "0" ] ; then
			INPUT=0$INPUT
		fi
		ok=1
	fi
done
UMASK=$INPUT
echo ""

####

echo "End of interactive configuration."
echo ""

###########################################################################

# Search for a compiler.

$ECHO2 "Searching for a suitable compiler... "$ECHO2SUF
if [ "$USER_CC" ] ; then
	CC="$USER_CC"
	echo "(supplied) using $CC."
elif [ "$CC" ] ; then
	echo "(cached) using $CC."
elif gcc --version >/dev/null 2>&1 ; then
	echo "great, found gcc!"
	CC=gcc
	DEF_CC_FLAGS=-O2
else
	echo "gcc not found."
	$ECHO2 "    Looking for alternatives... "$ECHO2SUF
	if cc >/dev/null 2>&1 ; then
		CC=cc
	elif c89 >/dev/null 2>&1 ; then
		CC=c89
	else
		echo "no C compiler found!"
		echo "    Use the -cc command line option to specify your C compiler."
		exit 1
	fi
	# See if it handles ANSI.
	cat >tmp/test.c <<EOT
	int main(int argc, char **argv) {
		extern void foo(int bar);
	}
EOT
	if $CC tmp/test.c -o tmp/test >/dev/null 2>&1 ; then
		echo "using $CC."
	else
		echo "found $CC, but it's not ANSI-compliant!"
		echo "    Use the -cc command line option to specify your C compiler."
		exit 1
	fi
	DEF_CC_FLAGS=-O
fi


# Test compiler options.

if [ "$USER_CC_FLAGS" != bonkle ] ; then
	CC_FLAGS="$USER_CC_FLAGS"
	echo "Compiler flags supplied: $CC_FLAGS"
elif [ "$CC_FLAGS" != bonkle ] ; then
	echo "Compiler flags: (cached) $CC_FLAGS"
else
	CC_FLAGS=$DEF_CC_FLAGS
	$ECHO2 "Testing default compiler flags ($CC_FLAGS)... "$ECHO2SUF
	cat >tmp/test.c <<EOT
	int main(int argc, char **argv) {
		extern void foo(int bar);
	}
EOT
	if $CC $CC_FLAGS tmp/test.c -o tmp/test >/dev/null 2>&1 ; then
		echo "looks good."
	else
		echo "no luck!  Using no flags."
		echo "    If you know what flags you want, use the -cflags option to configure."
		CC_FLAGS=
	fi
fi

###########################################################################

if [ "$USER_CC_LFLAGS" != "bonkle" ] ; then
	CC_LFLAGS=$USER_CC_LFLAGS
fi

# See what libraries we have that we might need.

$ECHO2 "Let's see what libraries are lying around... "$ECHO2SUF
if [ "$CC_LIBS" != bonkle ] ; then
	if [ "$CC_LIBS" ] ; then
		echo "(cached) $CC_LIBS"
	else
		echo "(cached) none"
	fi
else
	CC_LIBS=
	if $CC $CC_FLAGS tmp/test.c -lnsl tmp/test >/dev/null 2>&1 ; then
		CC_LIBS="$CC_LIBS -lnsl"
		$ECHO2 "-lnsl "$ECHO2SUF
	fi
	if $CC $CC_FLAGS tmp/test.c -lsocket tmp/test >/dev/null 2>&1 ; then
		CC_LIBS="$CC_LIBS -lsocket"
		$ECHO2 "-lsocket "$ECHO2SUF
	fi
	if $CC $CC_FLAGS tmp/test.c -lbsd tmp/test >/dev/null 2>&1 ; then
		CC_LIBS="$CC_LIBS -lbsd"
		$ECHO2 "-lbsd "$ECHO2SUF
	fi
	echo ""
fi
if [ "$USER_CC_LIBS" ] ; then
	CC_LIBS="$CC_LIBS $USER_CC_LIBS"
	echo "Additional user-supplied libraries: $USER_CC_LIBS"
fi

###########################################################################

# Look for missing/broken built-in routines, and similar compatibility
# stuff.

$ECHO2 "How to complain when something goes wrong... "$ECHO2SUF
if [ "$HAVE_STRERROR" ] ; then
	if [ "$HAVE_STRERROR" = 1 ] ; then
		echo "(cached) strerror()."
	elif [ "$HAVE_SYS_ERRLIST" = 1 ] ; then
		echo "(cached) sys_errlist."
	else
		HAVE_SYS_ERRLIST=0	# just in case... you never know.
		echo "(cached) pseudo sys_errlist."
	fi
else
	cat >tmp/test.c <<EOT
	int main() {
		extern void strerror(void);
		strerror();
	}
EOT
	if $CC $CC_FLAGS tmp/test.c $CC_LIBS -o tmp/test >/dev/null 2>&1 ; then
		HAVE_STRERROR=1
		echo "ah, strerror() is here."
	else
		echo "no strerror()."
		cat >tmp/test.c <<EOT
int main() {
	extern char *sys_errlist[];
	char *s;
	s = sys_errlist[0];
}
EOT
		if $CC $CC_FLAGS tmp/test.c $CC_LIBS -o tmp/test >/dev/null 2>&1 ; then
			HAVE_SYS_ERRLIST=1
			echo "    But you have sys_errlist, which will do nicely."
		else
			echo "    You don't have sys_errlist either, so we'll have to make do."
		fi
	fi
fi


$ECHO2 "Looking for other routines we need that you don't have... "$ECHO2SUF

if [ "$MISSING" != bonkle ] ; then
	echo "(cached)$MISSING"
else
	MISSING=

	cat >tmp/test.c <<EOT
	int main() {
		extern int stricmp(char *s1, char *s2);
		extern int strnicmp(char *s1, char *s2, int len);
		return stricmp("ABC","abc") == 0 &&
			strnicmp("ABC","abd",2) == 0 ? 0 : 1;
	}
EOT
	if $CC $CC_FLAGS tmp/test.c $CC_LIBS -o tmp/test >/dev/null 2>&1 && tmp/test >/dev/null 2>&1 ; then
		HAVE_STRICMP=1
		HAVE_STRCASECMP=0	# doesn't really matter
	else
		HAVE_STRICMP=0
		cat >tmp/test.c <<EOT
		int main() {
			extern int strcasecmp(char *s1, char *s2);
			extern int strncasecmp(char *s1, char *s2, int len);
			return strcasecmp("ABC","abc") == 0 &&
				strncasecmp("ABC","abd",2) == 0 ? 0 : 1;
		}
EOT
		if $CC $CC_FLAGS tmp/test.c $CC_LIBS -o tmp/test >/dev/null 2>&1 && tmp/test >/dev/null 2>&1 ; then
			HAVE_STRCASECMP=1
		else
			HAVE_STRCASECMP=0
			MISSING="$MISSING str[n]icmp"
			$ECHO2 "str[n]icmp "$ECHO2SUF
		fi
	fi

	cat >tmp/test.c <<EOT
	int main() {
		extern char *strdup(char *s);
		char *s, *t;
		s = "ABC"; t = strdup(s);
		return (t != (char *)0 && strcmp(s, t) == 0) ? 0 : 1;
	}
EOT
	if $CC $CC_FLAGS tmp/test.c $CC_LIBS -o tmp/test >/dev/null 2>&1 && tmp/test >/dev/null 2>&1 ; then
		HAVE_STRDUP=1
	else
		HAVE_STRDUP=0
		MISSING="$MISSING strdup"
		$ECHO2 "strdup "$ECHO2SUF
	fi

	cat >tmp/test.c <<EOT
	int main() {
		extern char *strspn(char *s, char *tok);
		return (strspn("ABCBA", "BA") == 2 && strspn("123", "123") == 3) ? 0 : 1;
	}
EOT
	if $CC $CC_FLAGS tmp/test.c $CC_LIBS -o tmp/test >/dev/null 2>&1 && tmp/test >/dev/null 2>&1 ; then
		HAVE_STRSPN=1
	else
		HAVE_STRSPN=0
		MISSING="$MISSING strspn"
		$ECHO2 "strspn "$ECHO2SUF
	fi

	cat >tmp/test.c <<EOT
	int main() {
		extern void strsignal(void);
		strsignal();
	}
EOT
	if $CC $CC_FLAGS tmp/test.c $CC_LIBS -o tmp/test >/dev/null 2>&1 ; then
		HAVE_STRSIGNAL=1
	else
		HAVE_STRSIGNAL=0
		MISSING="$MISSING strsignal"
		$ECHO2 "strsignal "$ECHO2SUF
	fi

	echo ""
fi

###########################################################################

$ECHO2 "Checking how to install files... "$ECHO2SUF

if [ "$INSTALL" ] ; then
	if [ "`echo $INSTALL | cut -c1`" = "." ] ; then
		echo '(cached) using our own "install".'
	else
		echo '(cached) this system'\''s "install" works.'
	fi
else
	cat >tmp/test.c <<EOT
	int main() { return 0; }
EOT
	if ! $CC $CC_FLAGS tmp/test.c $CC_LIBS -o tmp/test >/dev/null 2>&1 ; then
		echo ""
		echo ""
		echo "*** WHOA THERE! ***"
		echo "We suddenly couldn't compile using the C compiler we already tested!"
		echo "The command line we used was:"
		echo "     $CC $CC_FLAGS tmp/test.c $CC_LIBS -o tmp/test"
		echo "Please try to fix this; if you can't, mail achurch@dragonfire.net"
		echo "with information about your system and the output from this script."
		echo ""
		exit 4
	fi
	if install -c -m 500 tmp/test tmp/test2 >/dev/null 2>&1 && cmp tmp/test tmp/test2 >/dev/null 2>&1 ; then
		echo 'looks like "install" will work.'
		if [ "$RUNGROUP" ] ; then
			INSTALL="install -c -g $RUNGROUP -m 710"
		else
			INSTALL="install -c -m 700"
		fi
	else
		echo \"install\"" doesn't seem to work."
		echo "    But we can still use cp and friends, so we'll roll our own "\"install\".
		if [ "$RUNGROUP" ] ; then
			INSTALL="./install-script -c -g $RUNGROUP -m 710"
		else
			INSTALL="./install-script -c -m 700"
		fi
	fi
fi

###########################################################################

# Create files.

$ECHO2 "Creating sysconf.h... "$ECHO2SUF
cat >sysconf.h <<EOT
/*
 * This file is generated automatically by "configure".  Any changes made
 * to it will be erased next time "configure" is run.
 */

#define SERVICES_DIR		"$DATDEST"

EOT
if [ "$RUNGROUP" ] ; then cat >>sysconf.h <<EOT
#define RUNGROUP		"$RUNGROUP"
EOT
fi
cat >>sysconf.h <<EOT
#define DEFUMASK		$UMASK

#define HAVE_STRERROR		$HAVE_STRERROR
#define HAVE_SYS_ERRLIST	$HAVE_SYS_ERRLIST
#define HAVE_STRICMP		$HAVE_STRICMP
#define HAVE_STRCASECMP		$HAVE_STRCASECMP
#define HAVE_STRDUP		$HAVE_STRDUP
#define HAVE_STRSPN		$HAVE_STRSPN
#define HAVE_STRSIGNAL		$HAVE_STRSIGNAL
EOT
echo "done."

$ECHO2 "Creating Makefile.inc... "$ECHO2SUF
cat >Makefile.inc <<EOT
# This file is generated automatically by "configure".  Any changes made
# to it will be erased next time "configure" is run.

CC=$CC
EXTRA_CFLAGS=$CC_FLAGS
LFLAGS=$CC_LFLAGS
LIBS=$CC_LIBS

BINDEST=$BINDEST
DATDEST=$DATDEST

INSTALL=$INSTALL
RUNGROUP=$RUNGROUP
EOT
echo "done."

###########################################################################

# Save results in cache for next time around.

$ECHO2 "Saving configuration results in config.cache... "$ECHO2SUF

cat <<EOT >config.cache
BINDEST="$BINDEST"
DATDEST="$DATDEST"

INSTALL="$INSTALL"

RUNGROUP="$RUNGROUP"
UMASK=$UMASK

CC="$CC"
CC_FLAGS="$CC_FLAGS"
CC_LFLAGS="$CC_LFLAGS"
CC_LIBS="$CC_LIBS"

HAVE_STRERROR=$HAVE_STRERROR
HAVE_SYS_ERRLIST=$HAVE_SYS_ERRLIST

HAVE_STRICMP=$HAVE_STRICMP
HAVE_STRCASECMP=$HAVE_STRCASECMP
HAVE_STRDUP=$HAVE_STRDUP
HAVE_STRSPN=$HAVE_STRSPN
HAVE_STRSIGNAL=$HAVE_STRSIGNAL
MISSING="$MISSING"
EOT

echo "done."

###########################################################################

echo 'All done!  Now type "make" to compile Services.'
exit 0
