Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

STDIN under Windows?

Posted on 2005-04-13
18
Medium Priority
?
1,068 Views
Last Modified: 2008-03-10
I am trying to write a PHP shell script that works in windows and linux.

I am reading from STDIN but having problems with windows. I am executing the script using a bat file and it seems to ask for input; I can't really work out what it does with the input (I press CTRL C to continue).

Any suggestions?
0
Comment
Question by:thepadders
  • 10
  • 6
  • 2
18 Comments
 
LVL 3

Expert Comment

by:AndyWHV
ID: 13779184
on windows you need to use \con

like this:

if (substr(PHP_OS, 0, 3) == "WIN") {
   $tty = fOpen("\con", "rb");
} else {
   if (!($tty = fOpen("/dev/tty", "r"))) {
      $tty = fOpen("php://stdin", "r");
  }
}
0
 
LVL 3

Expert Comment

by:AndyWHV
ID: 13779196
you can also have a look at the comments on readline in the php manual...

http://www.php.net/manual/en/ref.readline.php
0
 
LVL 6

Expert Comment

by:alextr2003fr
ID: 13780025
pressing CTRL C terminates your shell script, be sure your script have the possibility to do I/O for example to handle your inputs :
<?php
  $stdin = fopen('php://stdin', 'r');
  echo 'Login : ';
  $mystr = fgets($stdin,100);
  echo 'Your login is : '.$mystr;
  fclose($stdin);
?>
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 

Author Comment

by:thepadders
ID: 13786485
Andy, it appears that $fp = fopen("php://stdin","r"); should work on Windows (?)

Alex, what should I use instead of CTRL C ? Ie, when i have finished entering input in the shell window, what should i press?
0
 

Author Comment

by:thepadders
ID: 13786522
Perhaps this is my problem, i am doing:

while ($data_bit = fgets(STDIN, 1024)) {

}

code (STDIN is defined above as php://stdin

Generaly what I use this for is pipeing email like:

|user@domain.com > /path/to/file.php

but I want to be able to just test it on windows entering a source text of unknown length.
0
 
LVL 6

Expert Comment

by:alextr2003fr
ID: 13786538
in windows console mode simply use enter to validate your inputs
to test it 1) start cmd 2) use this syntax : php \path\to\your_script.php
0
 
LVL 6

Expert Comment

