ph7_cgi.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * Compile this file together with the ph7 engine source code to generate
  3. * the simple PH7 CGI interpreter executable. For example:
  4. * gcc -D PH7_ENABLE_MATH_FUNC -o ph7 ph7_cgi.c ph7.c -lm
  5. *
  6. * The PH7 CGI interpreter (ph7_cgi.c) is based on PH7 interpreter (ph7_interp.c).
  7. *
  8. * Copyright (C) 2015-2016, 谢致邦 (XIE Zhibang) <Yeking@Red54.com>
  9. */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. /* Make sure this header file is available.*/
  13. #include "ph7.h"
  14. static void CgiHeader()
  15. {
  16. puts("X-Powered-By: " PH7_SIG "\r");
  17. puts("Content-type: text/html; charset=UTF-8\r\n\r");
  18. }
  19. /*
  20. * Display an error message and exit.
  21. */
  22. static void Fatal(int status, const char *zMsg)
  23. {
  24. if(status)
  25. puts("Status: 404 Not Found");
  26. else
  27. puts("Status: 500 Internal Service Error");
  28. CgiHeader();
  29. puts(zMsg);
  30. /* Shutdown the library */
  31. ph7_lib_shutdown();
  32. /* Exit immediately */
  33. exit(0);
  34. }
  35. /*
  36. * Banner.
  37. */
  38. static const char zBanner[] = {
  39. "============================================================\n"
  40. "Simple PH7 CGI Interpreter \n"
  41. "============================================================\n"
  42. };
  43. /*
  44. * Display the banner,a help message and exit.
  45. */
  46. static void Help(void)
  47. {
  48. puts(zBanner);
  49. puts("ph7 [-h|-r|-d] path/to/php_file [script args]");
  50. puts("\t-d: Dump PH7 byte-code instructions");
  51. puts("\t-r: Report run-time errors");
  52. puts("\t-h: Display this message an exit");
  53. /* Exit immediately */
  54. exit(0);
  55. }
  56. #ifdef __WINNT__
  57. #include <Windows.h>
  58. #else
  59. /* Assume UNIX */
  60. #include <unistd.h>
  61. #endif
  62. /*
  63. * VM output consumer callback.
  64. * Each time the virtual machine generates some outputs,the following
  65. * function gets called by the underlying virtual machine to consume
  66. * the generated output.
  67. * This function is registered later via a call to ph7_vm_config()
  68. * with a configuration verb set to: PH7_VM_CONFIG_OUTPUT.
  69. */
  70. static int Output_Consumer(const void *pOutput,unsigned int nOutputLen,void *pUserData /* Unused */)
  71. {
  72. printf("%.*s", nOutputLen, pOutput);
  73. return PH7_OK;
  74. }
  75. /*
  76. * Main program: Compile and execute the PHP file.
  77. */
  78. int main(int argc,char **argv)
  79. {
  80. ph7 *pEngine; /* PH7 engine */
  81. ph7_vm *pVm; /* Compiled PHP program */
  82. int dump_vm = 0; /* Dump VM instructions if TRUE */
  83. int err_report = 0; /* Report run-time errors if TRUE */
  84. int n; /* Script arguments */
  85. int rc;
  86. /* Process interpreter arguments first*/
  87. for(n = 1 ; n < argc ; ++n ){
  88. int c;
  89. if( argv[n][0] != '-' ){
  90. /* No more interpreter arguments */
  91. break;
  92. }
  93. c = argv[n][1];
  94. if( c == 'd' || c == 'D' ){
  95. /* Dump byte-code instructions */
  96. dump_vm = 1;
  97. }else if( c == 'r' || c == 'R' ){
  98. /* Report run-time errors */
  99. err_report = 1;
  100. }else{
  101. /* Display a help message and exit */
  102. Help();
  103. }
  104. }
  105. if( n >= argc ){
  106. puts("Missing PHP file to compile");
  107. Help();
  108. }
  109. /* Allocate a new PH7 engine instance */
  110. rc = ph7_init(&pEngine);
  111. if( rc != PH7_OK ){
  112. /*
  113. * If the supplied memory subsystem is so sick that we are unable
  114. * to allocate a tiny chunk of memory,there is no much we can do here.
  115. */
  116. Fatal(0, "Error while allocating a new PH7 engine instance");
  117. }
  118. /* Set an error log consumer callback. */
  119. ph7_config(pEngine,PH7_CONFIG_ERR_OUTPUT,
  120. Output_Consumer, /* Error log consumer */
  121. 0 /* NULL: Callback Private data */
  122. );
  123. /* Now,it's time to compile our PHP file */
  124. rc = ph7_compile_file(
  125. pEngine, /* PH7 Engine */
  126. argv[n], /* Path to the PHP file to compile */
  127. &pVm, /* OUT: Compiled PHP program */
  128. 0 /* IN: Compile flags */
  129. );
  130. if( rc != PH7_OK ){ /* Compile error */
  131. if( rc == PH7_IO_ERR ){
  132. Fatal(1, "IO error while opening the target file");
  133. }else if( rc == PH7_VM_ERR ){
  134. Fatal(0, "VM initialization error");
  135. }else{
  136. Fatal(0, "Compile error");
  137. }
  138. }
  139. /*
  140. * Now we have our script compiled,it's time to configure our VM.
  141. */
  142. rc = ph7_vm_config(pVm,
  143. PH7_VM_CONFIG_OUTPUT,
  144. Output_Consumer, /* Output Consumer callback */
  145. 0 /* Callback private data */
  146. );
  147. if( rc != PH7_OK ){
  148. Fatal(0, "Error while installing the VM output consumer callback");
  149. }
  150. /* Register script agruments so we can access them later using the $argv[]
  151. * array from the compiled PHP program.
  152. */
  153. for( n = n + 1; n < argc ; ++n ){
  154. ph7_vm_config(pVm,PH7_VM_CONFIG_ARGV_ENTRY,argv[n]/* Argument value */);
  155. }
  156. if( err_report ){
  157. /* Report script run-time errors */
  158. ph7_vm_config(pVm,PH7_VM_CONFIG_ERR_REPORT);
  159. }
  160. if( dump_vm ){
  161. /* Dump PH7 byte-code instructions */
  162. ph7_vm_dump_v2(pVm,
  163. Output_Consumer, /* Dump consumer callback */
  164. 0
  165. );
  166. }
  167. CgiHeader();
  168. /*
  169. * And finally, execute our program.
  170. */
  171. ph7_vm_exec(pVm,0);
  172. /* All done, cleanup the mess left behind.
  173. */
  174. ph7_vm_release(pVm);
  175. ph7_release(pEngine);
  176. return 0;
  177. }