xref: /PHP-7.0/sapi/litespeed/lsapilib.c (revision 478f119a)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2017 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 /*
20 Copyright (c) 2002-2015, Lite Speed Technologies Inc.
21 All rights reserved.
22 
23 Redistribution and use in source and binary forms, with or without
24 modification, are permitted provided that the following conditions are
25 met:
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 
38 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
39 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
40 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
41 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
42 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
44 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
45 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
46 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
47 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
48 OF 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 
94 struct lsapi_MD5Context {
95     uint32 buf[4];
96     uint32 bits[2];
97     unsigned char in[64];
98 };
99 
100 void lsapi_MD5Init(struct lsapi_MD5Context *context);
101 void lsapi_MD5Update(struct lsapi_MD5Context *context, unsigned char const *buf,
102            unsigned len);
103 void 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  */
108 typedef 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 
121 static int g_inited = 0;
122 static int g_running = 1;
123 static int s_ppid;
124 static int s_slow_req_msecs = 0;
125 static int s_keepListener = 0;
126 static int s_dump_debug_info = 0;
127 static int s_pid_dump_debug_info = 0;
128 
129 LSAPI_Request g_req = { -1, -1 };
130 
131 static char         s_secret[24];
132 
133 
134 void Flush_RespBuf_r( LSAPI_Request * pReq );
135 
136 static 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 
157 static 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 
162 static 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 
183 static 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 
lsapi_sigpipe(int sig)188 static void lsapi_sigpipe( int sig )
189 {
190 }
lsapi_siguser1(int sig)191 static void lsapi_siguser1( int sig )
192 {
193     g_running = 0;
194 }
195 
196 #ifndef sighandler_t
197 typedef void (*sighandler_t)(int);
198 #endif
199 
lsapi_signal(int signo,sighandler_t handler)200 static 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 
216 static int s_enable_core_dump = 0;
lsapi_enable_core_dump()217 static 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 
lsapi_buildPacketHeader(struct lsapi_packet_header * pHeader,char type,int len)244 static 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 
lsapi_set_nblock(int fd,int nonblock)254 static  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 
lsapi_close(int fd)274 static 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 
lsapi_read(int fd,void * pBuf,size_t len)286 static 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 /*
299 static 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 
lsapi_writev(int fd,struct iovec ** pVec,int count,int totalLen)320 static 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 /*
365 static 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 
allocateBuf(LSAPI_Request * pReq,int size)378 static 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 
allocateIovec(LSAPI_Request * pReq,int n)392 static 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 
allocateRespHeaderBuf(LSAPI_Request * pReq,int size)405 static 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 
verifyHeader(struct lsapi_packet_header * pHeader,char pktType)417 static 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 
allocateEnvList(struct LSAPI_key_value_pair ** pEnvList,int * curSize,int newSize)436 static 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 
isPipe(int fd)457 static 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 
parseEnv(struct LSAPI_key_value_pair * pEnvList,int count,char ** pBegin,char * pEnd)468 static 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 
swapIntEndian(int * pInteger)504 static 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 
fixEndian(LSAPI_Request * pReq)517 static 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 
fixHeaderIndexEndian(LSAPI_Request * pReq)531 static 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 
validateHeaders(LSAPI_Request * pReq)563 static 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 
596 static uid_t s_uid = 0;
597 static uid_t s_defaultUid;  //web server need set this
598 static 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
606 struct liblve;
607 static int s_enable_lve = LSAPI_LVE_DISABLED;
608 static struct liblve * s_lve = NULL;
609 
610 static void *s_liblve;
611 static int (*fp_lve_is_available)(void) = NULL;
612 static int (*fp_lve_instance_init)(struct liblve *) = NULL;
613 static int (*fp_lve_destroy)(struct liblve *) = NULL;
614 static int (*fp_lve_enter)(struct liblve *, uint32_t, int32_t, int32_t, uint32_t *) = NULL;
615 static int (*fp_lve_leave)(struct liblve *, uint32_t *) = NULL;
616 static int (*fp_lve_jail)( struct passwd *, char *) = NULL;
lsapi_load_lve_lib()617 static 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 
init_lve_ex()645 static 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 
readSecret(const char * pSecretFile)678 static 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 
LSAPI_is_suEXEC_Daemon()717 int LSAPI_is_suEXEC_Daemon()
718 {
719     if (( !s_uid )&&( s_secret[0] ))
720         return 1;
721     else
722         return 0;
723 }
724 
LSAPI_perror_r(LSAPI_Request * pReq,const char * pErr1,const char * pErr2)725 static 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 
lsapi_lve_error(LSAPI_Request * pReq)736 static 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 
lsapi_enterLVE(LSAPI_Request * pReq,uid_t uid)759 static 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 
lsapi_jailLVE(LSAPI_Request * pReq,uid_t uid,struct passwd * pw)780 static 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__)
lsapi_initLVE()799 static 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 
setUID_LVE(LSAPI_Request * pReq,uid_t uid,gid_t gid,const char * pChroot)826 static 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 
lsapi_suexec_auth(LSAPI_Request * pReq,char * pAuth,int len,char * pUgid,int ugidLen)906 static 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 
lsapi_changeUGid(LSAPI_Request * pReq)925 static 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 
parseContentLenFromHeader(LSAPI_Request * pReq)999 static 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 
parseRequest(LSAPI_Request * pReq,int totalLen)1008 static 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
1090 static char s_accept_notify = 0;
1091 static char s_schedule_notify = 0;
1092 static char s_notify_scheduled = 0;
1093 static char s_notified_pid = 0;
1094 
1095 static struct lsapi_packet_header s_ack = {'L', 'S',
1096                 LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
1097 
1098 
write_req_received_notification(int fd)1099 static 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 
lsapi_sigalarm(int sig)1107 static 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 
lsapi_schedule_notify()1117 static 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 
notify_req_received(int fd)1127 static 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 
lsapi_notify_pid(int fd)1136 static 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 
1149 static char s_conn_key_packet[16];
init_conn_key(int fd)1150 static 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 
readReq(LSAPI_Request * pReq)1171 static 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 
LSAPI_Init(void)1244 int 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 
LSAPI_Stop(void)1267 void LSAPI_Stop(void)
1268 {
1269     g_running = 0;
1270 }
1271 
LSAPI_IsRunning(void)1272 int LSAPI_IsRunning(void)
1273 {
1274     return g_running;
1275 }
1276 
LSAPI_InitRequest(LSAPI_Request * pReq,int fd)1277 int 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 
LSAPI_Is_Listen(void)1315 int LSAPI_Is_Listen( void )
1316 {
1317     return LSAPI_Is_Listen_r( &g_req );
1318 }
1319 
LSAPI_Is_Listen_r(LSAPI_Request * pReq)1320 int LSAPI_Is_Listen_r( LSAPI_Request * pReq)
1321 {
1322     return pReq->m_fdListen != -1;
1323 }
1324 
1325 
1326 
LSAPI_Accept_r(LSAPI_Request * pReq)1327 int 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 
1382 static struct lsapi_packet_header   finish = {'L', 'S',
1383                 LSAPI_RESP_END, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
1384 
LSAPI_Finish_r(LSAPI_Request * pReq)1385 int 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 
LSAPI_Reset_r(LSAPI_Request * pReq)1415 void 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 
LSAPI_Release_r(LSAPI_Request * pReq)1426 int 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 
LSAPI_GetHeader_r(LSAPI_Request * pReq,int headerIndex)1440 char * 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 
readBodyToReqBuf(LSAPI_Request * pReq)1457 static 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 
LSAPI_ReqBodyGetChar_r(LSAPI_Request * pReq)1479 int 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 
LSAPI_ReqBodyGetLine_r(LSAPI_Request * pReq,char * pBuf,size_t bufLen,int * getLF)1494 int 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 )|| !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 
LSAPI_ReadReqBody_r(LSAPI_Request * pReq,char * pBuf,size_t bufLen)1541 ssize_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 ))
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 
LSAPI_Write_r(LSAPI_Request * pReq,const char * pBuf,size_t len)1590 ssize_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__)
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)1676 ssize_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__)
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)1691 ssize_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>
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)1707 ssize_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)
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)1734 ssize_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 
LSAPI_sendfile_r(LSAPI_Request * pReq,int fdIn,off_t * off,size_t size)1740 ssize_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 
Flush_RespBuf_r(LSAPI_Request * pReq)1764 void 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 
LSAPI_Flush_r(LSAPI_Request * pReq)1790 int 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 
LSAPI_Write_Stderr_r(LSAPI_Request * pReq,const char * pBuf,size_t len)1834 ssize_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 
GetHeaderVar(LSAPI_Request * pReq,const char * name)1887 static 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 
LSAPI_GetEnv_r(LSAPI_Request * pReq,const char * name)1947 char * 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 
1966 struct _headerInfo
1967 {
1968     const char * _name;
1969     int          _nameLen;
1970     const char * _value;
1971     int          _valueLen;
1972 };
1973 
compareValueLocation(const void * v1,const void * v2)1974 int compareValueLocation(const void * v1, const void *v2 )
1975 {
1976     return ((const struct _headerInfo *)v1)->_value -
1977            ((const struct _headerInfo *)v2)->_value;
1978 }
1979 
LSAPI_ForeachOrgHeader_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)1980 int 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 
LSAPI_ForeachHeader_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)2057 int 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 
EnvForeach(struct LSAPI_key_value_pair * pEnv,int n,LSAPI_CB_EnvHandler fn,void * arg)2125 static 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 
LSAPI_ForeachEnv_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)2145 int 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 
LSAPI_ForeachSpecialEnv_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)2160 int 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 
LSAPI_FinalizeRespHeaders_r(LSAPI_Request * pReq)2177 int 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 
LSAPI_AppendRespHeader2_r(LSAPI_Request * pReq,const char * pHeaderName,const char * pHeaderValue)2204 int 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 
LSAPI_AppendRespHeader_r(LSAPI_Request * pReq,const char * pBuf,int len)2261 int 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 
LSAPI_CreateListenSock2(const struct sockaddr * pServerAddr,int backlog)2296 int 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 
LSAPI_ParseSockAddr(const char * pBind,struct sockaddr * pAddr)2344 int 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 
LSAPI_CreateListenSock(const char * pBind,int backlog)2441 int 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 
2454 static fn_select_t g_fnSelect = select;
2455 
2456 typedef 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 }
2469 lsapi_child_status;
2470 
2471 static lsapi_child_status * s_pChildStatus = NULL;
2472 
2473 typedef 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 
2491 static lsapi_prefork_server * g_prefork_server = NULL;
2492 
LSAPI_Init_Prefork_Server(int max_children,fn_select_t fp,int avoidFork)2493 int 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 
LSAPI_Set_Server_fd(int fd)2527 void LSAPI_Set_Server_fd( int fd )
2528 {
2529     if( g_prefork_server )
2530         g_prefork_server->m_fd = fd;
2531 }
2532 
2533 
lsapi_accept(int fdListen)2534 static 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 
2562 static int s_req_processed = 0;
2563 static int s_max_reqs = 10000;
2564 static int s_max_idle_secs = 300;
2565 
2566 static int s_stop;
2567 
lsapi_cleanup(int signal)2568 static void lsapi_cleanup(int signal)
2569 {
2570     s_stop = signal;
2571 }
2572 
find_child_status(int pid)2573 static 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 
lsapi_sigchild(int signal)2592 static 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 
lsapi_init_children_status()2628 static 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     g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf;
2643     g_prefork_server->m_pChildrenStatusCur = (lsapi_child_status *)pBuf;
2644     g_prefork_server->m_pChildrenStatusEnd = (lsapi_child_status *)pBuf + size / sizeof( lsapi_child_status );
2645     return 0;
2646 }
2647 
dump_debug_info(lsapi_child_status * pStatus,long tmCur)2648 static void dump_debug_info( lsapi_child_status * pStatus, long tmCur )
2649 {
2650     char achCmd[1024];
2651     if ( s_pid_dump_debug_info )
2652     {
2653         if ( kill( s_pid_dump_debug_info, 0 ) == 0 )
2654             return;
2655     }
2656     s_pid_dump_debug_info = fork();
2657 
2658     fprintf( stderr, "[%s] Possible runaway process, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld\n",
2659                 ctime(&tmCur), getpid(), pStatus->m_pid, pStatus->m_iReqCounter,
2660                 tmCur - pStatus->m_tmReqBegin, tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart );
2661     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 );
2662     if ( system( achCmd ) == -1 )
2663         perror( "system()" );
2664     exit( 0 );
2665 }
2666 
lsapi_check_child_status(long tmCur)2667 static void lsapi_check_child_status( long tmCur )
2668 {
2669     int idle = 0;
2670     int tobekilled;
2671     int dying = 0;
2672     int count = 0;
2673     lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
2674     lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusCur;
2675     while( pStatus < pEnd )
2676     {
2677         tobekilled = 0;
2678         if ( pStatus->m_pid != 0 )
2679         {
2680             ++count;
2681             if ( !pStatus->m_inProcess )
2682             {
2683 
2684                 if (( g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren)||
2685                     ( idle > g_prefork_server->m_iMaxIdleChildren ))
2686                 {
2687                     ++pStatus->m_iKillSent;
2688                     //tobekilled = SIGUSR1;
2689                 }
2690                 else
2691                 {
2692                     if (( s_max_idle_secs> 0)&&(tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5 ))
2693                     {
2694                         ++pStatus->m_iKillSent;
2695                         //tobekilled = SIGUSR1;
2696                     }
2697                 }
2698                 if ( !tobekilled )
2699                     ++idle;
2700             }
2701             else
2702             {
2703                 if ( tmCur - pStatus->m_tmReqBegin >
2704                         g_prefork_server->m_iMaxReqProcessTime )
2705                 {
2706                     if (( ( pStatus->m_iKillSent % 5 ) == 0 )&&( s_dump_debug_info ))
2707                         dump_debug_info( pStatus, tmCur );
2708                     if ( pStatus->m_iKillSent > 5 )
2709                     {
2710                         tobekilled = SIGKILL;
2711                         fprintf( stderr, "Force killing runaway process PID: %d with SIGKILL\n", pStatus->m_pid );
2712                     }
2713                     else
2714                     {
2715                         tobekilled = SIGTERM;
2716                         fprintf( stderr, "Killing runaway process PID: %d with SIGTERM\n", pStatus->m_pid );
2717                     }
2718                 }
2719             }
2720             if ( tobekilled )
2721             {
2722                 if (( kill( pStatus->m_pid, tobekilled ) == -1 )&&( errno == ESRCH ))
2723                 {
2724                     pStatus->m_pid = 0;
2725                     --count;
2726                 }
2727                 else
2728                 {
2729                     ++pStatus->m_iKillSent;
2730                     ++dying;
2731                 }
2732             }
2733         }
2734         ++pStatus;
2735     }
2736     if ( abs( g_prefork_server->m_iCurChildren - count ) > 1 )
2737     {
2738         fprintf( stderr, "Children tracking is wrong: PID: %d, Cur Children: %d, count: %d, idle: %d, dying: %d\n", getpid(),
2739                 g_prefork_server->m_iCurChildren, count, idle, dying );
2740 
2741     }
2742 }
2743 
lsapi_all_children_must_die()2744 static int lsapi_all_children_must_die()
2745 {
2746     int maxWait;
2747     int sec =0;
2748     g_prefork_server->m_iMaxReqProcessTime = 10;
2749     g_prefork_server->m_iMaxIdleChildren = -1;
2750     maxWait = 15;
2751 
2752     while( g_prefork_server->m_iCurChildren && (sec < maxWait) )
2753     {
2754         lsapi_check_child_status(time(NULL));
2755         sleep( 1 );
2756         sec++;
2757     }
2758     if ( g_prefork_server->m_iCurChildren != 0 )
2759         kill( -getpgrp(), SIGKILL );
2760     return 0;
2761 }
2762 
2763 
2764 
lsapi_prefork_server_accept(lsapi_prefork_server * pServer,LSAPI_Request * pReq)2765 static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Request * pReq )
2766 {
2767     struct sigaction act, old_term, old_quit, old_int,
2768                     old_usr1, old_child;
2769     lsapi_child_status * child_status;
2770     int             wait_secs = 0;
2771     int             ret = 0;
2772     int             pid;
2773     time_t          lastTime = 0;
2774     time_t          curTime = 0;
2775     fd_set          readfds;
2776     struct timeval  timeout;
2777 
2778     sigset_t mask;
2779     sigset_t orig_mask;
2780 
2781     lsapi_init_children_status();
2782 
2783     setsid();
2784 
2785     act.sa_flags = 0;
2786     act.sa_handler = lsapi_sigchild;
2787     if( sigaction( SIGCHLD, &act, &old_child ) )
2788     {
2789         perror( "Can't set signal handler for SIGCHILD" );
2790         return -1;
2791     }
2792 
2793     /* Set up handler to kill children upon exit */
2794     act.sa_flags = 0;
2795     act.sa_handler = lsapi_cleanup;
2796     if( sigaction( SIGTERM, &act, &old_term ) ||
2797         sigaction( SIGINT,  &act, &old_int  ) ||
2798         sigaction( SIGUSR1, &act, &old_usr1 ) ||
2799         sigaction( SIGQUIT, &act, &old_quit ))
2800     {
2801         perror( "Can't set signals" );
2802         return -1;
2803     }
2804     s_stop = 0;
2805     while( !s_stop )
2806     {
2807         curTime = time( NULL );
2808         if (curTime != lastTime )
2809         {
2810             lastTime = curTime;
2811             if (s_ppid && (getppid() != s_ppid ))
2812                 break;
2813             lsapi_check_child_status(curTime );
2814             if (pServer->m_iServerMaxIdle)
2815             {
2816                 if ( pServer->m_iCurChildren <= 0 )
2817                 {
2818                     ++wait_secs;
2819                     if ( wait_secs > pServer->m_iServerMaxIdle )
2820                         return -1;
2821                 }
2822                 else
2823                     wait_secs = 0;
2824             }
2825         }
2826 
2827         if ( pServer->m_iCurChildren >= (pServer->m_iMaxChildren + pServer->m_iExtraChildren ) )
2828         {
2829             fprintf( stderr, "Reached max children process limit: %d, extra: %d, current: %d, please increase LSAPI_CHILDREN.\n",
2830                                 pServer->m_iMaxChildren, pServer->m_iExtraChildren, pServer->m_iCurChildren );
2831             usleep( 100000 );
2832             continue;
2833         }
2834 
2835         FD_ZERO( &readfds );
2836         FD_SET( pServer->m_fd, &readfds );
2837         timeout.tv_sec = 1; timeout.tv_usec = 0;
2838         if ((ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout)) == 1 )
2839         {
2840             /*
2841             if ( pServer->m_iCurChildren >= 0 )
2842             {
2843                 usleep( 10 );
2844                 FD_ZERO( &readfds );
2845                 FD_SET( pServer->m_fd, &readfds );
2846                 timeout.tv_sec = 0; timeout.tv_usec = 0;
2847                 if ( (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout) == 0 )
2848                     continue;
2849             }*/
2850         }
2851         else if ( ret == -1 )
2852         {
2853             if ( errno == EINTR )
2854                 continue;
2855             /* perror( "select()" ); */
2856             break;
2857         }
2858         else
2859         {
2860             continue;
2861         }
2862 
2863         pReq->m_fd = lsapi_accept( pServer->m_fd );
2864         if ( pReq->m_fd != -1 )
2865         {
2866             child_status = find_child_status( 0 );
2867             if ( child_status )
2868                 memset( child_status, 0, sizeof( *child_status ) );
2869 
2870             sigemptyset( &mask );
2871             sigaddset( &mask, SIGCHLD );
2872 
2873             if ( sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0 )
2874             {
2875                 perror( "sigprocmask(SIG_BLOCK) to block SIGCHLD" );
2876             }
2877 
2878             pid = fork();
2879 
2880             if ( !pid )
2881             {
2882                 if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
2883                     perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK in child" );
2884                 g_prefork_server = NULL;
2885                 s_ppid = getppid();
2886                 s_req_processed = 0;
2887                 s_pChildStatus = child_status;
2888                 lsapi_set_nblock( pReq->m_fd, 0 );
2889                 if ( pReq->m_fdListen != -1 )
2890                 {
2891                     close( pReq->m_fdListen );
2892                     pReq->m_fdListen = -1;
2893                 }
2894                 /* don't catch our signals */
2895                 sigaction( SIGCHLD, &old_child, 0 );
2896                 sigaction( SIGTERM, &old_term, 0 );
2897                 sigaction( SIGQUIT, &old_quit, 0 );
2898                 sigaction( SIGINT,  &old_int,  0 );
2899                 sigaction( SIGUSR1, &old_usr1, 0 );
2900                 //init_conn_key( pReq->m_fd );
2901                 lsapi_notify_pid( pReq->m_fd );
2902                 s_notified_pid = 1;
2903                 //if ( s_accept_notify )
2904                 //    return notify_req_received( pReq->m_fd );
2905                 return 0;
2906             }
2907             else if ( pid == -1 )
2908             {
2909                 perror( "fork() failed, please increase process limit" );
2910             }
2911             else
2912             {
2913                 ++pServer->m_iCurChildren;
2914                 if ( child_status )
2915                 {
2916                     child_status->m_pid = pid;
2917                     child_status->m_tmWaitBegin = curTime;
2918                     child_status->m_tmStart = curTime;
2919                 }
2920             }
2921             close( pReq->m_fd );
2922             pReq->m_fd = -1;
2923 
2924             if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
2925                 perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK" );
2926 
2927         }
2928         else
2929         {
2930             if (( errno == EINTR )||( errno == EAGAIN))
2931                 continue;
2932             perror( "accept() failed" );
2933             return -1;
2934         }
2935     }
2936     sigaction( SIGUSR1, &old_usr1, 0 );
2937     //kill( -getpgrp(), SIGUSR1 );
2938     //lsapi_all_children_must_die();  /* Sorry, children ;-) */
2939     return -1;
2940 
2941 }
2942 
lsapi_error(const char * pMessage,int err_no)2943 void lsapi_error( const char * pMessage, int err_no )
2944 {
2945     fprintf( stderr, "%d: %s, errno: %d (%s)\n", getpid(), pMessage, err_no, strerror( err_no ) );
2946 }
2947 
LSAPI_Prefork_Accept_r(LSAPI_Request * pReq)2948 int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
2949 {
2950     int             fd;
2951     int             ret;
2952     int             wait_secs;
2953     fd_set          readfds;
2954     struct timeval  timeout;
2955 
2956     LSAPI_Finish_r( pReq );
2957 
2958 
2959     if ( g_prefork_server )
2960     {
2961         if ( g_prefork_server->m_fd != -1 )
2962             if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 )
2963                 return -1;
2964     }
2965     if ( s_req_processed >= s_max_reqs )
2966         return -1;
2967 
2968     if ( s_pChildStatus )
2969     {
2970         s_pChildStatus->m_tmWaitBegin = time( NULL );
2971     }
2972 
2973 
2974     while( g_running )
2975     {
2976         if ( pReq->m_fd != -1 )
2977         {
2978             fd = pReq->m_fd;
2979         }
2980         else if ( pReq->m_fdListen != -1 )
2981             fd = pReq->m_fdListen;
2982         else
2983         {
2984             break;
2985         }
2986         wait_secs = 0;
2987         while( 1 )
2988         {
2989             if ( !g_running )
2990                 return -1;
2991             if ((s_req_processed)&&( s_pChildStatus )&&( s_pChildStatus->m_iKillSent ))
2992                 return -1;
2993             FD_ZERO( &readfds );
2994             FD_SET( fd, &readfds );
2995             timeout.tv_sec = 1;
2996             timeout.tv_usec = 0;
2997             ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout);
2998             if ( ret == 0 )
2999             {
3000                 if ( s_pChildStatus )
3001                 {
3002                     s_pChildStatus->m_inProcess = 0;
3003                 }
3004                 ++wait_secs;
3005                 if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs ))
3006                     return -1;
3007                 if ( s_ppid &&( getppid() != s_ppid))
3008                     return -1;
3009             }
3010             else if ( ret == -1 )
3011             {
3012                 if ( errno == EINTR )
3013                     continue;
3014                 else
3015                     return -1;
3016             }
3017             else if ( ret >= 1 )
3018             {
3019                 if (s_req_processed && ( s_pChildStatus )&&( s_pChildStatus->m_iKillSent ))
3020                     return -1;
3021                 if ( fd == pReq->m_fdListen )
3022                 {
3023                     pReq->m_fd = lsapi_accept( pReq->m_fdListen );
3024                     if ( pReq->m_fd != -1 )
3025                     {
3026                         fd = pReq->m_fd;
3027                         lsapi_set_nblock( fd, 0 );
3028                         //init_conn_key( pReq->m_fd );
3029                         if ( !s_keepListener )
3030                         {
3031                             close( pReq->m_fdListen );
3032                             pReq->m_fdListen = -1;
3033                         }
3034                         if ( s_accept_notify )
3035                             if ( notify_req_received( pReq->m_fd ) == -1 )
3036                                 return -1;
3037                     }
3038                     else
3039                     {
3040                         if (( errno == EINTR )||( errno == EAGAIN))
3041                             continue;
3042                         lsapi_error( "lsapi_accept() error", errno );
3043                         return -1;
3044                     }
3045                 }
3046                 else
3047                     break;
3048             }
3049         }
3050 
3051         if ( !readReq( pReq ) )
3052         {
3053             if ( s_pChildStatus )
3054             {
3055                 s_pChildStatus->m_iKillSent = 0;
3056                 s_pChildStatus->m_inProcess = 1;
3057                 ++s_pChildStatus->m_iReqCounter;
3058                 s_pChildStatus->m_tmReqBegin = s_pChildStatus->m_tmLastCheckPoint = time(NULL);
3059             }
3060             ++s_req_processed;
3061             return 0;
3062         }
3063         lsapi_close( pReq->m_fd );
3064         pReq->m_fd = -1;
3065         LSAPI_Reset_r( pReq );
3066     }
3067     return -1;
3068 
3069 }
3070 
LSAPI_Set_Max_Reqs(int reqs)3071 void LSAPI_Set_Max_Reqs( int reqs )
3072 {   s_max_reqs = reqs;          }
3073 
LSAPI_Set_Max_Idle(int secs)3074 void LSAPI_Set_Max_Idle( int secs )
3075 {   s_max_idle_secs = secs;     }
3076 
LSAPI_Set_Max_Children(int maxChildren)3077 void LSAPI_Set_Max_Children( int maxChildren )
3078 {
3079     if ( g_prefork_server )
3080         g_prefork_server->m_iMaxChildren = maxChildren;
3081 }
3082 
LSAPI_Set_Extra_Children(int extraChildren)3083 void LSAPI_Set_Extra_Children( int extraChildren )
3084 {
3085     if (( g_prefork_server )&&( extraChildren >= 0 ))
3086         g_prefork_server->m_iExtraChildren = extraChildren;
3087 }
3088 
LSAPI_Set_Max_Process_Time(int secs)3089 void LSAPI_Set_Max_Process_Time( int secs )
3090 {
3091     if (( g_prefork_server )&&( secs > 0 ))
3092         g_prefork_server->m_iMaxReqProcessTime = secs;
3093 }
3094 
3095 
LSAPI_Set_Max_Idle_Children(int maxIdleChld)3096 void LSAPI_Set_Max_Idle_Children( int maxIdleChld )
3097 {
3098     if (( g_prefork_server )&&( maxIdleChld > 0 ))
3099         g_prefork_server->m_iMaxIdleChildren = maxIdleChld;
3100 }
3101 
LSAPI_Set_Server_Max_Idle_Secs(int serverMaxIdle)3102 void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle )
3103 {
3104     if ( g_prefork_server )
3105         g_prefork_server->m_iServerMaxIdle = serverMaxIdle;
3106 }
3107 
LSAPI_Set_Slow_Req_Msecs(int msecs)3108 void LSAPI_Set_Slow_Req_Msecs( int msecs )
3109 {
3110     s_slow_req_msecs = msecs;
3111 }
3112 
LSAPI_Get_Slow_Req_Msecs()3113 int  LSAPI_Get_Slow_Req_Msecs()
3114 {
3115     return s_slow_req_msecs;
3116 }
3117 
3118 
LSAPI_No_Check_ppid()3119 void LSAPI_No_Check_ppid()
3120 {
3121     s_ppid = 0;
3122 }
3123 
3124 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
3125 #include <crt_externs.h>
3126 #else
3127 extern char ** environ;
3128 #endif
unset_lsapi_envs()3129 static void unset_lsapi_envs()
3130 {
3131     char **env;
3132 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
3133     env = *_NSGetEnviron();
3134 #else
3135     env = environ;
3136 #endif
3137     while( env != NULL && *env != NULL )
3138     {
3139         if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 )
3140             || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid)))
3141         {
3142             char ** del = env;
3143             do
3144                 *del = del[1];
3145             while( *del++ );
3146         }
3147         else
3148             ++env;
3149     }
3150 }
3151 
lsapi_initSuEXEC()3152 static int lsapi_initSuEXEC()
3153 {
3154     int i;
3155     struct passwd * pw;
3156     s_defaultUid = 0;
3157     s_defaultGid = 0;
3158     if ( s_uid == 0 )
3159     {
3160         const char * p = getenv( "LSAPI_DEFAULT_UID" );
3161         if ( p )
3162         {
3163             i = atoi( p );
3164             if ( i > 0 )
3165                 s_defaultUid = i;
3166         }
3167         p = getenv( "LSAPI_DEFAULT_GID" );
3168         if ( p )
3169         {
3170             i = atoi( p );
3171             if ( i > 0 )
3172                 s_defaultGid = i;
3173         }
3174         p = getenv( "LSAPI_SECRET" );
3175         if (( !p )||( readSecret(p) == -1 ))
3176                 return -1;
3177         if ( g_prefork_server )
3178         {
3179             if ( g_prefork_server->m_iMaxChildren < 100 )
3180                 g_prefork_server->m_iMaxChildren = 100;
3181             if ( g_prefork_server->m_iExtraChildren < 1000 )
3182                 g_prefork_server->m_iExtraChildren = 1000;
3183         }
3184     }
3185     if ( !s_defaultUid || !s_defaultGid )
3186     {
3187         pw = getpwnam( "nobody" );
3188         if ( pw )
3189         {
3190             if ( !s_defaultUid )
3191                 s_defaultUid = pw->pw_uid;
3192             if ( !s_defaultGid )
3193                 s_defaultGid = pw->pw_gid;
3194         }
3195         else
3196         {
3197             if ( !s_defaultUid )
3198                 s_defaultUid = 10000;
3199             if ( !s_defaultGid )
3200                 s_defaultGid = 10000;
3201         }
3202     }
3203     return 0;
3204 }
3205 
3206 
LSAPI_Init_Env_Parameters(fn_select_t fp)3207 int LSAPI_Init_Env_Parameters( fn_select_t fp )
3208 {
3209     const char *p;
3210     int n;
3211     int avoidFork = 0;
3212     p = getenv( "PHP_LSAPI_MAX_REQUESTS" );
3213     if ( !p )
3214         p = getenv( "LSAPI_MAX_REQS" );
3215     if ( p )
3216     {
3217         n = atoi( p );
3218         if ( n > 0 )
3219             LSAPI_Set_Max_Reqs( n );
3220     }
3221 
3222     p = getenv( "LSAPI_AVOID_FORK" );
3223     if ( p )
3224     {
3225         avoidFork = atoi( p );
3226     }
3227 
3228     p = getenv( "LSAPI_ACCEPT_NOTIFY" );
3229     if ( p )
3230     {
3231         s_accept_notify = atoi( p );
3232     }
3233 
3234     p = getenv( "LSAPI_SLOW_REQ_MSECS" );
3235     if ( p )
3236     {
3237         n = atoi( p );
3238         LSAPI_Set_Slow_Req_Msecs( n );
3239     }
3240 
3241 #if defined( RLIMIT_CORE )
3242     p = getenv( "LSAPI_ALLOW_CORE_DUMP" );
3243     if ( !p )
3244     {
3245         struct rlimit limit = { 0, 0 };
3246         setrlimit( RLIMIT_CORE, &limit );
3247     }
3248     else
3249         s_enable_core_dump = 1;
3250 
3251 #endif
3252 
3253     p = getenv( "LSAPI_MAX_IDLE" );
3254     if ( p )
3255     {
3256         n = atoi( p );
3257         LSAPI_Set_Max_Idle( n );
3258     }
3259 
3260     p = getenv( "LSAPI_KEEP_LISTEN" );
3261     if ( p )
3262     {
3263         n = atoi( p );
3264         s_keepListener = n;
3265     }
3266 
3267 
3268     if ( LSAPI_Is_Listen() )
3269     {
3270         n = 0;
3271         p = getenv( "PHP_LSAPI_CHILDREN" );
3272         if ( !p )
3273             p = getenv( "LSAPI_CHILDREN" );
3274         if ( p )
3275             n = atoi( p );
3276         if ( n > 1 )
3277         {
3278             LSAPI_Init_Prefork_Server( n, fp, avoidFork );
3279             LSAPI_Set_Server_fd( g_req.m_fdListen );
3280         }
3281 
3282         p = getenv( "LSAPI_EXTRA_CHILDREN" );
3283         if ( p )
3284             LSAPI_Set_Extra_Children( atoi( p ) );
3285 
3286         p = getenv( "LSAPI_MAX_IDLE_CHILDREN" );
3287         if ( p )
3288             LSAPI_Set_Max_Idle_Children( atoi( p ) );
3289 
3290         p = getenv( "LSAPI_PGRP_MAX_IDLE" );
3291         if ( p )
3292         {
3293             LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) );
3294         }
3295 
3296         p = getenv( "LSAPI_MAX_PROCESS_TIME" );
3297         if ( p )
3298             LSAPI_Set_Max_Process_Time( atoi( p ) );
3299 
3300         if ( getenv( "LSAPI_PPID_NO_CHECK" ) )
3301         {
3302             LSAPI_No_Check_ppid();
3303         }
3304 
3305         p = getenv( "LSAPI_DUMP_DEBUG_INFO" );
3306         if ( p )
3307             s_dump_debug_info = atoi( p );
3308 
3309         if ( lsapi_initSuEXEC() == -1 )
3310             return -1;
3311 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3312         lsapi_initLVE();
3313 #endif
3314     }
3315     unset_lsapi_envs();
3316     return 0;
3317 }
3318 
3319 
LSAPI_ErrResponse_r(LSAPI_Request * pReq,int code,const char ** pRespHeaders,const char * pBody,int bodyLen)3320 int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders,
3321                          const char * pBody, int bodyLen )
3322 {
3323     LSAPI_SetRespStatus_r( pReq, code );
3324     if ( pRespHeaders )
3325     {
3326         while( *pRespHeaders )
3327         {
3328             LSAPI_AppendRespHeader_r( pReq, *pRespHeaders, strlen( *pRespHeaders ) );
3329             ++pRespHeaders;
3330         }
3331     }
3332     if ( pBody &&( bodyLen > 0 ))
3333     {
3334         LSAPI_Write_r( pReq, pBody, bodyLen );
3335     }
3336     LSAPI_Finish_r( pReq );
3337     return 0;
3338 }
3339 
3340 
3341 static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]);
3342 
3343 /*
3344  * Note: this code is harmless on little-endian machines.
3345  */
byteReverse(unsigned char * buf,unsigned longs)3346 static void byteReverse(unsigned char *buf, unsigned longs)
3347 {
3348     uint32 t;
3349     do {
3350         t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
3351             ((unsigned) buf[1] << 8 | buf[0]);
3352         *(uint32 *) buf = t;
3353         buf += 4;
3354     } while (--longs);
3355 }
3356 
3357 /*
3358  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
3359  * initialization constants.
3360  */
lsapi_MD5Init(struct lsapi_MD5Context * ctx)3361 void lsapi_MD5Init(struct lsapi_MD5Context *ctx)
3362 {
3363     ctx->buf[0] = 0x67452301;
3364     ctx->buf[1] = 0xefcdab89;
3365     ctx->buf[2] = 0x98badcfe;
3366     ctx->buf[3] = 0x10325476;
3367 
3368     ctx->bits[0] = 0;
3369     ctx->bits[1] = 0;
3370 }
3371 
3372 /*
3373  * Update context to reflect the concatenation of another buffer full
3374  * of bytes.
3375  */
lsapi_MD5Update(struct lsapi_MD5Context * ctx,unsigned char const * buf,unsigned len)3376 void lsapi_MD5Update(struct lsapi_MD5Context *ctx, unsigned char const *buf, unsigned len)
3377 {
3378     register uint32 t;
3379 
3380     /* Update bitcount */
3381 
3382     t = ctx->bits[0];
3383     if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
3384         ctx->bits[1]++;                /* Carry from low to high */
3385     ctx->bits[1] += len >> 29;
3386 
3387     t = (t >> 3) & 0x3f;        /* Bytes already in shsInfo->data */
3388 
3389     /* Handle any leading odd-sized chunks */
3390 
3391     if (t) {
3392         unsigned char *p = (unsigned char *) ctx->in + t;
3393 
3394         t = 64 - t;
3395         if (len < t) {
3396             memmove(p, buf, len);
3397             return;
3398         }
3399         memmove(p, buf, t);
3400         byteReverse(ctx->in, 16);
3401         lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3402         buf += t;
3403         len -= t;
3404     }
3405     /* Process data in 64-byte chunks */
3406 
3407     while (len >= 64) {
3408         memmove(ctx->in, buf, 64);
3409         byteReverse(ctx->in, 16);
3410         lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3411         buf += 64;
3412         len -= 64;
3413     }
3414 
3415     /* Handle any remaining bytes of data. */
3416 
3417     memmove(ctx->in, buf, len);
3418 }
3419 
3420 /*
3421  * Final wrapup - pad to 64-byte boundary with the bit pattern
3422  * 1 0* (64-bit count of bits processed, MSB-first)
3423  */
lsapi_MD5Final(unsigned char digest[16],struct lsapi_MD5Context * ctx)3424 void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *ctx)
3425 {
3426     unsigned int count;
3427     unsigned char *p;
3428 
3429     /* Compute number of bytes mod 64 */
3430     count = (ctx->bits[0] >> 3) & 0x3F;
3431 
3432     /* Set the first char of padding to 0x80.  This is safe since there is
3433        always at least one byte free */
3434     p = ctx->in + count;
3435     *p++ = 0x80;
3436 
3437     /* Bytes of padding needed to make 64 bytes */
3438     count = 64 - 1 - count;
3439 
3440     /* Pad out to 56 mod 64 */
3441     if (count < 8) {
3442         /* Two lots of padding:  Pad the first block to 64 bytes */
3443         memset(p, 0, count);
3444         byteReverse(ctx->in, 16);
3445         lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3446 
3447         /* Now fill the next block with 56 bytes */
3448         memset(ctx->in, 0, 56);
3449     } else {
3450         /* Pad block to 56 bytes */
3451         memset(p, 0, count - 8);
3452     }
3453     byteReverse(ctx->in, 14);
3454 
3455     /* Append length in bits and transform */
3456     ((uint32 *) ctx->in)[14] = ctx->bits[0];
3457     ((uint32 *) ctx->in)[15] = ctx->bits[1];
3458 
3459     lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
3460     byteReverse((unsigned char *) ctx->buf, 4);
3461     memmove(digest, ctx->buf, 16);
3462     memset(ctx, 0, sizeof(*ctx));        /* In case it's sensitive */
3463 }
3464 
3465 /* The four core functions - F1 is optimized somewhat */
3466 
3467 /* #define F1(x, y, z) (x & y | ~x & z) */
3468 #define F1(x, y, z) (z ^ (x & (y ^ z)))
3469 #define F2(x, y, z) F1(z, x, y)
3470 #define F3(x, y, z) (x ^ y ^ z)
3471 #define F4(x, y, z) (y ^ (x | ~z))
3472 
3473 /* This is the central step in the MD5 algorithm. */
3474 #define MD5STEP(f, w, x, y, z, data, s) \
3475         ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
3476 
3477 /*
3478  * The core of the MD5 algorithm, this alters an existing MD5 hash to
3479  * reflect the addition of 16 longwords of new data.  MD5Update blocks
3480  * the data and converts bytes into longwords for this routine.
3481  */
lsapi_MD5Transform(uint32 buf[4],uint32 const in[16])3482 static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16])
3483 {
3484     register uint32 a, b, c, d;
3485 
3486     a = buf[0];
3487     b = buf[1];
3488     c = buf[2];
3489     d = buf[3];
3490 
3491     MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
3492     MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
3493     MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
3494     MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
3495     MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
3496     MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
3497     MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
3498     MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
3499     MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
3500     MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
3501     MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
3502     MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
3503     MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
3504     MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
3505     MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
3506     MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
3507 
3508     MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
3509     MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
3510     MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
3511     MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
3512     MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
3513     MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
3514     MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
3515     MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
3516     MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
3517     MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
3518     MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
3519     MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
3520     MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
3521     MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
3522     MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
3523     MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
3524 
3525     MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
3526     MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
3527     MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
3528     MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
3529     MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
3530     MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
3531     MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
3532     MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
3533     MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
3534     MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
3535     MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
3536     MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
3537     MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
3538     MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
3539     MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
3540     MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
3541 
3542     MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
3543     MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
3544     MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
3545     MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
3546     MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
3547     MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
3548     MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
3549     MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
3550     MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
3551     MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
3552     MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
3553     MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
3554     MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
3555     MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
3556     MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
3557     MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
3558 
3559     buf[0] += a;
3560     buf[1] += b;
3561     buf[2] += c;
3562     buf[3] += d;
3563 }
3564 
3565