This is because of how xclip works. It keeps running until you kill it,
or until the number of pastes has been reached that you specify with -loops.

You will want to use Proc::Async or run with an :in parameter instead of
shelling into a redirect with echo, here's why:

    timo@schmand ~> cat BadFile.txt
    cat: BadFile.txt: No such file or directory
    timo@schmand ~ [1]> perl6 -e 'my $Str = "hello | touch BadFile.txt";
qqx{ echo $Str | xclip -selection primary }'
    ^C⏎
    timo@schmand ~ [130]> cat BadFile.txt
    timo@schmand ~>

See how just by giving a specially crafted string it created a file on
my filesystem?

Anyway, here's code that will work:

    perl6 -e 'my $Str = "hello | touch BadFile.txt"; my $proc = run
<xclip -selection primary -loops 1>, :in, :out;  $proc.in.say: $Str;
$proc.in.close; $proc.out.slurp-rest(:close);

This variant waits for the text to be pasted once. If you have something
like a clipboard manager (Klipper, for example), it'll probably
immediately grab your text and keep it for other programs to take.
Otherwise you'll have to paste the text once to other programs for it to
exit. When the user selects something else with the primary selection
xclip will exit, too.

The only reason it has :out is because otherwise there's no built-in way
to wait for it to exit. (I'm filing this as a bug, i think.)

If you want to be able to paste the text as often as you want, you'll
have to remove the -loops 1 part of the commandline and manually decide
when to .kill it.

It's also required that you close the $proc.in handle, because otherwise
xclip will keep waiting for more data and not actually offer anything to
the clipboard.

Hope that helps!
  - Timo

Reply via email to