Created
January 12, 2015 15:02
-
-
Save Dialga/1e19779ac7d0c77df579 to your computer and use it in GitHub Desktop.
Basic civetweb + PH7 web server
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Extremely minimal civetweb(formerly mongoose) + PH7 scripted web server for embedded use, | |
* or just a lightweight alternative to your usual PHP and Apache, nginx, lighttpd. | |
* Serves up files and PH7 scripts from the directory run. | |
* Compiles on linux with: | |
* cc -Wall -pipe -DPH7_ENABLE_MATH_FUNC -O2 -lm -ldl -lpthread civetweb.c ph7.c ph7_server.c -o server | |
* Windows: untested | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include "civetweb.h" | |
#include "ph7.h" | |
static struct mg_context *ctx; /* Set by start_civetweb() */ | |
static ph7 *pEngine; /* PH7 engine */ | |
static ph7_vm *pVm; /* Compiled PHP program */ | |
int exit_flag = 0; | |
// Display an error message and exit. | |
static void Fatal(const char *zMsg){ | |
puts(zMsg); | |
ph7_lib_shutdown(); | |
mg_stop(ctx); | |
exit(0); | |
} | |
#define STDOUT_FILENO 1 | |
/* | |
* VM output consumer callback. | |
* Each time the virtual machine generates some outputs,the following | |
* function gets called by the underlying virtual machine to consume | |
* the generated output. | |
* All this function does is redirecting the VM output to STDOUT. | |
* This function is registered later via a call to ph7_vm_config() | |
* with a configuration verb set to: PH7_VM_CONFIG_OUTPUT. | |
*/ | |
static int Output_Consumer( | |
const void *pOutput, | |
unsigned int nOutputLen, | |
void *pUserData // Unused | |
){ | |
ssize_t nWr; | |
nWr = printf("%.*s", nOutputLen, pOutput); | |
if( nWr < 0 ){ | |
return PH7_ABORT; | |
} | |
return PH7_OK; | |
} | |
int ph7_script(struct mg_connection *conn, void *cbdata){ | |
int rc; | |
const void *pOut; | |
unsigned int nLen; | |
/* Handler may access the request info using mg_get_request_info */ | |
struct mg_request_info * req_info = mg_get_request_info(conn); | |
/* Now,it's time to compile our PHP file */ | |
rc = ph7_compile_file( | |
pEngine, /* PH7 Engine */ | |
req_info->uri+1, /* Path to the PHP file to compile */ | |
&pVm, /* OUT: Compiled PHP program */ | |
0 /* IN: Compile flags */ | |
); | |
if( rc != PH7_OK ){ /* Compile error */ | |
if( rc == PH7_IO_ERR ){ | |
Fatal("IO error while opening the target file"); | |
}else if( rc == PH7_VM_ERR ){ | |
Fatal("VM initialization error"); | |
}else{ | |
/* Compile-time error, your output (STDOUT) should display the error messages */ | |
Fatal("Compile error"); | |
} | |
} | |
rc = ph7_vm_exec(pVm,0); | |
if( rc != PH7_OK ){ | |
Fatal("VM execution error"); | |
} | |
/* | |
* Now we have our script compiled,it's time to configure our VM. | |
* We will install the VM output consumer callback defined above | |
* so that we can consume the VM output and redirect it to STDOUT. | |
*/ | |
/* Extract the output */ | |
rc = ph7_vm_config(pVm, | |
PH7_VM_CONFIG_EXTRACT_OUTPUT, | |
&pOut, | |
&nLen | |
); | |
if(nLen > 0){ | |
mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); | |
mg_write(conn, pOut, nLen); | |
} | |
#if REPORT_ERRORS+1 | |
/* Report script run-time errors */ | |
ph7_vm_config(pVm,PH7_VM_CONFIG_ERR_REPORT); | |
#endif | |
ph7_vm_reset(pVm); | |
return 1; | |
} | |
int main(int argc, char **argv){ | |
int rc; | |
const char * options[] = { | |
"document_root", ".", | |
"listening_ports", "8080", | |
0 | |
}; | |
/* Allocate a new PH7 engine instance */ | |
rc = ph7_init(&pEngine); | |
if( rc != PH7_OK ){ | |
Fatal("Error while allocating a new PH7 engine instance"); | |
} | |
/* Set an error log consumer callback. This callback [Output_Consumer()] will | |
* redirect all compile-time error messages to STDOUT. | |
*/ | |
ph7_config(pEngine,PH7_CONFIG_ERR_OUTPUT, | |
Output_Consumer, // Error log consumer | |
0 // NULL: Callback Private data | |
); | |
// Start the web server. | |
ctx = mg_start(NULL, NULL, options); | |
mg_set_request_handler(ctx, "**.php$", ph7_script, 0); | |
printf("%s started on port(s) %s with web root [%s]\n", | |
argv[0], mg_get_option(ctx, "listening_ports"), | |
mg_get_option(ctx, "document_root")); | |
while (exit_flag == 0) { | |
#ifdef _WIN32 | |
Sleep(1000); | |
#else | |
sleep(1); | |
#endif | |
} | |
ph7_vm_release(pVm); | |
ph7_release(pEngine); | |
mg_stop(ctx); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment