ban
ban

Reputation: 685

Read from the keyboard file descriptor

I was trying to read from the STDIN file descriptor in /dev/fd/0

This is what I wrote, I just want to print every command I ever type on the command shell. I wrote this in Perl but its not good enough:

#!/usr/bin/perl

use strict;
use warnings;

open my $fh, "<", "/dev/fd/0" or die "bububububu";
while (<$fh>) {
print $_."\n";
}
close $fh;

So it doesn't print anything although it gets stuck. Does anyone know how to do it??? If this is not possible can I put all the commands in a file and then read them from the '0' file handle somehow. I just want to capture every command which goes through to the system.

Example file:

#!/usr/bin/perl

use strict;
use warnings;

system("./.file2");

and then file2 is:

echo this is hard!!!

So I want my program to run the first file. When I read the '0' filehandle, I wish to store all the lines run in an array somehow.

MAJOR EDIT: I THINK YOU MISUNDERSTOOD ME. I KNOW ABOUT STDIN AND HOW IT WORKS. THE THING IS I DON'T WANT THE SCRIPT TO READ FOR INPUTS FROM THE STDIN. I WANT THE SCRIPT TO READ FROM WHAT I TYPE IN THE SHELL PROMPT. SO LETS SAY I RUN THE FILE AND THEN I OPEN ANOTHER TEMINAL AND THEN I TYPE THE COMMANDS IN THE TERMINAL. I WANT THE SCRIPT TO RECOGNIZE THOSE LINES AND SAVE THEM IN AN ARRAY.

Upvotes: 0

Views: 2440

Answers (2)

Christian
Christian

Reputation: 73

ban, I don't think what you are trying to do will work. The /dev/fd/0 handle is different for each process (when you open it you basically make a copy/dup of the fh inherited by the parent process), so the file handle you open in perl will NOT be the same as for your bash.

I believe you have (at least) two options here, though:

  1. Read your commands with the while( <STDIN> ) approach, then store them to your file AND pass them to system()or $qx() to be executed by a shell, however, since this starts a shell for every command this only works for simple applications. You could work around this by opening a shell in a sub-child and connecting its STDIN/STDOUT filehandles with perl file handles you pipe new commands on and read out their input, though. See perldoc perlopentut (section Pipe Opens) and/or IPC::Open2 (http://search.cpan.org/~rjbs/perl-5.18.0/ext/IPC-Open3/lib/IPC/Open2.pm) for details. Combined with Term::ReadLine you can emulate the full input method of a shell and won't notice much of a difference, while logging all commands.
  2. Is there any reason why you don't just use bash's history feature (see for instance here: http://www.talug.org/events/20030709/cmdline_history.html). By default every command you execute in an interactive session should be recorded in ~/.bash_history, and you can access it with `history.

If your application is security related, and you are trying to log everything that for instance root does on a system, then you might want to look into sudo, also.

Hope this helps you, Christian

Upvotes: 2

Miguel Prz
Miguel Prz

Reputation: 13792

There is a special Perl file descriptor associated to standar input. You can rewrite your code as:

use strict;
use warnings;

while( <STDIN> ) {
   print;
   last if /^QUIT/;  #Exit loop if QUIT was typed
}

#<-- Note: no open neither close

Upvotes: 0

Related Questions