|
|
 |
popen (PHP 3, PHP 4, PHP 5) popen -- Opens process file pointer Descriptionresource popen ( string command, string mode )
Opens a pipe to a process executed by forking the command given
by command.
Returns a file pointer identical to that returned by
fopen(), except that it is unidirectional (may
only be used for reading or writing) and must be closed with
pclose(). This pointer may be used with
fgets(), fgetss(), and
fwrite().
If an error occurs, returns FALSE.
Note:
If you're looking for bi-directional support (two-way), use
proc_open().
Example 1. popen() example |
<?php
$handle = popen("/bin/ls", "r");
?>
|
|
If the command to be executed could not be found, a valid
resource is returned. This may seem odd, but makes sense; it
allows you to access any error message returned by the shell:
Note: When
safe mode is enabled, you can only
execute executables within the safe_mode_exec_dir.
For practical reasons it is currently not allowed to have ..
components in the path to the executable.
| Warning | With safe mode enabled,
all words following the initial command string are treated as a single argument. Thus,
echo y | echo x becomes echo "y | echo x". |
See also pclose(), fopen(),
and proc_open().
User Contributed Notes
popen
PGP Dude
07-May-2005 12:52
I should say, my host uses a modified form of safe mode, so I don't know if that might have caused a problem with "popen" as opposed to "proc_open". The warning below does NOT appear on the proc_open page:
quote:
With safe mode enabled, all words following the initial command string are treated as a single argument. Thus, echo y | echo x becomes echo "y | echo x".
PGP Dude
06-May-2005 02:30
LinixDude010's srcipt did not work for me. Seems wrong to read and write with popen, according to the manual.
The script produced pgp text, but there was something wrong with the text and I could not decode it.
This replacement script, using proc_open, which can read and write, DOES work:
<?php
function pgp_encrypt($keyring_location, $public_key_id, $plain_text) {
$encrypted_text='';
$key_id = EscapeShellArg($public_key_id);
putenv("PGPPATH=$keyring_location");
$descriptorspec = array(
0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w") );
$process = proc_open("pgpe -r $key_id -af", $descriptorspec, $pipes);
if (is_resource($process)) {
fwrite($pipes[0], $plain_text);
fclose($pipes[0]);
while($s= fgets($pipes[1], 1024)) {
$encrypted_text .= $s;
}
fclose($pipes[1]);
while($s= fgets($pipes[2], 1024)) {
$encrypted_text.= "\n<p>Error: $s</p>\n";
}
fclose($pipes[2]);
}
return $encrypted_text;
}
$message = pgp_encrypt("/home/username/.pgp", "to@domain.com", "dummy text to be encrypted");
print nl2br($message);
?>
shaun at nospam dot phplabs dot com
27-Feb-2005 07:52
Note that there appears to be a limit to the amount of data that fread() will return from a handle opened with popen(). A call to fread() may not return as much as you ask for.
For example, suppose I have a file "myfile.txt" which is more than 10KB in size. The following code works as expected:
<?php
$fp = fopen('myfile.txt', 'r');
$data = fread($fp, 10240);
echo strlen($data);
?>
The output is '10240.' However, popen() behaves differently:
<?php
$fp = popen('/bin/cat myfile.txt', 'r');
$data = fread($fp, 10240);
echo strlen($data);
?>
On my system, this code prints out '8192' instead of the expected '10240.'
webmaster at elcurriculum dot com
09-Dec-2004 02:05
This function send an email in html format.
function SendEmail($to,$asunto,$html,$from) {
$fd = popen("/usr/sbin/sendmail -t", "w");
fputs($fd, "Content-type: text/html\r\n");
fputs($fd, "To: $to\r\n");
fputs($fd, "From: TRYKE <" . $from . ">\r\n");
fputs($fd, "Subject: $asunto\r\n");
fputs($fd, "X-Mailer: PHP3\r\n\r\n");
fputs($fd, $html);
pclose($fd);
}
Examples:
SendEmail("tryke@hot.com","My Subject","<h1>Hi,<br>How are you?</h1>","miemail@midomain.com");
More:
http://tryke.blogcindario.com
kalvinb602 at hotmail dot com
06-Jul-2004 05:42
If you're having trouble with the server (Apache) hanging when issuing system commands consider the following bug report:
http://bugs.php.net/bug.php?id=22526
basically, if you're using sessions issue a
session_write_close();
command before you execute your system command to keep the server from hanging.
This may also correct the problem when using other system command executing functions like exec.
Ben
Michel Machado
06-Mar-2004 07:53
Yet another workaround for not having bidirectional pipes in php.
$Cmd =
"bc 2>&1 << END\n" .
"100+221\n" .
"1+3*3\n" .
"quit\n" .
"END\n";
$fp = popen($Cmd, 'r');
$read = fread($fp, 1024);
echo $read;
pclose($fp);
http://vmlinuz.nl/about/contact/
11-Nov-2002 10:58
From the popen linux programmers manual:
<quote>The command argument is a pointer to a null-terminated string containing a shell command line. This command is passed to /bin/sh using the -c flag.</quote>
Since php uses this popen function, you need to be sure /bin/sh exists. This file may not exist in chroot()ed environments.
ajv-php at erkle dot org
08-Aug-2002 01:02
I noticed that some of the examples above seem to advocate passing unencrypted data to gpg via the pipe shell escape, in the absence of a bi-directional popen (on some OSes).
The approach I've taken is similar to:
$prefix = 'example';
$command = '/usr/local/bin/gpg --encrypt --armor --no-tty --batch --no-secmem-warning --recipient "joe.soap@example.com"';
$tmpfile = tempnam('/tmp', $prefix);
$pipe = popen("$command 2>&1 >$tmpfile", 'w');
if (!$pipe) {
unlink($tmpfile);
} else {
fwrite($pipe, $plaintxt, strlen($plaintxt));
pclose($pipe);
$fd = fopen($tmpfile, "rb");
$output = fread($fd, filesize($tmpfile));
fclose($fd);
unlink($tmpfile);
}
return $output;
This means that unencrypted information is not passed via a (potentially readable) shell command, and only encrypted information gets stored on disc.
12-Jul-2002 04:33
Here is a workaround for not having bidirectional pipes in php.
If you have bidirectional pipe support, don't bother with this.
The trick here is to send the input on the command line to the target application. In particular I wanted to use openssl without using temp files or named pipes. This solution should also be thread/process safe.
This does work on Linux (RedHat 7).
function filterThroughCmd($input, $commandLine) {
$pipe = popen("echo \"$input\"|$commandLine" , 'r');
if (!$pipe) {
print "pipe failed.";
return "";
}
$output = '';
while(!feof($pipe)) {
$output .= fread($pipe, 1024);
}
pclose($pipe);
return $output;
}
# example:
print filterThroughCmd("hello", "cat");
# Piping to cat has the effect of echoing your input.
cyberlot at cyberlot dot net
30-Jun-2002 03:29
The below code works for both way processing ;) Have fun folks
<?
system("mkfifo pipeout");
$pipe = popen("./nwserver -module Chapter1E > pipeout","w");
$pipeout = fopen("pipeout", "r");
while ($s = fgets($pipeout,1024)) {
echo $s;
}
?>
linuxdude010 at yahoo dot com
24-May-2002 01:49
I had all kinds of trouble encrypting a message with PGP, but I finanlly got it to work. The trick was to 'chmod o+r pubring.pkr' so that the apache server could read the public keys!!! Then, this function worked fine:
<?PHP
function pgp_encrypt($keyring_location, $public_key_id, $plain_text) {
$key_id = EscapeShellArg($public_key_id);
putenv("PGPPATH=$keyring_location");
$pipe = popen("pgpe -r $key_id -af", "r");
fwrite($pipe, $plain_text);
$encrypted_text = '';
while($s = fgets($pipe, 1024)) {
$encrypted_text .= $s;
}
pclose($pipe);
return $encrypted_text;
}
$message = pgp_encrypt("/home/username/.pgp", "to@domain.com", "dummy text to be encrypted");
print nl2br($message);
?>
nricciardi at mindspring dot com
08-Mar-2002 06:38
ive tried using popen using bidirectional pipes without working for obvious reasons, but i managed to create a simple script that managed to take care of the problem. This example is for gpg encryption.
<?
$message = "this is the text to encrypt with gpg";
$sendto = 'Dummy Key <another@fake.email>';
system("mkfifo pipein");
system("mkfifo pipeout");
system("gpg --encrypt -a -r '$sendto' > pipeout < pipein &");
$fo = fopen("pipeout", "r");
$fi = fopen("pipein", "w");
fwrite($fi, $message, strlen($message));
fclose($fi);
while (!feof($fo)) {
$buf .= fread($fo, 1024);
}
echo $buf;
unlink("pipein");
unlink("pipeout");
?>
If anyone has a better way of doing this I would love to see it.
kevin at pricetrak dot com
29-Jun-2001 01:26
Just a quick note about your environment. None of the apache specific environment variables are available to the called program.
trevor at verite dot com
16-Feb-2001 02:42
Just make sure that you check the user information being passed into the command (if any) before it executes.
bevmo at gmx dot de
01-Dec-2000 12:27
Try this if you want to use sendmail...
$mailer = popen ("/usr/sbin/sendmail -t -i","w");
fwrite ($mailer,"Subject:
From:
To:
*insert text*
");
pclose ($mailer);
stevet at linuxfan dot com
13-Nov-2000 09:17
In PHP3, I could do:
$query = "echo hello world | mycmd"
$fp = ($query, "r");
Under PHP4, this just produces "hello world | mycmd" as the output - the pipe is not executed.
Instead, use:
$query = "hello world";
$cmd = "mycmd";
$fp = popen($cmd, "w+");
fwrite($fp, $query);
lexzeus at mifinca dot com
08-Nov-2000 11:53
Try this (if you're familiar with vi editor) :
<?php
$f=popen("vi newfile.txt","w");
sleep(1);
fputs($f,"i"); sleep(1);
fputs($f,"Hello world\r"); sleep(1);
fputs($f,chr(27)); sleep(1);
fputs($f,":wq\r"); pclose($f); exit;
?>
heh heh heh,
LexZEUS
matthew at leftcoast dot com
04-Oct-2000 08:16
Note that your OS must support bi-direction pipes for popen to be bi-directional.
FreeBSD and BSDI are known to support bi-pipes.
Not sure about Linux.
| |