1#!/usr/bin/perl 2##!~_~perlpath~_~ 3# 4# Interchange catalog configurator 5# 6# $Id: makecat.PL,v 2.27 2007-08-09 13:40:57 pajamian Exp $ 7# 8# Copyright (C) 2002-2007 Interchange Development Group 9# Copyright (C) 1996-2002 Red Hat, Inc. 10# 11# This program is free software; you can redistribute it and/or modify 12# it under the terms of the GNU General Public License as published by 13# the Free Software Foundation; either version 2 of the License, or 14# (at your option) any later version. 15# 16# This program is distributed in the hope that it will be useful, 17# but WITHOUT ANY WARRANTY; without even the implied warranty of 18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19# GNU General Public License for more details. 20# 21# You should have received a copy of the GNU General Public 22# License along with this program; if not, write to the Free 23# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, 24# MA 02110-1301 USA. 25 26use lib '/usr/local/interchange/lib'; 27#use lib '~_~INSTALLPRIVLIB~_~'; 28use lib '/usr/local/interchange'; 29#use lib '~_~INSTALLARCHLIB~_~'; 30 31#use strict; 32use Config; 33use File::Find; 34use File::Copy; 35use File::Path; 36use Sys::Hostname; 37use Vend::MakeCat; 38use Vend::Util; 39use Getopt::Long; 40use IniConf; 41use Cwd; 42use vars qw/$CGIwrap/; 43 44Getopt::Long::config(qw/permute/); 45#Getopt::Long::config(qw/debug/); 46 47BEGIN { 48 49 ($Global::VendRoot = $ENV{MINIVEND_ROOT}) 50 if defined $ENV{MINIVEND_ROOT}; 51 $Global::VendRoot = $Global::VendRoot || '/usr/local/interchange'; 52# $Global::VendRoot = $Global::VendRoot || '~_~INSTALLARCHLIB~_~'; 53 54 $Global::ProgRoot = '/usr/local/interchange'; 55# $Global::ProgRoot = '~_~INSTALLARCHLIB~_~'; 56 57 if(-f "$Global::VendRoot/interchange.cfg") { 58 $Global::ExeName = 'interchange'; 59 $Global::ConfigFile = 'interchange.cfg'; 60 } 61 elsif(-f "$Global::VendRoot/minivend.cfg") { 62 $Global::ExeName = 'minivend'; 63 $Global::ConfigFile = 'minivend.cfg'; 64 } 65 else { 66 $Global::ExeName = 'interchange'; 67 $Global::ConfigFile = 'interchange.cfg'; 68 } 69 70} 71 72### END CONFIGURATION VARIABLES 73 74$| = 1; select STDERR; 75$| = 1; select STDOUT; 76 77my $Removeconfig; 78my $Reconfigure = 0; 79my $Configfile; 80my $Cfg; 81my $Logfile = 'makecat.log'; 82my $catalog_name; 83use vars qw( %Conf ); 84my $Inetmode; 85my $Windows; 86my $pid; 87$Windows = 1 if $Config{osname} =~ /win32/i; 88 89 90my $USAGE = <<EOF; 91usage: $0 [options] [catalogname] 92 93options: 94 95 -F Force make of catalog with defaults 96 -c Configuration file (default is etc/makecat.cfg) 97 -l File to log to (default makecat.log) 98 -r Reconfigure defaults 99 100 [catalogname] must contain alphanumerics and hyphens only. 101 102 Defaults: 103 --basedir=directory Base directory for catalogs 104 --cgibase=url_fragment Base URL for link programs 105 --documentroot=directory The directory where HTML is based 106 --interchangegroup=group The default group files should be owned by 107 --interchangeuser=username The user ID which runs Interchange 108 --serverconf=filename Location of httpd.conf 109 --vendroot=filename Location of Interchange software 110 --homedir=directory Use instead of \$HOME to set defaults 111 112 Required: 113 --catroot=directory Directory where Interchange catalog files go 114 --cgidir=directory The directory the CGI link should go to 115 --servername=server Name of server (www.whatever.domain) 116 --cgiurl=url_fragment The path to the CGI link (no server name) 117 --demotype=template The template catalog (standard is the default) 118 --mailorderto=email Email address to send orders 119 120 Optional: 121 --catalogconf=file Specify separate configuration file for catalogs 122 --catuser=username The user files should be owned by (if root) 123 --sharedir=directory The directory where shared admin images go 124 --shareurl=url The URL to prefix shared admin images with 125 --imagedir=directory The directory where template images go 126 --imageurl=url The URL to prefix images with 127 --linkmode=mode UNIX or INET (link program vlink or tlink) 128 --linkprogram=file Use file as link program instead of vlink/tlink 129 --nocfg Don't add to $Global::ConfigFile 130 --nocopy Don't actually copy the files, just test 131 --norunning Don't add to running server 132 --noumask Don't set umask 133 --permtype=[M|G|U] Set permission type (Multi, Group, User) 134 --reference Return hash of config as string 135 (sets -F, no write) 136 --relocate=dir Directory to relocate files to (for RPM and such) 137 --samplehtml=directory The directory where template HTML goes 138 --sampleurl=url URL to access HTML for catalog 139 140EOF 141 142if (scalar @ARGV > 1) { 143 my %optctl = ( 144 'F' => \$Vend::MakeCat::Force, 145 'aliases' => \$Conf{aliases}, 146 'basedir' => \$Conf{basedir}, 147 'catalogconf' => \$Conf{catalogconf}, 148 'catalogname' => \$catalog_name, 149 'catroot' => \$Conf{catroot}, 150 'catuser' => \$Conf{catuser}, 151 'cgibase' => \$Conf{cgibase}, 152 'cgidir' => \$Conf{cgidir}, 153 'cgiurl' => \$Conf{cgiurl}, 154 'configfile' => \$Global::ConfigFile, 155 'demotype' => \$Conf{demotype}, 156 'documentroot' => \$Conf{documentroot}, 157 'c' => \$Configfile, 158 'homedir' => \$Conf{homedir}, 159 'imagedir' => \$Conf{imagedir}, 160 'imageurl' => \$Conf{imageurl}, 161 'l' => \$Logfile, 162 'linkmode' => \$Conf{linkmode}, 163 'linkhost' => \$Conf{linkhost}, 164 'linkport' => \$Conf{linkport}, 165 'linkprogram' => \$Conf{linkprogram}, 166 'mailorderto' => \$Conf{mailorderto}, 167 'interchangegroup' => \$Conf{interchangegroup}, 168 'interchangeuser' => \$Conf{interchangeuser}, 169 'nocfg' => \$Conf{nocfg}, 170 'nocopy' => \$Conf{nocopy}, 171 'norunning' => \$Conf{norunning}, 172 'noumask' => \$Conf{noumask}, 173 'permtype' => \$Conf{permtype}, 174 'r' => \$Reconfigure, 175 'reference' => \$Conf{reference}, 176 'relocate' => \$Conf{relocate}, 177 'samplehtml' => \$Conf{samplehtml}, 178 'sampleurl' => \$Conf{sampleurl}, 179 'sharedir' => \$Conf{sharedir}, 180 'shareurl' => \$Conf{shareurl}, 181 'serverconf' => \$Conf{serverconf}, 182 'servername' => \$Conf{servername}, 183 'linkfile' => \$Conf{linkfile}, 184 'vendroot' => \$Conf{vendroot}, 185 '<>' => sub { 186 my $arg = shift; 187 return unless $arg =~ /=/; 188 my ($opt, $val) = split /=/, $arg, 2; 189 $opt = lc $opt; 190 die "Can't set \U$opt\E twice.\n$USAGE\n" 191 if defined $Conf{$opt}; 192 $Conf{$opt} = $val; 193 return; 194 }, 195 ); 196 197 my @options = ( qw/ 198 F 199 aliases=s 200 basedir|base=s 201 catalogconf=s 202 catalogname|name=s 203 catroot|dir=s 204 catuser|user=s 205 cgibase=s 206 cgidir=s 207 cgiurl|script=s 208 configfile=s 209 demotype|template=s 210 documentroot=s 211 c=s 212 homedir=s 213 imagedir=s 214 imageurl=s 215 l=s 216 linkmode=s 217 linkfile=s 218 linkhost=s 219 linkport=s 220 linkprogram=s 221 mailorderto=s 222 interchangegroup|minivendgroup|group=s 223 interchangeuser|minivenduser|mvuser=s 224 nocfg 225 nocopy 226 norunning 227 permtype=s 228 r 229 reference 230 relocate=s 231 samplehtml|html=s 232 sampleurl=s 233 serverconf|conf=s 234 servername|server=s 235 sharedir=s 236 shareurl:s 237 vendroot|mvdir=s 238 <> 239 /); 240 241 GetOptions(\%optctl, @options) or die "\n$USAGE\n"; 242} 243elsif ($ARGV[0] =~ /^(--help|-h(elp)?)$/i) { 244 die "\n$USAGE\n"; 245} 246 247$catalog_name = shift unless $catalog_name; 248if(@ARGV) { 249 die <<EOF . "\n"; 250Extra command line arguments were found. (Did you specify 251both --catalogname=name and one on the command line?) 252 253$USAGE 254EOF 255} 256 257unless($catalog_name) { 258 die "$USAGE\n" if $Vend::MakeCat::Force; 259 print <<EOF; 260 261Select a short, mnemonic name for the catalog. This will be 262used to set the defaults for naming the catalog, executable, 263and directory, so you will have to type in this name frequently. 264 265NOTE: This will be the name of 'vlink' or 'tlink', the link CGI 266program. Depending on your CGI setup, it may also have the 267extension .cgi added. 268 269Only the characters [-a-zA-Z0-9_] are allowed, and it is strongly suggested 270that the catalog name be all lower case. 271 272If you are doing the demo for the first time, you might use "standard". 273 274EOF 275 $catalog_name = prompt ("Catalog name? "); 276} 277 278die "$catalog_name -- $USAGE\n" unless $catalog_name =~ /^[-\w]+$/; 279 280if($Conf{homedir}) { 281 die "Directory set with --homedir=$Conf{homedir} is not a directory.\n" 282 unless -d $Conf{homedir}; 283 $ENV{HOME} = $Conf{homedir}; 284} 285 286if($Conf{'reference'}) { 287 $Vend::MakeCat::Force = 288 $Conf{nocopy} = 289 $Conf{norunning} = 290 $Conf{nocfg} = 1; 291 $Logfile = $Windows ? 'nul:' : '/dev/null'; 292} 293 294if ($Vend::MakeCat::Force) { 295 my $file = $Logfile || 'makecat.log'; 296 open(LOGOUT, ">>$file") or die "write $file: $!\n"; 297 select LOGOUT; 298} 299 300$Configfile = "$Global::VendRoot/etc/makecat.cfg" unless $Configfile; 301my $Servername; 302my $Servers; 303my $Done_defaults; 304 305print <<EOF; 306makecat -- Interchange catalog installation program. 307 308*** We will be making a catalog named '$catalog_name'. *** 309 310EOF 311 312READCONFIG: { 313 my $cfgfile = "etc/$catalog_name.makecat.cfg"; 314 315 last READCONFIG unless -f $cfgfile; 316 open(READCONFIG, "< $cfgfile") or die "read $cfgfile: $!\n"; 317 318 while(<READCONFIG>) { 319 next unless /^\s*[A-Z]\w*\s+\S/; 320 chomp; 321 ($var, $val) = split " ", $_, 2; 322 $ENV{"MVC_$var"} = $val; 323 } 324 close READCONFIG; 325} 326 327my $CgiDefault = prefix('CGIDIR') || undef; 328my $DocrootDefault = prefix('DOCUMENTROOT') || undef; 329 330if ($Windows) { 331 $ENV{HOME} = $ENV{HOME} || $ENV{MINIVEND_ROOT} 332 || prefix('VENDROOT') || ''; 333 $CgiDefault = prefix('CGIDIR') || 'c:/webshare/scripts'; 334 $CgiUrlDefault = prefix('CGIURL') || '/scripts'; 335 $DocrootDefault = prefix('DOCUMENTROOT') || 'c:/webshare/wwwroot'; 336} 337 338$ENV{MVC_ENCRYPTOR} = prefix('ENCRYPTOR') || 'none'; 339 340FINDDOCROOT: { 341 last FINDDOCROOT if defined $DocrootDefault; 342 for(qw/www html web web-public public_html public-html htdocs/) { 343 -d "$ENV{HOME}/$_" and -w _ 344 and $DocrootDefault = "$ENV{HOME}/$_" 345 and last FINDDOCROOT; 346 } 347 348 for( glob("$ENV{HOME}/*html*"), 349 glob("$ENV{HOME}/*www*"), 350 glob("$ENV{HOME}/*web*") 351 ) 352 { 353 -d $_ and -w _ 354 and $DocrootDefault = $_ 355 and last FINDDOCROOT; 356 } 357 358 for( 359 '/home/httpd/html', 360 '/var/www/html', 361 '/usr/local/etc/httpd/htdocs', 362 '/usr/local/apache/htdocs', 363 '/home/httpd/htdocs', 364 glob("/*/httpd/*docs"), 365 glob("/*web*/*docs"), 366 glob("/*/ns-home/docs"), 367 glob("/export/*/ns-home/http*/docs"), 368 glob("/usr/*/ns-home/http*/docs"), 369 glob("/home/*/ns-home/http*/docs") 370 ) 371 { 372 -d $_ and -w _ 373 and $DocrootDefault = $_ 374 and last FINDDOCROOT; 375 } 376 377 $DocrootDefault = ''; 378} 379 380FINDCGIDIR: { 381 last FINDCGIDIR if defined $CgiDefault; 382 for(qw/cgi-bin cgi cgibin web-scripts scripts cgiwrap cgi-wrap/) { 383 -d "$ENV{HOME}/$_" and -w _ 384 and $CgiDefault = "$ENV{HOME}/$_" 385 and $CgiUrlDefault = "/$_" 386 and last FINDCGIDIR; 387 } 388 389 for( glob("$ENV{HOME}/*cgi*"), glob("$ENV{HOME}/*scripts*") ) { 390 -d $_ and -w _ 391 and $CgiDefault = $_ 392 and ($CgiUrlDefault = $_) =~ s:.*/:/: 393 and last FINDCGIDIR; 394 } 395 396 for( 397 '/home/httpd/cgi-bin', 398 '/var/www/cgi-bin', 399 '/usr/local/etc/httpd/cgi-bin', 400 '/usr/local/apache/cgi-bin', 401 glob("/*web*/cgi*"), 402 glob("/*/ns-home/cgi*"), 403 glob("/export/*/ns-home/http*/cgi*"), 404 glob("/usr/*/ns-home/http*/cgi*"), 405 glob("/home/*/ns-home/http*/cgi*"), 406 ) 407 { 408 -d $_ and -w _ 409 and $CgiDefault = $_ 410 and ($CgiUrlDefault = $_) =~ s:.*/:/: 411 and last FINDCGIDIR; 412 } 413 414 $CgiDefault = $CgiUrlDefault = ''; 415} 416 417my $isroot = 0; 418if ($< == 0) { 419 $isroot = 1 unless $Windows or $Conf{relocate}; 420} 421 422$Conf{catalogname} = $catalog_name; 423 424my %Initial; 425 426my %IfRoot = (qw( permtype 1 interchangeuser 1 interchangegroup 1 catuser 1 linkmode 1)); 427 428my %Prefix = ( 429 vendroot => $Global::VendRoot, 430 basedir => sub { 431 return prefix('basedir', 1) if prefix('basedir', 1); 432 return "$Conf{vendroot}/catalogs" 433 if $Windows; 434 return "$ENV{HOME}/catalogs" 435 unless $isroot; 436 return "~/catalogs"; 437 }, 438 interchangeuser => sub { return 'everybody' if $Windows; 439 get_id(); }, 440 interchangegroup=> '', 441 servername => sub { 442 return Sys::Hostname::hostname() || $Config{myhostname}; 443 }, 444 linkmode => 'UNIX', 445 documentroot => $ENV{MVC_DOCUMENTROOT} || $DocrootDefault, 446 cgidir => $ENV{MVC_CGIDIR} || $CgiDefault, 447 cgibase => $ENV{MVC_CGIBASE} || $CgiUrlDefault, 448 demotype => $ENV{MVC_DEMOTYPE} || 'standard', 449 catuser => sub { 450 $ENV{MVC_CATUSER} || 451 ($isroot ? '' : $Conf{'interchangeuser'}) 452 }, 453 mailorderto => 454 sub { return 'webmaster' if $Windows; 455 if($Conf{servername} =~ s:(/~[^/]+)$:: ) { 456 $Tilde = $1; 457 } 458 $Conf{catuser} }, 459 catroot => sub { 460 my $dir = prefix('basedir') . "/" . $catalog_name; 461 return $dir if $Windows; 462 my $userdir = (getpwnam($Conf{catuser}))[7]; 463 $dir =~ s/^\~/$userdir/; 464 return $dir; 465 }, 466 cgiurl => sub { 467 return $ENV{MVC_CGIURL} if $ENV{MVC_CGIURL}; 468 my $url = ''; 469 if ($Conf{cgibase} eq '') { 470 $url = $Tilde if defined $Tilde; 471 $url .= '/' . 472 $catalog_name . 473 '.cgi'; 474 } 475 else { 476 $url .= $Conf{cgibase} . '/' . $catalog_name; 477 } 478 $url; 479 }, 480 imagedir => sub { 481 return $ENV{MVC_IMAGEDIR} if $ENV{MVC_IMAGEDIR}; 482 return prefix('samplehtml') . '/' . 'images' 483 }, 484 imageurl => sub { 485 my $url = ''; 486 return $ENV{MVC_IMAGEURL} if $ENV{MVC_IMAGEURL}; 487 if(defined $Tilde) { 488 $url = $Tilde; 489 } 490 $url .= '/' . $catalog_name . '/' . 'images'; 491 $url; 492 }, 493 samplehtml => sub { 494 return $ENV{MVC_SAMPLEHTML} if $ENV{MVC_SAMPLEHTML}; 495 $Conf{documentroot} . '/' . $catalog_name; 496 }, 497 sharedir => sub { 498 return $ENV{MVC_SHAREDIR} if $ENV{MVC_SHAREDIR}; 499 return prefix('documentroot'); 500 }, 501 shareurl => sub { 502 return $ENV{MVC_SHAREURL} if $ENV{MVC_SHAREURL}; 503 my $url = ''; 504 $url = $Tilde if defined $Tilde; 505 return $url; 506 }, 507 508); 509 510sub strip_trailing_slash { 511 my $url = shift; 512 $url =~ s:[/\s]+$::; 513 return $url; 514} 515 516sub directory_process { 517 my $dir = shift; 518 $dir =~ s:[/\s]+$::; 519 if($Conf{catuser} and $dir =~ /^~/) { 520 my $userdir = ( getpwnam( $Conf{catuser} ) )[7]; 521 $dir =~ s/^~/$userdir/ if $userdir; 522 } 523 return $dir; 524} 525 526my %Postprocess = ( 527 528 cgibase => \&strip_trailing_slash, 529 cgidir => \&strip_trailing_slash, 530 basedir => \&strip_trailing_slash, 531 documentroot => \&directory_process, 532 imagedir => \&directory_process, 533 samplehtml => \&directory_process, 534 catroot => \&directory_process, 535 relocate => \&strip_trailing_slash, 536 shareurl => \&strip_trailing_slash, 537 sharedir => \&strip_trailing_slash, 538 539); 540 541sub sum_it { 542 my ($file) = @_; 543 open(IT, "<$file") 544 or return undef; 545 my $data = ''; 546 $data .= $_ while (<IT>); 547 close IT; 548 return unpack("%32c*", $data); 549} 550 551sub prefix { 552 my ($parm, $nodefault) = @_; 553 $parm = lc $parm; 554 return $Conf{$parm} if $Conf{$parm}; 555 return $ENV{"MVC_\U$parm"} if $ENV{"MVC_\U$parm"}; 556 return undef if $nodefault; 557 if(ref $Prefix{$parm}) { 558 return &{ $Prefix{$parm} }; 559 } 560 else { 561 return $Prefix{$parm}; 562 } 563} 564 565my %History = ( 566 demotype => sub { 567 my @dir; 568 @dir = sort map { s:(.*)/.*:$1:; $_ } glob("*/catalog.cfg"); 569 @dir = grep $_ ne 'standard', @dir; 570 unshift(@dir, 'standard') if -f 'standard/catalog.cfg'; 571 unshift(@dir, 'foundation') 572 if -f 'foundation/catalog.cfg' 573 and $catalog_name =~ /^foundation/; 574 unshift(@dir, 'construct') 575 if -f 'construct/catalog.cfg' 576 and $catalog_name =~ /^construct/; 577 unshift(@dir, 'barry') 578 if -f 'barry/catalog.cfg' 579 and $catalog_name =~ /^barry/; 580 unshift(@dir, 'art') 581 if -f 'art/catalog.cfg' 582 and $catalog_name =~ /^art/; 583 my %seen; 584 @dir = grep !$seen{$_}++, @dir; 585 return @dir; 586 }, 587 588 linkmode => sub { return ('UNIX', 'INET') }, 589 documentroot => sub { 590 if(defined $Servers->{$Servername}) { 591 return $Servers->{$Servername}->{documentroot} 592 if defined $Servers->{$Servername}->{documentroot}; 593 } 594 else { 595 return (@_); 596 } 597 }, 598 599 cgidir => sub { 600 if( defined $Servers->{$Servername} and 601 $Servers->{$Servername}->{scriptalias} 602 ) { 603 my @return; 604 @return = values %{$Servers->{$Servername}{scriptalias}}; 605 unshift @return, $ENV{MVC_CGIDIR} if $ENV{MVC_CGIDIR}; 606 return @return; 607 } 608 return (@_); 609 }, 610 611 cgibase => sub { 612 if(defined $Servers->{$Servername}) { 613 my $ref = $Servers->{$Servername}{scriptalias}; 614 return @_ unless defined $ref; 615 if($Conf{cgidir}) { 616 my ($k,$v); 617 for (keys %$ref) { 618 $k = $_; 619 $v = $ref->{$_}; 620 $v =~ s:[/\s]+$::; 621 next unless $v eq $Conf{cgidir}; 622 $k =~ s:[/\s]+$::; 623 return $k; 624 } 625 } 626 else { 627 return keys %$ref; 628 } 629 } 630 return (@_); 631 }, 632 mailorderto => sub { 633 my(@return) = @_; 634 if(defined $Servers->{$Servername}) { 635 push(@return, $Servers->{$Servername}->{serveradmin}) 636 if defined $Servers->{$Servername}->{serveradmin}; 637 } 638 return @return; 639 }, 640 641 sharedir => sub { 642 my (@return) = @_; 643 if(defined $Servers->{$Servername}) { 644 push (@return, 645 values %{$Servers->{$Servername}->{alias}}) 646 if defined $Servers->{$Servername}->{alias}; 647 } 648 return @return; 649 }, 650 651 shareurl => sub { 652 my (@return) = @_; 653 if(defined $Servers->{$Servername}) { 654 push (@return, 655 keys %{$Servers->{$Servername}->{alias}}) 656 if defined $Servers->{$Servername}->{alias}; 657 } 658 return @return; 659 }, 660 661 imagedir => sub { 662 my (@return) = @_; 663 if(defined $Servers->{$Servername}) { 664 push (@return, 665 values %{$Servers->{$Servername}->{alias}}) 666 if defined $Servers->{$Servername}->{alias}; 667 } 668 return @return; 669 }, 670 671 permtype => sub { 672 my (@return) = @_; 673 push(@return, 'G', 'M', 'U'); 674 return @return; 675 }, 676 677 imageurl => sub { 678 my (@return) = @_; 679 if(defined $Servers->{$Servername}) { 680 push (@return, 681 keys %{$Servers->{$Servername}->{alias}}) 682 if defined $Servers->{$Servername}->{alias}; 683 } 684 return @return; 685 }, 686 687 catuser => sub { 688 return 'everybody' if $Windows; 689 my @return = (@_); 690 my $u; 691 if(defined $Servers->{$Servername}) { 692 $nogood = $Servers->{$Servername}->{'user'} 693 if defined $Servers->{$Servername}->{'user'}; 694 } 695 my @out; 696 while($u = getpwent) { 697 next if $u eq 'root'; 698 next if $u eq $nogood; 699 push(@out, $u); 700 } 701 return (@return, sort @out); 702 }, 703 704 interchangeuser => sub { 705 return 'everybody' if $Windows; 706 my @return = (@_); 707 my $u; 708 if(defined $Servers->{$Servername}) { 709 $nogood = $Servers->{$Servername}->{'user'} 710 if defined $Servers->{$Servername}->{'user'}; 711 } 712 my @out; 713 while($u = getpwent) { 714 next if $u eq 'root'; 715 next if $u eq $nogood; 716 push(@out, $u); 717 } 718 return (@return, sort @out); 719 }, 720 721 interchangegroup => sub { 722 return 'nogroup' if $Windows; 723 my (@return) = @_; 724 my $u; 725 if(defined $Servers->{$Servername}) { 726 $nogood = $Servers->{$Servername}->{'group'} 727 if defined $Servers->{$Servername}->{'group'}; 728 } 729 my @out; 730 while($u = getgrent) { 731 next if $u eq 'root'; 732 next if $u eq $nogood; 733 push(@out, $u); 734 } 735 return (@return, sort @out); 736 }, 737 738); 739 740unless($isroot) { 741 @Prefix{qw(interchangeuser interchangegroup)} = get_ids(); 742 $Prefix{catuser} = $Prefix{interchangeuser}; 743 $Prefix{basedir} = "$ENV{HOME}/catalogs"; 744} 745 746my($ask,$param); 747 748unless (-f $Configfile) { 749 $Removeconfig = 1 if prefix('nocopy'); 750 open(CFGFILE, ">$Configfile") or die "Can't write $Configfile: $!\n"; 751 while(<DATA>) { 752 print CFGFILE $_; 753 } 754 close(CFGFILE) or die "Can't close $Configfile: $!\n"; 755 print "\nNew configuration file '$Configfile'\n" ; 756 $Reconfigure = 1; 757} 758 759$Cfg = new IniConf -file => $Configfile; 760unless ($Cfg) { 761 if (@IniConf::errors) { 762 print join("\n", @IniConf::errors, ''); 763 } 764 die "Can't parse config file $Configfile\n"; 765} 766 767my @parms; 768 769unless($Reconfigure or $Cfg->val('base', 'vendroot')) { 770 $Reconfigure = 1; 771} 772 773CHECKEXIST: { 774 775 if(grep /^catalog $catalog_name$/i, $Cfg->Sections()) { 776 @parms = $Cfg->Parameters("catalog $catalog_name"); 777 } 778 else { 779 @parms = (); 780 } 781 unless(@parms) { 782 @parms = $Cfg->Parameters('legalconfig'); 783 undef $Cfg; 784 my $user_time = "run by "; 785 $user_time .= scalar getpwuid($>); 786 $user_time .= " at "; 787 $user_time .= scalar localtime(); 788 789 open(CFGFILE, ">>$Configfile") or die "Can't write $Configfile: $!\n"; 790 print CFGFILE <<EOF; 791 792# New catalog definition '$catalog_name' written by makecat 793# $user_time 794[catalog $catalog_name] 795EOF 796 for(@parms) { 797 printf CFGFILE "%-19s =\n", $_; 798 } 799 close(CFGFILE) or die "Can't close $Configfile: $!\n"; 800 $Cfg = new IniConf -file => $Configfile; 801 die "Can't read config file $Configfile: $!\n" unless defined $Cfg; 802 redo CHECKEXIST; 803 } 804 805} 806 807my @conf; 808my @Servers; 809 810FINDCONF: { 811 812 last FINDCONF if $Windows; 813 last FINDCONF if $Vend::MakeCat::Force; 814 last FINDCONF if $ENV{MVC_SERVERNAME}; 815 my $httpdconf; 816 if($param = prefix('serverconf') || $Cfg->val('base', 'serverconf')) { 817 last FINDCONF if $param =~ /^none$/i; 818 @conf = split /\s+/, $param; 819 } 820 print <<EOF unless @conf; 821 822If you are using the Apache or NCSA web server, Interchange can set 823some of the default parameters for you by reading the file. 824 825If you use the Netscape Enterprise server or other non-NCSA HTTP server, 826enter 'none' -- the information, if any, will not be useful. 827 828EOF 829 if (defined $Vend::MakeCat::Prompt_sub) { 830 print <<EOF; 831 832Try using the UP arrow at some of the prompts -- you have the 833Term::ReadLine module installed, and Interchange may find some 834default values in your HTTP server configuration file. You can 835cycle among them with the UP and DOWN arrows. 836 837EOF 838 } 839 else { 840 print <<EOF unless @conf; 841 842This information may not be that useful to you, since you don't 843have the Term::ReadLine module installed. If the default setting 844presented is not correct, you will have to know the information. 845C'est la vie. 846 847EOF 848 } 849 850 my $not_set; 851 if(! scalar @conf) { 852 $not_set = 1; 853 if(findexe('locate')) { 854 @conf = findfiles('httpd.conf'); 855 } 856 else { 857 print <<EOF; 858 859Interchange can look for Apache or NCSA HTTP server configuration 860files for you by a slow method (using the system find 861command). This may take as many as several minutes. 862 863EOF 864 $ask = prompt("Find httpd.conf files? ", 'y'); 865 @conf = findfiles('httpd.conf') if $ask =~ /^\s*y/i; 866 } 867 } 868 869 sethistory(@conf); 870 if ($not_set) { 871 $httpdconf = prompt("Enter path to httpd.conf file: ", $conf[0]); 872 $Cfg->setval('base', 'serverconf', $httpdconf); 873 } 874 else { 875 $httpdconf = shift @conf; 876 } 877 last FINDCONF if $httpdconf =~ /^none$/i; 878 879 if($httpdconf) { 880 $Servers = conf_parse_http($httpdconf); 881 unless (defined $Servers) { 882 print <<EOF; 883 884The file '$httpdconf' was not parsed properly. 885 886Error: $Vend::MakeCat::Error 887 888You can edit the file and try again if you wish. (Don't worry if it 889didn't work, you will have the opportunity to enter all of the proper 890information manually.) 891 892EOF 893 $ask = prompt("Try again? ", 'y'); 894 last FINDCONF if $ask =~ /^\s*n/i; 895 redo FINDCONF; 896 } 897 else { 898 @Servers = sort keys %{$Servers}; 899 } 900 } 901} 902 903############## 904SETDEFAULTS: { 905 last SETDEFAULTS if $Done_defaults; 906 $Done_defaults = 1; 907 unless ($Reconfigure) { 908 my @parms = $Cfg->Parameters('base'); 909 for(@parms) { 910 next if $Conf{$_} = prefix($_, 1); 911 $Conf{$_} = $Cfg->val('base', $_) || undef; 912 } 913 last SETDEFAULTS; 914 } 915 916 PERMS: { 917 918 unless ($isroot) { 919 print <<EOF unless $Windows; 920 921This demo configuration sometimes requires root permissions, 922depending on your ISP. It needs to copy a few files to the CGI 923and HTML directories. 924 925You must either have your own CGI directory, or be able to run 926a CGI with an extension like '.cgi'. 927 928If you will be operating only on directories owned by the 929user you are running this as, you will be able to do 930everything. 931 932EOF 933 934 } 935 else { 936 last PERMS if prefix('permtype', 1); 937 print <<EOF; 938 939You are the super-user. You can set the permissions to GROUP, MULTIPLE 940GROUP, or USER mode for catalogs on this server. 941 942MULTIPLE GROUP or GROUP is appropriate when multiple users will be running 943catalogs on the same server. 944 945MULTIPLE GROUP is the best way. Put each user in their own group, and 946place the Interchange user in that group. In this mode, only the user of 947each catalog and the Interchange server may read database and error files -- 948files that may contain sensitive information. If the user's default UMASK 949is 2 on a UNIX system, then this the most troublefree mode of operation. 950 951GROUP mode causes all files to be owned by the Interchange user, with group 952ownership set to the group the user belongs to. This allows the Interchange 953user and each individual user to read and write the files associated with 954a catalog, but others in that group may read files from a catalog. This 955may not be secure, and may cause problems when the user creates new 956files that must be read/write to the Interchange user. 957 958USER mode is appropriate when only one user owns all catalogs running 959on this server, and the Interchange daemon is run by the same user. 960 961 M) MULTIPLE GROUP 962 G) GROUP 963 U) USER 964 965EOF 966 sethistory("MULTIPLE GROUP", "GROUP", "USER"); 967 $Conf{permtype} = prompt("Permission Mode? ", "M"); 968 unless($Conf{permtype} =~ s/^\s*([mgu]).*/uc $1/ie) { 969 print "Must be one of M(ULTIPLE), G(ROUP), or U(SER).\n"; 970 redo PERMS; 971 } 972 $Cfg->setval('base', 'permtype', $Conf{permtype}); 973 974 } 975 976 } # END PERMS 977 978 print <<EOF; 979 980Since there was no master configuration file, we will ask 981some questions to help set initial defaults for making this 982and future catalogs. 983 984EOF 985 986 987 ############## 988 DEFSERVER: { 989 990 last DEFSERVER unless @Servers; 991 992 print <<EOF if defined $Vend::MakeCat::Prompt_sub; 993 994Interchange can set many of the defaults for you if it knows the server 995name that is going to be used. 996 997Enter the default server that should be used. This is only a default, to 998determine the *first* one that will be looked at -- you will be given 999a choice of all available servers. 1000 1001There is a "history" mechanism that will allow you to use the up 1002and down arrows on your terminal (assuming you have a standard terminal) 1003to cycle between possible choices. This should contain the available 1004servers. 1005 1006EOF 1007 1008 sethistory(@Servers); 1009 $Conf{servername} = prompt('Default server? ', $Servers[0]); 1010 $Servername = $Conf{servername}; 1011 $Cfg->setval('base', 'servername', $Servername); 1012 1013 } 1014 ############ 1015 1016 my @ask = $Cfg->val('global', 'askbase'); 1017 1018 for('cgidir') { 1019 next if $Conf{$_}; 1020 print <<EOF; 1021 1022 1023We need to know if all of your CGI programs are run as a file ending 1024in .cgi or some other extension, or whether you have your own personal 1025CGI directory. 1026 1027EOF 1028 $ask = prompt ("Do you have a CGI directory? ", 'y'); 1029 last if is_yes($ask); 1030 $Prefix{cgidir} = prefix('documentroot'); 1031 } 1032 1033 my ($p, $i); 1034 1035 for ($i = 0; $i < scalar @ask; $i++) { 1036 $p = $ask[$i]; 1037 my $hval; 1038 $hval = prefix($p); 1039 if (defined $History{$p}) { 1040 @history = &{$History{$p}}(prefix($p)); 1041 $hval = $history[0]; 1042 sethistory(@history); 1043 } 1044 $val = prefix($p, 1) || $Cfg->val("base", $p) || $hval; 1045 if (! $isroot and defined $IfRoot{$p}) { 1046 $Conf{$p} = $val; 1047 next; 1048 } 1049 print "\n"; 1050 print description($p); 1051 print "\n\n"; 1052 my $msg = pretty($p) . "? "; 1053 $Conf{$p} = prompt ($msg, $val); 1054 if($Conf{$p} eq '@') { 1055 $i--; 1056 $i = 0 if $i < 0; 1057 redo; 1058 } 1059 if(defined $Postprocess{$p}) { 1060 $Conf{$p} = $Postprocess{$p}->($Conf{$p}); 1061 } 1062 } 1063 1064 for(@ask) { 1065 $Cfg->setval('base', $_, $Conf{$_}); 1066 } 1067 1068 $Cfg->WriteConfig("$Configfile.new") 1069 and File::Copy::copy "$Configfile.new", $Configfile; 1070 1071 print "######### END BASE CONFIGURATION #########\n\n"; 1072 1073} 1074############# 1075 1076 my $serv = prefix('servername') || 'www.yourdomain'; 1077 1078# Set server 1079 1080print "######### BEGINNING CATALOG CONFIGURATION #########\n"; 1081print <<EOF if defined $Vend::MakeCat::Prompt_sub; 1082 1083During many of the following operations, defaults are placed in 1084a buffer for you. You may use the up and down arrows to toggle 1085between the defaults. 1086 1087If you made a mistake on a *previous* entry and realize that 1088in a later one, if you enter ONLY an @ sign and press return you 1089should be returned to the previous step. 1090 1091EOF 1092SETSERVER: { 1093 sethistory(@Servers); 1094 print description('servername'); 1095 $Servername = prefix('servername', 1) || 1096 $Cfg->val('base', 'servername') || 1097 prefix('servername'); 1098 $Servername = 1099 $Conf{servername} = 1100 prompt("Server name? ", ($Servername || $Servers[0])); 1101 $Cfg->setval("catalog $catalog_name", 'servername', $Conf{servername}); 1102} 1103 1104 @ask = $Cfg->val('global', 'askconfig'); 1105 1106 my $redid; 1107 my $next_force; 1108 for ($i = 0; $i < scalar @ask; $i++) { 1109 $p = $ask[$i]; 1110 if ($redid) { 1111#print("###redo###\n"); 1112 # Handle the &-d option, don't want to force first time 1113 if (defined $next_force and ! $next_force) { 1114#print("###force next###\n"); 1115 $next_force = 1; 1116 } 1117 $val = $Conf{$p}; 1118 } 1119 elsif (defined $History{$p}) { 1120 @history = &{$History{$p}}(prefix($p)); 1121 sethistory(@history); 1122 $val = prefix($p,1) || 1123 $Cfg->val("catalog $catalog_name", $p) || 1124 $history[0] || 1125 prefix($p); 1126 } 1127 else { 1128 $val = prefix($p,1) || 1129 $Cfg->val("catalog $catalog_name", $p) || 1130 prefix($p); 1131 } 1132 if (! $isroot and defined $IfRoot{$p}) { 1133 $Conf{$p} = $val; 1134 next; 1135 } 1136 print "\n"; 1137 1138 unless($redid) { 1139 print description($p); 1140 print "\n\n"; 1141 } 1142 else { 1143 undef $redid; 1144 } 1145 1146 my $msg = pretty($p) . "? "; 1147 $Conf{$p} = prompt ($msg, $val); 1148#print("###force=$Vend::MakeCat::Force###\n"); 1149 if(defined $Postprocess{$p}) { 1150 $Conf{$p} = $Postprocess{$p}->($Conf{$p}); 1151 } 1152 if($Conf{$p} eq '@') { 1153 $Conf{$p} = $val; 1154 $redid = 1; 1155 $next_force = 0 if $next_force; 1156 $i--; 1157 $i = 0 if $i < 0; 1158 redo; 1159 } 1160 elsif ($Conf{$p} eq '&-d') { 1161 print "OK, I will run with defaults after this prompt.\n"; 1162 $Conf{$p} = $val; 1163 $redid = 1; 1164 $next_force = 0; 1165 redo; 1166 } 1167 1168 if ($next_force) { 1169#print("###force now###\n"); 1170 $Vend::MakeCat::Force = 1; 1171 } 1172 1173 $Cfg->setval("catalog $catalog_name", $p, $Conf{$p}); 1174 } 1175 1176if($Removeconfig) { 1177 unlink $Configfile; 1178} 1179elsif ( ! prefix('nocopy') ) { 1180 $Cfg->WriteConfig("$Configfile.new") 1181 and File::Copy::copy "$Configfile.new", $Configfile; 1182} 1183 1184undef $Cfg; 1185 1186# Try and get the URL we will use to access the catalog 1187GUESS: { 1188 1189 if( $Conf{samplehtml} =~ /^\s*none\s*$/i ) { 1190 $Conf{sampleurl} = 'NONE'; 1191 last GUESS; 1192 } 1193 1194 my $tempurl; 1195 $guessdir = $Conf{samplehtml}; 1196 1197 unless( $guessdir =~ s/^$Conf{documentroot}// ) { 1198 print <<EOF; 1199 1200The specified HTML directory, $Conf{samplehtml}, 1201is not a subdirectory of DocumentRoot. This will make it 1202hard for us to guess the URL needed to access pages from 1203the catalog. Please re-specify your HTML document root. 1204 1205# The base directory for HTML for the catalog, the DocumentRoot. 1206# This is a file name, not a URL. 1207 1208EOF 1209 $val = ''; 1210 my $msg = pretty('documentroot'); 1211 $Conf{documentroot} = prompt ("\n$msg? ", ''); 1212 redo GUESS; 1213 } 1214 1215 $guessdir =~ s:^/+::; 1216 $guessdir = "$Tilde/$guessdir" if defined $Tilde; 1217 $guessdir =~ s:^/+::; 1218 $tempurl = "http://$Conf{servername}/$guessdir"; 1219 if (defined $Conf{sampleurl} and $Conf{sampleurl} ne $tempurl) { 1220 print <<EOF; 1221 1222We were given a previous value for the URL that will run the catalog 1223(from the catalog configuration file $Configfile): 1224 1225 $Conf{sampleurl} 1226 1227This conflicts with what we guess from what you have just 1228entered: 1229 1230 $tempurl 1231 1232EOF 1233 1234 if ($Vend::MakeCat::Force) { 1235 $tempurl = $Conf{sampleurl}; 1236 } else { 1237 $tempurl = prompt ("\nPlease re-enter or confirm: ", 1238 "http://$Conf{servername}/$guessdir"); 1239 } 1240 } 1241 1242 $Conf{sampleurl} = $tempurl; 1243 1244} 1245 1246if ($Windows) { 1247 $mvuid = $catuid = 'everybody'; 1248 $mvgid = $catgid = 'nogroup'; 1249} 1250elsif ($Conf{relocate}) { 1251 $mvuid = $catuid = $mvgid = $catgid = 'nobody'; 1252} 1253else { 1254 $mvuid = (getpwnam($Conf{interchangeuser}))[2]; 1255 die "$Conf{interchangeuser} is not a valid user name on this machine.\n" 1256 unless defined $mvuid; 1257 1258 if ($Conf{interchangegroup}) { 1259 $mvgid = getgrnam($Conf{interchangegroup}); 1260 die "$Conf{interchangegroup} is not a valid group name on this machine.\n" 1261 unless defined $mvgid; 1262 } 1263 else { 1264 $mvgid = (getpwnam($Conf{interchangeuser}))[3]; 1265 $Conf{interchangegroup} = getgrgid($mvgid) 1266 } 1267 1268 ($catuid, $catgid) = (getpwnam($Conf{catuser}))[2,3]; 1269 die "$Conf{catuser} is not a valid user name on this machine.\n" 1270 unless defined $catuid; 1271} 1272 1273if($isroot) { 1274 chown ($mvuid, $mvgid, $Configfile) 1275 or warn "\nCouldn't set ownership of $Configfile: $!\n"; 1276 if(! $Conf{permtype} or $Conf{permtype} =~ /^[MUmu]/) { 1277 $Conf{catgroup} = getgrgid($catgid); 1278 } 1279 else { 1280 $Conf{catgroup} = getgrgid($mvgid); 1281 } 1282} 1283 1284# Final substitution 1285for(keys %Conf) { 1286 next unless $Conf{$_} =~ /__MVC_/; 1287 $Conf{$_} =~ s/__MVC_([A-Z]+)__/$Conf{lc $1}/g; 1288} 1289 1290# Find the perl path 1291$Conf{'perl'} = $Config{perlpath}; 1292 1293# Now change to the directory defined as Global::VendRoot 1294chdir "$Conf{relocate}$Conf{vendroot}" 1295 or die "Couldn't change directory to $Conf{relocate}$Conf{vendroot}: $!\n"; 1296 1297$warn = 0; 1298$msg = q# supposed to be a directory, not a file. Can't continue.#; 1299for ( $Conf{catroot}, $Conf{documentroot}, $Conf{basedir}, 1300 $Conf{samplehtml}, $Conf{imagedir} ) { 1301 next unless -f "$Conf{relocate}$_"; 1302 print "$_ $msg\n"; 1303 $warn++; 1304} 1305die "\n" if $warn; 1306 1307my $prog; 1308my ($lh, $lp); 1309 1310SETLINKMODE: { 1311 if($prog = prefix('linkprogram')) { 1312 last SETLINKMODE; 1313 } 1314 if ($Windows) { 1315 $Conf{linkmode} = 'INET'; 1316 $prog = "$Conf{relocate}$Conf{vendroot}/src/tlink.pl"; 1317 last SETLINKMODE; 1318 } 1319 print <<EOF; 1320 1321Interchange can use either UNIX- or internet-domain sockets. 1322Most ISPs would prefer UNIX mode, and it is more secure. 1323 1324If you already have a program there, or use a common program 1325and the FullURL directive, select NONE. You will then need 1326to copy the program by hand or otherwise ensure its presence. 1327 1328EOF 1329 print "(You can use the up/down arrows to toggle).\n" 1330 if $Vend::MakeCat::Prompt_sub; 1331 1332 sethistory("NONE", "UNIX", "INET"); 1333 1334 unless ( $default = prefix('linkmode') ) { 1335 $default = ($Config{osname} =~ /bsd/i and $Config{osvers} gt '3') 1336 ? 'INET' : 'UNIX'; 1337 } 1338 1339 $ask = prompt("INET or UNIX mode? ", $default); 1340 1341 $prog = "$Conf{relocate}$Conf{vendroot}/src/vlink"; 1342 1343 if($ask =~ /^\s*i/i) { 1344 $lm = "i"; 1345 $Conf{linkmode} = 'INET'; 1346 $Inetmode = 1; 1347 1348 my $defport; 1349 my $defhost; 1350 1351 INETASK: { 1352 my (@hosts); 1353 my (@ports); 1354 $prog = "$Conf{relocate}$Conf{vendroot}/src/tlink"; 1355 my $the_one = sum_it($prog); 1356 1357 my @poss = glob("$Conf{relocate}$Conf{vendroot}/src/tlink.*.*"); 1358 for (@poss) { 1359 my $name = $_; 1360 /tlink\.(.*)\.(\d+)$/ 1361 or next; 1362 my ($h, $p) = ($1, $2); 1363 push @hosts, $h; 1364 push @ports, $p; 1365 my $one = sum_it($_); 1366 next unless $one eq $the_one; 1367 $defhost = $h; 1368 $defport = $p; 1369 } 1370 1371 my %seen; 1372 sethistory(grep !$seen{$_}++, @ports); 1373 $default = $defport || $Conf{linkport} || 7786; 1374 $lp = $lh = ''; 1375 while(! $lp) { 1376 $lp = prompt("TCP socket to use? ", $default); 1377 redo INETASK if $lp eq '@'; 1378 if($lp !~ /^\d+$/ or $lp < 1024) { 1379 print "Looking for an integer number > 1024 here.\n"; 1380 undef $lp; 1381 } 1382 } 1383 1384 sethistory(grep !$seen{$_}++, @hosts); 1385 $default = $defhost || $Conf{linkhost} || '127.0.0.1'; 1386 while(! $lh) { 1387 $lh = prompt("Link host? ", $default); 1388 redo INETASK if $lh eq '@'; 1389 } 1390 $Conf{linkport} = $lp; 1391 $Conf{linkhost} = $lh; 1392 unlink $prog unless $lh eq $defhost && $lp eq $defport; 1393 } # END INETASK 1394 } 1395 elsif($ask =~ /^\s*n/i) { 1396 $Conf{linkmode} = $prog = "NONE"; 1397 } 1398 else { 1399 $lm = 'u'; 1400 $Conf{linkmode} = "UNIX"; 1401 my $def = -u '/usr/bin/suexec' ? 'y' : 'n'; 1402 $ask = prompt("Do you use CGIWRAP or SUEXEC? ", $def); 1403 $Conf{cgiwrap} = $CGIwrap = $ask =~ /^\s*y/i; 1404 } 1405 1406} 1407 1408my $tried_compile; 1409 1410FINDPROG: { 1411 last FINDPROG if $prog eq 'NONE'; 1412 unless (-x $prog and -f _) { 1413 if(! $tried_compile) { 1414 my $cmd = 'bin/compile_link '; 1415 $cmd .= "-$lm " if $lm; 1416 $cmd .= "-s $Conf{linkfile} " if $Conf{linkfile}; 1417 $cmd .= "-p $lp " if $lp; 1418 $cmd .= "-h $lh " if $lh; 1419 if ($Conf{relocate}) { 1420 $cmd .= "--source $Conf{relocate}/$Conf{vendroot}/src "; 1421 } 1422 system $cmd; 1423 $tried_compile = 1; 1424 redo FINDPROG; 1425 } 1426 my @history = (); 1427 $prog =~ s:.*src/::; 1428 print <<EOF; 1429 Couldn't find the executable file '$prog'. 1430 1431 Please give the complete path to the link program. 1432 1433EOF 1434 if($Config{osname} =~ /win32/i) { 1435 # do nothing 1436 } 1437 elsif (@history = glob("$Global::VendRoot/src/?link.???*")) { 1438 # do nothing 1439 } 1440 elsif (@history = glob("$Global::ProgRoot/src/?link.???*")) { 1441 # do nothing 1442 } 1443 elsif(findexe('locate')) { 1444 @history = findfiles($prog); 1445 } 1446 else { 1447 @history = `find . -name \*[vt]link\* -print`; 1448 chomp @history; 1449 } 1450 sethistory(@history); 1451 $prog = prompt("Link program? ", $history[0]); 1452 } 1453} 1454 1455umask(022) unless $Conf{noumask}; 1456 1457$warn = 0; 1458print do_msg("Checking directories"); 1459 1460$msg = q#directory exists!#; 1461for($Conf{catroot}, $Conf{samplehtml}) { 1462 next unless -d $_; 1463 print "\n$_: $msg\n"; 1464 $warn++; 1465} 1466 1467if($warn) { 1468 $ask = prompt "The above directories already exist. Overwrite files? ", 'n'; 1469 unless($Vend::MakeCat::Force) { 1470 exit 2 unless is_yes($ask); 1471 } 1472} 1473 1474$warn = 0; 1475for($Conf{documentroot}, $Conf{basedir}) { 1476 next if /^\s*none\s*$/i; 1477 next if -d $_; 1478 $warn++; 1479} 1480 1481for($Conf{catroot}, $Conf{samplehtml}, $Conf{imagedir}) { 1482 next if /^\s*none\s*$/i; 1483 next if -d $_; 1484 $warn++; 1485} 1486 1487if($warn) { 1488 for(qw(catroot samplehtml imagedir)) { 1489 $dir = "$Conf{relocate}$Conf{$_}"; 1490#print "doing dir=$dir\n"; 1491 # Allow nocopy 1492 next if $dir =~ /^\s*none\s*$/i; 1493 1494 (warn "\n$_ is empty, skipping.\n", next) 1495 unless $dir =~ /\S/; 1496 unless(-d $dir or prefix('nocopy') ) { 1497 File::Path::mkpath([$dir], 1, 0775) 1498 or die "Couldn't make directory $dir: $!\n"; 1499 } 1500 } 1501} 1502 1503for(qw(catroot samplehtml imagedir)) { 1504 my $userdir; 1505 if($dir =~ /^~/ and $userdir = (getpwnam($Conf{catuser}))[7] ) { 1506 $dir =~ s/^~/$userdir/; 1507 } 1508 $dir = "$Conf{relocate}$Conf{$_}"; 1509 1510 # Allow nocopy 1511 next if $dir =~ /^\s*none\s*$/i; 1512 1513 if (prefix('nocopy')) { 1514 next if -w $dir; 1515 my $parent = $dir; 1516 do { 1517 $parent =~ s:/[^/]+$::; 1518 } until $parent !~ m{/} or -d $parent; 1519 warn "Directory $dir (or parents) not writable, could be problems.\n" 1520 unless -w $dir || -w $parent; 1521 next; 1522 } 1523 1524 die "Directory $dir not writable, can't continue.\n" 1525 unless -w $dir or $dir =~ /^\s*none\s*$/i; 1526 set_owner($dir); 1527} 1528print "done.\n"; 1529 1530# Now change to the directory defined as Global::VendRoot if the checks 1531# have left us elsewhere 1532chdir "$Conf{relocate}$Conf{vendroot}" 1533 or die "Couldn't change directory to $Conf{relocate}$Conf{vendroot}: $!\n"; 1534 1535print do_msg("Copying demo files"); 1536unless (-d "$Conf{relocate}$Conf{vendroot}/$Conf{demotype}") { 1537 print "No $Conf{relocate}$Conf{vendroot}/$Conf{demotype} directory is present,\n"; 1538 $dir = prompt("where should the files come from? ", "$Conf{relocate}$Conf{catroot}"); 1539} 1540else { 1541 $dir = "$Conf{relocate}$Conf{vendroot}/$Conf{demotype}"; 1542} 1543 1544# Do some additional configuration if the additional_fields 1545# file is found 1546 1547ADDITIONAL: { 1548 last ADDITIONAL unless -f "$dir/config/additional_fields"; 1549 open(ADDL, "< $dir/config/additional_fields") 1550 or last ADDITIONAL; 1551 my %help; 1552 local ($/) = ""; 1553 if(open(ADDLHELP, "< $dir/config/additional_help") ) { 1554 while(<ADDLHELP>) { 1555 my($parm,$help) = split /\n/, $_, 2; 1556 $help =~ s/\s*$/\n\n/; 1557 $help =~ s/^[.\t ]+$//mg; 1558 $help{uc $parm} = $help; 1559 } 1560 close ADDLHELP; 1561 } 1562 my $said = 0; 1563 my $redid; 1564 my $next_force; 1565 while(<ADDL>) { 1566 my $noprompt = ''; 1567 my $grp; 1568 s/\s+$//; 1569 s/__MVC_([A-Z0-9]+)(__)?/substitute($1,$2)/eg; 1570 my ($var, $prompt, $default) = split /\n/, $_, 3; 1571 $var =~ s/\t(.*)//; 1572 next unless $var; 1573 $grp = $1 || $var; 1574 1575 if ($redid) { 1576#print("###redo###\n"); 1577 # Handle the &-d option, don't want to force first time 1578 if (defined $next_force and ! $next_force) { 1579#print("###force next###\n"); 1580 $next_force = 1; 1581 } 1582 $val = $Conf{$p}; 1583 } 1584 if($var =~ s/{\s*([A-Z0-9]+)(\s*\S.*?)?\s*}\s*//) { 1585 my $param = $1; 1586 my $test = $2; 1587 my $v = $Conf{lc $param}; 1588 $v = "q{$v}"; 1589 my $true; 1590 eval { 1591 $true = eval "$v$test"; 1592 }; 1593 next unless $true; 1594 } 1595 $var =~ s/\s+//g; 1596 $var =~ s:^!:: 1597 and $noprompt = 1; 1598 $var = lc $var; 1599 my $ucvar = uc $var; 1600 if($default =~ /\t/) { 1601 my (@history); 1602 (@history) = split /\t/, $default; 1603 $default = $history[0]; 1604 sethistory(@history); 1605 } 1606 unless ($noprompt) { 1607 if (defined $help{$ucvar} and ! $redid) { 1608 $help{$ucvar} =~ s/__MVC_([A-Z0-9]+)(__)?/substitute($1,$2)/eg; 1609 print $help{$ucvar}; 1610 } 1611 print "found more to ask.\n\n" unless $said++; 1612 $Conf{$var} = prompt( 1613 do_msg("$prompt: ", 50), 1614 ( delete $ENV{"MVC_$ucvar"} 1615 || $Conf{$var} 1616 || $default) 1617 ); 1618 if ($Conf{$var} eq '&-d') { 1619 print "OK, I will run with defaults after this prompt.\n"; 1620 $Conf{$var} = $default; 1621 $redid = 1; 1622 $next_force = 0; 1623 redo; 1624 } 1625 } 1626 else { 1627 $Conf{$var} = delete $ENV{"MVC_$ucvar"} || $Conf{$var} || $default; 1628 } 1629 1630 if ($next_force) { 1631#print("###force now###\n"); 1632 $Vend::MakeCat::Force = 1; 1633 } 1634 1635 } 1636 close ADDL; 1637} 1638 1639CRYPTPW: { 1640 my $pw = substitute('CRYPTPW', '__'); 1641 last CRYPTPW unless $pw; 1642 last CRYPTPW if substitute('ALREADYCRYPT', '__'); 1643 my @letters = ('A' .. 'Z', 'a' .. 'z'); 1644 my $salt = $letters[ int rand(scalar @letters) ]; 1645 $salt .= $letters[ int rand(scalar @letters) ]; 1646 $ENV{MVC_CRYPTPW} = crypt($pw, $salt); 1647} 1648 1649PRECMD: { 1650 last PRECMD unless -f "$dir/config/precopy_commands"; 1651 open(ADDL, "< $dir/config/precopy_commands") 1652 or last PRECMD; 1653 print "\nFound system commands to run.\n\n"; 1654 local ($/) = ""; 1655 while(<ADDL>) { 1656 my $unprompted; 1657 s/\s+$//; 1658 s/__MVC_([A-Z0-9]+)(__)?/substitute($1,$2)/eg; 1659 my ($command, $prompt) = split /\n/, $_, 2; 1660 $command =~ s/^\s+//; 1661 $command =~ s/\s+$//; 1662 $command =~ s/^!// and $unprompted = 1; 1663 if($command =~ s/{\s*([A-Z0-9]+)(\s*\S.*?)?\s*}\s*//) { 1664 my $param = $1; 1665 my $test = $2; 1666 my $v = $Conf{lc $param}; 1667 $v = "q{$v}"; 1668 my $true; 1669 eval { 1670 $true = eval "$v$test"; 1671 }; 1672 next unless $true; 1673 } 1674 print "$prompt\n\n"; 1675 print "Running: $command\n" if $unprompted; 1676 my $ans = $unprompted ? 'y' : prompt( qq{run "$command"? }, 'y' ); 1677 if($ans =~ /^\s*y/i) { 1678 system $command; 1679 if($?) { 1680 print "\nCommand returned error code " . ($? >> 8) . ": $!\n"; 1681 } 1682 } 1683 else { 1684 print "\nskipping '$command'\n"; 1685 } 1686 } 1687 close ADDL; 1688} 1689 1690# Here we actually do the file copy unless --nocopy is set 1691DOCOPY: { 1692 1693 if (prefix('nocopy')) { 1694 print "not copying.\n"; 1695 last DOCOPY; 1696 } 1697 1698 chdir $dir || die "Couldn't change directory to $dir: $!\n"; 1699 1700 1701 # This is what we used to do 1702 #system "tar -cf - * | (cd $Conf{catroot}; tar -xf -)"; 1703 1704 umask(07) unless $Conf{noumask}; 1705 1706 # remove any existing symbolic links in target directory 1707 File::Find::find( sub { 1708 return if ! -l $_; 1709 unlink $_ 1710 or die "couldn't unlink $File::Find::name: $!\n"; 1711 }, 1712 "$Conf{relocate}$Conf{catroot}", 1713 ); 1714 1715 eval { 1716 copy_current_to_dir("$Conf{relocate}$Conf{catroot}"); 1717 }; 1718 1719 umask(022) unless $Conf{noumask}; 1720 1721 if($@) { 1722 die <<EOF . "\n"; 1723There were errors in copying the demo files. Cannot 1724continue. Check to see if permissions are correct. 1725The problem was: 1726 1727 $@ 1728EOF 1729 } 1730 1731 unless($prog eq 'NONE') { 1732 File::Copy::copy( $prog, "$Conf{relocate}$Conf{catroot}/executable") 1733 or die "Couldn't copy link program from $prog: $!\n"; 1734 } 1735 1736 print "done.\n"; 1737 1738chdir "$Conf{relocate}$Conf{catroot}" 1739 || die "Couldn't change directory to $Conf{relocate}$Conf{catroot}: $!\n"; 1740 1741my ($umode, $gmode); 1742 1743if($Conf{permtype} =~ /^[mg]/i) { 1744 $umode = 0; $gmode = 1; 1745} 1746else { 1747 $umode = 1; $gmode = 0; 1748} 1749 1750 1751%MacroString = qw( 1752 1753 __MVC_CGIURL cgiurl 1754 __MVC_CGIDIR cgidir 1755 __MVC_MAILORDERTO mailorderto 1756 __MVC_IMAGEURL imageurl 1757 __MVC_SAMPLEURL sampleurl 1758 __MVC_SERVERNAME servername 1759 1760); 1761 1762sub set_owner { 1763 return unless $> == 0; 1764 my($file) = @_; 1765 my ($user, $group) = ($mvuid, $mvgid); 1766 if($Conf{permtype} =~ /^m/i) { $user = $catuid; $group = $catgid; } 1767 elsif($Conf{permtype} =~ /^g/i) { $group = $catgid; } 1768 chown($user, $group, $file) 1769 or die "Couldn't set ownership to UID=$user GID=$group for $file: $!\n"; 1770} 1771 1772sub substitute { 1773 my($parm,$new) = @_; 1774 1775 return $ENV{"MVC_$parm"} if defined $ENV{"MVC_$parm"}; 1776 1777 if($new) { 1778 return $Conf{lc $parm} || ''; 1779 } 1780 else { 1781 return $Conf{$MacroString{"__MVC_$parm"}} 1782 if defined $MacroString{"__MVC_$parm"}; 1783 } 1784 return "__MVC_${parm}__"; 1785} 1786 1787sub wanted { 1788 1789 my ($mode,$file); 1790 $file = $_; 1791 my $name = $File::Find::name; 1792 EDIT: { 1793 return if (-l $file); 1794 1795 # Ugly, but necessary on BSDI 1796 $File::Find::prune = 1 if -f _; 1797 1798 last EDIT unless (-f _); 1799 last EDIT unless (-T _); 1800 1801 open(IN, "< $file") or die "Couldn't open $name: $!\n"; 1802 open(OUT, ">$file.new") or die "Couldn't create $name.new: $!\n"; 1803 while(<IN>) { 1804 ( (print OUT $_), next) unless /__MV[CR]/; 1805 s/^#>>(.*)(__MVR_(\w+)__.*)\n\1.*/#>>$1$2/g; 1806 s/^#>>(.*__MVR_(\w+)__.*)/#>>$1\n$1/g; 1807 1 while s/\n([^#].*)__MVR_(.*)/\n$1__MVC_$2/g; 1808 s/__MVC_([A-Z0-9]+)(__)?/substitute($1,$2)/eg; 1809 print OUT $_; 1810 } 1811 close OUT; 1812 close IN; 1813 unlink ($file) 1814 or die "Couldn't unlink $name: $!\n"; 1815 rename ("$file.new", $file) 1816 or die "Couldn't rename $name.new to $name: $!\n"; 1817 } 1818 my %Xfile; 1819 if($Windows) { 1820 # None of this stuff applies for Windows, I don't think. 1821 # Put Win-specific stuff here. 1822 } 1823 else { 1824 set_owner($file); 1825 $mode = (stat($file))[2]; 1826 if ($Xfile{$file}) { 1827 $mode |= 0550; 1828 } 1829 else { 1830 $mode |= 060 if $gmode; 1831 $mode |= 02010 if $gmode and -d $file; 1832 } 1833 chmod ($mode, $file) 1834 or die "\nCouldn't set permissions on $name: $!\n"; 1835 } 1836} 1837 1838 $File::Find::dont_use_nlink = 1; 1839 set_owner("$Conf{relocate}$Conf{catroot}"); 1840 File::Find::find(\&wanted, "$Conf{relocate}$Conf{catroot}"); 1841 1842 $cginame = $Conf{cgiurl}; 1843 $cginame =~ s:.*/::; 1844 $Conf{cgifile} = $cginame = "$Conf{relocate}$Conf{cgidir}/$cginame"; 1845 1846 umask(022) unless $Conf{noumask}; 1847 1848 unless ($prog eq 'NONE') { 1849 my $ask_cgi = 'y'; 1850 if(-f $cginame) { 1851 $ask_cgi = prompt ( 1852 do_msg("Moving link, $cginame exists, overwrite? "), 1853 'n', 1854 ); 1855 } 1856 else { 1857 print do_msg("Moving link program to $cginame"); 1858 } 1859 1860 if(is_yes($ask_cgi)) { 1861 File::Copy::copy("$Conf{relocate}$Conf{catroot}/executable", $cginame) 1862 or die 1863 "\nCouldn't copy link executable from $prog to $cginame: $!\n"; 1864 chmod 0755, $cginame 1865 or die "\nCouldn't make $cginame executable: $!\n"; 1866 unlink "$Conf{relocate}$Conf{catroot}/executable"; 1867 } 1868 1869 if($isroot) { 1870 chown ($mvuid, $mvgid, $cginame) 1871 or die "\nCouldn't set ownership of $cginame: $!\n"; 1872 } 1873 1874 unless ($Windows or $Inetmode or $CGIwrap) { 1875 unless ($isroot or can_do_suid()) { 1876 print <<EOF; 1877 1878My test indicates you can't change vlink to SUID mode. 1879This will cause big problems -- you can make Interchange work anyway 1880by changing the ReadPermission and WritePermission directives in 1881all of your catalogs to 'world', but this is not secure. If you can, 1882you should run this as root, or su to root and do: 1883 1884 chmod 4755 $cginame 1885 1886EOF 1887 $ask = prompt("Continue? ", 'n'); 1888 unless($Vend::MakeCat::Force) { 1889 exit 2 unless is_yes($ask); 1890 } 1891 } 1892 1893 chmod 04755, $cginame 1894 or warn "\nCouldn't set permissions on $cginame: $!\n"; 1895 } 1896 1897 print "done.\n"; 1898 1899 if($CGIwrap and $isroot) { 1900 print <<EOF; 1901Since you selected the SUEXEC/CGIwrap option and are root, we aren't sure 1902which user and group you intended to own the link program. We have selected 1903the catalog user's UID/GID ($catuid/$catgid), but this may not match your 1904server definition. If you get a server error, change the ownership to its 1905proper value and ensure that the SUID bit is turned off on the link 1906program ($cginame). 1907 1908EOF 1909 chown($catuid, $catgid, $cginame) or die "\nchown $cginame: $!\n"; 1910 prompt("Press <ENTER> to continue...."); 1911 } 1912 } 1913 1914 my $chg_to_catuser = sub { 1915 next if -l $_; 1916 $File::Find::prune = 1 if -f _; 1917 my $mode = (stat(_))[2]; 1918 $mode |= 044; 1919 $mode |= 011 if -d $_; 1920 chmod( $mode, $_) 1921 or die "\nchmod $_ to $mode: $!\n"; 1922 chown($catuid, $catgid, $_) 1923 or die "\nchown $_: $!\n"; 1924 1925 }; 1926 1927 unless ($Conf{sharedir} eq 'NONE') { 1928 print do_msg("Copying share/ files to $Conf{relocate}$Conf{sharedir}"); 1929 my $oldpwd = cwd(); 1930 my @sharedirs; 1931 eval { 1932 chdir "$Conf{relocate}$Conf{vendroot}" 1933 or die "\nchdir $Conf{relocate}$Conf{vendroot}: $!\n"; 1934 # remember directories so we can chown below 1935 chdir "share" or die "error.\nchdir 'share': $!\n"; 1936 map { push @sharedirs, $_ if -d $_ } glob('*'); 1937 chdir ".."; 1938 copy_dir("share", "$Conf{relocate}$Conf{sharedir}") or die; 1939 }; 1940 if (! @sharedirs) { 1941 print "none found.\n"; 1942 } 1943 elsif ($@) { 1944 print "error.\nError installing share/ files: $@\n"; 1945 } else { 1946 File::Find::find( 1947 $chg_to_catuser, 1948 map { "$Conf{relocate}$Conf{sharedir}/$_" } @sharedirs 1949 ) if $isroot; 1950 print "done.\n"; 1951 } 1952 chdir $oldpwd; 1953 } 1954 1955 my $ok = 0; 1956 unless($Conf{samplehtml} eq 'NONE') { 1957 print do_msg("Moving HTML files to $Conf{samplehtml}"); 1958 eval { 1959 chdir 'html' or ++$ok and die "\nchdir html: $!\n"; 1960 copy_current_to_dir("$Conf{relocate}$Conf{samplehtml}"); 1961 chdir '..'; 1962 File::Path::rmtree('html'); 1963 }; 1964 1965 if($@ and !$ok) { 1966 die "\nCouldn't move HTML files to $Conf{relocate}$Conf{samplehtml}: $@\n"; 1967 } 1968 elsif ($ok) { 1969 warn "\nHTML dir copy error: $!\nTrying to continue.\n"; 1970 } 1971 else { 1972 File::Find::find( $chg_to_catuser, "$Conf{relocate}$Conf{samplehtml}") 1973 if $isroot; 1974 } 1975 1976 print "done.\n"; 1977 } 1978 1979 $ok = 0; 1980 unless($Conf{imagedir} eq 'NONE') { 1981 print do_msg("Moving image files to $Conf{imagedir}"); 1982 eval { 1983 chdir 'images' or ++$ok and die "chdir images: $!\n"; 1984 copy_current_to_dir("$Conf{relocate}$Conf{imagedir}"); 1985 chdir '..'; 1986 File::Path::rmtree('images'); 1987 }; 1988 1989 if($@ and !$ok) { 1990 die "\nCouldn't move image files $Conf{relocate}$Conf{imagedir}: $@\n"; 1991 } 1992 elsif ($ok) { 1993 warn "\nImage dir copy error: $!\nTrying to continue.\n"; 1994 } 1995 else { 1996 File::Find::find($chg_to_catuser, "$Conf{relocate}$Conf{imagedir}") 1997 if $isroot; 1998 } 1999 2000 print "done.\n"; 2001 } 2002 2003 chdir "$Conf{relocate}$Conf{vendroot}" 2004 or die "\nCouldn't change directory to $Conf{relocate}$Conf{vendroot}: $!\n"; 2005 2006 my $pidfile; 2007 for(qw! etc/interchange.pid etc/minivend.pid etc/interchange.pid !) { 2008 $pidfile = $_; 2009 last if -f $_; 2010 } 2011 2012 PID: { 2013 local ($/); 2014 open(PID,"+<$pidfile") or last PID; 2015 2016 # If we get lock we are not running 2017 unless($Windows) { 2018 lockfile(\*PID,1,0) and last PID; 2019 } 2020 2021 $pid = <PID>; 2022 $pid =~ /(\d+)/; 2023 $pid = $1; 2024 } 2025 2026} 2027 2028POSTCMD: { 2029 last POSTCMD unless -f "$dir/config/postcopy_commands"; 2030 open(ADDL, "< $dir/config/postcopy_commands") 2031 or last POSTCMD; 2032 print "\nFound additional system commands to run.\n\n"; 2033 local ($/) = ""; 2034 while(<ADDL>) { 2035 my $unprompted; 2036 s/\s+$//; 2037 s/__MVC_([A-Z0-9]+)(__)?/substitute($1,$2)/eg; 2038 my ($command, $prompt) = split /\n/, $_, 2; 2039 $command =~ s/^\s+//; 2040 $command =~ s/\s+$//; 2041 $command =~ s/^!// and $unprompted = 1; 2042 if($command =~ s/{\s*([A-Z0-9]+)(\s*\S.*?)?\s*}\s*//) { 2043 my $param = $1; 2044 my $test = $2; 2045 my $v = $Conf{lc $param}; 2046 $v = "q{$v}"; 2047 my $true; 2048 eval { 2049 $true = eval "$v$test"; 2050 }; 2051 next unless $true; 2052 } 2053 print "$prompt\n\n"; 2054 print "Running: $command\n" if $unprompted; 2055 my $ans = $unprompted ? 'y' : prompt( qq{run "$command"? }, 'y' ); 2056 if($ans =~ /^\s*y/i) { 2057 system $command; 2058 if($?) { 2059 print "\nCommand returned error code " . ($? >> 8) . ": $!\n"; 2060 } 2061 } 2062 else { 2063 print "\nskipping '$command'\n"; 2064 } 2065 } 2066 close ADDL; 2067} 2068 my $add; 2069 my $add_tcp; 2070 my $add_inet; 2071 2072 umask(07) unless $Conf{noumask}; 2073 2074 $add = prefix('nocfg') ? 'n' : 'y'; 2075 if ($Conf{catalogconf}) { 2076 $yes = prompt "Add catalog to $Conf{catalogconf}? ", $add; 2077 } else { 2078 $yes = prompt "Add catalog to $Global::ConfigFile? ", $add; 2079 } 2080 $add = prefix('norunning') ? 'n' : 'y'; 2081 2082 if($yes and $Inetmode) { 2083 $add_tcp = prompt "Add port $lp to TcpMap in interchange.cfg if necessary? ", $add; 2084 $add_tcp = is_yes($add_tcp); 2085 $add_inet = prompt "Set Interchange to run in INET mode if necessary? ", $add; 2086 $add_inet = is_yes($add_inet); 2087 } 2088 2089 if($pid) { 2090 $add_to_running = prompt "Add catalog to server running on PID $pid? ", $add; 2091 $add_to_running = is_yes($add_to_running); 2092 } 2093 2094 my $full = ''; 2095 my $newcfgline; 2096 my $tcpmark; 2097 2098 $newcfgline = sprintf "%-10s %s %s %s %s\n", 'Catalog', 2099 $catalog_name, $Conf{catroot}, $full . $Conf{cgiurl}, $Conf{aliases}; 2100 2101 if( is_yes($yes) ) { 2102 my ($newcfgline, $mark, @out); 2103 my $tmpfile; 2104 2105 if ($Conf{catalogconf}) { 2106 $tmpfile = "$Conf{catalogconf}.$$"; 2107 File::Copy::copy ($Conf{catalogconf}, $tmpfile) 2108 or die "\nCouldn't copy $Conf{catalogconf}: $!\n"; 2109 } else { 2110 $tmpfile= "$Global::ConfigFile.$$"; 2111 if (-f $Global::ConfigFile) { 2112 File::Copy::copy ($Global::ConfigFile, $tmpfile) 2113 or die "\nCouldn't copy $Global::ConfigFile: $!\n"; 2114 } 2115 else { 2116 my @cf = ("$Global::ConfigFile.dist", "$Global::VendRoot/interchange.cfg.dist"); 2117 my $cf; 2118 for(@cf) { 2119 $cf = $_ if -f $_; 2120 } 2121 2122 File::Copy::copy($cf, $tmpfile) 2123 or die "\nCouldn't copy $cf: $!\n"; 2124 } 2125 } 2126 2127 open(CFG, "< $tmpfile") 2128 or die "\nCouldn't open $tmpfile: $!\n"; 2129 while(<CFG>) { 2130 $mark = $. if /^#?catalog\s+/i; 2131 print "\nDeleting old configuration $catalog_name.\n" 2132 if s/^(catalog\s+$catalog_name\s+)/#$1/io; 2133 $full = is_yes($1) 2134 if /^\s*fullurl\s+(.*)/i; 2135 if ($add_tcp and /^tcpmap\s+/i and $_ !~ /\b$lh:$lp\b/) { 2136 $tcpmark = /^tcpmap\s+[^<]+$/i ? $. : $. + 1; 2137 $tcpmark-- if $mark; 2138 } 2139 push @out, $_; 2140 } 2141 close CFG; 2142 2143 if($full) { 2144 $full = $Conf{servername}; 2145 } 2146 2147 if ($Conf{catalogconf}) { 2148 open(NEWCFG, ">$Conf{catalogconf}") 2149 or die "\nCouldn't write $Conf{catalogconf}: $!\n"; 2150 } else { 2151 open(NEWCFG, ">$Global::ConfigFile") 2152 or die "\nCouldn't write $Global::ConfigFile: $!\n"; 2153 } 2154 2155 $newcfgline = sprintf "%-13s %s %s %s %s\n", 'Catalog', 2156 $catalog_name, $Conf{catroot}, $full . $Conf{cgiurl}, $Conf{aliases}; 2157 2158 if($tcpmark) { 2159 $out[$tcpmark] =~ s/\s*$/ $lh:$lp -\n/; 2160 } 2161 2162 if($add_inet) { 2163 my $found_inetmode; 2164 for(@out) { 2165 next unless /^\s*inet_mode\s+/i; 2166 $_ = "Inet_Mode Yes\n"; 2167 $found_inetmode = 1; 2168 last; 2169 } 2170 if(! $found_inetmode) { 2171 push @out, "Inet_Mode Yes\n"; 2172 } 2173 } 2174 2175 if (defined $mark) { 2176 print NEWCFG @out[0..$mark-1]; 2177 print NEWCFG $newcfgline; 2178 print NEWCFG @out[$mark..$#out]; 2179 } 2180 else { 2181 $newconfig = 1; 2182 print "\nNo catalog previously defined. Adding $catalog_name at top.\n"; 2183 print NEWCFG $newcfgline; 2184 print NEWCFG @out; 2185 } 2186 2187 close NEWCFG || die "close: $!\n"; 2188 unlink $tmpfile; 2189 if($isroot) { 2190 chown ($mvuid, $mvgid, $Global::ConfigFile) 2191 or warn "Couldn't set ownership of '$Global::ConfigFile': $!\n"; 2192 } 2193 } 2194 else { 2195 print <<EOF; 2196You will need to add the following line to your $Global::ConfigFile file 2197to activate the catalog. 2198 2199$newcfgline 2200 2201EOF 2202 } 2203 2204 $newcfgline = sprintf "%-13s %s %s %s %s\n", 'Catalog', 2205 $catalog_name, $Conf{catroot}, $full . $Conf{cgiurl}, $Conf{aliases}; 2206 2207 if($add_to_running) { 2208 my $fn = 'etc/restart'; 2209 open(RESTART, ">>$fn") or 2210 die "Couldn't write $fn to add catalog: $!\n"; 2211 Vend::Util::lockfile(\*RESTART, 1, 1) or die "lock $fn: $!\n"; 2212 printf RESTART $newcfgline; 2213 Vend::Util::unlockfile(\*RESTART) or die "unlock $fn: $!\n"; 2214 close RESTART; 2215 if($isroot) { 2216 chown ($mvuid, $mvgid, $fn) 2217 or warn "\nCouldn't set ownership of $fn: $!\n"; 2218 } 2219 unless ($Windows) { 2220 kill 'HUP', $pid; 2221 sleep 1; 2222 } 2223 $fn = 'etc/reconfig'; 2224 open(RESTART, ">>$fn") or 2225 die "Couldn't write $fn to add catalog: $!\n"; 2226 Vend::Util::lockfile(\*RESTART, 1, 1) or die "lock $fn: $!\n"; 2227 printf RESTART $full . $Conf{cgiurl} . "\n"; 2228 if($isroot) { 2229 chown ($mvuid, $mvgid, $fn) 2230 or warn "\nCouldn't set ownership of $fn: $!\n"; 2231 } 2232 Vend::Util::unlockfile(\*RESTART) or die "unlock $fn: $!\n"; 2233 close RESTART; 2234 unless ($Windows) { 2235 kill 'HUP', $pid; 2236 } 2237 } 2238 2239 my $start_string = $> == 0 2240 ? qq(su -c "$Conf{vendroot}/bin/interchange -r" $Conf{interchangeuser}) 2241 : "$Conf{vendroot}/bin/interchange -r"; 2242 2243 print <<EOF; 2244 2245Done with installation. If my reading of your input is correct, you 2246should be able to access the demo catalog with the following URL: 2247 2248 $Conf{sampleurl} 2249 2250In any case, you should get direct access at: 2251 2252 http://$Conf{servername}$Conf{cgiurl} 2253 2254That is, after you START or RESTART the Interchange server. 8-) 2255It is best done with: 2256 2257 $start_string 2258 2259EOF 2260 CHECKEXPIRE: { 2261 my $dbm; 2262 my $message; 2263 eval { require GDBM_File; $dbm = 1; }; 2264 eval { require DB_File; $dbm = 1; }; 2265 2266 if(! $Windows and $dbm) { 2267 2268 print <<EOF; 2269For session expiration, you might want to place a line like this in your 2270crontab: 2271 227244 4 * * * $Conf{vendroot}/bin/expireall -r 2273 2274It will prevent the session databases from getting too large. 2275 2276EOF 2277 2278 } 2279 else { 2280 print <<EOF; 2281Remember to expire your session databases on a regular basis (see 2282the documentation for details). 2283 2284EOF 2285 } 2286 } 2287 2288 print "Good luck with Interchange!\n" if defined $newconfig; 2289 2290 if($Conf{'reference'}) { 2291 $Data::Dumper::Terse = 1; 2292 $Data::Dumper::Indent = 3; 2293 print STDOUT Vend::Util::uneval(\%Conf); 2294 } 2295 2296=head1 NAME 2297 2298makecat - Build an Interchange catalog from a template 2299 2300=head1 SYNOPSIS 2301 2302makecat [--options] name 2303 2304=head1 VERSION 2305 2306# $Id: makecat.PL,v 2.27 2007-08-09 13:40:57 pajamian Exp $ 2307 2308=head1 INTRODUCTION 2309 2310The makecat program builds a Interchange catalog from a template based on your 2311server configuration. It interrogates for parameters like the directories to 2312use, URL to base the catalog in, HTTP server definitions, and file ownership. 2313It is self-documenting in that it asks verbose questions and gives relevant 2314examples. 2315 2316On UNIX, if you want to check on something during the process you can 2317usually hit <CTRL-Z> to suspend the program and do something and then 2318type C<fg> to return to <makecat>. Also, if your input begins with 2319an exclamation mark (C<!>), it will be interpreted as a shell command. 2320An exclamation mark (C<!>) alone should drop you into a shell. 2321 2322If you have the C<Term::ReadLine::Perl> and C<Term::ReadKey> modules 2323installed, the <UP> and <DOWN> arrows will cycle between suggested defaults; 2324and the following features will be in place: 2325 2326 TAB Completes file name 2327 <UP> Cycle suggestion up 2328 <DOWN> Cycle suggestion down 2329 <CTRL-P> Cycle suggestion up 2330 <CTRL-N> Cycle suggestion down 2331 <CTRL-B> Go back one question (if possible) 2332 <CTRL-U> Erase line 2333 <LEFT> Command-line editing left 2334 <RIGHT> Command-line editing left 2335 2336Also, if you make a mistake at some stage of the interrogation, you can 2337often hit the <CTRL-B> key to return to the previous query. If you don't 2338have Term::ReadLine installed, then you can enter an at sign (C<@>) by 2339itself on the line. 2340 2341=head1 OPTIONS 2342 2343usage: makecat [options] [catalogname] 2344 2345The makecat program can build a catalog based completely on a command line 2346description. An example is in eg/makecat.sh. 2347 2348There are just a few flag-based options: 2349 2350=over 4 2351 2352=item C<-F> 2353 2354Force make of catalog with defaults supplied on command line. 2355 2356=item C<-c> 2357 2358Configuration file -- default is makecat.cfg in Interchange Confdir (etc) directory. 2359 2360=item C<-l> 2361 2362File to log to (default makecat.log) 2363 2364=item C<-r> 2365 2366Reconfigure defaults normally set in makecat.cfg; this is done automatically 2367the first time the program is run. 2368 2369=back 2370 2371The remainder of the options are supplied on the command line as named 2372parameters followed by an C<=> sign, followed by the value, i.e. 2373 2374 --parameter=value 2375 2376Normally, if C<makecat> supplies a default you might guess at that. It 2377is fairly intelligent if you have an Apache server and it has found the 2378httpd.conf file. If you are on a Netscape or other web server, it is 2379less likely to be right. 2380 2381The options set at reconfig time, i.e. the first time the program is run: 2382 2383=over 4 2384 2385=item --basedir=directory 2386 2387Base directory for catalogs. This defaults to C<catalogs> in the home 2388directory of the catalog user. 2389 2390=item --cgibase=url_fragment 2391 2392Base URL for link programs. This is normally either blank (your programs 2393are made with .cgi extension) or C</cgi-bin> (you have a CGI directory). 2394 2395=item --documentroot=directory 2396 2397The directory where HTML is based. This is the root directory of the 2398web server, i.e. DocumentRoot. 2399 2400=item --interchangegroup=group 2401 2402The default group files should be owned by. 2403 2404=item --interchangeuser=username 2405 2406The user ID which runs Interchange. 2407 2408=item --serverconf=filename 2409 2410Location of httpd.conf; you will be queried otherwise. 2411 2412=item --vendroot=filename 2413 2414Location of Interchange software. 2415 2416=item --homedir=directory 2417 2418Use instead of \$HOME to set defaults 2419 2420=back 2421 2422These are options which are required to be set for any catalog; the 2423default will often be correct if you have set the above options correctly. 2424 2425=over 4 2426 2427=item --catroot=directory 2428 2429Directory where Interchange catalog files go. This is the base directory 2430for this catalog. 2431 2432=item --cgidir=directory 2433 2434The directory the CGI link should go to. This is the CGI directory; if 2435your CGI programs all end in C<.cgi> then this would normally be the same 2436as C<documentroot>; if you have a C<cgi bin> directory it should be used. 2437 2438=item --servername=server 2439 2440Name of server (www.whatever.domain). You can supply a port: 2441 2442 www.foo.com:8080 2443 2444or a username: 2445 2446 www.foo.com/~bar 2447 2448For testing on your local machine, just use C<localhost>. 2449 2450=item --cgiurl=url_fragment 2451 2452The path to the CGI link (no server name). For a catalog named 2453C<standard>, this would normally be one of: 2454 2455 --cgiurl=/cgi-bin/standard 2456 2457or 2458 2459 --cgiurl=/standard.cgi 2460 2461 2462=item --demotype=template 2463 2464The template catalog. The default is <standard>. 2465 2466=item --mailorderto=email 2467 2468Email address to send orders 2469 2470=item --catuser=username 2471 2472The user files should be owned by (option only operative if C<root>). 2473 2474=back 2475 2476The rest of the parameters need not be supplied on the 2477command line as intelligent defaults can be derived from 2478the above parameters. 2479 2480=over 4 2481 2482=item --samplehtml=directory 2483 2484The directory where template HTML goes. 2485 2486=item --imagedir=directory 2487 2488The directory where template images go. 2489 2490=item --imageurl=url 2491 2492The URL to prefix images with. 2493 2494=item --sharedir=directory 2495 2496The directory where shared admin images go. 2497 2498=item --shareurl=url 2499 2500The URL to prefix shared admin images with. 2501 2502=item --nocfg 2503 2504Don't add to interchange.cfg. 2505 2506=item --nocopy 2507 2508Don't actually copy the files, just test. 2509 2510=item --norunning 2511 2512Don't add to running server. 2513 2514=item --reference 2515 2516Return hash of config as string (sets C<-F>, no write). This is for 2517passing back to the makecat program in a autobuild environment. 2518 2519=item --linkprogram=file 2520 2521Use file as link program instead of vlink/tlink. 2522 2523=item --linkmode=mode 2524 2525UNIX or INET (link program vlink or tlink). 2526 2527=item --sampleurl=url 2528 2529URL to access HTML for catalog. 2530 2531=item --noumask 2532 2533Don't set umask to the value implied by mode. 2534 2535=item --catalogconf=file 2536 2537Use file as configuration file for catalog definitions. This option 2538has been designed for the use with Debian installations. 2539 2540=back 2541 2542=head1 DESCRIPTION 2543 2544C<makecat> needs a template catalog to operate on. The I<Foundation 2545Store> demo template is distributed with Interchange. You can 2546also look for additional demo catalogs (mostly for ideas) at 2547http://www.icdevgroup.org/ 2548 2549B<IMPORTANT NOTE:> You only make a catalog once. All further configuration 2550is done by editing the files within the I<catalog directory>. 2551 2552A catalog template contains an image of a configured catalog. The best 2553way to see what the makecat program does is to configure the 'standard' 2554demo and then run a recursive C<diff> on the template and configured 2555catalog directories: 2556 2557 diff -r interchange/standard catalogs/standard 2558 2559You will see that the files are mostly the same, except that certain 2560macro strings have been replaced with the answers you gave to the script. 2561For example, if you answered C<www.mydomain.com> at the prompt 2562for server name, then you would see this difference in the catalog.cfg file: 2563 2564 # template 2565 Variable SERVER_NAME __MVC_SERVERNAME__ 2566 2567 # configured catalog 2568 Variable SERVER_NAME www.mydomain.com 2569 2570The macro string __MVC_SERVERNAME__ was substituted with the answer to 2571the question about server name. In the same way, other variables are 2572substituted, and include (at least): 2573 2574 MVC_BASEDIR MVC_IMAGEDIR 2575 MVC_CATROOT MVC_IMAGEURL 2576 MVC_CATUSER MVC_MAILORDERTO 2577 MVC_CGIBASE MVC_MINIVENDGROUP 2578 MVC_CGIDIR MVC_MINIVENDUSER 2579 MVC_CGIURL MVC_SAMPLEHTML 2580 MVC_DEMOTYPE MVC_SAMPLEURL 2581 MVC_DOCUMENTROOT MVC_VENDROOT 2582 MVC_ENCRYPTOR 2583 2584(Not all of these are present in the standard template, and 2585quite a few more may be defined.) In fact, any environment variable that 2586is set and begins with MVC_ will be substituted for by the C<makecat> 2587script. So if you wanted to set up a configurable parameter to customize 2588the COMPANY variable in catalog.cfg, you could run a pre-qualifying 2589script that set the environment variable MVC_COMPANY and then place in 2590the catalog.cfg file: 2591 2592 Variable COMPANY __MVC_COMPANY__ 2593 2594All files within a template directory are substituted for macros, 2595not just the catalog.cfg file. There are two special directories 2596named C<html> and C<images>. These will be recursively copied to 2597the directories defined as SampleHTML and ImageDir. 2598 2599B<IMPORTANT NOTE:> The template directory is located in the Interchange 2600software directory, i.e. where C<interchange.cfg> resides. You normally do 2601not edit files in the template directory. If you want to try creating 2602your own template, it is recommended that you name it something besides 2603standard and copy the C<standard> demo directory to it as a starting point. 2604Templates are normally placed in the Interchange base directory, but can 2605be located anywhere -- the script will prompt you for location if it 2606cannot find a template. 2607 2608In addition to the standard parameters prompted for by Interchange, and 2609the standard catalog creation procedure, you may define four other 2610files in the C<config> directory of the template: 2611 2612 additional_fields -- file with more parameters for macro substitution 2613 additional_help -- extended description for the additional_fields 2614 precopy_commands -- commands passed to the system prior to catalog copy 2615 postcopy_commands -- commands passed to the system after catalog copy 2616 2617All files are paragraph-based; in other words, a blank line (with no spaces) 2618terminates the individual setting. 2619 2620The I<additional_fields> file contains: 2621 2622 PARAM 2623 The prompt. Set PARAM to? 2624 The default value of PARAM 2625 2626This would cause a question during makecat: 2627 2628 The prompt. Set PARAM to?.....[The default value of PARAM] 2629 2630If the I<additional_help> file is present, you can give additional 2631instructions for PARAM. 2632 2633 PARAM 2634 These are additional instructions for PARAM, and they 2635 may span multiple lines up to the first blank line. 2636 2637The prompt would now be: 2638 2639 These are additional instructions for PARAM, and they 2640 may span multiple lines up to the first blank line. 2641 2642 The prompt. Set PARAM to?.....[The default value of PARAM] 2643 2644If the file I<config/precopy_commands> exists, it will be read as 2645a command followed by the prompt/help value. 2646 2647 mysqladmin create __MVC_CATALOGNAME__ 2648 We need to create an SQL database for your Interchange 2649 database tables. 2650 2651This will cause the prompt: 2652 2653 We need to create an SQL database for your Interchange 2654 database tables. 2655 2656 Run command "mysqladmin create test_standard"? 2657 2658If the response is "y" or "yes", then the command will be run 2659by passing it through the Perl system() function. As with any 2660of the additional configuration files, MVC_PARAM macro substitution 2661is done on the command and help. Obviously you must have proper 2662permissions for the command. 2663 2664The file I<config/postcopy_commands> is exactly the same as I<precopy_commands> 2665except you are prompted I<after> the catalog files are copied and 2666macro substitution is performed on all files. 2667 2668=head1 ABOUT INTERCHANGE IN GENERAL 2669 2670Interchange has many, many, functions and features; they are too numerous 2671to describe in this venue. Complete information can be found at 2672its web site: 2673 2674 http://www.icdevgroup.org/ 2675 2676Interchange requires Perl 5.6.0 or higher; more information on Perl can 2677be seen at: 2678 2679 http://www.perl.com/ 2680 2681=head1 SEE ALSO 2682 2683interchange(1) 2684 2685=head1 LICENSE 2686 2687Interchange comes with ABSOLUTELY NO WARRANTY. This is free software, and 2688you are welcome to redistribute and modify it under the terms of the 2689GNU General Public License. 2690 2691=head1 COPYRIGHT 2692 2693Copyright 2002-2007 Interchange Development Group. 2694Copyright 1995-2002, Red Hat, Inc. 2695All rights reserved except as in the license. 2696 2697=cut 2698 2699=head1 AUTHOR 2700 2701Mike Heins, <mike@perusion.com>. Please do not contact the author for 2702direct help with the system. Use the Interchange mail list: 2703 2704 interchange-users 2705 2706Information on subscribing to the list, and general information and 2707documentation for Interchange is at: 2708 2709 http://www.icdevgroup.org/ 2710 2711=cut 2712 2713__END__ 2714 2715[catalog standard] 2716basedir = 2717catroot = 2718catuser = 2719cgibase = 2720cgibin = 2721cgidir = 2722cgiurl = 2723demotype = standard 2724documentroot = 2725imagedir = 2726imageurl = 2727mailorderto = 2728interchangegroup= 2729interchangeuser = 2730samplehtml = 2731sampleurl = 2732servername = 2733vendroot = 2734 2735[base] 2736permtype= 2737basedir= 2738cgidir= 2739cgibase= 2740documentroot= 2741sharedir= 2742shareurl= 2743interchangegroup= 2744interchangeuser= 2745serverconf= 2746servername= 2747vendroot= 2748linkmode= 2749 2750# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 2751# 2752# DO NOT EDIT BELOW HERE 2753# 2754# These are global parameters used by the program 2755# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 2756 2757[global] 2758# 2759# All params allowed 2760# 2761params=<<EOF 2762aliases 2763basedir 2764catroot 2765catuser 2766cgibase 2767cgibin 2768cgidir 2769cgiurl 2770demotype 2771documentroot 2772imagedir 2773imageurl 2774linkmode 2775mailorderto 2776interchangegroup 2777interchangeuser 2778samplehtml 2779sampleurl 2780serverconf 2781servername 2782sharedir 2783shareurl 2784vendroot 2785EOF 2786 2787catparams=<<EOF 2788aliases 2789catroot 2790catuser 2791cgidir 2792cgiurl 2793demotype 2794documentroot 2795imagedir 2796imageurl 2797mailorderto 2798interchangegroup 2799interchangeuser 2800samplehtml 2801sampleurl 2802servername 2803EOF 2804 2805# 2806# Default (base) parameters to ask about, in order 2807# 2808askbase=<<EOF 2809cgidir 2810cgibase 2811documentroot 2812sharedir 2813shareurl 2814vendroot 2815basedir 2816interchangeuser 2817linkmode 2818EOF 2819 2820# 2821# Catalog parameters to ask about, in order 2822# 2823askconfig=<<EOF 2824demotype 2825permtype 2826interchangeuser 2827catuser 2828interchangegroup 2829mailorderto 2830catroot 2831cgidir 2832cgiurl 2833aliases 2834documentroot 2835samplehtml 2836imagedir 2837imageurl 2838EOF 2839 2840######## END GLOBAL SECTION ######## 2841 2842# Simple test to make sure legal for config file 2843[legalconfig] 2844aliases=1 2845cgidir=1 2846cgiurl=1 2847catuser=1 2848demotype=1 2849imagedir=1 2850imageurl=1 2851mailorderto=1 2852interchangeuser=1 2853interchangegroup=1 2854permtype=1 2855samplehtml=1 2856sampleurl=1 2857servername=1 2858catroot=1 2859 2860# Simple test to make sure legal for base file 2861[legalbase] 2862basedir=1 2863cgidir=1 2864cgibase=1 2865documentroot=1 2866interchangegroup=1 2867interchangeuser=1 2868serverconf=1 2869servername=1 2870sharedir=1 2871shareurl=1 2872vendroot=1 2873linkmode=1 2874