#!/bin/sh

#
# (c) Copyright 1992, 1993 by Panagiotis Tsirigotis
#

#
# $Id: compile-src,v 1.14 1995/07/05 16:30:45 chuck Exp $
#

script_name=`basename $0`

if test "$script_name" != "$0" -a "./$script_name" != "$0" ; then
   echo This script must be executed from the top level directory 
   exit 1
fi

XPWD=`pwd`

#
# The order with which the libraries are listed is important.
# It is also a problem; to understand why consider this:
#		Library A depends (uses some functions from) library B
#		Then, B must be compiled and installed before A so that
#		A can find B's include files at the standard place.
#		But when linking the program with A and B, if B precedes A
#		then none of B's code will be included since nobody has yet
#		tried to use it (since has not been encountered yet).
#
# Our solution is to list the libraries in the order they are compiled
# and while compiling them also generate the reverse list which is the
# order they have to be linked.
#
mandatory_libs="misc sio pset xlog str"
optional_libs="pq timer"

catch_sigs="2 15"
inc=/usr/include

#
# The value of ccopt is used for setting the DEBUG makefile variable.
# Therefore, it can be used to either enable debugging support (i.e. -g),
# profiling support (i.e. -pg), or optimization support (i.e. -O)
# The default is optimization.
#
ccopt=-O

while test $# -gt 0
do
	option=$1 ; shift
	case $option in
		-libc)
				if test $# -eq 0 ; then
					echo "Argument missing. Exiting..."
					exit 1
				fi
				libc=$1
				shift
				if test ! -r $libc ; then
					echo "File is not readable: $libc"
					exit 1
				fi
				;;

		-signals)
				if test $# -eq 0 ; then
					echo "Argument missing. Exiting..."
					exit 1
				fi
				signal_handling=$1
				shift
				;;

		-ccopt)
				if test $# -eq 0 ; then
					echo "Argument missing. Exiting..."
					exit 1
				fi
				ccopt=$1
				shift
				;;

		-os)
				if test $# -eq 0 ; then
					echo "Argument missing. Exiting..."
					exit 1
				fi
				osversion=$1 ;
				shift
				;;
		
		-auto)
				autoconfig=yes
				;;

		-sf|-cf)
				if test $# -eq 0 ; then
					echo "Missing argument to $option. Exiting..."
					exit 1
				fi
					
				if test "$option" = "-sf" ; then
					v=yes
				else
					v=no
				fi

				specified_flags=yes
				flag=$1
				shift

				#
				# The first 2 lines are for xinetd.
				# The 3rd line has to do with the man pages (xinetd and libraries)
				# The rest of the lines are for the libraries
				#
				case "$flag" in
					old_wait|no_rpc|no_termios|no_posix_types)	eval $flag=$v ;;
					no_siglist)												eval $flag=$v ;;
					has_SB)													eval $flag=$v ;;
					old_dir|no_ftw|no_timers|no_syslog)				eval $flag=$v ;;
					has_mmap|has_memops|has_bcopy)      			eval $flag=$v ;;
					has_isatty|has_bsdtty|has_sysvtty)  			eval $flag=$v ;;
					has_onexit|has_atexit)              			eval $flag=$v ;;
					*)	echo "Bad flag name: $flag. Exiting..." ; exit 1
				esac
				;;

		-custom)
				custom=yes
				;;

		-verbose)
				verbose=yes
				;;
		-clean)
				for makes in $mandatory_libs $optional_libs
				do
					cd $XPWD/libs/src/$makes
					make clean
				done
				cd $XPWD/libs/lib
				/bin/rm -f *.a
				cd $XPWD/xinetd
				make clean
				exit 0
				;;
		#
		# THIS IS THE SCRIPT DOCUMENTATION
		#
		-help)
			echo "Usage: $script_name [options]"
			echo "Options:"
			echo "   -libc pathname : specifies the location of the C library"
			echo "   -signals type  : type of signal handling"
			echo "   -os osname     : specifies the OS name and version"
			echo "   -auto          : automatic configuration"
			echo "   -verbose       : display info about configuration"
			echo "   -custom        : there is a custom xinetd configuration file"
			echo "   -ccopt option  : option should be either -g for debugging"
			echo "                    or -O for optimization"
			echo "   -clean         : makes all clean"
			echo "Possible arguments to -signals:"
			echo "         posix, bsd, simple"
			echo "Possible arguments to -os:"
			echo "        sunos4, ultrix4, bsdi1, bsdi2, freebsd2, linux"
			echo "The -sf and -cf options set or clear flags that specify"
			echo "what facilities are available from the operating system"
			echo "Only one flag can be specified per -sf/-cf but these options"
			echo "can be used multiple times."
			echo "Available flags:"
         echo "   no_timers      : BSD-type timers are not available"
         echo "   no_rpc         : system does not support RPC"
         echo "   no_termios     : termios(3) is not available"
         echo "   no_siglist     : sys_siglist(3) is not available"
         echo "   no_ftw         : ftw(3) is not available"
         echo "   no_syslog      : syslog(3) is not available"
         echo "   no_posix_types : POSIX types are not available"
         echo "   has_isatty     : isatty(3) is available"
         echo "   has_bsdtty     : system has BSD-type tty interface"
         echo "   has_sysvtty    : system has SysV-type tty interface"
         echo "   has_mmap       : mmap(2) is available"
         echo "   has_memops     : memops(3) functions are available"
         echo "   has_bcopy      : bcopy(3) is available"
         echo "   has_onexit     : onexit(3) is available"
         echo "   has_atexit     : atexit(3) is available"
         echo "   old_wait       : wait(2) expects a 'union wait' argument"
         echo "   old_dir        : old directory(3) package"
         echo "   has_SB         : system supports .SB in man pages"
         echo
			echo "You can use the -os option to specify an operating system"
			echo "and then you can use -sf/-cf for further mods."
			exit 2
			;;

		*) echo "Bad argument: $1. Exiting..." ; exit 1
	esac
