1#! /bin/sh
2:
3# Copyright (c) 1990-1997, S.R. van den Berg, The Netherlands
4#$Id: autoconf,v 1.136 2001/08/10 18:52:30 guenther Exp $
5
6# All possible entries in autoconf.h:
7
8#	#define UNISTD_H_MISSING
9#	#define STDDEF_H_MISSING
10#	#define STDLIB_H_MISSING
11#	#define DIRENT_H_MISSING
12#	#define SYS_DIRENT_H_MISSING
13#	#define NDIR_H_MISSING
14#	#define SYS_NDIR_H_MISSING
15#	#define SYS_DIR_H_MISSING
16#	#define SYS_WAIT_H_MISSING
17#	#define SYS_UTSNAME_H_MISSING
18#	#define STRING_H_MISSING
19#	#define SYSEXITS_H_MISSING
20#Ok	#define SYS_FILE_H_MISSING
21#Ok	#define SYSLOG_H_MISSING
22#	#define MATH_H_MISSING
23#	#define LIMITS_H_MISSING
24#	#define NO_const
25#	#define volatile
26#	#define P(args) ()
27#	#define NO_enum
28#	#define void char
29#	typedef int mode_t;
30#	typedef int pid_t;
31#	typedef int uid_t;
32#	typedef int gid_t;
33#	typedef unsigned size_t;
34#	typedef long off_t;
35#	typedef long time_t;
36#	#define NOmemmove
37#Ok	#define NObcopy
38#	#define NOstrcspn
39#	#define NOstrpbrk
40#	#define NOopendir
41#	#define NOrename
42#	#define NOsetrgid
43#	#define NOsetegid
44#	#define NOsetregid
45#	#define NOsetresgid
46#	#define setrgid_BRAIN_DAMAGE
47#	#define setrgid_RUNTIME_CHECK
48#Ok	#define TOGGLE_SGID_OK
49#	#define NOpow
50#	#define NOmkdir
51#	#define NOfstat
52#	#define NOuname
53#	#define NO_exit
54#	#define NOstrtol
55#	#define NOstrtod
56#	#define NOstrerror
57#Ok	#define NOstrlcat
58#Ok	#define NOstrncasecmp
59#Ok	#define NOsys_errlist
60#Ok	#define NObzero
61#	#define NOmemset
62#	#define NOwaitpid
63#Ok	#define NOftruncate
64#	#define SLOWstrstr
65#Ok	#define CAN_chown
66#	#define strchr(s,c) index(s,c)
67#	#define NOinitgroups
68#	#define NOfsync
69#Ok	#define endpwent()
70#Ok	#define endgrent()
71#Ok	#define endhostent()
72#Ok	#define endservent()
73#Ok	#define endprotoent()
74#	#define h_0addr_list h_addr
75#Ok	#define NOpw_passwd
76#Ok	#define NOpw_class
77#Ok	#define NOpw_gecos
78#Ok	#define NO_COMSAT
79#	#define _GUID_T
80#Ok	#define UDP_protocolno 17
81#Ok	#define BIFF_serviceport "512"
82#Ok	#define IP_localhost {127,0,0,1}
83#	#define WMACROS_NON_POSIX
84#	#define oBRAIN_DAMAGE
85#Ok	#define GOT_bin_test
86#Ok	#define MAX_argc 128
87#Ok	#define MAX_envc 128
88#Ok	#define SMALLHEAP
89#	#define NOfcntl_lock
90#Ok	#define USElockf
91#Ok	#define USEflock
92#Ok	#define MAILSPOOLDIR "/var/spool/mail/"
93#Ok	#define SENDMAIL "/usr/sbin/sendmail"
94#	#define buggy_SENDMAIL
95#	#define DEFflagsendmail ""
96#Ok	#define CF_no_procmail_yet
97#Ok	#define defSPATH "PATH=/bin:/usr/bin:/usr/local/bin"
98#Ok	#define defPATH "PATH=$HOME/bin:/bin:/usr/bin:/usr/local/bin"
99#Ok	#define INEFFICIENTrealloc
100#Ok	#define PM_VERSION "n.nn"
101
102# A conforming ISO C compiler and POSIX library should not have any defines
103# not marked as "Ok" in the autoconf.h file.
104# Anything else indicates failure of your system to comply with either
105# the ISO or POSIX standards (but procmail should be installable anyway).
106
107if test -z "$IFS"
108then IFS=" \
109	\
110
111"
112  export IFS
113fi
114
115SHELL=$1
116PATH=.:$PATH
117shift; RM="$1"
118shift; MV="$1"
119shift; DEVNULL=$1
120shift; FGREP="$1"
121shift; MAKE="$1"
122shift; O=$1
123shift; LOCKINGTEST="$1"
124shift; BINDIR=$1
125shift; ACONF=$1
126
127test 1 != $# &&
128 echo "Don't start this script directly, use \`make ../autoconf.h'" && exit 1
129
130if test -f make_n
131then
132  $RM make_n
133else
134  # We were mistakenly invoked under "make -n", so pretend this didn't happen.
135  exit 0
136fi
137
138export SHELL PATH
139
140test "X$LOCKINGTEST" = X__defaults__ && LOCKINGTEST=""
141
142OLDTESTDIRS=""
143tailpid=""
144echo "" >_locktst.pid
145
146if test -f $ACONF
147then
148  if $FGREP -e "/* autoconf completed */" $ACONF >$DEVNULL
149  then
150     cat <<HERE
151==============================================================================
152Would you like to skip running autoconf and use the existing autoconf.h file?
153When in doubt, press return [n]:
154HERE
155     read a
156     case "$a"n in
157	[yY]*) touch $ACONF; exit 0;;
158     esac
159  fi
160  trap "kill \`cat _locktst.pid\` 2>$DEVNULL;cp $ACONF $ACONF.tmp
161   test ! -z \"\$OLDTESTDIRS\" && $RM -r \$OLDTESTDIRS \$OLDTESTDIRS 2>$DEVNULL
162   test ! -z \"\$tailpid\" && kill \$tailpid 2>$DEVNULL
163   kill \`cat _locktst.pid\` 2>$DEVNULL; exit 1" 1 2 3 13 15
164else
165  trap "kill \`cat _locktst.pid\` 2>$DEVNULL;$RM -r $ACONF.tmp
166   test ! -z \"\$OLDTESTDIRS\" && $RM -r \$OLDTESTDIRS \$OLDTESTDIRS 2>$DEVNULL
167   mv $ACONF $ACONF.tmp 2>$DEVNULL
168   test ! -z \"\$tailpid\" && kill \$tailpid 2>$DEVNULL
169   kill \`cat _locktst.pid\` 2>$DEVNULL; exit 1" 1 2 3 13 15
170fi
171
172nocore=yes
173set dummy *core*
174test -f $2 && nocore=no
175
176set dummy $LOCKINGTEST
177shift
178LOCKINGTEST="$*"
179
180test ! -z "$LOCKINGTEST" && exec 9>&1 1>$DEVNULL	# make it shut up
181
182cat <<HERE
183==============================================================================
184In order for the kernel-locking tests to work as intended I have to be able to
185test-lock files on as many semantically different filesystems as possible (for
186more information about this, READ PARAGRAPH TWO in INSTALL).  To suppress this
187prompt you can set the LOCKINGTEST variable in the Makefile.
188
189Please add writable directories to the list.  You should only add directories
190that reside on filesystems that have unique characteristics.  E.g. if you have
191several remote NFS partitions, pick some unique client-server pairs, there is
192little use in picking the same server twice from the same client-machine.
193An excellent candidate would be a remotely mounted mail spool directory.
194==============================================================================
195HERE
196
197testdirs="/tmp ."
198
199case "$LOCKINGTEST" in
200  ""|*[a-zA-Z/]*) b=dummy ;;
201  *) b=""; testdirs=$LOCKINGTEST; LOCKINGTEST=dummy ;;
202esac
203
204while test ! -z "$b"
205do
206  echo ""
207  b=""
208  OLDTESTDIRS="$TESTDIRS"
209  TESTDIRS=""
210  for a in $testdirs
211  do $RM -r $a/_locktest
212     if mkdir $a/_locktest 2>$DEVNULL
213     then
214	b="$b $a"
215	TESTDIRS="$TESTDIRS $a/_locktest"
216     else
217	echo 2>&1 "Can't create $a/_locktest"
218     fi
219  done
220  OLDTESTDIRS="$TESTDIRS"
221  testdirs="$b"
222  echo ""
223  echo "I will temporarily use a testdirectory named _locktest"
224  echo "in the following directories:"
225  echo ""
226  echo $testdirs
227  echo ""
228  echo "If you would like to add any, please specify them below,"
229  echo "press return to continue:"
230  echo ""
231  if test -z "$LOCKINGTEST"
232  then
233     #read b
234     b=""
235  elif test dummy = "$LOCKINGTEST"
236  then
237     b=""
238  else
239     testdirs=""; b="$LOCKINGTEST"; LOCKINGTEST=dummy
240     echo $b
241  fi
242  testdirs="$testdirs $b"
243done
244
245if test dummy = "$LOCKINGTEST"
246then
247   exec 1>&9 9>&-					# you can speak again
248   echo "Using the following directories for the LOCKINGTESTs:"
249   echo " $testdirs"
250fi
251
252cat >grepfor <<HERE
253$FGREP -e "\$1" _autotst.rrr >$DEVNULL && echo "\$2" >>$ACONF
254HERE
255chmod 0755 grepfor
256
257cat >$ACONF <<HERE
258/* This file was automagically generated by autoconf */
259
260HERE
261
262echo >_locktst.h
263
264$RM _autotst.$O
265
266cat >_autotst.c <<HERE
267#include "$ACONF"
268#include <sys/types.h>
269#include <time.h>
270void*vvoid;
271int main(){int i=0;char*p="t";
272 vvoid=p;
273 {time_t vtime;i+=vtime=1;}
274 {off_t voff;i+=voff=1;}
275 return !vvoid+!i;}
276#include <unistd.h>
277int empty()
278{ return setsid();
279}
280HERE
281
282if $MAKE _autotst.$O 2>&1 | $FGREP -v include/ >_autotst.rrr
283 test -f _autotst.$O
284then
285  $MAKE _autotst >$DEVNULL 2>&1 || echo "#define setsid()" >>_locktst.h
286else
287  grepfor void '#define void char'
288  grepfor time_t 'typedef long time_t;'
289  grepfor off_t 'typedef long off_t;'
290  if $MAKE _autotst.$O >$DEVNULL 2>&1
291  then
292     $MAKE _autotst >$DEVNULL 2>&1 || echo "#define setsid()" >>_locktst.h
293  else
294     echo "#define UNISTD_H_MISSING" >>$ACONF
295     echo "#define setsid()" >>_locktst.h
296  fi
297fi
298
299$RM _autotst.$O _autotst
300
301cat >_autotst.c <<HERE
302#include "$ACONF"
303#include <sys/types.h>
304#ifndef UNISTD_H_MISSING
305#include <unistd.h>
306#endif
307#include <fcntl.h>
308#ifndef SYS_FILE_H_MISSING
309#include <sys/file.h>
310#endif
311int main(){
312#ifdef F_SETLKW
313 fcntl(0,F_SETLKW,0);
314#endif
315#ifdef F_LOCK
316  lockf(0,F_LOCK,(off_t)0);
317#endif
318#ifdef LOCK_EX
319  flock(0,LOCK_EX);
320#endif
321 return 0;}
322HERE
323
324echo 'Initiating fcntl()/kernel-locking-support tests'
325if $MAKE _autotst.$O >$DEVNULL 2>&1
326then
327:
328else
329  $RM _autotst.$O
330  echo "#define SYS_FILE_H_MISSING" >>$ACONF
331  if $MAKE _autotst.$O >_autotst.rrr 2>&1
332  then
333  :
334  else
335     echo 2>&1 "Whoeaaa!  There's something fishy going on here."
336     echo 2>&1 "You have a look and see if you detect anything uncanny:"
337     echo 2>&1 "*******************************************************"
338     cat 2>&1 _autotst.rrr
339     echo 2>&1 "*******************************************************"
340     echo 2>&1 "I suggest you take a look at the definition of CFLAGS* and CC"
341     echo 2>&1 "in the Makefile before you try make again."
342     kill -15 $$
343  fi
344fi
345$MAKE _autotst >_autotst.rrr 2>&1
346$RM _autotst.$O _autotst
347
348$FGREP fcntl _autotst.rrr >$DEVNULL && echo "#undef F_SETLKW" >>_locktst.h
349$FGREP lockf _autotst.rrr >$DEVNULL && echo "#undef F_LOCK" >>_locktst.h
350$FGREP flock _autotst.rrr >$DEVNULL && cat >>_locktst.h <<HERE
351#ifdef LOCK_EX
352#undef LOCK_EX
353#endif
354#ifndef SYS_FILE_H_MISSING
355#define SYS_FILE_H_MISSING
356#endif
357HERE
358
359cat >_autotst.c <<HERE
360#include "$ACONF"
361#include "../config.h"
362#include <sys/types.h>
363#ifndef UNISTD_H_MISSING
364#include <unistd.h>		/* getpid() getppid() */
365#endif
366#include <stdio.h>
367#include <time.h>
368#include <fcntl.h>
369#include <signal.h>		/* SIGKILL */
370#ifndef tell
371#define tell(fd)	lseek(fd,(off_t)0,SEEK_CUR)
372#endif
373#ifndef EXIT_SUCCESS
374#define EXIT_SUCCESS	0
375#endif
376#include "_locktst.h"
377#ifndef SYS_FILE_H_MISSING
378#include <sys/file.h>
379#endif
380#ifndef SEEK_SET
381#define SEEK_SET	0
382#define SEEK_CUR	1
383#define SEEK_END	2
384#endif
385
386#define MIN_locks	128	  /* minimum of consecutive successful locks */
387#define SLEEP_loop	64		      /* iterations in the busy loop */
388#define SLEEP_delay	0		  /* sleep() time per busy iteration */
389#define SLEEP_retreat	1		 /* extra sleep() when quota reached */
390#define TIME_OUT_SEC	16			 /* initial timeout per lock */
391#define NR_of_forks	8			 /* concurrent test-programs */
392#define NR_of_lockfiles 2		  /* lockfiles used in testing (<=4) */
393#define GROW		3			    /* when timing got worse */
394#define DECAY		7/8			   /* when timing got better */
395#define GOBBLE		256			 /* for the SunOS crash test */
396
397#define LOCKS_per_child (((MIN_locks+NR_of_forks-1)/NR_of_forks+1)/2)
398#define SHIFT_childno	3
399#define MASK_fileno	((1<<SHIFT_childno)-1)
400#define MASK_childno	(~MASK_fileno)
401
402#ifdef NO_fcntl_LOCK
403#undef F_SETLKW
404#endif
405#ifdef NO_lockf_LOCK
406#undef F_LOCK
407#endif
408#ifdef NO_flock_LOCK
409#undef LOCK_EX
410#endif
411
412#define FIRST_lock	0x04		/* testing is in order of importance */
413#define MSK_fcntl	0x04	       /* don't change this order unless you */
414#define MSK_lockf	0x02	       /* change locking.c as well, fdlock() */
415#define MSK_flock	0x01			 /* and hotwired LOCKINGTEST */
416
417int dolock,child[NR_of_forks],timeout,fdcollect;
418char dirlocktest[]="_locktest";
419
420void stimeout()
421{ timeout=1;close(fdcollect);killchildren();
422}
423
424void Terminate()
425{ stimeout();exit(1);
426}
427
428static unsigned long seed;
429
430unsigned psrand()
431{ return (unsigned)(seed*=69069L)>>8;
432}
433
434unsigned sfork()
435{ int pid;
436  while((pid=fork())<0)
437     fprintf(stderr,"Couldn't fork _locktst, retrying\n"),sleep(TIME_OUT_SEC);
438  return pid;
439}
440
441int main(argc,argv)char*argv[];
442{ int goodlock,testlock,i,pip[2],pipw[2];time_t otimet;unsigned dtimet;
443  static char filename[]="_locktst.l0";
444  close(0);goodlock=0;testlock=FIRST_lock;signal(SIGPIPE,SIG_DFL);
445  if(argc==2)
446   { char*p;
447     for(p=argv[1];;)
448      { switch(*p++)					/* parse the hotwire */
449	 { case '1':goodlock<<=1;goodlock++;
450	      continue;
451	   case '0':goodlock<<=1;
452	      continue;
453	   case '\0':
454#ifndef F_SETLKW			/* sanity check, for the less gifted */
455	      goodlock&=~MSK_fcntl;
456#endif
457#ifndef F_LOCK
458	      goodlock&=~MSK_lockf;
459#endif
460#ifndef LOCK_EX
461	      goodlock&=~MSK_flock;
462#endif
463	      goto skip_tests;
464	 }
465	break;						 /* oops, no hotwire */
466      }
467     goodlock=0;
468   }
469  if(sfork())				 /* try to ditch the controlling tty */
470     return EXIT_SUCCESS;      /* to prevent rather messy kernel-diagnostics */
471  setsid();				       /* from appearing on your tty */
472  fprintf(stderr,"\
473Every two digits a file is locked.  First digit: which file, second digit:\n\
474which program, XX indicates a lock conflict or failure\n");
475  do
476   { int countlocks;
477     signal(SIGTERM,SIG_DFL);argc=1;dolock=goodlock|testlock;
478     do
479      { char*curdir;
480	curdir=argv[argc];otimet=time((time_t*)0);
481	if(sfork())
482	 { close(1);close(2);i=NR_of_lockfiles;chdir(curdir);
483	   chdir(dirlocktest);
484	   do			       /* prime the lock, see if it vanishes */
485	    { filename[sizeof filename-2]='0'+--i;
486	      lseek(goodlock=open(filename,O_WRONLY),(off_t)0,SEEK_END);
487	      fdlock(goodlock);
488	    }
489	   while(i);
490	   for(;;)				/* synchronising "busy"-wait */
491	      sleep(TIME_OUT_SEC);	   /* until the games can be started */
492	 }
493	sleep(1);pipe(pip);pipe(pipw);i=NR_of_forks;*child=0;
494	fprintf(stderr,"\nStarting test %x on %s\n",dolock,curdir);
495	while((child[--i]=sfork())&&i);		       /* divide and conquer */
496	if(!*child)
497	 { unsigned char lockflag;int fd,childno=i<<SHIFT_childno;
498	   int mylocks=LOCKS_per_child;
499	   close(pipw[0]);close(pip[0]);close(1);
500	   seed=time((time_t*)0)+getpid()|1;chdir(curdir);chdir(dirlocktest);
501	   close(pipw[1]);
502	   for(;;)					   /* and lock away! */
503	    { filename[sizeof filename-2]='0'+(i=psrand()%NR_of_lockfiles);
504	      lockflag=childno|i<<1|1;
505	      lseek(fd=open(filename,O_WRONLY),(off_t)0,SEEK_END);
506	      if(sfdlock(fd))
507		 lockflag&=~1,fprintf(stderr,"XX%x",lockflag);
508	      write(pip[1],&lockflag,1);
509	      fprintf(stderr," %x%x",i,childno>>SHIFT_childno);
510	      lseek(fd,(off_t)0,SEEK_END);write(fd,&lockflag,1);
511	      for(i=SLEEP_loop;i;i--,time((time_t*)0),sleep(SLEEP_delay));
512	      lockflag&=~1;write(pip[1],&lockflag,1);
513	      if(fdunlock()||close(fd))
514	       { write(pip[1],&lockflag,1);fprintf(stderr,"XX%x",lockflag);
515		 return 1;
516	       }
517	      if(--mylocks<0)
518		 sleep(SLEEP_retreat);
519	    }
520	 }
521	signal(SIGTERM,Terminate);
522	;{ unsigned char lckdfil[NR_of_lockfiles],curflag;
523	   int j,ppid;			       /* give all children a chance */
524	   ppid=getppid();
525	   if(sfork())	/* discard the old body, let init adopt our children */
526	      return EXIT_SUCCESS;
527	   ;{ FILE*fp;
528	      if(fp=fopen("_locktst.pid","w"))
529		 fprintf(fp,"%ld",(long)getpid()),fclose(fp);
530	    }
531	   countlocks=MIN_locks;close(pip[1]);close(pipw[1]);
532	   for(j=NR_of_lockfiles;lckdfil[--j]=0,j;);
533	   timeout=0;sleep(1);read(pipw[0],&curflag,1);close(pipw[0]);
534	   kill(ppid,SIGKILL);fdcollect=pip[0];signal(SIGALRM,stimeout);
535	   dtimet=(time((time_t*)0)-otimet)*GROW+TIME_OUT_SEC;
536	   do
537	    { unlink("_locktst.alive");alarm(dtimet+2);		 /* watchdog */
538	      dtimet=(otimet=time((time_t*)0)-otimet)>dtimet?
539	       otimet*GROW:otimet+(dtimet-otimet)*DECAY+1; /* load dependent */
540	      otimet=time((time_t*)0);
541	    }
542	   while(1==read(fdcollect,&curflag,1)&&
543	    (j=lckdfil[i=(curflag&MASK_fileno)>>1],!timeout)&&
544	    ((j^(lckdfil[i]=curflag))==1||!(j&1)&&curflag&1)&&--countlocks);
545	   alarm(0);close(fdcollect);killchildren();
546	   fprintf(stdout,
547	    "/*locktype: %x, countlocks: %x, timeout %x, watchdog %x, %s*/\n",
548	    dolock,countlocks,timeout,dtimet,curdir);fflush(stdout);
549	 }
550      }
551     while(!countlocks&&argv[++argc]);
552     if(!countlocks)			    /* Hurray!	Locking was flawless */
553	goodlock=dolock;			  /* make a mark on our colt */
554   }
555  while(testlock>>=1);
556skip_tests:
557  printf("/* Hotwire LOCKINGTEST=%c%c%c */\n",goodlock&0x4?'1':'0',
558   goodlock&0x2?'1':'0',goodlock&0x1?'1':'0');
559  printf("/* Procmail will lock via: dotlocking");    /* report our findings */
560  if(goodlock&MSK_fcntl)
561     printf(", fcntl()");
562  if(goodlock&MSK_lockf)
563     printf(", lockf()");
564  if(goodlock&MSK_flock)
565     printf(", flock()");
566  puts(" */");
567  if(!(goodlock&MSK_fcntl))		   /* and in machine readable format */
568     puts("#define NOfcntl_lock");
569  if(goodlock&MSK_lockf)
570     puts("#define USElockf");
571  if(goodlock&MSK_flock)
572   { puts("#define USEflock");
573#ifdef SYS_FILE_H_MISSING
574     puts("#define SYS_FILE_H_MISSING");
575#endif
576   }
577  puts("Kernel-locking tests completed.");fprintf(stderr,"\n");
578  return EXIT_SUCCESS;
579}
580
581int killchildren()
582{ int i;
583  i=NR_of_forks;
584  do
585     if(child[--i]>0)
586	kill(child[i],SIGTERM),child[i]=0;
587  while(i);
588  return 0;
589}
590
591int sfdlock(fd)
592{ int i;unsigned gobble[GOBBLE>>2];
593  for(i=GOBBLE>>2;i;gobble[--i]=~(unsigned)0);		 /* SunOS crash test */
594  return fdlock(fd);
595}
596
597static oldfdlock;
598#ifdef F_SETLKW
599static struct flock flck;		/* why can't it be a local variable? */
600#endif
601#ifdef F_LOCK
602static off_t oldlockoffset;
603#endif
604
605int fdlock(fd)
606{ int i;unsigned gobble[GOBBLE>>2];
607  for(i=GOBBLE>>2;i;gobble[--i]=~(unsigned)0);		 /* SunOS crash test */
608  oldfdlock=fd;fd=0;
609  if(MSK_fcntl&dolock)
610#ifdef F_SETLKW
611   { static unsigned extra;
612     flck.l_type=F_WRLCK;flck.l_whence=SEEK_SET;flck.l_start=tell(oldfdlock);
613     if(!extra--)
614	extra=MIN_locks/4,flck.l_len=2,i|=fcntl(oldfdlock,F_SETLK,&flck);
615     flck.l_len=0;fd|=fcntl(oldfdlock,F_SETLKW,&flck);
616   }
617#else
618     fd=1;
619#endif
620  if(MSK_lockf&dolock)
621#ifdef F_LOCK
622     oldlockoffset=tell(oldfdlock),fd|=lockf(oldfdlock,F_LOCK,(off_t)0);
623#else
624     fd=1;
625#endif
626  if(MSK_flock&dolock)
627#ifdef LOCK_EX
628     fd|=flock(oldfdlock,LOCK_EX);
629#else
630     fd=1;
631#endif
632  return fd;
633}
634
635int fdunlock()
636{ int i;unsigned gobble[GOBBLE];
637  for(i=GOBBLE;i;gobble[--i]=~(unsigned)0);  /* some SunOS libs mess this up */
638  if(MSK_flock&dolock)
639#ifdef LOCK_EX
640     i|=flock(oldfdlock,LOCK_UN);
641#else
642     i=1;
643#endif
644  if(MSK_lockf&dolock)
645#ifdef F_LOCK
646   { lseek(oldfdlock,oldlockoffset,SEEK_SET);
647     i|=lockf(oldfdlock,F_LOCK,(off_t)2);i|=lockf(oldfdlock,F_ULOCK,(off_t)0);
648   }
649#else
650     i=1;
651#endif
652  if(MSK_fcntl&dolock)
653#ifdef F_SETLKW
654     flck.l_type=F_UNLCK,flck.l_len=0,i|=fcntl(oldfdlock,F_SETLK,&flck);
655#else
656     i=1;
657#endif
658  if(!i)
659     for(i=GOBBLE;i&&gobble[--i]==~(unsigned)0;);
660  return i;
661}
662HERE
663
664if $MAKE _autotst >_autotst.rrr 2>&1
665then
666:
667else
668  echo 2>&1 "Whoeaaa!  There's something fishy going on here."
669  echo 2>&1 "You have a look and see if you detect anything uncanny:"
670  echo 2>&1 "*******************************************************"
671  cat 2>&1 _autotst.rrr
672  echo 2>&1 "*******************************************************"
673  echo 2>&1 "I suggest you take a look at the definition of LDFLAGS*"
674  echo 2>&1 "in the Makefile before you try make again."
675  kill -15 $$
676fi
677
678$MV _locktst _locktst.$$ 2>$DEVNULL
679$RM _autotst.$O _autotst.rrr _locktst* 2>$DEVNULL
680echo "" >_locktst.pid
681$MV _autotst _locktst
682
683case "$testdirs" in
684  *[a-zA-Z/]*)
685     for b in $TESTDIRS
686     do
687	for a in 0 1 2 3
688	do echo dummy_file >$b/_locktst.l$a
689	done
690     done ;;
691  *) TESTDIRS=$testdirs ;;
692esac
693
694echo 2>&1 ""
695
696_locktst $TESTDIRS >_locktst.rrr 2>lock.log	# will finish in the background
697echo 'Proceeding with kernel-locking-support tests in the background'
698
699
700cat >_autotst.c <<HERE
701#include "$ACONF"
702#ifndef UNISTD_H_MISSING
703#include <unistd.h>		/* execvp() */
704#endif
705int a(b)const int b[];
706{ return *++b;				  /* watcom 10.6 on QNX refuses this */
707}
708int main()
709{ char r[]="",*const*p;char*q="";const char*s="";
710  static const char*const nullp=0,*const*d= &nullp;	/* AIX 3.2.3 failure */
711  static struct{const int a;int b;}c[2]={{0,0},{0,0}};/* IRIX 7.3.1 compiler */
712			    /* requires initializers on static const objects */
713  --(c+1)->b;				 /* AIX 3.1.5 machines can't do this */
714  p= &q;
715  ;{ int pip[2];
716     pipe(pip);
717     if(fork())		       /* this should hide core dumps from the shell */
718      { close(pip[1]);				    /* close the writing end */
719	return 1==read(pip[0],r,1)?0:1;		   /* wait for the rendevouz */
720      }
721     close(pip[0]);				    /* close the writing end */
722     if(!*d&&c[1].b)		      /* some magic to confuse the optimiser */
723	d=(const char*const*)p;		     /* core dumps Ultrix 4.3 ANSI C */
724     else /* so that it can't complain about the uselessness of this program */
725	execvp(q,p);   /* IRIX 4.0.1 system-includes are wrong on this point */
726     if(write(pip[1],r,1)!=1)		      /* notify mam that we survived */
727	return 1;				   /* oops, lost mam somehow */
728   }
729  return r==s;		    /* Domain/OS warns here, not about "r==s" though */
730}
731HERE
732
733echo 'Testing for const'
734if $MAKE _autotst.$O 2>&1 | $FGREP -v include/ >_autotst.rrr
735  test -f _autotst.$O && $MAKE _autotst >$DEVNULL 2>&1 && _autotst
736then
737  grepfor const '#define NO_const'
738else
739  echo '#define NO_const' >>$ACONF
740  set dummy *core*
741  if test -f $2 -a $nocore = yes
742  then
743     echo "Removing core file (bogus readonly segment)"
744     $RM *core*
745  fi
746fi
747$RM _autotst.$O _autotst
748
749cat >_autotst.c <<HERE
750int main(){volatile int i;return (i=0);}
751HERE
752
753echo 'Testing for volatile'
754if $MAKE _autotst.$O >$DEVNULL 2>&1 && test -f _autotst.$O
755then
756:
757else
758 echo '#define volatile' >>$ACONF
759 not_ISO=yep
760fi
761$RM _autotst.$O
762
763if $FGREP NO_const $ACONF >$DEVNULL
764then
765  echo '#define P(args) ()' >>$ACONF
766  not_ISO=yep
767else
768  cat >_autotst.c <<HERE
769int main(const int argc,const char*const argv[]){return argc;}
770HERE
771
772  echo 'Testing for prototypes'
773  if $MAKE _autotst.$O >$DEVNULL 2>&1 && test -f _autotst.$O
774  then
775  :
776  else
777     echo '#define P(args) ()' >>$ACONF
778     not_ISO=yep
779  fi
780  $RM _autotst.$O
781fi
782
783cat >_autotst.c <<HERE
784enum foo { A, B, C, D=7, E, F= -3, G };
785int main(){return !(A==0&&B==1&&C==2&&D==7&&E==8&&F==-3&&G==-2);}
786HERE
787
788echo 'Testing for enum'
789if $MAKE _autotst.$O >$DEVNULL 2>&1 && test -f _autotst.$O &&
790   $MAKE _autotst >$DEVNULL 2>&1 && _autotst
791then
792:
793else
794 echo '#define NO_enum' >>$ACONF
795 not_ISO=yep
796fi
797$RM _autotst.$O
798
799if test -n "$not_ISO"
800then
801  cat <<HERE
802
803Your system appears to not (correctly) support at least one of:
804const, volatile, function prototypes, and enum types.  Future
805versions of procmail will probably require support for all of them,
806so you should either upgrade your compiler to one that's compliant
807with the ISO C standard (the standard's over 10 years old, for
808goodness sake), or send email to <bug@procmail.org> explaining why
809you need procmail to continue to support K&R C.
810
811HERE
812fi
813
814echo 'Checking for POSIX and ANSI/ISO system include files'
815
816cat >_autotst.c <<HERE
817#include "includes.h"
818int a;
819#ifndef SYS_DIRENT_H_MISSING
820typedef DIR*tDIR;
821tDIR vDIR;
822#endif
823HERE
824
825i0="";i1="";i2="";i3="";i4="";i5="";i6="";i7="";i8="";i9="";i10="";i11="";
826i12="";i13=""
827oldi=""
828
829while $MAKE _autotst.$O 2>&1 | $FGREP -v include/ >_autotst.rrr
830 test ! -f _autotst.$O
831do
832  test -z "$i0" && grepfor stddef.h "#define STDDEF_H_MISSING" && i0=I
833  test -z "$i1" && grepfor stdlib.h "#define STDLIB_H_MISSING" && i1=I
834  test -z "$i2" && grepfor dirent.h "#define DIRENT_H_MISSING" && i2=I
835  test -z "$i2" && grepfor DIR "#define DIRENT_H_MISSING		   \
836/* <dirent.h> is there, but empty */" && i2=I
837  test -z "$i3" && grepfor ndir.h "#define NDIR_H_MISSING" && i3=I
838   test I = "$i3$i4" && grepfor sys/ndir.h "#define SYS_NDIR_H_MISSING" && i4=I
839    test I = "$i4$i5" && grepfor sys/dir.h "#define SYS_DIR_H_MISSING" && i5=I
840     test I = "$i5$i6" && grepfor sys/dirent.h "#define SYS_DIRENT_H_MISSING" \
841      && i6=I
842  test -z "$i7" && grepfor sys/wait.h "#define SYS_WAIT_H_MISSING" && i7=I
843  test -z "$i8" && grepfor sys/utsname.h "#define SYS_UTSNAME_H_MISSING" &&
844   i8=I
845  test -z "$i9" && grepfor string.h "#define STRING_H_MISSING" && i9=I
846  test -z "$i10" && grepfor sysexits.h "#define SYSEXITS_H_MISSING" && i10=I
847  test -z "$i11" && grepfor math.h "#define MATH_H_MISSING" && i11=I
848  test -z "$i12" && grepfor limits.h "#define LIMITS_H_MISSING" && i12=I
849  test -z "$i13" && grepfor syslog.h "#define SYSLOG_H_MISSING" && i13=I
850  newi="$i0$i1$i2$i3$i4$i5$i6$i7$i8$i9$i10$i11$i12$i13"
851  if test a$oldi = a$newi
852  then
853     echo 2>&1 "Whoeaaa!  There's something fishy going on here."
854     echo 2>&1 "You have a look and see if you detect anything uncanny:"
855     echo 2>&1 "*******************************************************"
856     $MAKE _autotst.$O >_autotst.rrr 2>&1
857     cat 2>&1 _autotst.rrr
858     echo 2>&1 "*******************************************************"
859     echo 2>&1 "I suggest you take a look at the definition of CFLAGS*"
860     echo 2>&1 "in the Makefile before you try make again."
861     kill -15 $$
862  fi
863  oldi=$newi
864  echo \
865   "	...missing `expr $oldi : '.*'` include files, doublechecking..."
866done
867
868$RM _autotst.$O
869
870cat >_autotst.c <<HERE
871#include "includes.h"
872#include "network.h"
873int a;
874HERE
875
876echo 'Checking for network/comsat/biff support'
877
878if $MAKE _autotst.$O >$DEVNULL 2>&1
879 test -f _autotst.$O
880then
881:
882else
883  echo "#define NO_COMSAT" >>$ACONF
884fi
885
886$RM _autotst.$O
887
888cat >_autotst.c <<HERE
889#include "includes.h"
890#ifndef NO_COMSAT
891#include "network.h"
892#endif
893int main(){int i=0;
894 {size_t vsize_t;i+=vsize_t=1;}
895 {pid_t vpid_t;i+=vpid_t=1;}
896 {mode_t vmode_t;i+=vmode_t=1;}
897 {uid_t vuid_t;i+=vuid_t=1;}
898 {gid_t vgid_t;i+=vgid_t=1;}
899#ifndef NO_COMSAT
900 {struct hostent vhostent;i+=!(vhostent.h_addr_list=0);}
901#endif
902#ifndef NOuname
903 {struct utsname vutsname;i+=!(*vutsname.nodename='\0');}
904#endif
905 return !i;}
906HERE
907
908echo 'Testing for void*, size_t, off_t, pid_t, time_t, mode_t, uid_t & gid_t'
909
910i1="";i2="";i3="";i4="";i5="";i6="";i7=""
911oldi=""
912
913while $MAKE _autotst.$O 2>&1 | $FGREP -v include/ >_autotst.rrr
914 test ! -f _autotst.$O
915do
916  test -z "$i1" && grepfor size_t 'typedef unsigned size_t;' && i1=I
917  test -z "$i2" && grepfor pid_t 'typedef int pid_t;' && i2=I
918  test -z "$i3" && grepfor mode_t 'typedef int mode_t;' && i3=I
919  test -z "$i4" && grepfor uid_t 'typedef int uid_t;' && i4=I
920  test -z "$i5" && grepfor gid_t 'typedef int gid_t;' && i5=I
921  test -z "$i6" && grepfor h_addr_list '#define h_0addr_list h_addr' && i6=I
922  test -z "$i6" && grepfor hostent '#define h_0addr_list h_addr' && i6=I
923  test -z "$i6" && grepfor member '#define h_0addr_list h_addr' && i6=I
924  test -z "$i7" && grepfor utsname "#define NOuname			      \
925/* <sys/utsname.h> is there, but empty */" && i7=I
926  newi="$i1$i2$i3$i4$i5$i6$i7"
927  if test a$oldi = a$newi
928  then
929     echo 2>&1 "Whoeaaa!  There's something fishy going on here."
930     echo 2>&1 "You have a look and see if you detect anything uncanny:"
931     echo 2>&1 "*******************************************************"
932     $MAKE _autotst.$O >_autotst.rrr 2>&1
933     cat 2>&1 _autotst.rrr
934     echo 2>&1 "*******************************************************"
935     echo 2>&1 "I suggest you take a look at the definition of CFLAGS*"
936     echo 2>&1 "in the Makefile before you try make again."
937     kill -15 $$
938  fi
939  oldi=$newi
940  echo \
941   "	...missing `expr $oldi : '.*'` types, doublechecking..."
942done
943
944$RM _autotst.$O
945
946cat >_autotst.c <<HERE
947#include "$ACONF"
948#include "../config.h"
949#include <stdio.h>
950#ifndef STDLIB_H_MISSING
951#include <stdlib.h>
952#define INITIAL 60
953#else
954void*realloc(),*malloc();
955#endif
956int main()
957{ char*p=malloc(1),*q=0;
958  size_t len,last,max=BLKSIZ*64;	      /* 1M on non-SMALLHEAP systems */
959  int count=0;
960  for(last=len=INITIAL;len<=max+INITIAL;len+=BLKSIZ)
961   { if(!(p=realloc(p,len)))
962	break;
963     if(p!=q)
964	count++,q=p,fprintf(stderr,"len=%lu p=%p\n",(unsigned long)len,p);
965     for(;last<len;last+=1024)		    /* touch at least every new page */
966	p[last]=last%127;
967   }
968  free(q);
969  printf("/* %d move%s in %d steps of size %d when reallocing */\n",
970	 count,count==1?"":"s",(int)(max/BLKSIZ),BLKSIZ);
971  if(BLKSIZ*(10*count+1)>max)
972   { puts("#define INEFFICIENTrealloc");
973     exit(1);
974   }
975  exit(0);
976}
977HERE
978
979echo 'Checking realloc implementation'
980
981$RM -f _autotst
982if $MAKE _autotst >$DEVNULL 2>&1
983 test -f _autotst
984then
985 _autotst >_autotst.rrr 2>realloc.log
986 case "$?" in
987 0) cat _autotst.rrr >>$ACONF;;
988 1) cat _autotst.rrr >>$ACONF
989    echo 'Sorry, repeatedly reallocing is inefficient';;
990 *) echo "The test program failed somehow.  Assuming realloc is fine";;
991 esac
992fi
993
994$RM _autotst.$O _autotst _autotst.rrr
995
996cat >_autotst.c <<HERE
997#include "includes.h"
998int main(){int i;i=1;
999 i+=WIFEXITED(i);
1000 i+=WIFSTOPPED(i);
1001 i+=WEXITSTATUS(i);
1002 i+=WSIGTERM(i);
1003 return i;}
1004HERE
1005
1006echo 'Testing for WIFEXITED(), WIFSTOPPED(), WEXITSTATUS() & WSIGTERM()'
1007if $MAKE _autotst.$O >_autotst.rrr 2>&1
1008then
1009   $FGREP -v include/ <_autotst.rrr >_autotst.$O
1010   $MV _autotst.$O _autotst.rrr
1011   grepfor struct '#define WMACROS_NON_POSIX' ||
1012    grepfor union '#define WMACROS_NON_POSIX'
1013else
1014   echo '#define WMACROS_NON_POSIX' >>$ACONF
1015fi
1016$RM _autotst.$O _autotst.rrr
1017
1018cat >_autotst.c <<HERE
1019#include <pwd.h>
1020int main()
1021{ struct passwd*pw=getpwuid(0);
1022  return (pw->pw_passwd==0)+(pw->pw_class==0)+(pw->pw_gecos==0);
1023}
1024HERE
1025
1026echo 'Testing for various struct passwd members'
1027$MAKE _autotst.$O >_autotst.rrr 2>&1
1028grepfor pw_passwd '#define NOpw_passwd'
1029grepfor pw_class  '#define NOpw_class'
1030grepfor pw_gecos  '#define NOpw_gecos'
1031$RM _autotst.$O _autotst.rrr
1032
1033cat >_autotst.c <<HERE
1034#include "includes.h"
1035#ifndef NO_COMSAT
1036#include "network.h"
1037#endif
1038int main(){char a[2];
1039 endpwent();endgrent();memmove(a,"0",1);bcopy("0",a,1);strcspn(a,"0");
1040 strtol("0",(char**)0,10);strchr("0",'0');strpbrk(a,"0");rename(a,"0");
1041 setrgid(0);setegid(0);setregid(0,0);setresgid(0,0,0);opendir("0");
1042 initgroups("0",0);strstr("0","0");mkdir("0",0);pow(0.,0.);clock();
1043 waitpid((pid_t)-1,(int*)0,0);ftruncate(0,0);fsync(0);strtod("0.0",(char**)0);
1044 strncasecmp("0","0",3);strerror(ENOENT);strlcat(a,"0",2);
1045 bzero(a,2);memset(a,'\0',2);
1046#ifdef S_ISLNK
1047 {struct stat stbuf;fstat(0,&stbuf);}
1048#endif
1049#ifndef NOuname
1050 {struct utsname b;uname(&b);}
1051#endif
1052#ifndef NO_COMSAT
1053 gethostbyname("0");getprotobyname(COMSATprotocol);endhostent();endservent();
1054 endprotoent();
1055#endif
1056 _exit(0);
1057 return 0;}
1058HERE
1059
1060echo 'Testing for memmove, strchr, strpbrk, strcspn, strtol, strstr,'
1061echo '	rename, setrgid, setegid, pow, opendir, mkdir, waitpid, fsync,'
1062echo '	ftruncate, strtod, strncasecmp, strerror, strlcat,'
1063echo '	memset, bzero, and _exit'
1064if $MAKE _autotst.$O >$DEVNULL 2>&1
1065then
1066:
1067else
1068  echo 2>&1 "Whoeaaa!  There's something fishy going on here."
1069  echo 2>&1 "You have a look and see if you detect anything uncanny:"
1070  echo 2>&1 "*******************************************************"
1071  cat 2>&1 _autotst.rrr
1072  echo 2>&1 "*******************************************************"
1073  echo 2>&1 "Your include files seem to be beyond repair <sigh>."
1074  echo 2>&1 "I give up."
1075  kill -15 $$
1076fi
1077$MAKE _autotst >_autotst.rrr 2>&1
1078$RM _autotst _autotst.$O
1079
1080# The simple ones
1081for func in strcspn strpbrk rename pow mkdir fstat initgroups \
1082 strtol waitpid ftruncate fsync strtod strncasecmp strlcat memset bzero _exit
1083do
1084  grepfor $func "#define NO$func"
1085done
1086
1087NOstrerror=no
1088grepfor strerror "#define NOstrerror" && NOstrerror=yes
1089
1090grepfor opendir "
1091#define NOopendir	/* the readdir library does not seem to be available
1092			   this will slightly affect the way a filenumber is
1093			   selected in MH-folders by procmail */
1094"
1095a=no
1096grepfor setrgid '#define NOsetrgid' && a=yes
1097if grepfor setegid '#define NOsetegid' || test $a = yes
1098then
1099  grepfor setregid '#define NOsetregid' &&
1100   grepfor setresgid '#define NOsetresgid'
1101fi
1102grepfor strchr '#define strchr(s,c) index(s,c)'
1103grepfor uname "\
1104#define NOuname		  \
1105/* <sys/utsname.h> defines it, the libraries don't */"
1106grepfor endpwent '#define endpwent()'
1107grepfor endgrent '#define endgrent()'
1108if grepfor gethostbyname '#define NO_COMSAT'
1109then
1110:
1111else
1112  grepfor getprotobyname '#define UDP_protocolno 17'
1113  grepfor endhostent '#define endhostent()'
1114  grepfor endservent '#define endservent()'
1115  grepfor endprotoent '#define endprotoent()'
1116fi
1117grepfor strstr '#define SLOWstrstr' ||
1118 grepfor clock '#define SLOWstrstr'
1119grepfor memmove '#define NOmemmove' &&
1120if $FGREP -e bcopy _autotst.rrr >$DEVNULL
1121then
1122 echo '#define NObcopy' >>$ACONF
1123
1124if test $NOstrerror = yes
1125then
1126  cat >_autotst.c <<HERE
1127#include "includes.h"
1128extern int sys_nerr;extern char*sys_errlist[];
1129int main(){
1130 return puts(sys_errlist[sys_nerr-1]);}
1131HERE
1132
1133  echo 'Testing for sys_errlist'
1134  if $MAKE _autotst.$O >_autotst.rrr 2>&1
1135  then
1136    if $MAKE _autotst >_autotst.rrr 2>&1
1137    then
1138      echo '' >_autotst.rrr
1139    fi
1140  fi
1141  grepfor sys_errlist '#define NOsys_errlist'
1142  $RM _autotst _autotst.$O _autotst.rrr
1143fi
1144
1145 echo 'Testing for brain damage'
1146 cat >_autotst.c <<HERE
1147#include "includes.h"
1148struct tests{int a,b;};
1149int main(){
1150 return offsetof(struct tests,b);}
1151HERE
1152 if $MAKE _autotst.$O >$DEVNULL 2>&1
1153 then
1154    :
1155 else
1156    echo 'Yep, it is'			# ISC chokes on its own offsetof()
1157    echo '#define oBRAIN_DAMAGE' >>$ACONF
1158 fi
1159 $RM _autotst.$O
1160
1161else
1162
1163 cat >_autotst.c <<HERE
1164#include "includes.h"
1165#define M256	256
1166#define F33	33
1167int main(){int j=0,i=M256-1;static char a[M256];
1168  do a[i]=i;while(i--);
1169  bcopy(a+F33,a,M256-F33);bcopy(a,a+F33,M256-F33);i=F33-1;
1170  do j|=a[i]!=(char)(i+F33);while(i--);i=M256-1;
1171  do j|=a[i]!=(char)i;while(--i!=F33-1);return !j;}
1172HERE
1173
1174 echo 'Testing for bcopy handling overlaps'
1175 $MAKE _autotst >$DEVNULL 2>&1
1176
1177 if _autotst
1178 then
1179   echo 'Sorry, incompetent bcopy, using substitute instead'
1180   echo '#define NObcopy' >>$ACONF
1181 fi
1182 $RM _autotst.$O _autotst
1183fi
1184test -f /bin/test && echo "#define GOT_bin_test" >>$ACONF
1185
1186cat >_autotst.c <<\HERE
1187#define BENCHSIZE	16384
1188#define GRANULARITY	64		    /* maximal benchmark granularity */
1189#include "sublib.c"
1190#ifndef NO_COMSAT
1191#include "network.h"					 /* also for ntohs() */
1192#endif
1193#undef malloc						     /* from shell.h */
1194#ifdef BENCHSIZE
1195#undef strstr						  /* from includes.h */
1196#undef free						     /* from shell.h */
1197unsigned long dobench(strstr,iter,haystack)char*(*const strstr)();
1198 unsigned long iter;const char*const haystack;
1199{ unsigned long to;
1200  to=(unsigned long)clock();
1201  do (*strstr)(haystack,FROM_EXPR);
1202  while(--iter);
1203  return (unsigned long)clock()-to;
1204}
1205#endif
1206int main(argc,argv)int argc;const char*argv[];
1207{ if(argc==1)
1208   { char*haystack;
1209#ifdef BENCHSIZE
1210     if(haystack=malloc(BENCHSIZE))
1211      { unsigned c1,c2,i;time_t t;
1212	unsigned long iter,titer,syscnt;
1213	for(i=c1=c2=0;i<BENCHSIZE-1;i++,c1++,c2++)
1214	 { haystack[i]='a';
1215	   if(c1==37)
1216	      c1=0,haystack[i]='\n';
1217	   if(c2==51)
1218	      c2=0,haystack[i]='\n';
1219	 }
1220	haystack[i]='\0';
1221	for(titer=~(unsigned long)0,t=0,iter=1;t<=1&&iter<<1&&iter<titer;)
1222	 { t=time((time_t*)0);
1223	   if((syscnt=dobench(strstr,iter<<=1,haystack))&&!~titer)
1224	      titer=iter*GRANULARITY;
1225	   t=time((time_t*)0)-t;
1226	 }
1227	iter=dobench(sstrstr,iter,haystack);free(haystack);
1228	if(!syscnt)
1229	   syscnt=1;
1230	if(!iter)
1231	   iter=1;
1232	printf("\
1233/* Your system's strstr() is %.2f times %sER than my C-routine */\n",
1234	 syscnt>=iter?(double)syscnt/iter:(double)iter/syscnt,
1235	 syscnt>=iter?"SLOW":"FAST");
1236	if(syscnt>iter+iter/16)		  /* if at least 1.0625 times slower */
1237	   printf("\
1238#define SLOWstrstr\t\t\t      /* using my substitute instead */\n");
1239      }
1240     else
1241	printf("/* Insufficient memory to perform the benchmark! */\n");
1242#endif /* SLOWstrstr */
1243#ifndef NO_COMSAT
1244#ifndef UDP_protocolno
1245     ;{ const struct protoent*p;
1246	if(p=getprotobyname(COMSATprotocol))
1247	 { printf("#define UDP_protocolno %d\n",p->p_proto);
1248#else
1249     ;{ if(1)
1250	 {
1251#endif
1252	   ;{ const struct servent*serv;
1253	      if(serv=getservbyname(COMSATservice,COMSATprotocol))
1254		 printf("#define BIFF_serviceport \"%d\"\n",
1255		  ntohs(serv->s_port));
1256	    }
1257#ifdef AF_INET
1258	   ;{ const struct hostent*host;
1259	      if(!strcmp("localhost",COMSAThost)&&
1260	       (host=gethostbyname(COMSAThost))&&
1261	       host->h_0addr_list&&host->h_addrtype==AF_INET&&
1262	       host->h_length)
1263	       { int j=host->h_length;
1264		 const unsigned char*ad=(void*)host->h_0addr_list;
1265		 printf("#define IP_localhost {");
1266		 printf("%d",*ad++);
1267		 while(--j)
1268		    printf(",%d",*ad++);
1269		 puts("}");
1270	       }
1271	    }
1272#endif /* AF_INET */
1273	 }
1274	else
1275	   puts("#define NO_COMSAT");
1276      }
1277#endif /* NO_COMSAT */
1278     ;{ unsigned long s=(size_t)~0;int bits;
1279	for(bits=1;s>>=1;bits++);
1280	if(bits<=16)
1281	 { puts("#define SMALLHEAP");
1282	   return 0;
1283	 }
1284      }
1285#ifdef _GUID_T						      /* ISC cc hack */
1286     ;{ struct passwd*p;
1287	if(sizeof(int)>sizeof(uid_t)&&(p=getpwnam("root"))&&(*p->pw_dir!='/'||
1288	 (*p->pw_shell&&!(p->pw_shell)[1])))
1289	 { puts("#define _GUID_T\ntypedef int uid_t;\ntypedef int gid_t;");
1290	   goto skipsetrgid;
1291	 }
1292      }
1293#endif
1294#ifndef NOinitgroups
1295     if(geteuid()==ROOT_uid)
1296      { setgid(2);
1297	if(!setrgid(3)&&(getgid()!=3||getegid()!=2))
1298	   puts("#define setrgid_BRAIN_DAMAGE");
1299	else
1300	 { setuid(2);
1301	   if(!setgid(3)&&!setgid(2))
1302	      puts("#define TOGGLE_SGID_OK");
1303	 }
1304      }
1305     else
1306#ifndef NGROUPS_MAX			 /* is this safeguard really needed? */
1307#define NGROUPS_MAX	3
1308#endif				       /* some OSes expect an array of ints? */
1309      { gid_t groups[NGROUPS_MAX*sizeof(int)/sizeof(gid_t)];unsigned i;
1310	for(i=getgroups(NGROUPS_MAX,groups);
1311	    --i<NGROUPS_MAX&&groups[i]==getgid(););
1312	if(i<NGROUPS_MAX)
1313	 { setegid(groups[i]);
1314	   if(!setrgid(groups[i])&&getgid()!=groups[i])
1315	      puts("#define setrgid_BRAIN_DAMAGE");
1316	 }
1317	else
1318	   puts("#define setrgid_RUNTIME_CHECK");
1319      }
1320#endif
1321skipsetrgid:;
1322   }
1323#ifdef DEFsendmail
1324  if(argc==3)
1325   { printf("#define SENDMAIL \"%s\"\n",DEFsendmail);
1326     return 1;
1327   }
1328#endif
1329  if(argc==4)
1330   { FILE*fp;					      /* in case we are root */
1331     chown(argv[1],2,getegid());setuid(2);     /* adjust the directory first */
1332     if(!(fp=fopen(argv[2],"w")))
1333	goto openerr;				 /* shouldn't happen, really */
1334     fclose(fp);			   /* always clean up after yourself */
1335     if(!chown(argv[2],geteuid()==3?4:3,getegid()))
1336openerr:
1337	printf("#define CAN_chown\n");
1338   }
1339  if(argc>4)
1340#define MAX_ENVMEM	2048			 /* typical environment size */
1341#define MAX_ARGMEM	(2048*1024L)	       /* upper limit arguments size */
1342   { static const char arg[]="e%04u=6789012345";unsigned diff;
1343     charNUM(num,diff);char**nargv;const char*einfo="";
1344#define MAXT(type)	(~(type)0>>1)
1345     sscanf(argv[1],"%u",&diff);  /* what did our previous incarnation want? */
1346     if(!diff)			   /* first run?  initialise the environment */
1347      { char*envs,**nenviron,**nenv;
1348	diff=MAX_ENVMEM/sizeof arg+1;
1349	if(!(nenviron=malloc(diff*sizeof*environ+MAX_ENVMEM)))
1350	   goto printit;			      /* oops, panic already */
1351	envs=(char*)((nenv=nenviron)+diff);
1352	while(--diff)				       /* put in some colour */
1353	   sprintf(*nenviron++=envs,arg,diff),envs+=sizeof arg;
1354	*(environ=nenv)="PATH=.";*nenviron=0;diff=argc;	   /* start doubling */
1355      }
1356     if(MAX_ARGMEM/sizeof arg<=argc)			 /* we are satisfied */
1357      { einfo=" /* soft limit */";		  /* no reason to hog memory */
1358	goto printit;
1359      }
1360     ;{ unsigned narg;
1361	while(narg=argc+diff+1,		  /* allocate space for the new args */
1362	     !(nargv=malloc(narg*sizeof*argv+(size_t)diff*sizeof arg)))
1363	   if(!(diff>>=1))			 /* oops, no space, back off */
1364	      goto printit;					    /* panic */
1365	tmemmove(nargv,argv,argc*sizeof*argv);nargv[1]=num;	 /* copy old */
1366	;{ char**pargv,*args;unsigned i;
1367	   pargv=nargv+argc;args=(char*)(nargv+narg);i=diff;
1368	   do
1369	    { const char*p;			/* and paint in the new ones */
1370	      for(*pargv++=args,p=arg;*args++= *p++;);
1371	    }
1372	   while(--i);
1373	 }
1374      }
1375     for(;;diff>>=1)
1376      { unsigned newdiff=diff>>1;	    /* take a small step for mankind */
1377	if(argc==diff)				    /* or shall we boldly go */
1378	   newdiff=(unsigned)argc<<1;	    /* where no man has gone before? */
1379	;{ unsigned maxdiff=MAXT(unsigned)-argc;
1380	   if(newdiff>maxdiff)			 /* that would overflow argc */
1381	      newdiff=maxdiff;	 /* and we wouldn't want that, would we now? */
1382	 }
1383	if(!newdiff)				    /* reductio ad adsurdum? */
1384	   break;			    /* yes, break off the engagement */
1385	sprintf(num,"%u",newdiff);nargv[argc+diff]=0;  /* pass on the target */
1386	execv(argv[0],nargv);					/* jeronimo! */
1387      }
1388printit:				  /* we proudly present the findings */
1389     printf("#define MAX_argc %d%s\n",argc-2,einfo);	     /* of the jury! */
1390   }
1391  return EXIT_SUCCESS;
1392}
1393HERE
1394
1395echo "Determining the maximum number of 16 byte arguments execv() takes"
1396
1397if $MAKE _autotst >$DEVNULL 2>_autotst.rrr &&
1398   _autotst 0 012345678901234 012345678901234 012345678901234 \
1399    >>$ACONF 2>>_autotst.rrr
1400then
1401:
1402else
1403  echo 2>&1 "Whoeaaa!  This actually can't happen."
1404  echo 2>&1 "You have a look and see if you detect anything uncanny:"
1405  echo 2>&1 "*******************************************************"
1406  cat 2>&1 _autotst.rrr
1407  echo 2>&1 "*******************************************************"
1408  echo 2>&1 "I suggest you take a look at the definition of LDFLAGS*"
1409  echo 2>&1 "in the Makefile before you try make again."
1410  kill -15 $$
1411fi
1412
1413$RM _autotst.rrr
1414
1415echo "Benchmarking your system's strstr() implementation"
1416
1417_autotst >>$ACONF
1418
1419found=no
1420
1421for a in /var/spool/mail /usr/spool/mail /var/mail /usr/mail /spool/mail
1422do
1423  test -d $a -a $found != yes &&
1424   echo '#define MAILSPOOLDIR "'$a'/"' >>$ACONF && found=yes
1425done
1426if test $found != yes
1427then
1428 echo '#define MAILSPOOLDIR "/var/spool/mail/"' >>$ACONF
1429 echo Could not find the system-mailbox directory, supplied default.
1430fi
1431
1432cat >lookfor <<HERE
1433for a in /usr/sbin /usr/lib /lib /usr/etc /etc /usr/bin /bin /usr/local/bin \
1434 /usr/lbin /usr/local/lib /usr/local /usr/.lib /local/bin /sbin
1435do
1436 if test -f "\$a/\$1"
1437 then
1438    echo '#define SENDMAIL "'"\$a/\$1"'"' >>$ACONF
1439    exit 0
1440 fi
1441done
1442exit 1
1443HERE
1444chmod 0755 lookfor
1445
1446if _autotst 2 3 >>$ACONF
1447   test $? != 0 ||
1448    lookfor sendmail || lookfor smail || lookfor mail #|| lookfor rmail
1449then
1450:
1451else
1452 echo 'Could not find any mailer.  It should be a mailer accepting at least'
1453 echo 'one plain destination address as its only argument (any sendmail'
1454 echo 'compatible mailer will do), and the mail-to-be-sent on stdin.'
1455 echo 'What is your mailer called?  (You can override this in config.h)'
1456 read a
1457 echo "#define SENDMAIL \"$a\"" >>$ACONF
1458fi
1459
1460grep '^#define SENDMAIL ".*/sendmail"' $ACONF >$DEVNULL ||
1461 echo "#define DEFflagsendmail \"\"" >>$ACONF
1462
1463a=/tmp/_chowntst.$$
1464$RM -r $a
1465OLDTESTDIRS="$a $OLDTESTDIRS"
1466mkdir $a
1467mkdir $a/__
1468
1469_autotst $a/__ $a/__/__ 4 >>$ACONF
1470
1471cat /usr/lib/sendmail.cf /etc/sendmail.cf /etc/mail/sendmail.cf 2>$DEVNULL |
1472 grep 'Mlocal.*procmail' >$DEVNULL ||
1473 echo '#define CF_no_procmail_yet' >>$ACONF
1474
1475cat /usr/lib/sendmail.cf /etc/sendmail.cf /etc/mail/sendmail.cf 2>$DEVNULL |
1476 grep '^V' >$DEVNULL ||
1477 echo '#define buggy_SENDMAIL' >>$ACONF
1478
1479lpath='/bin'
1480bins="/bin"
1481
1482for newd in /usr/bin /usr/ucb /usr/5bin $BINDIR /local/bin /usr/local/bin \
1483 /global/bin /usr/bin/X11 /usr/X*/bin
1484do
1485  if test -d $newd
1486  then
1487     oldid=`cd $newd; ls -id . .. ../.. 2>&1`
1488     for oldd in $bins
1489     do
1490	test "X`cd $oldd; ls -id . .. ../.. 2>&1`" = "X$oldid" && oldid=found
1491     done
1492     test found != "$oldid" && bins="$bins $newd" && lpath="$lpath:$newd"
1493  fi
1494done
1495
1496case ":$lpath:" in
1497    *:/usr/local/bin:*) ;;
1498    *) lpath="$lpath:/usr/local/bin" ;;
1499esac
1500
1501echo "#define defPATH \"PATH=\$HOME/bin:$lpath\"" >>$ACONF
1502echo "#define defSPATH \"PATH=$lpath\"" >>$ACONF
1503
1504sed -n -e 's/^ v\([^ ]*\) .*$/#define PM_VERSION "\1"/p' \
1505 ../patchlevel.h >>$ACONF
1506
1507while $FGREP -e "Kernel-locking tests completed." _locktst.rrr >$DEVNULL; \
1508 test 0 != $?
1509do
1510  if test -z "$tailpid"
1511  then
1512     echo "Waiting for the kernel-locking tests to finish..."
1513     exec 9>&2 2>$DEVNULL
1514     tail -f lock.log &
1515     tailpid=$!
1516     exec 2>&9 9>&-
1517  fi
1518# if test ! -f _locktst.alive
1519# then
1520#    echo >_locktst.alive
1521#    echo "Waiting for kernel-locking tests to finish..."
1522# fi
1523  sleep 4
1524done
1525exec 9>&2 2>$DEVNULL
1526test ! -z "$tailpid" && kill $tailpid && echo "" && echo ""
1527tailpid=""
1528wait			# wait now, to prevent a notification message afterward
1529exec 2>&9 9>&-
1530echo "Collecting results from kernel-locking tests"
1531sed -e '/^Kernel-locking tests completed./,$ d' <_locktst.rrr >>$ACONF
1532set dummy *core*
1533if test -f $2 -a $nocore = yes
1534then
1535  echo "Removing core file (probably from the locking tests)"
1536  $RM *core*
1537fi
1538
1539echo "/* autoconf completed */" >>$ACONF
1540
1541$RM -r $OLDTESTDIRS $OLDTESTDIRS 2>$DEVNULL
1542$RM _autotst* _locktst* lookfor grepfor 2>$DEVNULL
1543
1544echo =============================autoconf.h===================================
1545cat $ACONF
1546echo ==========================================================================
1547