4 use warnings qw( all );
12 use base 'Module::Build' ;
14 $ENV{HARNESS_DEBUG} = 1 ;
15 $ENV{HARNESS_VERBOSE} = 1 ;
17 # this is the common env values to control running stem stuff in the
21 'PATH=blib/bin:blib/demo:$PATH PERL5LIB=blib/lib STEM_CONF_PATH=conf' ;
24 PATH => "blib/bin:blib/demo:$ENV{PATH}",
25 PERL5LIB => 'blib/lib',
26 STEM_CONF_PATH => 'conf',
29 local( @ENV{ keys %env } ) = values %env ;
32 my ( @manifest_lines ) ;
35 require Stem::InstallConfig
37 my $conf = \%Stem::InstallConfig::Config ;
39 my $is_win32 = ( $^O =~ /Win32/) ? 1 : 0 ;
41 my $default_stem_path = $is_win32 ?
44 File::Spec->rootdir, qw( usr local stem ) ) ;
46 my $default_conf_path = File::Spec->catfile( $default_stem_path, 'conf' ) ;
47 #my $default_tail_dir = File::Spec->catfile( File::Spec->tmpdir, 'stem_tail' );
50 bin_path => $Config{bin},
51 run_stem_path => File::Spec->catfile( $Config{bin}, 'run_stem' ),
52 perl_path => $Config{perlpath},
53 conf_path => $default_conf_path,
54 prefix => $Config{prefix},
55 # tail_dir => $default_tail_dir,
56 build_demos => ! $is_win32,
57 install_demos => ! $is_win32,
58 install_ssfe => ! $is_win32,
63 # these are the top level action handlers. ACTION_foo gets called when you do
64 # 'Build foo' on the command line
71 $self->query_for_config() ;
73 $self->SUPER::ACTION_build() ;
75 # $self->build_bin() ;
82 local( @ENV{ keys %env } ) = values %env ;
84 $self->depends_on('build');
86 $self->SUPER::ACTION_test() ;
93 $self->install_config_files() ;
94 # $self->install_ssfe() ;
96 $self->SUPER::ACTION_install() ;
103 $self->depends_on('build');
105 my $run_cmd = $self->{'args'}{'cmd'} || '' ;
107 $run_cmd or die "Missing cmd=name argument" ;
109 my $cmd = "$env $run_cmd" ;
110 # print "CMD: $cmd\n" ;
115 sub ACTION_run_stem {
119 $self->depends_on('build');
121 my $conf = $self->{'args'}{'conf'} || '' ;
123 $conf or die "Missing conf=name argument" ;
125 my $cmd = "$env run_stem $conf" ;
126 # print "DEMO: $cmd\n" ;
136 $self->depends_on('build');
138 my $cmd = "$env $self->{action}_demo" ;
139 print "DEMO: $cmd\n" ;
153 *ACTION_chat = \&run_demo ;
154 *ACTION_chat2 = \&run_demo ;
155 *ACTION_inetd = \&run_demo ;
157 sub ACTION_update_pod {
161 my @manifest_sublist = $self->grep_manifest( qr/\.pm$/ ) ;
163 @manifest_sublist = grep /Codec/, @manifest_sublist ;
165 print join( "\n", @manifest_sublist ), "\n" ;
167 system( "bin/spec2pod.pl @manifest_sublist" ) ;
172 # grep through all matched files
174 # files=<regex> (default is all .pm files)
181 my $args = $self->{'args'} ;
183 my $file_regex = $args->{ files } || qr/\.pm$/ ;
184 my $grep_regex = $args->{ re } or die "need grep regex" ;
186 my @manifest_sublist = $self->grep_manifest( $file_regex ) ;
188 local( @ARGV ) = @manifest_sublist ;
192 next unless /$grep_regex/ ;
204 # ACTION: grep through MANIFEST
208 # do we need this action?
211 sub ACTION_grep_manifest {
215 my @manifest_sublist = $self->grep_manifest() ;
217 print join( "\n", @manifest_sublist ), "\n" ;
221 # ACTION: count source lines
223 # files=<regex> (defaults to all .pm and bin files
225 # do we need this action?
231 my $args = $self->{'args'} ;
232 my $file_regex = $args->{ files } || qr/\.pm$|^bin/ ;
234 my @manifest_sublist = $self->grep_manifest( $file_regex ) ;
236 system( "./util/lines @manifest_sublist" ) ;
241 # build a distro and scp to stemsystems.com
247 my $dist_tar = $self->dist_dir() . '.tar.gz' ;
251 $self->ACTION_dist() ;
253 system "scp $dist_tar stemsystems.com:www/" ;
257 # this sub overrides the find_test_files method in Module::Build
259 sub find_test_files {
263 my $test_args = $self->{ args }{ tests } ;
265 my @tests = $test_args ? split( ':', $test_args ) :
266 $self->grep_manifest( qr/\.t$/ ) ;
271 sub process_script_files {
274 my @scripts = $self->grep_manifest( qr{^bin/} ) ;
276 #print "SCR @scripts\n" ;
277 foreach my $file ( @scripts ) {
279 my $bin_dir = File::Spec->catdir(
281 $file =~ /_demo$/ ? 'demo' : 'bin' ) ;
283 File::Path::mkpath( $bin_dir );
285 my $result = $self->copy_if_modified(
286 $file, $bin_dir, 'flatten') or next;
288 #print "COPY $file\n" ;
289 $self->fix_run_stem($result);
290 $self->fix_demos($result);
291 $self->fix_shebang_line($result);
292 $self->make_executable($result);
298 my( $self, $file ) = @_ ;
300 return unless $file =~ m{/run_stem$} ;
302 my $text = read_file( $file ) ;
304 $text =~ s/'conf:.'/'$conf->{'conf_path'}'/ if $conf->{'conf_path'} ;
306 write_file( $file, $text ) ;
311 my( $self, $file ) = @_ ;
313 return unless $file =~ /_demo$/ ;
315 my $text = read_file( $file ) ;
317 $conf->{xterm_path} ||= 'NOT FOUND' ;
318 $conf->{telnet_path} ||= 'NOT FOUND' ;
320 $text =~ s[xterm][$conf->{xterm_path}]g;
321 $text =~ s[telnet][$conf->{telnet_path}]g;
323 write_file( $file, $text ) ;
326 # MANIFEST helper subs
330 my( $self, $file_regex ) = @_ ;
332 $file_regex ||= $self->{ args }{ files } || qr/.*/ ;
336 return grep( /$file_regex/, @manifest_lines ) ;
341 return if @manifest_lines ;
343 @manifest_lines = grep ! /^\s*$|^\s*#/, read_file( 'MANIFEST' ) ;
345 chomp @manifest_lines ;
350 #################################
352 sub query_for_config {
356 return if $defaults{ 'config_done' } ;
362 This script will ask you various questions in order to properly
363 configure, build and install Stem on your system. Whenever a question
364 is asked, the default answer will be shown inside [brackets].
365 Pressing enter will accept the default answer. If a choice needs to be
366 made from a list of values, that list will be inside (parentheses).
368 If you have already configured Stem in a previous build, you can put
369 use_defaults=1 on the Build command line and you won't be prompted for
370 any answers and the previous settings will be used.
372 If you want to force a new build, run Build clean.
376 $self->get_path_config() ;
377 $self->get_demo_config() ;
379 $defaults{ 'config_done' } = 1 ;
381 $self->write_config_pm() ;
385 my $package = 'Stem::InstallConfig' ;
389 return File::Spec->catfile(
390 File::Spec->curdir, 'lib', split( /::/, $package) ) . '.pm' ;
394 sub write_config_pm {
398 my $config = Data::Dumper->Dump(
400 ["*${package}::Config"]
403 my $conf_pm_file = $self->config_pm_path() ;
405 $self->add_to_cleanup( $conf_pm_file ) ;
407 write_file( $conf_pm_file, <<EOT ) ;
410 # this file is generated by running Build build
421 sub get_path_config {
425 # $self->query_config_value( <<'EOT', 'perl_path' );
427 # Stem has several executable Perl programs and demonstration scripts
428 # and they need to have the correct path to your perl binary.
430 # What is the path to perl?
433 # $self->query_config_value( <<'EOT', 'bin_path' );
435 # Those Stem executables need to be installed in a directory that is in your
436 # shell $PATH variable.
438 # What directory will have the Stem executables?
441 $self->query_config_value( <<'EOT', 'conf_path' );
443 Stem configuration files are used to create and initialize Stem Cells
444 (objects). Stem needs to know the list of directories to search to
445 find its configurations files.
447 Note that the default has a single absolute path. You can test Stem
448 configurations easily setting this path when executing run_stem. You
449 can override or modify the path time with either a shell environment
450 variable or on the command line of run_stem. See the documentation on
451 run_stem for how so do this.
453 The first directory in the list is where the standard Stem
454 configuration files will be installed.
456 Enter a list of absolute directory paths separated by ':'.
458 What directories do you want to search for Stem configuration files?
464 sub get_demo_config {
468 # don't even bother if win32
470 return if $is_win32 ;
472 # $self->get_config_boolean( <<'EOT', 'build_demos' );
474 # Stem comes with several demonstration scripts. After building them,
475 # they can be run from the main directory by the Build script: ./Build
476 # chat, Build inetd, etc. Do you want to build the demos?
479 # return unless $defaults{build_demos};
481 # all the demos need xterm
483 $self->get_xterm_path();
484 $self->get_telnet_path();
485 return unless -x $defaults{xterm_path} && -x $defaults{telnet_path};
487 # $self->query_config_value( <<'EOT', 'tail_dir' );
489 # The tail demo script needs a temporary working directory. Enter the
490 # path to a directory to use for this purpose. If it does not exist,
491 # this directory will be created.
494 $self->get_config_boolean( <<'EOT', 'install_ssfe' );
496 ssfe (Split Screen Front End) is a compiled program optionally used by
497 the Stem demonstration scripts that provides a full screen interface
498 with command line editing and history. It is not required to run Stem
499 but it makes the demonstrations easier to work with and they look much
500 nicer. To use ssfe add the '-s' option when you run any demonstration
501 script. You can also use ssfe for your own programs. Install ssfe in
502 some place in your \$PATH ($conf->{'bin_path'} is where Stem executables
503 are being installed) so it can be used by the demo scripts. The ssfe
504 install script will do this for you or you can do it manually after
507 Do you want to install ssfe?
518 # unless ( $xterm_path = which_exec( 'xterm' ) ) {
520 # foreach my $path ( qw(
521 # /usr/openwin/bin/xterm
523 # /usr/X11R6/bin/xterm ) ) {
525 # next unless -x $path;
526 # $xterm_path = $path ;
531 # if ( $xterm_path ) {
533 # $defaults{'xterm_path'} = $xterm_path ;
534 # print "xterm was found at '$xterm_path'\n";
538 $self->query_config_value( <<"EOT", 'xterm_path' );
540 xterm was not found on this system. you can't run the demo programs
541 without xterm. Make sure you enter a valid path to xterm or some other
544 NOTE: If you don't have an xterm, you can still run the demo scripts
545 by hand. Run a *_demo script and see what commands it issues. Take the
546 part after the -e and run that command in its own terminal window.
548 Enter the path to xterm (or another compatible terminal emulator)
553 sub get_telnet_path {
559 unless ( $telnet_path = which_exec( 'telnet' ) ) {
561 # enter a list of common places to find telnet. or delete this as it
562 # will almost always be in the path
564 foreach my $path ( qw( ) ) {
566 next unless -x $path;
567 $telnet_path = $path ;
572 if ( $telnet_path ) {
574 $defaults{'telnet_path'} = $telnet_path ;
575 print "telnet was found at '$telnet_path'\n";
579 $self->query_config_value( <<"EOT", 'telnet_path' );
581 telnet was not found on this system. you can't run the demo programs
582 without telnet. Make sure you enter a valid path to telnet or some other
585 NOTE: If you don't have an telnet, you can still run the demo scripts
586 by hand. Run a *_demo script and see what telnet commands it
587 issues. The run those telnet commands using your telnet or another
590 Enter the path to telnet (or another compatible terminal emulator)
595 sub install_config_files {
599 my ( $conf_path ) = split /:/, $conf->{conf_path} ;
601 mkpath( $conf_path, 1, 0755 ) unless -d $conf_path ;
603 my @config_files = $self->grep_manifest( qr{^conf/.+\.stem$} ) ;
605 foreach my $conf_file (@config_files) {
607 $conf_file =~ s{conf/}{} ;
609 my $out_file = File::Spec->catfile( $conf_path, $conf_file );
611 print "Installing config file: $out_file\n";
613 my $in_file = File::Spec->catfile(
614 File::Spec->curdir(), 'conf', $conf_file );
616 my $conf_text = read_file($in_file);
618 if ( $conf_file eq 'inetd.stem' ) {
620 my $quote_serve = File::Spec->catfile(
621 $conf->{bin_path}, 'quote_serve' );
623 $conf_text =~ s[path\s+=>\s+'bin/quote_serve',]
624 [path\t\t=> '$quote_serve',];
626 # elsif ( $conf eq 'monitor.stem' || $conf eq 'archive.stem' ) {
628 # $conf_text =~ s[path'\s+=>\s+'tail]
629 # [path'\t\t=> '$conf->{tail_dir}]g ;
632 write_file( $out_file, $conf_text );
641 return unless $conf->{install_stem_demos} &&
642 $conf->{install_ssfe} ;
648 This is not a Stem install script and it will ask its own
649 questions. It will execute in its own xterm (whatever was configured
650 earlier) to keep this install's output clean. The xterm is kept open
651 with a long sleep call and can be exited by typing ^C.
660 xterm -e /bin/sh -c 'chdir extras ;
661 tar zxvf sirc-2.211.tar.gz ;
667 print "\nInstallation of ssfe is done\n\n";
670 #########################################################
671 # this sub builds the exec scripts in bin and puts them into blib/bin
672 # for local running or later installation
676 # my ( $self ) = @_ ;
678 # my @bin_scripts = $self->grep_manifest( qr{^bin/} ) ;
680 # foreach my $bin_file ( @bin_scripts ) {
682 # #print "BIN $bin_file\n" ;
684 # my $bin_text = read_file( $bin_file ) ;
686 # $bin_file =~ s{bin/}{} ;
688 # # fix the shebang line
690 # $bin_text =~ s{/usr/local/bin/perl}{$conf->{'perl_path'}} ;
694 # if ( $bin_file =~ /_demo$/ ) {
696 # next unless $conf->{build_demos} ;
698 # $bin_dir = 'demo' ;
700 # # fix the location of xterms in the demo scripts
702 # $bin_text =~ s[xterm][$conf->{xterm_path}]g;
703 # $bin_text =~ s[telnet][$conf->{telnet_path}]g;
705 # # fix the default config search path in run_stem
711 # # fix the default config search path in run_stem
713 # if ( $bin_file eq 'run_stem' ) {
715 # s/'conf:.'/'$conf->{'conf_path'}'/ ;
719 # # elsif ( $bin_file eq 'tail_demo' ) {
720 # # $bin_text =~ s['tail']['$conf->{tail_dir}'];
723 # # write the built script into the blib/ dir
725 # my $out_file = File::Spec->catfile( 'blib',
730 # mkdir "blib/$bin_dir" ;
731 # print "Building executable script: $out_file\n";
732 # write_file( $out_file, $bin_text );
733 # chmod 0755, $out_file;
737 #############################################################
739 # this sub searches the path for the locations of an executable
745 foreach my $path_dir ( split /[:;]/, $ENV{PATH} ) {
747 my $exec_path = File::Spec->catfile( $path_dir, $exec );
748 return $exec_path if -x $exec_path ;
754 # the sub searches a list of dir paths to find the first one that
755 # exists with a prefix dir
757 # UNUSED FOR THE MOMENT
761 # my ( $prefix, @dirs ) = @_;
763 # foreach my $subdir ( @dirs ) {
765 # my $dir = File::Spec->catfile( $prefix, $subdir );
766 # return $dir if -x $dir;
772 #############################################################
774 # these subs handle querying for a user answer. it uses the key to
775 # find a current value in the defaults and prompt for another value
776 # if 'use_defaults' is set on the command line, then no prompting will be done
778 sub query_config_value {
780 my( $self, $query, $key ) = @_ ;
782 my $default = $self->{args}{$key} ;
784 $default = $defaults{ $key } unless defined $default ;
786 $defaults{ $key } = ( $self->{args}{use_defaults} ) ?
788 $self->prompt( edit_query( $query, $default ), $default ) ;
791 sub get_config_boolean {
793 my( $self, $query, $key ) = @_ ;
795 my $default = $self->{args}{$key} ;
797 $default = $defaults{ $key } unless defined $default ;
798 $default =~ tr/01/ny/ ;
800 $defaults{ $key } = ( $self->{args}{use_defaults} ) ?
802 $self->y_n( edit_query( $query, $default ), $default ) ;
807 my ( $query, $default ) = @_ ;
813 my $last_line = (split /\n/, $query)[-1] ;
815 if ( length( $last_line ) + 2 * length( $default ) > 70 ) {
823 # low level file i/o subs. should be replaced with File::Slurp. stem
824 # should depend on it
829 my ( $file_name ) = @_ ;
833 open( FH, $file_name ) || croak "Can't open $file_name $!";
835 return <FH> if wantarray;
837 read FH, my $buf, -s FH;
843 my( $file_name ) = shift ;
847 open( FH, ">$file_name" ) || croak "can't create $file_name $!" ;