views:

53

answers:

2

I'm trying to write a Perl script that will work better with KDE's kwrited, which, as far as I can tell, is connected to a pts and puts every line it receives through the KDE system tray notifications with the title "KDE write daemon".

Unfortunately, it makes a separate notification for each and every line, so it spams up the system tray with multiline messages on regular old write, and for some reason it cuts off the entire last line of the message when using wall. One-line messages are also goners.

I was also hoping to make it so that it could broadcast across a LAN with thick clients. Before starting on that (which would require SSH, of course), I tried to make an SSH-less version to make sure it works. Unfortunately, it doesn't:

perl ./write.pl "Testing 1 2 3"

where the following is the contents of ./write.pl:

#!/usr/bin/perl

use strict;
use warnings;

my $message = "";
my $device = "";
my $possibledevice = '`w -hs | grep "/usr/bin/kwrited"`'; #Where is kwrited?
$possibledevice =~ s/^[^\t][\t]//;
$possibledevice =~ s/[\t][^\t][\t ]\/usr\/bin\/kwrited$//;
$possibledevice = '/dev/'.$possibledevice;
unless ($possibledevice eq "") {
    $device = $possibledevice;
}

if ($ARGV[0] ne "") {
    $message = $ARGV[0];
    $device = $ARGV[1];
}
else {
    $device = $ARGV[0] unless $ARGV[0] eq "";
    while (<STDIN>) {
        chomp;
        $message .= <STDIN>;
    }
}

if ($message ne "") {
    system "echo \'$message\' > $device";
}
else {
    print "Error: empty message"
}

produces the following error:

$ perl write.pl "Testing 1 2 3"
Use of uninitialized value $device in concatenation (.) or string at write.pl line 29.
sh: -c: line 0: syntax error near unexpected token `newline'
sh: -c: line 0: `echo 'foo' > '

Somehow, the regular expressions and/or the backtick escape in processing $possibledevice are not working properly, because where kwrited is connected to /dev/pts/0, the following works perfectly:

$ perl write.pl "Testing 1 2 3" /dev/pts/0
A: 

One problem is your ' around the attempted system call. No interpolation takes place inside single quotes in Perl.

If you look at a simple case:

#!/usr/bin/perl

use strict;
use warnings;


my $possibledevice = '`w -hs | grep "/usr/bin/kwrited"`'; #Where is kwrited?
print $possibledevice;

The output is:

`w -hs | grep "/usr/bin/kwrited"`

So your shell call never takes place. The fix is to change the shell call to something more like this:

my $possibledevice = `w -hs | grep \"/usr/bin/kwrited\"`; #shud b there...
#or
my $possibledevice = qx$w -hs | grep \"/usr/bin/kwrited\"$; #alternate form

You can read about the different quote like operators in perlop or at perldoc HERE

There is a backtick, system and shell tutorial HERE

drewk
I tried that just now, no effect: I get the exact same error.Something is still wrong with the regexes.
Bushman
DVK has the other part of the solution below... You still need to change your shell quotes or nothing will happen.
drewk
+4  A: 

You supply only ONE command line argument (string "Testing 1 2 3").

So $ARGV[1] is undef.

So $device is undef because of the logic inside if ($ARGV[0] ne "") .

So your shell's echo command redirects to nothing ("echo something >") and thus shell complains (and that's where "undefined $device" Perl warning is from as well).

If you meant the device to be "1", then un-quote your argument string (perl write.pl Testing 1 2 3) on command line.

Also, please consider opening $device as a file for writing and printing "$message" to the file handle. It's a bit more idiomatic Perl and less prone to problems stemming from perl-to-shell transitions/quoting/etc...

DVK
Adding more stuff in the argument-processing conditionals fixed it. The regexes did need some modification, but it works now. Thank you very much!
Bushman