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