0
  "   ˆl–Ðz¾”Jj"TÒ�zàœ¸”Å£Åƒx-ÀÇ Ì    #!/usr/local/cpanel/3rdparty/bin/perl

# cpanel - scripts/try-later                       Copyright 2022 cPanel, L.L.C.
#                                                           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;

use Cpanel::Alarm           ();
use Cpanel::Binaries        ();
use Cpanel::SafeRun::Errors ();
use Cpanel::SafeRun::Object ();
use Cpanel::Usage           ();
use DateTime                ();
use IPC::Open3              ();
use Cpanel::Version::Full   ();

my $act_finally;
my $action_command;
my $at_args;
my $check_command;
my $delay = 5;
my $max_retries;
my $skip_first;
my $has_jobs;
my $at_cmd  = Cpanel::Binaries::path('at');
my $atd_cmd = Cpanel::Binaries::path('atd');

if ( !-x $at_cmd || !-x $atd_cmd ) {
    print_usage_and_exit('System "at" command required to run this utility.');
}

Cpanel::Usage::wrap_options(
    \@ARGV,
    \&print_usage_and_exit,
    {
        'act-finally' => \$act_finally,
        'action'      => \$action_command,
        'at'          => \$at_args,
        'check'       => \$check_command,
        'delay'       => \$delay,
        'max-retries' => \$max_retries,
        'skip-first'  => \$skip_first,
        'has-jobs'    => \$has_jobs,
    },
);

if ($has_jobs) {

    # exit 0 : queue is empty
    # exit 1 : queue has at least one job
    exit try_later_has_jobs();
}

if ( !$action_command ) {
    print_usage_and_exit('An action command is required.');
}

if ( !$check_command ) {
    print_usage_and_exit('A check command is required');
}

# The extra parens are necessary.
if ( $max_retries && ( $max_retries !~ m/^\d+$/ || $max_retries < 1 ) ) {
    print_usage_and_exit('Invalid value for --max-retries');
}

# if we're skipping running the check immediately, then
# we need to add a retry as it is decremented during
# do_later
if ( $skip_first && $max_retries ) {
    ++$max_retries;
}

if ( $delay && $delay =~ m/^\d+$/ && $delay > 0 ) {

    # at seems to subtract a minute from the now +, so adding
    # an extra minute seems to make it more understandable
    ++$delay;
    $at_args = "now + $delay minutes";
}
elsif ($delay) {
    print_usage_and_exit('Invalid value for --delay');
}

check() unless $skip_first;

if ( $max_retries == 1 ) {
    if ($act_finally) {
        exit run_command($action_command);
    }
    exit;
}

if ( !start_atd() ) {
    print "Unable to start 'atd', which is required to run this utility.\n";
    exit 1;
}

do_later();

sub check {
    if ( run_command($check_command) ) {
        return;
    }
    exit run_command($action_command);
}

sub do_later {
    my %arg_for_name = (
        '--act-finally' => $act_finally,
        '--action'      => $action_command,
        '--at'          => $at_args,
        '--check'       => $check_command,
    );
    my $me = '/usr/local/cpanel/scripts/try-later';

    # during a fast upgrade / downgrade we could disappear
    # we should empty the at queue before upgrading or downgrading
    exit unless -x $me;
    my @self_command = ($me);

    if ($max_retries) {
        --$max_retries;
        push @self_command, '--max-retries', $max_retries;
    }

    while ( my ( $name, $arg ) = each %arg_for_name ) {
        next if !length $arg;
        push @self_command, $name, "'$arg'";
    }

    # _job_tag() is used to identify jobs in queue
    # could be used to clean the at queue when launching an upgrade
    my $stdin = _job_tag() . "\nif [ -x $me ]; then \n" . join( ' ', @self_command ) . "\nfi\n";

    my $result = Cpanel::SafeRun::Object->new(
        'program' => $at_cmd,
        'args'    => [$at_args],
        'stdin'   => $stdin,
    );

    exit( $result->error_code() // 0 );
}

sub start_atd {

    # Before we start atd, we need to check for stale jobs so that if atd has
    # been disabled, we don't unleash an angry horde of ancient jobs on the
    # system when we re-enable it.

    m