#!/usr/bin/env perl # # Script taken from InspIRCd, https://www.inspircd.org/ # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # BEGIN { require 5.8.0; } use strict; use warnings FATAL => qw(all); use File::Copy (); use Cwd; sub list_extras (); sub enable_extras (@); sub disable_extras (@); # Routine to list out the extra/ modules that have been enabled. # Note: when getting any filenames out and comparing, it's important to lc it if the # file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32 # (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on # configuration, however, File::Spec does not currently tell us (it assumes Unix behavior). sub list_extras () { use File::Spec; # @_ not used my $srcdir = File::Spec->catdir("modules"); my $abs_srcdir = File::Spec->rel2abs($srcdir); local $_; my $dd; opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n"); my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd)); closedir $dd; undef $dd; opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n"; my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd)); closedir $dd; undef $dd; my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0]; my %extras = (); EXTRA: for my $extra (@extras) { next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra); my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra); my $abs_source = File::Spec->catfile($abs_srcdir, $extra); next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory if (-l $abs_source) { # Symlink, is it in the right place? my $targ = readlink($abs_source); my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir); if ($abs_targ eq $abs_extra) { $extras{$extra} = "\e[32;1menabled\e[0m"; } else { $extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ); } } elsif (-e $abs_source) { my ($devext, $inoext) = stat($abs_extra); my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source); if ($lnksrc > 1) { if ($devsrc == $devext && $inosrc == $inoext) { $extras{$extra} = "\e[32;1menabled\e[0m"; } else { $extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc); } } else { open my $extfd, "<", $abs_extra; open my $srcfd, "<", $abs_source; local $/ = undef; if (scalar(<$extfd>) eq scalar(<$srcfd>)) { $extras{$extra} = "\e[32;1menabled\e[0m"; } else { $extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m"); } } } else { $extras{$extra} = "\e[33;1mdisabled\e[0m"; } } for my $extra (sort {$a cmp $b} keys(%extras)) { my $text = $extras{$extra}; if ($text =~ m/needed by/ && $text !~ m/enabled/) { printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : ""); } else { printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : ""); } } return keys(%extras) if wantarray; # Can be used by manage_extras. } sub enable_extras (@) { my (@extras) = @_; for my $extra (@extras) { my $extrapath = "modules/extra/$extra"; if (!-e $extrapath) { print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in modules/extra\n"; next; } my $source = "modules/$extra"; if (-e $source) { print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in modules exists (might already be enabled?)\n"; next; } print "Enabling $extra ... \n"; symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n"; } } sub disable_extras (@) { opendir my $dd, "modules/extra/"; my @files = readdir($dd); closedir $dd; my (@extras) = @_; EXTRA: for my $extra (@extras) { my $extrapath = "modules/extra/$extra"; my $source = "modules/$extra"; if (!-e $extrapath) { print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n"; next; } if ((! -l $source) || readlink($source) ne "extra/$extra") { print STDERR "Cannot disable \e[32;1m$extra\e[0m : Source is not a link or doesn't refer to the right file. Remove manually if this is in error.\n"; next; } # Now remove. print "Disabling $extra ... \n"; unlink "modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n"; } } my $clearscreen = `clear`; print $clearscreen; while (1) { list_extras; # print the module list print "\nPlease enter the name of the module or type 'q' to quit.: "; my $input = ; chop($input); # remove the trailing \n from the user input if ($input eq "q") { if (-e "build/CMakeFiles") { system("cmake", "build/."); print "\nNow cd build, then run make to build Anope.\n\n"; } else { print "\nBuild directory not found. You should run ./Config now.\n\n" } exit 0; } print $clearscreen; if ($input eq "") { next; } if (-e "modules/$input") { disable_extras($input) } else { enable_extras($input) } }