6

Under Linux ,if I want to pass pure string from PHP to C, how do i do that? what I've tried do far is:

exec("./myexec.bin -a mystring");

in PHP and

getopt(argc,argv, "a:");

in C

everything works, but when i pass strings longers than MAX_ARG_STRLEN (131072), it will no longer return 0 instead it returns 127 which is command not found....

is there any other ways to pass string data to a linux executable? or is there any way to overcome the MAX_ARG_STRLEN problem?

tom91136
  • 8,662
  • 12
  • 58
  • 74
  • just to add, the string i'm passing might be longer than 393216 characters, because ((256^2)*6)*2; i thought of storing them in a file but then it's almost 1MB in size, @Linus Kleen solution is currently my best solution so far – tom91136 Nov 19 '11 at 09:43
  • is it really only a string or is it a data-structure you want to pass? – aurora Nov 19 '11 at 10:04
  • after some experiments, i conclude that proc_open() is better since it provides both stdin and stdout whereas popen() provides only in or out – tom91136 Nov 21 '11 at 19:37

4 Answers4

6

You could use popen() to open a pipe to the executable:

$fp = popen('./myexec.bin', 'w');
fwrite($fp, $data);
pclose($fp);

Then, as previously suggested, read from stdin in your C program:

fopen(stdin, "r");
// ...

It is "safer" to use popen() rather than exec('/bin/echo') because you can write characters that would otherwise be interpreted by the shell (&, |, ...). Note that the handle returned from PHP's popen() must be closed with pclose().

Linus Kleen
  • 33,871
  • 11
  • 91
  • 99
3

A few options spring immediately to mind:

  • Store the data in a file and pass the filename on the command line. It's easy and simple but does require permissions to create and store files somewhere on the filesystem.

  • Open a pipe between your program and the C program; leave both processes running, at least until the C program has consumed the entire contents of your string. popen() is a convenient wrapper around this approach, but it does assume that standard input is the right destination, and it is unidirectional. Managing the pipes yourself lets you use a different file descriptor -- and you can tell the child which file descriptor to read via a command line argument. (See gpg(1)'s command line option --passphrase-fd to see what I mean.)

  • Use a SysV or POSIX shared memory segment to store you data in PHP, and then attach to the shared memory segment from your C program to read the contents. Note that shared memory segments persist, so you must clean up after them when you are done -- otherwise you will leak memory. This doesn't require permissions to create files in the filesystem and might be a nicer mechanism than dealing with pipes and keeping both processes alive long enough for one to completely write the data and the other to completely read the data.

sarnold
  • 102,305
  • 22
  • 181
  • 238
1

If it is more like a data structure than a string, what about using an embedded webserver? At first sight it may sound like overkill for your purpose, but mongoose for example is a very lightweight embeddable webserver:

http://code.google.com/p/mongoose/

There's also a nice tutorial about the exact same problem you have, transfering data between a PHP application and a C/C++ application. It's in german, though ... but maybe google translator can help:

http://blog.aditu.de/2010/05/15/serverbridge-zwischen-php-und-cc/

aurora
  • 9,607
  • 7
  • 36
  • 54
0

try using echo and pipe the output to your C executable instead of using args:

exec("/bin/echo | ./myexec.bin");

as @sarnold mentioned in comments it's wrong. Look at @Linus Kleen answer.

in your C program:

fopen(stdin, "r");
// ...
Community
  • 1
  • 1
fardjad
  • 20,031
  • 6
  • 53
  • 68