#!/bin/sh
eval 'if [ -x /usr/local/cpanel/3rdparty/bin/perl ]; then exec /usr/local/cpanel/3rdparty/bin/perl -x -- $0 ${1+"$@"}; else exec /usr/bin/perl -x $0 ${1+"$@"}; fi;'
  if 0;

#!/usr/bin/perl

# targz/Cpanel/Easy/Xcache.pm.tar.gz.d/cpanel-install
#                                                 Copyright(c) 2014 cPanel, Inc.
#                                                           All rights Reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited

use strict;
use warnings;

BEGIN {
    unshift @INC, '/usr/local/cpanel';
}

use Cpanel::SafeRun   ();
use Cpanel::FileUtils ();
use Cpanel::SafeFile  ();
use IO::Handle;

my $installed       = 0;
my $current_version = 'xcache-3';

my @prefixes = ( '/usr/local', '/usr/local/php4' );
if (@ARGV) {
    @prefixes = @ARGV;
}

foreach my $php_prefix (@prefixes) {
    $php_prefix =~ s/\/$//;
    my $php_ini = $php_prefix . '/lib/php.ini';
    if ( $php_prefix eq '/usr/local/cpanel/3rdparty' || $php_prefix eq '/var/cpanel/3rdparty' ) {
        $php_ini = '/usr/local/cpanel/3rdparty/etc/php.ini';
    }
    unless ( -e $php_ini ) {
        print "Skipping install to $php_prefix, missing php.ini\n";
        next;
    }
    unless ( -e $php_prefix . '/bin/php' ) {
        print "Skipping install to $php_prefix, missing php\n";
        next;
    }
    unless ( -e $php_prefix . '/bin/phpize' ) {
        print "Skipping install to $php_prefix, missing phpize\n";
        next;
    }
    unless ( -e $php_prefix . '/bin/php-config' ) {
        print "Skipping install to $php_prefix, missing php-config\n";
        next;
    }

    # determine version to use
    print "Determining PHP version\n";
    my @cmd;
    if ( -e '/usr/local/cpanel/scripts/php.ini' ) {
        @cmd = ( $php_prefix . '/bin/php', '-c', '/usr/local/cpanel/scripts/php.ini', '-v' );
    }
    else {
        @cmd = ( $php_prefix . '/bin/php', '-v' );
    }
    my $phpout = Cpanel::SafeRun::saferunallerrors(@cmd);
    my $php_version;
    my $src_version;
    if ( $phpout =~ m/^PHP\s+(\d+\.\d+)\.\d+\S*\s+\(([^\)]+)\)/m ) {
        $php_version = $1;

        my $min_version = 5.0;
        if ( $php_version < $min_version ) {
            print "PHP version $php_version is less than $min_version, I cannot install the Xcache extension for PHP\n";
            next;
        }
    }
    else {
        print "Could not determine PHP version from output:\n";
        print $phpout;
        next;
    }

    my @configure = ( './configure', '--with-php-config=' . $php_prefix . '/bin/php-config' );

    chdir $current_version || die "Could not chdir to current version $current_version";

    system( $php_prefix . '/bin/phpize' );

    my @cmds = (
        [@configure],
        [qw( make clean   )],
        [qw( make         )],
        [qw( make install )],
        [qw( make clean   )]
    );
    for my $cmd (@cmds) {
        my $ret = System( @${cmd} );
        $ret >>= 8;
        $ret && die "Command @{ [ join ' ', @{$cmd} ] } failed";
    }

    my ( $ok, $res ) = activate_xcache( $php_prefix, $php_ini );
    $installed = 1 if $ok;
    print $res . "\n";
    chdir '..' || die "Could not return to starting directory: $!";

    my $exit = $installed ? 0 : 1;
    print STDERR "$0 exiting with exit code $exit\n";
    exit $exit;
}

