#!/bin/sh
# Purpose: This script should make simplier the compiling of GAEN
# sources, avoiding user to search the right parametters for GCC compiler.
# There are a finite number of parameters/problems which could cause
# compiling crashes, all of them (we hope) being tested below.
# Usage: easy.compile [SourceFile.c] [ -o ] [ OutputFile ]
# If the "-o" parameter is not present then the arguments will be
# parsed in the following order: SourceFile OutputFile. If it is present,
# then the OutputFile will be taken from the next argument.
# Any of those parameters may not be present, as you can see below:
# $ easy.compile
# $ easy.compile -o gaend
# $ easy.compile MyOwnSourceFile.c
# $ easy.compile -o MyOutputFile MyOwnSourceFile.c
# $ easy.compile MyOwnSourceFile.c MyOutputFile
# $ easy.compile --help
# Some modifications are made by Sabin Corneliu Buraga <busaco@infoiasi.ro>:
# - messages' colours changed
# - all temporary "a.out" files are written in "/tmp",
# instead of current directory
# - minor corrections to internal script comments/remarks
# - the "--help" parameter added to show the syntax of this script
# - using of "strip --strip-all" instead of "strip" without parameters
Version="[1m[33m1.3.1 final ([31minternal version 1.1.1[33m), 05 May 2002[0m"
echo;
echo " >>>[32mGAEN[0m [1mEasy Compile[0m Concept script<<<"
echo;
echo ">>>Version "${Version}".";
echo ">>>Author: Victor Tarhon-Onu [1m<mituc@ac.tuiasi.ro>";
echo " (modified by Sabin-Corneliu Buraga [1m<busaco@infoiasi.ro>)[0m";
echo;
if [ $# -eq 1 ]; then
if [ "$1" = "--help" ]; then
echo;
echo "Usage: easy.compile [SourceFile.c] [ -o ] [ OutputFile ]"
echo;
exit 2;
fi
fi
# No cores...
ulimit -c 0;
# Setting up PATH if we are running on nasty configurated systems.
PATH=/usr/bin:/bin:/usr/local/bin:/usr/ucb
# Selecting the best tools for viewing processes and showing text...
# It seems like 'ps' does not have universal options. We'll use
# "-ef" or "-awxu" parameters, depending on ps's requirements.
if [ "`ps -elf 2>&1 1>/dev/null`" = "" ]; then
PS_ARGS="-elf";
else
PS_ARGS="-auxw"
fi;
# Some broken echo's may require this...
SYSV3=""
ECHO_ENUM=`whereis ps | cut -d " " -f 2-`;
for i in $ECHO_ENUM; do
if [ "`echo -n`" = "" ]; then
break;
fi;
done;
# Does out echo support -e option...?
if [ "`echo -e`" = "" ]; then
ECHO="echo -e";
else
ECHO="echo";
fi;
# Initialising default parameters...
LIBS="";
FLAGS="";
DEFAULT_SOURCE_FILE="src/gaen.c";
DEFAULT_OUTPUT_FILE="gaend";
SOURCE_FILE="";
DEFAULT_BASE_FILE="gaen.c";
OUTPUT_FILE="";
# ... and some internal constants and functions.
UNIQUE="$RANDOM";
GAENCompillingScript="/tmp/"$UNIQUE"GAENCompillingScript";
LockFile="/tmp/"$UNIQUE"GAENLockFile";
ErrFile="/tmp/"$UNIQUE"GAENErrFile";
UserName=`whoami`;
# Terminating signals handler function.
make_clean()
{
# Killing the gcc compiling the source file.
for PID in `ps "$PS_ARGS" | grep "$UserName" | grep -v "${0}" | grep -v grep | grep "${BASE_FILE}" | awk {'print $4'}`; do
kill -15 "${PID}" 2>/dev/null 1>/dev/null;
done;
# ...and the cc1's too. cc1 does not have an argument who's name
# is alike with the source's name... So we'll kill'em all :)
for PID in `ps "$PS_ARGS" | grep "$UserName" | grep -v "${0}" | grep -v grep | grep cc1 | awk '{print $4}'`; do
kill -15 "${PID}" 2>/dev/null 1>/dev/null;
done;
# Remove all temporarily created files.
rm -f "${GAENCompillingScript}" "${LockFile}" "${ErrFile}" \
/tmp/gcctest.c /tmp/crypt.c /tmp/socket.c \
/tmp/nsl.c /tmp/opt.c /tmp/a.out 2>/dev/null 1>/dev/null;
echo "[0m";
exit;
}
# This will delete all files made during tests and compiling activity.
trap make_clean 0 1 2 3 15;
# Parsing command line arguments - if any...
FoundOptFlag=0;
for Param in "${@}"; do
if [ "${Param}" = "-o" ]; then
FoundOptFlag=1;
else
if [ "${FoundOptFlag}" = "1" ]; then
OUTPUT_FILE="${Param}";
FoundOptFlag=0;
else
if [ "${SOURCE_FILE}" = "" ]; then
SOURCE_FILE="${Param}";
else
OUTPUT_FILE="${Param}";
fi;
fi;
fi;
done;
# If some params where not found then we'll initialise them default values.
if [ "${SOURCE_FILE}" = "" ]; then
SOURCE_FILE="${DEFAULT_SOURCE_FILE}";
BASE_FILE="${DEFAULT_BASE_FILE}";
else
BASE_FILE=`basename "${SOURCE_FILE}"`;
fi;
# Determine the relative filename of the sourcefile - useful in make_clean();
if [ "${OUTPUT_FILE}" = "" ]; then
OUTPUT_FILE="${DEFAULT_OUTPUT_FILE}";
fi;
# Anyway, if there is no source file, it makes no sense to make the rest
# of the test.
if [ ! -f "${SOURCE_FILE}" ]; then
echo "[47m[5m[31m>>>Fatal error: Cannot open source file \""${SOURCE_FILE}"\" \
for [32mGAEN[5m[31m server.[0m" >&2;
exit 1;
fi;
# We'll do it the same way if gcc is a jerk or just does not exist.
$ECHO ">>>Checking if [1mgcc[0m compiler exists and works... "\\c;
echo "main(){}" > /tmp/gcctest.c;
GCC="";
GCC_ENUM=`whereis gcc | cut -d " " -f 2-; whereis cc | cut -d " " -f 2-`;
for i in $GCC_ENUM; do
if [ "`echo $i | grep obsolete`" != "" -o \
"`echo $i | grep old`" != "" ]; then
continue;
fi;
ERR=`$i /tmp/gcctest.c -o/tmp/a.out 2>&1 1>/dev/null`;
if [ "$ERR" = "" ]; then
GCC="$i";
echo "[1m[32mdone[0m."
break;
fi;
done;
if [ "$GCC" = "" ]; then
echo "[1m[31mfailed.";
echo "[47m[31m[5m>>>Fatal error: It seems like gcc doesn't work ! <:-([0m";
exit 1;
fi;
# The crypt() functions (and other similar functions) are not
# included in libc (or glibc), but in a library named 'libcrypt' which
# contains all the stuff concerning the crypt() functions.
# This happens for glibc packages newer than 5.3, we think.
$ECHO ">>>Searching for [1m[36mcrypt()[0m function in [1m[36mcrypt[0m library... "\\c;
cat > /tmp/crypt.c <<EOF
#include <unistd.h>
main (void) /* test file created by GAEN easy compile script */
{
crypt (NULL, NULL);
return 0;
}
EOF
ERR=`$GCC /tmp/crypt.c -lcrypt -o/tmp/a.out 2>&1 1>/dev/null | grep "crypt"`;
if [ "${ERR}" = "" ]; then
LIBS="-lcrypt";
echo "[1m[32mfound[0m.";
else
echo "[1m[31mnot found[0m.";
fi;
# For some versions of GNU GCC - those coming with Solaris, some of the
# functions concerning the networking part are all included in a stand-alone
# library named 'libsocket'.
$ECHO ">>>Searching for [1mBSD[0m socket functions in [1m[36msocket[0m library... "\\c;
cat > /tmp/socket.c <<EOF
#include <sys/socket.h>
main (void) /* test file created by GAEN easy compile script */
{
return socket (AF_INET, SOCK_STREAM, 0);
}
EOF
ERR=`$GCC /tmp/socket.c -lsocket -o/tmp/a.out 2>&1 1>/dev/null | grep "socket"`;
if [ "${ERR}" = "" ]; then
LIBS="-lsocket "${LIBS}"";
echo "[1m[32mfound[0m.";
else
echo "[1m[31mnot found[0m.";
fi;
# ...and the rest of them (e.g. DNS manipulation routines) in 'libnsl'.
$ECHO ">>>Searching for other [1m[36msocket/DNS[0m functions in [1m[36mnsl[0m library... "\\c;
cat > /tmp/nsl.c <<EOF
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
main (void) /* test file created by GAEN easy compile script */
{
return socket (AF_INET, SOCK_STREAM, 0);
}
EOF
ERR=`$GCC /tmp/nsl.c -lnsl -o/tmp/a.out 2>&1 1>/dev/null`;
if [ "${ERR}" = "" ]; then
LIBS="-lnsl "${LIBS}"";
echo "[1m[32mfound[0m.";
else
echo "[1m[31mnot found[0m.";
fi;
# Older/particular versions of GCC don't know how to optimize code when
# we demand it or just usually... Maybe newer versions of GCC having this
# problem but we just didn't heared about any...
$ECHO ">>>Checking if [1mgcc[0m can generate optimized code... "\\c;
cat >/tmp/opt.c <<EOF
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
main (void) /* test file created by GAEN easy compile script */
{
(void) fprintf(stderr, "We really have to write something here?:)\n");
socket (AF_INET, SOCK_STREAM, 0);
crypt (NULL, NULL);
return 0;
}
EOF
ERR=`$GCC /tmp/opt.c $LIBS -O -o/tmp/a.out 2>&1`;
if [ "$ERR" = "" ]; then
FLAGS="-O";
echo "[1m[32mok[0m.";
CAN_OPTIMIZE="1";
else
echo "[1m[34mcannot[0m.";
fi;
# We obtained the smallest, the fastest and the most stable code we've got
# under various versions of Linux compiling with "-O2" ("-O3" option
# makes the ELF bigger). We suppose (hope) that's common to most of UNIX/GCC
# versions. We're thinking about OS's libraries... but at least GCC generates
# the code, not the OS. So, this should be common to most of GCC versions.
if [ "$CAN_OPTIMIZE" = "1" ]; then
$ECHO ">>>Forcing [1mgcc[0m to a higher optimization level... "\\c;
ERR=`$GCC /tmp/opt.c $LIBS -O2 -o/tmp/a.out 2>&1 1>/dev/null | grep "O"`;
if [ "${ERR}" = "" ]; then
FLAGS=""${FLAGS}"2";
echo "[1m[32msuccess[0m.";
else
echo "[1m[34mcannot[0m.";
fi;
fi;
# We just want to be sure the file does not exist. It may happen to exist
# sometimes... if you interrupted this script before it finishes its work.
# In this case, if the name of the lock file is the same or nor depends on
# the way the OS generates random numbers (via shell)... or if it really
# does this... Anyway, it's more safe if we removed it before.
rm -f "${LockFile}" 2>/dev/null 1>/dev/null;
# Here it will be generated a script based on the information already
# obtained. The idea is to run it in a subshell, so it'll be easier to
# supervise.
cat >"${GAENCompillingScript}" <<EOF
#!/bin/sh
$GCC $SOURCE_FILE -o $OUTPUT_FILE $FLAGS $LIBS $NO_SUPPORT 2>>$ErrFile\\
&& strip --strip-all $OUTPUT_FILE 2>>$ErrFile
touch $LockFile 2>>$ErrFile
EOF
$ECHO ">>>Compiling [32mGAEN[0m server \"[1m"${OUTPUT_FILE}"[0m\" from file \"[1m"${SOURCE_FILE}"[0m\"..."\\c;
# Running the script in background...
. ${GAENCompillingScript} &
# Some poor visual effects using the lock file...
Time="-1";
dash="";
printf "%s" "[1m[34m";
while [ ! -f "${LockFile}" ]; do
Time=`expr $Time + 1`;
dash=`expr $Time % 4`;
case "$dash" in
"0")
printf "%s\b" "-";
;;
"1")
printf "%s\b" "\\";
;;
"2")
printf "%s\b" "|";
;;
"3")
printf "%s\b" "/";
;;
esac;
sleep 1;
done;
# Showing some info about the compiling time and about any errors...
# which may be occured.
if [ -s "${ErrFile}" ]; then
$ECHO \\b"[1m[31mfailed.";
echo "[0m>>>[1m[34mDone in "$Time" seconds with [1m[31mthe following error(s):";
echo "[33m********************************************************[31m";
less "${ErrFile}" 1>&2;
echo "[33m********************************************************";
else
$ECHO \\b"[1m[34mdone.";
echo "[0m>>>[1m[34mDone in "$Time" seconds with [1m[32msuccess.";
fi;
$ECHO \\b"[0m";
# Chatting is beautiful !:) That's COOL !!!:)))