done

if test "$autoconfig" != "" -a "$osversion" != "" ; then
	echo "Only one of -auto, -os can be specified"
	exit 1
fi

if test ! "$osversion" -a ! "$autoconfig" ; then
	echo "I need to know the operating system you are using and the version."
	echo "I know about"
	echo "   SunOS 4.x     (sunos4)"
	echo "   Ultrix 4.x   (ultrix4)"
	echo "   BSDI 1.x       (bsdi1)"
	echo "   BSDI 2.x       (bsdi2)"
	echo "   FreeBSD 2.x (freebsd2)"
	echo "   Linux 1.x      (linux)"
	echo "If your OS is among these, use the name in the parentheses, otherwise"
	echo "just hit <return> and I will try to figure out how to properly"
	echo -n "configure xinetd for your system --> "
	read osversion
fi

#
# This if statement checks if we have a known osversion.
# If we don't, we set the autoconfig flag.
#
if test "$osversion" ; then
	case $osversion in
		sunos4|ultrix4)
			autoconfig= 
			signal_handling=bsd
			;;
		bsdi1|bsdi2|freebsd2|linux)
			autoconfig=
			signal_handling=posix
			;;
		*) echo "I don't know anything about this OS. Exiting..." ; exit 1
	esac
else
	autoconfig=yes
fi

#
# Get namelist of C library
#
if test "$autoconfig" ; then
	echo "Obtaining name list of C library"

	if test ! "$libc" ; then
		if test -r /lib/libc.a ; then
			libc=/lib/libc.a
		else
			if test -r /usr/lib/libc.a ; then
				libc=/usr/lib/libc.a
			else
				echo -n "Please give me the pathname of the C library -> "
				read libc
				if test ! "$libc" -o ! -r "$libc" ; then
					echo "Bad pathname. Exiting..."
					exit 1
				fi
			fi
		fi
	fi
	nmfile=/tmp/libc.nm.$$
	nm $libc > $nmfile 2>/dev/null
	if test $? -ne 0 ; then
		if test ! -s $nmfile ; then
			echo "Couldn't get the namelist of C library. Exiting..."
			rm -f $nmfile
			exit 1
		else		# name list file is not empty
			echo "WARNING: The 'nm' command returned a non-zero exit status"
			echo "WARNING: so the namelist obtained from the C library may be incomplete"
			echo "Continuing with auto-configuration"
		fi
	fi
