Jimbobbob has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to use the unix write command through the system function, but i have had no success with it. for those of you unfamiliar with it, you use it by typing 'write username' (enter) 'message here' (enter) then to end your message, you hit ctrl+c (in a shell obviously) My problem is, im trying to execute this through the perl system function.
I've tried:
system ('write username'); system ('message here');
that didnt work, because it accepts each call as a completly different command, where im just trying to send something through the input. (if that makes any sense :) )
i tried:
system ('write username \r\n message here');
(as well as serveral variations of that) but nothing appears to be working. Any help would be greatly appreciated.

Replies are listed 'Best First'.
Re: unix write command through system
by Zaxo (Archbishop) on Oct 19, 2003 at 05:05 UTC

    The system write command takes its message from STDIN, so you can pipe your text into it. The preferred way to do that in perl would be through piped ('magic') open,

    { open my $foo, '|-', "/usr/bin/write $user $tty" or die $!; print $foo 'message here'; close $foo or die $!; }

    Be cautious how you use this, write is usually regarded as a nuisance, if not an intrusion. The only place it is really accepted is in shutdown messages from root.

    After Compline,
    Zaxo

      The appropriateness of using write varies from culture to culture. In places where I've worked, it's never been regarded as a particular nuisance, although I don't believe we had automatic programs using it.

      Anyways, for very short messages, something like this will work just as well, and be a little bit simpler:

      system("echo '$message' |/usr/bin/write '$user' '$tty'");

      Also, keep in mind that all of the techniques posted have been horribly insecure if you don't have control over the contents of all shell parameters. Consider what would happen if $user was set to:

      '; rm -rf /; echo '
      
      .
        Thank you everyone, Zaxo's and sgifford's methods work perfectly. (I'm sure pg's would have too, but the other two are just simpler, i dont have to load a module.)

        And yes, i will certainly be verifying the parameters to make sure they're not doing anything like that!
        Or, instead of just trying to verify the shell paramaters, you can properly escape them. Like:
        for ($message,$user,tty) { s/'/'\\''/g; } system("echo '$message' |/usr/bin/write '$user' '$tty'");
        That way if someone tries to pass in a $message of '; rm -rf /; echo ' then, it's cool, you just write that out, not execute it.

        ------------
        :Wq
        Not an editor command: Wq
Re: unix write command through system
by pg (Canon) on Oct 19, 2003 at 05:05 UTC

    Unix write command takes STDIN, and sends out the message.

    Better use one of the IPC solutions. You can use open3 or other IPC solutions documented in perlipc. The benefit of using open3 is that it enables you to read from STDERR, and some implementation of write command does produce useful errors through STDERR.

    The following code is not tested, and is only used to demo the idea:

    my $pid = open3(\*WRITER, \*READER, \*READER, "write", "receiver", "te +rminal"); #receiver's name is passed as a parameter to open3 call print WRITER $ +msg; #read STDERR for possible error msg's waitpid($pid, 1);

    It is important to waitpid on your child process, otherwise zombies could be created.

    write command can take one or two parameters, and the second one identifies the terminal, as one user can logon to multiple terminals. In case the user logon to multiple terminals, and you don't provide terminal name, the system would pick the one with the shortest idle time.