by:alextr2003fr
ID: 13786564
shouldn't it be
while ($data_bit = fgets($STDIN, 1024)) {
rather than
while ($data_bit = fgets(STDIN, 1024)) {
since $STDIN is the ressource handle.
0
 
LVL 6

Expert Comment

by:alextr2003fr
ID: 13786571
or more something like :
<?php
  $stdin = fopen('php://stdin', 'r');
  $data_bit = fgets($stdin,1024);
  /* your code */
  fclose($stdin);
?>
0
 
LVL 6

Expert Comment

by:alextr2003fr
ID: 13786591
then you can scan through your $data_bit with while

or

while (!feof($stdin)) {
    $data_bit = fgets($handle, 1024);
    echo $data_bit;
}

perhaps $data_bit = fgets($handle, 1); instead of $data_bit = fgets($handle, 1024);
0
 

Author Comment

by:thepadders
ID: 13786668
As i understand it STDIN in PHP > 4.3 is a constant holding the handle, it is auto created.

I have got a test of what I am doing:

<?php

if (version_compare(phpversion(),'4.3.0','<')) {
                              
      define('STDIN', fopen("php://stdin","rb"));
      define('STDOUT', fopen("php://stdout","rb"));
      define('STDERR', fopen("php://stderr","rb"));
                                
      register_shutdown_function(
            create_function('' , 'fclose(STDIN); fclose(STDOUT); fclose(STDERR); return true;')
      );
}

echo 'Login : ';
$mystr = fgets(STDIN,100);
echo 'Your login is : '.$mystr;
echo 'Password : ';
$mystr = fgets(STDIN,100);
echo 'Your Password is : '.$mystr;

echo 'Address : ';
while (!feof(STDIN)) {
    $mystr .= fgets(STDIN, 1024);
}
echo 'Address is : '.$mystr;


The problem is i can't get multiple line to work, in that I can't end the multiple line input without doing CTRL C

0
 
LVL 6

Expert Comment

by:alextr2003fr
ID: 13786724
if you want to handle the multilines you can try something like :
   while(($mystr = readline("")) != ".") {
       $mystr .= ($PHP_OS == "WIN") ? "\r\n".$mystr :
                                         "\n".$mystr;
  }
and end your lines with a . instead of enter
0
 

Author Comment

by:thepadders
ID: 13786767
Ok, i will try that. I dosen't seem as neat as how it works on linux, when I pipe a file to the php script it knows when its got all the data for some reason. Is there no way to replicate that in windows?
0
 
LVL 6

Accepted Solution

by:
alextr2003fr earned 2000 total points
ID: 13786783
I do not think it will be same as on Linux but see the script that joshua at neocodesoftware.com provided on http://fr3.php.net/readline
section multilines it is what you need.
0
 
LVL 6

Expert Comment

by:alextr2003fr
ID: 13786802
also do not forget that to use readline / read functions you will need to have libreadline installed.
0
 

Author Comment

by:thepadders
ID: 13786827
I see. Thanks very much Alex - much appreciated.
0
 
LVL 6

Expert Comment

by:alextr2003fr
ID: 13786834
you are welcome :) to resume this in combination with above :
<?php
function multilineread () { //function from  http://fr3.php.net/readline
   do {
       $in = read();

       # test exit
       if ($in == ".") return $read;

       # concat input
       (PHP_OS == "WINNT") ? ($read = $read . ($read ? "\r\n" : "") . $in) : ($read = $read . "\n" . $in);

   } while ($inp != ".");

   return $read;
}
if (version_compare(phpversion(),'4.3.0','<')) {

     define('STDIN', fopen("php://stdin","rb"));
     define('STDOUT', fopen("php://stdout","rb"));
     define('STDERR', fopen("php://stderr","rb"));

     register_shutdown_function(
          create_function('' , 'fclose(STDIN); fclose(STDOUT); fclose(STDERR); return true;')
     );
}

echo 'Login : ';
$mystr = fgets(STDIN,100);
echo 'Your login is : '.$mystr;
echo 'Password : ';
$mystr = fgets(STDIN,100);
echo 'Your Password is : '.$mystr;

echo 'Address : ';
$myaddress = multilineread();
echo 'Address is : '.$myaddress;

?>
0
 

Author Comment

by:thepadders
ID: 13786922
It seems that it is based on the idea of closing the stream after reading a line of it, and that is why it seems to work it seems.
What its doing is not really taking a multi line input but appending lots of single line inputs into one string.

This might work for debugging like I want, but is very different to the linux read all date piped in method.
0
 
LVL 6

Expert Comment

by:alextr2003fr
ID: 13786984
yeah I agree with you, it is not very confortable, but under MS-DOS you have to use a escaping caracter of your choice for multilines, welcome to the world of MS-DOS :)
0

Featured Post

Prep for the ITIL® Foundation Certification Exam

December’s Course of the Month is now available! Enroll to learn ITIL® Foundation best practices for delivering IT services effectively and efficiently.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Build an array called $myWeek which will hold the array elements Today, Yesterday and then builds up the rest of the week by the name of the day going back 1 week.   (CODE) (CODE) Then you just need to pass your date to the function. If i…
The title says it all. Writing any type of PHP Application or API code that provides high throughput, while under a heavy load, seems to be an arcane art form (Black Magic). This article aims to provide some general guidelines for producing this typ…
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.
Suggested Courses
Course of the Month20 days, 19 hours left to enroll

810 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question