1use ExtUtils::MakeMaker;
2# See lib/ExtUtils/MakeMaker.pm for details of how to influence
3# the contents of the Makefile that is written.
4use strict;
5use 5.006;   # builds on 5.005, but Slaven Rezic got strange testresults
6use Config;
7
8use Getopt::Long;
9my %options;
10
11my @whichcand = qw(/bin/which /usr/bin/which);
12
13my @KRB5_CONFIG_TRIES = (
14
15    '/usr/kerberos/bin/krb5-config',   # for use with CentOS,  as suggested by Mark Hedges in https://rt.cpan.org/Ticket/Display.html?id=48732
16    '/usr/bin/krb5-config',            # always worth a try ;-)
17
18);
19
20
21my $LINE = "\n\n----------------------------------------------------------\n";
22&GetOptions(\%options , "gssapiimpl=s",  "help", "gssapi_libs=s", "gssapi_inc=s", "gssapi_lddlflags=s");
23
24open(MANIFEST, "MANIFEST")	or die "$0: Unable to open MANIFEST: $!";
25my $otherxs = join " ",
26		map { substr($_, 0, -1) }
27		grep { m:^xs/: }
28		<MANIFEST>;
29close(MANIFEST);
30
31
32
33if ($options{'help'}){
34print <<HELP;
35
36==================================================================
37BUILDING HELP
38==================================================================
39
40Hello - you obviously need Help! :-)
41
42This additional command line options are available
43for adjusting:
44
45(1) --gssapiimpl /bla/local/heimdal
46  This tells me where to look for your installed
47  GSSAPI installation MIT or Heimdal.
48  This must be the directory that contains
49  the ./bin/krb5_config utility.
50
51(2) --gssapi_libs='-L/bla/local/mitkrb/lib -lgss_all'
52  The precise location of the libraries with -L and the libraries needed with -l.
53
54(3) --gssapi_inc -I/bla/local/mitkrb/include
55  The exact location of the header files.
56
57(4) --gssapi_lddlflags='-shared -Wl,--enable-new-dtags -Wl,-rpath -Wl/bla/local/mitkrb/lib'
58  Allows for any flags to be passed to the linker, for instance if WriteMakefile ignores
59  entries in LIBS.
60
61Option (1) is preferred, use (2),(3) and (4) only if needed and you know what you
62are doing. If any of (2),(3) or (4) is supplied, (1) will be ignored.
63
64HELP
65;
66  exit;
67}
68
69#-------------------------------------------------------------
70print "\n Welcome to GSSAPI.pm setup! \n\n ($0 Version 0.03) \n";
71print qq{\n run "perl Makefile.PL --help" to see further installation options\n};
72
73#---------------------------------------------------------------
74my @GSSLIBS = ();
75my @LDDLFLAGS = ();
76my $incconf = '';
77my @EXTRADEFINES;
78#---------------------------------------------------------------
79
80if (exists $options{gssapi_libs} || exists $options{gssapi_inc} || exists $options{gssapi_lddlflags} ) {
81    if ($options{gssapi_libs}) {
82	push @GSSLIBS, $options{gssapi_libs}
83    } else {
84	die 'if options gssapi_inc or gssapi_lddlflags are provided, then gssapi_libs must be as well';
85    }
86    if ($options{gssapi_inc}) {
87	$incconf = $options{gssapi_inc}
88    } else {
89	die 'if options gssapi_libs or gssapi_lddlflags are provided, then gssapi_inc must be as well';
90    }
91    if ($options{gssapi_lddlflags}) {
92	if ( $Config{lddlflags} ) {
93	    print "$LINE Adding from your Perlinstallation (\$Config{lddlflags}) to LDDLFLAGS \n",
94	          $Config{lddlflags};
95        }
96	push @LDDLFLAGS, 'LDDLFLAGS',
97	                 join ' ', $Config{lddlflags}, $options{gssapi_lddlflags};
98    }
99} else {
100    print $LINE, ' Searching krb5-config command... ';
101    my $krb5cmd = find_krb5config_cmd($options{'gssapiimpl'} );
102    unless ($krb5cmd) {
103	print 'NOT FOUND!';
104        print "\n\n seems this is a missing prerequirement.",
105              "\n The README file shipped with this module provides\n more information regarding prerequirements. \n\n";
106        exit 0; # send no automated FAIL testreport
107    } else {
108      print "\n\n using krb5-config command '$krb5cmd'.";
109    }
110    #---------------------------------------------
111    my $implementation = krb5_version( $krb5cmd  );
112    print $LINE, " using GSSAPI implementation \n $implementation";
113    #---------------------------------------------
114    my $libconf =  krb5_libconfig( $krb5cmd );
115    unless ($libconf) {
116       die "$krb5cmd does not respond libconf!";
117    } else {
118      if ($libconf =~ /Unknown/ && $implementation =~ /Solaris Kerberos/) {
119            $libconf = "-L/usr/lib -R/usr/lib -lgss";
120      }
121
122      my ($gsslibs, $otherparm) = find_libs_in_krb5config_string( $libconf  );
123
124      #
125      # LIBS accepts only -L and -l flags and ignores others.
126      # but we need them at linktime!
127      # so all the output of krb5-config --libs gssapi
128      # has to be passed into LDDLFLAGS,
129      # und only -L and -l params to LIBS (to avoid warnings)
130      # <http://sourceforge.net/mailarchive/forum.php?thread_id=9655729&forum_id=47637>
131      #
132      if ( @{$otherparm} > 0 ) {
133         my $lddflagstring = join ' ', $Config{lddlflags},  @{$otherparm};
134	 if ( $Config{lddlflags} ) {
135	    print $LINE,
136	          ' Adding from your Perlinstallation ($Config{lddlflags}) to LDDLFLAGS', "\n\n ",
137	          $Config{lddlflags};
138         }
139         print $LINE, " Bypassing to LDDLFLAGS \n\n $lddflagstring";
140         push @LDDLFLAGS, 'LDDLFLAGS', $lddflagstring ;
141      }
142      #--------------------------------------
143      push @GSSLIBS,  join ' ', @{$gsslibs};
144    }
145
146    #---------------------------------------------------------------
147    $incconf =  krb5_cflags( $krb5cmd  );
148    unless ( $incconf ) {
149       #
150       # krb5-conf does not respond -I/usr/include
151       # on Fedora and RHL.
152       # Thanks to Dax Kelson <dax@gurulabs.com>
153       #
154       $incconf = '-I/usr/include';
155    }
156    if ($incconf =~ /Unknown/ && $implementation =~ /Solaris Kerberos/) {
157          $incconf = "-I/usr/include/kerberosv5";
158          push @EXTRADEFINES,  '-DSEAM';
159    }
160    #---------------------------------------------------------------
161    if ( is_heimdal($krb5cmd) ) {
162       push @EXTRADEFINES,  '-DHEIMDAL';
163    }
164
165    if ( is_mit_1_2($krb5cmd) ) {
166        #
167        # activate Workaround to support
168        # MIT Kerberos 1.2.x
169        # (constants in old lowercase-style)
170        #
171        push @EXTRADEFINES,  '-DMITKERB12';
172    }
173}
174
175#--------------------------------------------------------------
176print "$LINE Adding own DEFINEs \n\n @EXTRADEFINES" if( scalar(@EXTRADEFINES) );
177print "$LINE Using LIBS\n\n @GSSLIBS",
178      "$LINE Using INC includeconfiguration\n\n $incconf",
179      $LINE;
180#--------------------------------------------------------------
181
182
183WriteMakefile(
184    'AUTHOR'            => 'Achim Grolms <perl@grolmsnet.de>',
185    'ABSTRACT_FROM'     => 'GSSAPI.pm',
186    'LICENSE'           => 'perl',
187    'LIBS'              => join (' ', @GSSLIBS),
188    'NAME'		=> 'GSSAPI',
189    'VERSION_FROM'	=> 'GSSAPI.pm',
190#    'CCFLAGS'           => '-Wall',
191    'PREREQ_PM'		=> { 'Test::More' => 0 },
192    @LDDLFLAGS,
193    'DEFINE'            => join (' ', @EXTRADEFINES),
194    'INC'               => $incconf,
195    'macro'		=> { OTHER_XS => $otherxs },
196    'depend'		=> { 'GSSAPI.c' => '$(OTHER_XS)' }
197);
198
199#--------------------------------------------------------------
200#-------------------------------------------------
201sub find_which_command {
202    foreach (@whichcand) {
203       return $_ if ( -e $_);
204    }
205    return undef;
206}
207#-------------------------------------------------
208sub find_krb5config_cmd {
209   my ($expl_path) = @_;
210   my $r = undef;
211   unless ($expl_path) {
212      #my $whichcmd =  find_which_command() || die 'cannot locate which command';
213      $r = '/usr/local/bin/krb5-config';
214
215      chomp $r;
216      unless ( $r ) {
217          my $n = 1;
218          print "\n krb5-config NOT found in \$PATH... now doing some guesswork: \n";
219          foreach $r ( @KRB5_CONFIG_TRIES ) {
220              print "\n $n. trying $r ...";
221              if ( -e $r ) {
222                  print 'found.';
223                  return $r;
224              }
225              else {
226                 print 'not found.';
227              }
228              $n++;
229          }
230      }
231   } else {
232      my $supposed = join '/', $expl_path, 'bin', 'krb5-config';
233      if ( -e $supposed ) {
234         $r = $supposed ;
235      }
236   }
237   return $r;
238}
239#-------------------------------------------------
240sub krb5_libconfig {
241   my ($cfgcmd) = @_;
242   $cfgcmd || die 'no $cfgcmd ';
243   return `$cfgcmd --libs gssapi`;
244}
245#-------------------------------------------------
246#-------------------------------------------------
247sub krb5_cflags  {
248   my ($cfgcmd) = @_;
249   $cfgcmd || die 'no $cfgcmd ';
250   return `$cfgcmd --cflags gssapi`;
251}
252#-------------------------------------------------
253sub krb5_version {
254   my ($cfgcmd) = @_;
255   $cfgcmd || die 'no $cfgcmd ';
256   return `$cfgcmd --version`;
257}
258#-------------------------------------------------
259#-------------------------------------------------
260sub is_heimdal {
261   my ($cfgcmd) = @_;
262   my $r = undef;
263   my @vinfo = krb5_version( $cfgcmd );
264   FOUND: {
265      foreach ( @vinfo) {
266         if ( m/eimdal/) {
267            $r = 1;
268	    last FOUND;
269         }
270       }
271   }
272   return $r;
273}
274#-------------------------------------------------
275sub is_mit_1_2 {
276   my ($cfgcmd) = @_;
277   my $r = undef;
278   my @vinfo = krb5_version( $cfgcmd );
279   FOUND: {
280      foreach ( @vinfo) {
281         if ( m/Kerberos 5 release 1\.2/ && !m/Solaris Kerberos/) {
282            $r = 1;
283	    last FOUND;
284         }
285       }
286   }
287   return $r;
288}
289#-------------------------------------------------
290
291sub find_libs_in_krb5config_string {
292   my ( $confstringstring ) = @_;
293   my (@libs, @others);
294   foreach ( split ' ',  $confstringstring ) {
295      #if ( m/(-(Wl,-R|[LlR])[^ ]*)/) {
296      if ( m/(^-(Wl,-R|[LlR])[^ ]*)/) {
297        push @libs, $1
298      } else {
299        push @others, $_;
300      }
301   }
302   return (\@libs, \@others);
303}
304#-------------------------------------------------
305
306