fi

if test "$specified_flags" -o "$autoconfig" ; then
	lib_defs=
	xinetd_defs=

	#
	# Determine supported signal handing
	#
	if test "$autoconfig" -a ! "$signal_handling" ; then
		if test "$verbose" ; then echo "Looking for sigaction" ; fi
		found=`grep sigaction $nmfile | grep T`
		if test "$found" ; then
			signal_handling=posix
		else
			if test "$verbose" ; then echo "Looking for sigvec" ; fi
			found=`grep sigvec $nmfile | grep T`
			if test "$found" ; then 
				signal_handling=bsd
			else
				signal_handling=simple
			fi
		fi
	fi

	case "$signal_handling" in
		posix)	v= ;;
		bsd)		v="-DNO_POSIX_SIGS" ;;
		simple)	v="-DNO_POSIX_SIGS -DNO_SIGVEC" ;;
	esac
	xinetd_defs="$xinetd_defs $v"

	#
	# Check for setitimer(2)
	#
	case "$no_timers" in
		yes)	v=-DNO_TIMERS ;;
		no)	v= ;;
		*)
				if test "$autoconfig" ; then
					if test "$verbose" ; then echo "Looking for setitimer" ; fi
					found=`grep setitimer $nmfile | grep T`
					if test ! "$found" ; then v=-DNO_TIMERS ; else v= ; fi
				else
					v=
				fi
	esac
	xinetd_defs="$xinetd_defs $v"

	#
	# Check for sys_siglist
	#
	case "$no_siglist" in
		yes)	v=-DNO_SIGLIST ;;
		no)	v= ;;
		*)
				if test "$autoconfig" ; then
					if test "$verbose" ; then echo "Looking for sys_siglist" ; fi
					found=`grep sys_siglist $nmfile | grep D`
					if test ! "$found" ; then v=-DNO_SIGLIST ; else v= ; fi
				else
					v=
				fi
	esac
	xinetd_defs="$xinetd_defs $v"

	#
	# Check for RPC
	#
	case "$no_rpc" in
		yes)	v=-DNO_RPC ;;
		no)	v= ;;
		*)
				if test "$autoconfig" ; then
					if test "$verbose" ; then echo "Looking for RPC" ; fi
					found=`grep rpcent $inc/netdb.h`
					if test ! "$found" ; then v=-DNO_RPC ; else v= ; fi
				else
					v=
				fi
	esac
	xinetd_defs="$xinetd_defs $v"

	#
	# Check if this system supports the old wait
	#
	case "$old_wait" in
		yes)	v=-DOLD_WAIT ;;
		no)	v= ;;
		*)
			if test "$autoconfig" ; then
				if test "$verbose" ; then echo "Looking for WEXITSTATUS" ; fi
				found=`grep WEXITSTATUS $inc/sys/wait.h`
				if test ! "$found" ; then v=-DOLD_WAIT ; else v= ; fi
			else
				v=
			fi
	esac
	xinetd_defs="$xinetd_defs $v"

	#
	# Check for pid_t
	# 
	case "$no_posix_types" in
		yes)	v=-DNO_POSIX_TYPES ;;
		no)	v= ;;
		*)
			if test "$autoconfig" ; then
				if test "$verbose" ; then echo "Looking for pid_t" ; fi
				found=`cd $inc/sys ; grep pid_t *.h | grep typedef`
				if test ! "$found" ; then v=-DNO_POSIX_TYPES ; else v= ; fi
			else
				v=
			fi
	esac
	xinetd_defs="$xinetd_defs $v"

	#
	# Check for termios
	#
	case "$no_termios" in
		yes)	v=-DNO_TERMIOS ;;
		no)	v= ;;
		*)
			if test "$autoconfig" ; then
				if test -r $inc/sys/termios.h -o -r $inc/termios.h ; then
					v=
				else
					v=-DNO_TERMIOS
				fi
			else
				v=
			fi
	esac
	xinetd_defs="$xinetd_defs $v"

	#
	# Check for new directory types
	#
	case "$old_dir" in
		yes)	v=-DOLD_DIR ;;
		no)	v= ;;
		*)
				if test "$autoconfig" ; then
					if test -r $inc/dirent.h ; then
						v=
					else
						v=-DOLD_DIR
					fi
				else
					v=
				fi
	esac
	lib_defs="$lib_defs $v"

	#
	# Check for ftw(3)
	#
	case "$no_ftw" in
		yes)	v=-D__FTWX_NO_FTW ;;
		no)	v= ;;
		*)
				if test "$autoconfig" ; then
					if test -r $inc/ftw.h ; then 
						v=
					else
						v=-D__FTWX_NO_FTW
					fi
				else
					v=
				fi
	esac
	lib_defs="$lib_defs $v"

	#
	# Check for syslog(3)
	#
	case "$no_syslog" in
		yes)	v=-DNO_SYSLOG ;;
		no)	v= ;;
		*)
				if test "$autoconfig" ; then
					if test "$verbose" ; then echo "Looking for syslog" ; fi
					found=`grep syslog $nmfile | grep T`
					if test ! "$found" ; then v=-DNO_SYSLOG ; else v= ; fi
				else
					v=
				fi
	esac
	lib_defs="$lib_defs $v"

	#
	# Check for mmap. Since it is not required, we do not try to find
	# if the system supports it.
	#
	case "$has_mmap" in
		yes)  v=-DHAS_MMAP ;;
		*)    v= ;;
	esac
	lib_defs="$lib_defs $v"

   case "$has_onexit" in
      yes)  v=-DHAS_ONEXIT ;;
      no)   v= ;;
      *)
            if test "$autoconfig" ; then
               if test "$verbose" ; then echo "Looking for on_exit" ; fi
               found=`grep on_exit $nmfile | grep T`
               if test "$found" ; then v=-DHAS_ONEXIT ; else v= ; fi
            else
               v=
            fi
   esac
   lib_defs="$lib_defs $v"

   case "$has_atexit" in
      yes)  v=-DHAS_ATEXIT ;;
      no)   v= ;;
      *)
            if test "$autoconfig" ; then
               if test "$verbose" ; then echo "Looking for atexit" ; fi
               found=`grep atexit $nmfile | grep T`
               if test "$found" ; then v=-DHAS_ATEXIT ; else v= ; fi
            else
               v=
            fi
   esac
   lib_defs="$lib_defs $v"

   case "$has_memops" in
      yes)  v=-DHAS_MEMOPS ;;
      no)   v= ;;
      *)
            if test "$autoconfig" ; then
               if test "$verbose" ; then echo "Looking for memcpy" ; fi
               found=`grep memcpy $nmfile | grep T`
               if test "$found" ; then v=-DHAS_MEMOPS ; else v= ; fi
            else
               v=
            fi
   esac
   lib_defs="$lib_defs $v"

   case "$has_bcopy" in
      yes)  v=-DHAS_BCOPY ;;
      no)   v= ;;
      *)
            if test "$autoconfig" ; then
               if test "$verbose" ; then echo "Looking for bcopy" ; fi
               found=`grep bcopy $nmfile | grep T`
               if test "$found" ; then v=-DHAS_BCOPY ; else v= ; fi
            else
               v=
            fi
   esac
   lib_defs="$lib_defs $v"

   case "$has_isatty" in
      yes)  v=-DHAS_ISATTY ;;
      no)   v= ;;
      *)
            if test "$autoconfig" ; then
               if test "$verbose" ; then echo "Looking for isatty" ; fi
               found=`grep bcopy $nmfile | grep T`
               if test "$found" ; then v=-DHAS_ISATTY ; else v= ; fi
            else
               v=
            fi
   esac
   #
   # Since SIO cannot compile without the isatty function, if isatty is not
   # in the C library, we have to provide our own. For this, we need to know
   # if the system supports BSD or SysV tty handling.
   #
   if test ! "$osversion" -a ! "$v" ; then
      while test ! "$v"
      do
         echo "Is your OS based on System V or on BSD 4.x ? I am really"
         echo -n "interested in terminal handling. You can say sysv or bsd -->"
         read ans
         case $ans in
            sysv) v=-DHAS_SYSVTTY ;;
            bsd)  v=-DHAS_BSDTTY ;;
            *) echo "Please say either 'sysv' or 'bsd'"
         esac
      done
   fi
   lib_defs="$lib_defs $v"
