2021-07-26 03:43:35 +02:00
|
|
|
# File: RunCommand.pm
|
|
|
|
#
|
2021-07-26 03:55:34 +02:00
|
|
|
# Purpose: Runs a system command, streaming each line of output in real-time.
|
2021-07-26 03:54:07 +02:00
|
|
|
#
|
2021-07-26 03:55:34 +02:00
|
|
|
# WARNING: The `runcmd` command will allow a user to run any command on your
|
|
|
|
# system. Do not give out the `can-runcmd` capability to anyone you do not
|
2021-07-26 06:30:55 +02:00
|
|
|
# absolutely trust 100%. Instead, make a locked-down factoid; i.e.:
|
2021-07-26 03:54:07 +02:00
|
|
|
#
|
|
|
|
# factalias ls runcmd ls $args
|
|
|
|
# factset ls cap-override can-runcmd
|
|
|
|
# factset ls locked 1
|
|
|
|
#
|
|
|
|
# The above will create an `ls` alias that can only run `runcmd ls $args` and
|
2021-07-26 06:30:55 +02:00
|
|
|
# cannot be modified by anybody. The cap-override is necessary so the factoid
|
2021-07-26 03:54:07 +02:00
|
|
|
# itself has permission to use `runcmd` regardless of whether the user has the
|
|
|
|
# `can-runcmd` capability.
|
2021-07-26 06:30:55 +02:00
|
|
|
#
|
|
|
|
# This plugin is not in data/plugin_autoload. Load at your own risk.
|
2021-07-26 03:54:07 +02:00
|
|
|
|
2021-07-26 03:43:35 +02:00
|
|
|
# SPDX-FileCopyrightText: 2021 Pragmatic Software <pragma78@gmail.com>
|
|
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
|
|
|
|
package PBot::Plugin::RunCommand;
|
|
|
|
use parent 'PBot::Plugin::Base';
|
|
|
|
|
|
|
|
use PBot::Imports;
|
|
|
|
|
2021-07-26 04:14:07 +02:00
|
|
|
use IPC::Run qw/start pump finish/;
|
2021-07-26 03:43:35 +02:00
|
|
|
|
|
|
|
sub initialize {
|
|
|
|
my ($self, %conf) = @_;
|
|
|
|
|
2021-07-31 04:01:24 +02:00
|
|
|
$self->{pbot}->{commands}->add(
|
|
|
|
name => 'runcmd',
|
|
|
|
help => 'Executes a system command and outputs each line in real-time',
|
|
|
|
requires_cap => 1,
|
|
|
|
subref => sub { $self->cmd_runcmd(@_) },
|
|
|
|
);
|
2021-07-26 03:43:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
sub unload {
|
|
|
|
my $self = shift;
|
2021-07-31 04:01:24 +02:00
|
|
|
$self->{pbot}->{commands}->remove('runcmd');
|
2021-07-26 03:43:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
sub cmd_runcmd {
|
|
|
|
my ($self, $context) = @_;
|
|
|
|
|
|
|
|
my @args = $self->{pbot}->{interpreter}->split_line($context->{arguments}, strip_quotes => 1);
|
|
|
|
|
|
|
|
my ($in, $out, $err);
|
|
|
|
|
|
|
|
my $h = start \@args, \$in, \$out, \$err;
|
|
|
|
|
|
|
|
my $lines = 0;
|
|
|
|
|
|
|
|
while (pump $h) {
|
2021-08-05 03:50:07 +02:00
|
|
|
$lines += $self->send_lines($context, \$out);
|
2021-07-26 03:43:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
finish $h;
|
|
|
|
|
2021-08-05 03:50:07 +02:00
|
|
|
$lines += $self->send_lines($context, \$out);
|
|
|
|
|
|
|
|
return "No output." if not $lines;
|
|
|
|
}
|
2021-07-26 03:43:35 +02:00
|
|
|
|
2021-08-05 03:50:07 +02:00
|
|
|
sub send_lines {
|
|
|
|
my ($self, $context, $buffer) = @_;
|
|
|
|
|
2021-08-05 04:01:57 +02:00
|
|
|
my $lines = 0;
|
2021-08-05 03:50:07 +02:00
|
|
|
|
|
|
|
while ($$buffer =~ s/(.{1,370})//) {
|
2021-08-05 04:01:57 +02:00
|
|
|
my $line = $1;
|
2021-08-05 03:50:07 +02:00
|
|
|
$line =~ s/^\s+|\s+$//g;
|
|
|
|
|
|
|
|
if (length $line) {
|
2021-07-26 03:43:35 +02:00
|
|
|
$self->{pbot}->{conn}->privmsg($context->{from}, $line);
|
|
|
|
$lines++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-05 03:50:07 +02:00
|
|
|
return $lines;
|
2021-07-26 03:43:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
1;
|