Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1582
  • Last Modified:

PERL: Checking <STDIN> without actually waiting on it.

I want to check if there is something in the <STDIN> buffer, without actually having the system hang waiting for input.

basically:

while(true){
  $cntr=$cntr+1;
  if(<STDIN>){
    do something...
  }
}

i want to be able to run through the loop without it pausing every time to get input, and i want the 'do something' section to run only when there is something in the <STDIN> buffer, i.e. the user has typed something and pressed enter. (basically cntr keeps incrementing while waiting for input)

thanks guys,
Caleb
0
Cajones
Asked:
Cajones
  • 8
  • 5
  • 4
  • +2
3 Solutions
 
FishMongerCommented:
Do I understand you correctly, you want to get user input from STDIN, but you don't want to wait for the user to actually input anything?  What's the purpose for the counter?  Are you wanting to track the time interval inbetween the receiving of the users input or the number of times that you received input?
0
 
CajonesAuthor Commented:
Heh, no i want the user to input something.. but i want the while loop to be unhindered by the <STDIN> because as soon as you use that it holds the system. And im not really using the counter it was just a quick example.. im really working with the Net::AIM protocol and trying to develop an aimbot. and i have this control loop for my shell

while($cmd ne 'exit'){
      print ">> ";
      $aim->do_one_loop;
      $line=<STDIN>;chomp($line);
      @lv=split(/ /,$line);
      $cmd=$lv[0];
      if($cmd eq "im"){&sendIM;}
}

now $aim->do_one_loop; reads from the socket, but i need that to continually read from the socket -- not only read once and wait for user input. Yet i still want to be able to get user input.. i just need a way for the loop to continue and only run the cmd parsing when there is actually something in the <STDIN> buffer... does that make sense?

thanks, Caleb
0
 
FishMongerCommented:
I've never used that module, (in fact I don't even use aim), and it's documentaion is weak, but have you tried using $aim->start() instead of $aim->do_one_loop

This is just a personal preference of mine, but here's a couple of syntax changes that I'd suggest.

chomp($line = <STDIN>);

sendIM() if ($cmd eq'im');
0
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
CajonesAuthor Commented:
well, thats just coding style suggestions, and if you use $aim->start it just starts its own infinite loop. I still want to be able to have some control after that.. like be able to send im's from the cmd line... so i need to create my own loop

do you know of a way to check if the <STDIN> buffer is full without actually trying to get anything from it, so it wont hang?
0
 
rkosaiCommented:
You may want to consider using fork to create two threads in this case.  Consider reading the perlfork documentation at http://www.perldoc.com/perl5.8.0/pod/perlfork.html.

my $pid = fork();
if ($pid) { #parent process
  while(1) {
    $aim->do_one_loop;
    sleep 1;
  }
} elseif (defined($pid)) {
  #child process
  while ($command = <STDIN>) {
    handle_command($command);
  }
} else {
  #fork failed, handle error
}
0
 
CajonesAuthor Commented:
hey, rkosai... fork just might do it.. i didnt know perl could fork... let me try it out!
thanks, Caleb
0
 
TintinCommented:
Can I ask if there is a CGI component to this question?
0
 
CajonesAuthor Commented:
well its PERL, and PERL is a CGI language :-D

and cgi means common gateway interface, and aim is a common gateway... sorta ;)

hey rkosai... forking the process seems to have issues.. will the $aim variable be a pointer to the original $aim object, or just a copy of it? because its yelling at me for having undefined variables in the module (i think one of the shared variables isnt getting transfered)... any ideas?

~caleb
0
 
rkosaiCommented:
If I recall correctly, only the parent will have the variables previously set in the script.  You'll have to use interprocess communication documented in the perlipc man page.  (http://www.perldoc.com/perl5.8.0/pod/perlipc.html)
0
 
FishMongerCommented:
AIM has nothing to do with CGI.
http://www.google.com/search?q=define:CGI
0
 
