开发者

C Program to Expand and Run PHP

开发者 https://www.devze.com 2023-03-18 08:45 出处:网络
How wou开发者_StackOverflow中文版ld I make a GCC C program on Linux that: has a PHP program script inside itself, not as a separate file

How wou开发者_StackOverflow中文版ld I make a GCC C program on Linux that:

  • has a PHP program script inside itself, not as a separate file
  • expands itself out to /tmp
  • shells out to php CLI command line to run the PHP script
  • passes command line arguments of the C program as command line arguments of the PHP program
  • errors out nicely with a message if php CLI is not possible on the system


PHP program script could be stored as a global char * use the fopen, fwrite functions to open and write the global variable out. Then use popen to execute the php interpreter (this will pretty much execute whatever command you send to it) and specify a file descriptor that you could read from to get the output. If you don't need the output for your program (or that is not the intention) than you can utilize the exec suite to execute the command and pass the /tmp/filename as an argument.

To get the arguments from the C program, you'll use the *argv[] in int main(int argc, char *argv[]) just remember that argv[0] is YOUR applications name (I always forget that).

The exec functions will return -1 and errno will be set. Man pages should answer the implementation of each of these. but just in case you get lost.

char *script = "here are your script contents";

char *php_application_name = "pear";

int main(int argc, char *argv[]) {
  FILE *fd;
  char *filename = create_random_filename("/tmp/");
  fd = fopen(filename, "rw");

  fwrite(script, sizeof(char), strlen(script), fd);

  fclose(fd);

  /* Assuming application executes like
     pear <script> <arguments>
   */
  char *script_args[argc];
  int i = 1;
  script_args[0] = php_application_name;
  script_args[1] = filename;
  for(i = 1; i < argc; i++) {
    script_args[i+1] = argv[i];
  }

  execvp(php_application_name, script_args);
}


I want to give props to @Suroot and also this great article: http://www.linuxjournal.com/content/embedding-file-executable-aka-hello-world-version-5967

However, the entire process is like so at Linux command line:

...first, you need to be on Linux, PHP for command line (CLI) needs to be enabled, and PHP at command line should not have any errors when you do "php -v" or pass it a test script that you know typically would work at command line.

...second, you need to have GCC installed for compiling C programs.

...create a working directory and 'cd' into it.

...create a file script.php that has this test code inside:

<?php

$s1 = @ $argv[1];
$s2 = @ $argv[2];
$s3 = @ $argv[3];

for($i=0;$i<=10;$i++){
    echo "($s1) ($s2) ($s3)\n";
}

...note, this is only our test. You can put your own PHP code in there later on once you've proven that the test works.

...note that "script.php" is critical to be named that or the main.c won't work when it hits the _binary_script_php_start line. That through me for a loop at first because I didn't make the mental connection that the variable name is glued in by this process.

...create a C code file main.c that has this code inside:

#include <stdio.h>
#include <stdlib.h>

extern char _binary_script_php_start;
extern char _binary_script_php_end;

int main(int argc, char *argv[]) {
    // EXTRACT OUR RESOURCE OBJECT INTO /tmp/test.php
    char *p = &_binary_script_php_start;
    FILE *fp = fopen("/tmp/test.php","wb");
    while ( p != &_binary_script_php_end ) {
        fputc(*p++,fp);
    }
    fclose(fp);
    // NOW READ IN OUR STANDARD ARGUMENTS AND LAUNCH OUR COMMAND
    int i = 1;
    char *cmd = "php /tmp/test.php";
    char *s = NULL;
    asprintf(&s, "%s",cmd);
    for(i = 1; i < argc; i++) {
        asprintf(&s, "%s \"%s\"",s,argv[i]);
    }
    system(s);
    free(s);
    unlink("/tmp/test.php"); // comment me out for debugging if you want
}

...note, I'm sort of rusty with C (haven't used it since the 1980s), and strcpy() is not advised because it's unsafe. So, I read up on StackOverflow that we should use asprintf() on GNU Linux systems. Evidently asprintf() handles buffer overflow and malloc issues? I sure hope so -- I don't want to lead you wrong here. Please research that!

...and now the magic begins!

...we need to embed the script.php into an object file "data.o" with this command-line command (thus starting with the $ prompt):

$ objcopy -I binary -O elf32-i386 -B i386 script.php data.o

...now we build our command "runme" where we link in "data.o" and "main.c" together:

$ gcc main.c data.o -o runme

...this then made a compiled C program for us called "runme". We can then execute it to test it:

$ ./runme "test1" "test2 test3" "test4"

...You should see an output like the following:

(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)

...as you can see, the doublequotes actually are important -- they tell the C, and therefore the PHP, that the parameters should be grouped together. That's why test3 doesn't appear in the last parentheses. Without the doublequotes, you'll see a completely different result.

At this point, you see how we can make a C program that has an embedded PHP script inside and which runs on Linux. (Mac, Windows -- you'll likely need to tweak this code somewhat.) The C program expands our PHP script into /tmp, executes it, and passes it parameters that we can read in and use. From here on out, you can revise the script.php to do as you need, and you can see about using a unique filename so that you don't clobber someone else's /tmp/test.php file, just in case.

0

精彩评论

暂无评论...
验证码 换一张
取 消