1/*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2015 The PHP Group                                |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 3.01 of the PHP license,      |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available at through the world-wide-web at the following url:        |
10   | http://www.php.net/license/3_01.txt.                                 |
11   | If you did not receive a copy of the PHP license and are unable to   |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@php.net so we can mail you a copy immediately.               |
14   +----------------------------------------------------------------------+
15   | Author: George Wang <gwang@litespeedtech.com>                        |
16   +----------------------------------------------------------------------+
17*/
18
19/*
20Copyright (c) 2002-2015, Lite Speed Technologies Inc.
21All rights reserved.
22
23Redistribution and use in source and binary forms, with or without
24modification, are permitted provided that the following conditions are
25met:
26
27    * Redistributions of source code must retain the above copyright
28      notice, this list of conditions and the following disclaimer.
29    * Redistributions in binary form must reproduce the above
30      copyright notice, this list of conditions and the following
31      disclaimer in the documentation and/or other materials provided
32      with the distribution.
33    * Neither the name of the Lite Speed Technologies Inc nor the
34      names of its contributors may be used to endorse or promote
35      products derived from this software without specific prior
36      written permission.
37
38THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
39"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
40LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
41A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
42OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
44LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
45DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
46THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
47(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
48OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49*/
50
51
52#include <ctype.h>
53#include <dlfcn.h>
54#include <errno.h>
55#include <fcntl.h>
56
57#include <sys/stat.h>
58#include <signal.h>
59#include <stdlib.h>
60#include <stdio.h>
61#include <string.h>
62#include <sys/mman.h>
63#include <sys/resource.h>
64#include <sys/socket.h>
65#include <sys/time.h>
66#include <sys/uio.h>
67#include <sys/wait.h>
68#include <grp.h>
69#include <pwd.h>
70#include <time.h>
71#include <unistd.h>
72#include <arpa/inet.h>
73#include <netdb.h>
74#include <netinet/in.h>
75#include <netinet/tcp.h>
76#include <sys/un.h>
77
78#include "lsapilib.h"
79
80#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
81#include <sys/prctl.h>
82#endif
83
84#if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
85    || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
86#include <sys/sysctl.h>
87#endif
88
89#include <inttypes.h>
90#ifndef uint32
91#define uint32 uint32_t
92#endif
93
94struct lsapi_MD5Context {
95    uint32 buf[4];
96    uint32 bits[2];
97    unsigned char in[64];
98};
99
100void lsapi_MD5Init(struct lsapi_MD5Context *context);
101void lsapi_MD5Update(struct lsapi_MD5Context *context, unsigned char const *buf,
102           unsigned len);
103void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *context);
104
105/*
106 * This is needed to make RSAREF happy on some MS-DOS compilers.
107 */
108typedef struct lsapi_MD5Context lsapi_MD5_CTX;
109
110
111#define LSAPI_ST_REQ_HEADER     1
112#define LSAPI_ST_REQ_BODY       2
113#define LSAPI_ST_RESP_HEADER    4
114#define LSAPI_ST_RESP_BODY      8
115
116#define LSAPI_RESP_BUF_SIZE     8192
117#define LSAPI_INIT_RESP_HEADER_LEN 4096
118
119
120
121static int g_inited = 0;
122static int g_running = 1;
123static int s_ppid;
124static int s_slow_req_msecs = 0;
125static int s_keepListener = 0;
126static int s_dump_debug_info = 0;
127static int s_pid_dump_debug_info = 0;
128
129LSAPI_Request g_req = { -1, -1 };
130
131static char         s_pSecret[24];
132
133
134void Flush_RespBuf_r( LSAPI_Request * pReq );
135
136static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] =
137{
138    "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET",
139    "HTTP_ACCEPT_ENCODING",
140    "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHORIZATION",
141    "HTTP_CONNECTION", "CONTENT_TYPE",
142    "CONTENT_LENGTH", "HTTP_COOKIE", "HTTP_COOKIE2",
143    "HTTP_HOST", "HTTP_PRAGMA",
144    "HTTP_REFERER", "HTTP_USER_AGENT",
145    "HTTP_CACHE_CONTROL",
146    "HTTP_IF_MODIFIED_SINCE", "HTTP_IF_MATCH",
147    "HTTP_IF_NONE_MATCH",
148    "HTTP_IF_RANGE",
149    "HTTP_IF_UNMODIFIED_SINCE",
150    "HTTP_KEEP_ALIVE",
151    "HTTP_RANGE",
152    "HTTP_X_FORWARDED_FOR",
153    "HTTP_VIA",
154    "HTTP_TRANSFER_ENCODING"
155};
156
157static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] =
158{    11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 18,
159     22, 13, 18, 13, 24, 15, 10, 20, 8, 22 };
160
161
162static const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] =
163{
164    "Accept", "Accept-Charset",
165    "Accept-Encoding",
166    "Accept-Language", "Authorization",
167    "Connection", "Content-Type",
168    "Content-Length", "Cookie", "Cookie2",
169    "Host", "Pragma",
170    "Referer", "User-Agent",
171    "Cache-Control",
172    "If-Modified-Since", "If-Match",
173    "If-None-Match",
174    "If-Range",
175    "If-Unmodified-Since",
176    "Keep-Alive",
177    "Range",
178    "X-Forwarded-For",
179    "Via",
180    "Transfer-Encoding"
181};
182
183static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] =
184{   6, 14, 15, 15, 13, 10, 12, 14, 6, 7, 4, 6, 7, 10, //user-agent
185    13,17, 8, 13, 8, 19, 10, 5, 15, 3, 17
186};
187
188static void lsapi_sigpipe( int sig )
189{
190}
191static void lsapi_siguser1( int sig )
192{
193    g_running = 0;
194}
195
196#ifndef sighandler_t
197typedef void (*sighandler_t)(int);
198#endif
199
200static void lsapi_signal(int signo, sighandler_t handler)
201{
202    struct sigaction sa;
203
204    sigaction(signo, NULL, &sa);
205
206    if (sa.sa_handler == SIG_DFL)
207    {
208        sigemptyset(&sa.sa_mask);
209        sa.sa_flags = 0;
210        sa.sa_handler = handler;
211        sigaction(signo, &sa, NULL);
212    }
213}
214
215
216static int s_enable_core_dump = 0;
217static void lsapi_enable_core_dump()
218{
219#if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
220    || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
221    int  mib[2];
222    size_t len;
223
224    len = 2;
225    if ( sysctlnametomib("kern.sugid_coredump", mib, &len) == 0 )
226    {
227        len = sizeof(s_enable_core_dump);
228        if (sysctl(mib, 2, NULL, 0, &s_enable_core_dump, len) == -1)
229            perror( "sysctl: Failed to set 'kern.sugid_coredump', "
230                    "core dump may not be available!");
231    }
232
233
234#endif
235
236#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
237    if (prctl(PR_SET_DUMPABLE, s_enable_core_dump,0,0,0) == -1)
238        perror( "prctl: Failed to set dumpable, "
239                    "core dump may not be available!");
240#endif
241}
242
243
244static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader,
245                                char type, int len )
246{
247    pHeader->m_versionB0 = LSAPI_VERSION_B0;  /* LSAPI protocol version */
248    pHeader->m_versionB1 = LSAPI_VERSION_B1;
249    pHeader->m_type      = type;
250    pHeader->m_flag      = LSAPI_ENDIAN;
251    pHeader->m_packetLen.m_iLen = len;
252}
253
254static  int lsapi_set_nblock( int fd, int nonblock )
255{
256    int val = fcntl( fd, F_GETFL, 0 );
257    if ( nonblock )
258    {
259        if (!( val & O_NONBLOCK ))
260        {
261            return fcntl( fd, F_SETFL, val | O_NONBLOCK );
262        }
263    }
264    else
265    {
266        if ( val & O_NONBLOCK )
267        {
268            return fcntl( fd, F_SETFL, val &(~O_NONBLOCK) );
269        }
270    }
271    return 0;
272}
273
274static int lsapi_close( int fd )
275{
276    int ret;
277    while( 1 )
278    {
279        ret = close( fd );
280        if (( ret == -1 )&&( errno == EINTR )&&(g_running))
281            continue;
282        return ret;
283    }
284}
285
286static inline ssize_t lsapi_read( int fd, void * pBuf, size_t len )
287{
288    ssize_t ret;
289    while( 1 )
290    {
291        ret = read( fd, (char *)pBuf, len );
292        if (( ret == -1 )&&( errno == EINTR )&&(g_running))
293            continue;
294        return ret;
295    }
296}
297
298/*
299static int lsapi_write( int fd, const void * pBuf, int len )
300{
301   int ret;
302   const char * pCur;
303   const char * pEnd;
304   if ( len == 0 )
305       return 0;
306   pCur = (const char *)pBuf;
307   pEnd = pCur + len;
308   while( g_running && (pCur < pEnd) )
309   {
310       ret = write( fd, pCur, pEnd - pCur );
311       if ( ret >= 0)
312           pCur += ret;
313       else if (( ret == -1 )&&( errno != EINTR ))
314           return ret;
315   }
316   return pCur - (const char *)pBuf;
317}
318*/
319
320static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen )
321{
322    int ret;
323    int left = totalLen;
324    int n = count;
325    while(( left > 0 )&&g_running )
326    {
327        ret = writev( fd, *pVec, n );
328        if ( ret > 0 )
329        {
330            left -= ret;
331            if (( left <= 0)||( !g_running ))
332                return totalLen - left;
333            while( ret > 0 )
334            {
335                if ( (*pVec)->iov_len <= (unsigned int )ret )
336                {
337                    ret -= (*pVec)->iov_len;
338                    ++(*pVec);
339                }
340                else
341                {
342                    (*pVec)->iov_base = (char *)(*pVec)->iov_base + ret;
343                    (*pVec)->iov_len -= ret;
344                    break;
345                }
346            }
347        }
348        else if ( ret == -1 )
349        {
350            if ( errno == EAGAIN )
351            {
352                if ( totalLen - left > 0 )
353                    return totalLen - left;
354                else
355                    return -1;
356            }
357            else if ( errno != EINTR )
358                return ret;
359        }
360    }
361    return totalLen - left;
362}
363
364/*
365static int getTotalLen( struct iovec * pVec, int count )
366{
367   struct iovec * pEnd = pVec + count;
368   int total = 0;
369   while( pVec < pEnd )
370   {
371       total += pVec->iov_len;
372       ++pVec;
373   }
374   return total;
375}
376*/
377
378static inline int allocateBuf( LSAPI_Request * pReq, int size )
379{
380    char * pBuf = (char *)realloc( pReq->m_pReqBuf, size );
381    if ( pBuf )
382    {
383        pReq->m_pReqBuf = pBuf;
384        pReq->m_reqBufSize = size;
385        pReq->m_pHeader = (struct lsapi_req_header *)pReq->m_pReqBuf;
386        return 0;
387    }
388    return -1;
389}
390
391
392static int allocateIovec( LSAPI_Request * pReq, int n )
393{
394    struct iovec * p = (struct iovec *)realloc(
395                pReq->m_pIovec, sizeof(struct iovec) * n );
396    if ( !p )
397        return -1;
398    pReq->m_pIovecToWrite = p + ( pReq->m_pIovecToWrite - pReq->m_pIovec );
399    pReq->m_pIovecCur = p + ( pReq->m_pIovecCur - pReq->m_pIovec );
400    pReq->m_pIovec = p;
401    pReq->m_pIovecEnd = p + n;
402    return 0;
403}
404
405static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size )
406{
407    char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size );
408    if ( !p )
409        return -1;
410    pReq->m_pRespHeaderBufPos   = p + ( pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf );
411    pReq->m_pRespHeaderBuf      = p;
412    pReq->m_pRespHeaderBufEnd   = p + size;
413    return 0;
414}
415
416
417static inline int verifyHeader( struct lsapi_packet_header * pHeader, char pktType )
418{
419    if (( LSAPI_VERSION_B0 != pHeader->m_versionB0 )||
420        ( LSAPI_VERSION_B1 != pHeader->m_versionB1 )||
421        ( pktType != pHeader->m_type ))
422        return -1;
423    if ( LSAPI_ENDIAN != (pHeader->m_flag & LSAPI_ENDIAN_BIT ))
424    {
425        register char b;
426        b = pHeader->m_packetLen.m_bytes[0];
427        pHeader->m_packetLen.m_bytes[0] = pHeader->m_packetLen.m_bytes[3];
428        pHeader->m_packetLen.m_bytes[3] = b;
429        b = pHeader->m_packetLen.m_bytes[1];
430        pHeader->m_packetLen.m_bytes[1] = pHeader->m_packetLen.m_bytes[2];
431        pHeader->m_packetLen.m_bytes[2] = b;
432    }
433    return pHeader->m_packetLen.m_iLen;
434}
435
436static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList,
437                        int *curSize, int newSize )
438{
439    struct LSAPI_key_value_pair * pBuf;
440        if ( *curSize >= newSize )
441        return 0;
442    if ( newSize > 8192 )
443        return -1;
444    pBuf = (struct LSAPI_key_value_pair *)realloc( *pEnvList, newSize *
445                    sizeof(struct LSAPI_key_value_pair) );
446    if ( pBuf )
447    {
448        *pEnvList = pBuf;
449        *curSize  = newSize;
450        return 0;
451    }
452    else
453        return -1;
454
455}
456
457static inline int isPipe( int fd )
458{
459    char        achPeer[128];
460    socklen_t   len = 128;
461    if (( getpeername( fd, (struct sockaddr *)achPeer, &len ) != 0 )&&
462        ( errno == ENOTCONN ))
463        return 0;
464    else
465        return 1;
466}
467
468static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count,
469            char **pBegin, char * pEnd )
470{
471    struct LSAPI_key_value_pair * pEnvEnd;
472        int keyLen = 0, valLen = 0;
473    if ( count > 8192 )
474        return -1;
475    pEnvEnd = pEnvList + count;
476    while( pEnvList != pEnvEnd )
477    {
478        if ( pEnd - *pBegin < 4 )
479            return -1;
480        keyLen = *((unsigned char *)((*pBegin)++));
481        keyLen = (keyLen << 8) + *((unsigned char *)((*pBegin)++));
482        valLen = *((unsigned char *)((*pBegin)++));
483        valLen = (valLen << 8) + *((unsigned char *)((*pBegin)++));
484        if ( *pBegin + keyLen + valLen > pEnd )
485            return -1;
486        if (( !keyLen )||( !valLen ))
487            return -1;
488
489        pEnvList->pKey = *pBegin;
490        *pBegin += keyLen;
491        pEnvList->pValue = *pBegin;
492        *pBegin += valLen;
493
494        pEnvList->keyLen = keyLen - 1;
495        pEnvList->valLen = valLen - 1;
496        ++pEnvList;
497    }
498    if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 )
499        return -1;
500    *pBegin += 4;
501    return 0;
502}
503
504static inline void swapIntEndian( int * pInteger )
505{
506    char * p = (char *)pInteger;
507    register char b;
508    b = p[0];
509    p[0] = p[3];
510    p[3] = b;
511    b = p[1];
512    p[1] = p[2];
513    p[2] = b;
514
515}
516
517static inline void fixEndian( LSAPI_Request * pReq )
518{
519    struct lsapi_req_header *p= pReq->m_pHeader;
520    swapIntEndian( &p->m_httpHeaderLen );
521    swapIntEndian( &p->m_reqBodyLen );
522    swapIntEndian( &p->m_scriptFileOff );
523    swapIntEndian( &p->m_scriptNameOff );
524    swapIntEndian( &p->m_queryStringOff );
525    swapIntEndian( &p->m_requestMethodOff );
526    swapIntEndian( &p->m_cntUnknownHeaders );
527    swapIntEndian( &p->m_cntEnv );
528    swapIntEndian( &p->m_cntSpecialEnv );
529}
530
531static void fixHeaderIndexEndian( LSAPI_Request * pReq )
532{
533    int i;
534    for( i = 0; i < H_TRANSFER_ENCODING; ++i )
535    {
536        if ( pReq->m_pHeaderIndex->m_headerOff[i] )
537        {
538            register char b;
539            char * p = (char *)(&pReq->m_pHeaderIndex->m_headerLen[i]);
540            b = p[0];
541            p[0] = p[1];
542            p[1] = b;
543            swapIntEndian( &pReq->m_pHeaderIndex->m_headerOff[i] );
544        }
545    }
546    if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
547    {
548        struct lsapi_header_offset * pCur, *pEnd;
549        pCur = pReq->m_pUnknownHeader;
550        pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
551        while( pCur < pEnd )
552        {
553            swapIntEndian( &pCur->nameOff );
554            swapIntEndian( &pCur->nameLen );
555            swapIntEndian( &pCur->valueOff );
556            swapIntEndian( &pCur->valueLen );
557            ++pCur;
558        }
559    }
560}
561
562static uid_t s_uid = 0;
563static uid_t s_defaultUid;  //web server need set this
564static gid_t s_defaultGid;
565
566#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
567
568#define LSAPI_LVE_DISABLED  0
569#define LSAPI_LVE_ENABLED   1
570#define LSAPI_CAGEFS_ENABLED 2
571#define LSAPI_CAGEFS_NO_SUEXEC 3
572struct liblve;
573static int s_enable_lve = LSAPI_LVE_DISABLED;
574static struct liblve * s_lve = NULL;
575
576static void *s_liblve;
577static int (*fp_lve_is_available)(void) = NULL;
578static int (*fp_lve_instance_init)(struct liblve *) = NULL;
579static int (*fp_lve_destroy)(struct liblve *) = NULL;
580static int (*fp_lve_enter)(struct liblve *, uint32_t, int32_t, int32_t, uint32_t *) = NULL;
581static int (*fp_lve_leave)(struct liblve *, uint32_t *) = NULL;
582static int (*fp_lve_jail)( struct passwd *, char *) = NULL;
583static int lsapi_load_lve_lib()
584{
585    s_liblve = dlopen("liblve.so.0", RTLD_LAZY);
586    if (s_liblve)
587    {
588        fp_lve_is_available = dlsym(s_liblve, "lve_is_available");
589        if (dlerror() == NULL)
590        {
591            if ( !(*fp_lve_is_available)() )
592            {
593                int uid = getuid();
594                if ( uid )
595                {
596                    setreuid( s_uid, uid );
597                    if ( !(*fp_lve_is_available)() )
598                        s_enable_lve = 0;
599                    setreuid( uid, s_uid );
600                }
601            }
602        }
603    }
604    else
605    {
606        s_enable_lve = LSAPI_LVE_DISABLED;
607    }
608    return (s_liblve)? 0 : -1;
609}
610
611static int init_lve_ex()
612{
613    int rc;
614    if ( !s_liblve )
615        return -1;
616    fp_lve_instance_init = dlsym(s_liblve, "lve_instance_init");
617    fp_lve_destroy = dlsym(s_liblve, "lve_destroy");
618    fp_lve_enter = dlsym(s_liblve, "lve_enter");
619    fp_lve_leave = dlsym(s_liblve, "lve_leave");
620    if ( s_enable_lve >= LSAPI_CAGEFS_ENABLED )
621        fp_lve_jail = dlsym(s_liblve, "jail" );
622
623    if ( s_lve == NULL )
624    {
625        rc = (*fp_lve_instance_init)(NULL);
626        s_lve = malloc(rc);
627    }
628    rc = (*fp_lve_instance_init)(s_lve);
629    if (rc != 0)
630    {
631        perror( "LSAPI: Unable to initialize LVE" );
632        free( s_lve );
633        s_lve = NULL;
634        return -1;
635    }
636    return 0;
637
638}
639
640#endif
641
642
643
644static int readSecret( const char * pSecretFile )
645{
646    struct stat st;
647    int fd = open( pSecretFile, O_RDONLY , 0600 );
648    if ( fd == -1 )
649    {
650        fprintf( stderr, "LSAPI: failed to open secret file: %s!\n", pSecretFile );
651        return -1;
652    }
653    if ( fstat( fd, &st ) == -1 )
654    {
655        fprintf( stderr, "LSAPI: failed to check state of file: %s!\n", pSecretFile );
656        close( fd );
657        return -1;
658    }
659/*
660    if ( st.st_uid != s_uid )
661    {
662        fprintf( stderr, "LSAPI: file owner check failure: %s!\n", pSecretFile );
663        close( fd );
664        return -1;
665    }
666*/
667    if ( st.st_mode & 0077 )
668    {
669        fprintf( stderr, "LSAPI: file permission check failure: %s\n", pSecretFile );
670        close( fd );
671        return -1;
672    }
673    if ( read( fd, s_pSecret, 16 ) < 16 )
674    {
675        fprintf( stderr, "LSAPI: failed to read secret from secret file: %s\n", pSecretFile );
676        close( fd );
677        return -1;
678    }
679    close( fd );
680    return 0;
681}
682
683int LSAPI_is_suEXEC_Daemon()
684{
685    if (( !s_uid )&&( s_pSecret[0] ))
686        return 1;
687    else
688        return 0;
689}
690
691static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char *pErr2 )
692{
693    char achError[1024];
694    int n = snprintf(achError, 1024, "%s:%s: %s\n", pErr1, (pErr2)?pErr2:"", strerror( errno ) );
695    if ( pReq )
696        LSAPI_Write_Stderr_r( pReq, achError, n );
697    else
698        write( STDERR_FILENO, achError, n );
699    return 0;
700}
701
702static int lsapi_lve_error( LSAPI_Request * pReq )
703{
704    static const char * headers[] =
705    {
706        "Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0",
707        "Pragma: no-cache",
708        "Retry-After: 60",
709        "Content-Type: text/html",
710        NULL
711    };
712    static const char achBody[] =
713        "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"
714        "<HTML><HEAD>\n<TITLE>508 Resource Limit Is Reached</TITLE>\n"
715        "</HEAD><BODY>\n" "<H1>Resource Limit Is Reached</H1>\n"
716        "The website is temporarily unable to service your request as it exceeded resource limit.\n"
717        "Please try again later.\n"
718        "<HR>\n"
719        "</BODY></HTML>\n";
720
721    LSAPI_ErrResponse_r( pReq, 508, headers, achBody, sizeof( achBody ) - 1 );
722    return 0;
723}
724
725static int lsapi_enterLVE( LSAPI_Request * pReq, uid_t uid )
726{
727#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
728    if ( s_lve && uid ) //root user should not do that
729    {
730        uint32_t cookie;
731        int ret = -1;
732        ret = (*fp_lve_enter)(s_lve, uid, -1, -1, &cookie);
733        if ( ret < 0 )
734        {
735            fprintf( stderr, "Pid (%d): enter LVE (%d) : ressult: %d !\n", getpid(), uid, ret );
736            LSAPI_perror_r(pReq, "LSAPI: lve_enter() failure, reached resource limit.", NULL );
737            lsapi_lve_error( pReq );
738            return -1;
739        }
740    }
741#endif
742
743    return 0;
744}
745
746static int lsapi_jailLVE( LSAPI_Request * pReq, uid_t uid, struct passwd * pw )
747{
748    int ret = 0;
749#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
750    char  error_msg[1024] = "";
751    ret = (*fp_lve_jail)( pw, error_msg );
752    if ( ret < 0 )
753    {
754        fprintf( stderr, "LSAPI (%d): LVE jail(%d) ressult: %d, error: %s !\n",
755                        getpid(), uid, ret, error_msg );
756        LSAPI_perror_r( pReq, "LSAPI: jail() failure.", NULL );
757        return -1;
758    }
759#endif
760    return ret;
761}
762
763
764#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
765static int lsapi_initLVE()
766{
767    const char * pEnv;
768    if ( (pEnv = getenv( "LSAPI_LVE_ENABLE" ))!= NULL )
769    {
770        s_enable_lve = atol( pEnv );
771        pEnv = NULL;
772    }
773    else if ( (pEnv = getenv( "LVE_ENABLE" ))!= NULL )
774    {
775        s_enable_lve = atol( pEnv );
776        pEnv = NULL;
777    }
778    if ( s_enable_lve && !s_uid )
779    {
780        lsapi_load_lve_lib();
781        if ( s_enable_lve )
782        {
783            return init_lve_ex();
784        }
785
786    }
787    return 0;
788}
789#endif
790
791
792static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * pChroot)
793{
794    int rv;
795    struct passwd * pw;
796    pw = getpwuid( uid );
797#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
798    if ( s_lve )
799    {
800        if( lsapi_enterLVE( pReq, uid ) == -1 )
801            return -1;
802        if ( pw && fp_lve_jail)
803        {
804            rv = lsapi_jailLVE( pReq, uid, pw );
805            if ( rv == -1 )
806                return -1;
807            if (( rv == 1 )&&(s_enable_lve == LSAPI_CAGEFS_NO_SUEXEC ))    //this mode only use cageFS, does not use suEXEC
808            {
809                uid = s_defaultUid;
810                gid = s_defaultGid;
811                pw = getpwuid( uid );
812            }
813        }
814    }
815#endif
816    //if ( !uid || !gid )  //do not allow root
817    //{
818    //    return -1;
819    //}
820
821#if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
822    || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
823    if ( s_enable_core_dump )
824        lsapi_enable_core_dump();
825#endif
826
827    rv = setgid(gid);
828    if (rv == -1)
829    {
830        LSAPI_perror_r(pReq, "LSAPI: setgid()", NULL);
831        return -1;
832    }
833    if ( pw && (pw->pw_gid == gid ))
834    {
835        rv = initgroups( pw->pw_name, gid );
836        if (rv == -1)
837        {
838            LSAPI_perror_r(pReq, "LSAPI: initgroups()", NULL);
839            return -1;
840        }
841    }
842    else
843    {
844        rv = setgroups(1, &gid);
845        if (rv == -1)
846        {
847            LSAPI_perror_r(pReq, "LSAPI: setgroups()", NULL);
848        }
849    }
850    if ( pChroot )
851    {
852        rv = chroot( pChroot );
853        if ( rv == -1 )
854        {
855            LSAPI_perror_r(pReq, "LSAPI: chroot()", NULL);
856            return -1;
857        }
858    }
859    rv = setuid(uid);
860    if (rv == -1)
861    {
862        LSAPI_perror_r(pReq, "LSAPI: setuid()", NULL);
863        return -1;
864    }
865#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
866    if ( s_enable_core_dump )
867        lsapi_enable_core_dump();
868#endif
869    return 0;
870}
871
872static int lsapi_suexec_auth( LSAPI_Request *pReq,
873            char * pAuth, int len, char * pUgid, int ugidLen )
874{
875    lsapi_MD5_CTX md5ctx;
876    unsigned char achMD5[16];
877    if ( len < 32 )
878        return -1;
879    memmove( achMD5, pAuth + 16, 16 );
880    memmove( pAuth + 16, s_pSecret, 16 );
881    lsapi_MD5Init( &md5ctx );
882    lsapi_MD5Update( &md5ctx, (unsigned char *)pAuth, 32 );
883    lsapi_MD5Update( &md5ctx, (unsigned char *)pUgid, 8 );
884    lsapi_MD5Final( (unsigned char *)pAuth + 16, &md5ctx);
885    if ( memcmp( achMD5, pAuth + 16, 16 ) == 0 )
886        return 0;
887    return 1;
888}
889
890
891static int lsapi_changeUGid( LSAPI_Request * pReq )
892{
893    int uid = s_defaultUid;
894    int gid = s_defaultGid;
895    const char * pChroot = NULL;
896    struct LSAPI_key_value_pair * pEnv;
897    struct LSAPI_key_value_pair * pAuth;
898    int i;
899    if ( s_uid )
900        return 0;
901    //with special ID  0x00
902    //authenticate the suEXEC request;
903    //first one should be MD5( nonce + lscgid secret )
904    //remember to clear the secret after verification
905    //it should be set at the end of special env
906    i = pReq->m_pHeader->m_cntSpecialEnv - 1;
907    if ( i >= 0 )
908    {
909        pEnv = pReq->m_pSpecialEnvList + i;
910        if (( *pEnv->pKey == '\000' )&&
911            ( strcmp( pEnv->pKey+1, "SUEXEC_AUTH" ) == 0 ))
912        {
913            --pReq->m_pHeader->m_cntSpecialEnv;
914            pAuth = pEnv--;
915            if (( *pEnv->pKey == '\000' )&&
916                ( strcmp( pEnv->pKey+1, "SUEXEC_UGID" ) == 0 ))
917            {
918                --pReq->m_pHeader->m_cntSpecialEnv;
919                uid = *(uint32_t *)pEnv->pValue;
920                gid = *(((uint32_t *)pEnv->pValue) + 1 );
921                //fprintf( stderr, "LSAPI: SUEXEC_UGID set UID: %d, GID: %d\n", uid, gid );
922            }
923            else
924            {
925                fprintf( stderr, "LSAPI: missing SUEXEC_UGID env, use default user!\n" );
926                pEnv = NULL;
927            }
928            if ( pEnv&& lsapi_suexec_auth( pReq, pAuth->pValue, pAuth->valLen, pEnv->pValue, pEnv->valLen ) == 0 )
929            {
930                //read UID, GID from specialEnv
931
932            }
933            else
934            {
935                //authentication error
936                fprintf( stderr, "LSAPI: SUEXEC_AUTH authentication failed, use default user!\n" );
937                uid = 0;
938            }
939        }
940        else
941        {
942            //fprintf( stderr, "LSAPI: no SUEXEC_AUTH env, use default user!\n" );
943        }
944    }
945
946
947    if ( !uid )
948    {
949        uid = s_defaultUid;
950        gid = s_defaultGid;
951    }
952
953    //change uid
954    if ( setUID_LVE( pReq, uid, gid, pChroot ) == -1 )
955    {
956        return -1;
957    }
958
959    s_uid = uid;
960
961    return 0;
962
963}
964
965static int parseContentLenFromHeader(LSAPI_Request * pReq)
966{
967    const char * pContentLen = LSAPI_GetHeader_r( pReq, H_CONTENT_LENGTH );
968    if ( pContentLen )
969        pReq->m_reqBodyLen = strtoll( pContentLen, NULL, 10 );
970    return 0;
971}
972
973
974static int parseRequest( LSAPI_Request * pReq, int totalLen )
975{
976    int shouldFixEndian;
977    char * pBegin = pReq->m_pReqBuf + sizeof( struct lsapi_req_header );
978    char * pEnd = pReq->m_pReqBuf + totalLen;
979    shouldFixEndian = ( LSAPI_ENDIAN != (
980                pReq->m_pHeader->m_pktHeader.m_flag & LSAPI_ENDIAN_BIT ) );
981    if ( shouldFixEndian )
982    {
983        fixEndian( pReq );
984    }
985    if ( (pReq->m_specialEnvListSize < pReq->m_pHeader->m_cntSpecialEnv )&&
986            allocateEnvList( &pReq->m_pSpecialEnvList,
987                &pReq->m_specialEnvListSize,
988                pReq->m_pHeader->m_cntSpecialEnv ) == -1 )
989        return -1;
990    if ( (pReq->m_envListSize < pReq->m_pHeader->m_cntEnv )&&
991            allocateEnvList( &pReq->m_pEnvList, &pReq->m_envListSize,
992                pReq->m_pHeader->m_cntEnv ) == -1 )
993        return -1;
994
995    if ( parseEnv( pReq->m_pSpecialEnvList,
996                pReq->m_pHeader->m_cntSpecialEnv,
997                &pBegin, pEnd ) == -1 )
998        return -1;
999    if ( parseEnv( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
1000                &pBegin, pEnd ) == -1 )
1001        return -1;
1002
1003    pReq->m_pScriptFile     = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptFileOff;
1004    pReq->m_pScriptName     = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptNameOff;
1005    pReq->m_pQueryString    = pReq->m_pReqBuf + pReq->m_pHeader->m_queryStringOff;
1006    pReq->m_pRequestMethod  = pReq->m_pReqBuf + pReq->m_pHeader->m_requestMethodOff;
1007
1008    pBegin = pReq->m_pReqBuf + (( pBegin - pReq->m_pReqBuf + 7 ) & (~0x7));
1009    pReq->m_pHeaderIndex = ( struct lsapi_http_header_index * )pBegin;
1010    pBegin += sizeof( struct lsapi_http_header_index );
1011
1012    pReq->m_pUnknownHeader = (struct lsapi_header_offset *)pBegin;
1013    pBegin += sizeof( struct lsapi_header_offset) *
1014                    pReq->m_pHeader->m_cntUnknownHeaders;
1015
1016    pReq->m_pHttpHeader = pBegin;
1017    pBegin += pReq->m_pHeader->m_httpHeaderLen;
1018    if ( pBegin != pEnd )
1019    {
1020        fprintf( stderr, "%d: request header does match total size, total: %d, real: %ld\n", getpid(), totalLen,
1021                    pBegin - pReq->m_pReqBuf );
1022        return -1;
1023    }
1024    if ( shouldFixEndian )
1025    {
1026        fixHeaderIndexEndian( pReq );
1027    }
1028    pReq->m_reqBodyLen = pReq->m_pHeader->m_reqBodyLen;
1029    if ( pReq->m_reqBodyLen == -2 )
1030    {
1031        parseContentLenFromHeader(pReq);
1032    }
1033
1034    return 0;
1035}
1036
1037//OPTIMIZATION
1038static char s_accept_notify = 0;
1039static char s_schedule_notify = 0;
1040static char s_notify_scheduled = 0;
1041static char s_notified_pid = 0;
1042
1043static struct lsapi_packet_header s_ack = {'L', 'S',
1044                LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
1045
1046
1047static inline int write_req_received_notification( int fd )
1048{
1049    if ( write( fd, &s_ack, LSAPI_PACKET_HEADER_LEN )
1050                < LSAPI_PACKET_HEADER_LEN )
1051        return -1;
1052    return 0;
1053}
1054
1055static void lsapi_sigalarm( int sig )
1056{
1057    if ( s_notify_scheduled )
1058    {
1059        s_notify_scheduled = 0;
1060        if ( g_req.m_fd != -1 )
1061            write_req_received_notification( g_req.m_fd );
1062    }
1063}
1064
1065static inline int lsapi_schedule_notify()
1066{
1067    if ( !s_notify_scheduled )
1068    {
1069        alarm( 2 );
1070        s_notify_scheduled = 1;
1071    }
1072    return 0;
1073}
1074
1075static inline int notify_req_received( int fd )
1076{
1077    if ( s_schedule_notify )
1078        return lsapi_schedule_notify();
1079    return write_req_received_notification( fd );
1080
1081}
1082
1083
1084static inline int lsapi_notify_pid( int fd )
1085{
1086    char achBuf[16];
1087    lsapi_buildPacketHeader( (struct lsapi_packet_header *)achBuf, LSAPI_STDERR_STREAM,
1088                        8 + LSAPI_PACKET_HEADER_LEN );
1089    memmove( &achBuf[8], "\0PID", 4 );
1090    *((int *)&achBuf[12]) = getpid();
1091
1092    if ( write( fd, achBuf, 16 ) < 16 )
1093        return -1;
1094    return 0;
1095}
1096
1097static char s_conn_key_packet[16];
1098static inline int init_conn_key( int fd )
1099{
1100    struct lsapi_packet_header * pHeader = (struct lsapi_packet_header *)s_conn_key_packet;
1101    struct timeval tv;
1102    int i;
1103    gettimeofday( &tv, NULL );
1104    srand( (tv.tv_sec % 0x1000 + tv.tv_usec) ^ rand() );
1105    for( i = 8; i < 16; ++i )
1106    {
1107        s_conn_key_packet[i]=(int) (256.0*rand()/(RAND_MAX+1.0));
1108    }
1109    lsapi_buildPacketHeader( pHeader, LSAPI_REQ_RECEIVED,
1110                        8 + LSAPI_PACKET_HEADER_LEN );
1111    if ( write( fd, s_conn_key_packet, LSAPI_PACKET_HEADER_LEN+8 )
1112                < LSAPI_PACKET_HEADER_LEN+8 )
1113        return -1;
1114    return 0;
1115
1116
1117}
1118
1119static int readReq( LSAPI_Request * pReq )
1120{
1121    int len;
1122    int packetLen;
1123    if ( !pReq )
1124        return -1;
1125    if ( pReq->m_reqBufSize < 8192 )
1126    {
1127        if ( allocateBuf( pReq, 8192 ) == -1 )
1128            return -1;
1129    }
1130
1131    while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN )
1132    {
1133        len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf, pReq->m_reqBufSize );
1134        if ( len <= 0 )
1135            return -1;
1136        pReq->m_bufRead += len;
1137    }
1138    pReq->m_reqState = LSAPI_ST_REQ_HEADER;
1139
1140    packetLen = verifyHeader( &pReq->m_pHeader->m_pktHeader, LSAPI_BEGIN_REQUEST );
1141    if ( packetLen < 0 )
1142    {
1143        fprintf( stderr, "%d: packetLen < 0\n", getpid() );
1144        return -1;
1145    }
1146    if ( packetLen > LSAPI_MAX_HEADER_LEN )
1147    {
1148        fprintf( stderr, "%d: packetLen > %d\n", getpid(), LSAPI_MAX_HEADER_LEN );
1149        return -1;
1150    }
1151
1152    if ( packetLen + 1024 > pReq->m_reqBufSize )
1153    {
1154        if ( allocateBuf( pReq, packetLen + 1024 ) == -1 )
1155            return -1;
1156    }
1157    while( packetLen > pReq->m_bufRead )
1158    {
1159        len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, packetLen - pReq->m_bufRead );
1160        if ( len <= 0 )
1161            return -1;
1162        pReq->m_bufRead += len;
1163    }
1164    if ( parseRequest( pReq, packetLen ) < 0 )
1165    {
1166        fprintf( stderr, "%d: parseRequest error\n", getpid() );
1167        return -1;
1168    }
1169
1170    pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER;
1171
1172    if ( !s_uid )
1173        if ( lsapi_changeUGid( pReq ) )
1174            return -1;
1175    pReq->m_bufProcessed = packetLen;
1176
1177    //OPTIMIZATION
1178    if ( !s_accept_notify && !s_notified_pid )
1179        return notify_req_received( pReq->m_fd );
1180    else
1181    {
1182        s_notified_pid = 0;
1183        return 0;
1184    }
1185}
1186
1187
1188
1189int LSAPI_Init(void)
1190{
1191    if ( !g_inited )
1192    {
1193        s_uid = geteuid();
1194        s_pSecret[0] = 0;
1195        lsapi_signal(SIGPIPE, lsapi_sigpipe);
1196        lsapi_signal(SIGUSR1, lsapi_siguser1);
1197
1198#if defined(SIGXFSZ) && defined(SIG_IGN)
1199        signal(SIGXFSZ, SIG_IGN);
1200#endif
1201        /* let STDOUT function as STDERR,
1202           just in case writing to STDOUT directly */
1203        dup2( 2, 1 );
1204        if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 )
1205            return -1;
1206        g_inited = 1;
1207        s_ppid = getppid();
1208    }
1209    return 0;
1210}
1211
1212void LSAPI_Stop(void)
1213{
1214    g_running = 0;
1215}
1216
1217int LSAPI_IsRunning(void)
1218{
1219    return g_running;
1220}
1221
1222int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
1223{
1224    int newfd;
1225    if ( !pReq )
1226        return -1;
1227    memset( pReq, 0, sizeof( LSAPI_Request ) );
1228    if ( allocateIovec( pReq, 16 ) == -1 )
1229        return -1;
1230    pReq->m_pRespBuf = pReq->m_pRespBufPos = (char *)malloc( LSAPI_RESP_BUF_SIZE );
1231    if ( !pReq->m_pRespBuf )
1232        return -1;
1233    pReq->m_pRespBufEnd = pReq->m_pRespBuf + LSAPI_RESP_BUF_SIZE;
1234    pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
1235    pReq->m_respPktHeaderEnd = &pReq->m_respPktHeader[5];
1236    if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 )
1237        return -1;
1238
1239    if ( fd == STDIN_FILENO )
1240    {
1241        fd = dup( fd );
1242        newfd = open( "/dev/null", O_RDWR );
1243        dup2( newfd, STDIN_FILENO );
1244    }
1245
1246    if ( isPipe( fd ) )
1247    {
1248        pReq->m_fdListen = -1;
1249        pReq->m_fd = fd;
1250    }
1251    else
1252    {
1253        pReq->m_fdListen = fd;
1254        pReq->m_fd = -1;
1255        lsapi_set_nblock( fd, 1 );
1256    }
1257    return 0;
1258}
1259
1260int LSAPI_Is_Listen( void )
1261{
1262    return LSAPI_Is_Listen_r( &g_req );
1263}
1264
1265int LSAPI_Is_Listen_r( LSAPI_Request * pReq)
1266{
1267    return pReq->m_fdListen != -1;
1268}
1269
1270
1271
1272int LSAPI_Accept_r( LSAPI_Request * pReq )
1273{
1274    char        achPeer[128];
1275    socklen_t   len;
1276    int         nodelay = 1;
1277
1278    if ( !pReq )
1279        return -1;
1280    if ( LSAPI_Finish_r( pReq ) == -1 )
1281        return -1;
1282    lsapi_set_nblock( pReq->m_fdListen , 0 );
1283    while( g_running )
1284    {
1285        if ( pReq->m_fd == -1 )
1286        {
1287            if ( pReq->m_fdListen != -1)
1288            {
1289                len = sizeof( achPeer );
1290                pReq->m_fd = accept( pReq->m_fdListen,
1291                            (struct sockaddr *)&achPeer, &len );
1292                if ( pReq->m_fd == -1 )
1293                {
1294                    if (( errno == EINTR )||( errno == EAGAIN))
1295                        continue;
1296                    else
1297                        return -1;
1298                }
1299                else
1300                {
1301                    lsapi_set_nblock( pReq->m_fd , 0 );
1302                    if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
1303                    {
1304                        setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY,
1305                                   (char *)&nodelay, sizeof(nodelay));
1306                    }
1307                    //init_conn_key( pReq->m_fd );
1308                    //OPTIMIZATION
1309                    if ( s_accept_notify )
1310                        if ( notify_req_received( pReq->m_fd ) == -1 )
1311                                return -1;
1312                }
1313            }
1314            else
1315                return -1;
1316        }
1317        if ( !readReq( pReq ) )
1318            break;
1319        //abort();
1320        lsapi_close( pReq->m_fd );
1321        pReq->m_fd = -1;
1322        LSAPI_Reset_r( pReq );
1323    }
1324    return 0;
1325}
1326
1327static struct lsapi_packet_header   finish = {'L', 'S',
1328                LSAPI_RESP_END, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
1329
1330int LSAPI_Finish_r( LSAPI_Request * pReq )
1331{
1332    /* finish req body */
1333    if ( !pReq )
1334        return -1;
1335    if (pReq->m_reqState)
1336    {
1337        if ( pReq->m_fd != -1 )
1338        {
1339            if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1340            {
1341                LSAPI_FinalizeRespHeaders_r( pReq );
1342            }
1343            if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
1344            {
1345                Flush_RespBuf_r( pReq );
1346            }
1347
1348            pReq->m_pIovecCur->iov_base = (void *)&finish;
1349            pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
1350            pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN;
1351            ++pReq->m_pIovecCur;
1352            LSAPI_Flush_r( pReq );
1353        }
1354        LSAPI_Reset_r( pReq );
1355    }
1356    return 0;
1357}
1358
1359
1360void LSAPI_Reset_r( LSAPI_Request * pReq )
1361{
1362    pReq->m_pRespBufPos         = pReq->m_pRespBuf;
1363    pReq->m_pIovecCur           = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
1364    pReq->m_pRespHeaderBufPos   = pReq->m_pRespHeaderBuf;
1365
1366    memset( &pReq->m_pHeaderIndex, 0,
1367            (char *)(pReq->m_respHeaderLen) - (char *)&pReq->m_pHeaderIndex );
1368}
1369
1370
1371int LSAPI_Release_r( LSAPI_Request * pReq )
1372{
1373    if ( pReq->m_pReqBuf )
1374        free( pReq->m_pReqBuf );
1375    if ( pReq->m_pSpecialEnvList )
1376        free( pReq->m_pSpecialEnvList );
1377    if ( pReq->m_pEnvList )
1378        free( pReq->m_pEnvList );
1379    if ( pReq->m_pRespHeaderBuf )
1380        free( pReq->m_pRespHeaderBuf );
1381    return 0;
1382}
1383
1384
1385char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex )
1386{
1387    int off;
1388    if ( !pReq || ((unsigned int)headerIndex > H_TRANSFER_ENCODING) )
1389        return NULL;
1390    off = pReq->m_pHeaderIndex->m_headerOff[ headerIndex ];
1391    if ( !off )
1392        return NULL;
1393    if ( *(pReq->m_pHttpHeader + off
1394        + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) )
1395    {
1396        *( pReq->m_pHttpHeader + off
1397            + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0;
1398    }
1399    return pReq->m_pHttpHeader + off;
1400}
1401
1402static int readBodyToReqBuf( LSAPI_Request * pReq )
1403{
1404    off_t bodyLeft;
1405    ssize_t len = pReq->m_bufRead - pReq->m_bufProcessed;
1406    if ( len > 0 )
1407        return len;
1408    pReq->m_bufRead = pReq->m_bufProcessed = pReq->m_pHeader->m_pktHeader.m_packetLen.m_iLen;
1409
1410    bodyLeft = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
1411    len = pReq->m_reqBufSize - pReq->m_bufRead;
1412    if ( len < 0 )
1413        return -1;
1414    if ( len > bodyLeft )
1415        len = bodyLeft;
1416
1417    len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, len );
1418    if ( len > 0 )
1419        pReq->m_bufRead += len;
1420    return len;
1421}
1422
1423
1424int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq )
1425{
1426    if (!pReq || (pReq->m_fd ==-1) )
1427        return EOF;
1428    if ( pReq->m_bufProcessed >= pReq->m_bufRead )
1429    {
1430        if ( readBodyToReqBuf( pReq ) <= 0 )
1431            return EOF;
1432    }
1433    ++pReq->m_reqBodyRead;
1434    return (unsigned char)*(pReq->m_pReqBuf + pReq->m_bufProcessed++);
1435}
1436
1437
1438
1439int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF )
1440{
1441    ssize_t len;
1442    ssize_t left;
1443    char * pBufEnd = pBuf + bufLen - 1;
1444    char * pBufCur = pBuf;
1445    char * pCur;
1446    char * p;
1447    if (!pReq || (pReq->m_fd ==-1) ||( !pBuf )||(bufLen < 0 )|| !getLF )
1448        return -1;
1449    *getLF = 0;
1450    while( (left = pBufEnd - pBufCur ) > 0 )
1451    {
1452
1453        len = pReq->m_bufRead - pReq->m_bufProcessed;
1454        if ( len <= 0 )
1455        {
1456            if ( (len = readBodyToReqBuf( pReq )) <= 0 )
1457            {
1458                *getLF = 1;
1459                break;
1460            }
1461        }
1462        if ( len > left )
1463            len = left;
1464        pCur = pReq->m_pReqBuf + pReq->m_bufProcessed;
1465        p = memchr( pCur, '\n', len );
1466        if ( p )
1467            len = p - pCur + 1;
1468        memmove( pBufCur, pCur, len );
1469        pBufCur += len;
1470        pReq->m_bufProcessed += len;
1471
1472        pReq->m_reqBodyRead += len;
1473
1474        if ( p )
1475        {
1476            *getLF = 1;
1477            break;
1478        }
1479    }
1480    *pBufCur = 0;
1481
1482    return pBufCur - pBuf;
1483}
1484
1485
1486ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen )
1487{
1488    ssize_t len;
1489    off_t total;
1490    /* char *pOldBuf = pBuf; */
1491    if (!pReq || (pReq->m_fd ==-1) || ( !pBuf )||(bufLen < 0 ))
1492        return -1;
1493
1494    total = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
1495
1496    if ( total <= 0 )
1497        return 0;
1498    if ( total < bufLen )
1499        bufLen = total;
1500
1501    total = 0;
1502    len = pReq->m_bufRead - pReq->m_bufProcessed;
1503    if ( len > 0 )
1504    {
1505        if ( len > bufLen )
1506            len = bufLen;
1507        memmove( pBuf, pReq->m_pReqBuf + pReq->m_bufProcessed, len );
1508        pReq->m_bufProcessed += len;
1509        total += len;
1510        pBuf += len;
1511        bufLen -= len;
1512    }
1513    while( bufLen > 0 )
1514    {
1515        len = lsapi_read( pReq->m_fd, pBuf, bufLen );
1516        if ( len > 0 )
1517        {
1518            total += len;
1519            pBuf += len;
1520            bufLen -= len;
1521        }
1522        else if ( len <= 0 )
1523        {
1524            if ( !total)
1525                return -1;
1526            break;
1527        }
1528    }
1529    pReq->m_reqBodyRead += total;
1530    return total;
1531
1532}
1533
1534
1535ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
1536{
1537    struct lsapi_packet_header * pHeader;
1538    const char * pEnd;
1539    const char * p;
1540    ssize_t bufLen;
1541    ssize_t toWrite;
1542    ssize_t packetLen;
1543    int skip = 0;
1544
1545    if ( !pReq || !pBuf || (pReq->m_fd == -1) )
1546        return -1;
1547    if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1548    {
1549        LSAPI_FinalizeRespHeaders_r( pReq );
1550/*
1551        if ( *pBuf == '\r' )
1552        {
1553            ++skip;
1554        }
1555        if ( *pBuf == '\n' )
1556        {
1557            ++skip;
1558        }
1559*/
1560    }
1561    pReq->m_reqState |= LSAPI_ST_RESP_BODY;
1562
1563    if ( (len - skip) < pReq->m_pRespBufEnd - pReq->m_pRespBufPos )
1564    {
1565        memmove( pReq->m_pRespBufPos, pBuf + skip, len - skip );
1566        pReq->m_pRespBufPos += len - skip;
1567        return len;
1568    }
1569
1570
1571    pHeader = pReq->m_respPktHeader;
1572    p       = pBuf + skip;
1573    pEnd    = pBuf + len;
1574    bufLen  = pReq->m_pRespBufPos - pReq->m_pRespBuf;
1575
1576    while( ( toWrite = pEnd - p ) > 0 )
1577    {
1578        packetLen = toWrite + bufLen;
1579        if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen)
1580        {
1581            packetLen = LSAPI_MAX_DATA_PACKET_LEN;
1582            toWrite = packetLen - bufLen;
1583        }
1584
1585        lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
1586                            packetLen + LSAPI_PACKET_HEADER_LEN );
1587        pReq->m_totalLen += packetLen + LSAPI_PACKET_HEADER_LEN;
1588
1589        pReq->m_pIovecCur->iov_base = (void *)pHeader;
1590        pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
1591        ++pReq->m_pIovecCur;
1592        ++pHeader;
1593        if ( bufLen > 0 )
1594        {
1595            pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
1596            pReq->m_pIovecCur->iov_len  = bufLen;
1597            pReq->m_pRespBufPos = pReq->m_pRespBuf;
1598            ++pReq->m_pIovecCur;
1599            bufLen = 0;
1600        }
1601
1602        pReq->m_pIovecCur->iov_base = (void *)p;
1603        pReq->m_pIovecCur->iov_len  = toWrite;
1604        ++pReq->m_pIovecCur;
1605        p += toWrite;
1606
1607        if ( pHeader >= pReq->m_respPktHeaderEnd - 1)
1608        {
1609            if ( LSAPI_Flush_r( pReq ) == -1 )
1610                return -1;
1611            pHeader = pReq->m_respPktHeader;
1612        }
1613    }
1614    if ( pHeader != pReq->m_respPktHeader )
1615        if ( LSAPI_Flush_r( pReq ) == -1 )
1616            return -1;
1617    return p - pBuf;
1618}
1619
1620#if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__)
1621ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1622{
1623    ssize_t ret;
1624    off_t written;
1625    ret = sendfile( fdIn, fdOut, *off, size, NULL, &written, 0 );
1626    if ( written > 0 )
1627    {
1628        ret = written;
1629        *off += ret;
1630    }
1631    return ret;
1632}
1633#endif
1634
1635#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
1636ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1637{
1638    ssize_t ret;
1639    off_t len = size;
1640    ret = sendfile( fdIn, fdOut, *off, &len, NULL, 0 );
1641    if (( ret == 0 )&&( len > 0 ))
1642    {
1643        ret = len;
1644        *off += len;
1645    }
1646    return ret;
1647}
1648#endif
1649
1650#if defined(sun) || defined(__sun)
1651#include <sys/sendfile.h>
1652ssize_t gsendfile( int fdOut, int fdIn, off_t *off, size_t size )
1653{
1654    int n = 0 ;
1655    sendfilevec_t vec[1];
1656
1657    vec[n].sfv_fd   = fdIn;
1658    vec[n].sfv_flag = 0;
1659    vec[n].sfv_off  = *off;
1660    vec[n].sfv_len  = size;
1661    ++n;
1662
1663    size_t written;
1664    ssize_t ret = sendfilev( fdOut, vec, n, &written );
1665    if (( !ret )||( errno == EAGAIN ))
1666        ret = written;
1667    if ( ret > 0 )
1668        *off += ret;
1669    return ret;
1670}
1671#endif
1672
1673#if defined(linux) || defined(__linux) || defined(__linux__) || \
1674    defined(__gnu_linux__)
1675#include <sys/sendfile.h>
1676#define gsendfile sendfile
1677#endif
1678#if defined(HPUX)
1679ssize_t gsendfile( int fdOut, int fdIn, off_t * off, size_t size )
1680{
1681    return sendfile( fdOut, fdIn, off, size, NULL, 0 );
1682}
1683#endif
1684
1685ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size )
1686{
1687    struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
1688    if ( !pReq || (pReq->m_fd == -1) || fdIn == -1 )
1689        return -1;
1690    if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1691    {
1692        LSAPI_FinalizeRespHeaders_r( pReq );
1693    }
1694    pReq->m_reqState |= LSAPI_ST_RESP_BODY;
1695
1696    LSAPI_Flush_r(pReq);
1697
1698    lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
1699                            size + LSAPI_PACKET_HEADER_LEN );
1700
1701
1702    if (write(pReq->m_fd,  (const char *) pHeader, LSAPI_PACKET_HEADER_LEN ) != LSAPI_PACKET_HEADER_LEN)
1703        return -1;
1704
1705    return gsendfile( pReq->m_fd, fdIn, off, size );
1706}
1707
1708
1709void Flush_RespBuf_r( LSAPI_Request * pReq )
1710{
1711    struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
1712    int bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf;
1713    pReq->m_reqState |= LSAPI_ST_RESP_BODY;
1714    lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
1715                        bufLen + LSAPI_PACKET_HEADER_LEN );
1716    pReq->m_totalLen += bufLen + LSAPI_PACKET_HEADER_LEN;
1717
1718    pReq->m_pIovecCur->iov_base = (void *)pHeader;
1719    pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
1720    ++pReq->m_pIovecCur;
1721    ++pHeader;
1722    if ( bufLen > 0 )
1723    {
1724        pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
1725        pReq->m_pIovecCur->iov_len  = bufLen;
1726        pReq->m_pRespBufPos = pReq->m_pRespBuf;
1727        ++pReq->m_pIovecCur;
1728        bufLen = 0;
1729    }
1730}
1731
1732
1733
1734
1735int LSAPI_Flush_r( LSAPI_Request * pReq )
1736{
1737    int ret = 0;
1738    int n;
1739    if ( !pReq )
1740        return -1;
1741    n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
1742    if (( 0 == n )&&( pReq->m_pRespBufPos == pReq->m_pRespBuf ))
1743        return 0;
1744    if ( pReq->m_fd == -1 )
1745    {
1746        pReq->m_pRespBufPos = pReq->m_pRespBuf;
1747        pReq->m_totalLen = 0;
1748        pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
1749        return -1;
1750    }
1751    if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1752    {
1753        LSAPI_FinalizeRespHeaders_r( pReq );
1754    }
1755    if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
1756    {
1757        Flush_RespBuf_r( pReq );
1758    }
1759
1760    n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
1761    if ( n > 0 )
1762    {
1763
1764        ret = lsapi_writev( pReq->m_fd, &pReq->m_pIovecToWrite,
1765                  n, pReq->m_totalLen );
1766        if ( ret < pReq->m_totalLen )
1767        {
1768            lsapi_close( pReq->m_fd );
1769            pReq->m_fd = -1;
1770            ret = -1;
1771        }
1772        pReq->m_totalLen = 0;
1773        pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
1774    }
1775    return ret;
1776}
1777
1778
1779ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
1780{
1781    struct lsapi_packet_header header;
1782    const char * pEnd;
1783    const char * p;
1784    ssize_t packetLen;
1785    ssize_t totalLen;
1786    int ret;
1787    struct iovec iov[2];
1788    struct iovec *pIov;
1789
1790    if ( !pReq )
1791        return -1;
1792    if (( pReq->m_fd == -1 )||(pReq->m_fd == pReq->m_fdListen ))
1793        return write( 2, pBuf, len );
1794    if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
1795    {
1796        LSAPI_Flush_r( pReq );
1797    }
1798
1799    p       = pBuf;
1800    pEnd    = pBuf + len;
1801
1802    while( ( packetLen = pEnd - p ) > 0 )
1803    {
1804        if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen)
1805        {
1806            packetLen = LSAPI_MAX_DATA_PACKET_LEN;
1807        }
1808
1809        lsapi_buildPacketHeader( &header, LSAPI_STDERR_STREAM,
1810                            packetLen + LSAPI_PACKET_HEADER_LEN );
1811        totalLen = packetLen + LSAPI_PACKET_HEADER_LEN;
1812
1813        iov[0].iov_base = (void *)&header;
1814        iov[0].iov_len  = LSAPI_PACKET_HEADER_LEN;
1815
1816        iov[1].iov_base = (void *)p;
1817        iov[1].iov_len  = packetLen;
1818        p += packetLen;
1819        pIov = iov;
1820        ret = lsapi_writev( pReq->m_fd, &pIov,
1821                  2, totalLen );
1822        if ( ret < totalLen )
1823        {
1824            lsapi_close( pReq->m_fd );
1825            pReq->m_fd = -1;
1826            ret = -1;
1827        }
1828    }
1829    return p - pBuf;
1830}
1831
1832static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
1833{
1834    int i;
1835    char * pValue;
1836    for( i = 0; i < H_TRANSFER_ENCODING; ++i )
1837    {
1838        if ( pReq->m_pHeaderIndex->m_headerOff[i] )
1839        {
1840            if ( strcmp( name, CGI_HEADERS[i] ) == 0 )
1841            {
1842                pValue = pReq->m_pHttpHeader
1843                         + pReq->m_pHeaderIndex->m_headerOff[i];
1844                if ( *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) != '\0')
1845                {
1846                    *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) = '\0';
1847                }
1848                return pValue;
1849            }
1850        }
1851    }
1852    if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
1853    {
1854        const char *p;
1855        char *pKey;
1856        char *pKeyEnd;
1857        int  keyLen;
1858        struct lsapi_header_offset * pCur, *pEnd;
1859        pCur = pReq->m_pUnknownHeader;
1860        pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
1861        while( pCur < pEnd )
1862        {
1863            pKey = pReq->m_pHttpHeader + pCur->nameOff;
1864            keyLen = pCur->nameLen;
1865            pKeyEnd = pKey + keyLen;
1866            p = &name[5];
1867
1868            while(( pKey < pKeyEnd )&&( *p ))
1869            {
1870                char ch = toupper( *pKey );
1871                if ((ch != *p )||(( *p == '_' )&&( ch != '-')))
1872                    break;
1873                ++p; ++pKey;
1874            }
1875            if (( pKey == pKeyEnd )&& (!*p ))
1876            {
1877                pValue = pReq->m_pHttpHeader + pCur->valueOff;
1878
1879                if ( *(pValue + pCur->valueLen) != '\0')
1880                {
1881                    *(pValue + pCur->valueLen) = '\0';
1882                }
1883                return pValue;
1884            }
1885            ++pCur;
1886        }
1887    }
1888    return NULL;
1889}
1890
1891
1892char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name )
1893{
1894    struct LSAPI_key_value_pair * pBegin = pReq->m_pEnvList;
1895    struct LSAPI_key_value_pair * pEnd = pBegin + pReq->m_pHeader->m_cntEnv;
1896    if ( !pReq || !name )
1897        return NULL;
1898    if ( strncmp( name, "HTTP_", 5 ) == 0 )
1899    {
1900        return GetHeaderVar( pReq, name );
1901    }
1902    while( pBegin < pEnd )
1903    {
1904        if ( strcmp( name, pBegin->pKey ) == 0 )
1905            return pBegin->pValue;
1906        ++pBegin;
1907    }
1908    return NULL;
1909}
1910
1911struct _headerInfo
1912{
1913    const char * _name;
1914    int          _nameLen;
1915    const char * _value;
1916    int          _valueLen;
1917};
1918
1919int compareValueLocation(const void * v1, const void *v2 )
1920{
1921    return ((const struct _headerInfo *)v1)->_value -
1922           ((const struct _headerInfo *)v2)->_value;
1923}
1924
1925int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
1926            LSAPI_CB_EnvHandler fn, void * arg )
1927{
1928    int i;
1929    int len = 0;
1930    char * pValue;
1931    int ret;
1932    int count = 0;
1933    struct _headerInfo headers[512];
1934
1935    if ( !pReq || !fn )
1936        return -1;
1937
1938    if ( !pReq->m_pHeaderIndex )
1939        return 0;
1940
1941    for( i = 0; i < H_TRANSFER_ENCODING; ++i )
1942    {
1943        if ( pReq->m_pHeaderIndex->m_headerOff[i] )
1944        {
1945            len = pReq->m_pHeaderIndex->m_headerLen[i];
1946            pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
1947            *(pValue + len ) = 0;
1948            headers[count]._name = HTTP_HEADERS[i];
1949            headers[count]._nameLen = HTTP_HEADER_LEN[i];
1950            headers[count]._value = pValue;
1951            headers[count]._valueLen = len;
1952            ++count;
1953
1954            //ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i],
1955            //            pValue, len, arg );
1956            //if ( ret <= 0 )
1957            //    return ret;
1958        }
1959    }
1960    if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
1961    {
1962        char *pKey;
1963        int  keyLen;
1964        struct lsapi_header_offset * pCur, *pEnd;
1965        pCur = pReq->m_pUnknownHeader;
1966        pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
1967        while( pCur < pEnd )
1968        {
1969            pKey = pReq->m_pHttpHeader + pCur->nameOff;
1970            keyLen = pCur->nameLen;
1971            *(pKey + keyLen ) = 0;
1972
1973            pValue = pReq->m_pHttpHeader + pCur->valueOff;
1974            *(pValue + pCur->valueLen ) = 0;
1975            headers[count]._name = pKey;
1976            headers[count]._nameLen = keyLen;
1977            headers[count]._value = pValue;
1978            headers[count]._valueLen = pCur->valueLen;
1979            ++count;
1980            if ( count == 512 )
1981                break;
1982            //ret = (*fn)( pKey, keyLen,
1983            //            pValue, pCur->valueLen, arg );
1984            //if ( ret <= 0 )
1985            //    return ret;
1986            ++pCur;
1987        }
1988    }
1989    qsort( headers, count, sizeof( struct _headerInfo ), compareValueLocation );
1990    for( i = 0; i < count; ++i )
1991    {
1992        ret = (*fn)( headers[i]._name, headers[i]._nameLen,
1993                    headers[i]._value, headers[i]._valueLen, arg );
1994        if ( ret <= 0 )
1995            return ret;
1996    }
1997    return count;
1998
1999}
2000
2001
2002int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
2003            LSAPI_CB_EnvHandler fn, void * arg )
2004{
2005    int i;
2006    int len = 0;
2007    char * pValue;
2008    int ret;
2009    int count = 0;
2010    if ( !pReq || !fn )
2011        return -1;
2012    for( i = 0; i < H_TRANSFER_ENCODING; ++i )
2013    {
2014        if ( pReq->m_pHeaderIndex->m_headerOff[i] )
2015        {
2016            len = pReq->m_pHeaderIndex->m_headerLen[i];
2017            pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
2018            *(pValue + len ) = 0;
2019            ret = (*fn)( CGI_HEADERS[i], CGI_HEADER_LEN[i],
2020                        pValue, len, arg );
2021            ++count;
2022            if ( ret <= 0 )
2023                return ret;
2024        }
2025    }
2026    if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
2027    {
2028        char achHeaderName[256];
2029        char *p;
2030        char *pKey;
2031        char *pKeyEnd ;
2032        int  keyLen;
2033        struct lsapi_header_offset * pCur, *pEnd;
2034        pCur = pReq->m_pUnknownHeader;
2035        pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
2036        while( pCur < pEnd )
2037        {
2038            pKey = pReq->m_pHttpHeader + pCur->nameOff;
2039            keyLen = pCur->nameLen;
2040            if ( keyLen > 250 )
2041                keyLen = 250;
2042            pKeyEnd = pKey + keyLen;
2043            memcpy( achHeaderName, "HTTP_", 5 );
2044            p = &achHeaderName[5];
2045
2046            while( pKey < pKeyEnd )
2047            {
2048                char ch = *pKey++;
2049                if ( ch == '-' )
2050                    *p++ = '_';
2051                else
2052                    *p++ = toupper( ch );
2053            }
2054            *p = 0;
2055            keyLen += 5;
2056
2057            pValue = pReq->m_pHttpHeader + pCur->valueOff;
2058            *(pValue + pCur->valueLen ) = 0;
2059            ret = (*fn)( achHeaderName, keyLen,
2060                        pValue, pCur->valueLen, arg );
2061            if ( ret <= 0 )
2062                return ret;
2063            ++pCur;
2064        }
2065    }
2066    return count + pReq->m_pHeader->m_cntUnknownHeaders;
2067
2068}
2069
2070static int EnvForeach( struct LSAPI_key_value_pair * pEnv,
2071            int n, LSAPI_CB_EnvHandler fn, void * arg )
2072{
2073    struct LSAPI_key_value_pair * pEnd = pEnv + n;
2074    int ret;
2075    if ( !pEnv || !fn )
2076        return -1;
2077    while( pEnv < pEnd )
2078    {
2079        ret = (*fn)( pEnv->pKey, pEnv->keyLen,
2080                    pEnv->pValue, pEnv->valLen, arg );
2081        if ( ret <= 0 )
2082            return ret;
2083        ++pEnv;
2084    }
2085    return n;
2086}
2087
2088
2089
2090int LSAPI_ForeachEnv_r( LSAPI_Request * pReq,
2091            LSAPI_CB_EnvHandler fn, void * arg )
2092{
2093    if ( !pReq || !fn )
2094        return -1;
2095    if ( pReq->m_pHeader->m_cntEnv > 0 )
2096    {
2097        return EnvForeach( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
2098                    fn, arg );
2099    }
2100    return 0;
2101}
2102
2103
2104
2105int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq,
2106            LSAPI_CB_EnvHandler fn, void * arg )
2107{
2108    if ( !pReq || !fn )
2109        return -1;
2110    if ( pReq->m_pHeader->m_cntSpecialEnv > 0 )
2111    {
2112        return EnvForeach( pReq->m_pSpecialEnvList,
2113                pReq->m_pHeader->m_cntSpecialEnv,
2114                    fn, arg );
2115    }
2116    return 0;
2117
2118}
2119
2120
2121
2122int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq )
2123{
2124    if ( !pReq || !pReq->m_pIovec )
2125        return -1;
2126    if ( !( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) )
2127        return 0;
2128    pReq->m_reqState &= ~LSAPI_ST_RESP_HEADER;
2129    if ( pReq->m_pRespHeaderBufPos > pReq->m_pRespHeaderBuf )
2130    {
2131        pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespHeaderBuf;
2132        pReq->m_pIovecCur->iov_len  = pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf;
2133        pReq->m_totalLen += pReq->m_pIovecCur->iov_len;
2134        ++pReq->m_pIovecCur;
2135    }
2136
2137    pReq->m_pIovec->iov_len  = sizeof( struct lsapi_resp_header)
2138            + pReq->m_respHeader.m_respInfo.m_cntHeaders * sizeof( short );
2139    pReq->m_totalLen += pReq->m_pIovec->iov_len;
2140
2141    lsapi_buildPacketHeader( &pReq->m_respHeader.m_pktHeader,
2142                    LSAPI_RESP_HEADER, pReq->m_totalLen  );
2143    pReq->m_pIovec->iov_base = (void *)&pReq->m_respHeader;
2144    pReq->m_pIovecToWrite = pReq->m_pIovec;
2145    return 0;
2146}
2147
2148
2149int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName,
2150                              const char * pHeaderValue )
2151{
2152    int nameLen, valLen, len;
2153    if ( !pReq || !pHeaderName || !pHeaderValue )
2154        return -1;
2155    if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
2156        return -1;
2157    if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS )
2158        return -1;
2159    nameLen = strlen( pHeaderName );
2160    valLen = strlen( pHeaderValue );
2161    if ( nameLen == 0 )
2162        return -1;
2163    while( nameLen > 0 )
2164    {
2165        char ch = *(pHeaderName + nameLen - 1 );
2166        if (( ch == '\n' )||( ch == '\r' ))
2167            --nameLen;
2168        else
2169            break;
2170    }
2171    if ( nameLen <= 0 )
2172        return 0;
2173    while( valLen > 0 )
2174    {
2175        char ch = *(pHeaderValue + valLen - 1 );
2176        if (( ch == '\n' )||( ch == '\r' ))
2177            --valLen;
2178        else
2179            break;
2180    }
2181    len = nameLen + valLen + 1;
2182    if ( len > LSAPI_RESP_HTTP_HEADER_MAX )
2183        return -1;
2184
2185    if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
2186    {
2187        int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
2188        newlen -= newlen % 4096;
2189        if ( allocateRespHeaderBuf( pReq, newlen ) == -1 )
2190            return -1;
2191    }
2192    memmove( pReq->m_pRespHeaderBufPos, pHeaderName, nameLen );
2193    pReq->m_pRespHeaderBufPos += nameLen;
2194    *pReq->m_pRespHeaderBufPos++ = ':';
2195    memmove( pReq->m_pRespHeaderBufPos, pHeaderValue, valLen );
2196    pReq->m_pRespHeaderBufPos += valLen;
2197    *pReq->m_pRespHeaderBufPos++ = 0;
2198    ++len;  /* add one byte padding for \0 */
2199    pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
2200    ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
2201    return 0;
2202}
2203
2204
2205
2206int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len )
2207{
2208    if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX )
2209        return -1;
2210    if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
2211        return -1;
2212    if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS )
2213        return -1;
2214    while( len > 0 )
2215    {
2216        char ch = *(pBuf + len - 1 );
2217        if (( ch == '\n' )||( ch == '\r' ))
2218            --len;
2219        else
2220            break;
2221    }
2222    if ( len <= 0 )
2223        return 0;
2224    if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
2225    {
2226        int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
2227        newlen -= newlen % 4096;
2228        if ( allocateRespHeaderBuf( pReq, newlen ) == -1 )
2229            return -1;
2230    }
2231    memmove( pReq->m_pRespHeaderBufPos, pBuf, len );
2232    pReq->m_pRespHeaderBufPos += len;
2233    *pReq->m_pRespHeaderBufPos++ = 0;
2234    ++len;  /* add one byte padding for \0 */
2235    pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
2236    ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
2237    return 0;
2238}
2239
2240
2241int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog )
2242{
2243    int ret;
2244    int fd;
2245    int flag = 1;
2246    int addr_len;
2247
2248    switch( pServerAddr->sa_family )
2249    {
2250    case AF_INET:
2251        addr_len = 16;
2252        break;
2253    case AF_INET6:
2254        addr_len = sizeof( struct sockaddr_in6 );
2255        break;
2256    case AF_UNIX:
2257        addr_len = sizeof( struct sockaddr_un );
2258        unlink( ((struct sockaddr_un *)pServerAddr)->sun_path );
2259        break;
2260    default:
2261        return -1;
2262    }
2263
2264    fd = socket( pServerAddr->sa_family, SOCK_STREAM, 0 );
2265    if ( fd == -1 )
2266        return -1;
2267
2268    fcntl( fd, F_SETFD, FD_CLOEXEC );
2269
2270    if(setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
2271                (char *)( &flag ), sizeof(flag)) == 0)
2272    {
2273        ret = bind( fd, pServerAddr, addr_len );
2274        if ( !ret )
2275        {
2276            ret = listen( fd, backlog );
2277            if ( !ret )
2278                return fd;
2279        }
2280    }
2281
2282    ret = errno;
2283    close(fd);
2284    errno = ret;
2285    return -1;
2286
2287}
2288
2289int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
2290{
2291    char achAddr[256];
2292    char * p = achAddr;
2293    char * pEnd;
2294    struct addrinfo *res, hints;
2295    int  doAddrInfo = 0;
2296    int port;
2297
2298    if ( !pBind )
2299        return -1;
2300
2301    while( isspace( *pBind ) )
2302        ++pBind;
2303
2304    strncpy( achAddr, pBind, 256 );
2305
2306    switch( *p )
2307    {
2308    case '/':
2309        pAddr->sa_family = AF_UNIX;
2310        strncpy( ((struct sockaddr_un *)pAddr)->sun_path, p,
2311                sizeof(((struct sockaddr_un *)pAddr)->sun_path) );
2312        return 0;
2313
2314    case '[':
2315        pAddr->sa_family = AF_INET6;
2316        ++p;
2317        pEnd = strchr( p, ']' );
2318        if ( !pEnd )
2319            return -1;
2320        *pEnd++ = 0;
2321
2322        if ( *p == '*' )
2323        {
2324            strcpy( achAddr, "::" );
2325            p = achAddr;
2326        }
2327        doAddrInfo = 1;
2328        break;
2329
2330    default:
2331        pAddr->sa_family = AF_INET;
2332        pEnd = strchr( p, ':' );
2333        if ( !pEnd )
2334            return -1;
2335        *pEnd++ = 0;
2336
2337        doAddrInfo = 0;
2338        if ( *p == '*' )
2339        {
2340            ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl(INADDR_ANY);
2341        }
2342        else if (!strcasecmp( p, "localhost" ) )
2343            ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl( INADDR_LOOPBACK );
2344        else
2345        {
2346            ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = inet_addr( p );
2347            if ( ((struct sockaddr_in *)pAddr)->sin_addr.s_addr == INADDR_BROADCAST)
2348            {
2349                doAddrInfo = 1;
2350            }
2351        }
2352        break;
2353    }
2354    if ( *pEnd == ':' )
2355        ++pEnd;
2356
2357    port = atoi( pEnd );
2358    if (( port <= 0 )||( port > 65535 ))
2359        return -1;
2360    if ( doAddrInfo )
2361    {
2362
2363        memset(&hints, 0, sizeof(hints));
2364
2365        hints.ai_family   = pAddr->sa_family;
2366        hints.ai_socktype = SOCK_STREAM;
2367        hints.ai_protocol = IPPROTO_TCP;
2368
2369        if ( getaddrinfo(p, NULL, &hints, &res) )
2370        {
2371            return -1;
2372        }
2373
2374        memcpy(pAddr, res->ai_addr, res->ai_addrlen);
2375        freeaddrinfo(res);
2376    }
2377
2378    if ( pAddr->sa_family == AF_INET )
2379        ((struct sockaddr_in *)pAddr)->sin_port = htons( port );
2380    else
2381        ((struct sockaddr_in6 *)pAddr)->sin6_port = htons( port );
2382    return 0;
2383
2384}
2385
2386int LSAPI_CreateListenSock( const char * pBind, int backlog )
2387{
2388    char serverAddr[128];
2389    int ret;
2390    int fd = -1;
2391    ret = LSAPI_ParseSockAddr( pBind, (struct sockaddr *)serverAddr );
2392    if ( !ret )
2393    {
2394        fd = LSAPI_CreateListenSock2( (struct sockaddr *)serverAddr, backlog );
2395    }
2396    return fd;
2397}
2398
2399static fn_select_t g_fnSelect = select;
2400
2401typedef struct _lsapi_child_status
2402{
2403    int     m_pid;
2404    long    m_tmStart;
2405
2406    volatile short   m_iKillSent;
2407    volatile short   m_inProcess;
2408    volatile int     m_iReqCounter;
2409
2410    volatile long    m_tmWaitBegin;
2411    volatile long    m_tmReqBegin;
2412    volatile long    m_tmLastCheckPoint;
2413}
2414lsapi_child_status;
2415
2416static lsapi_child_status * s_pChildStatus = NULL;
2417
2418typedef struct _lsapi_prefork_server
2419{
2420    int m_fd;
2421    int m_iMaxChildren;
2422    int m_iExtraChildren;
2423    int m_iCurChildren;
2424    int m_iMaxIdleChildren;
2425    int m_iServerMaxIdle;
2426    int m_iChildrenMaxIdleTime;
2427    int m_iMaxReqProcessTime;
2428    int m_iAvoidFork;
2429
2430    lsapi_child_status * m_pChildrenStatus;
2431    lsapi_child_status * m_pChildrenStatusCur;
2432    lsapi_child_status * m_pChildrenStatusEnd;
2433
2434}lsapi_prefork_server;
2435
2436static lsapi_prefork_server * g_prefork_server = NULL;
2437
2438int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
2439{
2440    int pid;
2441    if ( g_prefork_server )
2442        return 0;
2443    if ( max_children <= 1 )
2444        return -1;
2445    if ( max_children >= 10000)
2446        max_children = 10000;
2447
2448
2449    g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) );
2450    if ( !g_prefork_server )
2451        return -1;
2452    memset( g_prefork_server, 0, sizeof( lsapi_prefork_server ) );
2453
2454    if ( fp != NULL )
2455        g_fnSelect = fp;
2456
2457    s_ppid = getppid();
2458    pid = getpid();
2459    setpgid( pid, pid );
2460    g_prefork_server->m_iAvoidFork = avoidFork;
2461    g_prefork_server->m_iMaxChildren = max_children;
2462
2463    g_prefork_server->m_iExtraChildren = ( avoidFork ) ? 0 : (max_children / 3) ;
2464    g_prefork_server->m_iMaxIdleChildren = ( avoidFork ) ? (max_children + 1) : (max_children / 3);
2465    if ( g_prefork_server->m_iMaxIdleChildren == 0 )
2466        g_prefork_server->m_iMaxIdleChildren = 1;
2467    g_prefork_server->m_iChildrenMaxIdleTime = 300;
2468    g_prefork_server->m_iMaxReqProcessTime = 3600;
2469    return 0;
2470}
2471
2472void LSAPI_Set_Server_fd( int fd )
2473{
2474    if( g_prefork_server )
2475        g_prefork_server->m_fd = fd;
2476}
2477
2478
2479static int lsapi_accept( int fdListen )
2480{
2481    int         fd;
2482    int         nodelay = 1;
2483    socklen_t   len;
2484    char        achPeer[128];
2485
2486    len = sizeof( achPeer );
2487    fd = accept( fdListen, (struct sockaddr *)&achPeer, &len );
2488    if ( fd != -1 )
2489    {
2490        if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
2491        {
2492            setsockopt( fd, IPPROTO_TCP, TCP_NODELAY,
2493                    (char *)&nodelay, sizeof(nodelay));
2494        }
2495
2496        //OPTIMIZATION
2497        //if ( s_accept_notify )
2498        //    notify_req_received( fd );
2499    }
2500    return fd;
2501
2502}
2503
2504
2505
2506
2507static int s_req_processed = 0;
2508static int s_max_reqs = 10000;
2509static int s_max_idle_secs = 300;
2510
2511static int s_stop;
2512
2513static void lsapi_cleanup(int signal)
2514{
2515    s_stop = signal;
2516}
2517
2518static lsapi_child_status * find_child_status( int pid )
2519{
2520    lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
2521    lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd;
2522    while( pStatus < pEnd )
2523    {
2524        if ( pStatus->m_pid == pid )
2525        {
2526            if ( pStatus + 1 > g_prefork_server->m_pChildrenStatusCur )
2527                g_prefork_server->m_pChildrenStatusCur = pStatus + 1;
2528            return pStatus;
2529        }
2530        ++pStatus;
2531    }
2532    return NULL;
2533}
2534
2535
2536
2537static void lsapi_sigchild( int signal )
2538{
2539    int status, pid;
2540    lsapi_child_status * child_status;
2541    while( 1 )
2542    {
2543        pid = waitpid( -1, &status, WNOHANG|WUNTRACED );
2544        if ( pid <= 0 )
2545        {
2546            break;
2547        }
2548        if ( WIFSIGNALED( status ))
2549        {
2550            int sig_num = WTERMSIG( status );
2551            int dump = WCOREDUMP( status );
2552            fprintf( stderr, "Child process with pid: %d was killed by signal: %d, core dump: %d\n", pid, sig_num, dump );
2553        }
2554        if ( pid == s_pid_dump_debug_info )
2555        {
2556            pid = 0;
2557            continue;
2558        }
2559        child_status = find_child_status( pid );
2560        if ( child_status )
2561        {
2562            child_status->m_pid = 0;
2563            --g_prefork_server->m_iCurChildren;
2564
2565        }
2566    }
2567    while(( g_prefork_server->m_pChildrenStatusCur > g_prefork_server->m_pChildrenStatus )
2568            &&( g_prefork_server->m_pChildrenStatusCur[-1].m_pid == 0 ))
2569        --g_prefork_server->m_pChildrenStatusCur;
2570
2571}
2572
2573static int lsapi_init_children_status()
2574{
2575    int size = 4096;
2576
2577    char * pBuf;
2578    size = (g_prefork_server->m_iMaxChildren + g_prefork_server->m_iExtraChildren ) * sizeof( lsapi_child_status ) * 2;
2579    size = (size + 4095 ) / 4096 * 4096;
2580    pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE,
2581        MAP_ANON | MAP_SHARED, -1, 0 );
2582    if ( pBuf == MAP_FAILED )
2583    {
2584        perror( "Anonymous mmap() failed" );
2585        return -1;
2586    }
2587    memset( pBuf, 0, size );
2588    g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf;
2589    g_prefork_server->m_pChildrenStatusCur = (lsapi_child_status *)pBuf;
2590    g_prefork_server->m_pChildrenStatusEnd = (lsapi_child_status *)pBuf + size / sizeof( lsapi_child_status );
2591    return 0;
2592}
2593
2594static void dump_debug_info( lsapi_child_status * pStatus, long tmCur )
2595{
2596    char achCmd[1024];
2597    if ( s_pid_dump_debug_info )
2598    {
2599        if ( kill( s_pid_dump_debug_info, 0 ) == 0 )
2600            return;
2601    }
2602    s_pid_dump_debug_info = fork();
2603
2604    fprintf( stderr, "[%s] Possible runaway process, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld\n",
2605                ctime(&tmCur), getpid(), pStatus->m_pid, pStatus->m_iReqCounter,
2606                tmCur - pStatus->m_tmReqBegin, tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart );
2607    snprintf( achCmd, 1024, "gdb --batch -ex \"attach %d\" -ex \"set height 0\" -ex \"bt\" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2", pStatus->m_pid, pStatus->m_pid );
2608    if ( system( achCmd ) == -1 )
2609        perror( "system()" );
2610    exit( 0 );
2611}
2612
2613static void lsapi_check_child_status( long tmCur )
2614{
2615    int idle = 0;
2616    int tobekilled;
2617    int dying = 0;
2618    int count = 0;
2619    lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
2620    lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusCur;
2621    while( pStatus < pEnd )
2622    {
2623        tobekilled = 0;
2624        if ( pStatus->m_pid != 0 )
2625        {
2626            ++count;
2627            if ( !pStatus->m_inProcess )
2628            {
2629
2630                if (( g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren)||
2631                    ( idle > g_prefork_server->m_iMaxIdleChildren ))
2632                {
2633                    ++pStatus->m_iKillSent;
2634                    //tobekilled = SIGUSR1;
2635                }
2636                else
2637                {
2638                    if (( s_max_idle_secs> 0)&&(tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5 ))
2639                    {
2640                        ++pStatus->m_iKillSent;
2641                        //tobekilled = SIGUSR1;
2642                    }
2643                }
2644                if ( !tobekilled )
2645                    ++idle;
2646            }
2647            else
2648            {
2649                if ( tmCur - pStatus->m_tmReqBegin >
2650                        g_prefork_server->m_iMaxReqProcessTime )
2651                {
2652                    if (( ( pStatus->m_iKillSent % 5 ) == 0 )&&( s_dump_debug_info ))
2653                        dump_debug_info( pStatus, tmCur );
2654                    if ( pStatus->m_iKillSent > 5 )
2655                    {
2656                        tobekilled = SIGKILL;
2657                        fprintf( stderr, "Force killing runaway process PID: %d with SIGKILL\n", pStatus->m_pid );
2658                    }
2659                    else
2660                    {
2661                        tobekilled = SIGTERM;
2662                        fprintf( stderr, "Killing runaway process PID: %d with SIGTERM\n", pStatus->m_pid );
2663                    }
2664                }
2665            }
2666            if ( tobekilled )
2667            {
2668                if (( kill( pStatus->m_pid, tobekilled ) == -1 )&&( errno == ESRCH ))
2669                {
2670                    pStatus->m_pid = 0;
2671                    --count;
2672                }
2673                else
2674                {
2675                    ++pStatus->m_iKillSent;
2676                    ++dying;
2677                }
2678            }
2679        }
2680        ++pStatus;
2681    }
2682    if ( abs( g_prefork_server->m_iCurChildren - count ) > 1 )
2683    {
2684        fprintf( stderr, "Children tracking is wrong: PID: %d, Cur Children: %d, count: %d, idle: %d, dying: %d\n", getpid(),
2685                g_prefork_server->m_iCurChildren, count, idle, dying );
2686
2687    }
2688}
2689
2690static int lsapi_all_children_must_die()
2691{
2692    int maxWait;
2693    int sec =0;
2694    g_prefork_server->m_iMaxReqProcessTime = 10;
2695    g_prefork_server->m_iMaxIdleChildren = -1;
2696    maxWait = 15;
2697
2698    while( g_prefork_server->m_iCurChildren && (sec < maxWait) )
2699    {
2700        lsapi_check_child_status(time(NULL));
2701        sleep( 1 );
2702        sec++;
2703    }
2704    if ( g_prefork_server->m_iCurChildren != 0 )
2705        kill( -getpgrp(), SIGKILL );
2706    return 0;
2707}
2708
2709
2710
2711static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Request * pReq )
2712{
2713    struct sigaction act, old_term, old_quit, old_int,
2714                    old_usr1, old_child;
2715    lsapi_child_status * child_status;
2716    int             wait_secs = 0;
2717    int             ret = 0;
2718    int             pid;
2719    time_t          lastTime = 0;
2720    time_t          curTime = 0;
2721    fd_set          readfds;
2722    struct timeval  timeout;
2723
2724    sigset_t mask;
2725    sigset_t orig_mask;
2726
2727    lsapi_init_children_status();
2728
2729    setsid();
2730
2731    act.sa_flags = 0;
2732    act.sa_handler = lsapi_sigchild;
2733    if( sigaction( SIGCHLD, &act, &old_child ) )
2734    {
2735        perror( "Can't set signal handler for SIGCHILD" );
2736        return -1;
2737    }
2738
2739    /* Set up handler to kill children upon exit */
2740    act.sa_flags = 0;
2741    act.sa_handler = lsapi_cleanup;
2742    if( sigaction( SIGTERM, &act, &old_term ) ||
2743        sigaction( SIGINT,  &act, &old_int  ) ||
2744        sigaction( SIGUSR1, &act, &old_usr1 ) ||
2745        sigaction( SIGQUIT, &act, &old_quit ))
2746    {
2747        perror( "Can't set signals" );
2748        return -1;
2749    }
2750    s_stop = 0;
2751    while( !s_stop )
2752    {
2753        curTime = time( NULL );
2754        if (curTime != lastTime )
2755        {
2756            lastTime = curTime;
2757            if (s_ppid && (getppid() != s_ppid ))
2758                break;
2759            lsapi_check_child_status(curTime );
2760            if (pServer->m_iServerMaxIdle)
2761            {
2762                if ( pServer->m_iCurChildren <= 0 )
2763                {
2764                    ++wait_secs;
2765                    if ( wait_secs > pServer->m_iServerMaxIdle )
2766                        return -1;
2767                }
2768                else
2769                    wait_secs = 0;
2770            }
2771        }
2772
2773        if ( pServer->m_iCurChildren >= (pServer->m_iMaxChildren + pServer->m_iExtraChildren ) )
2774        {
2775            fprintf( stderr, "Reached max children process limit: %d, extra: %d, current: %d, please increase LSAPI_CHILDREN.\n",
2776                                pServer->m_iMaxChildren, pServer->m_iExtraChildren, pServer->m_iCurChildren );
2777            usleep( 100000 );
2778            continue;
2779        }
2780
2781        FD_ZERO( &readfds );
2782        FD_SET( pServer->m_fd, &readfds );
2783        timeout.tv_sec = 1; timeout.tv_usec = 0;
2784        if ((ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout)) == 1 )
2785        {
2786            /*
2787            if ( pServer->m_iCurChildren >= 0 )
2788            {
2789                usleep( 10 );
2790                FD_ZERO( &readfds );
2791                FD_SET( pServer->m_fd, &readfds );
2792                timeout.tv_sec = 0; timeout.tv_usec = 0;
2793                if ( (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout) == 0 )
2794                    continue;
2795            }*/
2796        }
2797        else if ( ret == -1 )
2798        {
2799            if ( errno == EINTR )
2800                continue;
2801            /* perror( "select()" ); */
2802            break;
2803        }
2804        else
2805        {
2806            continue;
2807        }
2808
2809        pReq->m_fd = lsapi_accept( pServer->m_fd );
2810        if ( pReq->m_fd != -1 )
2811        {
2812            child_status = find_child_status( 0 );
2813            if ( child_status )
2814                memset( child_status, 0, sizeof( *child_status ) );
2815
2816            sigemptyset( &mask );
2817            sigaddset( &mask, SIGCHLD );
2818
2819            if ( sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0 )
2820            {
2821                perror( "sigprocmask(SIG_BLOCK) to block SIGCHLD" );
2822            }
2823
2824            pid = fork();
2825
2826            if ( !pid )
2827            {
2828                if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
2829                    perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK in child" );
2830                g_prefork_server = NULL;
2831                s_ppid = getppid();
2832                s_req_processed = 0;
2833                s_pChildStatus = child_status;
2834                lsapi_set_nblock( pReq->m_fd, 0 );
2835                if ( pReq->m_fdListen != -1 )
2836                {
2837                    close( pReq->m_fdListen );
2838                    pReq->m_fdListen = -1;
2839                }
2840                /* don't catch our signals */
2841                sigaction( SIGCHLD, &old_child, 0 );
2842                sigaction( SIGTERM, &old_term, 0 );
2843                sigaction( SIGQUIT, &old_quit, 0 );
2844                sigaction( SIGINT,  &old_int,  0 );
2845                sigaction( SIGUSR1, &old_usr1, 0 );
2846                //init_conn_key( pReq->m_fd );
2847                lsapi_notify_pid( pReq->m_fd );
2848                s_notified_pid = 1;
2849                //if ( s_accept_notify )
2850                //    return notify_req_received( pReq->m_fd );
2851                return 0;
2852            }
2853            else if ( pid == -1 )
2854            {
2855                perror( "fork() failed, please increase process limit" );
2856            }
2857            else
2858            {
2859                ++pServer->m_iCurChildren;
2860                if ( child_status )
2861                {
2862                    child_status->m_pid = pid;
2863                    child_status->m_tmWaitBegin = curTime;
2864                    child_status->m_tmStart = curTime;
2865                }
2866            }
2867            close( pReq->m_fd );
2868            pReq->m_fd = -1;
2869
2870            if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
2871                perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK" );
2872
2873        }
2874        else
2875        {
2876            if (( errno == EINTR )||( errno == EAGAIN))
2877                continue;
2878            perror( "accept() failed" );
2879            return -1;
2880        }
2881    }
2882    sigaction( SIGUSR1, &old_usr1, 0 );
2883    //kill( -getpgrp(), SIGUSR1 );
2884    //lsapi_all_children_must_die();  /* Sorry, children ;-) */
2885    return -1;
2886
2887}
2888
2889void lsapi_error( const char * pMessage, int err_no )
2890{
2891    fprintf( stderr, "%d: %s, errno: %d (%s)\n", getpid(), pMessage, err_no, strerror( err_no ) );
2892}
2893
2894int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
2895{
2896    int             fd;
2897    int             ret;
2898    int             wait_secs;
2899    fd_set          readfds;
2900    struct timeval  timeout;
2901
2902    LSAPI_Finish_r( pReq );
2903
2904
2905    if ( g_prefork_server )
2906    {
2907        if ( g_prefork_server->m_fd != -1 )
2908            if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 )
2909                return -1;
2910    }
2911    if ( s_req_processed >= s_max_reqs )
2912        return -1;
2913
2914    if ( s_pChildStatus )
2915    {
2916        s_pChildStatus->m_tmWaitBegin = time( NULL );
2917    }
2918
2919
2920    while( g_running )
2921    {
2922        if ( pReq->m_fd != -1 )
2923        {
2924            fd = pReq->m_fd;
2925        }
2926        else if ( pReq->m_fdListen != -1 )
2927            fd = pReq->m_fdListen;
2928        else
2929        {
2930            break;
2931        }
2932        wait_secs = 0;
2933        while( 1 )
2934        {
2935            if ( !g_running )
2936                return -1;
2937            if ((s_req_processed)&&( s_pChildStatus )&&( s_pChildStatus->m_iKillSent ))
2938                return -1;
2939            FD_ZERO( &readfds );
2940            FD_SET( fd, &readfds );
2941            timeout.tv_sec = 1;
2942            timeout.tv_usec = 0;
2943            ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout);
2944            if ( ret == 0 )
2945            {
2946                if ( s_pChildStatus )
2947                {
2948                    s_pChildStatus->m_inProcess = 0;
2949                }
2950                ++wait_secs;
2951                if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs ))
2952                    return -1;
2953                if ( s_ppid &&( getppid() != s_ppid))
2954                    return -1;
2955            }
2956            else if ( ret == -1 )
2957            {
2958                if ( errno == EINTR )
2959                    continue;
2960                else
2961                    return -1;
2962            }
2963            else if ( ret >= 1 )
2964            {
2965                if (s_req_processed && ( s_pChildStatus )&&( s_pChildStatus->m_iKillSent ))
2966                    return -1;
2967                if ( fd == pReq->m_fdListen )
2968                {
2969                    pReq->m_fd = lsapi_accept( pReq->m_fdListen );
2970                    if ( pReq->m_fd != -1 )
2971                    {
2972                        fd = pReq->m_fd;
2973                        lsapi_set_nblock( fd, 0 );
2974                        //init_conn_key( pReq->m_fd );
2975                        if ( !s_keepListener )
2976                        {
2977                            close( pReq->m_fdListen );
2978                            pReq->m_fdListen = -1;
2979                        }
2980                        if ( s_accept_notify )
2981                            if ( notify_req_received( pReq->m_fd ) == -1 )
2982                                return -1;
2983                    }
2984                    else
2985                    {
2986                        if (( errno == EINTR )||( errno == EAGAIN))
2987                            continue;
2988                        lsapi_error( "lsapi_accept() error", errno );
2989                        return -1;
2990                    }
2991                }
2992                else
2993                    break;
2994            }
2995        }
2996
2997        if ( !readReq( pReq ) )
2998        {
2999            if ( s_pChildStatus )
3000            {
3001                s_pChildStatus->m_iKillSent = 0;
3002                s_pChildStatus->m_inProcess = 1;
3003                ++s_pChildStatus->m_iReqCounter;
3004                s_pChildStatus->m_tmReqBegin = s_pChildStatus->m_tmLastCheckPoint = time(NULL);
3005            }
3006            ++s_req_processed;
3007            return 0;
3008        }
3009        lsapi_close( pReq->m_fd );
3010        pReq->m_fd = -1;
3011        LSAPI_Reset_r( pReq );
3012    }
3013    return -1;
3014
3015}
3016
3017void LSAPI_Set_Max_Reqs( int reqs )
3018{   s_max_reqs = reqs;          }
3019
3020void LSAPI_Set_Max_Idle( int secs )
3021{   s_max_idle_secs = secs;     }
3022
3023void LSAPI_Set_Max_Children( int maxChildren )
3024{
3025    if ( g_prefork_server )
3026        g_prefork_server->m_iMaxChildren = maxChildren;
3027}
3028
3029void LSAPI_Set_Extra_Children( int extraChildren )
3030{
3031    if (( g_prefork_server )&&( extraChildren >= 0 ))
3032        g_prefork_server->m_iExtraChildren = extraChildren;
3033}
3034
3035void LSAPI_Set_Max_Process_Time( int secs )
3036{
3037    if (( g_prefork_server )&&( secs > 0 ))
3038        g_prefork_server->m_iMaxReqProcessTime = secs;
3039}
3040
3041
3042void LSAPI_Set_Max_Idle_Children( int maxIdleChld )
3043{
3044    if (( g_prefork_server )&&( maxIdleChld > 0 ))
3045        g_prefork_server->m_iMaxIdleChildren = maxIdleChld;
3046}
3047
3048void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle )
3049{
3050    if ( g_prefork_server )
3051        g_prefork_server->m_iServerMaxIdle = serverMaxIdle;
3052}
3053
3054void LSAPI_Set_Slow_Req_Msecs( int msecs )
3055{
3056    s_slow_req_msecs = msecs;
3057}
3058
3059int  LSAPI_Get_Slow_Req_Msecs()
3060{
3061    return s_slow_req_msecs;
3062}
3063
3064
3065void LSAPI_No_Check_ppid()
3066{
3067    s_ppid = 0;
3068}
3069
3070#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
3071#include <crt_externs.h>
3072#else
3073extern char ** environ;
3074#endif
3075static void unset_lsapi_envs()
3076{
3077    char **env;
3078#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
3079    env = *_NSGetEnviron();
3080#else
3081    env = environ;
3082#endif
3083    while( env != NULL && *env != NULL )
3084    {
3085        if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 )
3086            || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid)))
3087        {
3088            char ** del = env;
3089            do
3090                *del = del[1];
3091            while( *del++ );
3092        }
3093        else
3094            ++env;
3095    }
3096}
3097
3098static int lsapi_initSuEXEC()
3099{
3100    int i;
3101    struct passwd * pw;
3102    s_defaultUid = 0;
3103    s_defaultGid = 0;
3104    if ( s_uid == 0 )
3105    {
3106        const char * p = getenv( "LSAPI_DEFAULT_UID" );
3107        if ( p )
3108        {
3109            i = atoi( p );
3110            if ( i > 0 )
3111                s_defaultUid = i;
3112        }
3113        p = getenv( "LSAPI_DEFAULT_GID" );
3114        if ( p )
3115        {
3116            i = atoi( p );
3117            if ( i > 0 )
3118                s_defaultGid = i;
3119        }
3120        p = getenv( "LSAPI_SECRET" );
3121        if (( !p )||( readSecret(p) == -1 ))
3122                return -1;
3123        if ( g_prefork_server )
3124        {
3125            if ( g_prefork_server->m_iMaxChildren < 100 )
3126                g_prefork_server->m_iMaxChildren = 100;
3127            if ( g_prefork_server->m_iExtraChildren < 1000 )
3128                g_prefork_server->m_iExtraChildren = 1000;
3129        }
3130    }
3131    if ( !s_defaultUid || !s_defaultGid )
3132    {
3133        pw = getpwnam( "nobody" );
3134        if ( !s_defaultUid )
3135            s_defaultUid = pw->pw_uid;
3136        if ( !s_defaultGid )
3137            s_defaultGid = pw->pw_gid;
3138    }
3139    return 0;
3140}
3141
3142
3143int LSAPI_Init_Env_Parameters( fn_select_t fp )
3144{
3145    const char *p;
3146    int n;
3147    int avoidFork = 0;
3148    p = getenv( "PHP_LSAPI_MAX_REQUESTS" );
3149    if ( !p )
3150        p = getenv( "LSAPI_MAX_REQS" );
3151    if ( p )
3152    {
3153        n = atoi( p );
3154        if ( n > 0 )
3155            LSAPI_Set_Max_Reqs( n );
3156    }
3157
3158    p = getenv( "LSAPI_AVOID_FORK" );
3159    if ( p )
3160    {
3161        avoidFork = atoi( p );
3162    }
3163
3164    p = getenv( "LSAPI_ACCEPT_NOTIFY" );
3165    if ( p )
3166    {
3167        s_accept_notify = atoi( p );
3168    }
3169
3170    p = getenv( "LSAPI_SLOW_REQ_MSECS" );
3171    if ( p )
3172    {
3173        n = atoi( p );
3174        LSAPI_Set_Slow_Req_Msecs( n );
3175    }
3176
3177#if defined( RLIMIT_CORE )
3178    p = getenv( "LSAPI_ALLOW_CORE_DUMP" );
3179    if ( !p )
3180    {
3181        struct rlimit limit = { 0, 0 };
3182        setrlimit( RLIMIT_CORE, &limit );
3183    }
3184    else
3185        s_enable_core_dump = 1;
3186
3187#endif
3188
3189    p = getenv( "LSAPI_MAX_IDLE" );
3190    if ( p )
3191    {
3192        n = atoi( p );
3193        LSAPI_Set_Max_Idle( n );
3194    }
3195
3196    p = getenv( "LSAPI_KEEP_LISTEN" );
3197    if ( p )
3198    {
3199        n = atoi( p );
3200        s_keepListener = n;
3201    }
3202
3203
3204    if ( LSAPI_Is_Listen() )
3205    {
3206        n = 0;
3207        p = getenv( "PHP_LSAPI_CHILDREN" );
3208        if ( !p )
3209            p = getenv( "LSAPI_CHILDREN" );
3210        if ( p )
3211            n = atoi( p );
3212        if ( n > 1 )
3213        {
3214            LSAPI_Init_Prefork_Server( n, fp, avoidFork );
3215            LSAPI_Set_Server_fd( g_req.m_fdListen );
3216        }
3217
3218        p = getenv( "LSAPI_EXTRA_CHILDREN" );
3219        if ( p )
3220            LSAPI_Set_Extra_Children( atoi( p ) );
3221
3222        p = getenv( "LSAPI_MAX_IDLE_CHILDREN" );
3223        if ( p )
3224            LSAPI_Set_Max_Idle_Children( atoi( p ) );
3225
3226        p = getenv( "LSAPI_PGRP_MAX_IDLE" );
3227        if ( p )
3228        {
3229            LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) );
3230        }
3231
3232        p = getenv( "LSAPI_MAX_PROCESS_TIME" );
3233        if ( p )
3234            LSAPI_Set_Max_Process_Time( atoi( p ) );
3235
3236        if ( getenv( "LSAPI_PPID_NO_CHECK" ) )
3237        {
3238            LSAPI_No_Check_ppid();
3239        }
3240
3241        p = getenv( "LSAPI_DUMP_DEBUG_INFO" );
3242        if ( p )
3243            s_dump_debug_info = atoi( p );
3244
3245        if ( lsapi_initSuEXEC() == -1 )
3246            return -1;
3247#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3248        lsapi_initLVE();
3249#endif
3250    }
3251    unset_lsapi_envs();
3252    return 0;
3253}
3254
3255
3256int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders,
3257                         const char * pBody, int bodyLen )
3258{
3259    LSAPI_SetRespStatus_r( pReq, code );
3260    if ( pRespHeaders )
3261    {
3262        while( *pRespHeaders )
3263        {
3264            LSAPI_AppendRespHeader_r( pReq, *pRespHeaders, strlen( *pRespHeaders ) );
3265            ++pRespHeaders;
3266        }
3267    }
3268    if ( pBody &&( bodyLen > 0 ))
3269    {
3270        LSAPI_Write_r( pReq, pBody, bodyLen );
3271    }
3272    LSAPI_Finish_r( pReq );
3273    return 0;
3274}
3275
3276
3277static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]);
3278
3279/*
3280 * Note: this code is harmless on little-endian machines.
3281 */
3282static void byteReverse(unsigned char *buf, unsigned longs)
3283{
3284    uint32 t;
3285    do {
3286        t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
3287            ((unsigned) buf[1] << 8 | buf[0]);
3288        *(uint32 *) buf = t;
3289        buf += 4;
3290    } while (--longs);
3291}
3292
3293/*
3294 * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
3295 * initialization constants.
3296 */
3297void lsapi_MD5Init(struct lsapi_MD5Context *ctx)
3298{
3299    ctx->buf[0] = 0x67452301;
3300    ctx->buf[1] = 0xefcdab89;
3301    ctx->buf[2] = 0x98badcfe;
3302    ctx->buf[3] = 0x10325476;
3303
3304    ctx->bits[0] = 0;
3305    ctx->bits[1] = 0;
3306}
3307
3308/*
3309 * Update context to reflect the concatenation of another buffer full
3310 * of bytes.
3311 */
3312void lsapi_MD5Update(struct lsapi_MD5Context *ctx, unsigned char const *buf, unsigned len)
3313{
3314    register uint32 t;
3315
3316    /* Update bitcount */
3317
3318    t = ctx->bits[0];
3319    if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
3320        ctx->bits[1]++;                /* Carry from low to high */
3321    ctx->bits[1] += len >> 29;
3322
3323    t = (t >> 3) & 0x3f;        /* Bytes already in shsInfo->data */
3324
3325    /* Handle any leading odd-sized chunks */
3326
3327    if (t) {
3328        unsigned char *p = (unsigned char *) ctx->in + t;
3329
3330        t = 64 - t;
3331        if (len < t) {
3332            memmove(p, buf, len);
3333            return;
3334        }
3335        memmove(p, buf, t);
3336        byteReverse(ctx->in, 16);
3337        lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3338        buf += t;
3339        len -= t;
3340    }
3341    /* Process data in 64-byte chunks */
3342
3343    while (len >= 64) {
3344        memmove(ctx->in, buf, 64);
3345        byteReverse(ctx->in, 16);
3346        lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3347        buf += 64;
3348        len -= 64;
3349    }
3350
3351    /* Handle any remaining bytes of data. */
3352
3353    memmove(ctx->in, buf, len);
3354}
3355
3356/*
3357 * Final wrapup - pad to 64-byte boundary with the bit pattern
3358 * 1 0* (64-bit count of bits processed, MSB-first)
3359 */
3360void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *ctx)
3361{
3362    unsigned int count;
3363    unsigned char *p;
3364
3365    /* Compute number of bytes mod 64 */
3366    count = (ctx->bits[0] >> 3) & 0x3F;
3367
3368    /* Set the first char of padding to 0x80.  This is safe since there is
3369       always at least one byte free */
3370    p = ctx->in + count;
3371    *p++ = 0x80;
3372
3373    /* Bytes of padding needed to make 64 bytes */
3374    count = 64 - 1 - count;
3375
3376    /* Pad out to 56 mod 64 */
3377    if (count < 8) {
3378        /* Two lots of padding:  Pad the first block to 64 bytes */
3379        memset(p, 0, count);
3380        byteReverse(ctx->in, 16);
3381        lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3382
3383        /* Now fill the next block with 56 bytes */
3384        memset(ctx->in, 0, 56);
3385    } else {
3386        /* Pad block to 56 bytes */
3387        memset(p, 0, count - 8);
3388    }
3389    byteReverse(ctx->in, 14);
3390
3391    /* Append length in bits and transform */
3392    ((uint32 *) ctx->in)[14] = ctx->bits[0];
3393    ((uint32 *) ctx->in)[15] = ctx->bits[1];
3394
3395    lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3396    byteReverse((unsigned char *) ctx->buf, 4);
3397    memmove(digest, ctx->buf, 16);
3398    memset(ctx, 0, sizeof(*ctx));        /* In case it's sensitive */
3399}
3400
3401/* The four core functions - F1 is optimized somewhat */
3402
3403/* #define F1(x, y, z) (x & y | ~x & z) */
3404#define F1(x, y, z) (z ^ (x & (y ^ z)))
3405#define F2(x, y, z) F1(z, x, y)
3406#define F3(x, y, z) (x ^ y ^ z)
3407#define F4(x, y, z) (y ^ (x | ~z))
3408
3409/* This is the central step in the MD5 algorithm. */
3410#define MD5STEP(f, w, x, y, z, data, s) \
3411        ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
3412
3413/*
3414 * The core of the MD5 algorithm, this alters an existing MD5 hash to
3415 * reflect the addition of 16 longwords of new data.  MD5Update blocks
3416 * the data and converts bytes into longwords for this routine.
3417 */
3418static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16])
3419{
3420    register uint32 a, b, c, d;
3421
3422    a = buf[0];
3423    b = buf[1];
3424    c = buf[2];
3425    d = buf[3];
3426
3427    MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
3428    MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
3429    MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
3430    MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
3431    MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
3432    MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
3433    MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
3434    MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
3435    MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
3436    MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
3437    MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
3438    MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
3439    MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
3440    MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
3441    MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
3442    MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
3443
3444    MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
3445    MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
3446    MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
3447    MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
3448    MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
3449    MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
3450    MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
3451    MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
3452    MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
3453    MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
3454    MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
3455    MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
3456    MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
3457    MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
3458    MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
3459    MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
3460
3461    MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
3462    MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
3463    MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
3464    MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
3465    MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
3466    MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
3467    MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
3468    MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
3469    MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
3470    MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
3471    MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
3472    MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
3473    MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
3474    MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
3475    MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
3476    MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
3477
3478    MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
3479    MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
3480    MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
3481    MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
3482    MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
3483    MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
3484    MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
3485    MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
3486    MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
3487    MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
3488    MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
3489    MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
3490    MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
3491    MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
3492    MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
3493    MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
3494
3495    buf[0] += a;
3496    buf[1] += b;
3497    buf[2] += c;
3498    buf[3] += d;
3499}
3500
3501