#!/usr/bin/env perl ############################################################################## # $HeadURL: http://svn.dev.rambler.ru/cndinst/trunk/bin/install $ # $Id: install 65 2009-12-18 12:09:37Z abavykin $ ############################################################################## use strict; use File::Spec; use FindBin qw($RealBin); use Getopt::Long; use User::grent; use User::pwent; # defaults my $options = { svn_program => (`which svn` =~ /(.*)/)[0], core_repository => ($ENV{CORE_REPOSITORY} || 'http://contenido.me/repos/Contenido/utf8/core'), server => (`hostname` =~ /(.*)/)[0], httpd_port => ($ENV{HTTPD_PORT} || 0), db_type => 'R', backups => '/spool/backups', crosslinks => '/spool/crosslinks', sessions => '/spool/sessions', }; my ($force, $help); GetOptions('force' => \$force, 'help' => \$help); if ($help) { &usage; exit; } my $yes_no = { y => 'YES', n => 'NO' }; my $db_types = { N => 'NONE', R => 'REMOTE', S => 'SINGLE' }; # begin my ($user, $group, $umask) = (getpwuid($>), getgrgid($)), sprintf('%03o', umask)); my $destdir = $ENV{CNDINST_DESTDIR} || undef; (my $home = $user->dir) =~ s/\/+$//; load_conf($home, $options); START: while ($umask !~ /^\d0\d$/) { my $a = user_prompt("Current umask ($umask) isn't group friendly. Are you sure?", default => 'n'); last if $a eq 'y'; next unless $a eq 'n'; print "Correct umask and try again!\n"; exit 0; } print sprintf (<<'EOM' Start installation as: User: %s [%d] Group: %s [%d] Home: %s Shell: %s Umask: %s EOM , $user->name, $user->uid, $group->name, $group->gid, $home, $user->shell, $umask); while (1) { my $a = lc(user_prompt('Is it correct?', default => 'y')); last if $a eq 'y'; next unless $a eq 'n'; print "Bye, see you later!\n"; exit 0; } while (1) { $destdir = user_prompt('Enter installation directory (absolute path)', default => $destdir ? $destdir : $home."/Contenido", ignore_force=>1); next unless $destdir; $destdir = File::Spec->canonpath($destdir); $destdir =~ s/\/*$//; if (-d $destdir) { unless (is_dir_empty($destdir)) { print "Directory exists and non-empty!\n"; undef $destdir; next; } unless (-w $destdir) { print "Directory exists, but you have no write permissions in it!\n"; undef $destdir; next; } } else { my @dirs = split /\/+/, $destdir; my $pdir = '/'.join('/', @dirs[0..$#dirs-1]); unless (-w $pdir) { print "You have no permissions to create directory!\n"; undef $destdir; next; } } last; } while (1) { my $a = lc(user_prompt('Which is svn executable?', default => $options->{svn_program})); unless ($a && -x $a) { print "There is no svn executable!\n"; next; } $options->{svn_program} = $a; save_conf($home, $options); last; } while (1) { my $a = user_prompt('Which Contenido repository will be checked out?', default => $options->{core_repository}); $a =~ s/\/$//; print "Contacting repository... "; next if system("$options->{svn_program} ls $a >/dev/null"); print "success\n"; $options->{core_repository} = $a; save_conf($home, $options); last; } while (1) { my $a = user_prompt('Enter server name', default => $options->{server}); next unless $a =~ /^[\w\-\+\.]+$/i; $options->{server} = $a; save_conf($home, $options); last; } while (1) { my $a = user_prompt('Enter HTTP port', default => $options->{httpd_port}, ignore_force=>1); next unless $a =~ /^(\d)+$/i; next if int($a)<1024 || int($a)>65535; my %occupied = map {chomp; s/.*?(\d+)$/$1/; $_ => 1} `netstat -na | grep LISTEN | awk '{print \$4}'`; if ($occupied{$a}) { my $ao; while (1) { $ao = lc(user_prompt('Port seems busy. Are you sure?', default => 'n')); last if $ao eq 'y'; next unless $ao eq 'n'; last; } next unless $ao eq 'y'; } $options->{httpd_port} = $a; save_conf($home, $options); last; } while (1) { my $a = user_prompt('Select database type: [N]ONE [R]EMOTE [S]INGLE', default => $options->{db_type}, ignore_force=>1); next unless $a =~ /^[NRS]$/i; $options->{db_type} = uc($a); save_conf($home, $options); last; } while (1) { my $a = user_prompt('Enter backups directory', default => $options->{backups}); next unless $a; $options->{backups} = $a; save_conf($home, $options); last; } while (1) { my $a = user_prompt('Enter crosslinks directory', default => $options->{crosslinks}); next unless $a; $options->{crosslinks} = $a; save_conf($home, $options); last; } while (1) { my $a = user_prompt('Enter sessions directory', default => $options->{sessions}); next unless $a; $options->{sessions} = $a; save_conf($home, $options); last; } print <{svn_program} Contenido repository: $options->{core_repository} Server name: $options->{server} HTTP port: $options->{httpd_port} Database type: $db_types->{$options->{db_type}} Backups directory: $options->{backups} Crosslinks directory: $options->{crosslinks} Sessions directory: $options->{sessions} EOM ; while (1) { my $a = lc(user_prompt('Is it correct?', default => 'y')); last if $a eq 'y'; next unless $a eq 'n'; print "\n\nRestarting config procedure\n\n\n"; goto START; } print "\nGreat, start installation!\n\n"; print "Creating installation directory...\n"; mkdir $destdir, 0775 or die "Can't mkdir: $destdir - $!" unless -d $destdir; print "Creating installation layout...\n"; system("cp -R $RealBin/../skel/* $destdir/") and die "Can't copy: skel - $!"; system("find $destdir -depth -type d -name .svn -exec rm -Rf {} \\;") and die "Can't clean - $!"; system("find $destdir -depth \\! -perm +20 -exec chmod g+w {} \\;") and die "Can't chmod - $!"; unlink "$destdir/config.mk.proto" or die $!; print "Checking out Contenido core...\n"; system("$options->{svn_program} co $options->{core_repository} $destdir/src/core/") and die < $user->name, ROOT_DIR => $destdir, SERVER => $options->{server}, HTTPD_PORT => $options->{httpd_port}, DB_TYPE => $db_types->{$options->{db_type}}, BACKUPS => $options->{backups}, CROSSLINKS => $options->{crosslinks}, SESSIONS => $options->{sessions}, }; open PROTO, "< $RealBin/../skel/config.mk.proto" or die "Can't read: config.mk.proto - $!"; open MK, "> $destdir/config.mk" or die "Can't create: config.mk - $!"; print MK @{ rewrite([], $rewrites) }; close MK; close PROTO; print " done\n"; print <; chomp $answer; return $answer ? $answer : $opts{default}; } sub is_dir_empty { my $dir = shift; opendir D, $dir; while ($_ = readdir D) { next if $_ eq '.' || $_ eq '..'; return 0; } closedir D; return 1; } sub load_conf { my ($home, $options) = @_; return save_conf($home, $options) unless -f "$home/.cndinst/install.conf"; open CONF, "< $home/.cndinst/install.conf" or die "Can't read: $home/.cndinst/install.conf - $!"; while () { chomp; next if /^\s*#/; next unless /^\s*([^\s]+)\s*=\s*([^\s]+)/; next unless exists $options->{$1}; $options->{$1} = $2; } close CONF; return $options; } sub save_conf { my ($home, $options) = @_; mkdir "$home/.cndinst", 0775 or die "Can't mkdir: $home/.cndinst - $!" unless -d $home.'/.cndinst'; open CONF, "> $home/.cndinst/install.conf" or die "Can't create: $home/.cndinst/install.conf - $!"; print CONF "# Contenido installer config file\n\n"; printf CONF "%-20s = %s\n", $_, $options->{$_} for sort keys %{$options}; close CONF; } sub rewrite { my ($lines, $rewrites) = @_; s/\@([A-Z0-9\_]+)\@/$rewrites->{$1}/ms for @{$lines}; return $lines; } sub usage { print <