X-Git-Url: https://git.draconx.ca/gitweb/mpdhacks.git/blobdiff_plain/efd378c6eac050f999cad78ade5b4a3946164105..6d6c4cbf5e70092b30c3496e9003d454ef80f857:/mpdexec.pl?ds=sidebyside diff --git a/mpdexec.pl b/mpdexec.pl index 9c6e069..02c2950 100755 --- a/mpdexec.pl +++ b/mpdexec.pl @@ -1,18 +1,24 @@ #!/usr/bin/env perl # -# Copyright © 2012 Nick Bowler +# Copyright © 2012,2019 Nick Bowler # -# Simple program to send a command to MPD. The result is printed to standard -# output. +# Simple program to send a command to MPD. Each command-line argument is +# quoted as necessary so it appears as a single argument at the protocol +# level. The result is printed to standard output. # -# License WTFPL2: Do What The Fuck You Want To Public License, version 2. -# This is free software: you are free to do what the fuck you want to. +# License GPLv3+: GNU General Public License version 3 or any later version. +# This is free software: you are free to change and redistribute it. # There is NO WARRANTY, to the extent permitted by law. use strict; use utf8; -use encoding 'utf8'; + +use Encode::Locale qw(decode_argv); +decode_argv(Encode::FB_CROAK); + +binmode(STDOUT, ":utf8"); +binmode(STDIN, ":utf8"); use IO::Socket::INET6; my $host = $ENV{MPD_HOST} // "localhost"; @@ -29,11 +35,37 @@ if (!(<$sock> =~ /^OK MPD ([0-9]+)\.([0-9]+)\.([0-9]+)$/)) { die "MPD failed to announce version: $!"; } -print $sock join(' ', @ARGV), "\n"; -while (<$sock>) { - last if (/^OK/); - print; - exit 1 if (/^ACK/); +sub mpd_escape { + ($_) = @_; + + # No way to encode literal newlines in the protocol, so we convert + # any newlines in the arguments into a space, which can help with + # shell quoting. + s/\n/ /g; + + if (/[ \t\\"]/) { + s/[\\"]/\\$&/g; + return "\"$_\""; + } + return $_; +} + +sub mpd_exec { + print $sock join(' ', @_), "\n"; + while (<$sock>) { + last if (/^OK/); + print; + exit 1 if (/^ACK/); + } +} + +if (@ARGV) { + mpd_exec(map { mpd_escape($_) } @ARGV) +} else { + while (<>) { + chomp; + mpd_exec($_); + } } print $sock "close\n";