rkosaiCommented:
You're quite right.  This is not a CGI question.  However, this is true of many of the questions we answer in this forum.  For example, these two questions both are DBI related and don't necessarily have any relevance to CGI.  Does this mean we should question the validity of requests that only ask about Perl, and not the Common Gateway Interface specification?

http://www.experts-exchange.com/Web/Web_Languages/CGI/Q_20917094.html
http://www.experts-exchange.com/Web/Web_Languages/CGI/Q_20923999.html

Just a thought.
0
 
CajonesAuthor Commented:
"Any piece of software can be a CGI program if it handles input and output according to the CGI standard" .. according to your definition, aim may not use the CGI standard exactly buts why i said sorta ;) however it does interact with a web server -- anyway, thats just semantics, and not why we are all here (i honestly didnt know where to place this question, and when i think CGI i think PERL, so i asked it here)
0
 
FishMongerCommented:
If you take that statment out of context, then yes, you're correct.  However 99% of the time, when refering to cgi scripts, were talking about interacting with web pages in some form or another (and have the server do something with our interaction), which is what my prior comment was refering to.  If we stretch the definition of cgi to its limits, then aim might just be in reach.

It's perfectly fine to ask your question here (some of the top Perl experts are also the top cgi experts), but the Perl section might have been better for this question.

As to your question, fork might be what you need, but it doesn't directly answer the question/problem you first stated.  We might need a little more info about what your script is supposed to do, before we can provide the best answer.
0
 
CajonesAuthor Commented:
fair enough, i didnt know there was a PERL section, this is the first one i saw.
Basically i want to run a shell where the user can type commands in -- like "im soandso hello" and such and concurrently wait on incoming instant messages -- both of which need an infinite loop to do. so fork seems like a good choice, although i am having problems with talking to the child, i have the child do the $aim loop, but when i send a command to the aim buffer from the parent and the child tries to send the command to the aol server the value isnt there.. and it bombs. Pipe doesnt work because i have to read from stdin and that would need some kind of loop as well defeating the purpose of splitting the process off in the first place.
i dont know if any of that makes sense.. but thats what im trying to do
0
 
FishMongerCommented:
So, as I understand it, you want to use Perl to recreate what AOL's instantant messanger program is already doing?  Is this an assignment for a programming class?

I've had too many glasses of wine tonight to write code, but you may want to look at some of the other cpan modules.  Start with these ones to see if they will help.

http://search.cpan.org/~matthewg/Net-OSCAR-1.11/OSCAR.pm
http://search.cpan.org/~elizabeth/forks-0.15/lib/forks/shared.pm
0
 
CajonesAuthor Commented:
yeah, basically im trying to write a cmd line aim
0
 
rkosaiCommented:
"i have the child do the $aim loop, but when i send a command to the aim buffer from the parent and the child tries to send the command to the aol server the value isnt there.. and it bombs"

Did you see my comment about Interprocess Communication?  I think you're going to need to use that to have the child tell the parent to send it.

0
 
CajonesAuthor Commented:
hey rkosai, unless im completely nuts.. doesnt the perl IPC write to the standard in of the process you send it to? That's the impression I got and if thats so, you are still going to have to wait on STDIN in the child, does anyone happen to have an example code that sends a string to a child process and how the child process is supposed to receive it?
sorry im being so dense..
~Caleb
0
 
mishagaleCommented:
I think doing multiple threads/processes here is overkill - all Caleb needs it to do non-blocking input on STDIN. According manpages (perlopentut) you can do the following to make a filehandle non-blocking:

    use Fcntl;
    fcntl(STDIN, F_SETFL, O_NONBLOCK)
        or die "can't set non blocking: $!";

After this call (once, at the begining of your script) you will be able to get data one char at a time. If there is no data, read() returns 0 and lets you get on. I think. I may be wrong about that, in which case you must use select() first to check for data. The main snag is that this won't work on windows, and since you are writing an AIM bot, I imagine thats what you are running.
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 8
  • 5
  • 4
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now