#! /bin/sh
:
if test -z "$IFS"
then IFS=" \
\
"
export IFS
fi
SHELL=$1
PATH=.:$PATH
shift; RM="$1"
shift; MV="$1"
shift; DEVNULL=$1
shift; FGREP="$1"
shift; MAKE="$1"
shift; O=$1
shift; LOCKINGTEST="$1"
shift; BINDIR=$1
shift; ACONF=$1
test 1 != $ echo "Don't start this script directly, use \`make ../autoconf.h'" && exit 1
if test -f make_n
then
$RM make_n
else
exit 0
fi
export SHELL PATH
test "X$LOCKINGTEST" = X__defaults__ && LOCKINGTEST=""
OLDTESTDIRS=""
tailpid=""
echo "" >_locktst.pid
if test -f $ACONF
then
if $FGREP -e "/* autoconf completed */" $ACONF >$DEVNULL
then
cat <<HERE
==============================================================================
Would you like to skip running autoconf and use the existing autoconf.h file?
When in doubt, press return [n]:
HERE
read a
case "$a"n in
[yY]*) touch $ACONF; exit 0;;
esac
fi
trap "kill \`cat _locktst.pid\` 2>$DEVNULL;cp $ACONF $ACONF.tmp
test ! -z \"\$OLDTESTDIRS\" && $RM -r \$OLDTESTDIRS \$OLDTESTDIRS 2>$DEVNULL
test ! -z \"\$tailpid\" && kill \$tailpid 2>$DEVNULL
kill \`cat _locktst.pid\` 2>$DEVNULL; exit 1" 1 2 3 13 15
else
trap "kill \`cat _locktst.pid\` 2>$DEVNULL;$RM -r $ACONF.tmp
test ! -z \"\$OLDTESTDIRS\" && $RM -r \$OLDTESTDIRS \$OLDTESTDIRS 2>$DEVNULL
mv $ACONF $ACONF.tmp 2>$DEVNULL
test ! -z \"\$tailpid\" && kill \$tailpid 2>$DEVNULL
kill \`cat _locktst.pid\` 2>$DEVNULL; exit 1" 1 2 3 13 15
fi
nocore=yes
set dummy *core*
test -f $2 && nocore=no
set dummy $LOCKINGTEST
shift
LOCKINGTEST="$*"
test ! -z "$LOCKINGTEST" && exec 9>&1 1>$DEVNULL
cat <<HERE
==============================================================================
In order for the kernel-locking tests to work as intended I have to be able to
test-lock files on as many semantically different filesystems as possible (for
more information about this, READ PARAGRAPH TWO in INSTALL). To suppress this
prompt you can set the LOCKINGTEST variable in the Makefile.
Please add writable directories to the list. You should only add directories
that reside on filesystems that have unique characteristics. E.g. if you have
several remote NFS partitions, pick some unique client-server pairs, there is
little use in picking the same server twice from the same client-machine.
An excellent candidate would be a remotely mounted mail spool directory.
==============================================================================
HERE
testdirs="/tmp ."
case "$LOCKINGTEST" in
""|*[a-zA-Z/]*) b=dummy ;;
*) b=""; testdirs=$LOCKINGTEST; LOCKINGTEST=dummy ;;
esac
while test ! -z "$b"
do
echo ""
b=""
OLDTESTDIRS="$TESTDIRS"
TESTDIRS=""
for a in $testdirs
do $RM -r $a/_locktest
if mkdir $a/_locktest 2>$DEVNULL
then
b="$b $a"
TESTDIRS="$TESTDIRS $a/_locktest"
else
echo 2>&1 "Can't create $a/_locktest"
fi
done
OLDTESTDIRS="$TESTDIRS"
testdirs="$b"
echo ""
echo "I will temporarily use a testdirectory named _locktest"
echo "in the following directories:"
echo ""
echo $testdirs
echo ""
echo "If you would like to add any, please specify them below,"
echo "press return to continue:"
echo ""
if test -z "$LOCKINGTEST"
then
read b
elif test dummy = "$LOCKINGTEST"
then
b=""
else
testdirs=""; b="$LOCKINGTEST"; LOCKINGTEST=dummy
echo $b
fi
testdirs="$testdirs $b"
done
if test dummy = "$LOCKINGTEST"
then
exec 1>&9 9>&- echo "Using the following directories for the LOCKINGTESTs:"
echo " $testdirs"
fi
cat >grepfor <<HERE
$FGREP -e "\$1" _autotst.rrr >$DEVNULL && echo "\$2" >>$ACONF
HERE
chmod 0755 grepfor
cat >$ACONF <<HERE
/* This file was automagically generated by autoconf */
HERE
echo >_locktst.h
$RM _autotst.$O
cat >_autotst.c <<HERE
void*vvoid;
int main(){int i=0;char*p="t";
vvoid=p;
{time_t vtime;i+=vtime=1;}
{off_t voff;i+=voff=1;}
return !vvoid+!i;}
int empty()
{ return setsid();
}
HERE
if $MAKE _autotst.$O 2>&1 | $FGREP -v include/ >_autotst.rrr
test -f _autotst.$O
then
$MAKE _autotst >$DEVNULL 2>&1 || echo "#define setsid()" >>_locktst.h
else
grepfor void ' grepfor time_t 'typedef long time_t;'
grepfor off_t 'typedef long off_t;'
if $MAKE _autotst.$O >$DEVNULL 2>&1
then
$MAKE _autotst >$DEVNULL 2>&1 || echo "#define setsid()" >>_locktst.h
else
echo "#define UNISTD_H_MISSING" >>$ACONF
echo "#define setsid()" >>_locktst.h
fi
fi
$RM _autotst.$O _autotst
cat >_autotst.c <<HERE
int main(){
fcntl(0,F_SETLKW,0);
lockf(0,F_LOCK,(off_t)0);
flock(0,LOCK_EX);
return 0;}
HERE
echo 'Initiating fcntl()/kernel-locking-support tests'
if $MAKE _autotst.$O >$DEVNULL 2>&1
then
:
else
$RM _autotst.$O
echo "#define SYS_FILE_H_MISSING" >>$ACONF
if $MAKE _autotst.$O >_autotst.rrr 2>&1
then
:
else
echo 2>&1 "Whoeaaa! There's something fishy going on here."
echo 2>&1 "You have a look and see if you detect anything uncanny:"
echo 2>&1 "*******************************************************"
cat 2>&1 _autotst.rrr
echo 2>&1 "*******************************************************"
echo 2>&1 "I suggest you take a look at the definition of CFLAGS* and CC"
echo 2>&1 "in the Makefile before you try make again."
kill -15 $$
fi
fi
$MAKE _autotst >_autotst.rrr 2>&1
$RM _autotst.$O _autotst
$FGREP fcntl _autotst.rrr >$DEVNULL && echo "#undef F_SETLKW" >>_locktst.h
$FGREP lockf _autotst.rrr >$DEVNULL && echo "#undef F_LOCK" >>_locktst.h
$FGREP flock _autotst.rrr >$DEVNULL && cat >>_locktst.h <<HERE
HERE
cat >_autotst.c <<HERE
int dolock,child[NR_of_forks],timeout,fdcollect;
char dirlocktest[]="_locktest";
void stimeout()
{ timeout=1;close(fdcollect);killchildren();
}
void Terminate()
{ stimeout();exit(1);
}
static unsigned long seed;
unsigned psrand()
{ return (unsigned)(seed*=69069L)>>8;
}
unsigned sfork()
{ int pid;
while((pid=fork())<0)
fprintf(stderr,"Couldn't fork _locktst, retrying\n"),sleep(TIME_OUT_SEC);
return pid;
}
int main(argc,argv)char*argv[];
{ int goodlock,testlock,i,pip[2],pipw[2];time_t otimet;unsigned dtimet;
static char filename[]="_locktst.l0";
close(0);goodlock=0;testlock=FIRST_lock;signal(SIGPIPE,SIG_DFL);
if(argc==2)
{ char*p;
for(p=argv[1];;)
{ switch(*p++) /* parse the hotwire */
{ case '1':goodlock<<=1;goodlock++;
continue;
case '0':goodlock<<=1;
continue;
case '\0':
goodlock&=~MSK_fcntl;
goodlock&=~MSK_lockf;
goodlock&=~MSK_flock;
goto skip_tests;
}
break; /* oops, no hotwire */
}
goodlock=0;
}
if(sfork()) /* try to ditch the controlling tty */
return EXIT_SUCCESS; /* to prevent rather messy kernel-diagnostics */
setsid(); /* from appearing on your tty */
fprintf(stderr,"\
Every two digits a file is locked. First digit: which file, second digit:\n\
which program, XX indicates a lock conflict or failure\n");
do
{ int countlocks;
signal(SIGTERM,SIG_DFL);argc=1;dolock=goodlock|testlock;
do
{ char*curdir;
curdir=argv[argc];otimet=time((time_t*)0);
if(sfork())
{ close(1);close(2);i=NR_of_lockfiles;chdir(curdir);
chdir(dirlocktest);
do /* prime the lock, see if it vanishes */
{ filename[sizeof filename-2]='0'+--i;
lseek(goodlock=open(filename,O_WRONLY),(off_t)0,SEEK_END);
fdlock(goodlock);
}
while(i);
for(;;) /* synchronising "busy"-wait */
sleep(TIME_OUT_SEC); /* until the games can be started */
}
sleep(1);pipe(pip);pipe(pipw);i=NR_of_forks;*child=0;
fprintf(stderr,"\nStarting test %x on %s\n",dolock,curdir);
while((child[--i]=sfork())&&i); /* divide and conquer */
if(!*child)
{ unsigned char lockflag;int fd,childno=i<<SHIFT_childno;
int mylocks=LOCKS_per_child;
close(pipw[0]);close(pip[0]);close(1);
seed=time((time_t*)0)+getpid()|1;chdir(curdir);chdir(dirlocktest);
close(pipw[1]);
for(;;) /* and lock away! */
{ filename[sizeof filename-2]='0'+(i=psrand()%NR_of_lockfiles);
lockflag=childno|i<<1|1;
lseek(fd=open(filename,O_WRONLY),(off_t)0,SEEK_END);
if(sfdlock(fd))
lockflag&=~1,fprintf(stderr,"XX%x",lockflag);
write(pip[1],&lockflag,1);
fprintf(stderr," %x%x",i,childno>>SHIFT_childno);
lseek(fd,(off_t)0,SEEK_END);write(fd,&lockflag,1);
for(i=SLEEP_loop;i;i--,time((time_t*)0),sleep(SLEEP_delay));
lockflag&=~1;write(pip[1],&lockflag,1);
if(fdunlock()||close(fd))
{ write(pip[1],&lockflag,1);fprintf(stderr,"XX%x",lockflag);
return 1;
}
if(--mylocks<0)
sleep(SLEEP_retreat);
}
}
signal(SIGTERM,Terminate);
;{ unsigned char lckdfil[NR_of_lockfiles],curflag;
int j,ppid; /* give all children a chance */
ppid=getppid();
if(sfork()) /* discard the old body, let init adopt our children */
return EXIT_SUCCESS;
;{ FILE*fp;
if(fp=fopen("_locktst.pid","w"))
fprintf(fp,"%ld",(long)getpid()),fclose(fp);
}
countlocks=MIN_locks;close(pip[1]);close(pipw[1]);
for(j=NR_of_lockfiles;lckdfil[--j]=0,j;);
timeout=0;sleep(1);read(pipw[0],&curflag,1);close(pipw[0]);
kill(ppid,SIGKILL);fdcollect=pip[0];signal(SIGALRM,stimeout);
dtimet=(time((time_t*)0)-otimet)*GROW+TIME_OUT_SEC;
do
{ unlink("_locktst.alive");alarm(dtimet+2); /* watchdog */
dtimet=(otimet=time((time_t*)0)-otimet)>dtimet?
otimet*GROW:otimet+(dtimet-otimet)*DECAY+1; /* load dependent */
otimet=time((time_t*)0);
}
while(1==read(fdcollect,&curflag,1)&&
(j=lckdfil[i=(curflag&MASK_fileno)>>1],!timeout)&&
((j^(lckdfil[i]=curflag))==1||!(j&1)&&curflag&1)&&--countlocks);
alarm(0);close(fdcollect);killchildren();
fprintf(stdout,
"/*locktype: %x, countlocks: %x, timeout %x, watchdog %x, %s*/\n",
dolock,countlocks,timeout,dtimet,curdir);fflush(stdout);
}
}
while(!countlocks&&argv[++argc]);
if(!countlocks) /* Hurray! Locking was flawless */
goodlock=dolock; /* make a mark on our colt */
}
while(testlock>>=1);
skip_tests:
printf("/* Hotwire LOCKINGTEST=%c%c%c */\n",goodlock&0x4?'1':'0',
goodlock&0x2?'1':'0',goodlock&0x1?'1':'0');
printf("/* Procmail will lock via: dotlocking"); /* report our findings */
if(goodlock&MSK_fcntl)
printf(", fcntl()");
if(goodlock&MSK_lockf)
printf(", lockf()");
if(goodlock&MSK_flock)
printf(", flock()");
puts(" */");
if(!(goodlock&MSK_fcntl)) /* and in machine readable format */
puts("#define NOfcntl_lock");
if(goodlock&MSK_lockf)
puts("#define USElockf");
if(goodlock&MSK_flock)
{ puts("#define USEflock");
puts("#define SYS_FILE_H_MISSING");
}
puts("Kernel-locking tests completed.");fprintf(stderr,"\n");
return EXIT_SUCCESS;
}
int killchildren()
{ int i;
i=NR_of_forks;
do
if(child[--i]>0)
kill(child[i],SIGTERM),child[i]=0;
while(i);
return 0;
}
int sfdlock(fd)
{ int i;unsigned gobble[GOBBLE>>2];
for(i=GOBBLE>>2;i;gobble[--i]=~(unsigned)0); /* SunOS crash test */
return fdlock(fd);
}
static oldfdlock;
static struct flock flck; /* why can't it be a local variable? */
static off_t oldlockoffset;
int fdlock(fd)
{ int i;unsigned gobble[GOBBLE>>2];
for(i=GOBBLE>>2;i;gobble[--i]=~(unsigned)0); /* SunOS crash test */
oldfdlock=fd;fd=0;
if(MSK_fcntl&dolock)
{ static unsigned extra;
flck.l_type=F_WRLCK;flck.l_whence=SEEK_SET;flck.l_start=tell(oldfdlock);
if(!extra--)
extra=MIN_locks/4,flck.l_len=2,i|=fcntl(oldfdlock,F_SETLK,&flck);
flck.l_len=0;fd|=fcntl(oldfdlock,F_SETLKW,&flck);
}
fd=1;
if(MSK_lockf&dolock)
oldlockoffset=tell(oldfdlock),fd|=lockf(oldfdlock,F_LOCK,(off_t)0);
fd=1;
if(MSK_flock&dolock)
fd|=flock(oldfdlock,LOCK_EX);
fd=1;
return fd;
}
int fdunlock()
{ int i;unsigned gobble[GOBBLE];
for(i=GOBBLE;i;gobble[--i]=~(unsigned)0); /* some SunOS libs mess this up */
if(MSK_flock&dolock)
i|=flock(oldfdlock,LOCK_UN);
i=1;
if(MSK_lockf&dolock)
{ lseek(oldfdlock,oldlockoffset,SEEK_SET);
i|=lockf(oldfdlock,F_LOCK,(off_t)2);i|=lockf(oldfdlock,F_ULOCK,(off_t)0);
}
i=1;
if(MSK_fcntl&dolock)
flck.l_type=F_UNLCK,flck.l_len=0,i|=fcntl(oldfdlock,F_SETLK,&flck);
i=1;
if(!i)
for(i=GOBBLE;i&&gobble[--i]==~(unsigned)0;);
return i;
}
HERE
if $MAKE _autotst >_autotst.rrr 2>&1
then
:
else
echo 2>&1 "Whoeaaa! There's something fishy going on here."
echo 2>&1 "You have a look and see if you detect anything uncanny:"
echo 2>&1 "*******************************************************"
cat 2>&1 _autotst.rrr
echo 2>&1 "*******************************************************"
echo 2>&1 "I suggest you take a look at the definition of LDFLAGS*"
echo 2>&1 "in the Makefile before you try make again."
kill -15 $$
fi
$MV _locktst _locktst.$$ 2>$DEVNULL
$RM _autotst.$O _autotst.rrr _locktst* 2>$DEVNULL
echo "" >_locktst.pid
$MV _autotst _locktst
case "$testdirs" in
*[a-zA-Z/]*)
for b in $TESTDIRS
do
for a in 0 1 2 3
do echo dummy_file >$b/_locktst.l$a
done
done ;;
*) TESTDIRS=$testdirs ;;
esac
echo 2>&1 ""
_locktst $TESTDIRS >_locktst.rrr 2>lock.log echo 'Proceeding with kernel-locking-support tests in the background'
cat >_autotst.c <<HERE
int a(b)const int b[];
{ return *++b; /* watcom 10.6 on QNX refuses this */
}
int main()
{ char r[]="",*const*p;char*q="";const char*s="";
static const char*const nullp=0,*const*d= &nullp; /* AIX 3.2.3 failure */
static struct{const int a;int b;}c[2]={{0,0},{0,0}};/* IRIX 7.3.1 compiler */
/* requires initializers on static const objects */
--(c+1)->b; /* AIX 3.1.5 machines can't do this */
p= &q;
;{ int pip[2];
pipe(pip);
if(fork()) /* this should hide core dumps from the shell */
{ close(pip[1]); /* close the writing end */
return 1==read(pip[0],r,1)?0:1; /* wait for the rendevouz */
}
close(pip[0]); /* close the writing end */
if(!*d&&c[1].b) /* some magic to confuse the optimiser */
d=(const char*const*)p; /* core dumps Ultrix 4.3 ANSI C */
else /* so that it can't complain about the uselessness of this program */
execvp(q,p); /* IRIX 4.0.1 system-includes are wrong on this point */
if(write(pip[1],r,1)!=1) /* notify mam that we survived */
return 1; /* oops, lost mam somehow */
}
return r==s; /* Domain/OS warns here, not about "r==s" though */
}
HERE
echo 'Testing for const'
if $MAKE _autotst.$O 2>&1 | $FGREP -v include/ >_autotst.rrr
test -f _autotst.$O && $MAKE _autotst >$DEVNULL 2>&1 && _autotst
then
grepfor const 'else
echo ' set dummy *core*
if test -f $2 -a $nocore = yes
then
echo "Removing core file (bogus readonly segment)"
$RM *core*
fi
fi
$RM _autotst.$O _autotst
cat >_autotst.c <<HERE
int main(){volatile int i;return (i=0);}
HERE
echo 'Testing for volatile'
if $MAKE _autotst.$O >$DEVNULL 2>&1 && test -f _autotst.$O
then
:
else
echo ' not_ISO=yep
fi
$RM _autotst.$O
if $FGREP NO_const $ACONF >$DEVNULL
then
echo ' not_ISO=yep
else
cat >_autotst.c <<HERE
int main(const int argc,const char*const argv[]){return argc;}
HERE
echo 'Testing for prototypes'
if $MAKE _autotst.$O >$DEVNULL 2>&1 && test -f _autotst.$O
then
:
else
echo ' not_ISO=yep
fi
$RM _autotst.$O
fi
cat >_autotst.c <<HERE
enum foo { A, B, C, D=7, E, F= -3, G };
int main(){return !(A==0&&B==1&&C==2&&D==7&&E==8&&F==-3&&G==-2);}
HERE
echo 'Testing for enum'
if $MAKE _autotst.$O >$DEVNULL 2>&1 && test -f _autotst.$O &&
$MAKE _autotst >$DEVNULL 2>&1 && _autotst
then
:
else
echo ' not_ISO=yep
fi
$RM _autotst.$O
if test -n "$not_ISO"
then
cat <<HERE
Your system appears to not (correctly) support at least one of:
const, volatile, function prototypes, and enum types. Future
versions of procmail will probably require support for all of them,
so you should either upgrade your compiler to one that's compliant
with the ISO C standard (the standard's over 10 years old, for
goodness sake), or send email to <bug@procmail.org> explaining why
you need procmail to continue to support K&R C.
HERE
fi
echo 'Checking for POSIX and ANSI/ISO system include files'
cat >_autotst.c <<HERE
int a;
typedef DIR*tDIR;
tDIR vDIR;
HERE
i0="";i1="";i2="";i3="";i4="";i5="";i6="";i7="";i8="";i9="";i10="";i11="";
i12="";i13=""
oldi=""
while $MAKE _autotst.$O 2>&1 | $FGREP -v include/ >_autotst.rrr
test ! -f _autotst.$O
do
test -z "$i0" && grepfor stddef.h "#define STDDEF_H_MISSING" && i0=I
test -z "$i1" && grepfor stdlib.h "#define STDLIB_H_MISSING" && i1=I
test -z "$i2" && grepfor dirent.h "#define DIRENT_H_MISSING" && i2=I
test -z "$i2" && grepfor DIR "#define DIRENT_H_MISSING \
/* <dirent.h> is there, but empty */" && i2=I
test -z "$i3" && grepfor ndir.h "#define NDIR_H_MISSING" && i3=I
test I = "$i3$i4" && grepfor sys/ndir.h "#define SYS_NDIR_H_MISSING" && i4=I
test I = "$i4$i5" && grepfor sys/dir.h "#define SYS_DIR_H_MISSING" && i5=I
test I = "$i5$i6" && grepfor sys/dirent.h "#define SYS_DIRENT_H_MISSING" \
&& i6=I
test -z "$i7" && grepfor sys/wait.h "#define SYS_WAIT_H_MISSING" && i7=I
test -z "$i8" && grepfor sys/utsname.h "#define SYS_UTSNAME_H_MISSING" &&
i8=I
test -z "$i9" && grepfor string.h "#define STRING_H_MISSING" && i9=I
test -z "$i10" && grepfor sysexits.h "#define SYSEXITS_H_MISSING" && i10=I
test -z "$i11" && grepfor math.h "#define MATH_H_MISSING" && i11=I
test -z "$i12" && grepfor limits.h "#define LIMITS_H_MISSING" && i12=I
test -z "$i13" && grepfor syslog.h "#define SYSLOG_H_MISSING" && i13=I
newi="$i0$i1$i2$i3$i4$i5$i6$i7$i8$i9$i10$i11$i12$i13"
if test a$oldi = a$newi
then
echo 2>&1 "Whoeaaa! There's something fishy going on here."
echo 2>&1 "You have a look and see if you detect anything uncanny:"
echo 2>&1 "*******************************************************"
$MAKE _autotst.$O >_autotst.rrr 2>&1
cat 2>&1 _autotst.rrr
echo 2>&1 "*******************************************************"
echo 2>&1 "I suggest you take a look at the definition of CFLAGS*"
echo 2>&1 "in the Makefile before you try make again."
kill -15 $$
fi
oldi=$newi
echo \
" ...missing `expr $oldi : '.*'` include files, doublechecking..."
done
$RM _autotst.$O
cat >_autotst.c <<HERE
int a;
HERE
echo 'Checking for network/comsat/biff support'
if $MAKE _autotst.$O >$DEVNULL 2>&1
test -f _autotst.$O
then
:
else
echo "#define NO_COMSAT" >>$ACONF
fi
$RM _autotst.$O
cat >_autotst.c <<HERE
int main(){int i=0;
{size_t vsize_t;i+=vsize_t=1;}
{pid_t vpid_t;i+=vpid_t=1;}
{mode_t vmode_t;i+=vmode_t=1;}
{uid_t vuid_t;i+=vuid_t=1;}
{gid_t vgid_t;i+=vgid_t=1;}
{struct hostent vhostent;i+=!(vhostent.h_addr_list=0);}
{struct utsname vutsname;i+=!(*vutsname.nodename='\0');}
return !i;}
HERE
echo 'Testing for void*, size_t, off_t, pid_t, time_t, mode_t, uid_t & gid_t'
i1="";i2="";i3="";i4="";i5="";i6="";i7=""
oldi=""
while $MAKE _autotst.$O 2>&1 | $FGREP -v include/ >_autotst.rrr
test ! -f _autotst.$O
do
test -z "$i1" && grepfor size_t 'typedef unsigned size_t;' && i1=I
test -z "$i2" && grepfor pid_t 'typedef int pid_t;' && i2=I
test -z "$i3" && grepfor mode_t 'typedef int mode_t;' && i3=I
test -z "$i4" && grepfor uid_t 'typedef int uid_t;' && i4=I
test -z "$i5" && grepfor gid_t 'typedef int gid_t;' && i5=I
test -z "$i6" && grepfor h_addr_list ' test -z "$i6" && grepfor hostent ' test -z "$i6" && grepfor member ' test -z "$i7" && grepfor utsname "#define NOuname \
/* <sys/utsname.h> is there, but empty */" && i7=I
newi="$i1$i2$i3$i4$i5$i6$i7"
if test a$oldi = a$newi
then
echo 2>&1 "Whoeaaa! There's something fishy going on here."
echo 2>&1 "You have a look and see if you detect anything uncanny:"
echo 2>&1 "*******************************************************"
$MAKE _autotst.$O >_autotst.rrr 2>&1
cat 2>&1 _autotst.rrr
echo 2>&1 "*******************************************************"
echo 2>&1 "I suggest you take a look at the definition of CFLAGS*"
echo 2>&1 "in the Makefile before you try make again."
kill -15 $$
fi
oldi=$newi
echo \
" ...missing `expr $oldi : '.*'` types, doublechecking..."
done
$RM _autotst.$O
cat >_autotst.c <<HERE
void*realloc(),*malloc();
int main()
{ char*p=malloc(1),*q=0;
size_t len,last,max=BLKSIZ*64; /* 1M on non-SMALLHEAP systems */
int count=0;
for(last=len=INITIAL;len<=max+INITIAL;len+=BLKSIZ)
{ if(!(p=realloc(p,len)))
break;
if(p!=q)
count++,q=p,fprintf(stderr,"len=%lu p=%p\n",(unsigned long)len,p);
for(;last<len;last+=1024) /* touch at least every new page */
p[last]=last%127;
}
free(q);
printf("/* %d move%s in %d steps of size %d when reallocing */\n",
count,count==1?"":"s",(int)(max/BLKSIZ),BLKSIZ);
if(BLKSIZ*(10*count+1)>max)
{ puts("#define INEFFICIENTrealloc");
exit(1);
}
exit(0);
}
HERE
echo 'Checking realloc implementation'
if $MAKE _autotst >$DEVNULL 2>&1
test -f _autotst
then
_autotst >_autotst.rrr 2>realloc.log
case "$?" in
0) cat _autotst.rrr >>$ACONF;;
1) cat _autotst.rrr >>$ACONF
echo 'Sorry, repeatedly reallocing is inefficient';;
*) echo "The test program failed somehow. Assuming realloc is fine";;
esac
fi
$RM _autotst.$O _autotst _autotst.rrr
cat >_autotst.c <<HERE
int main(){int i;i=1;
i+=WIFEXITED(i);
i+=WIFSTOPPED(i);
i+=WEXITSTATUS(i);
i+=WSIGTERM(i);
return i;}
HERE
echo 'Testing for WIFEXITED(), WIFSTOPPED(), WEXITSTATUS() & WSIGTERM()'
if $MAKE _autotst.$O >_autotst.rrr 2>&1
then
$FGREP -v include/ <_autotst.rrr >_autotst.$O
$MV _autotst.$O _autotst.rrr
grepfor struct ' grepfor union 'else
echo 'fi
$RM _autotst.$O _autotst.rrr
cat >_autotst.c <<HERE
int main()
{ struct passwd*pw=getpwuid(0);
return (pw->pw_passwd==0)+(pw->pw_class==0)+(pw->pw_gecos==0);
}
HERE
echo 'Testing for various struct passwd members'
$MAKE _autotst.$O >_autotst.rrr 2>&1
grepfor pw_passwd 'grepfor pw_class 'grepfor pw_gecos '$RM _autotst.$O _autotst.rrr
cat >_autotst.c <<HERE
int main(){char a[2];
endpwent();endgrent();memmove(a,"0",1);bcopy("0",a,1);strcspn(a,"0");
strtol("0",(char**)0,10);strchr("0",'0');strpbrk(a,"0");rename(a,"0");
setrgid(0);setegid(0);setregid(0,0);setresgid(0,0,0);opendir("0");
initgroups("0",0);strstr("0","0");mkdir("0",0);pow(0.,0.);clock();
waitpid((pid_t)-1,(int*)0,0);ftruncate(0,0);fsync(0);strtod("0.0",(char**)0);
strncasecmp("0","0",3);strerror(ENOENT);strlcat(a,"0",2);
bzero(a,2);memset(a,'\0',2);
{struct stat stbuf;fstat(0,&stbuf);}
{struct utsname b;uname(&b);}
gethostbyname("0");getprotobyname(COMSATprotocol);endhostent();endservent();
endprotoent();
_exit(0);
return 0;}
HERE
echo 'Testing for memmove, strchr, strpbrk, strcspn, strtol, strstr,'
echo ' rename, setrgid, setegid, pow, opendir, mkdir, waitpid, fsync,'
echo ' ftruncate, strtod, strncasecmp, strerror, strlcat,'
echo ' memset, bzero, and _exit'
if $MAKE _autotst.$O >$DEVNULL 2>&1
then
:
else
echo 2>&1 "Whoeaaa! There's something fishy going on here."
echo 2>&1 "You have a look and see if you detect anything uncanny:"
echo 2>&1 "*******************************************************"
cat 2>&1 _autotst.rrr
echo 2>&1 "*******************************************************"
echo 2>&1 "Your include files seem to be beyond repair <sigh>."
echo 2>&1 "I give up."
kill -15 $$
fi
$MAKE _autotst >_autotst.rrr 2>&1
$RM _autotst _autotst.$O
for func in strcspn strpbrk rename pow mkdir fstat initgroups \
strtol waitpid ftruncate fsync strtod strncasecmp strlcat memset bzero _exit
do
grepfor $func "#define NO$func"
done
NOstrerror=no
grepfor strerror "#define NOstrerror" && NOstrerror=yes
grepfor opendir "
#define NOopendir /* the readdir library does not seem to be available
this will slightly affect the way a filenumber is
selected in MH-folders by procmail */
"
a=no
grepfor setrgid 'if grepfor setegid 'then
grepfor setregid ' grepfor setresgid 'fi
grepfor strchr 'grepfor uname "\
#define NOuname \
/* <sys/utsname.h> defines it, the libraries don't */"
grepfor endpwent 'grepfor endgrent 'if grepfor gethostbyname 'then
:
else
grepfor getprotobyname ' grepfor endhostent ' grepfor endservent ' grepfor endprotoent 'fi
grepfor strstr ' grepfor clock 'grepfor memmove 'if $FGREP -e bcopy _autotst.rrr >$DEVNULL
then
echo '
if test $NOstrerror = yes
then
cat >_autotst.c <<HERE
extern int sys_nerr;extern char*sys_errlist[];
int main(){
return puts(sys_errlist[sys_nerr-1]);}
HERE
echo 'Testing for sys_errlist'
if $MAKE _autotst.$O >_autotst.rrr 2>&1
then
if $MAKE _autotst >_autotst.rrr 2>&1
then
echo '' >_autotst.rrr
fi
fi
grepfor sys_errlist ' $RM _autotst _autotst.$O _autotst.rrr
fi
echo 'Testing for brain damage'
cat >_autotst.c <<HERE
struct tests{int a,b;};
int main(){
return offsetof(struct tests,b);}
HERE
if $MAKE _autotst.$O >$DEVNULL 2>&1
then
:
else
echo 'Yep, it is' echo ' fi
$RM _autotst.$O
else
cat >_autotst.c <<HERE
int main(){int j=0,i=M256-1;static char a[M256];
do a[i]=i;while(i--);
bcopy(a+F33,a,M256-F33);bcopy(a,a+F33,M256-F33);i=F33-1;
do j|=a[i]!=(char)(i+F33);while(i--);i=M256-1;
do j|=a[i]!=(char)i;while(--i!=F33-1);return !j;}
HERE
echo 'Testing for bcopy handling overlaps'
$MAKE _autotst >$DEVNULL 2>&1
if _autotst
then
echo 'Sorry, incompetent bcopy, using substitute instead'
echo ' fi
$RM _autotst.$O _autotst
fi
test -f /bin/test && echo "#define GOT_bin_test" >>$ACONF
cat >_autotst.c <<\HERE
unsigned long dobench(strstr,iter,haystack)char*(*const strstr)();
unsigned long iter;const char*const haystack;
{ unsigned long to;
to=(unsigned long)clock();
do (*strstr)(haystack,FROM_EXPR);
while(--iter);
return (unsigned long)clock()-to;
}
int main(argc,argv)int argc;const char*argv[];
{ if(argc==1)
{ char*haystack;
if(haystack=malloc(BENCHSIZE))
{ unsigned c1,c2,i;time_t t;
unsigned long iter,titer,syscnt;
for(i=c1=c2=0;i<BENCHSIZE-1;i++,c1++,c2++)
{ haystack[i]='a';
if(c1==37)
c1=0,haystack[i]='\n';
if(c2==51)
c2=0,haystack[i]='\n';
}
haystack[i]='\0';
for(titer=~(unsigned long)0,t=0,iter=1;t<=1&&iter<<1&&iter<titer;)
{ t=time((time_t*)0);
if((syscnt=dobench(strstr,iter<<=1,haystack))&&!~titer)
titer=iter*GRANULARITY;
t=time((time_t*)0)-t;
}
iter=dobench(sstrstr,iter,haystack);free(haystack);
if(!syscnt)
syscnt=1;
if(!iter)
iter=1;
printf("\
/* Your system's strstr() is %.2f times %sER than my C-routine */\n",
syscnt>=iter?(double)syscnt/iter:(double)iter/syscnt,
syscnt>=iter?"SLOW":"FAST");
if(syscnt>iter+iter/16) /* if at least 1.0625 times slower */
printf("\
#define SLOWstrstr\t\t\t /* using my substitute instead */\n");
}
else
printf("/* Insufficient memory to perform the benchmark! */\n");
;{ const struct protoent*p;
if(p=getprotobyname(COMSATprotocol))
{ printf("#define UDP_protocolno %d\n",p->p_proto);
;{ if(1)
{
;{ const struct servent*serv;
if(serv=getservbyname(COMSATservice,COMSATprotocol))
printf("#define BIFF_serviceport \"%d\"\n",
ntohs(serv->s_port));
}
;{ const struct hostent*host;
if(!strcmp("localhost",COMSAThost)&&
(host=gethostbyname(COMSAThost))&&
host->h_0addr_list&&host->h_addrtype==AF_INET&&
host->h_length)
{ int j=host->h_length;
const unsigned char*ad=(void*)host->h_0addr_list;
printf("#define IP_localhost {");
printf("%d",*ad++);
while(--j)
printf(",%d",*ad++);
puts("}");
}
}
}
else
puts("#define NO_COMSAT");
}
;{ unsigned long s=(size_t)~0;int bits;
for(bits=1;s>>=1;bits++);
if(bits<=16)
{ puts("#define SMALLHEAP");
return 0;
}
}
;{ struct passwd*p;
if(sizeof(int)>sizeof(uid_t)&&(p=getpwnam("root"))&&(*p->pw_dir!='/'||
(*p->pw_shell&&!(p->pw_shell)[1])))
{ puts("#define _GUID_T\ntypedef int uid_t;\ntypedef int gid_t;");
goto skipsetrgid;
}
}
if(geteuid()==ROOT_uid)
{ setgid(2);
if(!setrgid(3)&&(getgid()!=3||getegid()!=2))
puts("#define setrgid_BRAIN_DAMAGE");
else
{ setuid(2);
if(!setgid(3)&&!setgid(2))
puts("#define TOGGLE_SGID_OK");
}
}
else
{ gid_t groups[NGROUPS_MAX*sizeof(int)/sizeof(gid_t)];unsigned i;
for(i=getgroups(NGROUPS_MAX,groups);
--i<NGROUPS_MAX&&groups[i]==getgid(););
if(i<NGROUPS_MAX)
{ setegid(groups[i]);
if(!setrgid(groups[i])&&getgid()!=groups[i])
puts("#define setrgid_BRAIN_DAMAGE");
}
else
puts("#define setrgid_RUNTIME_CHECK");
}
skipsetrgid:;
}
if(argc==3)
{ printf("#define SENDMAIL \"%s\"\n",DEFsendmail);
return 1;
}
if(argc==4)
{ FILE*fp; /* in case we are root */
chown(argv[1],2,getegid());setuid(2); /* adjust the directory first */
if(!(fp=fopen(argv[2],"w")))
goto openerr; /* shouldn't happen, really */
fclose(fp); /* always clean up after yourself */
if(!chown(argv[2],geteuid()==3?4:3,getegid()))
openerr:
printf("#define CAN_chown\n");
}
if(argc>4)
{ static const char arg[]="e%04u=6789012345";unsigned diff;
charNUM(num,diff);char**nargv;const char*einfo="";
sscanf(argv[1],"%u",&diff); /* what did our previous incarnation want? */
if(!diff) /* first run? initialise the environment */
{ char*envs,**nenviron,**nenv;
diff=MAX_ENVMEM/sizeof arg+1;
if(!(nenviron=malloc(diff*sizeof*environ+MAX_ENVMEM)))
goto printit; /* oops, panic already */
envs=(char*)((nenv=nenviron)+diff);
while(--diff) /* put in some colour */
sprintf(*nenviron++=envs,arg,diff),envs+=sizeof arg;
*(environ=nenv)="PATH=.";*nenviron=0;diff=argc; /* start doubling */
}
if(MAX_ARGMEM/sizeof arg<=argc) /* we are satisfied */
{ einfo=" /* soft limit */"; /* no reason to hog memory */
goto printit;
}
;{ unsigned narg;
while(narg=argc+diff+1, /* allocate space for the new args */
!(nargv=malloc(narg*sizeof*argv+(size_t)diff*sizeof arg)))
if(!(diff>>=1)) /* oops, no space, back off */
goto printit; /* panic */
tmemmove(nargv,argv,argc*sizeof*argv);nargv[1]=num; /* copy old */
;{ char**pargv,*args;unsigned i;
pargv=nargv+argc;args=(char*)(nargv+narg);i=diff;
do
{ const char*p; /* and paint in the new ones */
for(*pargv++=args,p=arg;*args++= *p++;);
}
while(--i);
}
}
for(;;diff>>=1)
{ unsigned newdiff=diff>>1; /* take a small step for mankind */
if(argc==diff) /* or shall we boldly go */
newdiff=(unsigned)argc<<1; /* where no man has gone before? */
;{ unsigned maxdiff=MAXT(unsigned)-argc;
if(newdiff>maxdiff) /* that would overflow argc */
newdiff=maxdiff; /* and we wouldn't want that, would we now? */
}
if(!newdiff) /* reductio ad adsurdum? */
break; /* yes, break off the engagement */
sprintf(num,"%u",newdiff);nargv[argc+newdiff]=0; /* pass on the target */
execv(argv[0],nargv); /* jeronimo! */
}
printit: /* we proudly present the findings */
printf("#define MAX_argc %d%s\n",argc-2,einfo); /* of the jury! */
}
return EXIT_SUCCESS;
}
HERE
echo "Determining the maximum number of 16 byte arguments execv() takes"
if $MAKE _autotst >$DEVNULL 2>_autotst.rrr &&
_autotst 0 012345678901234 012345678901234 012345678901234 \
>>$ACONF 2>>_autotst.rrr
then
:
else
echo 2>&1 "Whoeaaa! This actually can't happen."
echo 2>&1 "You have a look and see if you detect anything uncanny:"
echo 2>&1 "*******************************************************"
cat 2>&1 _autotst.rrr
echo 2>&1 "*******************************************************"
echo 2>&1 "I suggest you take a look at the definition of LDFLAGS*"
echo 2>&1 "in the Makefile before you try make again."
kill -15 $$
fi
$RM _autotst.rrr
echo "Benchmarking your system's strstr() implementation"
_autotst >>$ACONF
found=no
for a in /var/spool/mail /usr/spool/mail /var/mail /usr/mail /spool/mail
do
test -d $a -a $found != yes &&
echo 'done
if test $found != yes
then
echo ' echo Could not find the system-mailbox directory, supplied default.
fi
cat >lookfor <<HERE
for a in /usr/sbin /usr/lib /lib /usr/etc /etc /usr/bin /bin /usr/local/bin \
/usr/lbin /usr/local/lib /usr/local /usr/.lib /local/bin /sbin
do
if test -f "\$a/\$1"
then
echo ' exit 0
fi
done
exit 1
HERE
chmod 0755 lookfor
if _autotst 2 3 >>$ACONF
test $? != 0 ||
lookfor sendmail || lookfor smail || lookfor mail then
:
else
echo 'Could not find any mailer. It should be a mailer accepting at least'
echo 'one plain destination address as its only argument (any sendmail'
echo 'compatible mailer will do), and the mail-to-be-sent on stdin.'
echo 'What is your mailer called? (You can override this in config.h)'
read a
echo "#define SENDMAIL \"$a\"" >>$ACONF
fi
grep '^ echo "#define DEFflagsendmail \"\"" >>$ACONF
a=/tmp/_chowntst.$$
$RM -r $a
OLDTESTDIRS="$a $OLDTESTDIRS"
mkdir $a
mkdir $a/__
_autotst $a/__ $a/__/__ 4 >>$ACONF
cat /usr/lib/sendmail.cf /etc/sendmail.cf /etc/mail/sendmail.cf 2>$DEVNULL |
grep 'Mlocal.*procmail' >$DEVNULL ||
echo '
cat /usr/lib/sendmail.cf /etc/sendmail.cf /etc/mail/sendmail.cf 2>$DEVNULL |
grep '^V' >$DEVNULL ||
echo '
lpath='/bin'
bins="/bin"
for newd in /usr/bin /usr/ucb /usr/5bin $BINDIR /local/bin /usr/local/bin \
/global/bin /usr/bin/X11 /usr/X*/bin
do
if test -d $newd
then
oldid=`cd $newd; ls -id . .. ../.. 2>&1`
for oldd in $bins
do
test "X`cd $oldd; ls -id . .. ../.. 2>&1`" = "X$oldid" && oldid=found
done
test found != "$oldid" && bins="$bins $newd" && lpath="$lpath:$newd"
fi
done
echo "#define defPATH \"PATH=\$HOME/bin:$lpath\"" >>$ACONF
echo "#define defSPATH \"PATH=$lpath\"" >>$ACONF
sed -n -e 's/^ v\([^ ]*\) .*$/ ../patchlevel.h >>$ACONF
while $FGREP -e "Kernel-locking tests completed." _locktst.rrr >$DEVNULL; \
test 0 != $?
do
if test -z "$tailpid"
then
echo "Waiting for the kernel-locking tests to finish..."
exec 9>&2 2>$DEVNULL
tail -f lock.log &
tailpid=$!
exec 2>&9 9>&-
fi
sleep 4
done
exec 9>&2 2>$DEVNULL
test ! -z "$tailpid" && kill $tailpid && echo "" && echo ""
tailpid=""
wait exec 2>&9 9>&-
echo "Collecting results from kernel-locking tests"
sed -e '/^Kernel-locking tests completed./,$ d' <_locktst.rrr >>$ACONF
set dummy *core*
if test -f $2 -a $nocore = yes
then
echo "Removing core file (probably from the locking tests)"
$RM *core*
fi
echo "/* autoconf completed */" >>$ACONF
$RM -r $OLDTESTDIRS $OLDTESTDIRS 2>$DEVNULL
$RM _autotst* _locktst* lookfor grepfor 2>$DEVNULL
echo =============================autoconf.h===================================
cat $ACONF
echo ==========================================================================