sub activate_xcache {
    my $prefix    = shift;
    my $ini_file  = shift;
    my $phpconfig = $prefix . '/bin/php-config';

    my $ext_dir = Cpanel::SafeRun::saferun( $phpconfig, '--extension-dir' );
    chomp $ext_dir;

    return ( 0, q{Could not locate Xcache extenstion at '[_1]}, $ext_dir . '/xcache.so' ) unless ( -e $ext_dir . '/xcache.so' );

    # An earlier version of this script erroneously considered the following to be xcache ini vars, but they are not. So we'll need to delete
    # any we find from php.ini . Notice we have omitted 'optimizer' from the list, because although it, too, was in the erroneous list,
    # it happens also to be in the correct list (see %xcache_settings below); the only difference is that we earlier thought its default was
    # '1', but it's real default is 'Off'. We'll deal with that oddity later.
    my @not_xcache_settings = qw(
      shm_size
      cache_dir
      enable
      check_mtime
      debug
      filter
      shm_max
      shm_ttl
      shm_prune_period
      shm_only
      compress
      compress_level
      admin_user
      admin_pass
      admin_enable_auth
    );

    my %xcache_settings = (
        'admin.user' => 'mOo', 'admin.pass' => ''
        , 'admin.enable_auth'      => 'on'
        , 'test'                   => 'Off'
        , 'coredump_directory'     => ''
        , 'cacher'                 => 'On'
        , 'size'                   => '0'
        , 'count'                  => '1'
        , 'slots'                  => '8K'
        , 'ttl'                    => '0'
        , 'gc_interval'            => '0'
        , 'var_size'               => '0'
        , 'var_count'              => '1'
        , 'var_slots'              => '8K'
        , 'var_ttl'                => '0'
        , 'var_maxttl'             => '0'
        , 'var_gc_interval'        => '300'
        , 'readonly_protection'    => 'Off'
        , 'mmap_path'              => '/dev/zero'
        , 'optimizer'              => 'Off'
        , 'coverager'              => 'Off'
        , 'coveragedump_directory' => '/tmp/pcov/'
    );

    my $ini_fh = IO::Handle->new();
    my $lock = Cpanel::SafeFile::safeopen( $ini_fh, '+<', $ini_file );
    return ( 0, "Failed to open $ini_file for writing: $!" ) unless $lock;
    my @ini_contents = ();
    my $extension_dir_line;    # This will actually point to the last line before the extension_dir line
    my $line_counter = -1;
    while ( my $line = readline($ini_fh) ) {
        next if ( $line =~ /^\s*(zend_)?extension(_ts)?\s*=\s*"?\S*xcache\.so"?\s*$/ );
        if ( $line =~ /^\s*xcache\.([^\s=]+)\s*=\s*['"]?([^\s'"]*?)['"]?\s*$/ ) {
            my ( $key, $val ) = ( $1, $2 );
            if ( grep { $key eq $_ } @not_xcache_settings ) {
                next;          # Skip, it's not an xcache setting, if present it's an error.
            }

            # Optimizer is a special case because, as mentioned earlier, this script once erroneously
            # thought its default to be '1', but we now know its true default is 'Off'.
            $val = 'Off' if $key eq 'optimizer' && $val eq '1';    # [sic] (a human would use 'On', presumably)

            $xcache_settings{$key} = $val;
            next;
        }
        if ( $line =~ /^\s*;?\s*extension_dir\s*=.*$/ ) {
            $extension_dir_line = $line_counter;
            next;
        }
        $line_counter++;
        push @ini_contents, $line;
    }

    seek( $ini_fh, 0, 0 );

    # Deal with no extension_dir line
    if ( !defined $extension_dir_line || $extension_dir_line < 0 ) {
        $extension_dir_line = $#ini_contents;
    }

    # Deal with last line missing newline
    if ( $#ini_contents >= 0 && $ini_contents[$#ini_contents] !~ /\n$/s ) {
        $ini_contents[$#ini_contents] .= "\n";
    }

    print $ini_fh @ini_contents[ 0 .. $extension_dir_line ];
    print $ini_fh qq{extension_dir = "$ext_dir"\nextension="xcache.so"\n};
    foreach my $setting_name ( sort keys %xcache_settings ) {
        my $setting_value = $xcache_settings{$setting_name};
        print $ini_fh qq{xcache.${setting_name}="${setting_value}"\n};
    }
    if ( ++$extension_dir_line <= $#ini_contents ) {
        print $ini_fh @ini_contents[ $extension_dir_line .. $#ini_contents ];
    }

    truncate( $ini_fh, tell($ini_fh) );
    Cpanel::SafeFile::safeclose( $ini_fh, $lock );

    return ( 1, 'Xcache extension activated' );
}

sub System {
    my @args = @_;
    printf STDERR "Will now run system( %s )\n", ( join ',', @args );
    my $ret = system @_;
    printf STDERR "Got ret value %s from system( %s )\n", $ret, ( join ',', @args );
    return $ret;
}