fi

if test "$autoconfig" ; then
	rm -f $nmfile
fi

#
# If we know the OS, we can provide the appropriate flags for SIO
#
case "$osversion" in
   sunos4)  sio_defs="-DHAS_MMAP -DHAS_ONEXIT -DHAS_MEMOPS -DHAS_ISATTY"
	    cp $XPWD/libs/src/misc/Makefile-2.1.4 $XPWD/libs/src/misc/Makefile
	    cp $XPWD/xinetd/Makefile-2.1.4 $XPWD/xinetd/Makefile
            ;;
   ultrix4) sio_defs="-DHAS_MEMOPS -DHAS_ATEXIT -DHAS_ISATTY"
	    cp $XPWD/libs/src/misc/Makefile-2.1.4 $XPWD/libs/src/misc/Makefile
	    cp $XPWD/xinetd/Makefile-2.1.4 $XPWD/xinetd/Makefile
            ;;
   bsdi1)   sio_defs="-D__FTWX_NO_FTW -DHAS_MMAP -DHAS_ATEXIT -DHAS_BCOPY -DHAS_ISATTY -DBSDI"
	    lib_defs="$sio_defs"
       xinetd_defs="-DNO_TERMIOS -DBSDI"
	    cp $XPWD/libs/src/misc/Makefile-2.1.4 $XPWD/libs/src/misc/Makefile
	    cp $XPWD/xinetd/Makefile.bsdi $XPWD/xinetd/Makefile
		 CC=cc; export CC
            ;;
   bsdi2)   sio_defs="-D__FTWX_NO_FTW -DHAS_MMAP -DHAS_ATEXIT -DHAS_BCOPY -DHAS_ISATTY -DBSDI -DBSDI2"
	    lib_defs="$sio_defs"
       xinetd_defs="-DBSDI -DBSDI2"
	    cp $XPWD/libs/src/misc/Makefile-2.1.4 $XPWD/libs/src/misc/Makefile
	    cp $XPWD/xinetd/Makefile.bsdi $XPWD/xinetd/Makefile
		 CC=shlicc2; export CC
            ;;
   freebsd2)   sio_defs="-D__FTWX_NO_FTW -DHAS_MMAP -DHAS_ATEXIT -DHAS_BCOPY -DHAS_ISATTY -DBSDI -DFREEBSD"
	    lib_defs="$sio_defs"
       xinetd_defs="-DBSDI -DFREEBSD"
