#include <lsapilib.h>
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
typedef struct
{
    char * pBuf;
    char * pBufEnd;
    char * pCur;
}Buff;
int PrintEnv( const char * pKey, int keyLen, const char * pValue, int valLen,
                void * arg )
{
    int len;
    Buff * buf = (Buff *)arg;
    buf->pCur += snprintf( buf->pCur,
                buf->pBufEnd - buf->pCur, "%s=%s\n", pKey, pValue );
    len = buf->pCur - buf->pBuf;
    if ( len > 4096 )
    {
        if ( LSAPI_Write( buf->pBuf, len ) < len )
            return -1;
        buf->pCur = buf->pBuf;
    }
    return 1;             
}
int processReq( int *count )
{
    int i = 0, l;
    int len;
    int n;
    char achBuf[8192];
    char * p = achBuf;
    char * pEnd = &achBuf[8192];
    Buff buf;
    char achHeader[] = "Content-type: text/html";
    char achHeader2[] = "X-Powered-by: LSAPI";
    len = LSAPI_GetReqBodyLen();
    /* response header should be added one by one */
    LSAPI_AppendRespHeader( achHeader, sizeof( achHeader ) - 1 );
    LSAPI_AppendRespHeader( achHeader2, sizeof( achHeader2 ) - 1 );
    p += snprintf( p, pEnd - p, 
            "<title>LSAPI echo</title>"
            "<h1>LSAPI echo</h1>\n"
            "Request number %d,  Process ID: %d<p>\n"
            "Request environment:<br>\n<pre>", ++(*count), getpid());
            
    buf.pBuf = achBuf;
    buf.pBufEnd = pEnd;
    buf.pCur = p;
    /*Write a error message to STDERR stream */
    char *pErr = "this is a error message send to STDERR.";
    LSAPI_Write_Stderr( pErr, strlen( pErr ) );
        
    if ( LSAPI_ForeachHeader( PrintEnv, &buf ) == -1 )
    {
        return -1;
    }
    if ( LSAPI_ForeachEnv( PrintEnv, &buf ) == -1 )
    {
        return -1;
    }
            
    p = buf.pCur;
    if (len <= 0)
    {
        p += snprintf( p, pEnd - p, "No data from standard input.<p>\n" );
    }
    else
    {
        p += snprintf(p, pEnd - p, "Standard input:<br>\n<pre>\n");
        if ( LSAPI_Write( achBuf, p - achBuf ) < p - achBuf )
            return -1;
            
        p = achBuf;
        while( i < len )
        {
            n = len - i;
            if ( n > sizeof( achBuf ) )
                n = sizeof( achBuf );
            l = LSAPI_ReadReqBody( achBuf, n );
            if ( l == 0 )
            {
                p += snprintf(p, pEnd-p,
                    "\nERROR: Error occured before enough bytes received on standard input<p>\n");
                break;
            }
            if ( l < 0 )
            {
                p += snprintf(p, pEnd-p,
                        "\nERROR: Read failed before enough bytes of request body received<p>\n");
                break;
            }
            i += l;
            if ( LSAPI_Write( achBuf, l ) < l )
                return -1;
        }
        p += snprintf(p, pEnd - p, "\n</pre><p>\n");
    }
    
    if ( p > achBuf )
    {
        if ( LSAPI_Write( achBuf, p - achBuf ) < p - achBuf )
            return -1;
    }
    
    LSAPI_Finish();
    return 0;
}
int processHello( )
{
    int len;
    char achHeader[] = "Content-type: text/html";
    len = LSAPI_GetReqBodyLen();
    /* response header should be added one by one */
    LSAPI_AppendRespHeader( achHeader, sizeof( achHeader ) - 1 );
    char achMessage[] = "Hello, World";
    if ( LSAPI_Write( achMessage, sizeof( achMessage ) - 1 )
                < sizeof( achMessage ) - 1 )
        return -1;
    LSAPI_Finish();
    return 0;
}
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(int argc, char *argv[])
{
    LSAPI_Request req;
    int count = 0;
    int fd;
    if ( argc > 1 )
    {
        fd = LSAPI_CreateListenSock( argv[1], 10 );
    }
    
    LSAPI_Init();
    LSAPI_InitRequest( &req, fd );
    LSAPI_Init_Prefork_Server( 10, select, 0 );
    
    while( LSAPI_Prefork_Accept_r( &req ) >= 0 )
    {
        if ( processReq( &count ) == -1 )
            return 1;
        if ( count >= 10000 )
            break;
    }
/* Hello world example */
/* 
    LSAPI_Init();
    while( LSAPI_Accept() >= 0 )
    {
        if ( processHello() == -1 )
            return 1;
    }
*/    
    return EXIT_SUCCESS;
}