#	We do this differently for FreeBSD to add ecvt(), fcvt(), and gcvt()
	    cp $XPWD/libs/src/misc/Makefile.freebsd $XPWD/libs/src/misc/Makefile
	    cp $XPWD/xinetd/Makefile.freebsd $XPWD/xinetd/Makefile
            ;;
   linux)   sio_defs="-D__FTWX_NO_FTW -DHAS_MMAP -DHAS_ATEXIT -DHAS_BCOPY -DHAS_ISATTY -DLINUX"
	    lib_defs="$sio_defs"
       xinetd_defs="-DLINUX"
	    cp $XPWD/libs/src/misc/Makefile-2.1.4 $XPWD/libs/src/misc/Makefile
	    cp $XPWD/xinetd/Makefile.linux $XPWD/xinetd/Makefile
            ;;
   *)       sio_defs="$lib_defs"
esac

case "$no_timers" in
	yes) lib_names="$mandatory_libs" ;;
	*)
		case "$signal_handling" in
			posix)	lib_names="$mandatory_libs $optional_libs" ;;
			bsd)		lib_names="$mandatory_libs $optional_libs"
						lib_defs="$lib_defs -DNO_POSIX_SIGS"
						;;
			*)			lib_names="$mandatory_libs"
		esac
esac

incdir=$XPWD/libs/include
mandir=$XPWD/libs/man
libdir=$XPWD/libs/lib

#
# Only Suns undestand .SB in man pages, so if we are not dealing with
# a Sun we replace .SB with .B
#
if test "$osversion" = "sunos4" ; then
	modify_manpages=
else
	case "$has_SB" in
		yes) modify_manpages= ;;
		no)  modify_manpages=yes ;;
		*)
		echo -n "Can your machine handle .SB in a man page ? (if you are not sure, say no) -->"
		read x
		if test "$x" = "n" -o "$x" = "no" ; then
			modify_manpages=yes
		else
			modify_manpages=
		fi
	esac
fi

if test "$modify_manpages" ; then
	#
	# We can't take any interrupts while processing the manpages
	#
	trap 'interrupt_occured=yes' $catch_sigs

	echo "Replacing .SB in library man pages with .B (if a man page is changed"
	echo "the original will be kept by appending .orig to its name)"
	for i in $lib_names
	do
		cd $XPWD/libs/src/$i
		for i in *.3
		do
			mv $i $i.orig											# save the original
			sed 's/[.]SB/.B/' $i.orig > $i					# do the replacement
			cmp -s $i $i.orig										# are they the same ?
			if test $? -eq 0 ; then rm $i.orig ; fi		# if yes, remove the copy
		done
		if test "$interrupt_occured" = "yes" ; then
			echo "Interrupt: quiting"
			exit 1
		fi
	done

	trap $catch_sigs		# no more trapping
fi

#
# Make the libraries
# Also prepare the value of the LIBS variable in the xinetd Makefile
#
mvars="DEBUG=$ccopt MANDIR=$mandir INCLUDEDIR=$incdir LIBDIR=$libdir"
for i in $lib_names
do
	libs="-l$i $libs"
	cd $XPWD/libs/src/$i
	echo Making library: $i
	#
	# Remove the archive if it is already there; this is to avoid ld complaints
	# that the table of contents is out of date.
	#
	rm -f lib$i.a
	if test "$i" = "sio" ; then
		make $mvars DEFS="$sio_defs" install
	else
		make $mvars DEFS="$lib_defs" install
	fi
	if test $? -ne 0 ; then
		echo "Failed to create library: $i"
		exit 2
	fi
done

#
# Now make xinetd
# We remove the xinetd executable, if there is one, in case the libraries
# have changed
#
cd $XPWD/xinetd
rm -f xinetd
mvars="DEBUG=$ccopt INCLUDEDIR=-I$incdir LDFLAGS=-L$libdir"
if test "$custom" ; then xinetd_defs="$xinetd_defs -DCUSTOMCONF" ; fi

case "$osversion" in
	bsdi1|bsdi2)
		make "DEFS=$xinetd_defs" "LIBS=$libs -lrpc -lcompat" $mvars
		;;
	freebsd2)
		make "DEFS=$xinetd_defs" "LIBS=$libs -lrpcsvc -lcrypt -lcompat -lm" $mvars
		;;
	linux)
		make "DEFS=$xinetd_defs" "LIBS=$libs" $mvars
		;;
	*)
		make "DEFS=$xinetd_defs" "LIBS=$libs -lcompat" $mvars
esac

if test $? -ne 0 ; then
	echo Failed to create xinetd
	exit 2
fi

if test "$modify_manpages" ; then

	trap 'interrupt_occured=yes' $catch_sigs

	echo "Replacing .SB in xinetd man pages with .B"
	for i in *.man
	do
		mv $i $i.orig
		sed 's/[.]SB/.B/' $i.orig > $i
		cmp -s $i $i.orig										# are they the same ?
		if test $? -eq 0 ; then rm $i.orig ; fi		# if yes, remove the copy

		if test "$interrupt_occured" = "yes" ; then
			echo "Interrupt: quiting"
			exit 1
		fi
	done
	trap $catch_sigs		# no more trapping
fi

